diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml index 231ad141e4..c4c522fe3f 100644 --- a/.github/workflows/cli.yml +++ b/.github/workflows/cli.yml @@ -96,7 +96,7 @@ jobs: type=raw,value=latest,enable=${{ github.event_name == 'release' }} - name: Build and push image - uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0 + uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6.16.0 with: file: cli/Dockerfile platforms: linux/amd64,linux/arm64 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 7d07785de7..69ef63efe9 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -50,7 +50,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@45775bd8235c68ba998cffa5171334d58593da47 # v3 + uses: github/codeql-action/init@28deaeda66b76a05916b6923827895f2b14ab387 # v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -63,7 +63,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@45775bd8235c68ba998cffa5171334d58593da47 # v3 + uses: github/codeql-action/autobuild@28deaeda66b76a05916b6923827895f2b14ab387 # v3 # â„šī¸ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -76,6 +76,6 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@45775bd8235c68ba998cffa5171334d58593da47 # v3 + uses: github/codeql-action/analyze@28deaeda66b76a05916b6923827895f2b14ab387 # v3 with: category: '/language:${{matrix.language}}' diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index a78d3c25dc..1746c93bc7 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -205,7 +205,7 @@ jobs: - name: Build and push image id: build - uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0 + uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6.16.0 with: context: ${{ env.context }} file: ${{ env.file }} @@ -224,7 +224,7 @@ jobs: BUILD_SOURCE_COMMIT=${{ github.sha }} - name: Export digest - run: | + run: | # zizmor: ignore[template-injection] mkdir -p ${{ runner.temp }}/digests digest="${{ steps.build.outputs.digest }}" touch "${{ runner.temp }}/digests/${digest#sha256:}" @@ -266,7 +266,7 @@ jobs: - build_and_push_ml steps: - name: Download digests - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: path: ${{ runner.temp }}/digests pattern: ml-digests-${{ matrix.device }}-* @@ -407,7 +407,7 @@ jobs: - name: Build and push image id: build - uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0 + uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6.16.0 with: context: ${{ env.context }} file: ${{ env.file }} @@ -426,7 +426,7 @@ jobs: BUILD_SOURCE_COMMIT=${{ github.sha }} - name: Export digest - run: | + run: | # zizmor: ignore[template-injection] mkdir -p ${{ runner.temp }}/digests digest="${{ steps.build.outputs.digest }}" touch "${{ runner.temp }}/digests/${digest#sha256:}" @@ -454,7 +454,7 @@ jobs: - build_and_push_server steps: - name: Download digests - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: path: ${{ runner.temp }}/digests pattern: server-digests-* @@ -535,6 +535,7 @@ jobs: run: exit 1 - name: All jobs passed or skipped if: ${{ !(contains(needs.*.result, 'failure')) }} + # zizmor: ignore[template-injection] run: echo "All jobs passed or skipped" && echo "${{ toJSON(needs.*.result) }}" success-check-ml: @@ -549,4 +550,5 @@ jobs: run: exit 1 - name: All jobs passed or skipped if: ${{ !(contains(needs.*.result, 'failure')) }} + # zizmor: ignore[template-injection] run: echo "All jobs passed or skipped" && echo "${{ toJSON(needs.*.result) }}" diff --git a/.github/workflows/docs-build.yml b/.github/workflows/docs-build.yml index ece3bbd248..aaa1780657 100644 --- a/.github/workflows/docs-build.yml +++ b/.github/workflows/docs-build.yml @@ -72,4 +72,5 @@ jobs: with: name: docs-build-output path: docs/build/ + include-hidden-files: true retention-days: 1 diff --git a/.github/workflows/docs-deploy.yml b/.github/workflows/docs-deploy.yml index 10277a0c5e..fd12423fd9 100644 --- a/.github/workflows/docs-deploy.yml +++ b/.github/workflows/docs-deploy.yml @@ -1,6 +1,6 @@ name: Docs deploy on: - workflow_run: + workflow_run: # zizmor: ignore[dangerous-triggers] no attacker inputs are used here workflows: ['Docs build'] types: - completed @@ -115,22 +115,22 @@ jobs: - name: Load parameters id: parameters uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7 + env: + PARAM_JSON: ${{ needs.checks.outputs.parameters }} with: script: | - const json = `${{ needs.checks.outputs.parameters }}`; - const parameters = JSON.parse(json); + const parameters = JSON.parse(process.env.PARAM_JSON); core.setOutput("event", parameters.event); core.setOutput("name", parameters.name); core.setOutput("shouldDeploy", parameters.shouldDeploy); - - run: | - echo "Starting docs deployment for ${{ steps.parameters.outputs.event }} ${{ steps.parameters.outputs.name }}" - - name: Download artifact uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7 + env: + ARTIFACT_JSON: ${{ needs.checks.outputs.artifact }} with: script: | - let artifact = ${{ needs.checks.outputs.artifact }}; + let artifact = JSON.parse(process.env.ARTIFACT_JSON); let download = await github.rest.actions.downloadArtifact({ owner: context.repo.owner, repo: context.repo.repo, diff --git a/.github/workflows/docs-destroy.yml b/.github/workflows/docs-destroy.yml index 9d1e4b6612..0da258de09 100644 --- a/.github/workflows/docs-destroy.yml +++ b/.github/workflows/docs-destroy.yml @@ -1,6 +1,6 @@ name: Docs destroy on: - pull_request_target: + pull_request_target: # zizmor: ignore[dangerous-triggers] no attacker inputs are used here types: [closed] permissions: {} diff --git a/.github/workflows/pr-label-validation.yml b/.github/workflows/pr-label-validation.yml index 8d34597a08..c5e5131920 100644 --- a/.github/workflows/pr-label-validation.yml +++ b/.github/workflows/pr-label-validation.yml @@ -1,7 +1,7 @@ name: PR Label Validation on: - pull_request_target: + pull_request_target: # zizmor: ignore[dangerous-triggers] no attacker inputs are used here types: [opened, labeled, unlabeled, synchronize] permissions: {} diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml index 5704f4275f..75c6836ab9 100644 --- a/.github/workflows/pr-labeler.yml +++ b/.github/workflows/pr-labeler.yml @@ -1,6 +1,6 @@ name: 'Pull Request Labeler' on: - - pull_request_target + - pull_request_target # zizmor: ignore[dangerous-triggers] no attacker inputs are used here permissions: {} diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index 7971f7574a..27957ca4a3 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -44,10 +44,13 @@ jobs: persist-credentials: true - name: Install uv - uses: astral-sh/setup-uv@0c5e2b8115b80b4c7c5ddf6ffdd634974642d182 # v5 + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5 - name: Bump version - run: misc/release/pump-version.sh -s "${{ inputs.serverBump }}" -m "${{ inputs.mobileBump }}" + env: + SERVER_BUMP: ${{ inputs.serverBump }} + MOBILE_BUMP: ${{ inputs.mobileBump }} + run: misc/release/pump-version.sh -s "${SERVER_BUMP}" -m "${MOBILE_BUMP}" - name: Commit and tag id: push-tag @@ -61,6 +64,8 @@ jobs: build_mobile: uses: ./.github/workflows/build-mobile.yml needs: bump_version + permissions: + contents: read secrets: KEY_JKS: ${{ secrets.KEY_JKS }} ALIAS: ${{ secrets.ALIAS }} @@ -90,12 +95,12 @@ jobs: persist-credentials: false - name: Download APK - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: release-apk-signed - name: Create draft release - uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2 + uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 # v2 with: draft: true tag_name: ${{ env.IMMICH_VERSION }} diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml index 1a3c11d3d5..3a0b702210 100644 --- a/.github/workflows/static_analysis.yml +++ b/.github/workflows/static_analysis.yml @@ -95,3 +95,30 @@ jobs: - name: Run dart custom_lint run: dart run custom_lint working-directory: ./mobile + + zizmor: + name: zizmor + runs-on: ubuntu-latest + permissions: + security-events: write + contents: read + actions: read + steps: + - name: Checkout repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + with: + persist-credentials: false + + - name: Install the latest version of uv + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5 + + - name: Run zizmor 🌈 + run: uvx zizmor --format=sarif . > results.sarif + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Upload SARIF file + uses: github/codeql-action/upload-sarif@28deaeda66b76a05916b6923827895f2b14ab387 # v3 + with: + sarif_file: results.sarif + category: zizmor diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 91389c25ff..605993f5e9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -184,8 +184,49 @@ jobs: run: npm run test:cov if: ${{ !cancelled() }} + web-lint: + name: Lint Web + needs: pre-job + if: ${{ needs.pre-job.outputs.should_run_web == 'true' }} + runs-on: mich + permissions: + contents: read + defaults: + run: + working-directory: ./web + + steps: + - name: Checkout code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + with: + persist-credentials: false + + - name: Setup Node + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version-file: './web/.nvmrc' + + - name: Run setup typescript-sdk + run: npm ci && npm run build + working-directory: ./open-api/typescript-sdk + + - name: Run npm install + run: npm ci + + - name: Run linter + run: npm run lint:p + if: ${{ !cancelled() }} + + - name: Run formatter + run: npm run format + if: ${{ !cancelled() }} + + - name: Run svelte checks + run: npm run check:svelte + if: ${{ !cancelled() }} + web-unit-tests: - name: Test & Lint Web + name: Test Web needs: pre-job if: ${{ needs.pre-job.outputs.should_run_web == 'true' }} runs-on: ubuntu-latest @@ -213,18 +254,6 @@ jobs: - name: Run npm install run: npm ci - - name: Run linter - run: npm run lint - if: ${{ !cancelled() }} - - - name: Run formatter - run: npm run format - if: ${{ !cancelled() }} - - - name: Run svelte checks - run: npm run check:svelte - if: ${{ !cancelled() }} - - name: Run tsc run: npm run check:typescript if: ${{ !cancelled() }} @@ -309,12 +338,15 @@ jobs: name: End-to-End Tests (Server & CLI) needs: pre-job if: ${{ needs.pre-job.outputs.should_run_e2e_server_cli == 'true' }} - runs-on: mich + runs-on: ${{ matrix.runner }} permissions: contents: read defaults: run: working-directory: ./e2e + strategy: + matrix: + runner: [mich, ubuntu-24.04-arm] steps: - name: Checkout code @@ -354,12 +386,15 @@ jobs: name: End-to-End Tests (Web) needs: pre-job if: ${{ needs.pre-job.outputs.should_run_e2e_web == 'true' }} - runs-on: mich + runs-on: ${{ matrix.runner }} permissions: contents: read defaults: run: working-directory: ./e2e + strategy: + matrix: + runner: [mich, ubuntu-24.04-arm] steps: - name: Checkout code @@ -394,6 +429,21 @@ jobs: run: npx playwright test if: ${{ !cancelled() }} + success-check-e2e: + name: End-to-End Tests Success + needs: [e2e-tests-server-cli, e2e-tests-web] + permissions: {} + runs-on: ubuntu-latest + if: always() + steps: + - name: Any jobs failed? + if: ${{ contains(needs.*.result, 'failure') }} + run: exit 1 + - name: All jobs passed or skipped + if: ${{ !(contains(needs.*.result, 'failure')) }} + # zizmor: ignore[template-injection] + run: echo "All jobs passed or skipped" && echo "${{ toJSON(needs.*.result) }}" + mobile-unit-tests: name: Unit Test Mobile needs: pre-job @@ -431,8 +481,8 @@ jobs: persist-credentials: false - name: Install uv - uses: astral-sh/setup-uv@0c5e2b8115b80b4c7c5ddf6ffdd634974642d182 # v5 - - uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5 + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 # TODO: add caching when supported (https://github.com/actions/setup-python/pull/818) # with: # python-version: 3.11 diff --git a/.github/workflows/weblate-lock.yml b/.github/workflows/weblate-lock.yml index 2aef5c472a..2d644955bc 100644 --- a/.github/workflows/weblate-lock.yml +++ b/.github/workflows/weblate-lock.yml @@ -57,4 +57,5 @@ jobs: run: exit 1 - name: All jobs passed or skipped if: ${{ !(contains(needs.*.result, 'failure')) }} + # zizmor: ignore[template-injection] run: echo "All jobs passed or skipped" && echo "${{ toJSON(needs.*.result) }}" diff --git a/.vscode/settings.json b/.vscode/settings.json index 49692809bc..396755a634 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,45 +1,63 @@ { - "editor.formatOnSave": true, - "[javascript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.tabSize": 2, - "editor.formatOnSave": true - }, - "[typescript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.tabSize": 2, - "editor.formatOnSave": true - }, "[css]": { "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.tabSize": 2, - "editor.formatOnSave": true - }, - "[svelte]": { - "editor.defaultFormatter": "svelte.svelte-vscode", + "editor.formatOnSave": true, "editor.tabSize": 2 }, - "svelte.enable-ts-plugin": true, - "eslint.validate": [ - "javascript", - "svelte" - ], - "typescript.preferences.importModuleSpecifier": "non-relative", "[dart]": { + "editor.defaultFormatter": "Dart-Code.dart-code", "editor.formatOnSave": true, "editor.selectionHighlight": false, "editor.suggest.snippetsPreventQuickSuggestions": false, "editor.suggestSelection": "first", "editor.tabCompletion": "onlySnippets", - "editor.wordBasedSuggestions": "off", - "editor.defaultFormatter": "Dart-Code.dart-code" + "editor.wordBasedSuggestions": "off" }, - "cSpell.words": [ - "immich" - ], + "[javascript]": { + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit", + "source.removeUnusedImports": "explicit" + }, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.tabSize": 2 + }, + "[json]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.tabSize": 2 + }, + "[jsonc]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.tabSize": 2 + }, + "[svelte]": { + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit", + "source.removeUnusedImports": "explicit" + }, + "editor.defaultFormatter": "svelte.svelte-vscode", + "editor.formatOnSave": true, + "editor.tabSize": 2 + }, + "[typescript]": { + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit", + "source.removeUnusedImports": "explicit" + }, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.tabSize": 2 + }, + "cSpell.words": ["immich"], + "editor.formatOnSave": true, + "eslint.validate": ["javascript", "svelte"], "explorer.fileNesting.enabled": true, "explorer.fileNesting.patterns": { - "*.ts": "${capture}.spec.ts,${capture}.mock.ts", - "*.dart": "${capture}.g.dart,${capture}.gr.dart,${capture}.drift.dart" - } -} \ No newline at end of file + "*.dart": "${capture}.g.dart,${capture}.gr.dart,${capture}.drift.dart", + "*.ts": "${capture}.spec.ts,${capture}.mock.ts" + }, + "svelte.enable-ts-plugin": true, + "typescript.preferences.importModuleSpecifier": "non-relative" +} diff --git a/Makefile b/Makefile index e15faa8051..1e7760ae68 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,9 @@ e2e: prod: docker compose -f ./docker/docker-compose.prod.yml up --build -V --remove-orphans +prod-down: + docker compose -f ./docker/docker-compose.prod.yml down --remove-orphans + prod-scale: docker compose -f ./docker/docker-compose.prod.yml up --build -V --scale immich-server=3 --scale immich-microservices=3 --remove-orphans diff --git a/cli/Dockerfile b/cli/Dockerfile index 356537213b..ce345c29a0 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,4 +1,4 @@ -FROM node:22.14.0-alpine3.20@sha256:40be979442621049f40b1d51a26b55e281246b5de4e5f51a18da7beb6e17e3f9 AS core +FROM node:22.15.0-alpine3.20@sha256:686b8892b69879ef5bfd6047589666933508f9a5451c67320df3070ba0e9807b AS core WORKDIR /usr/src/open-api/typescript-sdk COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./ diff --git a/cli/package-lock.json b/cli/package-lock.json index 22f8980754..cc8e88012f 100644 --- a/cli/package-lock.json +++ b/cli/package-lock.json @@ -1,12 +1,12 @@ { "name": "@immich/cli", - "version": "2.2.61", + "version": "2.2.65", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@immich/cli", - "version": "2.2.61", + "version": "2.2.65", "license": "GNU Affero General Public License version 3", "dependencies": { "chokidar": "^4.0.3", @@ -27,7 +27,7 @@ "@types/lodash-es": "^4.17.12", "@types/micromatch": "^4.0.9", "@types/mock-fs": "^4.13.1", - "@types/node": "^22.14.0", + "@types/node": "^22.14.1", "@vitest/coverage-v8": "^3.0.0", "byte-size": "^9.0.0", "cli-progress": "^3.12.0", @@ -54,14 +54,14 @@ }, "../open-api/typescript-sdk": { "name": "@immich/sdk", - "version": "1.131.3", + "version": "1.132.3", "dev": true, "license": "GNU Affero General Public License version 3", "dependencies": { "@oazapfts/runtime": "^1.0.2" }, "devDependencies": { - "@types/node": "^22.14.0", + "@types/node": "^22.14.1", "typescript": "^5.3.3" } }, @@ -647,9 +647,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", - "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", + "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -697,9 +697,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.24.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.24.0.tgz", - "integrity": "sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==", + "version": "9.25.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.25.1.tgz", + "integrity": "sha512-dEIwmjntEx8u3Uvv+kr3PDeeArL8Hw07H9kyYxCjnM9pBjfEhk6uLXSchxxzgiwtRhhzVzqmUSDFBOi1TuZ7qg==", "dev": true, "license": "MIT", "engines": { @@ -730,19 +730,6 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", - "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -1380,17 +1367,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.30.1.tgz", - "integrity": "sha512-v+VWphxMjn+1t48/jO4t950D6KR8JaJuNXzi33Ve6P8sEmPr5k6CEXjdGwT6+LodVnEa91EQCtwjWNUCPweo+Q==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.31.0.tgz", + "integrity": "sha512-evaQJZ/J/S4wisevDvC1KFZkPzRetH8kYZbkgcTRyql3mcKsf+ZFDV1BVWUGTCAW5pQHoqn5gK5b8kn7ou9aFQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.30.1", - "@typescript-eslint/type-utils": "8.30.1", - "@typescript-eslint/utils": "8.30.1", - "@typescript-eslint/visitor-keys": "8.30.1", + "@typescript-eslint/scope-manager": "8.31.0", + "@typescript-eslint/type-utils": "8.31.0", + "@typescript-eslint/utils": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1410,16 +1397,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.30.1.tgz", - "integrity": "sha512-H+vqmWwT5xoNrXqWs/fesmssOW70gxFlgcMlYcBaWNPIEWDgLa4W9nkSPmhuOgLnXq9QYgkZ31fhDyLhleCsAg==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.31.0.tgz", + "integrity": "sha512-67kYYShjBR0jNI5vsf/c3WG4u+zDnCTHTPqVMQguffaWWFs7artgwKmfwdifl+r6XyM5LYLas/dInj2T0SgJyw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.30.1", - "@typescript-eslint/types": "8.30.1", - "@typescript-eslint/typescript-estree": "8.30.1", - "@typescript-eslint/visitor-keys": "8.30.1", + "@typescript-eslint/scope-manager": "8.31.0", + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/typescript-estree": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0", "debug": "^4.3.4" }, "engines": { @@ -1435,14 +1422,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.30.1.tgz", - "integrity": "sha512-+C0B6ChFXZkuaNDl73FJxRYT0G7ufVPOSQkqkpM/U198wUwUFOtgo1k/QzFh1KjpBitaK7R1tgjVz6o9HmsRPg==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.31.0.tgz", + "integrity": "sha512-knO8UyF78Nt8O/B64i7TlGXod69ko7z6vJD9uhSlm0qkAbGeRUSudcm0+K/4CrRjrpiHfBCjMWlc08Vav1xwcw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.30.1", - "@typescript-eslint/visitor-keys": "8.30.1" + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1453,14 +1440,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.30.1.tgz", - "integrity": "sha512-64uBF76bfQiJyHgZISC7vcNz3adqQKIccVoKubyQcOnNcdJBvYOILV1v22Qhsw3tw3VQu5ll8ND6hycgAR5fEA==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.31.0.tgz", + "integrity": "sha512-DJ1N1GdjI7IS7uRlzJuEDCgDQix3ZVYVtgeWEyhyn4iaoitpMBX6Ndd488mXSx0xah/cONAkEaYyylDyAeHMHg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.30.1", - "@typescript-eslint/utils": "8.30.1", + "@typescript-eslint/typescript-estree": "8.31.0", + "@typescript-eslint/utils": "8.31.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.1" }, @@ -1477,9 +1464,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.30.1.tgz", - "integrity": "sha512-81KawPfkuulyWo5QdyG/LOKbspyyiW+p4vpn4bYO7DM/hZImlVnFwrpCTnmNMOt8CvLRr5ojI9nU1Ekpw4RcEw==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.31.0.tgz", + "integrity": "sha512-Ch8oSjVyYyJxPQk8pMiP2FFGYatqXQfQIaMp+TpuuLlDachRWpUAeEu1u9B/v/8LToehUIWyiKcA/w5hUFRKuQ==", "dev": true, "license": "MIT", "engines": { @@ -1491,14 +1478,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.30.1.tgz", - "integrity": "sha512-kQQnxymiUy9tTb1F2uep9W6aBiYODgq5EMSk6Nxh4Z+BDUoYUSa029ISs5zTzKBFnexQEh71KqwjKnRz58lusQ==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.0.tgz", + "integrity": "sha512-xLmgn4Yl46xi6aDSZ9KkyfhhtnYI15/CvHbpOy/eR5NWhK/BK8wc709KKwhAR0m4ZKRP7h07bm4BWUYOCuRpQQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.30.1", - "@typescript-eslint/visitor-keys": "8.30.1", + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1544,16 +1531,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.30.1.tgz", - "integrity": "sha512-T/8q4R9En2tcEsWPQgB5BQ0XJVOtfARcUvOa8yJP3fh9M/mXraLxZrkCfGb6ChrO/V3W+Xbd04RacUEqk1CFEQ==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.31.0.tgz", + "integrity": "sha512-qi6uPLt9cjTFxAb1zGNgTob4x9ur7xC6mHQJ8GwEzGMGE9tYniublmJaowOJ9V2jUzxrltTPfdG2nKlWsq0+Ww==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.30.1", - "@typescript-eslint/types": "8.30.1", - "@typescript-eslint/typescript-estree": "8.30.1" + "@typescript-eslint/scope-manager": "8.31.0", + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/typescript-estree": "8.31.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1568,13 +1555,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.30.1.tgz", - "integrity": "sha512-aEhgas7aJ6vZnNFC7K4/vMGDGyOiqWcYZPpIWrTKuTAlsvDNKy2GFDqh9smL+iq069ZvR0YzEeq0B8NJlLzjFA==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.0.tgz", + "integrity": "sha512-QcGHmlRHWOl93o64ZUMNewCdwKGU6WItOU52H0djgNmn1EOrhVudrDzXz4OycCRSCPwFCDrE2iIt5vmuUdHxuQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.30.1", + "@typescript-eslint/types": "8.31.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -1586,9 +1573,9 @@ } }, "node_modules/@vitest/coverage-v8": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.1.1.tgz", - "integrity": "sha512-MgV6D2dhpD6Hp/uroUoAIvFqA8AuvXEFBC2eepG3WFc1pxTfdk1LEqqkWoWhjz+rytoqrnUUCdf6Lzco3iHkLQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.1.2.tgz", + "integrity": "sha512-XDdaDOeaTMAMYW7N63AqoK32sYUWbXnTkC6tEbVcu3RlU1bB9of32T+PGf8KZvxqLNqeXhafDFqCkwpf2+dyaQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1601,7 +1588,7 @@ "istanbul-reports": "^3.1.7", "magic-string": "^0.30.17", "magicast": "^0.3.5", - "std-env": "^3.8.1", + "std-env": "^3.9.0", "test-exclude": "^7.0.1", "tinyrainbow": "^2.0.0" }, @@ -1609,8 +1596,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "3.1.1", - "vitest": "3.1.1" + "@vitest/browser": "3.1.2", + "vitest": "3.1.2" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -1619,14 +1606,14 @@ } }, "node_modules/@vitest/expect": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.1.tgz", - "integrity": "sha512-q/zjrW9lgynctNbwvFtQkGK9+vvHA5UzVi2V8APrp1C6fG6/MuYYkmlx4FubuqLycCeSdHD5aadWfua/Vr0EUA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.2.tgz", + "integrity": "sha512-O8hJgr+zREopCAqWl3uCVaOdqJwZ9qaDwUP7vy3Xigad0phZe9APxKhPcDNqYYi0rX5oMvwJMSCAXY2afqeTSA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.1.1", - "@vitest/utils": "3.1.1", + "@vitest/spy": "3.1.2", + "@vitest/utils": "3.1.2", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" }, @@ -1635,13 +1622,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.1.tgz", - "integrity": "sha512-bmpJJm7Y7i9BBELlLuuM1J1Q6EQ6K5Ye4wcyOpOMXMcePYKSIYlpcrCm4l/O6ja4VJA5G2aMJiuZkZdnxlC3SA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.2.tgz", + "integrity": "sha512-kOtd6K2lc7SQ0mBqYv/wdGedlqPdM/B38paPY+OwJ1XiNi44w3Fpog82UfOibmHaV9Wod18A09I9SCKLyDMqgw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.1.1", + "@vitest/spy": "3.1.2", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -1662,9 +1649,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.1.tgz", - "integrity": "sha512-dg0CIzNx+hMMYfNmSqJlLSXEmnNhMswcn3sXO7Tpldr0LiGmg3eXdLLhwkv2ZqgHb/d5xg5F7ezNFRA1fA13yA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.2.tgz", + "integrity": "sha512-R0xAiHuWeDjTSB3kQ3OQpT8Rx3yhdOAIm/JM4axXxnG7Q/fS8XUwggv/A4xzbQA+drYRjzkMnpYnOGAc4oeq8w==", "dev": true, "license": "MIT", "dependencies": { @@ -1675,13 +1662,13 @@ } }, "node_modules/@vitest/runner": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.1.tgz", - "integrity": "sha512-X/d46qzJuEDO8ueyjtKfxffiXraPRfmYasoC4i5+mlLEJ10UvPb0XH5M9C3gWuxd7BAQhpK42cJgJtq53YnWVA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.2.tgz", + "integrity": "sha512-bhLib9l4xb4sUMPXnThbnhX2Yi8OutBMA8Yahxa7yavQsFDtwY/jrUZwpKp2XH9DhRFJIeytlyGpXCqZ65nR+g==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.1.1", + "@vitest/utils": "3.1.2", "pathe": "^2.0.3" }, "funding": { @@ -1689,13 +1676,13 @@ } }, "node_modules/@vitest/snapshot": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.1.tgz", - "integrity": "sha512-bByMwaVWe/+1WDf9exFxWWgAixelSdiwo2p33tpqIlM14vW7PRV5ppayVXtfycqze4Qhtwag5sVhX400MLBOOw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.2.tgz", + "integrity": "sha512-Q1qkpazSF/p4ApZg1vfZSQ5Yw6OCQxVMVrLjslbLFA1hMDrT2uxtqMaw8Tc/jy5DLka1sNs1Y7rBcftMiaSH/Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.1.1", + "@vitest/pretty-format": "3.1.2", "magic-string": "^0.30.17", "pathe": "^2.0.3" }, @@ -1704,9 +1691,9 @@ } }, "node_modules/@vitest/spy": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.1.tgz", - "integrity": "sha512-+EmrUOOXbKzLkTDwlsc/xrwOlPDXyVk3Z6P6K4oiCndxz7YLpp/0R0UsWVOKT0IXWjjBJuSMk6D27qipaupcvQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.2.tgz", + "integrity": "sha512-OEc5fSXMws6sHVe4kOFyDSj/+4MSwst0ib4un0DlcYgQvRuYQ0+M2HyqGaauUMnjq87tmUaMNDxKQx7wNfVqPA==", "dev": true, "license": "MIT", "dependencies": { @@ -1717,13 +1704,13 @@ } }, "node_modules/@vitest/utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.1.tgz", - "integrity": "sha512-1XIjflyaU2k3HMArJ50bwSh3wKWPD6Q47wz/NUSmRV0zNywPc4w79ARjg/i/aNINHwA+mIALhUVqD9/aUvZNgg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.2.tgz", + "integrity": "sha512-5GGd0ytZ7BH3H6JTj9Kw7Prn1Nbg0wZVrIvou+UWxm54d+WoXXgAgjFJ8wn3LdagWLFSEfpPeyYrByZaGEZHLg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.1.1", + "@vitest/pretty-format": "3.1.2", "loupe": "^3.1.3", "tinyrainbow": "^2.0.0" }, @@ -2183,9 +2170,9 @@ "license": "MIT" }, "node_modules/es-module-lexer": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", - "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", "dev": true, "license": "MIT" }, @@ -2254,20 +2241,20 @@ } }, "node_modules/eslint": { - "version": "9.24.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.24.0.tgz", - "integrity": "sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==", + "version": "9.25.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.25.1.tgz", + "integrity": "sha512-E6Mtz9oGQWDCpV12319d59n4tx9zOTXSTmc8BLVxBx+G/0RdM5MvEEJLU9c0+aleoePYYgVTOsRblx433qmhWQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.20.0", - "@eslint/config-helpers": "^0.2.0", - "@eslint/core": "^0.12.0", + "@eslint/config-helpers": "^0.2.1", + "@eslint/core": "^0.13.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.24.0", - "@eslint/plugin-kit": "^0.2.7", + "@eslint/js": "9.25.1", + "@eslint/plugin-kit": "^0.2.8", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", @@ -4028,6 +4015,51 @@ "dev": true, "license": "MIT" }, + "node_modules/tinyglobby": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", + "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/tinypool": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", @@ -4152,15 +4184,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.30.1.tgz", - "integrity": "sha512-D7lC0kcehVH7Mb26MRQi64LMyRJsj3dToJxM1+JVTl53DQSV5/7oUGWQLcKl1C1KnoVHxMMU2FNQMffr7F3Row==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.31.0.tgz", + "integrity": "sha512-u+93F0sB0An8WEAPtwxVhFby573E8ckdjwUUQUj9QA4v8JAvgtoDdIyYR3XFwFHq2W1KJ1AurwJCO+w+Y1ixyQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.30.1", - "@typescript-eslint/parser": "8.30.1", - "@typescript-eslint/utils": "8.30.1" + "@typescript-eslint/eslint-plugin": "8.31.0", + "@typescript-eslint/parser": "8.31.0", + "@typescript-eslint/utils": "8.31.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4247,15 +4279,18 @@ } }, "node_modules/vite": { - "version": "6.2.6", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.6.tgz", - "integrity": "sha512-9xpjNl3kR4rVDZgPNdTL0/c6ao4km69a/2ihNQbcANz8RuCOK3hQBmLSJf3bRKVQjVMda+YvizNE8AwvogcPbw==", + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.3.tgz", + "integrity": "sha512-5nXH+QsELbFKhsEfWLkHrvgRpTdGJzqOZ+utSdmPTvwHmvU6ITTm3xx+mRusihkcI8GeC7lCDyn3kDtiki9scw==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", "postcss": "^8.5.3", - "rollup": "^4.30.1" + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" }, "bin": { "vite": "bin/vite.js" @@ -4319,9 +4354,9 @@ } }, "node_modules/vite-node": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.1.tgz", - "integrity": "sha512-V+IxPAE2FvXpTCHXyNem0M+gWm6J7eRyWPR6vYoG/Gl+IscNOjXzztUhimQgTxaAoUoj40Qqimaa0NLIOOAH4w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.2.tgz", + "integrity": "sha512-/8iMryv46J3aK13iUXsei5G/A3CUlW4665THCPS+K8xAaqrVWiGB4RfXMQXCLjpK9P2eK//BczrVkn5JLAk6DA==", "dev": true, "license": "MIT", "dependencies": { @@ -4361,32 +4396,61 @@ } } }, + "node_modules/vite/node_modules/fdir": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/vitest": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.1.tgz", - "integrity": "sha512-kiZc/IYmKICeBAZr9DQ5rT7/6bD9G7uqQEki4fxazi1jdVl2mWGzedtBs5s6llz59yQhVb7FFY2MbHzHCnT79Q==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.2.tgz", + "integrity": "sha512-WaxpJe092ID1C0mr+LH9MmNrhfzi8I65EX/NRU/Ld016KqQNRgxSOlGNP1hHN+a/F8L15Mh8klwaF77zR3GeDQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "3.1.1", - "@vitest/mocker": "3.1.1", - "@vitest/pretty-format": "^3.1.1", - "@vitest/runner": "3.1.1", - "@vitest/snapshot": "3.1.1", - "@vitest/spy": "3.1.1", - "@vitest/utils": "3.1.1", + "@vitest/expect": "3.1.2", + "@vitest/mocker": "3.1.2", + "@vitest/pretty-format": "^3.1.2", + "@vitest/runner": "3.1.2", + "@vitest/snapshot": "3.1.2", + "@vitest/spy": "3.1.2", + "@vitest/utils": "3.1.2", "chai": "^5.2.0", "debug": "^4.4.0", - "expect-type": "^1.2.0", + "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", - "std-env": "^3.8.1", + "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.13", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", - "vite-node": "3.1.1", + "vite-node": "3.1.2", "why-is-node-running": "^2.3.0" }, "bin": { @@ -4402,8 +4466,8 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.1.1", - "@vitest/ui": "3.1.1", + "@vitest/browser": "3.1.2", + "@vitest/ui": "3.1.2", "happy-dom": "*", "jsdom": "*" }, diff --git a/cli/package.json b/cli/package.json index 304c2acfbd..b2d29d6bb9 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,6 +1,6 @@ { "name": "@immich/cli", - "version": "2.2.61", + "version": "2.2.65", "description": "Command Line Interface (CLI) for Immich", "type": "module", "exports": "./dist/index.js", @@ -21,7 +21,7 @@ "@types/lodash-es": "^4.17.12", "@types/micromatch": "^4.0.9", "@types/mock-fs": "^4.13.1", - "@types/node": "^22.14.0", + "@types/node": "^22.14.1", "@vitest/coverage-v8": "^3.0.0", "byte-size": "^9.0.0", "cli-progress": "^3.12.0", diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml index af7e2c52a9..01be1ef247 100644 --- a/docker/docker-compose.dev.yml +++ b/docker/docker-compose.dev.yml @@ -116,7 +116,7 @@ services: redis: container_name: immich_redis - image: docker.io/valkey/valkey:8-bookworm@sha256:42cba146593a5ea9a622002c1b7cba5da7be248650cbb64ecb9c6c33d29794b1 + image: docker.io/valkey/valkey:8-bookworm@sha256:c855f98e09d558a0d7cc1a4e56473231206a4c54c0114ada9c485b47aeb92ec8 healthcheck: test: redis-cli ping || exit 1 diff --git a/docker/docker-compose.prod.yml b/docker/docker-compose.prod.yml index f4a57ecbb9..c4fb086a09 100644 --- a/docker/docker-compose.prod.yml +++ b/docker/docker-compose.prod.yml @@ -56,7 +56,7 @@ services: redis: container_name: immich_redis - image: docker.io/valkey/valkey:8-bookworm@sha256:42cba146593a5ea9a622002c1b7cba5da7be248650cbb64ecb9c6c33d29794b1 + image: docker.io/valkey/valkey:8-bookworm@sha256:c855f98e09d558a0d7cc1a4e56473231206a4c54c0114ada9c485b47aeb92ec8 healthcheck: test: redis-cli ping || exit 1 restart: always @@ -90,7 +90,7 @@ services: container_name: immich_prometheus ports: - 9090:9090 - image: prom/prometheus@sha256:502ad90314c7485892ce696cb14a99fceab9fc27af29f4b427f41bd39701a199 + image: prom/prometheus@sha256:339ce86a59413be18d0e445472891d022725b4803fab609069110205e79fb2f1 volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - prometheus-data:/prometheus @@ -102,7 +102,7 @@ services: command: [ './run.sh', '-disable-reporting' ] ports: - 3000:3000 - image: grafana/grafana:11.6.0-ubuntu@sha256:fd8fa48213c624e1a95122f1d93abbf1cf1cbe85fc73212c1e599dbd76c63ff8 + image: grafana/grafana:11.6.1-ubuntu@sha256:6fc273288470ef499dd3c6b36aeade093170d4f608f864c5dd3a7fabeae77b50 volumes: - grafana-data:/var/lib/grafana diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 499673a383..b9fa6f8b02 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -49,7 +49,7 @@ services: redis: container_name: immich_redis - image: docker.io/valkey/valkey:8-bookworm@sha256:42cba146593a5ea9a622002c1b7cba5da7be248650cbb64ecb9c6c33d29794b1 + image: docker.io/valkey/valkey:8-bookworm@sha256:c855f98e09d558a0d7cc1a4e56473231206a4c54c0114ada9c485b47aeb92ec8 healthcheck: test: redis-cli ping || exit 1 restart: always diff --git a/docs/docs/administration/backup-and-restore.md b/docs/docs/administration/backup-and-restore.md index 817a7dca6d..7e55e4e88f 100644 --- a/docs/docs/administration/backup-and-restore.md +++ b/docs/docs/administration/backup-and-restore.md @@ -23,23 +23,32 @@ Refer to the official [postgres documentation](https://www.postgresql.org/docs/c It is not recommended to directly backup the `DB_DATA_LOCATION` folder. Doing so while the database is running can lead to a corrupted backup that cannot be restored. ::: -### Automatic Database Backups +### Automatic Database Dumps -For convenience, Immich will automatically create database backups by default. The backups are stored in `UPLOAD_LOCATION/backups`. -As mentioned above, you should make your own backup of these together with the asset folders as noted below. -You can adjust the schedule and amount of kept backups in the [admin settings](http://my.immich.app/admin/system-settings?isOpen=backup). -By default, Immich will keep the last 14 backups and create a new backup every day at 2:00 AM. +:::warning +The automatic database dumps can be used to restore the database in the event of damage to the Postgres database files. +There is no monitoring for these dumps and you will not be notified if they are unsuccessful. +::: -#### Trigger Backup +:::caution +The database dumps do **NOT** contain any pictures or videos, only metadata. They are only usable with a copy of the other files in `UPLOAD_LOCATION` as outlined below. +::: -You are able to trigger a backup in the [admin job status page](http://my.immich.app/admin/jobs-status). -Visit the page, open the "Create job" modal from the top right, select "Backup Database" and click "Confirm". -A job will run and trigger a backup, you can verify this worked correctly by checking the logs or the backup folder. -This backup will count towards the last X backups that will be kept based on your settings. +For disaster-recovery purposes, Immich will automatically create database dumps. The dumps are stored in `UPLOAD_LOCATION/backups`. +Please be sure to make your own, independent backup of the database together with the asset folders as noted below. +You can adjust the schedule and amount of kept database dumps in the [admin settings](http://my.immich.app/admin/system-settings?isOpen=backup). +By default, Immich will keep the last 14 database dumps and create a new dump every day at 2:00 AM. + +#### Trigger Dump + +You are able to trigger a database dump in the [admin job status page](http://my.immich.app/admin/jobs-status). +Visit the page, open the "Create job" modal from the top right, select "Create Database Dump" and click "Confirm". +A job will run and trigger a dump, you can verify this worked correctly by checking the logs or the `backups/` folder. +This dumps will count towards the last `X` dumps that will be kept based on your settings. #### Restoring -We hope to make restoring simpler in future versions, for now you can find the backups in the `UPLOAD_LOCATION/backups` folder on your host. +We hope to make restoring simpler in future versions, for now you can find the database dumps in the `UPLOAD_LOCATION/backups` folder on your host. Then please follow the steps in the following section for restoring the database. ### Manual Backup and Restore diff --git a/docs/docs/features/ml-hardware-acceleration.md b/docs/docs/features/ml-hardware-acceleration.md index 8371e726b9..a94f8c8c64 100644 --- a/docs/docs/features/ml-hardware-acceleration.md +++ b/docs/docs/features/ml-hardware-acceleration.md @@ -42,7 +42,7 @@ You do not need to redo any machine learning jobs after enabling hardware accele - The GPU must have compute capability 5.2 or greater. - The server must have the official NVIDIA driver installed. -- The installed driver must be >= 535 (it must support CUDA 12.2). +- The installed driver must be >= 545 (it must support CUDA 12.3). - On Linux (except for WSL2), you also need to have [NVIDIA Container Toolkit][nvct] installed. #### ROCm diff --git a/docs/docs/guides/custom-map-styles.md b/docs/docs/guides/custom-map-styles.md index 3f52937432..1a61afc324 100644 --- a/docs/docs/guides/custom-map-styles.md +++ b/docs/docs/guides/custom-map-styles.md @@ -14,14 +14,14 @@ online generators you can use. 2. Paste the link to your JSON style in either the **Light Style** or **Dark Style**. (You can add different styles which will help make the map style more appropriate depending on whether you set **Immich** to Light or Dark mode.) 3. Save your selections. Reload the map, and enjoy your custom map style! -## Use Maptiler to build a custom style +## Use MapTiler to build a custom style -Customizing the map style can be done easily using Maptiler, if you do not want to write an entire JSON document by hand. +Customizing the map style can be done easily using MapTiler, if you do not want to write an entire JSON document by hand. 1. Create a free account at https://cloud.maptiler.com 2. Once logged in, you can either create a brand new map by clicking on **New Map**, selecting a starter map, and then clicking **Customize**, OR by selecting a **Standard Map** and customizing it from there. 3. The **editor** interface is self-explanatory. You can change colors, remove visible layers, or add optional layers (e.g., administrative, topo, hydro, etc.) in the composer. 4. Once you have your map composed, click on **Save** at the top right. Give it a unique name to save it to your account. -5. Next, **Publish** your style using the **Publish** button at the top right. This will deploy it to production, which means it is able to be exposed over the Internet. Maptiler will present an interactive side-by-side map with the original and your changes prior to publication.
![Maptiler Publication Settings](img/immich_map_styles_publish.webp) -6. Maptiler will warn you that changing the map will change it across all apps using the map. Since no apps are using the map yet, this is okay. -7. Clicking on the name of your new map at the top left will bring you to the item's **details** page. From here, copy the link to the JSON style under **Use vector style**. This link will automatically contain your personal API key to Maptiler. +5. Next, **Publish** your style using the **Publish** button at the top right. This will deploy it to production, which means it is able to be exposed over the Internet. MapTiler will present an interactive side-by-side map with the original and your changes prior to publication.
![MapTiler Publication Settings](img/immich_map_styles_publish.webp) +6. MapTiler will warn you that changing the map will change it across all apps using the map. Since no apps are using the map yet, this is okay. +7. Clicking on the name of your new map at the top left will bring you to the item's **details** page. From here, copy the link to the JSON style under **Use vector style**. This link will automatically contain your personal API key to MapTiler. diff --git a/docs/docs/guides/database-queries.md b/docs/docs/guides/database-queries.md index 89a4f07bc0..209f673993 100644 --- a/docs/docs/guides/database-queries.md +++ b/docs/docs/guides/database-queries.md @@ -1,7 +1,7 @@ # Database Queries :::danger -Keep in mind that mucking around in the database might set the moon on fire. Avoid modifying the database directly when possible, and always have current backups. +Keep in mind that mucking around in the database might set the Moon on fire. Avoid modifying the database directly when possible, and always have current backups. ::: :::tip diff --git a/docs/src/components/community-projects.tsx b/docs/src/components/community-projects.tsx index b30544d461..e70b5af50f 100644 --- a/docs/src/components/community-projects.tsx +++ b/docs/src/components/community-projects.tsx @@ -40,8 +40,9 @@ const projects: CommunityProjectProps[] = [ }, { title: 'Lightroom Immich Plugin: lrc-immich-plugin', - description: 'Another Lightroom plugin to publish or export photos from Lightroom to Immich.', - url: 'https://github.com/bmachek/lrc-immich-plugin', + description: + 'Lightroom plugin to publish, export photos from Lightroom to Immich. Import from Immich to Lightroom is also supported.', + url: 'https://blog.fokuspunk.de/lrc-immich-plugin/', }, { title: 'Immich Duplicate Finder', diff --git a/docs/src/pages/index.tsx b/docs/src/pages/index.tsx index 2ffe1debc7..db299271aa 100644 --- a/docs/src/pages/index.tsx +++ b/docs/src/pages/index.tsx @@ -4,6 +4,7 @@ import Layout from '@theme/Layout'; import { discordPath, discordViewBox } from '@site/src/components/svg-paths'; import ThemedImage from '@theme/ThemedImage'; import Icon from '@mdi/react'; +import { mdiAndroid } from '@mdi/js'; function HomepageHeader() { return (
@@ -88,11 +89,18 @@ function HomepageHeader() { Get it on Google Play +
Download on the App Store
+ +
+ + Download APK + +
+ + + + + + + + + + + + diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml index e05d7734ed..48c17c828b 100644 --- a/e2e/docker-compose.yml +++ b/e2e/docker-compose.yml @@ -34,7 +34,7 @@ services: - 2285:2285 redis: - image: redis:6.2-alpine@sha256:148bb5411c184abd288d9aaed139c98123eeb8824c5d3fce03cf721db58066d8 + image: redis:6.2-alpine@sha256:3211c33a618c457e5d241922c975dbc4f446d0bdb2dc75694f5573ef8e2d01fa database: image: tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:739cdd626151ff1f796dc95a6591b55a714f341c737e27f045019ceabf8e8c52 diff --git a/e2e/package-lock.json b/e2e/package-lock.json index d09a7e9701..a61324beff 100644 --- a/e2e/package-lock.json +++ b/e2e/package-lock.json @@ -1,12 +1,12 @@ { "name": "immich-e2e", - "version": "1.131.3", + "version": "1.132.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "immich-e2e", - "version": "1.131.3", + "version": "1.132.3", "license": "GNU Affero General Public License version 3", "devDependencies": { "@eslint/eslintrc": "^3.1.0", @@ -15,7 +15,7 @@ "@immich/sdk": "file:../open-api/typescript-sdk", "@playwright/test": "^1.44.1", "@types/luxon": "^3.4.2", - "@types/node": "^22.14.0", + "@types/node": "^22.14.1", "@types/oidc-provider": "^8.5.1", "@types/pg": "^8.11.0", "@types/pngjs": "^6.0.4", @@ -44,7 +44,7 @@ }, "../cli": { "name": "@immich/cli", - "version": "2.2.61", + "version": "2.2.65", "dev": true, "license": "GNU Affero General Public License version 3", "dependencies": { @@ -66,7 +66,7 @@ "@types/lodash-es": "^4.17.12", "@types/micromatch": "^4.0.9", "@types/mock-fs": "^4.13.1", - "@types/node": "^22.14.0", + "@types/node": "^22.14.1", "@vitest/coverage-v8": "^3.0.0", "byte-size": "^9.0.0", "cli-progress": "^3.12.0", @@ -93,14 +93,14 @@ }, "../open-api/typescript-sdk": { "name": "@immich/sdk", - "version": "1.131.3", + "version": "1.132.3", "dev": true, "license": "GNU Affero General Public License version 3", "dependencies": { "@oazapfts/runtime": "^1.0.2" }, "devDependencies": { - "@types/node": "^22.14.0", + "@types/node": "^22.14.1", "typescript": "^5.3.3" } }, @@ -194,9 +194,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz", - "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.3.tgz", + "integrity": "sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==", "cpu": [ "ppc64" ], @@ -211,9 +211,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz", - "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.3.tgz", + "integrity": "sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==", "cpu": [ "arm" ], @@ -228,9 +228,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz", - "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.3.tgz", + "integrity": "sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==", "cpu": [ "arm64" ], @@ -245,9 +245,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz", - "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.3.tgz", + "integrity": "sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==", "cpu": [ "x64" ], @@ -262,9 +262,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz", - "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.3.tgz", + "integrity": "sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==", "cpu": [ "arm64" ], @@ -279,9 +279,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz", - "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.3.tgz", + "integrity": "sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==", "cpu": [ "x64" ], @@ -296,9 +296,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz", - "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.3.tgz", + "integrity": "sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==", "cpu": [ "arm64" ], @@ -313,9 +313,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz", - "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.3.tgz", + "integrity": "sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==", "cpu": [ "x64" ], @@ -330,9 +330,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz", - "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.3.tgz", + "integrity": "sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==", "cpu": [ "arm" ], @@ -347,9 +347,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz", - "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.3.tgz", + "integrity": "sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==", "cpu": [ "arm64" ], @@ -364,9 +364,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz", - "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.3.tgz", + "integrity": "sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==", "cpu": [ "ia32" ], @@ -381,9 +381,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz", - "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.3.tgz", + "integrity": "sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==", "cpu": [ "loong64" ], @@ -398,9 +398,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz", - "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.3.tgz", + "integrity": "sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==", "cpu": [ "mips64el" ], @@ -415,9 +415,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz", - "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.3.tgz", + "integrity": "sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==", "cpu": [ "ppc64" ], @@ -432,9 +432,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz", - "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.3.tgz", + "integrity": "sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==", "cpu": [ "riscv64" ], @@ -449,9 +449,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz", - "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.3.tgz", + "integrity": "sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==", "cpu": [ "s390x" ], @@ -466,9 +466,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz", - "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.3.tgz", + "integrity": "sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==", "cpu": [ "x64" ], @@ -483,9 +483,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz", - "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.3.tgz", + "integrity": "sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==", "cpu": [ "arm64" ], @@ -500,9 +500,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz", - "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.3.tgz", + "integrity": "sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==", "cpu": [ "x64" ], @@ -517,9 +517,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz", - "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.3.tgz", + "integrity": "sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==", "cpu": [ "arm64" ], @@ -534,9 +534,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz", - "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.3.tgz", + "integrity": "sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==", "cpu": [ "x64" ], @@ -551,9 +551,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz", - "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.3.tgz", + "integrity": "sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==", "cpu": [ "x64" ], @@ -568,9 +568,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz", - "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.3.tgz", + "integrity": "sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==", "cpu": [ "arm64" ], @@ -585,9 +585,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz", - "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.3.tgz", + "integrity": "sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==", "cpu": [ "ia32" ], @@ -602,9 +602,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz", - "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.3.tgz", + "integrity": "sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==", "cpu": [ "x64" ], @@ -686,9 +686,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", - "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", + "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -736,9 +736,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.24.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.24.0.tgz", - "integrity": "sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==", + "version": "9.25.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.25.1.tgz", + "integrity": "sha512-dEIwmjntEx8u3Uvv+kr3PDeeArL8Hw07H9kyYxCjnM9pBjfEhk6uLXSchxxzgiwtRhhzVzqmUSDFBOi1TuZ7qg==", "dev": true, "license": "MIT", "engines": { @@ -769,19 +769,6 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", - "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -1082,13 +1069,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.51.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.51.1.tgz", - "integrity": "sha512-nM+kEaTSAoVlXmMPH10017vn3FSiFqr/bh4fKg9vmAdMfd9SDqRZNvPSiAHADc/itWak+qPvMPZQOPwCBW7k7Q==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.52.0.tgz", + "integrity": "sha512-uh6W7sb55hl7D6vsAeA+V2p5JnlAqzhqFyF0VcJkKZXkgnFcVG9PziERRHQfPLfNGx1C292a4JqbWzhR8L4R1g==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.51.1" + "playwright": "1.52.0" }, "bin": { "playwright": "cli.js" @@ -1098,9 +1085,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.0.tgz", - "integrity": "sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.1.tgz", + "integrity": "sha512-kxz0YeeCrRUHz3zyqvd7n+TVRlNyTifBsmnmNPtk3hQURUyG9eAB+usz6DAwagMusjx/zb3AjvDUvhFGDAexGw==", "cpu": [ "arm" ], @@ -1112,9 +1099,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.0.tgz", - "integrity": "sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.1.tgz", + "integrity": "sha512-PPkxTOisoNC6TpnDKatjKkjRMsdaWIhyuMkA4UsBXT9WEZY4uHezBTjs6Vl4PbqQQeu6oION1w2voYZv9yquCw==", "cpu": [ "arm64" ], @@ -1126,9 +1113,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.0.tgz", - "integrity": "sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.1.tgz", + "integrity": "sha512-VWXGISWFY18v/0JyNUy4A46KCFCb9NVsH+1100XP31lud+TzlezBbz24CYzbnA4x6w4hx+NYCXDfnvDVO6lcAA==", "cpu": [ "arm64" ], @@ -1140,9 +1127,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.0.tgz", - "integrity": "sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.1.tgz", + "integrity": "sha512-nIwkXafAI1/QCS7pxSpv/ZtFW6TXcNUEHAIA9EIyw5OzxJZQ1YDrX+CL6JAIQgZ33CInl1R6mHet9Y/UZTg2Bw==", "cpu": [ "x64" ], @@ -1154,9 +1141,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.0.tgz", - "integrity": "sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.1.tgz", + "integrity": "sha512-BdrLJ2mHTrIYdaS2I99mriyJfGGenSaP+UwGi1kB9BLOCu9SR8ZpbkmmalKIALnRw24kM7qCN0IOm6L0S44iWw==", "cpu": [ "arm64" ], @@ -1168,9 +1155,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.0.tgz", - "integrity": "sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.1.tgz", + "integrity": "sha512-VXeo/puqvCG8JBPNZXZf5Dqq7BzElNJzHRRw3vjBE27WujdzuOPecDPc/+1DcdcTptNBep3861jNq0mYkT8Z6Q==", "cpu": [ "x64" ], @@ -1182,9 +1169,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.0.tgz", - "integrity": "sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.1.tgz", + "integrity": "sha512-ehSKrewwsESPt1TgSE/na9nIhWCosfGSFqv7vwEtjyAqZcvbGIg4JAcV7ZEh2tfj/IlfBeZjgOXm35iOOjadcg==", "cpu": [ "arm" ], @@ -1196,9 +1183,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.0.tgz", - "integrity": "sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.1.tgz", + "integrity": "sha512-m39iO/aaurh5FVIu/F4/Zsl8xppd76S4qoID8E+dSRQvTyZTOI2gVk3T4oqzfq1PtcvOfAVlwLMK3KRQMaR8lg==", "cpu": [ "arm" ], @@ -1210,9 +1197,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.0.tgz", - "integrity": "sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.1.tgz", + "integrity": "sha512-Y+GHnGaku4aVLSgrT0uWe2o2Rq8te9hi+MwqGF9r9ORgXhmHK5Q71N757u0F8yU1OIwUIFy6YiJtKjtyktk5hg==", "cpu": [ "arm64" ], @@ -1224,9 +1211,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.0.tgz", - "integrity": "sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.1.tgz", + "integrity": "sha512-jEwjn3jCA+tQGswK3aEWcD09/7M5wGwc6+flhva7dsQNRZZTe30vkalgIzV4tjkopsTS9Jd7Y1Bsj6a4lzz8gQ==", "cpu": [ "arm64" ], @@ -1238,9 +1225,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.0.tgz", - "integrity": "sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.1.tgz", + "integrity": "sha512-ySyWikVhNzv+BV/IDCsrraOAZ3UaC8SZB67FZlqVwXwnFhPihOso9rPOxzZbjp81suB1O2Topw+6Ug3JNegejQ==", "cpu": [ "loong64" ], @@ -1252,9 +1239,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.0.tgz", - "integrity": "sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.1.tgz", + "integrity": "sha512-BvvA64QxZlh7WZWqDPPdt0GH4bznuL6uOO1pmgPnnv86rpUpc8ZxgZwcEgXvo02GRIZX1hQ0j0pAnhwkhwPqWg==", "cpu": [ "ppc64" ], @@ -1266,9 +1253,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.0.tgz", - "integrity": "sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.1.tgz", + "integrity": "sha512-EQSP+8+1VuSulm9RKSMKitTav89fKbHymTf25n5+Yr6gAPZxYWpj3DzAsQqoaHAk9YX2lwEyAf9S4W8F4l3VBQ==", "cpu": [ "riscv64" ], @@ -1280,9 +1267,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.0.tgz", - "integrity": "sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.1.tgz", + "integrity": "sha512-n/vQ4xRZXKuIpqukkMXZt9RWdl+2zgGNx7Uda8NtmLJ06NL8jiHxUawbwC+hdSq1rrw/9CghCpEONor+l1e2gA==", "cpu": [ "riscv64" ], @@ -1294,9 +1281,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.0.tgz", - "integrity": "sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.1.tgz", + "integrity": "sha512-h8d28xzYb98fMQKUz0w2fMc1XuGzLLjdyxVIbhbil4ELfk5/orZlSTpF/xdI9C8K0I8lCkq+1En2RJsawZekkg==", "cpu": [ "s390x" ], @@ -1308,9 +1295,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.0.tgz", - "integrity": "sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.1.tgz", + "integrity": "sha512-XiK5z70PEFEFqcNj3/zRSz/qX4bp4QIraTy9QjwJAb/Z8GM7kVUsD0Uk8maIPeTyPCP03ChdI+VVmJriKYbRHQ==", "cpu": [ "x64" ], @@ -1322,9 +1309,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.0.tgz", - "integrity": "sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.1.tgz", + "integrity": "sha512-2BRORitq5rQ4Da9blVovzNCMaUlyKrzMSvkVR0D4qPuOy/+pMCrh1d7o01RATwVy+6Fa1WBw+da7QPeLWU/1mQ==", "cpu": [ "x64" ], @@ -1336,9 +1323,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.0.tgz", - "integrity": "sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.1.tgz", + "integrity": "sha512-b2bcNm9Kbde03H+q+Jjw9tSfhYkzrDUf2d5MAd1bOJuVplXvFhWz7tRtWvD8/ORZi7qSCy0idW6tf2HgxSXQSg==", "cpu": [ "arm64" ], @@ -1350,9 +1337,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.0.tgz", - "integrity": "sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.1.tgz", + "integrity": "sha512-DfcogW8N7Zg7llVEfpqWMZcaErKfsj9VvmfSyRjCyo4BI3wPEfrzTtJkZG6gKP/Z92wFm6rz2aDO7/JfiR/whA==", "cpu": [ "ia32" ], @@ -1364,9 +1351,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.0.tgz", - "integrity": "sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.1.tgz", + "integrity": "sha512-ECyOuDeH3C1I8jH2MK1RtBJW+YPMvSfT0a5NN0nHfQYnDSJ6tUiZH3gzwVP5/Kfh/+Tt7tpWVF9LXNTnhTJ3kA==", "cpu": [ "x64" ], @@ -1613,9 +1600,9 @@ } }, "node_modules/@types/pg": { - "version": "8.11.13", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.13.tgz", - "integrity": "sha512-6kXByGkvRvwXLuyaWzsebs2du6+XuAB2CuMsuzP7uaihQahshVgSmB22Pmh0vQMkQ1h5+PZU0d+Di1o+WpVWJg==", + "version": "8.11.14", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.14.tgz", + "integrity": "sha512-qyD11E5R3u0eJmd1lB0WnWKXJGA7s015nyARWljfz5DcX83TKAIlY+QrmvzQTsbIe+hkiFtkyL2gHC6qwF6Fbg==", "dev": true, "license": "MIT", "dependencies": { @@ -1696,17 +1683,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.30.1.tgz", - "integrity": "sha512-v+VWphxMjn+1t48/jO4t950D6KR8JaJuNXzi33Ve6P8sEmPr5k6CEXjdGwT6+LodVnEa91EQCtwjWNUCPweo+Q==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.31.0.tgz", + "integrity": "sha512-evaQJZ/J/S4wisevDvC1KFZkPzRetH8kYZbkgcTRyql3mcKsf+ZFDV1BVWUGTCAW5pQHoqn5gK5b8kn7ou9aFQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.30.1", - "@typescript-eslint/type-utils": "8.30.1", - "@typescript-eslint/utils": "8.30.1", - "@typescript-eslint/visitor-keys": "8.30.1", + "@typescript-eslint/scope-manager": "8.31.0", + "@typescript-eslint/type-utils": "8.31.0", + "@typescript-eslint/utils": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1726,16 +1713,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.30.1.tgz", - "integrity": "sha512-H+vqmWwT5xoNrXqWs/fesmssOW70gxFlgcMlYcBaWNPIEWDgLa4W9nkSPmhuOgLnXq9QYgkZ31fhDyLhleCsAg==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.31.0.tgz", + "integrity": "sha512-67kYYShjBR0jNI5vsf/c3WG4u+zDnCTHTPqVMQguffaWWFs7artgwKmfwdifl+r6XyM5LYLas/dInj2T0SgJyw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.30.1", - "@typescript-eslint/types": "8.30.1", - "@typescript-eslint/typescript-estree": "8.30.1", - "@typescript-eslint/visitor-keys": "8.30.1", + "@typescript-eslint/scope-manager": "8.31.0", + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/typescript-estree": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0", "debug": "^4.3.4" }, "engines": { @@ -1751,14 +1738,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.30.1.tgz", - "integrity": "sha512-+C0B6ChFXZkuaNDl73FJxRYT0G7ufVPOSQkqkpM/U198wUwUFOtgo1k/QzFh1KjpBitaK7R1tgjVz6o9HmsRPg==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.31.0.tgz", + "integrity": "sha512-knO8UyF78Nt8O/B64i7TlGXod69ko7z6vJD9uhSlm0qkAbGeRUSudcm0+K/4CrRjrpiHfBCjMWlc08Vav1xwcw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.30.1", - "@typescript-eslint/visitor-keys": "8.30.1" + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1769,14 +1756,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.30.1.tgz", - "integrity": "sha512-64uBF76bfQiJyHgZISC7vcNz3adqQKIccVoKubyQcOnNcdJBvYOILV1v22Qhsw3tw3VQu5ll8ND6hycgAR5fEA==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.31.0.tgz", + "integrity": "sha512-DJ1N1GdjI7IS7uRlzJuEDCgDQix3ZVYVtgeWEyhyn4iaoitpMBX6Ndd488mXSx0xah/cONAkEaYyylDyAeHMHg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.30.1", - "@typescript-eslint/utils": "8.30.1", + "@typescript-eslint/typescript-estree": "8.31.0", + "@typescript-eslint/utils": "8.31.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.1" }, @@ -1793,9 +1780,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.30.1.tgz", - "integrity": "sha512-81KawPfkuulyWo5QdyG/LOKbspyyiW+p4vpn4bYO7DM/hZImlVnFwrpCTnmNMOt8CvLRr5ojI9nU1Ekpw4RcEw==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.31.0.tgz", + "integrity": "sha512-Ch8oSjVyYyJxPQk8pMiP2FFGYatqXQfQIaMp+TpuuLlDachRWpUAeEu1u9B/v/8LToehUIWyiKcA/w5hUFRKuQ==", "dev": true, "license": "MIT", "engines": { @@ -1807,14 +1794,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.30.1.tgz", - "integrity": "sha512-kQQnxymiUy9tTb1F2uep9W6aBiYODgq5EMSk6Nxh4Z+BDUoYUSa029ISs5zTzKBFnexQEh71KqwjKnRz58lusQ==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.0.tgz", + "integrity": "sha512-xLmgn4Yl46xi6aDSZ9KkyfhhtnYI15/CvHbpOy/eR5NWhK/BK8wc709KKwhAR0m4ZKRP7h07bm4BWUYOCuRpQQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.30.1", - "@typescript-eslint/visitor-keys": "8.30.1", + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1860,16 +1847,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.30.1.tgz", - "integrity": "sha512-T/8q4R9En2tcEsWPQgB5BQ0XJVOtfARcUvOa8yJP3fh9M/mXraLxZrkCfGb6ChrO/V3W+Xbd04RacUEqk1CFEQ==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.31.0.tgz", + "integrity": "sha512-qi6uPLt9cjTFxAb1zGNgTob4x9ur7xC6mHQJ8GwEzGMGE9tYniublmJaowOJ9V2jUzxrltTPfdG2nKlWsq0+Ww==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.30.1", - "@typescript-eslint/types": "8.30.1", - "@typescript-eslint/typescript-estree": "8.30.1" + "@typescript-eslint/scope-manager": "8.31.0", + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/typescript-estree": "8.31.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1884,13 +1871,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.30.1.tgz", - "integrity": "sha512-aEhgas7aJ6vZnNFC7K4/vMGDGyOiqWcYZPpIWrTKuTAlsvDNKy2GFDqh9smL+iq069ZvR0YzEeq0B8NJlLzjFA==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.0.tgz", + "integrity": "sha512-QcGHmlRHWOl93o64ZUMNewCdwKGU6WItOU52H0djgNmn1EOrhVudrDzXz4OycCRSCPwFCDrE2iIt5vmuUdHxuQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.30.1", + "@typescript-eslint/types": "8.31.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -1902,9 +1889,9 @@ } }, "node_modules/@vitest/coverage-v8": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.1.1.tgz", - "integrity": "sha512-MgV6D2dhpD6Hp/uroUoAIvFqA8AuvXEFBC2eepG3WFc1pxTfdk1LEqqkWoWhjz+rytoqrnUUCdf6Lzco3iHkLQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.1.2.tgz", + "integrity": "sha512-XDdaDOeaTMAMYW7N63AqoK32sYUWbXnTkC6tEbVcu3RlU1bB9of32T+PGf8KZvxqLNqeXhafDFqCkwpf2+dyaQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1917,7 +1904,7 @@ "istanbul-reports": "^3.1.7", "magic-string": "^0.30.17", "magicast": "^0.3.5", - "std-env": "^3.8.1", + "std-env": "^3.9.0", "test-exclude": "^7.0.1", "tinyrainbow": "^2.0.0" }, @@ -1925,8 +1912,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "3.1.1", - "vitest": "3.1.1" + "@vitest/browser": "3.1.2", + "vitest": "3.1.2" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -1935,14 +1922,14 @@ } }, "node_modules/@vitest/expect": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.1.tgz", - "integrity": "sha512-q/zjrW9lgynctNbwvFtQkGK9+vvHA5UzVi2V8APrp1C6fG6/MuYYkmlx4FubuqLycCeSdHD5aadWfua/Vr0EUA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.2.tgz", + "integrity": "sha512-O8hJgr+zREopCAqWl3uCVaOdqJwZ9qaDwUP7vy3Xigad0phZe9APxKhPcDNqYYi0rX5oMvwJMSCAXY2afqeTSA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.1.1", - "@vitest/utils": "3.1.1", + "@vitest/spy": "3.1.2", + "@vitest/utils": "3.1.2", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" }, @@ -1951,13 +1938,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.1.tgz", - "integrity": "sha512-bmpJJm7Y7i9BBELlLuuM1J1Q6EQ6K5Ye4wcyOpOMXMcePYKSIYlpcrCm4l/O6ja4VJA5G2aMJiuZkZdnxlC3SA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.2.tgz", + "integrity": "sha512-kOtd6K2lc7SQ0mBqYv/wdGedlqPdM/B38paPY+OwJ1XiNi44w3Fpog82UfOibmHaV9Wod18A09I9SCKLyDMqgw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.1.1", + "@vitest/spy": "3.1.2", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -1978,9 +1965,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.1.tgz", - "integrity": "sha512-dg0CIzNx+hMMYfNmSqJlLSXEmnNhMswcn3sXO7Tpldr0LiGmg3eXdLLhwkv2ZqgHb/d5xg5F7ezNFRA1fA13yA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.2.tgz", + "integrity": "sha512-R0xAiHuWeDjTSB3kQ3OQpT8Rx3yhdOAIm/JM4axXxnG7Q/fS8XUwggv/A4xzbQA+drYRjzkMnpYnOGAc4oeq8w==", "dev": true, "license": "MIT", "dependencies": { @@ -1991,13 +1978,13 @@ } }, "node_modules/@vitest/runner": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.1.tgz", - "integrity": "sha512-X/d46qzJuEDO8ueyjtKfxffiXraPRfmYasoC4i5+mlLEJ10UvPb0XH5M9C3gWuxd7BAQhpK42cJgJtq53YnWVA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.2.tgz", + "integrity": "sha512-bhLib9l4xb4sUMPXnThbnhX2Yi8OutBMA8Yahxa7yavQsFDtwY/jrUZwpKp2XH9DhRFJIeytlyGpXCqZ65nR+g==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.1.1", + "@vitest/utils": "3.1.2", "pathe": "^2.0.3" }, "funding": { @@ -2005,13 +1992,13 @@ } }, "node_modules/@vitest/snapshot": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.1.tgz", - "integrity": "sha512-bByMwaVWe/+1WDf9exFxWWgAixelSdiwo2p33tpqIlM14vW7PRV5ppayVXtfycqze4Qhtwag5sVhX400MLBOOw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.2.tgz", + "integrity": "sha512-Q1qkpazSF/p4ApZg1vfZSQ5Yw6OCQxVMVrLjslbLFA1hMDrT2uxtqMaw8Tc/jy5DLka1sNs1Y7rBcftMiaSH/Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.1.1", + "@vitest/pretty-format": "3.1.2", "magic-string": "^0.30.17", "pathe": "^2.0.3" }, @@ -2020,9 +2007,9 @@ } }, "node_modules/@vitest/spy": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.1.tgz", - "integrity": "sha512-+EmrUOOXbKzLkTDwlsc/xrwOlPDXyVk3Z6P6K4oiCndxz7YLpp/0R0UsWVOKT0IXWjjBJuSMk6D27qipaupcvQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.2.tgz", + "integrity": "sha512-OEc5fSXMws6sHVe4kOFyDSj/+4MSwst0ib4un0DlcYgQvRuYQ0+M2HyqGaauUMnjq87tmUaMNDxKQx7wNfVqPA==", "dev": true, "license": "MIT", "dependencies": { @@ -2033,13 +2020,13 @@ } }, "node_modules/@vitest/utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.1.tgz", - "integrity": "sha512-1XIjflyaU2k3HMArJ50bwSh3wKWPD6Q47wz/NUSmRV0zNywPc4w79ARjg/i/aNINHwA+mIALhUVqD9/aUvZNgg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.2.tgz", + "integrity": "sha512-5GGd0ytZ7BH3H6JTj9Kw7Prn1Nbg0wZVrIvou+UWxm54d+WoXXgAgjFJ8wn3LdagWLFSEfpPeyYrByZaGEZHLg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.1.1", + "@vitest/pretty-format": "3.1.2", "loupe": "^3.1.3", "tinyrainbow": "^2.0.0" }, @@ -2915,9 +2902,9 @@ } }, "node_modules/es-module-lexer": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", - "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", "dev": true, "license": "MIT" }, @@ -2951,9 +2938,9 @@ } }, "node_modules/esbuild": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", - "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.3.tgz", + "integrity": "sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -2964,31 +2951,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.2", - "@esbuild/android-arm": "0.25.2", - "@esbuild/android-arm64": "0.25.2", - "@esbuild/android-x64": "0.25.2", - "@esbuild/darwin-arm64": "0.25.2", - "@esbuild/darwin-x64": "0.25.2", - "@esbuild/freebsd-arm64": "0.25.2", - "@esbuild/freebsd-x64": "0.25.2", - "@esbuild/linux-arm": "0.25.2", - "@esbuild/linux-arm64": "0.25.2", - "@esbuild/linux-ia32": "0.25.2", - "@esbuild/linux-loong64": "0.25.2", - "@esbuild/linux-mips64el": "0.25.2", - "@esbuild/linux-ppc64": "0.25.2", - "@esbuild/linux-riscv64": "0.25.2", - "@esbuild/linux-s390x": "0.25.2", - "@esbuild/linux-x64": "0.25.2", - "@esbuild/netbsd-arm64": "0.25.2", - "@esbuild/netbsd-x64": "0.25.2", - "@esbuild/openbsd-arm64": "0.25.2", - "@esbuild/openbsd-x64": "0.25.2", - "@esbuild/sunos-x64": "0.25.2", - "@esbuild/win32-arm64": "0.25.2", - "@esbuild/win32-ia32": "0.25.2", - "@esbuild/win32-x64": "0.25.2" + "@esbuild/aix-ppc64": "0.25.3", + "@esbuild/android-arm": "0.25.3", + "@esbuild/android-arm64": "0.25.3", + "@esbuild/android-x64": "0.25.3", + "@esbuild/darwin-arm64": "0.25.3", + "@esbuild/darwin-x64": "0.25.3", + "@esbuild/freebsd-arm64": "0.25.3", + "@esbuild/freebsd-x64": "0.25.3", + "@esbuild/linux-arm": "0.25.3", + "@esbuild/linux-arm64": "0.25.3", + "@esbuild/linux-ia32": "0.25.3", + "@esbuild/linux-loong64": "0.25.3", + "@esbuild/linux-mips64el": "0.25.3", + "@esbuild/linux-ppc64": "0.25.3", + "@esbuild/linux-riscv64": "0.25.3", + "@esbuild/linux-s390x": "0.25.3", + "@esbuild/linux-x64": "0.25.3", + "@esbuild/netbsd-arm64": "0.25.3", + "@esbuild/netbsd-x64": "0.25.3", + "@esbuild/openbsd-arm64": "0.25.3", + "@esbuild/openbsd-x64": "0.25.3", + "@esbuild/sunos-x64": "0.25.3", + "@esbuild/win32-arm64": "0.25.3", + "@esbuild/win32-ia32": "0.25.3", + "@esbuild/win32-x64": "0.25.3" } }, "node_modules/escalade": { @@ -3022,20 +3009,20 @@ } }, "node_modules/eslint": { - "version": "9.24.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.24.0.tgz", - "integrity": "sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==", + "version": "9.25.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.25.1.tgz", + "integrity": "sha512-E6Mtz9oGQWDCpV12319d59n4tx9zOTXSTmc8BLVxBx+G/0RdM5MvEEJLU9c0+aleoePYYgVTOsRblx433qmhWQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.20.0", - "@eslint/config-helpers": "^0.2.0", - "@eslint/core": "^0.12.0", + "@eslint/config-helpers": "^0.2.1", + "@eslint/core": "^0.13.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.24.0", - "@eslint/plugin-kit": "^0.2.7", + "@eslint/js": "9.25.1", + "@eslint/plugin-kit": "^0.2.8", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", @@ -5235,15 +5222,15 @@ } }, "node_modules/pg": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.14.1.tgz", - "integrity": "sha512-0TdbqfjwIun9Fm/r89oB7RFQ0bLgduAhiIqIXOsyKoiC/L54DbuAAzIEN/9Op0f1Po9X7iCPXGoa/Ah+2aI8Xw==", + "version": "8.15.5", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.15.5.tgz", + "integrity": "sha512-EpAhHFQc+aH9VfeffWIVC+XXk6lmAhS9W1FxtxcPXs94yxhrI1I6w/zkWfIOII/OkBv3Be04X3xMOj0kQ78l6w==", "dev": true, "license": "MIT", "dependencies": { - "pg-connection-string": "^2.7.0", - "pg-pool": "^3.8.0", - "pg-protocol": "^1.8.0", + "pg-connection-string": "^2.8.5", + "pg-pool": "^3.9.5", + "pg-protocol": "^1.9.5", "pg-types": "^2.1.0", "pgpass": "1.x" }, @@ -5251,7 +5238,7 @@ "node": ">= 8.0.0" }, "optionalDependencies": { - "pg-cloudflare": "^1.1.1" + "pg-cloudflare": "^1.2.5" }, "peerDependencies": { "pg-native": ">=3.0.1" @@ -5263,17 +5250,17 @@ } }, "node_modules/pg-cloudflare": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.2.5.tgz", + "integrity": "sha512-OOX22Vt0vOSRrdoUPKJ8Wi2OpE/o/h9T8X1s4qSkCedbNah9ei2W2765be8iMVxQUsvgT7zIAT2eIa9fs5+vtg==", "dev": true, "license": "MIT", "optional": true }, "node_modules/pg-connection-string": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.7.0.tgz", - "integrity": "sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==", + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.8.5.tgz", + "integrity": "sha512-Ni8FuZ8yAF+sWZzojvtLE2b03cqjO5jNULcHFfM9ZZ0/JXrgom5pBREbtnAw7oxsxJqHw9Nz/XWORUEL3/IFow==", "dev": true, "license": "MIT" }, @@ -5298,9 +5285,9 @@ } }, "node_modules/pg-pool": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.8.0.tgz", - "integrity": "sha512-VBw3jiVm6ZOdLBTIcXLNdSotb6Iy3uOCwDGFAksZCXmi10nyRvnP2v3jl4d+IsLYRyXf6o9hIm/ZtUzlByNUdw==", + "version": "3.9.6", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.9.6.tgz", + "integrity": "sha512-rFen0G7adh1YmgvrmE5IPIqbb+IgEzENUm+tzm6MLLDSlPRoZVhzU1WdML9PV2W5GOdRA9qBKURlbt1OsXOsPw==", "dev": true, "license": "MIT", "peerDependencies": { @@ -5308,9 +5295,9 @@ } }, "node_modules/pg-protocol": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.8.0.tgz", - "integrity": "sha512-jvuYlEkL03NRvOoyoRktBK7+qU5kOvlAwvmrH8sr3wbLrOdVWsRxQfz8mMy9sZFsqJ1hEWNfdWKI4SAmoL+j7g==", + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.9.5.tgz", + "integrity": "sha512-DYTWtWpfd5FOro3UnAfwvhD8jh59r2ig8bPtc9H8Ds7MscE/9NYruUQWFAOuraRl29jwcT2kyMFQ3MxeaVjUhg==", "dev": true, "license": "MIT" }, @@ -5424,13 +5411,13 @@ } }, "node_modules/playwright": { - "version": "1.51.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.51.1.tgz", - "integrity": "sha512-kkx+MB2KQRkyxjYPc3a0wLZZoDczmppyGJIvQ43l+aZihkaVvmu/21kiyaHeHjiFxjxNNFnUncKmcGIyOojsaw==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.52.0.tgz", + "integrity": "sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.51.1" + "playwright-core": "1.52.0" }, "bin": { "playwright": "cli.js" @@ -5443,9 +5430,9 @@ } }, "node_modules/playwright-core": { - "version": "1.51.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.51.1.tgz", - "integrity": "sha512-/crRMj8+j/Nq5s8QcvegseuyeZPxpQCZb6HNk3Sos3BlZyAknRjoyJPFWkpNn8v0+P3WiwqFF8P+zQo4eqiNuw==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.52.0.tgz", + "integrity": "sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==", "dev": true, "license": "Apache-2.0", "bin": { @@ -5878,9 +5865,9 @@ } }, "node_modules/rollup": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.0.tgz", - "integrity": "sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.1.tgz", + "integrity": "sha512-C5VvvgCCyfyotVITIAv+4efVytl5F7wt+/I2i9q9GZcEXW9BP52YYOXC58igUi+LFZVHukErIIqQSWwv/M3WRw==", "dev": true, "license": "MIT", "dependencies": { @@ -5894,26 +5881,26 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.40.0", - "@rollup/rollup-android-arm64": "4.40.0", - "@rollup/rollup-darwin-arm64": "4.40.0", - "@rollup/rollup-darwin-x64": "4.40.0", - "@rollup/rollup-freebsd-arm64": "4.40.0", - "@rollup/rollup-freebsd-x64": "4.40.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.40.0", - "@rollup/rollup-linux-arm-musleabihf": "4.40.0", - "@rollup/rollup-linux-arm64-gnu": "4.40.0", - "@rollup/rollup-linux-arm64-musl": "4.40.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.40.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.40.0", - "@rollup/rollup-linux-riscv64-gnu": "4.40.0", - "@rollup/rollup-linux-riscv64-musl": "4.40.0", - "@rollup/rollup-linux-s390x-gnu": "4.40.0", - "@rollup/rollup-linux-x64-gnu": "4.40.0", - "@rollup/rollup-linux-x64-musl": "4.40.0", - "@rollup/rollup-win32-arm64-msvc": "4.40.0", - "@rollup/rollup-win32-ia32-msvc": "4.40.0", - "@rollup/rollup-win32-x64-msvc": "4.40.0", + "@rollup/rollup-android-arm-eabi": "4.40.1", + "@rollup/rollup-android-arm64": "4.40.1", + "@rollup/rollup-darwin-arm64": "4.40.1", + "@rollup/rollup-darwin-x64": "4.40.1", + "@rollup/rollup-freebsd-arm64": "4.40.1", + "@rollup/rollup-freebsd-x64": "4.40.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.40.1", + "@rollup/rollup-linux-arm-musleabihf": "4.40.1", + "@rollup/rollup-linux-arm64-gnu": "4.40.1", + "@rollup/rollup-linux-arm64-musl": "4.40.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.40.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.40.1", + "@rollup/rollup-linux-riscv64-gnu": "4.40.1", + "@rollup/rollup-linux-riscv64-musl": "4.40.1", + "@rollup/rollup-linux-s390x-gnu": "4.40.1", + "@rollup/rollup-linux-x64-gnu": "4.40.1", + "@rollup/rollup-linux-x64-musl": "4.40.1", + "@rollup/rollup-win32-arm64-msvc": "4.40.1", + "@rollup/rollup-win32-ia32-msvc": "4.40.1", + "@rollup/rollup-win32-x64-msvc": "4.40.1", "fsevents": "~2.3.2" } }, @@ -6570,6 +6557,51 @@ "dev": true, "license": "MIT" }, + "node_modules/tinyglobby": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", + "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/tinypool": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", @@ -6715,15 +6747,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.30.1.tgz", - "integrity": "sha512-D7lC0kcehVH7Mb26MRQi64LMyRJsj3dToJxM1+JVTl53DQSV5/7oUGWQLcKl1C1KnoVHxMMU2FNQMffr7F3Row==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.31.0.tgz", + "integrity": "sha512-u+93F0sB0An8WEAPtwxVhFby573E8ckdjwUUQUj9QA4v8JAvgtoDdIyYR3XFwFHq2W1KJ1AurwJCO+w+Y1ixyQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.30.1", - "@typescript-eslint/parser": "8.30.1", - "@typescript-eslint/utils": "8.30.1" + "@typescript-eslint/eslint-plugin": "8.31.0", + "@typescript-eslint/parser": "8.31.0", + "@typescript-eslint/utils": "8.31.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6852,15 +6884,18 @@ } }, "node_modules/vite": { - "version": "6.2.6", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.6.tgz", - "integrity": "sha512-9xpjNl3kR4rVDZgPNdTL0/c6ao4km69a/2ihNQbcANz8RuCOK3hQBmLSJf3bRKVQjVMda+YvizNE8AwvogcPbw==", + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.3.tgz", + "integrity": "sha512-5nXH+QsELbFKhsEfWLkHrvgRpTdGJzqOZ+utSdmPTvwHmvU6ITTm3xx+mRusihkcI8GeC7lCDyn3kDtiki9scw==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", "postcss": "^8.5.3", - "rollup": "^4.30.1" + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" }, "bin": { "vite": "bin/vite.js" @@ -6924,9 +6959,9 @@ } }, "node_modules/vite-node": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.1.tgz", - "integrity": "sha512-V+IxPAE2FvXpTCHXyNem0M+gWm6J7eRyWPR6vYoG/Gl+IscNOjXzztUhimQgTxaAoUoj40Qqimaa0NLIOOAH4w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.2.tgz", + "integrity": "sha512-/8iMryv46J3aK13iUXsei5G/A3CUlW4665THCPS+K8xAaqrVWiGB4RfXMQXCLjpK9P2eK//BczrVkn5JLAk6DA==", "dev": true, "license": "MIT", "dependencies": { @@ -6946,6 +6981,21 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/vite/node_modules/fdir": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, "node_modules/vite/node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -6961,32 +7011,46 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/vitest": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.1.tgz", - "integrity": "sha512-kiZc/IYmKICeBAZr9DQ5rT7/6bD9G7uqQEki4fxazi1jdVl2mWGzedtBs5s6llz59yQhVb7FFY2MbHzHCnT79Q==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.2.tgz", + "integrity": "sha512-WaxpJe092ID1C0mr+LH9MmNrhfzi8I65EX/NRU/Ld016KqQNRgxSOlGNP1hHN+a/F8L15Mh8klwaF77zR3GeDQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "3.1.1", - "@vitest/mocker": "3.1.1", - "@vitest/pretty-format": "^3.1.1", - "@vitest/runner": "3.1.1", - "@vitest/snapshot": "3.1.1", - "@vitest/spy": "3.1.1", - "@vitest/utils": "3.1.1", + "@vitest/expect": "3.1.2", + "@vitest/mocker": "3.1.2", + "@vitest/pretty-format": "^3.1.2", + "@vitest/runner": "3.1.2", + "@vitest/snapshot": "3.1.2", + "@vitest/spy": "3.1.2", + "@vitest/utils": "3.1.2", "chai": "^5.2.0", "debug": "^4.4.0", - "expect-type": "^1.2.0", + "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", - "std-env": "^3.8.1", + "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.13", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", - "vite-node": "3.1.1", + "vite-node": "3.1.2", "why-is-node-running": "^2.3.0" }, "bin": { @@ -7002,8 +7066,8 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.1.1", - "@vitest/ui": "3.1.1", + "@vitest/browser": "3.1.2", + "@vitest/ui": "3.1.2", "happy-dom": "*", "jsdom": "*" }, diff --git a/e2e/package.json b/e2e/package.json index f141430c97..c4da9b8a4a 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -1,6 +1,6 @@ { "name": "immich-e2e", - "version": "1.131.3", + "version": "1.132.3", "description": "", "main": "index.js", "type": "module", @@ -25,7 +25,7 @@ "@immich/sdk": "file:../open-api/typescript-sdk", "@playwright/test": "^1.44.1", "@types/luxon": "^3.4.2", - "@types/node": "^22.14.0", + "@types/node": "^22.14.1", "@types/oidc-provider": "^8.5.1", "@types/pg": "^8.11.0", "@types/pngjs": "^6.0.4", diff --git a/e2e/src/api/specs/audit.e2e-spec.ts b/e2e/src/api/specs/audit.e2e-spec.ts deleted file mode 100644 index c6a2adbb0a..0000000000 --- a/e2e/src/api/specs/audit.e2e-spec.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { deleteAssets, getAuditFiles, updateAsset, type LoginResponseDto } from '@immich/sdk'; -import { asBearerAuth, utils } from 'src/utils'; -import { beforeAll, describe, expect, it } from 'vitest'; - -describe('/audits', () => { - let admin: LoginResponseDto; - - beforeAll(async () => { - await utils.resetDatabase(); - await utils.resetFilesystem(); - - admin = await utils.adminSetup(); - }); - - // TODO: Enable these tests again once #7436 is resolved as these were flaky - describe.skip('GET :/file-report', () => { - it('excludes assets without issues from report', async () => { - const [trashedAsset, archivedAsset] = await Promise.all([ - utils.createAsset(admin.accessToken), - utils.createAsset(admin.accessToken), - utils.createAsset(admin.accessToken), - ]); - - await Promise.all([ - deleteAssets({ assetBulkDeleteDto: { ids: [trashedAsset.id] } }, { headers: asBearerAuth(admin.accessToken) }), - updateAsset( - { - id: archivedAsset.id, - updateAssetDto: { isArchived: true }, - }, - { headers: asBearerAuth(admin.accessToken) }, - ), - ]); - - const body = await getAuditFiles({ - headers: asBearerAuth(admin.accessToken), - }); - - expect(body.orphans).toHaveLength(0); - expect(body.extras).toHaveLength(0); - }); - }); -}); diff --git a/e2e/src/api/specs/oauth.e2e-spec.ts b/e2e/src/api/specs/oauth.e2e-spec.ts index 9cd5f0252a..9e4d64892e 100644 --- a/e2e/src/api/specs/oauth.e2e-spec.ts +++ b/e2e/src/api/specs/oauth.e2e-spec.ts @@ -6,6 +6,7 @@ import { startOAuth, updateConfig, } from '@immich/sdk'; +import { createHash, randomBytes } from 'node:crypto'; import { errorDto } from 'src/responses'; import { OAuthClient, OAuthUser } from 'src/setup/auth-server'; import { app, asBearerAuth, baseUrl, utils } from 'src/utils'; @@ -21,18 +22,30 @@ const mobileOverrideRedirectUri = 'https://photos.immich.app/oauth/mobile-redire const redirect = async (url: string, cookies?: string[]) => { const { headers } = await request(url) - .get('/') + .get('') .set('Cookie', cookies || []); return { cookies: (headers['set-cookie'] as unknown as string[]) || [], location: headers.location }; }; +// Function to generate a code challenge from the verifier +const generateCodeChallenge = async (codeVerifier: string): Promise => { + const hashed = createHash('sha256').update(codeVerifier).digest(); + return hashed.toString('base64url'); +}; + const loginWithOAuth = async (sub: OAuthUser | string, redirectUri?: string) => { - const { url } = await startOAuth({ oAuthConfigDto: { redirectUri: redirectUri ?? `${baseUrl}/auth/login` } }); + const state = randomBytes(16).toString('base64url'); + const codeVerifier = randomBytes(64).toString('base64url'); + const codeChallenge = await generateCodeChallenge(codeVerifier); + + const { url } = await startOAuth({ + oAuthConfigDto: { redirectUri: redirectUri ?? `${baseUrl}/auth/login`, state, codeChallenge }, + }); // login const response1 = await redirect(url.replace(authServer.internal, authServer.external)); const response2 = await request(authServer.external + response1.location) - .post('/') + .post('') .set('Cookie', response1.cookies) .type('form') .send({ prompt: 'login', login: sub, password: 'password' }); @@ -40,7 +53,7 @@ const loginWithOAuth = async (sub: OAuthUser | string, redirectUri?: string) => // approve const response3 = await redirect(response2.header.location, response1.cookies); const response4 = await request(authServer.external + response3.location) - .post('/') + .post('') .type('form') .set('Cookie', response3.cookies) .send({ prompt: 'consent' }); @@ -51,9 +64,9 @@ const loginWithOAuth = async (sub: OAuthUser | string, redirectUri?: string) => expect(redirectUrl).toBeDefined(); const params = new URL(redirectUrl).searchParams; expect(params.get('code')).toBeDefined(); - expect(params.get('state')).toBeDefined(); + expect(params.get('state')).toBe(state); - return redirectUrl; + return { url: redirectUrl, state, codeVerifier }; }; const setupOAuth = async (token: string, dto: Partial) => { @@ -119,9 +132,42 @@ describe(`/oauth`, () => { expect(body).toEqual(errorDto.badRequest(['url should not be empty'])); }); - it('should auto register the user by default', async () => { - const url = await loginWithOAuth('oauth-auto-register'); + it(`should throw an error if the state is not provided`, async () => { + const { url } = await loginWithOAuth('oauth-auto-register'); const { status, body } = await request(app).post('/oauth/callback').send({ url }); + expect(status).toBe(400); + expect(body).toEqual(errorDto.badRequest('OAuth state is missing')); + }); + + it(`should throw an error if the state mismatches`, async () => { + const callbackParams = await loginWithOAuth('oauth-auto-register'); + const { state } = await loginWithOAuth('oauth-auto-register'); + const { status } = await request(app) + .post('/oauth/callback') + .send({ ...callbackParams, state }); + expect(status).toBeGreaterThanOrEqual(400); + }); + + it(`should throw an error if the codeVerifier is not provided`, async () => { + const { url, state } = await loginWithOAuth('oauth-auto-register'); + const { status, body } = await request(app).post('/oauth/callback').send({ url, state }); + expect(status).toBe(400); + expect(body).toEqual(errorDto.badRequest('OAuth code verifier is missing')); + }); + + it(`should throw an error if the codeVerifier doesn't match the challenge`, async () => { + const callbackParams = await loginWithOAuth('oauth-auto-register'); + const { codeVerifier } = await loginWithOAuth('oauth-auto-register'); + const { status, body } = await request(app) + .post('/oauth/callback') + .send({ ...callbackParams, codeVerifier }); + console.log(body); + expect(status).toBeGreaterThanOrEqual(400); + }); + + it('should auto register the user by default', async () => { + const callbackParams = await loginWithOAuth('oauth-auto-register'); + const { status, body } = await request(app).post('/oauth/callback').send(callbackParams); expect(status).toBe(201); expect(body).toMatchObject({ accessToken: expect.any(String), @@ -132,16 +178,30 @@ describe(`/oauth`, () => { }); }); + it('should allow passing state and codeVerifier via cookies', async () => { + const { url, state, codeVerifier } = await loginWithOAuth('oauth-auto-register'); + const { status, body } = await request(app) + .post('/oauth/callback') + .set('Cookie', [`immich_oauth_state=${state}`, `immich_oauth_code_verifier=${codeVerifier}`]) + .send({ url }); + expect(status).toBe(201); + expect(body).toMatchObject({ + accessToken: expect.any(String), + userId: expect.any(String), + userEmail: 'oauth-auto-register@immich.app', + }); + }); + it('should handle a user without an email', async () => { - const url = await loginWithOAuth(OAuthUser.NO_EMAIL); - const { status, body } = await request(app).post('/oauth/callback').send({ url }); + const callbackParams = await loginWithOAuth(OAuthUser.NO_EMAIL); + const { status, body } = await request(app).post('/oauth/callback').send(callbackParams); expect(status).toBe(400); expect(body).toEqual(errorDto.badRequest('OAuth profile does not have an email address')); }); it('should set the quota from a claim', async () => { - const url = await loginWithOAuth(OAuthUser.WITH_QUOTA); - const { status, body } = await request(app).post('/oauth/callback').send({ url }); + const callbackParams = await loginWithOAuth(OAuthUser.WITH_QUOTA); + const { status, body } = await request(app).post('/oauth/callback').send(callbackParams); expect(status).toBe(201); expect(body).toMatchObject({ accessToken: expect.any(String), @@ -154,8 +214,8 @@ describe(`/oauth`, () => { }); it('should set the storage label from a claim', async () => { - const url = await loginWithOAuth(OAuthUser.WITH_USERNAME); - const { status, body } = await request(app).post('/oauth/callback').send({ url }); + const callbackParams = await loginWithOAuth(OAuthUser.WITH_USERNAME); + const { status, body } = await request(app).post('/oauth/callback').send(callbackParams); expect(status).toBe(201); expect(body).toMatchObject({ accessToken: expect.any(String), @@ -176,8 +236,8 @@ describe(`/oauth`, () => { buttonText: 'Login with Immich', signingAlgorithm: 'RS256', }); - const url = await loginWithOAuth('oauth-RS256-token'); - const { status, body } = await request(app).post('/oauth/callback').send({ url }); + const callbackParams = await loginWithOAuth('oauth-RS256-token'); + const { status, body } = await request(app).post('/oauth/callback').send(callbackParams); expect(status).toBe(201); expect(body).toMatchObject({ accessToken: expect.any(String), @@ -196,8 +256,8 @@ describe(`/oauth`, () => { buttonText: 'Login with Immich', profileSigningAlgorithm: 'RS256', }); - const url = await loginWithOAuth('oauth-signed-profile'); - const { status, body } = await request(app).post('/oauth/callback').send({ url }); + const callbackParams = await loginWithOAuth('oauth-signed-profile'); + const { status, body } = await request(app).post('/oauth/callback').send(callbackParams); expect(status).toBe(201); expect(body).toMatchObject({ userId: expect.any(String), @@ -213,8 +273,8 @@ describe(`/oauth`, () => { buttonText: 'Login with Immich', signingAlgorithm: 'something-that-does-not-work', }); - const url = await loginWithOAuth('oauth-signed-bad'); - const { status, body } = await request(app).post('/oauth/callback').send({ url }); + const callbackParams = await loginWithOAuth('oauth-signed-bad'); + const { status, body } = await request(app).post('/oauth/callback').send(callbackParams); expect(status).toBe(500); expect(body).toMatchObject({ error: 'Internal Server Error', @@ -235,8 +295,8 @@ describe(`/oauth`, () => { }); it('should not auto register the user', async () => { - const url = await loginWithOAuth('oauth-no-auto-register'); - const { status, body } = await request(app).post('/oauth/callback').send({ url }); + const callbackParams = await loginWithOAuth('oauth-no-auto-register'); + const { status, body } = await request(app).post('/oauth/callback').send(callbackParams); expect(status).toBe(400); expect(body).toEqual(errorDto.badRequest('User does not exist and auto registering is disabled.')); }); @@ -247,8 +307,8 @@ describe(`/oauth`, () => { email: 'oauth-user3@immich.app', password: 'password', }); - const url = await loginWithOAuth('oauth-user3'); - const { status, body } = await request(app).post('/oauth/callback').send({ url }); + const callbackParams = await loginWithOAuth('oauth-user3'); + const { status, body } = await request(app).post('/oauth/callback').send(callbackParams); expect(status).toBe(201); expect(body).toMatchObject({ userId, @@ -286,13 +346,15 @@ describe(`/oauth`, () => { }); it('should auto register the user by default', async () => { - const url = await loginWithOAuth('oauth-mobile-override', 'app.immich:///oauth-callback'); - expect(url).toEqual(expect.stringContaining(mobileOverrideRedirectUri)); + const callbackParams = await loginWithOAuth('oauth-mobile-override', 'app.immich:///oauth-callback'); + expect(callbackParams.url).toEqual(expect.stringContaining(mobileOverrideRedirectUri)); // simulate redirecting back to mobile app - const redirectUri = url.replace(mobileOverrideRedirectUri, 'app.immich:///oauth-callback'); + const url = callbackParams.url.replace(mobileOverrideRedirectUri, 'app.immich:///oauth-callback'); - const { status, body } = await request(app).post('/oauth/callback').send({ url: redirectUri }); + const { status, body } = await request(app) + .post('/oauth/callback') + .send({ ...callbackParams, url }); expect(status).toBe(201); expect(body).toMatchObject({ accessToken: expect.any(String), diff --git a/e2e/src/api/specs/user-admin.e2e-spec.ts b/e2e/src/api/specs/user-admin.e2e-spec.ts index 9299e62b79..1fbee84c3f 100644 --- a/e2e/src/api/specs/user-admin.e2e-spec.ts +++ b/e2e/src/api/specs/user-admin.e2e-spec.ts @@ -215,6 +215,19 @@ describe('/admin/users', () => { const user = await getMyUser({ headers: asBearerAuth(token.accessToken) }); expect(user).toMatchObject({ email: nonAdmin.userEmail }); }); + + it('should update the avatar color', async () => { + const { status, body } = await request(app) + .put(`/admin/users/${admin.userId}`) + .send({ avatarColor: 'orange' }) + .set('Authorization', `Bearer ${admin.accessToken}`); + + expect(status).toBe(200); + expect(body).toMatchObject({ avatarColor: 'orange' }); + + const after = await getUserAdmin({ id: admin.userId }, { headers: asBearerAuth(admin.accessToken) }); + expect(after).toMatchObject({ avatarColor: 'orange' }); + }); }); describe('PUT /admin/users/:id/preferences', () => { @@ -240,19 +253,6 @@ describe('/admin/users', () => { expect(after).toMatchObject({ memories: { enabled: false } }); }); - it('should update the avatar color', async () => { - const { status, body } = await request(app) - .put(`/admin/users/${admin.userId}/preferences`) - .send({ avatar: { color: 'orange' } }) - .set('Authorization', `Bearer ${admin.accessToken}`); - - expect(status).toBe(200); - expect(body).toMatchObject({ avatar: { color: 'orange' } }); - - const after = await getUserPreferencesAdmin({ id: admin.userId }, { headers: asBearerAuth(admin.accessToken) }); - expect(after).toMatchObject({ avatar: { color: 'orange' } }); - }); - it('should update download archive size', async () => { const { status, body } = await request(app) .put(`/admin/users/${admin.userId}/preferences`) diff --git a/e2e/src/api/specs/user.e2e-spec.ts b/e2e/src/api/specs/user.e2e-spec.ts index 54d11e5049..b9eb140c56 100644 --- a/e2e/src/api/specs/user.e2e-spec.ts +++ b/e2e/src/api/specs/user.e2e-spec.ts @@ -139,6 +139,19 @@ describe('/users', () => { profileChangedAt: expect.anything(), }); }); + + it('should update avatar color', async () => { + const { status, body } = await request(app) + .put(`/users/me`) + .send({ avatarColor: 'blue' }) + .set('Authorization', `Bearer ${admin.accessToken}`); + + expect(status).toBe(200); + expect(body).toMatchObject({ avatarColor: 'blue' }); + + const after = await getMyUser({ headers: asBearerAuth(admin.accessToken) }); + expect(after).toMatchObject({ avatarColor: 'blue' }); + }); }); describe('PUT /users/me/preferences', () => { @@ -158,19 +171,6 @@ describe('/users', () => { expect(after).toMatchObject({ memories: { enabled: false } }); }); - it('should update avatar color', async () => { - const { status, body } = await request(app) - .put(`/users/me/preferences`) - .send({ avatar: { color: 'blue' } }) - .set('Authorization', `Bearer ${admin.accessToken}`); - - expect(status).toBe(200); - expect(body).toMatchObject({ avatar: { color: 'blue' } }); - - const after = await getMyPreferences({ headers: asBearerAuth(admin.accessToken) }); - expect(after).toMatchObject({ avatar: { color: 'blue' } }); - }); - it('should require an integer for download archive size', async () => { const { status, body } = await request(app) .put(`/users/me/preferences`) diff --git a/e2e/src/web/specs/auth.e2e-spec.ts b/e2e/src/web/specs/auth.e2e-spec.ts index e89f17a4e9..74bee64e0a 100644 --- a/e2e/src/web/specs/auth.e2e-spec.ts +++ b/e2e/src/web/specs/auth.e2e-spec.ts @@ -25,7 +25,7 @@ test.describe('Registration', () => { // login await expect(page).toHaveTitle(/Login/); - await page.goto('/auth/login'); + await page.goto('/auth/login?autoLaunch=0'); await page.getByLabel('Email').fill('admin@immich.app'); await page.getByLabel('Password').fill('password'); await page.getByRole('button', { name: 'Login' }).click(); @@ -59,7 +59,7 @@ test.describe('Registration', () => { await context.clearCookies(); // login - await page.goto('/auth/login'); + await page.goto('/auth/login?autoLaunch=0'); await page.getByLabel('Email').fill('user@immich.cloud'); await page.getByLabel('Password').fill('password'); await page.getByRole('button', { name: 'Login' }).click(); @@ -72,7 +72,7 @@ test.describe('Registration', () => { await page.getByRole('button', { name: 'Change password' }).click(); // login with new password - await expect(page).toHaveURL('/auth/login'); + await expect(page).toHaveURL('/auth/login?autoLaunch=0'); await page.getByLabel('Email').fill('user@immich.cloud'); await page.getByLabel('Password').fill('new-password'); await page.getByRole('button', { name: 'Login' }).click(); diff --git a/e2e/src/web/specs/photo-viewer.e2e-spec.ts b/e2e/src/web/specs/photo-viewer.e2e-spec.ts index 4871e7522c..c8a9b42b2a 100644 --- a/e2e/src/web/specs/photo-viewer.e2e-spec.ts +++ b/e2e/src/web/specs/photo-viewer.e2e-spec.ts @@ -21,23 +21,9 @@ test.describe('Photo Viewer', () => { test.beforeEach(async ({ context, page }) => { // before each test, login as user await utils.setAuthCookies(context, admin.accessToken); - await page.goto('/photos'); await page.waitForLoadState('networkidle'); }); - test('initially shows a loading spinner', async ({ page }) => { - await page.route(`/api/assets/${asset.id}/thumbnail**`, async (route) => { - // slow down the request for thumbnail, so spinner has chance to show up - await new Promise((f) => setTimeout(f, 2000)); - await route.continue(); - }); - await page.goto(`/photos/${asset.id}`); - await page.waitForLoadState('load'); - // this is the spinner - await page.waitForSelector('svg[role=status]'); - await expect(page.getByTestId('loading-spinner')).toBeVisible(); - }); - test('loads original photo when zoomed', async ({ page }) => { await page.goto(`/photos/${asset.id}`); await expect.poll(async () => await imageLocator(page).getAttribute('src')).toContain('thumbnail'); diff --git a/e2e/src/web/specs/shared-link.e2e-spec.ts b/e2e/src/web/specs/shared-link.e2e-spec.ts index 562a0b4e8c..aeddb86322 100644 --- a/e2e/src/web/specs/shared-link.e2e-spec.ts +++ b/e2e/src/web/specs/shared-link.e2e-spec.ts @@ -55,7 +55,6 @@ test.describe('Shared Links', () => { await page.goto(`/share/${sharedLink.key}`); await page.getByRole('heading', { name: 'Test Album' }).waitFor(); await page.getByRole('button', { name: 'Download' }).click(); - await page.getByText('DOWNLOADING', { exact: true }).waitFor(); await page.waitForEvent('download'); }); diff --git a/i18n/be.json b/i18n/be.json index 8377ec5383..eea566df6a 100644 --- a/i18n/be.json +++ b/i18n/be.json @@ -4,6 +4,7 @@ "account_settings": "НаĐģĐ°Đ´Ņ‹ ŅžĐģŅ–ĐēĐžĐ˛Đ°ĐŗĐ° СаĐŋŅ–ŅŅƒ", "acknowledge": "ĐŸĐ°Ņ†Đ˛ĐĩŅ€Đ´ĐˇŅ–Ņ†ŅŒ", "action": "ДзĐĩŅĐŊĐŊĐĩ", + "action_common_update": "АйĐŊĐ°Đ˛Ņ–Ņ†ŅŒ", "actions": "ДзĐĩŅĐŊĐŊŅ–", "active": "АĐēŅ‚Ņ‹ŅžĐŊŅ‹", "activity": "АĐēŅ‚Ņ‹ŅžĐŊĐ°ŅŅ†ŅŒ", @@ -20,8 +21,10 @@ "add_partner": "Đ”Đ°Đ´Đ°Ņ†ŅŒ ĐŋĐ°Ņ€Ņ‚ĐŊŅ‘Ņ€Đ°", "add_path": "Đ”Đ°Đ´Đ°Ņ†ŅŒ ҈ĐģŅŅ…", "add_photos": "Đ”Đ°Đ´Đ°Ņ†ŅŒ Ņ„ĐžŅ‚Đ°", - "add_to": "Đ”Đ°Đ´Đ°Ņ†ŅŒ ҃...", + "add_to": "Đ”Đ°Đ´Đ°Ņ†ŅŒ ҃â€Ļ", "add_to_album": "Đ”Đ°Đ´Đ°Ņ†ŅŒ ҃ аĐģŅŒĐąĐžĐŧ", + "add_to_album_bottom_sheet_added": "ДададзĐĩĐŊа да {album}", + "add_to_album_bottom_sheet_already_exists": "ĐŖĐļĐž СĐŊĐ°Ņ…ĐžĐ´ĐˇŅ–Ņ†Ņ†Đ° Ņž {album}", "add_to_shared_album": "Đ”Đ°Đ´Đ°Ņ†ŅŒ ҃ Đ°ĐŗŅƒĐģҌĐŊŅ‹ аĐģŅŒĐąĐžĐŧ", "add_url": "Đ”Đ°Đ´Đ°Ņ†ŅŒ URL", "added_to_archive": "ДададзĐĩĐŊа Ņž Đ°Ņ€Ņ…Ņ–Ņž", @@ -41,6 +44,7 @@ "backup_settings": "НаĐģĐ°Đ´Ņ‹ Ņ€ŅĐˇĐĩŅ€Đ˛ĐžĐ˛Đ°ĐŗĐ° ĐēаĐŋŅ–ŅĐ˛Đ°ĐŊĐŊŅ", "backup_settings_description": "ĐšŅ–Ņ€Đ°Đ˛Đ°ĐŊĐŊĐĩ ĐŊаĐģадĐēаĐŧŅ– Ņ€ŅĐˇĐĩŅ€Đ˛ĐžĐ˛Đ°ĐŗĐ° ĐēаĐŋŅ–ŅĐ˛Đ°ĐŊĐŊŅ ĐąĐ°ĐˇŅ‹ даĐŊҋ҅", "check_all": "ĐŸŅ€Đ°Đ˛ĐĩŅ€Ņ‹Ņ†ŅŒ ҃ҁĐĩ", + "cleanup": "ĐŅ‡Ņ‹ŅŅ‚Đēа", "cleared_jobs": "ĐŅ‡Ņ‹ŅˆŅ‡Đ°ĐŊŅ‹ СадаĐŊĐŊŅ– Đ´ĐģŅ: {job}", "config_set_by_file": "КаĐŊŅ„Ņ–ĐŗŅƒŅ€Đ°Ņ†Ņ‹Ņ Ņž ĐˇĐ°Ņ€Đ°Đˇ ŅƒŅŅ‚Đ°ĐģŅĐ˛Đ°ĐŊа ĐŋŅ€Đ°Đˇ Ņ„Đ°ĐšĐģ ĐēаĐŊŅ„Ņ–ĐŗŅƒŅ€Đ°Ņ†Ņ‹Ņ–", "confirm_delete_library": "Đ’Ņ‹ ŅžĐŋŅŅžĐŊĐĩĐŊŅ‹ ŅˆŅ‚Đž ĐļадаĐĩ҆Đĩ Đ˛Ņ‹Đ´Đ°ĐģŅ–Ņ†ŅŒ {library} ĐąŅ–ĐąĐģŅ–ŅŅ‚ŅĐē҃?", diff --git a/i18n/ca.json b/i18n/ca.json index 52a47a83d5..c2482f3ddd 100644 --- a/i18n/ca.json +++ b/i18n/ca.json @@ -533,7 +533,7 @@ "backup_controller_page_backup_sub": "Fotografies i vídeos copiats", "backup_controller_page_created": "Creat el: {}", "backup_controller_page_desc_backup": "Activeu la cÃ˛pia de seguretat per pujar automàticament els nous elements al servidor en obrir l'aplicaciÃŗ.", - "backup_controller_page_excluded": "Exclosos:", + "backup_controller_page_excluded": "Exclosos: ", "backup_controller_page_failed": "Fallats ({})", "backup_controller_page_filename": "Nom de l'arxiu: {} [{}]", "backup_controller_page_id": "ID: {}", diff --git a/i18n/cs.json b/i18n/cs.json index f3373f06a1..46cde0affd 100644 --- a/i18n/cs.json +++ b/i18n/cs.json @@ -39,11 +39,11 @@ "authentication_settings_disable_all": "Opravdu chcete zakÃĄzat vÅĄechny metody přihlÃĄÅĄení? PřihlaÅĄovÃĄní bude Ãēplně zakÃĄzÃĄno.", "authentication_settings_reenable": "Pro opětovnÊ povolení pouÅžijte příkaz Příkaz serveru.", "background_task_job": "Úkoly na pozadí", - "backup_database": "ZÃĄlohovÃĄní databÃĄze", - "backup_database_enable_description": "Povolit zÃĄlohovÃĄní databÃĄze", - "backup_keep_last_amount": "Počet předchozích zÃĄloh k uchovÃĄní", - "backup_settings": "Nastavení zÃĄlohovÃĄní", - "backup_settings_description": "SprÃĄva nastavení zÃĄlohovÃĄní databÃĄze", + "backup_database": "Vytvořit vÃŊpis databÃĄze", + "backup_database_enable_description": "Povolit vÃŊpisy z databÃĄze", + "backup_keep_last_amount": "Počet předchozích vÃŊpisů, kterÊ se mají ponechat", + "backup_settings": "Nastavení vÃŊpisu databÃĄze", + "backup_settings_description": "SprÃĄva nastavení vÃŊpisu databÃĄze. PoznÃĄmka: Tyto Ãēlohy nejsou monitorovÃĄny a nebudete upozorněni na jejich selhÃĄní.", "check_all": "VÅĄe zkontrolovat", "cleanup": "VyčiÅĄtění", "cleared_jobs": "HotovÊ Ãēlohy pro: {job}", @@ -371,6 +371,8 @@ "admin_password": "Heslo sprÃĄvce", "administration": "Administrace", "advanced": "PokročilÊ", + "advanced_settings_enable_alternate_media_filter_subtitle": "Tuto moÅžnost pouÅžijte k filtrovÃĄní mÊdií během synchronizace na zÃĄkladě alternativních kritÊrií. Tuto moÅžnost vyzkouÅĄejte pouze v případě, Åže mÃĄte problÊmy s detekcí vÅĄech alb v aplikaci.", + "advanced_settings_enable_alternate_media_filter_title": "[EXPERIMENTÁLNÍ] PouŞít alternativní filtr pro synchronizaci alb zařízení", "advanced_settings_log_level_title": "Úroveň protokolovÃĄní: {}", "advanced_settings_prefer_remote_subtitle": "U některÃŊch zařízení je načítÃĄní miniatur z prostředků v zařízení velmi pomalÊ. Aktivujte toto nastavení, aby se místo toho načítaly vzdÃĄlenÊ obrÃĄzky.", "advanced_settings_prefer_remote_title": "Preferovat vzdÃĄlenÊ obrÃĄzky", @@ -378,6 +380,8 @@ "advanced_settings_proxy_headers_title": "Proxy hlavičky", "advanced_settings_self_signed_ssl_subtitle": "VynechÃĄ ověření SSL certifikÃĄtu serveru. VyÅžadovÃĄno pro self-signed certifikÃĄty.", "advanced_settings_self_signed_ssl_title": "Povolit self-signed SSL certifikÃĄty", + "advanced_settings_sync_remote_deletions_subtitle": "Automaticky odstranit nebo obnovit poloÅžku v tomto zařízení, kdyÅž je tato akce provedena na webu", + "advanced_settings_sync_remote_deletions_title": "Synchronizace vzdÃĄlenÊho mazÃĄní [EXPERIMENTÁLNÍ]", "advanced_settings_tile_subtitle": "PokročilÊ uÅživatelskÊ nastavení", "advanced_settings_troubleshooting_subtitle": "Zobrazit dodatečnÊ vlastnosti pro řeÅĄení problÊmů", "advanced_settings_troubleshooting_title": "ŘeÅĄení problÊmů", @@ -410,7 +414,7 @@ "album_viewer_appbar_delete_confirm": "Opravdu chcete toto album odstranit ze svÊho Ãēčtu?", "album_viewer_appbar_share_err_delete": "Nepodařilo se smazat album", "album_viewer_appbar_share_err_leave": "Nepodařilo se opustit album", - "album_viewer_appbar_share_err_remove": "Při odstraňovÃĄní poloÅžek z alba se vyskytly problÊmy.", + "album_viewer_appbar_share_err_remove": "Při odstraňovÃĄní poloÅžek z alba se vyskytly problÊmy", "album_viewer_appbar_share_err_title": "Nepodařilo se změnit nÃĄzev alba", "album_viewer_appbar_share_leave": "Opustit album", "album_viewer_appbar_share_to": "Sdílet na", @@ -504,16 +508,16 @@ "backup_album_selection_page_selection_info": "Informace o vÃŊběru", "backup_album_selection_page_total_assets": "CelkovÃŊ počet jedinečnÃŊch poloÅžek", "backup_all": "VÅĄe", - "backup_background_service_backup_failed_message": "ZÃĄlohovÃĄní mÊdií selhalo. ZkouÅĄÃ­m to znovu...", - "backup_background_service_connection_failed_message": "Nepodařilo se připojit k serveru. ZkouÅĄÃ­m to znovu...", + "backup_background_service_backup_failed_message": "ZÃĄlohovÃĄní mÊdií selhalo. ZkouÅĄÃ­m to znovuâ€Ļ", + "backup_background_service_connection_failed_message": "Nepodařilo se připojit k serveru. ZkouÅĄÃ­m to znovuâ€Ļ", "backup_background_service_current_upload_notification": "NahrÃĄvÃĄní {}", "backup_background_service_default_notification": "Kontrola novÃŊch mÊdiíâ€Ļ", "backup_background_service_error_title": "Chyba zÃĄlohovÃĄní", - "backup_background_service_in_progress_notification": "ZÃĄlohovÃĄní vaÅĄich mÊdií...", + "backup_background_service_in_progress_notification": "ZÃĄlohovÃĄní vaÅĄich mÊdiíâ€Ļ", "backup_background_service_upload_failure_notification": "Nepodařilo se nahrÃĄt {}", "backup_controller_page_albums": "ZÃĄlohovanÃĄ alba", "backup_controller_page_background_app_refresh_disabled_content": "Povolte obnovení aplikace na pozadí v Nastavení > ObecnÊ > Obnovení aplikace na pozadí, abyste mohli pouŞívat zÃĄlohovÃĄní na pozadí.", - "backup_controller_page_background_app_refresh_disabled_title": " ObnovovÃĄní aplikací na pozadí je vypnutÊ", + "backup_controller_page_background_app_refresh_disabled_title": "ObnovovÃĄní aplikací na pozadí je vypnutÊ", "backup_controller_page_background_app_refresh_enable_button_text": "Přejít do nastavení", "backup_controller_page_background_battery_info_link": "UkaÅž mi jak", "backup_controller_page_background_battery_info_message": "Chcete-li dosÃĄhnout nejlepÅĄÃ­ch vÃŊsledků při zÃĄlohovÃĄní na pozadí, vypněte vÅĄechny optimalizace baterie, kterÊ omezují aktivitu na pozadí pro Immich ve vaÅĄem zařízení. \n\nJelikoÅž je to zÃĄvislÊ na typu zařízení, vyhledejte poÅžadovanÊ informace pro vÃŊrobce vaÅĄeho zařízení.", @@ -721,7 +725,7 @@ "delete_dialog_alert": "Tyto poloÅžky budou trvale smazÃĄny z aplikace Immich i z vaÅĄeho zařízení", "delete_dialog_alert_local": "Tyto poloÅžky budou z vaÅĄeho zařízení trvale smazÃĄny, ale budou stÃĄle k dispozici na Immich serveru", "delete_dialog_alert_local_non_backed_up": "NěkterÊ poloÅžky nejsou zÃĄlohovÃĄny na Immich server a budou ze zařízení trvale smazÃĄny", - "delete_dialog_alert_remote": "Tyto poloÅžky budou trvale smazÃĄny z Immich serveru ", + "delete_dialog_alert_remote": "Tyto poloÅžky budou trvale smazÃĄny z Immich serveru", "delete_dialog_ok_force": "Přesto smazat", "delete_dialog_title": "Smazat trvale", "delete_duplicates_confirmation": "Opravdu chcete tyto duplicity trvale odstranit?", @@ -992,6 +996,7 @@ "filetype": "Typ souboru", "filter": "Filtr", "filter_people": "Filtrovat lidi", + "filter_places": "Filtrovat místa", "find_them_fast": "Najděte je rychle vyhledÃĄním jejich jmÊna", "fix_incorrect_match": "Opravit nesprÃĄvnou shodu", "folder": "SloÅžka", @@ -1040,7 +1045,7 @@ "home_page_delete_remote_err_local": "Místní poloÅžky ve vzdÃĄlenÊm vÃŊběru pro smazÃĄní, přeskakuji", "home_page_favorite_err_local": "Zatím není moÅžnÊ zařadit lokÃĄlní mÊdia mezi oblíbenÃĄ, přeskakuji", "home_page_favorite_err_partner": "PoloÅžky partnera nelze označit jako oblíbenÊ, přeskakuji", - "home_page_first_time_notice": "Pokud aplikaci pouŞívÃĄte poprvÊ, nezapomeňte si vybrat zÃĄlohovanÃĄ alba, aby se na časovÊ ose mohly nachÃĄzet fotografie a videa z vybranÃŊch alb.", + "home_page_first_time_notice": "Pokud aplikaci pouŞívÃĄte poprvÊ, nezapomeňte si vybrat zÃĄlohovanÃĄ alba, aby se na časovÊ ose mohly nachÃĄzet fotografie a videa z vybranÃŊch alb", "home_page_share_err_local": "Nelze sdílet místní poloÅžky prostřednictvím odkazu, přeskakuji", "home_page_upload_err_limit": "Lze nahrÃĄt nejvÃŊÅĄe 30 poloÅžek najednou, přeskakuji", "host": "Hostitel", @@ -1144,7 +1149,7 @@ "login_form_err_trailing_whitespace": "KoncovÃĄ mezera", "login_form_failed_get_oauth_server_config": "Chyba přihlÃĄÅĄení pomocí OAuth, zkontrolujte adresu URL serveru", "login_form_failed_get_oauth_server_disable": "Funkce OAuth není na tomto serveru dostupnÃĄ", - "login_form_failed_login": "Chyba přihlÃĄÅĄení, zkontrolujte URL adresu serveru, e-mail a heslo.", + "login_form_failed_login": "Chyba přihlÃĄÅĄení, zkontrolujte URL adresu serveru, e-mail a heslo", "login_form_handshake_exception": "DoÅĄlo k vÃŊjimce Handshake se serverem. Pokud pouŞívÃĄte self-signed certifikÃĄt, povolte v nastavení podporu self-signed certifikÃĄtu.", "login_form_password_hint": "heslo", "login_form_save_login": "Zůstat přihlÃĄÅĄen", @@ -1282,6 +1287,7 @@ "onboarding_welcome_user": "Vítej, {user}", "online": "Online", "only_favorites": "Pouze oblíbenÊ", + "open": "Otevřít", "open_in_map_view": "Otevřít v zobrazení mapy", "open_in_openstreetmap": "Otevřít v OpenStreetMap", "open_the_search_filters": "Otevřít vyhledÃĄvací filtry", @@ -1759,7 +1765,7 @@ "theme_setting_system_primary_color_title": "PouÅžití systÊmovÊ barvy", "theme_setting_system_theme_switch": "Automaticky (podle systemovÊho nastavení)", "theme_setting_theme_subtitle": "Vyberte nastavení tÊmatu aplikace", - "theme_setting_three_stage_loading_subtitle": "TřístupňovÊ načítÃĄní můŞe zvÃŊÅĄit vÃŊkonnost načítÃĄní, ale vede k vÃŊrazně vyÅĄÅĄÃ­mu zatíŞení sítě.", + "theme_setting_three_stage_loading_subtitle": "TřístupňovÊ načítÃĄní můŞe zvÃŊÅĄit vÃŊkonnost načítÃĄní, ale vede k vÃŊrazně vyÅĄÅĄÃ­mu zatíŞení sítě", "theme_setting_three_stage_loading_title": "Povolení třístupňovÊho načítÃĄní", "they_will_be_merged_together": "Budou sloučeny dohromady", "third_party_resources": "Zdroje třetích stran", diff --git a/i18n/da.json b/i18n/da.json index 086b97f15a..a9aaef523c 100644 --- a/i18n/da.json +++ b/i18n/da.json @@ -70,8 +70,10 @@ "forcing_refresh_library_files": "Tvinger genopfriskning af alle biblioteksfiler", "image_format": "Format", "image_format_description": "WebP producerer mindre filer end JPEG, men er langsommere at komprimere.", + "image_fullsize_description": "Fuld størrelses billede uden metadata, brugt nÃĨr zoomet ind", + "image_fullsize_enabled": "Aktiver fuld størrelses billede generering", "image_prefer_embedded_preview": "ForetrÃĻk indlejret forhÃĨndsvisning", - "image_prefer_embedded_preview_setting_description": "Brug indlejrede forhÃĨndsvisninger i RAW fotos som input til billedbehandling, nÃĨr det er tilgÃĻngeligt. Dette kan give mere nøjagtige farver for nogle billeder, men kvaliteten af forhÃĨndsvisningen er kameraafhÃĻngig, og billedet kan have flere komprimeringsartefakter.", + "image_prefer_embedded_preview_setting_description": "Brug indlejrede forhÃĨndsvisninger i RAW fotos som input til billedbehandling og nÃĨr det er tilgÃĻngeligt. Dette kan give mere nøjagtige farver for nogle billeder, men kvaliteten af forhÃĨndsvisningen er kameraafhÃĻngig, og billedet kan have flere komprimeringsartefakter.", "image_prefer_wide_gamut": "ForetrÃĻkker bred farveskala", "image_prefer_wide_gamut_setting_description": "Brug Display P3 til miniaturebilleder. Dette bevarer billeder med brede farveskalaers dynamik bedre, men billeder kan komme til at se anderledes ud pÃĨ gamle enheder med en gammel browserversion. sRGB-billeder bliver beholdt som sRGB for at undgÃĨ farveskift.", "image_preview_description": "Mellemstørrelse billede med fjernet metadata, der bruges, nÃĨr du ser en enkelt mediefil og til machine learning", @@ -366,6 +368,7 @@ "admin_password": "Administratoradgangskode", "administration": "Administration", "advanced": "Avanceret", + "advanced_settings_enable_alternate_media_filter_subtitle": "Brug denne valgmulighed for at filtrere media under synkronisering baseret pÃĨ alternative kriterier. Prøv kun denne hvis du har problemer med at appen ikke opdager alle albums.", "advanced_settings_log_level_title": "Logniveau: {}", "advanced_settings_prefer_remote_subtitle": "Nogle enheder tager meget lang tid om at indlÃĻse miniaturebilleder af elementer pÃĨ enheden. Aktiver denne indstilling for i stedetat indlÃĻse elementer fra serveren.", "advanced_settings_prefer_remote_title": "ForetrÃĻk elementer pÃĨ serveren", diff --git a/i18n/de.json b/i18n/de.json index bc4bc28575..b0649474fd 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -39,11 +39,11 @@ "authentication_settings_disable_all": "Bist du sicher, dass du alle Anmeldemethoden deaktivieren willst? Die Anmeldung wird vollständig deaktiviert.", "authentication_settings_reenable": "Nutze einen Server-Befehl zur Reaktivierung.", "background_task_job": "Hintergrundaufgaben", - "backup_database": "Datenbank sichern", - "backup_database_enable_description": "Sicherung der Datenbank aktivieren", - "backup_keep_last_amount": "Anzahl der aufzubewahrenden frÃŧheren Sicherungen", - "backup_settings": "Datensicherungs-Einstellungen", - "backup_settings_description": "Datensicherungs-Einstellungen verwalten", + "backup_database": "Datenbankabbild erstellen", + "backup_database_enable_description": "Erstellen von Datenbankabbildern aktivieren", + "backup_keep_last_amount": "Anzahl der aufzubewahrenden frÃŧheren Abbilder", + "backup_settings": "Datenbankabbild-Einstellungen", + "backup_settings_description": "Einstellungen zum Datenbankabbild verwalten. Hinweis: Diese Jobs werden nicht Ãŧberwacht und du wirst nicht Ãŧber Fehlschläge informiert.", "check_all": "Alle ÃŧberprÃŧfen", "cleanup": "Aufräumen", "cleared_jobs": "Folgende Aufgaben zurÃŧckgesetzt: {job}", @@ -371,13 +371,17 @@ "admin_password": "Administrator Passwort", "administration": "Verwaltung", "advanced": "Erweitert", - "advanced_settings_log_level_title": "Log-Level: {}", + "advanced_settings_enable_alternate_media_filter_subtitle": "Verwende diese Option, um Medien während der Synchronisierung nach anderen Kriterien zu filtern. Versuchen dies nur, wenn Probleme mit der Erkennung aller Alben durch die App auftreten.", + "advanced_settings_enable_alternate_media_filter_title": "[EXPERIMENTELL] Benutze alternativen Filter fÃŧr Synchronisierung der Gerätealben", + "advanced_settings_log_level_title": "Log-Level: {name}", "advanced_settings_prefer_remote_subtitle": "Einige Geräte sind sehr langsam beim Laden von Miniaturbildern direkt aus dem Gerät. Aktivieren Sie diese Einstellung, um stattdessen die Server-Bilder zu laden.", "advanced_settings_prefer_remote_title": "Server-Bilder bevorzugen", "advanced_settings_proxy_headers_subtitle": "Definiere einen Proxy-Header, den Immich bei jeder Netzwerkanfrage mitschicken soll", "advanced_settings_proxy_headers_title": "Proxy-Headers", "advanced_settings_self_signed_ssl_subtitle": "Verifizierung von SSL-Zertifikaten vom Server Ãŧberspringen. Notwendig bei selbstsignierten Zertifikaten.", "advanced_settings_self_signed_ssl_title": "Selbstsignierte SSL-Zertifikate erlauben", + "advanced_settings_sync_remote_deletions_subtitle": "Automatisches LÃļschen oder Wiederherstellen einer Datei auf diesem Gerät, wenn diese Aktion im Web durchgefÃŧhrt wird", + "advanced_settings_sync_remote_deletions_title": "Synchrone Remote-LÃļschungen [Experimentell]", "advanced_settings_tile_subtitle": "Erweiterte Benutzereinstellungen", "advanced_settings_troubleshooting_subtitle": "Erweiterte Funktionen zur Fehlersuche aktivieren", "advanced_settings_troubleshooting_title": "Fehlersuche", @@ -447,8 +451,8 @@ "archived_count": "{count, plural, other {# archiviert}}", "are_these_the_same_person": "Ist das dieselbe Person?", "are_you_sure_to_do_this": "Bist du sicher, dass du das tun willst?", - "asset_action_delete_err_read_only": "SchreibgeschÃŧtzte Inhalte kÃļnnen nicht gelÃļscht werden, Ãŧberspringen...", - "asset_action_share_err_offline": "Die Offline-Inhalte konnten nicht gelesen werden, Ãŧberspringen...", + "asset_action_delete_err_read_only": "SchreibgeschÃŧtzte Inhalte kÃļnnen nicht gelÃļscht werden, Ãŧberspringen", + "asset_action_share_err_offline": "Die Offline-Inhalte konnten nicht gelesen werden, Ãŧberspringen", "asset_added_to_album": "Zum Album hinzugefÃŧgt", "asset_adding_to_album": "HinzufÃŧgen zum Albumâ€Ļ", "asset_description_updated": "Die Beschreibung der Datei wurde aktualisiert", @@ -491,29 +495,29 @@ "assets_trashed_from_server": "{} Datei/en vom Immich-Server gelÃļscht", "assets_were_part_of_album_count": "{count, plural, one {# Datei ist} other {# Dateien sind}} bereits im Album vorhanden", "authorized_devices": "Verwendete Geräte", - "automatic_endpoint_switching_subtitle": "Verbinden Sie sich lokal Ãŧber ein bestimmtes WLAN, wenn es verfÃŧgbar ist, und verwenden Sie andere VerbindungsmÃļglichkeiten anderswo.", + "automatic_endpoint_switching_subtitle": "Verbinden Sie sich lokal Ãŧber ein bestimmtes WLAN, wenn es verfÃŧgbar ist, und verwenden Sie andere VerbindungsmÃļglichkeiten anderswo", "automatic_endpoint_switching_title": "Automatische URL-Umschaltung", "back": "ZurÃŧck", "back_close_deselect": "ZurÃŧck, Schließen oder Abwählen", "background_location_permission": "Hintergrund Standortfreigabe", "background_location_permission_content": "Um im Hintergrund zwischen den Netzwerken wechseln zu kÃļnnen, muss Immich *immer* Zugriff auf den genauen Standort haben, damit die App den Namen des WLAN-Netzwerks ermitteln kann", "backup_album_selection_page_albums_device": "Alben auf dem Gerät ({})", - "backup_album_selection_page_albums_tap": "Einmalig das Album antippen um es zu sichern, doppelt antippen um es nicht mehr zu sichern.", + "backup_album_selection_page_albums_tap": "Einmalig das Album antippen um es zu sichern, doppelt antippen um es nicht mehr zu sichern", "backup_album_selection_page_assets_scatter": "Elemente (Fotos / Videos) kÃļnnen sich Ãŧber mehrere Alben verteilen. Daher kÃļnnen diese vor der Sicherung eingeschlossen oder ausgeschlossen werden.", "backup_album_selection_page_select_albums": "Alben auswählen", "backup_album_selection_page_selection_info": "Information", "backup_album_selection_page_total_assets": "Elemente", "backup_all": "Alle", - "backup_background_service_backup_failed_message": "Es trat ein Fehler bei der Sicherung auf. Erneuter Versuch...", - "backup_background_service_connection_failed_message": "Es konnte keine Verbindung zum Server hergestellt werden. Erneuter Versuch...", + "backup_background_service_backup_failed_message": "Es trat ein Fehler bei der Sicherung auf. Erneuter Versuchâ€Ļ", + "backup_background_service_connection_failed_message": "Es konnte keine Verbindung zum Server hergestellt werden. Erneuter Versuchâ€Ļ", "backup_background_service_current_upload_notification": "Lädt {} hoch", "backup_background_service_default_notification": "Suche nach neuen Elementenâ€Ļ", "backup_background_service_error_title": "Fehler bei der Sicherung", - "backup_background_service_in_progress_notification": "Elemente werden gesichert...", + "backup_background_service_in_progress_notification": "Elemente werden gesichertâ€Ļ", "backup_background_service_upload_failure_notification": "Konnte {} nicht hochladen", "backup_controller_page_albums": "Gesicherte Alben", - "backup_controller_page_background_app_refresh_disabled_content": "Aktiviere Hintergrundaktualisierungen in Einstellungen -> Allgemein -> Hintergrundaktualisierungen um Sicherungen im Hintergrund zu ermÃļglichen. ", - "backup_controller_page_background_app_refresh_disabled_title": "Hintergrundaktualisierungen sind deaktiviert.", + "backup_controller_page_background_app_refresh_disabled_content": "Aktiviere Hintergrundaktualisierungen in Einstellungen -> Allgemein -> Hintergrundaktualisierungen um Sicherungen im Hintergrund zu ermÃļglichen.", + "backup_controller_page_background_app_refresh_disabled_title": "Hintergrundaktualisierungen sind deaktiviert", "backup_controller_page_background_app_refresh_enable_button_text": "Gehe zu Einstellungen", "backup_controller_page_background_battery_info_link": "Zeige mir wie", "backup_controller_page_background_battery_info_message": "FÃŧr die besten Ergebnisse fÃŧr Sicherungen im Hintergrund, deaktiviere alle Batterieoptimierungen und Einschränkungen fÃŧr die Hintergrundaktivitäten von Immich.\n\nDa dies gerätespezifisch ist, schlage diese Informationen fÃŧr deinen Gerätehersteller nach.", @@ -554,7 +558,7 @@ "backup_err_only_album": "Das einzige Album kann nicht entfernt werden", "backup_info_card_assets": "Elemente", "backup_manual_cancelled": "Abgebrochen", - "backup_manual_in_progress": "Sicherung läuft bereits. Bitte versuche es später erneut.", + "backup_manual_in_progress": "Sicherung läuft bereits. Bitte versuche es später erneut", "backup_manual_success": "Erfolgreich", "backup_manual_title": "Sicherungsstatus", "backup_options_page_title": "Sicherungsoptionen", @@ -630,8 +634,8 @@ "client_cert_import_success_msg": "Client Zertifikat wurde importiert", "client_cert_invalid_msg": "UngÃŧltige Zertifikatsdatei oder falsches Passwort", "client_cert_remove_msg": "Client Zertifikat wurde entfernt", - "client_cert_subtitle": "UnterstÃŧtzt nur das PKCS12 (.p12, .pfx) Format. Zertifikatsimporte oder -entfernungen sind nur vor dem Login mÃļglich.", - "client_cert_title": "SSL-Client-Zertifikat ", + "client_cert_subtitle": "UnterstÃŧtzt nur das PKCS12 (.p12, .pfx) Format. Zertifikatsimporte oder -entfernungen sind nur vor dem Login mÃļglich", + "client_cert_title": "SSL-Client-Zertifikat", "clockwise": "Im Uhrzeigersinn", "close": "Schließen", "collapse": "Zusammenklappen", @@ -644,7 +648,7 @@ "comments_are_disabled": "Kommentare sind deaktiviert", "common_create_new_album": "Neues Album erstellen", "common_server_error": "Bitte ÃŧberprÃŧfe Deine Netzwerkverbindung und stelle sicher, dass die App und Server Versionen kompatibel sind.", - "completed": "Fertig\n", + "completed": "Fertig", "confirm": "Bestätigen", "confirm_admin_password": "Administrator Passwort bestätigen", "confirm_delete_face": "Bist du sicher dass du das Gesicht von {name} aus der Datei entfernen willst?", @@ -719,9 +723,9 @@ "delete_album": "Album lÃļschen", "delete_api_key_prompt": "Bist du sicher, dass du diesen API-SchlÃŧssel lÃļschen willst?", "delete_dialog_alert": "Diese Elemente werden unwiderruflich von Immich und dem Gerät entfernt", - "delete_dialog_alert_local": "Diese Inhalte werden vom Gerät gelÃļscht, bleiben aber auf dem Immich-Server.", - "delete_dialog_alert_local_non_backed_up": "Einige Inhalte sind nicht in Immich gesichert und werden dauerhaft vom Gerät gelÃļscht.", - "delete_dialog_alert_remote": "Diese Inhalte werden dauerhaft vom Immich-Server gelÃļscht.", + "delete_dialog_alert_local": "Diese Inhalte werden vom Gerät gelÃļscht, bleiben aber auf dem Immich-Server", + "delete_dialog_alert_local_non_backed_up": "Einige Inhalte sind nicht in Immich gesichert und werden dauerhaft vom Gerät gelÃļscht", + "delete_dialog_alert_remote": "Diese Inhalte werden dauerhaft vom Immich-Server gelÃļscht", "delete_dialog_ok_force": "Trotzdem lÃļschen", "delete_dialog_title": "EndgÃŧltig lÃļschen", "delete_duplicates_confirmation": "Bist du sicher, dass du diese Duplikate endgÃŧltig lÃļschen willst?", @@ -741,7 +745,7 @@ "deletes_missing_assets": "LÃļscht Dateien, die auf der Festplatte fehlen", "description": "Beschreibung", "description_input_hint_text": "Beschreibung hinzufÃŧgen...", - "description_input_submit_error": "Beschreibung konnte nicht geändert werden, bitte im Log fÃŧr mehr Details nachsehen.", + "description_input_submit_error": "Beschreibung konnte nicht geändert werden, bitte im Log fÃŧr mehr Details nachsehen", "details": "Details", "direction": "Richtung", "disabled": "Deaktiviert", @@ -758,23 +762,23 @@ "documentation": "Dokumentation", "done": "Fertig", "download": "Herunterladen", - "download_canceled": "Download abgebrochen!", - "download_complete": "Download vollständig!", - "download_enqueue": "Download in die Warteschlange gesetzt!", + "download_canceled": "Download abgebrochen", + "download_complete": "Download vollständig", + "download_enqueue": "Download in die Warteschlange gesetzt", "download_error": "Download fehlerhaft", - "download_failed": "Download fehlerhaft!", + "download_failed": "Download fehlerhaft", "download_filename": "Datei: {}", "download_finished": "Download abgeschlossen", "download_include_embedded_motion_videos": "Eingebettete Videos", "download_include_embedded_motion_videos_description": "Videos, die in Bewegungsfotos eingebettet sind, als separate Datei einfÃŧgen", - "download_notfound": "Download nicht gefunden!", - "download_paused": "Download pausiert!", + "download_notfound": "Download nicht gefunden", + "download_paused": "Download pausiert", "download_settings": "Download", "download_settings_description": "Einstellungen fÃŧr das Herunterladen von Dateien verwalten", "download_started": "Download gestartet", "download_sucess": "Download erfolgreich", "download_sucess_android": "Die Datei wurde nach DCIM/Immich heruntergeladen", - "download_waiting_to_retry": "Warte auf erneuten Versuch...", + "download_waiting_to_retry": "Warte auf erneuten Versuch", "downloading": "Herunterladen", "downloading_asset_filename": "Datei {filename} wird heruntergeladen", "downloading_media": "Medien werden heruntergeladen", @@ -954,9 +958,9 @@ "exif_bottom_sheet_people": "PERSONEN", "exif_bottom_sheet_person_add_person": "Namen hinzufÃŧgen", "exif_bottom_sheet_person_age": "Alter {}", - "exif_bottom_sheet_person_age_months": "Age {} months", - "exif_bottom_sheet_person_age_year_months": "Age 1 year, {} months", - "exif_bottom_sheet_person_age_years": "Age {}", + "exif_bottom_sheet_person_age_months": "{} Monate alt", + "exif_bottom_sheet_person_age_year_months": "1 Jahr, {} Monate alt", + "exif_bottom_sheet_person_age_years": "{} alt", "exit_slideshow": "Diashow beenden", "expand_all": "Alle aufklappen", "experimental_settings_new_asset_list_subtitle": "In Arbeit", @@ -992,6 +996,7 @@ "filetype": "Dateityp", "filter": "Filter", "filter_people": "Personen filtern", + "filter_places": "Orte filtern", "find_them_fast": "Finde sie schneller mit der Suche nach Namen", "fix_incorrect_match": "Fehlerhafte Übereinstimmung beheben", "folder": "Ordner", @@ -1001,7 +1006,7 @@ "forward": "Vorwärts", "general": "Allgemein", "get_help": "Hilfe erhalten", - "get_wifiname_error": "WLAN-Name konnte nicht ermittelt werden. Vergewissere dich, dass die erforderlichen Berechtigungen erteilt wurden und du mit einem WLAN-Netzwerk verbunden bist.\n", + "get_wifiname_error": "WLAN-Name konnte nicht ermittelt werden. Vergewissere dich, dass die erforderlichen Berechtigungen erteilt wurden und du mit einem WLAN-Netzwerk verbunden bist", "getting_started": "Erste Schritte", "go_back": "ZurÃŧck", "go_to_folder": "Gehe zu Ordner", @@ -1030,23 +1035,23 @@ "hide_person": "Person verbergen", "hide_unnamed_people": "Unbenannte Personen verbergen", "home_page_add_to_album_conflicts": "{added} Elemente zu {album} hinzugefÃŧgt. {failed} Elemente sind bereits vorhanden.", - "home_page_add_to_album_err_local": "Es kÃļnnen lokale Elemente noch nicht zu Alben hinzugefÃŧgt werden, Ãŧberspringen...", + "home_page_add_to_album_err_local": "Es kÃļnnen lokale Elemente noch nicht zu Alben hinzugefÃŧgt werden, Ãŧberspringen", "home_page_add_to_album_success": "{added} Elemente zu {album} hinzugefÃŧgt.", - "home_page_album_err_partner": "Inhalte von Partnern kÃļnnen derzeit nicht zu Alben hinzugefÃŧgt werden!", - "home_page_archive_err_local": "Kann lokale Elemente nicht archvieren, Ãŧberspringen...", - "home_page_archive_err_partner": "Inhalte von Partnern kÃļnnen nicht archiviert werden!", - "home_page_building_timeline": "Zeitachse wird erstellt.", - "home_page_delete_err_partner": "Inhalte von Partnern kÃļnnen nicht gelÃļscht werden!", - "home_page_delete_remote_err_local": "Lokale Inhalte in der Auswahl, Ãŧberspringen...", - "home_page_favorite_err_local": "Kann lokale Elemente noch nicht favorisieren, Ãŧberspringen...", - "home_page_favorite_err_partner": "Inhalte von Partnern kÃļnnen nicht favorisiert werden!", - "home_page_first_time_notice": "Wenn dies das erste Mal ist dass Du Immich nutzt, stelle bitte sicher, dass mindestens ein Album zur Sicherung ausgewählt ist, sodass die Zeitachse mit Fotos und Videos gefÃŧllt werden kann.", + "home_page_album_err_partner": "Inhalte von Partnern kÃļnnen derzeit nicht zu Alben hinzugefÃŧgt werden", + "home_page_archive_err_local": "Kann lokale Elemente nicht archvieren, Ãŧberspringen", + "home_page_archive_err_partner": "Inhalte von Partnern kÃļnnen nicht archiviert werden", + "home_page_building_timeline": "Zeitachse wird erstellt", + "home_page_delete_err_partner": "Inhalte von Partnern kÃļnnen nicht gelÃļscht werden, Ãŧberspringe", + "home_page_delete_remote_err_local": "Lokale Inhalte in der Auswahl, Ãŧberspringen", + "home_page_favorite_err_local": "Kann lokale Elemente noch nicht favorisieren, Ãŧberspringen", + "home_page_favorite_err_partner": "Inhalte von Partnern kÃļnnen nicht favorisiert werden, Ãŧberspringe", + "home_page_first_time_notice": "Wenn dies das erste Mal ist dass Du Immich nutzt, stelle bitte sicher, dass mindestens ein Album zur Sicherung ausgewählt ist, sodass die Zeitachse mit Fotos und Videos gefÃŧllt werden kann", "home_page_share_err_local": "Lokale Inhalte kÃļnnen nicht per Link geteilt werden, Ãŧberspringe", - "home_page_upload_err_limit": "Es kÃļnnen max. 30 Elemente gleichzeitig hochgeladen werden, Ãŧberspringen...", + "home_page_upload_err_limit": "Es kÃļnnen max. 30 Elemente gleichzeitig hochgeladen werden, Ãŧberspringen", "host": "Host", "hour": "Stunde", "ignore_icloud_photos": "iCloud Fotos ignorieren", - "ignore_icloud_photos_description": "Fotos, die in der iCloud gespeichert sind, werden nicht auf den immich Server hochgeladen", + "ignore_icloud_photos_description": "Fotos, die in der iCloud gespeichert sind, werden nicht auf den immich Server hochgeladen", "image": "Bild", "image_alt_text_date": "{isVideo, select, true {Video} other {Bild}} aufgenommen am {date}", "image_alt_text_date_1_person": "{isVideo, select, true {Video} other {Bild}} aufgenommen mit {person1} am {date}", @@ -1080,7 +1085,7 @@ "night_at_midnight": "Täglich um Mitternacht", "night_at_twoam": "Täglich nachts um 2:00 Uhr" }, - "invalid_date": "UngÃŧltiges Datum ", + "invalid_date": "UngÃŧltiges Datum", "invalid_date_format": "UngÃŧltiges Datumsformat", "invite_people": "Personen einladen", "invite_to_album": "Zum Album einladen", @@ -1143,7 +1148,7 @@ "login_form_err_leading_whitespace": "Leerzeichen am Anfang", "login_form_err_trailing_whitespace": "Leerzeichen am Ende", "login_form_failed_get_oauth_server_config": "Fehler beim Login per OAuth, bitte Server-URL ÃŧberprÃŧfen", - "login_form_failed_get_oauth_server_disable": "Die OAuth-Funktion ist auf diesem Server nicht verfÃŧgbar.", + "login_form_failed_get_oauth_server_disable": "Die OAuth-Funktion ist auf diesem Server nicht verfÃŧgbar", "login_form_failed_login": "Fehler beim Login, bitte ÃŧberprÃŧfe die Server-URL, deine E-Mail oder das Passwort", "login_form_handshake_exception": "Fehler beim Verbindungsaufbau mit dem Server. Falls du ein selbstsigniertes Zertifikat verwendest, aktiviere die UnterstÃŧtzung dafÃŧr in den Einstellungen.", "login_form_password_hint": "Passwort", @@ -1151,8 +1156,8 @@ "login_form_server_empty": "Serveradresse eingeben.", "login_form_server_error": "Es Konnte sich nicht mit dem Server verbunden werden.", "login_has_been_disabled": "Die Anmeldung wurde deaktiviert.", - "login_password_changed_error": "Fehler beim Passwort ändern!", - "login_password_changed_success": "Passwort erfolgreich geändert.", + "login_password_changed_error": "Fehler beim Ändern deines Passwort", + "login_password_changed_success": "Passwort erfolgreich geändert", "logout_all_device_confirmation": "Bist du sicher, dass du alle Geräte abmelden willst?", "logout_this_device_confirmation": "Bist du sicher, dass du dieses Gerät abmelden willst?", "longitude": "Längengrad", @@ -1172,7 +1177,7 @@ "map": "Karte", "map_assets_in_bound": "{} Foto", "map_assets_in_bounds": "{} Fotos", - "map_cannot_get_user_location": "Standort konnte nicht ermittelt werden!", + "map_cannot_get_user_location": "Standort konnte nicht ermittelt werden", "map_location_dialog_yes": "Ja", "map_location_picker_page_use_location": "Aufnahmeort verwenden", "map_location_service_disabled_content": "Ortungsdienste mÃŧssen aktiviert sein, um Inhalte am aktuellen Standort anzuzeigen. Willst du die Ortungsdienste jetzt aktivieren?", @@ -1181,7 +1186,7 @@ "map_marker_with_image": "Kartenmarkierung mit Bild", "map_no_assets_in_bounds": "Keine Fotos in dieser Gegend", "map_no_location_permission_content": "Ortungsdienste mÃŧssen aktiviert sein, um Inhalte am aktuellen Standort anzuzeigen. Willst du die Ortungsdienste jetzt aktivieren?", - "map_no_location_permission_title": "Kein Zugriff auf den Standort!", + "map_no_location_permission_title": "Kein Zugriff auf den Standort", "map_settings": "Karteneinstellungen", "map_settings_dark_mode": "Dunkler Modus", "map_settings_date_range_option_day": "Letzte 24 Stunden", @@ -1198,7 +1203,7 @@ "media_type": "Medientyp", "memories": "Erinnerungen", "memories_all_caught_up": "Alles aufgeholt", - "memories_check_back_tomorrow": "Schau morgen wieder vorbei fÃŧr weitere Erinnerungen!", + "memories_check_back_tomorrow": "Schau morgen wieder vorbei fÃŧr weitere Erinnerungen", "memories_setting_description": "Verwalte, was du in deinen Erinnerungen siehst", "memories_start_over": "Erneut beginnen", "memories_swipe_to_close": "Nach oben Wischen zum schließen", @@ -1221,8 +1226,8 @@ "monthly_title_text_date_format": "MMMM y", "more": "Mehr", "moved_to_trash": "In den Papierkorb verschoben", - "multiselect_grid_edit_date_time_err_read_only": "Das Datum und die Uhrzeit von schreibgeschÃŧtzten Inhalten kann nicht verändert werden, Ãŧberspringen...", - "multiselect_grid_edit_gps_err_read_only": "Der Aufnahmeort von schreibgeschÃŧtzten Inhalten kann nicht verändert werden, Ãŧberspringen...", + "multiselect_grid_edit_date_time_err_read_only": "Das Datum und die Uhrzeit von schreibgeschÃŧtzten Inhalten kann nicht verändert werden, Ãŧberspringen", + "multiselect_grid_edit_gps_err_read_only": "Der Aufnahmeort von schreibgeschÃŧtzten Inhalten kann nicht verändert werden, Ãŧberspringen", "mute_memories": "Erinnerungen stumm schalten", "my_albums": "Meine Alben", "name": "Name", @@ -1260,8 +1265,8 @@ "not_selected": "Nicht ausgewählt", "note_apply_storage_label_to_previously_uploaded assets": "Hinweis: Um eine Speicherpfadbezeichnung anzuwenden, starte den", "notes": "Notizen", - "notification_permission_dialog_content": "Um Benachrichtigungen zu aktivieren, navigiere zu Einstellungen und klicke \"Erlauben\"", - "notification_permission_list_tile_content": "Erlaube Berechtigung fÃŧr Benachrichtigungen", + "notification_permission_dialog_content": "Um Benachrichtigungen zu aktivieren, navigiere zu Einstellungen und klicke \"Erlauben\".", + "notification_permission_list_tile_content": "Erlaube Berechtigung fÃŧr Benachrichtigungen.", "notification_permission_list_tile_enable_button": "Aktiviere Benachrichtigungen", "notification_permission_list_tile_title": "Benachrichtigungs-Berechtigung", "notification_toggle_setting_description": "E-Mail-Benachrichtigungen aktivieren", @@ -1282,6 +1287,7 @@ "onboarding_welcome_user": "Willkommen, {user}", "online": "Online", "only_favorites": "Nur Favoriten", + "open": "Öffnen", "open_in_map_view": "In Kartenansicht Ãļffnen", "open_in_openstreetmap": "In OpenStreetMap Ãļffnen", "open_the_search_filters": "Die Suchfilter Ãļffnen", @@ -1371,7 +1377,7 @@ "profile_drawer_app_logs": "Logs", "profile_drawer_client_out_of_date_major": "Mobile-App ist veraltet. Bitte aktualisiere auf die neueste Major-Version.", "profile_drawer_client_out_of_date_minor": "Mobile-App ist veraltet. Bitte aktualisiere auf die neueste Minor-Version.", - "profile_drawer_client_server_up_to_date": "Die App-Version / Server-Version sind aktuell.", + "profile_drawer_client_server_up_to_date": "Die App-Version / Server-Version sind aktuell", "profile_drawer_github": "GitHub", "profile_drawer_server_out_of_date_major": "Server-Version ist veraltet. Bitte aktualisiere auf die neueste Major-Version.", "profile_drawer_server_out_of_date_minor": "Server-Version ist veraltet. Bitte aktualisiere auf die neueste Minor-Version.", @@ -1504,7 +1510,7 @@ "search_city": "Suche nach Stadt...", "search_country": "Suche nach Land...", "search_filter_apply": "Filter anwenden", - "search_filter_camera_title": "Kameratyp auswählen ", + "search_filter_camera_title": "Kameratyp auswählen", "search_filter_date": "Datum", "search_filter_date_interval": "{start} bis {end}", "search_filter_date_title": "Wähle einen Zeitraum", @@ -1512,10 +1518,10 @@ "search_filter_display_options": "Anzeigeeinstellungen", "search_filter_filename": "Suche nach Dateiname", "search_filter_location": "Ort", - "search_filter_location_title": "Ort auswählen ", + "search_filter_location_title": "Ort auswählen", "search_filter_media_type": "Medientyp", - "search_filter_media_type_title": "Medientyp auswählen ", - "search_filter_people_title": "Personen auswählen ", + "search_filter_media_type_title": "Medientyp auswählen", + "search_filter_people_title": "Personen auswählen", "search_for": "Suche nach", "search_for_existing_person": "Suche nach vorhandener Person", "search_no_more_result": "Keine weiteren Ergebnisse", @@ -1596,7 +1602,7 @@ "setting_notifications_notify_minutes": "{} Minuten", "setting_notifications_notify_never": "niemals", "setting_notifications_notify_seconds": "{} Sekunden", - "setting_notifications_single_progress_subtitle": "Detaillierter Upload-Fortschritt fÃŧr jedes Element.", + "setting_notifications_single_progress_subtitle": "Detaillierter Upload-Fortschritt fÃŧr jedes Element", "setting_notifications_single_progress_title": "Zeige den detaillierten Fortschritt der Hintergrundsicherung", "setting_notifications_subtitle": "Benachrichtigungen anpassen", "setting_notifications_total_progress_subtitle": "Gesamter Upload-Fortschritt (abgeschlossen/Anzahl Elemente)", @@ -1605,14 +1611,14 @@ "setting_video_viewer_original_video_subtitle": "Beim Streaming eines Videos vom Server wird das Original abgespielt, auch wenn eine Transkodierung verfÃŧgbar ist. Kann zu Pufferung fÃŧhren. Lokal verfÃŧgbare Videos werden unabhängig von dieser Einstellung in Originalqualität wiedergegeben.", "setting_video_viewer_original_video_title": "Originalvideo erzwingen", "settings": "Einstellungen", - "settings_require_restart": "Bitte starte Immich neu, um diese Einstellung anzuwenden.", + "settings_require_restart": "Bitte starte Immich neu, um diese Einstellung anzuwenden", "settings_saved": "Einstellungen gespeichert", "share": "Teilen", "share_add_photos": "Fotos hinzufÃŧgen", "share_assets_selected": "{} ausgewählt", "share_dialog_preparing": "Vorbereiten...", "shared": "Geteilt", - "shared_album_activities_input_disable": "Kommentare sind deaktiviert.", + "shared_album_activities_input_disable": "Kommentare sind deaktiviert", "shared_album_activity_remove_content": "MÃļchtest du diese Aktivität entfernen?", "shared_album_activity_remove_title": "Aktivität entfernen", "shared_album_section_people_action_error": "Fehler beim Verlassen oder Entfernen aus dem Album", @@ -1635,20 +1641,20 @@ "shared_link_edit_expire_after_option_hours": "{} Stunden", "shared_link_edit_expire_after_option_minute": "1 Minute", "shared_link_edit_expire_after_option_minutes": "{} Minuten", - "shared_link_edit_expire_after_option_months": "{} Monat/en", - "shared_link_edit_expire_after_option_year": "{} Jahr/en", + "shared_link_edit_expire_after_option_months": "{} Monate", + "shared_link_edit_expire_after_option_year": "{} Jahr", "shared_link_edit_password_hint": "Passwort eingeben", "shared_link_edit_submit_button": "Link aktualisieren", "shared_link_error_server_url_fetch": "Fehler beim Ermitteln der Server-URL", "shared_link_expires_day": "Verfällt in {} Tag", - "shared_link_expires_days": "Verfällt in {} Tag/en", + "shared_link_expires_days": "Verfällt in {} Tagen", "shared_link_expires_hour": "Verfällt in {} Stunde", - "shared_link_expires_hours": "Verfällt in {} Stunde/n", + "shared_link_expires_hours": "Verfällt in {} Stunden", "shared_link_expires_minute": "Verfällt in {} Minute", - "shared_link_expires_minutes": "Verfällt in {} Minute/n", + "shared_link_expires_minutes": "Verfällt in {} Minuten", "shared_link_expires_never": "Läuft nie ab", "shared_link_expires_second": "Verfällt in {} Sekunde", - "shared_link_expires_seconds": "Verfällt in {} Sekunde/n", + "shared_link_expires_seconds": "Verfällt in {} Sekunden", "shared_link_individual_shared": "Individuell geteilt", "shared_link_info_chip_metadata": "EXIF", "shared_link_manage_links": "Geteilte Links verwalten", @@ -1750,11 +1756,11 @@ "theme_selection_description": "Automatische Einstellung des Themes auf Hell oder Dunkel, je nach Systemeinstellung des Browsers", "theme_setting_asset_list_storage_indicator_title": "Forschrittsbalken der Sicherung auf dem Vorschaubild", "theme_setting_asset_list_tiles_per_row_title": "Anzahl der Elemente pro Reihe ({})", - "theme_setting_colorful_interface_subtitle": "Primärfarbe auf App-Hintergrund anwenden", + "theme_setting_colorful_interface_subtitle": "Primärfarbe auf App-Hintergrund anwenden.", "theme_setting_colorful_interface_title": "Farbige UI-Oberfläche", "theme_setting_image_viewer_quality_subtitle": "Einstellen der Qualität des Detailbildbetrachters", "theme_setting_image_viewer_quality_title": "Qualität des Bildbetrachters", - "theme_setting_primary_color_subtitle": "Farbauswahl fÃŧr primäre Aktionen und Akzente", + "theme_setting_primary_color_subtitle": "Farbauswahl fÃŧr primäre Aktionen und Akzente.", "theme_setting_primary_color_title": "Primärfarbe", "theme_setting_system_primary_color_title": "Systemfarbe verwenden", "theme_setting_system_theme_switch": "Automatisch (Systemeinstellung)", @@ -1784,7 +1790,7 @@ "trash_no_results_message": "GelÃļschte Fotos und Videos werden hier angezeigt.", "trash_page_delete_all": "Alle lÃļschen", "trash_page_empty_trash_dialog_content": "Elemente im Papierkorb lÃļschen? Diese Elemente werden dauerhaft aus Immich entfernt", - "trash_page_info": "Elemente im Papierkorb werden nach {} Tagen endgÃŧltig gelÃļscht.", + "trash_page_info": "Elemente im Papierkorb werden nach {} Tagen endgÃŧltig gelÃļscht", "trash_page_no_assets": "Es gibt keine Daten im Papierkorb", "trash_page_restore_all": "Alle wiederherstellen", "trash_page_select_assets_btn": "Elemente auswählen", diff --git a/i18n/el.json b/i18n/el.json index 52efcccd50..a8a56f5122 100644 --- a/i18n/el.json +++ b/i18n/el.json @@ -39,11 +39,11 @@ "authentication_settings_disable_all": "Î•Î¯ĪƒĪ„Îĩ βέβιΚÎŋΚ ĪŒĪ„Îš θέÎģÎĩĪ„Îĩ ÎŊÎą ÎąĪ€ÎĩÎŊÎĩĪÎŗÎŋĪ€ÎŋÎšÎŽĪƒÎĩĪ„Îĩ ΌÎģÎĩĪ‚ Ī„ÎšĪ‚ ÎŧÎĩÎ¸ĪŒÎ´ÎŋĪ…Ī‚ ĪƒĪÎŊδÎĩĪƒÎˇĪ‚; Η ĪƒĪÎŊδÎĩĪƒÎˇ θι ÎąĪ€ÎĩÎŊÎĩĪÎŗÎŋĪ€ÎŋΚΡθÎĩί Ī€ÎģÎŽĪĪ‰Ī‚.", "authentication_settings_reenable": "Για ÎĩĪ€ÎąÎŊÎĩÎŊÎĩĪÎŗÎŋĪ€ÎŋÎ¯ÎˇĪƒÎˇ, Ī‡ĪÎˇĪƒÎšÎŧÎŋĪ€ÎŋÎšÎŽĪƒĪ„Îĩ ÎŧÎ¯Îą ΕÎŊĪ„ÎŋÎģÎŽ ΔιαÎēÎŋÎŧÎšĪƒĪ„ÎŽ.", "background_task_job": "Î•ĪÎŗÎąĪƒÎ¯ÎĩĪ‚ Î ÎąĪÎąĪƒÎēΡÎŊίÎŋĪ…", - "backup_database": "ΔηÎŧΚÎŋĪ…ĪÎŗÎ¯Îą ΑÎŊĪ„ÎšÎŗĪÎŦΆÎŋĪ… Î‘ĪƒĪ†ÎąÎģÎĩÎ¯ÎąĪ‚ Ī„ÎˇĪ‚ ΒÎŦĪƒÎˇĪ‚ ΔÎĩδÎŋÎŧέÎŊΉÎŊ", - "backup_database_enable_description": "ΕÎŊÎĩĪÎŗÎŋĪ€ÎŋÎ¯ÎˇĪƒÎˇ ÎąÎŊĪ„ÎšÎŗĪÎŦΆΉÎŊ ÎąĪƒĪ†ÎąÎģÎĩÎ¯ÎąĪ‚ Ī„ÎˇĪ‚ βÎŦĪƒÎˇĪ‚ δÎĩδÎŋÎŧέÎŊΉÎŊ", - "backup_keep_last_amount": "Î‘ĪÎšÎ¸ÎŧĪŒĪ‚ ΀΁ÎŋÎˇÎŗÎŋĪÎŧÎĩÎŊΉÎŊ ÎąÎŊĪ„ÎšÎŗĪÎŦΆΉÎŊ ÎąĪƒĪ†ÎąÎģÎĩÎ¯ÎąĪ‚ ÎŗÎšÎą Î´ÎšÎąĪ„ÎŽĪÎˇĪƒÎˇ", - "backup_settings": "ÎĄĪ…Î¸ÎŧÎ¯ĪƒÎĩÎšĪ‚ ΑÎŊĪ„ÎšÎŗĪÎŦΆΉÎŊ Î‘ĪƒĪ†ÎąÎģÎĩÎ¯ÎąĪ‚", - "backup_settings_description": "Î”ÎšÎąĪ‡ÎĩÎ¯ĪÎˇĪƒÎˇ ĪĪ…Î¸ÎŧÎ¯ĪƒÎĩΉÎŊ ΄ΉÎŊ ÎąÎŊĪ„ÎšÎŗĪÎŦΆΉÎŊ ÎąĪƒĪ†ÎąÎģÎĩÎ¯ÎąĪ‚ Ī„ÎˇĪ‚ βÎŦĪƒÎˇĪ‚ δÎĩδÎŋÎŧέÎŊΉÎŊ", + "backup_database": "ΔηÎŧΚÎŋĪ…ĪÎŗÎ¯Îą Dump βÎŦĪƒÎˇĪ‚ δÎĩδÎŋÎŧέÎŊΉÎŊ", + "backup_database_enable_description": "ΕÎŊÎĩĪÎŗÎŋĪ€ÎŋÎ¯ÎˇĪƒÎˇ dumps βÎŦĪƒÎˇĪ‚ δÎĩδÎŋÎŧέÎŊΉÎŊ", + "backup_keep_last_amount": "ΠÎŋĪƒĪŒĪ„ÎˇĪ„Îą ΀΁ÎŋÎˇÎŗÎŋĪÎŧÎĩÎŊΉÎŊ dumps Ī€ÎŋĪ… Ī€ĪÎ­Ī€ÎĩΚ ÎŊÎą Î´ÎšÎąĪ„ÎˇĪÎˇÎ¸ÎŋĪÎŊ", + "backup_settings": "ÎĄĪ…Î¸ÎŧÎ¯ĪƒÎĩÎšĪ‚ dump βÎŦĪƒÎˇĪ‚ δÎĩδÎŋÎŧέÎŊΉÎŊ", + "backup_settings_description": "Î”ÎšÎąĪ‡ÎĩÎ¯ĪÎšĪƒÎˇ ĪĪ…Î¸ÎŧÎ¯ĪƒÎĩΉÎŊ dump Ī„ÎˇĪ‚ βÎŦĪƒÎˇĪ‚ δÎĩδÎŋÎŧέÎŊΉÎŊ. ÎŖÎˇÎŧÎĩÎ¯Ī‰ĪƒÎˇ: Î‘Ī…Ī„Î­Ī‚ ÎŋΚ ÎĩĪÎŗÎąĪƒÎ¯ÎĩĪ‚ δÎĩÎŊ Ī€ÎąĪÎąÎēÎŋÎģÎŋĪ…Î¸ÎŋĪÎŊĪ„ÎąÎš ÎēιΚ δÎĩÎŊ θι ÎĩΚδÎŋĪ€ÎŋΚΡθÎĩÎ¯Ī„Îĩ ÎŗÎšÎą ÎąĪ€ÎŋĪ„Ī…Ī‡Î¯Îą.", "check_all": "ΈÎģÎĩÎŗĪ‡ÎŋĪ‚ ΌÎģΉÎŊ", "cleanup": "ΕÎēÎēιθÎŦĪÎšĪƒÎˇ", "cleared_jobs": "ΕÎēÎēÎąÎ¸ÎąĪÎ¯ĪƒĪ„ÎˇÎēÎąÎŊ ÎŋΚ ÎĩĪÎŗÎąĪƒÎ¯ÎĩĪ‚ ÎŗÎšÎą: {job}", @@ -371,13 +371,17 @@ "admin_password": "ÎšĪ‰Î´ÎšÎēĪŒĪ‚ Ī€ĪĪŒĪƒÎ˛ÎąĪƒÎˇĪ‚ Î”ÎšÎąĪ‡ÎĩÎšĪÎšĪƒĪ„ÎŽ", "administration": "Î”ÎšÎąĪ‡ÎĩÎ¯ĪÎšĪƒÎˇ", "advanced": "Για ΀΁ÎŋĪ‡Ī‰ĪÎˇÎŧέÎŊÎŋĪ…Ī‚", - "advanced_settings_log_level_title": "Î•Ī€Î¯Ī€ÎĩδÎŋ ÎēÎąĪ„ÎąÎŗĪÎąĪ†ÎŽĪ‚: {}", + "advanced_settings_enable_alternate_media_filter_subtitle": "Î§ĪÎˇĪƒÎšÎŧÎŋĪ€ÎŋÎšÎŽĪƒĪ„Îĩ ÎąĪ…Ī„ÎŽÎŊ Ī„ÎˇÎŊ ÎĩĪ€ÎšÎģÎŋÎŗÎŽ ÎŗÎšÎą ÎŊÎą Ī†ÎšÎģ΄΁ÎŦ΁ÎĩĪ„Îĩ Ī„Îą ÎŧÎ­ĪƒÎą ÎĩÎŊΡÎŧÎ­ĪĪ‰ĪƒÎˇĪ‚ ÎēÎąĪ„ÎŦ Ī„ÎŋÎŊ ĪƒĪ…ÎŗĪ‡ĪÎŋÎŊÎšĪƒÎŧΌ ÎŧÎĩ βÎŦĪƒÎˇ ÎĩÎŊÎąÎģÎģÎąÎēĪ„ÎšÎēÎŦ ÎēĪÎšĪ„ÎŽĪÎšÎą. ΔÎŋÎēΚÎŧÎŦĪƒĪ„Îĩ ÎąĪ…Ī„ÎŽ Ī„Îˇ Î´Ī…ÎŊÎąĪ„ĪŒĪ„ÎˇĪ„Îą ÎŧΌÎŊÎŋ ÎąÎŊ Î­Ī‡ÎĩĪ„Îĩ ΀΁ÎŋβÎģÎŽÎŧÎąĪ„Îą ÎŧÎĩ Ī„ÎˇÎŊ ÎĩĪ†ÎąĪÎŧÎŋÎŗÎŽ Ī€ÎŋĪ… ÎĩÎŊĪ„ÎŋĪ€Î¯ÎļÎĩΚ ΌÎģÎą Ī„Îą ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ.", + "advanced_settings_enable_alternate_media_filter_title": "[ΠΕΙΡΑΜΑΤΙΚΟ] Î§ĪÎŽĪƒÎˇ ÎĩÎŊÎąÎģÎģÎąÎēĪ„ÎšÎēÎŋĪ Ī†Î¯Îģ΄΁ÎŋĪ… ĪƒĪ…ÎŗĪ‡ĪÎŋÎŊÎšĪƒÎŧÎŋĪ ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ ĪƒĪ…ĪƒÎēÎĩĪ…ÎŽĪ‚", + "advanced_settings_log_level_title": "Î•Ī€Î¯Ī€ÎĩδÎŋ ĪƒĪÎŊδÎĩĪƒÎˇĪ‚: {}", "advanced_settings_prefer_remote_subtitle": "ΜÎĩĪÎšÎēÎ­Ī‚ ĪƒĪ…ĪƒÎēÎĩĪ…Î­Ī‚ ÎąĪÎŗÎŋĪÎŊ Ī€ÎŋÎģĪ ÎŊÎą ΆÎŋĪĪ„ĪŽĪƒÎŋĪ…ÎŊ ÎŧΚÎē΁ÎŋÎŗĪÎąĪ†Î¯ÎĩĪ‚ ÎąĪ€ĪŒ ÎąĪĪ‡ÎĩÎ¯Îą ĪƒĪ„Îˇ ĪƒĪ…ĪƒÎēÎĩĪ…ÎŽ. ΕÎŊÎĩĪÎŗÎŋĪ€ÎŋÎšÎŽĪƒĪ„Îĩ ÎąĪ…Ī„ÎŽÎŊ Ī„Îˇ ĪĪÎ¸ÎŧÎšĪƒÎˇ ÎŗÎšÎą ÎŊÎą ΆÎŋĪĪ„ĪŽÎŊÎŋÎŊĪ„ÎąÎš ÎąÎŊĪ„Î¯ ÎąĪ…Ī„ÎŋĪ ÎąĪ€ÎŋÎŧÎąÎēĪĪ…ĪƒÎŧέÎŊÎĩĪ‚ ÎĩΚÎēΌÎŊÎĩĪ‚.", "advanced_settings_prefer_remote_title": "Î ĪÎŋĪ„Î¯ÎŧÎˇĪƒÎˇ ÎąĪ€ÎŋÎŧÎąÎēĪĪ…ĪƒÎŧέÎŊΉÎŊ ÎĩΚÎēΌÎŊΉÎŊ.", "advanced_settings_proxy_headers_subtitle": "ΚαθÎŋĪÎšĪƒÎŧĪŒĪ‚ ÎēÎĩĪ†ÎąÎģÎ¯Î´Ī‰ÎŊ δΚιÎēÎŋÎŧÎšĪƒĪ„ÎŽ ÎŧÎĩ΃ÎŋÎģÎŦÎ˛ÎˇĪƒÎˇĪ‚ Ī€ÎŋĪ… Ī„Îŋ Immich Ī€ĪÎ­Ī€ÎĩΚ ÎŊÎą ĪƒĪ„Î­ÎģÎŊÎĩΚ ÎŧÎĩ ÎēÎŦθÎĩ ÎąÎ¯Ī„ÎˇÎŧÎą δΚÎēĪ„ĪÎŋĪ…", "advanced_settings_proxy_headers_title": "ΚÎĩĪ†ÎąÎģίδÎĩĪ‚ δΚιÎēÎŋÎŧÎšĪƒĪ„ÎŽ ÎŧÎĩ΃ÎŋÎģÎŦÎ˛ÎˇĪƒÎˇĪ‚", "advanced_settings_self_signed_ssl_subtitle": "Î ÎąĪÎąÎēÎŦÎŧ΀΄ÎĩΚ Ī„ÎŋÎŊ έÎģÎĩÎŗĪ‡Îŋ Ī€ÎšĪƒĪ„ÎŋĪ€ÎŋÎšÎˇĪ„ÎšÎēÎŋĪ SSL Ī„ÎŋĪ… δΚιÎēÎŋÎŧÎšĪƒĪ„ÎŽ. Î‘Ī€ÎąĪÎąÎ¯Ī„ÎˇĪ„Îŋ ÎŗÎšÎą ÎąĪ…Ī„Îŋ-Ī…Ī€ÎŋÎŗÎĩÎŗĪÎąÎŧÎŧέÎŊÎą Ī€ÎšĪƒĪ„ÎŋĪ€ÎŋÎšÎˇĪ„ÎšÎēÎŦ.", "advanced_settings_self_signed_ssl_title": "Να ÎĩĪ€ÎšĪ„ĪÎ­Ī€ÎŋÎŊĪ„ÎąÎš ÎąĪ…Ī„Îŋ-Ī…Ī€ÎŋÎŗÎĩÎŗĪÎąÎŧÎŧέÎŊÎą Ī€ÎšĪƒĪ„ÎŋĪ€ÎŋÎšÎˇĪ„ÎšÎēÎŦ SSL", + "advanced_settings_sync_remote_deletions_subtitle": "Î‘Ī…Ī„ĪŒÎŧÎąĪ„Îˇ Î´ÎšÎąÎŗĪÎąĪ†ÎŽ ÎŽ ÎĩĪ€ÎąÎŊÎąĪ†Îŋ΁ÎŦ ÎĩÎŊĪŒĪ‚ Ī€ÎĩĪÎšÎŋĪ…ĪƒÎšÎąÎēÎŋĪ ĪƒĪ„ÎŋÎšĪ‡ÎĩίÎŋĪ… ΃Îĩ ÎąĪ…Ī„ÎŽ Ī„Îˇ ĪƒĪ…ĪƒÎēÎĩĪ…ÎŽ, ĪŒĪ„ÎąÎŊ Ρ ÎĩÎŊÎ­ĪÎŗÎĩΚι ÎąĪ…Ī„ÎŽ Ī€ĪÎąÎŗÎŧÎąĪ„ÎŋĪ€ÎŋΚÎĩÎ¯Ī„ÎąÎš ĪƒĪ„Îŋ Î´ÎšÎąÎ´Î¯Îē΄΅Îŋ", + "advanced_settings_sync_remote_deletions_title": "ÎŖĪ…ÎŗĪ‡ĪÎŋÎŊÎšĪƒÎŧĪŒĪ‚ ÎąĪ€ÎŋÎŧÎąÎēĪĪ…ĪƒÎŧέÎŊΉÎŊ Î´ÎšÎąÎŗĪÎąĪ†ĪŽÎŊ [ΠΕΙΡΑΜΑΤΙΚΟ]", "advanced_settings_tile_subtitle": "ÎĄĪ…Î¸ÎŧÎ¯ĪƒÎĩÎšĪ‚ ΀΁ÎŋĪ‡Ī‰ĪÎˇÎŧέÎŊÎŋĪ… Ī‡ĪÎŽĪƒĪ„Îˇ", "advanced_settings_troubleshooting_subtitle": "ΕÎŊÎĩĪÎŗÎŋĪ€ÎŋÎ¯ÎˇĪƒÎˇ Ī€ĪĪŒĪƒÎ¸Îĩ΄ΉÎŊ Ī‡ÎąĪÎąÎēĪ„ÎˇĪÎšĪƒĪ„ÎšÎēĪŽÎŊ ÎŗÎšÎą ÎąÎŊĪ„ÎšÎŧÎĩĪ„ĪŽĪ€ÎšĪƒÎˇ ΀΁ÎŋβÎģΡÎŧÎŦ΄ΉÎŊ", "advanced_settings_troubleshooting_title": "ΑÎŊĪ„ÎšÎŧÎĩĪ„ĪŽĪ€ÎšĪƒÎˇ ΀΁ÎŋβÎģΡÎŧÎŦ΄ΉÎŊ", @@ -477,8 +481,8 @@ "assets_added_to_album_count": "Î ĪÎŋĪƒĪ„Î­Î¸ÎˇÎēÎĩ {count, plural, one {# ÎąĪĪ‡ÎĩίÎŋ} other {# ÎąĪĪ‡ÎĩÎ¯Îą}} ĪƒĪ„Îŋ ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ", "assets_added_to_name_count": "Î ĪÎŋĪƒĪ„Î­Î¸ÎˇÎēÎĩ {count, plural, one {# ÎąĪĪ‡ÎĩίÎŋ} other {# ÎąĪĪ‡ÎĩÎ¯Îą}} ĪƒĪ„Îŋ {hasName, select, true {{name}} other {ÎŊέÎŋ ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ}}", "assets_count": "{count, plural, one {# ÎąĪĪ‡ÎĩίÎŋ} other {# ÎąĪĪ‡ÎĩÎ¯Îą}}", - "assets_deleted_permanently": "{} ĪƒĪ„ÎŋÎšĪ‡ÎĩίÎŋ(Îą) Î´ÎšÎąÎŗĪÎŦĪ†ÎˇÎēÎąÎŊ ÎŋĪÎšĪƒĪ„ÎšÎēÎŦ", - "assets_deleted_permanently_from_server": "{} ĪƒĪ„ÎŋÎšĪ‡ÎĩίÎŋ(Îą) Î´ÎšÎąÎŗĪÎŦĪ†ÎˇÎēÎąÎŊ ÎŋĪÎšĪƒĪ„ÎšÎēÎŦ ÎąĪ€ĪŒ Ī„ÎŋÎŊ δΚιÎēÎŋÎŧÎšĪƒĪ„ÎŽ Immich", + "assets_deleted_permanently": "{} ĪƒĪ„ÎŋÎšĪ‡ÎĩίÎŋ(-Îą) Î´ÎšÎąÎŗĪÎŦĪ†ÎˇÎēÎĩ(-ÎąÎŊ) ÎŋĪÎšĪƒĪ„ÎšÎēÎŦ", + "assets_deleted_permanently_from_server": "{} ĪƒĪ„ÎŋÎšĪ‡ÎĩίÎŋ(Îą) Î´ÎšÎąÎŗĪÎŦĪ†ÎˇÎēÎĩ(-ÎąÎŊ) ÎŋĪÎšĪƒĪ„ÎšÎēÎŦ ÎąĪ€ĪŒ Ī„ÎŋÎŊ δΚιÎēÎŋÎŧÎšĪƒĪ„ÎŽ Immich", "assets_moved_to_trash_count": "ΜÎĩĪ„ÎąÎēΚÎŊΎθΡÎēÎĩ/ÎēÎąÎŊ {count, plural, one {# ÎąĪĪ‡ÎĩίÎŋ} other {# ÎąĪĪ‡ÎĩÎ¯Îą}} ĪƒĪ„ÎŋÎŊ ÎēÎŦδÎŋ ÎąĪ€ÎŋĪĪÎšÎŧÎŧÎŦ΄ΉÎŊ", "assets_permanently_deleted_count": "Î”ÎšÎąÎŗĪÎŦĪ†ÎˇÎēÎĩ/ÎēÎąÎŊ ÎŧΌÎŊΚÎŧÎą {count, plural, one {# ÎąĪĪ‡ÎĩίÎŋ} other {# ÎąĪĪ‡ÎĩÎ¯Îą}}", "assets_removed_count": "Î‘Ī†ÎąÎšĪÎ­Î¸ÎˇÎēÎąÎŊ {count, plural, one {# ÎąĪĪ‡ÎĩίÎŋ} other {# ÎąĪĪ‡ÎĩÎ¯Îą}}", @@ -529,11 +533,11 @@ "backup_controller_page_background_turn_on": "ΕÎŊÎĩĪÎŗÎŋĪ€ÎŋÎ¯ÎˇĪƒÎˇ Ī…Ī€ÎˇĪÎĩĪƒÎ¯ÎąĪ‚ Ī€ÎąĪÎąĪƒÎēΡÎŊίÎŋĪ…", "backup_controller_page_background_wifi": "ÎœĪŒÎŊÎŋ ΃Îĩ ĪƒĪÎŊδÎĩĪƒÎˇ WiFi", "backup_controller_page_backup": "ΑÎŊĪ„Î¯ÎŗĪÎąĪ†Îą ÎąĪƒĪ†ÎąÎģÎĩÎ¯ÎąĪ‚", - "backup_controller_page_backup_selected": "Î•Ī€ÎšÎģÎĩÎŗÎŧέÎŊÎą:", + "backup_controller_page_backup_selected": "Î•Ī€ÎšÎģÎĩÎŗÎŧέÎŊÎą: ", "backup_controller_page_backup_sub": "ÎĻΉ΄ÎŋÎŗĪÎąĪ†Î¯ÎĩĪ‚ ÎēιΚ Î˛Î¯ÎŊĪ„ÎĩÎŋ ÎŗÎšÎą Ī„Îą ÎŋĪ€ÎŋÎ¯Îą Î­Ī‡ÎŋĪ…ÎŊ δΡÎŧΚÎŋĪ…ĪÎŗÎˇÎ¸Îĩί ÎąÎŊĪ„Î¯ÎŗĪÎąĪ†Îą ÎąĪƒĪ†ÎąÎģÎĩÎ¯ÎąĪ‚", "backup_controller_page_created": "ΔηÎŧΚÎŋĪ…ĪÎŗÎŽÎ¸ÎˇÎēÎĩ ĪƒĪ„ÎšĪ‚: {}", "backup_controller_page_desc_backup": "ΕÎŊÎĩĪÎŗÎŋĪ€ÎŋÎšÎŽĪƒĪ„Îĩ Ī„ÎˇÎŊ δΡÎŧΚÎŋĪ…ĪÎŗÎ¯Îą ÎąÎŊĪ„ÎšÎŗĪÎŦΆΉÎŊ ÎąĪƒĪ†ÎąÎģÎĩÎ¯ÎąĪ‚ ĪƒĪ„Îŋ ΀΁Îŋ΃ÎēÎŽÎŊΚÎŋ ÎŗÎšÎą ÎąĪ…Ī„ĪŒÎŧÎąĪ„Îˇ ÎŧÎĩĪ„ÎąĪ†ĪŒĪĪ„Ī‰ĪƒÎˇ ÎŊÎ­Ī‰ÎŊ ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Ī‰ÎŊ ĪƒĪ„ÎŋÎŊ δΚιÎēÎŋÎŧÎšĪƒĪ„ÎŽ ĪŒĪ„ÎąÎŊ ÎąÎŊÎŋÎ¯ÎŗÎĩĪ„Îĩ Ī„ÎˇÎŊ ÎĩĪ†ÎąĪÎŧÎŋÎŗÎŽ.", - "backup_controller_page_excluded": "Î•ÎžÎąÎšĪÎŋĪÎŧÎĩÎŊÎą:", + "backup_controller_page_excluded": "Î•ÎžÎąÎšĪÎŋĪÎŧÎĩÎŊÎą: ", "backup_controller_page_failed": "Î‘Ī€ÎŋĪ„Ī…Ī‡ÎˇÎŧέÎŊÎą ({})", "backup_controller_page_filename": "ΌÎŊÎŋÎŧÎą ÎąĪĪ‡ÎĩίÎŋĪ…: {} [{}]", "backup_controller_page_id": "ID: {}", diff --git a/i18n/en.json b/i18n/en.json index c4b4746871..c01cd65712 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -39,11 +39,11 @@ "authentication_settings_disable_all": "Are you sure you want to disable all login methods? Login will be completely disabled.", "authentication_settings_reenable": "To re-enable, use a Server Command.", "background_task_job": "Background Tasks", - "backup_database": "Backup Database", - "backup_database_enable_description": "Enable database backups", - "backup_keep_last_amount": "Amount of previous backups to keep", - "backup_settings": "Backup Settings", - "backup_settings_description": "Manage database backup settings", + "backup_database": "Create Database Dump", + "backup_database_enable_description": "Enable database dumps", + "backup_keep_last_amount": "Amount of previous dumps to keep", + "backup_settings": "Database Dump Settings", + "backup_settings_description": "Manage database dump settings. Note: These jobs are not monitored and you will not be notified of failure.", "check_all": "Check All", "cleanup": "Cleanup", "cleared_jobs": "Cleared jobs for: {job}", @@ -192,26 +192,22 @@ "oauth_auto_register": "Auto register", "oauth_auto_register_description": "Automatically register new users after signing in with OAuth", "oauth_button_text": "Button text", - "oauth_client_id": "Client ID", - "oauth_client_secret": "Client Secret", + "oauth_client_secret_description": "Required if PKCE (Proof Key for Code Exchange) is not supported by the OAuth provider", "oauth_enable_description": "Login with OAuth", - "oauth_issuer_url": "Issuer URL", "oauth_mobile_redirect_uri": "Mobile redirect URI", "oauth_mobile_redirect_uri_override": "Mobile redirect URI override", "oauth_mobile_redirect_uri_override_description": "Enable when OAuth provider does not allow a mobile URI, like '{callback}'", - "oauth_profile_signing_algorithm": "Profile signing algorithm", - "oauth_profile_signing_algorithm_description": "Algorithm used to sign the user profile.", - "oauth_scope": "Scope", "oauth_settings": "OAuth", "oauth_settings_description": "Manage OAuth login settings", "oauth_settings_more_details": "For more details about this feature, refer to the docs.", - "oauth_signing_algorithm": "Signing algorithm", "oauth_storage_label_claim": "Storage label claim", "oauth_storage_label_claim_description": "Automatically set the user's storage label to the value of this claim.", "oauth_storage_quota_claim": "Storage quota claim", "oauth_storage_quota_claim_description": "Automatically set the user's storage quota to the value of this claim.", "oauth_storage_quota_default": "Default storage quota (GiB)", "oauth_storage_quota_default_description": "Quota in GiB to be used when no claim is provided (Enter 0 for unlimited quota).", + "oauth_timeout": "Request Timeout", + "oauth_timeout_description": "Timeout for requests in milliseconds", "offline_paths": "Offline Paths", "offline_paths_description": "These results may be due to manual deletion of files that are not part of an external library.", "password_enable_description": "Login with email and password", @@ -853,10 +849,12 @@ "failed_to_keep_this_delete_others": "Failed to keep this asset and delete the other assets", "failed_to_load_asset": "Failed to load asset", "failed_to_load_assets": "Failed to load assets", + "failed_to_load_notifications": "Failed to load notifications", "failed_to_load_people": "Failed to load people", "failed_to_remove_product_key": "Failed to remove product key", "failed_to_stack_assets": "Failed to stack assets", "failed_to_unstack_assets": "Failed to un-stack assets", + "failed_to_update_notification_status": "Failed to update notification status", "import_path_already_exists": "This import path already exists.", "incorrect_email_or_password": "Incorrect email or password", "paths_validation_failed": "{paths, plural, one {# path} other {# paths}} failed validation", @@ -978,7 +976,7 @@ "external": "External", "external_libraries": "External Libraries", "external_network": "External network", - "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", + "external_network_sheet_info": "When not on the preferred Wi-Fi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "face_unassigned": "Unassigned", "failed": "Failed", "failed_to_load_assets": "Failed to load assets", @@ -1125,7 +1123,7 @@ "local_network": "Local network", "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", "location_permission": "Location permission", - "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", + "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current Wi-Fi network's name", "location_picker_choose_on_map": "Choose on map", "location_picker_latitude_error": "Enter a valid latitude", "location_picker_latitude_hint": "Enter your latitude here", @@ -1199,6 +1197,9 @@ "map_settings_only_show_favorites": "Show Favorite Only", "map_settings_theme_settings": "Map Theme", "map_zoom_to_see_photos": "Zoom out to see photos", + "mark_as_read": "Mark as read", + "mark_all_as_read": "Mark all as read", + "marked_all_as_read": "Marked all as read", "matches": "Matches", "media_type": "Media type", "memories": "Memories", @@ -1225,6 +1226,8 @@ "month": "Month", "monthly_title_text_date_format": "MMMM y", "more": "More", + "moved_to_archive": "Moved {count, plural, one {# asset} other {# assets}} to archive", + "moved_to_library": "Moved {count, plural, one {# asset} other {# assets}} to library", "moved_to_trash": "Moved to trash", "multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping", "multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping", @@ -1257,9 +1260,11 @@ "no_favorites_message": "Add favorites to quickly find your best pictures and videos", "no_libraries_message": "Create an external library to view your photos and videos", "no_name": "No Name", + "no_people_found": "No matching people found", "no_places": "No places", "no_results": "No results", "no_results_description": "Try a synonym or more general keyword", + "no_notifications": "No notifications", "no_shared_albums_message": "Create an album to share photos and videos with people in your network", "not_in_any_album": "Not in any album", "not_selected": "Not selected", @@ -1432,6 +1437,8 @@ "recent_searches": "Recent searches", "recently_added": "Recently added", "recently_added_page_title": "Recently Added", + "recently_taken": "Recently taken", + "recently_taken_page_title": "Recently Taken", "refresh": "Refresh", "refresh_encoded_videos": "Refresh encoded videos", "refresh_faces": "Refresh faces", @@ -1566,6 +1573,7 @@ "select_keep_all": "Select keep all", "select_library_owner": "Select library owner", "select_new_face": "Select new face", + "select_person_to_tag": "Select a person to tag", "select_photos": "Select photos", "select_trash_all": "Select trash all", "select_user_for_sharing_page_err_album": "Failed to create album", diff --git a/i18n/es.json b/i18n/es.json index 0fe78eb66f..64521c1aa8 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -14,7 +14,7 @@ "add_a_location": "Agregar ubicaciÃŗn", "add_a_name": "Agregar nombre", "add_a_title": "Agregar título", - "add_endpoint": "Add endpoint", + "add_endpoint": "AÃąadir endpoint", "add_exclusion_pattern": "Agregar patrÃŗn de exclusiÃŗn", "add_import_path": "Agregar ruta de importaciÃŗn", "add_location": "Agregar ubicaciÃŗn", @@ -39,11 +39,11 @@ "authentication_settings_disable_all": "ÂŋEstÃĄs seguro de que deseas desactivar todos los mÊtodos de inicio de sesiÃŗn? Esto desactivarÃĄ por completo el inicio de sesiÃŗn.", "authentication_settings_reenable": "Para reactivarlo, utiliza un Comando del servidor.", "background_task_job": "Tareas en segundo plano", - "backup_database": "Respaldar base de datos", - "backup_database_enable_description": "Activar respaldo de base de datos", - "backup_keep_last_amount": "Cantidad de respaldos previos a mantener", - "backup_settings": "Ajustes de respaldo", - "backup_settings_description": "Administrar configuraciÃŗn de respaldo de base de datos", + "backup_database": "Crear volcado de base de datos", + "backup_database_enable_description": "Activar volcado de base de datos", + "backup_keep_last_amount": "Cantidad de volcados previos a mantener", + "backup_settings": "Ajustes de volcado de base de datos", + "backup_settings_description": "Administrar configuraciÃŗn de volcado de base de datos. Nota: estas tareas no estÃĄn monitorizadas y no se notificarÃĄn los fallos.", "check_all": "Verificar todo", "cleanup": "Limpieza", "cleared_jobs": "Trabajos borrados para: {job}", @@ -91,9 +91,9 @@ "image_thumbnail_quality_description": "Calidad de miniatura de 1 a 100. Es mejor cuanto mÃĄs alto es el valor pero genera archivos mÃĄs grandes y puede reducir la capacidad de respuesta de la aplicaciÃŗn.", "image_thumbnail_title": "Ajustes de las miniaturas", "job_concurrency": "{job}: Procesos simultÃĄneos", - "job_created": "Trabajo creado", + "job_created": "Tarea creada", "job_not_concurrency_safe": "Esta tarea no es segura para la simultaneidad.", - "job_settings": "ConfiguraciÃŗn tareas", + "job_settings": "ConfiguraciÃŗn de tareas", "job_settings_description": "Administrar tareas simultÃĄneas", "job_status": "Estado de la tarea", "jobs_delayed": "{jobCount, plural, one {# retrasado} other {# retrasados}}", @@ -169,7 +169,7 @@ "migration_job_description": "Migrar miniaturas de archivos y caras a la estructura de carpetas mÃĄs reciente", "no_paths_added": "No se han aÃąadido carpetas", "no_pattern_added": "No se han aÃąadido patrones", - "note_apply_storage_label_previous_assets": "Nota: para aplicar una Etiqueta de Almacenamient a un elemento anteriormente cargado, lanza el", + "note_apply_storage_label_previous_assets": "Nota: para aplicar una Etiqueta de Almacenamiento a un elemento anteriormente cargado, lanza el", "note_cannot_be_changed_later": "NOTA: ÂĄNo se puede cambiar posteriormente!", "notification_email_from_address": "Desde", "notification_email_from_address_description": "DirecciÃŗn de correo electrÃŗnico del remitente, por ejemplo: \"Immich Photo Server \"", @@ -252,12 +252,12 @@ "storage_template_migration": "MigraciÃŗn de plantillas de almacenamiento", "storage_template_migration_description": "Aplicar la {template} actual a los elementos subidos previamente", "storage_template_migration_info": "La plantilla de almacenamiento convertirÃĄ todas las extensiones a minÃēscula. Los cambios en las plantillas solo se aplican a los elementos nuevos. Para aplicarlos retroactivamente a los elementos subidos previamente ejecute la {job}.", - "storage_template_migration_job": "MigraciÃŗn de la plantilla de almacenamiento", + "storage_template_migration_job": "Tarea de migraciÃŗn de la plantilla de almacenamiento", "storage_template_more_details": "Para obtener mÃĄs detalles sobre esta funciÃŗn, consulte la Plantilla de almacenamiento y sus implicaciones", "storage_template_onboarding_description": "Cuando estÃĄ habilitada, esta funciÃŗn organizarÃĄ automÃĄticamente los archivos segÃēn una plantilla definida por el usuario. Debido a problemas de estabilidad, la funciÃŗn se ha desactivado de forma predeterminada. Para obtener mÃĄs informaciÃŗn, consulte la documentaciÃŗn.", "storage_template_path_length": "Límite aproximado de la longitud de la ruta: {length, number}/{limit, number}", "storage_template_settings": "Plantilla de almacenamiento", - "storage_template_settings_description": "Administre la estructura de carpetas y el nombre de archivo del recurso cargado", + "storage_template_settings_description": "Administrar la estructura de carpetas y el nombre de archivo del recurso cargado", "storage_template_user_label": "{label} es la etiqueta de almacenamiento del usuario", "system_settings": "Ajustes del Sistema", "tag_cleanup_job": "Limpieza de etiquetas", @@ -345,7 +345,7 @@ "trash_settings": "ConfiguraciÃŗn papelera", "trash_settings_description": "Administrar la configuraciÃŗn de la papelera", "untracked_files": "Archivos sin seguimiento", - "untracked_files_description": "La aplicaciÃŗn no rastrea estos archivos. Puede ser el resultado de movimientos fallidos, cargas interrumpidas o sin procesar debido a un error", + "untracked_files_description": "La aplicaciÃŗn no rastrea estos archivos. Puede ser el resultado de movimientos fallidos, subidas interrumpidas o sin procesar debido a un error", "user_cleanup_job": "Limpieza de usuarios", "user_delete_delay": "La cuenta {user} y los archivos se programarÃĄn para su eliminaciÃŗn permanente en {delay, plural, one {# día} other {# días}}.", "user_delete_delay_settings": "Eliminar retardo", @@ -371,19 +371,23 @@ "admin_password": "ContraseÃąa del Administrador", "administration": "AdministraciÃŗn", "advanced": "Avanzada", + "advanced_settings_enable_alternate_media_filter_subtitle": "Usa esta opciÃŗn para filtrar medios durante la sincronizaciÃŗn segÃēn criterios alternativos. Intenta esto solo si tienes problemas con que la aplicaciÃŗn detecte todos los ÃĄlbumes.", + "advanced_settings_enable_alternate_media_filter_title": "[EXPERIMENTAL] Usar filtro alternativo de sincronizaciÃŗn de ÃĄlbumes del dispositivo", "advanced_settings_log_level_title": "Nivel de registro: {}", "advanced_settings_prefer_remote_subtitle": "Algunos dispositivos tardan mucho en cargar las miniaturas de los elementos encontrados en el dispositivo. Activa esta opciÃŗn para cargar imÃĄgenes remotas en su lugar.", "advanced_settings_prefer_remote_title": "Preferir imÃĄgenes remotas", "advanced_settings_proxy_headers_subtitle": "Configura headers HTTP que Immich incluirÃĄ en cada peticiÃŗn de red", - "advanced_settings_proxy_headers_title": "Proxy Headers", - "advanced_settings_self_signed_ssl_subtitle": "Omitir verificaciÃŗn del certificado SSL del servidor. Requerido para certificados autofirmados", + "advanced_settings_proxy_headers_title": "Cabeceras Proxy", + "advanced_settings_self_signed_ssl_subtitle": "Omitir verificaciÃŗn del certificado SSL del servidor. Requerido para certificados autofirmados.", "advanced_settings_self_signed_ssl_title": "Permitir certificados autofirmados", + "advanced_settings_sync_remote_deletions_subtitle": "Eliminar o restaurar automÃĄticamente un recurso en este dispositivo cuando se realice esa acciÃŗn en la web", + "advanced_settings_sync_remote_deletions_title": "Sincronizar eliminaciones remotas [EXPERIMENTAL]", "advanced_settings_tile_subtitle": "Configuraciones avanzadas del usuario", "advanced_settings_troubleshooting_subtitle": "Habilitar funciones adicionales para soluciÃŗn de problemas", "advanced_settings_troubleshooting_title": "SoluciÃŗn de problemas", "age_months": "Tiempo {months, plural, one {# mes} other {# meses}}", "age_year_months": "1 aÃąo, {months, plural, one {# mes} other {# meses}}", - "age_years": "Edad {years, plural, one {# aÃąo} other {# aÃąos}}", + "age_years": "AntigÃŧedad {years, plural, one {# aÃąo} other {# aÃąos}}", "album_added": "Álbum aÃąadido", "album_added_notification_setting_description": "Reciba una notificaciÃŗn por correo electrÃŗnico cuando lo agreguen a un ÃĄlbum compartido", "album_cover_updated": "Portada del ÃĄlbum actualizada", @@ -401,7 +405,7 @@ "album_share_no_users": "Parece que has compartido este ÃĄlbum con todos los usuarios o no tienes ningÃēn usuario con quien compartirlo.", "album_thumbnail_card_item": "1 elemento", "album_thumbnail_card_items": "{} elementos", - "album_thumbnail_card_shared": "Compartido", + "album_thumbnail_card_shared": " ¡ Compartido", "album_thumbnail_shared_by": "Compartido por {}", "album_updated": "Album actualizado", "album_updated_setting_description": "Reciba una notificaciÃŗn por correo electrÃŗnico cuando un ÃĄlbum compartido tenga nuevos archivos", @@ -411,8 +415,8 @@ "album_viewer_appbar_share_err_delete": "No ha podido eliminar el ÃĄlbum", "album_viewer_appbar_share_err_leave": "No se ha podido abandonar el ÃĄlbum", "album_viewer_appbar_share_err_remove": "Hay problemas para eliminar los elementos del ÃĄlbum", - "album_viewer_appbar_share_err_title": "Error al cambiar el título del ÃĄlbum ", - "album_viewer_appbar_share_leave": "Abandonar ÃĄlbum ", + "album_viewer_appbar_share_err_title": "Error al cambiar el título del ÃĄlbum", + "album_viewer_appbar_share_leave": "Abandonar ÃĄlbum", "album_viewer_appbar_share_to": "Compartir Con", "album_viewer_page_share_add_users": "Agregar usuarios", "album_with_link_access": "Permita que cualquier persona con el enlace vea fotos y personas en este ÃĄlbum.", @@ -425,7 +429,7 @@ "allow_dark_mode": "Permitir modo oscuro", "allow_edits": "Permitir ediciÃŗn", "allow_public_user_to_download": "Permitir descargar al usuario pÃēblico", - "allow_public_user_to_upload": "Permitir cargar al usuario publico", + "allow_public_user_to_upload": "Permitir subir al usuario publico", "alt_text_qr_code": "CÃŗdigo QR", "anti_clockwise": "En sentido antihorario", "api_key": "Clave API", @@ -477,8 +481,8 @@ "assets_added_to_album_count": "AÃąadido {count, plural, one {# asset} other {# assets}} al ÃĄlbum", "assets_added_to_name_count": "AÃąadido {count, plural, one {# asset} other {# assets}} a {hasName, select, true {{name}} other {new album}}", "assets_count": "{count, plural, one {# activo} other {# activos}}", - "assets_deleted_permanently": "\n{} elementos(s) eliminado(s) permanentemente", - "assets_deleted_permanently_from_server": "{} asset(s) deleted permanently from the Immich server", + "assets_deleted_permanently": "{} elementos(s) eliminado(s) permanentemente", + "assets_deleted_permanently_from_server": "{} recurso(s) eliminado(s) de forma permanente del servidor de Immich", "assets_moved_to_trash_count": "{count, plural, one {# elemento movido} other {# elementos movidos}} a la papelera", "assets_permanently_deleted_count": "Eliminado permanentemente {count, plural, one {# elemento} other {# elementos}}", "assets_removed_count": "Eliminado {count, plural, one {# elemento} other {# elementos}}", @@ -488,15 +492,15 @@ "assets_restored_successfully": "{} elemento(s) restaurado(s) exitosamente", "assets_trashed": "{} elemento(s) eliminado(s)", "assets_trashed_count": "Borrado {count, plural, one {# elemento} other {# elementos}}", - "assets_trashed_from_server": "{} elemento(s) movido a la papelera en Immich", + "assets_trashed_from_server": "{} recurso(s) enviado(s) a la papelera desde el servidor de Immich", "assets_were_part_of_album_count": "{count, plural, one {Asset was} other {Assets were}} ya forma parte del ÃĄlbum", "authorized_devices": "Dispositivos Autorizados", - "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", - "automatic_endpoint_switching_title": "Automatic URL switching", + "automatic_endpoint_switching_subtitle": "Conectarse localmente a travÊs de la Wi-Fi designada cuando estÊ disponible y usar conexiones alternativas en otros lugares", + "automatic_endpoint_switching_title": "Cambio automÃĄtico de URL", "back": "AtrÃĄs", "back_close_deselect": "AtrÃĄs, cerrar o anular la selecciÃŗn", - "background_location_permission": "Background location permission", - "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", + "background_location_permission": "Permiso de ubicaciÃŗn en segundo plano", + "background_location_permission_content": "Para poder cambiar de red mientras se ejecuta en segundo plano, Immich debe tener *siempre* acceso a la ubicaciÃŗn precisa para que la aplicaciÃŗn pueda leer el nombre de la red Wi-Fi", "backup_album_selection_page_albums_device": "Álbumes en el dispositivo ({})", "backup_album_selection_page_albums_tap": "Toque para incluir, doble toque para excluir", "backup_album_selection_page_assets_scatter": "Los elementos pueden dispersarse en varios ÃĄlbumes. De este modo, los ÃĄlbumes pueden ser incluidos o excluidos durante el proceso de copia de seguridad.", @@ -504,13 +508,13 @@ "backup_album_selection_page_selection_info": "InformaciÃŗn sobre la SelecciÃŗn", "backup_album_selection_page_total_assets": "Total de elementos Ãēnicos", "backup_all": "Todos", - "backup_background_service_backup_failed_message": "Error al copiar elementos. Reintentando...", - "backup_background_service_connection_failed_message": "Error al conectar con el servidor. Reintentando...", - "backup_background_service_current_upload_notification": "Cargando {}", - "backup_background_service_default_notification": "Verificando si hay nuevos elementos", + "backup_background_service_backup_failed_message": "Error al copiar elementos. Reintentandoâ€Ļ", + "backup_background_service_connection_failed_message": "Error al conectar con el servidor. Reintentandoâ€Ļ", + "backup_background_service_current_upload_notification": "Subiendo {}", + "backup_background_service_default_notification": "Comprobando nuevos elementosâ€Ļ", "backup_background_service_error_title": "Error de copia de seguridad", - "backup_background_service_in_progress_notification": "Creando copia de seguridad de tus elementos...", - "backup_background_service_upload_failure_notification": "Error al cargar {}", + "backup_background_service_in_progress_notification": "Creando copia de seguridad de tus elementosâ€Ļ", + "backup_background_service_upload_failure_notification": "Error al subir {}", "backup_controller_page_albums": "Álbumes de copia de seguridad", "backup_controller_page_background_app_refresh_disabled_content": "Activa la actualizaciÃŗn en segundo plano de la aplicaciÃŗn en ConfiguraciÃŗn > General > ActualizaciÃŗn en segundo plano para usar la copia de seguridad en segundo plano.", "backup_controller_page_background_app_refresh_disabled_title": "ActualizaciÃŗn en segundo plano desactivada", @@ -521,19 +525,19 @@ "backup_controller_page_background_battery_info_title": "Optimizaciones de batería", "backup_controller_page_background_charging": "Solo mientras se carga", "backup_controller_page_background_configure_error": "Error al configurar el servicio en segundo plano", - "backup_controller_page_background_delay": "Retraso en la copia de seguridad de nuevos elementos: {}", - "backup_controller_page_background_description": "Activa el servicio en segundo plano para copiar automÃĄticamente cualquier nuevos elementos sin necesidad de abrir la aplicaciÃŗn.", + "backup_controller_page_background_delay": "Retrasar la copia de seguridad de los nuevos elementos: {}", + "backup_controller_page_background_description": "Activa el servicio en segundo plano para copiar automÃĄticamente cualquier nuevos elementos sin necesidad de abrir la aplicaciÃŗn", "backup_controller_page_background_is_off": "La copia de seguridad en segundo plano automÃĄtica estÃĄ desactivada", "backup_controller_page_background_is_on": "La copia de seguridad en segundo plano automÃĄtica estÃĄ activada", "backup_controller_page_background_turn_off": "Desactivar el servicio en segundo plano", "backup_controller_page_background_turn_on": "Activar el servicio en segundo plano", "backup_controller_page_background_wifi": "Solo en WiFi", "backup_controller_page_backup": "Copia de Seguridad", - "backup_controller_page_backup_selected": "Seleccionado:", + "backup_controller_page_backup_selected": "Seleccionado: ", "backup_controller_page_backup_sub": "Fotos y videos respaldados", "backup_controller_page_created": "Creado el: {}", - "backup_controller_page_desc_backup": "Active la copia de seguridad para cargar automÃĄticamente los nuevos elementos al servidor.", - "backup_controller_page_excluded": "Excluido:", + "backup_controller_page_desc_backup": "Active la copia de seguridad para subir automÃĄticamente los nuevos elementos al servidor cuando se abre la aplicaciÃŗn.", + "backup_controller_page_excluded": "Excluido: ", "backup_controller_page_failed": "Fallidos ({})", "backup_controller_page_filename": "Nombre del archivo: {} [{}]", "backup_controller_page_id": "ID: {}", @@ -550,11 +554,11 @@ "backup_controller_page_total_sub": "Todas las fotos y vídeos Ãēnicos de los ÃĄlbumes seleccionados", "backup_controller_page_turn_off": "Apagar la copia de seguridad", "backup_controller_page_turn_on": "Activar la copia de seguridad", - "backup_controller_page_uploading_file_info": "Cargando informaciÃŗn del archivo", + "backup_controller_page_uploading_file_info": "Subiendo informaciÃŗn del archivo", "backup_err_only_album": "No se puede eliminar el Ãēnico ÃĄlbum", "backup_info_card_assets": "elementos", "backup_manual_cancelled": "Cancelado", - "backup_manual_in_progress": "Subida en progreso. Espere", + "backup_manual_in_progress": "Subida ya en progreso. Vuelve a intentarlo mÃĄs tarde", "backup_manual_success": "Éxito", "backup_manual_title": "Estado de la subida", "backup_options_page_title": "Opciones de Copia de Seguridad", @@ -593,12 +597,12 @@ "camera_model": "Modelo de cÃĄmara", "cancel": "Cancelar", "cancel_search": "Cancelar bÃēsqueda", - "canceled": "Canceled", + "canceled": "Cancelado", "cannot_merge_people": "No se pueden fusionar personas", "cannot_undo_this_action": "ÂĄNo puedes deshacer esta acciÃŗn!", "cannot_update_the_description": "No se puede actualizar la descripciÃŗn", "change_date": "Cambiar fecha", - "change_display_order": "Change display order", + "change_display_order": "Cambiar orden de visualizaciÃŗn", "change_expiration_time": "Cambiar fecha de caducidad", "change_location": "Cambiar ubicaciÃŗn", "change_name": "Cambiar nombre", @@ -613,9 +617,9 @@ "change_your_password": "Cambia tu contraseÃąa", "changed_visibility_successfully": "Visibilidad cambiada correctamente", "check_all": "Comprobar todo", - "check_corrupt_asset_backup": "Check for corrupt asset backups", - "check_corrupt_asset_backup_button": "Perform check", - "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", + "check_corrupt_asset_backup": "Comprobar copias de seguridad de archivos corruptos", + "check_corrupt_asset_backup_button": "Realizar comprobaciÃŗn", + "check_corrupt_asset_backup_description": "Ejecutar esta comprobaciÃŗn solo por Wi-Fi y una vez que todos los archivos hayan sido respaldados. El procedimiento puede tardar unos minutos.", "check_logs": "Comprobar Registros", "choose_matching_people_to_merge": "Elija personas similares para fusionar", "city": "Ciudad", @@ -627,11 +631,11 @@ "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Introduzca contraseÃąa", "client_cert_import": "Importar", - "client_cert_import_success_msg": "Client certificate is imported", - "client_cert_invalid_msg": "Invalid certificate file or wrong password", - "client_cert_remove_msg": "Client certificate is removed", - "client_cert_subtitle": "Supports PKCS12 (.p12, .pfx) format only. Certificate Import/Remove is available only before login", - "client_cert_title": "SSL Client Certificate", + "client_cert_import_success_msg": "El certificado de cliente estÃĄ importado", + "client_cert_invalid_msg": "Archivo de certificado no vÃĄlido o contraseÃąa incorrecta", + "client_cert_remove_msg": "El certificado de cliente se ha eliminado", + "client_cert_subtitle": "Solo se admite el formato PKCS12 (.p12, .pfx). La importaciÃŗn/eliminaciÃŗn de certificados solo estÃĄ disponible antes de iniciar sesiÃŗn", + "client_cert_title": "Certificado de cliente SSL", "clockwise": "En el sentido de las agujas del reloj", "close": "Cerrar", "collapse": "Agrupar", @@ -644,7 +648,7 @@ "comments_are_disabled": "Los comentarios estÃĄn deshabilitados", "common_create_new_album": "Crear nuevo ÃĄlbum", "common_server_error": "Por favor, verifica tu conexiÃŗn de red, asegÃērate de que el servidor estÊ accesible y las versiones de la aplicaciÃŗn y del servidor sean compatibles.", - "completed": "Completed", + "completed": "Completado", "confirm": "Confirmar", "confirm_admin_password": "Confirmar ContraseÃąa de Administrador", "confirm_delete_face": "ÂŋEstÃĄs seguro que deseas eliminar la cara de {name} del archivo?", @@ -660,7 +664,7 @@ "control_bottom_app_bar_delete_from_local": "Borrar del dispositivo", "control_bottom_app_bar_edit_location": "Editar ubicaciÃŗn", "control_bottom_app_bar_edit_time": "Editar fecha y hora", - "control_bottom_app_bar_share_link": "Share Link", + "control_bottom_app_bar_share_link": "Enlace para compartir", "control_bottom_app_bar_share_to": "Enviar", "control_bottom_app_bar_trash_from_immich": "Mover a la papelera", "copied_image_to_clipboard": "Imagen copiada al portapapeles.", @@ -695,7 +699,7 @@ "crop": "Recortar", "curated_object_page_title": "Objetos", "current_device": "Dispositivo actual", - "current_server_address": "Current server address", + "current_server_address": "DirecciÃŗn actual del servidor", "custom_locale": "ConfiguraciÃŗn regional personalizada", "custom_locale_description": "Formatear fechas y nÃēmeros segÃēn el idioma y la regiÃŗn", "daily_title_text_date": "E dd, MMM", @@ -746,7 +750,7 @@ "direction": "DirecciÃŗn", "disabled": "Deshabilitado", "disallow_edits": "Bloquear ediciÃŗn", - "discord": "", + "discord": "Discord", "discover": "Descubrir", "dismiss_all_errors": "Descartar todos los errores", "dismiss_error": "Descartar error", @@ -763,7 +767,7 @@ "download_enqueue": "Descarga en cola", "download_error": "Error al descargar", "download_failed": "Descarga fallida", - "download_filename": "Archivo: {}", + "download_filename": "archivo: {}", "download_finished": "Descarga completada", "download_include_embedded_motion_videos": "Vídeos incrustados", "download_include_embedded_motion_videos_description": "Incluir vídeos incrustados en fotografías en movimiento como un archivo separado", @@ -807,16 +811,16 @@ "editor_crop_tool_h2_aspect_ratios": "Proporciones del aspecto", "editor_crop_tool_h2_rotation": "RotaciÃŗn", "email": "Correo", - "empty_folder": "This folder is empty", + "empty_folder": "Esta carpeta estÃĄ vacía", "empty_trash": "Vaciar papelera", "empty_trash_confirmation": "ÂŋEstÃĄs seguro de que quieres vaciar la papelera? Esto eliminarÃĄ permanentemente todos los archivos de la basura de Immich.\nÂĄNo puedes deshacer esta acciÃŗn!", "enable": "Habilitar", "enabled": "Habilitado", "end_date": "Fecha final", - "enqueued": "Enqueued", + "enqueued": "AÃąadido a la cola", "enter_wifi_name": "Enter WiFi name", "error": "Error", - "error_change_sort_album": "Failed to change album sort order", + "error_change_sort_album": "No se pudo cambiar el orden de visualizaciÃŗn del ÃĄlbum", "error_delete_face": "Error al eliminar la cara del archivo", "error_loading_image": "Error al cargar la imagen", "error_saving_image": "Error: {}", @@ -953,15 +957,15 @@ "exif_bottom_sheet_location": "UBICACIÓN", "exif_bottom_sheet_people": "PERSONAS", "exif_bottom_sheet_person_add_person": "AÃąadir nombre", - "exif_bottom_sheet_person_age": "Age {}", - "exif_bottom_sheet_person_age_months": "Age {} months", - "exif_bottom_sheet_person_age_year_months": "Age 1 year, {} months", - "exif_bottom_sheet_person_age_years": "Age {}", + "exif_bottom_sheet_person_age": "AntigÃŧedad {}", + "exif_bottom_sheet_person_age_months": "AntigÃŧedad {} meses", + "exif_bottom_sheet_person_age_year_months": "AntigÃŧedad 1 aÃąo, {} meses", + "exif_bottom_sheet_person_age_years": "AntigÃŧedad {}", "exit_slideshow": "Salir de la presentaciÃŗn", "expand_all": "Expandir todo", "experimental_settings_new_asset_list_subtitle": "Trabajo en progreso", "experimental_settings_new_asset_list_title": "Habilitar cuadrícula fotogrÃĄfica experimental", - "experimental_settings_subtitle": "Úsalo bajo tu responsabilidad", + "experimental_settings_subtitle": "ÂĄÃšsalo bajo tu propia responsabilidad!", "experimental_settings_title": "Experimental", "expire_after": "Expirar despuÊs de", "expired": "Caducado", @@ -973,12 +977,12 @@ "extension": "Extension", "external": "Externo", "external_libraries": "Bibliotecas Externas", - "external_network": "External network", - "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", + "external_network": "Red externa", + "external_network_sheet_info": "Cuando no estÊs conectado a la red Wi-Fi preferida, la aplicaciÃŗn se conectarÃĄ al servidor utilizando la primera de las siguientes URLs a la que pueda acceder, comenzando desde la parte superior de la lista hacia abajo", "face_unassigned": "Sin asignar", - "failed": "Failed", + "failed": "Fallido", "failed_to_load_assets": "Error al cargar los activos", - "failed_to_load_folder": "Failed to load folder", + "failed_to_load_folder": "No se pudo cargar la carpeta", "favorite": "Favorito", "favorite_or_unfavorite_photo": "Foto favorita o no favorita", "favorites": "Favoritos", @@ -992,21 +996,22 @@ "filetype": "Tipo de archivo", "filter": "Filtrar", "filter_people": "Filtrar personas", + "filter_places": "Filtrar lugares", "find_them_fast": "EncuÊntrelos rÃĄpidamente por nombre con la bÃēsqueda", "fix_incorrect_match": "Corregir coincidencia incorrecta", - "folder": "Folder", - "folder_not_found": "Folder not found", + "folder": "Carpeta", + "folder_not_found": "Carpeta no encontrada", "folders": "Carpetas", "folders_feature_description": "Explorar la vista de carpetas para las fotos y los videos en el sistema de archivos", "forward": "Reenviar", "general": "General", "get_help": "Solicitar ayuda", - "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "get_wifiname_error": "No se pudo obtener el nombre de la red Wi-Fi. AsegÃērate de haber concedido los permisos necesarios y de estar conectado a una red Wi-Fi", "getting_started": "Comenzamos", "go_back": "Volver atrÃĄs", "go_to_folder": "Ir al directorio", "go_to_search": "Ir a bÃēsqueda", - "grant_permission": "Grant permission", + "grant_permission": "Conceder permiso", "group_albums_by": "Agrupar albums por...", "group_country": "Agrupar por país", "group_no": "Sin agrupaciÃŗn", @@ -1031,7 +1036,7 @@ "hide_unnamed_people": "Ocultar personas anÃŗnimas", "home_page_add_to_album_conflicts": "{added} elementos agregados al ÃĄlbum {album}.{failed} elementos ya existen en el ÃĄlbum.", "home_page_add_to_album_err_local": "AÃēn no se pueden agregar elementos locales a ÃĄlbumes, omitiendo", - "home_page_add_to_album_success": "{added} elementos agregados al ÃĄlbum {album}. ", + "home_page_add_to_album_success": "Se aÃąadieron {added} elementos al ÃĄlbum {album}.", "home_page_album_err_partner": "AÃēn no se pueden agregar elementos a un ÃĄlbum de un compaÃąero, omitiendo", "home_page_archive_err_local": "Los elementos locales no pueden ser archivados, omitiendo", "home_page_archive_err_partner": "No se pueden archivar elementos de un compaÃąero, omitiendo", @@ -1040,7 +1045,7 @@ "home_page_delete_remote_err_local": "Elementos locales en la selecciÃŗn de eliminaciÃŗn remota, omitiendo", "home_page_favorite_err_local": "AÃēn no se pueden archivar elementos locales, omitiendo", "home_page_favorite_err_partner": "AÃēn no se pueden marcar elementos de compaÃąeros como favoritos, omitiendo", - "home_page_first_time_notice": "Si esta es la primera vez que usas la app, por favor, asegÃērate de elegir un ÃĄlbum de respaldo para que la línea de tiempo pueda cargar fotos y videos en los ÃĄlbumes.", + "home_page_first_time_notice": "Si es la primera vez que usas la aplicaciÃŗn, asegÃērate de elegir un ÃĄlbum de copia de seguridad para que la línea de tiempo pueda mostrar fotos y vídeos en Êl", "home_page_share_err_local": "No se pueden compartir elementos locales a travÊs de un enlace, omitiendo", "home_page_upload_err_limit": "Solo se pueden subir 30 elementos simultÃĄneamente, omitiendo", "host": "Host", @@ -1118,9 +1123,9 @@ "loading": "Cargando", "loading_search_results_failed": "Error al cargar los resultados de la bÃēsqueda", "local_network": "Local network", - "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", - "location_permission": "Location permission", - "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", + "local_network_sheet_info": "La aplicaciÃŗn se conectarÃĄ al servidor a travÊs de esta URL cuando utilice la red Wi-Fi especificada", + "location_permission": "Permiso de ubicaciÃŗn", + "location_permission_content": "Para usar la funciÃŗn de cambio automÃĄtico, Immich necesita permiso de ubicaciÃŗn precisa para poder leer el nombre de la red Wi-Fi actual", "location_picker_choose_on_map": "Elegir en el mapa", "location_picker_latitude_error": "Introduce una latitud vÃĄlida", "location_picker_latitude_hint": "Introduce tu latitud aquí", @@ -1145,7 +1150,7 @@ "login_form_failed_get_oauth_server_config": "Error al iniciar sesiÃŗn con OAuth, verifica la URL del servidor", "login_form_failed_get_oauth_server_disable": "La funciÃŗn de OAuth no estÃĄ disponible en este servidor", "login_form_failed_login": "Error al iniciar sesiÃŗn, comprueba la URL del servidor, el correo electrÃŗnico y la contraseÃąa", - "login_form_handshake_exception": "Hubo un error de verificaciÃŗn del certificado del servidor. Activa el soporte para certificados autofirmados en las preferencias si estÃĄs usando un certificado autofirmado", + "login_form_handshake_exception": "Hubo una excepciÃŗn de handshake con el servidor. Activa la compatibilidad con certificados autofirmados en la configuraciÃŗn si estÃĄs utilizando un certificado autofirmado.", "login_form_password_hint": "contraseÃąa", "login_form_save_login": "Mantener la sesiÃŗn iniciada", "login_form_server_empty": "Agrega la URL del servidor.", @@ -1222,7 +1227,7 @@ "more": "Mas", "moved_to_trash": "Movido a la papelera", "multiselect_grid_edit_date_time_err_read_only": "No se puede cambiar la fecha del archivo(s) de solo lectura, omitiendo", - "multiselect_grid_edit_gps_err_read_only": "No se puede cambiar la localizaciÃŗn de archivos de solo lectura. Saltando.", + "multiselect_grid_edit_gps_err_read_only": "No se puede editar la ubicaciÃŗn de activos de solo lectura, omitiendo", "mute_memories": "Silenciar Recuerdos", "my_albums": "Mis albums", "name": "Nombre", @@ -1257,8 +1262,8 @@ "no_results_description": "Pruebe con un sinÃŗnimo o una palabra clave mÃĄs general", "no_shared_albums_message": "Crea un ÃĄlbum para compartir fotos y vídeos con personas de tu red", "not_in_any_album": "Sin ÃĄlbum", - "not_selected": "Not selected", - "note_apply_storage_label_to_previously_uploaded assets": "Nota: Para aplicar la etiqueta de almacenamiento a los archivos cargados previamente, ejecute el", + "not_selected": "No seleccionado", + "note_apply_storage_label_to_previously_uploaded assets": "Nota: Para aplicar la etiqueta de almacenamiento a los archivos subidos previamente, ejecute el", "notes": "Notas", "notification_permission_dialog_content": "Para activar las notificaciones, ve a ConfiguraciÃŗn y selecciona permitir.", "notification_permission_list_tile_content": "Concede permiso para habilitar las notificaciones.", @@ -1282,6 +1287,7 @@ "onboarding_welcome_user": "Bienvenido, {user}", "online": "En línea", "only_favorites": "Solo favoritos", + "open": "Abierto", "open_in_map_view": "Abrir en la vista del mapa", "open_in_openstreetmap": "Abrir en OpenStreetMap", "open_the_search_filters": "Abre los filtros de bÃēsqueda", @@ -1302,10 +1308,10 @@ "partner_list_view_all": "Ver todas", "partner_page_empty_message": "Tus fotos aÃēn no se han compartido con ningÃēn compaÃąero.", "partner_page_no_more_users": "No hay mÃĄs usuarios para agregar", - "partner_page_partner_add_failed": "CompaÃąero no pudo ser agregado ", + "partner_page_partner_add_failed": "No se pudo aÃąadir el socio", "partner_page_select_partner": "Seleccionar compaÃąero", "partner_page_shared_to_title": "Compartido con", - "partner_page_stop_sharing_content": "{} ya no podrÃĄ acceder a tus fotos", + "partner_page_stop_sharing_content": "{} ya no podrÃĄ acceder a tus fotos.", "partner_sharing": "Compartir con invitados", "partners": "Invitados", "password": "ContraseÃąa", @@ -1426,6 +1432,8 @@ "recent_searches": "BÃēsquedas recientes", "recently_added": "AÃąadidos recientemente", "recently_added_page_title": "ReciÊn Agregadas", + "recently_taken": "Recientemente tomado", + "recently_taken_page_title": "Recientemente Tomado", "refresh": "Actualizar", "refresh_encoded_videos": "Recargar los vídeos codificados", "refresh_faces": "Actualizar caras", @@ -1509,8 +1517,8 @@ "search_filter_date_interval": "{start} al {end}", "search_filter_date_title": "Selecciona un intervalo de fechas", "search_filter_display_option_not_in_album": "No en ÃĄlbum", - "search_filter_display_options": "Display Options", - "search_filter_filename": "Search by file name", + "search_filter_display_options": "Opciones de visualizaciÃŗn", + "search_filter_filename": "Buscar por nombre de archivo", "search_filter_location": "UbicaciÃŗn", "search_filter_location_title": "Seleccionar una ubicaciÃŗn", "search_filter_media_type": "Tipo de archivo", @@ -1518,10 +1526,10 @@ "search_filter_people_title": "Seleccionar personas", "search_for": "Buscar", "search_for_existing_person": "Buscar persona existente", - "search_no_more_result": "No more results", + "search_no_more_result": "No hay mÃĄs resultados", "search_no_people": "Ninguna persona", "search_no_people_named": "Ninguna persona llamada \"{name}\"", - "search_no_result": "No results found, try a different search term or combination", + "search_no_result": "No se encontraron resultados, prueba con un tÊrmino o combinaciÃŗn de bÃēsqueda diferente", "search_options": "Opciones de bÃēsqueda", "search_page_categories": "Categorías", "search_page_motion_photos": "Foto en Movimiento", @@ -1567,7 +1575,7 @@ "selected_count": "{count, plural, one {# seleccionado} other {# seleccionados}}", "send_message": "Enviar mensaje", "send_welcome_email": "Enviar correo de bienvenida", - "server_endpoint": "Server Endpoint", + "server_endpoint": "Punto final del servidor", "server_info_box_app_version": "VersiÃŗn de la AplicaciÃŗn", "server_info_box_server_url": "URL del servidor", "server_offline": "Servidor desconectado", @@ -1602,14 +1610,14 @@ "setting_notifications_total_progress_subtitle": "Progreso general de subida (elementos completados/total)", "setting_notifications_total_progress_title": "Mostrar progreso total de copia de seguridad en segundo plano", "setting_video_viewer_looping_title": "Bucle", - "setting_video_viewer_original_video_subtitle": "When streaming a video from the server, play the original even when a transcode is available. May lead to buffering. Videos available locally are played in original quality regardless of this setting.", - "setting_video_viewer_original_video_title": "Force original video", + "setting_video_viewer_original_video_subtitle": "Al reproducir un video en streaming desde el servidor, reproducir el original incluso cuando haya una transcodificaciÃŗn disponible. Puede causar buffering. Los videos disponibles localmente se reproducen en calidad original independientemente de esta configuraciÃŗn.", + "setting_video_viewer_original_video_title": "Forzar vídeo original", "settings": "Ajustes", "settings_require_restart": "Por favor, reinicia Immich para aplicar este ajuste", "settings_saved": "Ajustes guardados", "share": "Compartir", "share_add_photos": "Agregar fotos", - "share_assets_selected": "{} seleccionados", + "share_assets_selected": "{} seleccionado(s)", "share_dialog_preparing": "Preparando...", "shared": "Compartido", "shared_album_activities_input_disable": "Los comentarios estÃĄn deshabilitados", @@ -1623,7 +1631,7 @@ "shared_by_user": "Compartido por {user}", "shared_by_you": "Compartido por ti", "shared_from_partner": "Fotos de {partner}", - "shared_intent_upload_button_progress_text": "{} / {} Uploaded", + "shared_intent_upload_button_progress_text": "{} / {} Cargado(s)", "shared_link_app_bar_title": "Enlaces compartidos", "shared_link_clipboard_copied_massage": "Copiado al portapapeles", "shared_link_clipboard_text": "Enlace: {}\nContraseÃąa: {}", @@ -1734,7 +1742,7 @@ "sync": "Sincronizar", "sync_albums": "Sincronizar ÃĄlbumes", "sync_albums_manual_subtitle": "Sincroniza todos los videos y fotos subidos con los ÃĄlbumes seleccionados a respaldar", - "sync_upload_album_setting_subtitle": "Create and upload your photos and videos to the selected albums on Immich", + "sync_upload_album_setting_subtitle": "Crea y sube tus fotos y videos a los ÃĄlbumes seleccionados en Immich", "tag": "Etiqueta", "tag_assets": "Etiquetar activos", "tag_created": "Etiqueta creada: {tag}", @@ -1750,12 +1758,12 @@ "theme_selection_description": "Establece el tema automÃĄticamente como \"claro\" u \"oscuro\" segÃēn las preferencias del sistema/navegador", "theme_setting_asset_list_storage_indicator_title": "Mostrar indicador de almacenamiento en las miniaturas de los archivos", "theme_setting_asset_list_tiles_per_row_title": "NÃēmero de elementos por fila ({})", - "theme_setting_colorful_interface_subtitle": "Apply primary color to background surfaces.", - "theme_setting_colorful_interface_title": "Colorful interface", + "theme_setting_colorful_interface_subtitle": "Aplicar el color primario a las superficies de fondo.", + "theme_setting_colorful_interface_title": "Color de Interfaz", "theme_setting_image_viewer_quality_subtitle": "Ajustar la calidad del visor de detalles de imÃĄgenes", "theme_setting_image_viewer_quality_title": "Calidad del visor de imÃĄgenes", - "theme_setting_primary_color_subtitle": "Pick a color for primary actions and accents.", - "theme_setting_primary_color_title": "Primary color", + "theme_setting_primary_color_subtitle": "Elige un color para las acciones principales y los acentos.", + "theme_setting_primary_color_title": "Color primario", "theme_setting_system_primary_color_title": "Usar color del sistema", "theme_setting_system_theme_switch": "AutomÃĄtico (seguir ajuste del sistema)", "theme_setting_theme_subtitle": "Elige la configuraciÃŗn del tema de la aplicaciÃŗn", @@ -1784,7 +1792,7 @@ "trash_no_results_message": "Las fotos y videos que se envíen a la papelera aparecerÃĄn aquí.", "trash_page_delete_all": "Eliminar todos", "trash_page_empty_trash_dialog_content": "ÂŋEstÃĄ seguro que quiere eliminar los elementos? Estos elementos serÃĄn eliminados de Immich permanentemente", - "trash_page_info": "Los archivos en la papelera serÃĄn eliminados automÃĄticamente despuÊs de {} días", + "trash_page_info": "Los archivos en la papelera serÃĄn eliminados automÃĄticamente de forma permanente despuÊs de {} días", "trash_page_no_assets": "No hay elementos en la papelera", "trash_page_restore_all": "Restaurar todos", "trash_page_select_assets_btn": "Seleccionar elementos", @@ -1812,25 +1820,25 @@ "unstack": "Desapilar", "unstacked_assets_count": "Desapilado(s) {count, plural, one {# elemento} other {# elementos}}", "untracked_files": "Archivos no monitorizados", - "untracked_files_decription": "Estos archivos no estÃĄn siendo monitorizados por la aplicaciÃŗn. Es posible que sean resultado de errores al moverlos, cargas interrumpidas o por un fallo de la aplicaciÃŗn", + "untracked_files_decription": "Estos archivos no estÃĄn siendo monitorizados por la aplicaciÃŗn. Es posible que sean resultado de errores al moverlos, subidas interrumpidas o por un fallo de la aplicaciÃŗn", "up_next": "A continuaciÃŗn", "updated_password": "ContraseÃąa actualizada", "upload": "Subir", - "upload_concurrency": "Cargas simultÃĄneas", + "upload_concurrency": "Subidas simultÃĄneas", "upload_dialog_info": "ÂŋQuieres hacer una copia de seguridad al servidor de los elementos seleccionados?", "upload_dialog_title": "Subir elementos", - "upload_errors": "Carga completada con {count, plural, one {# error} other {# errores}}, actualice la pÃĄgina para ver los nuevos recursos de carga.", + "upload_errors": "Subida completada con {count, plural, one {# error} other {# errores}}, actualice la pÃĄgina para ver los nuevos recursos de la subida.", "upload_progress": "Restante {remaining, number} - Procesado {processed, number}/{total, number}", "upload_skipped_duplicates": "Saltado {count, plural, one {# duplicate asset} other {# duplicate assets}}", "upload_status_duplicates": "Duplicados", "upload_status_errors": "Errores", "upload_status_uploaded": "Subido", - "upload_success": "Carga realizada correctamente, actualice la pÃĄgina para ver los nuevos recursos de carga.", - "upload_to_immich": "Upload to Immich ({})", - "uploading": "Uploading", + "upload_success": "Subida realizada correctamente, actualice la pÃĄgina para ver los nuevos recursos de subida.", + "upload_to_immich": "Subir a Immich ({})", + "uploading": "Subiendo", "url": "URL", "usage": "Uso", - "use_current_connection": "use current connection", + "use_current_connection": "Usar conexiÃŗn actual", "use_custom_date_range": "Usa un intervalo de fechas personalizado", "user": "Usuario", "user_id": "ID de usuario", @@ -1845,7 +1853,7 @@ "users": "Usuarios", "utilities": "Utilidades", "validate": "Validar", - "validate_endpoint_error": "Please enter a valid URL", + "validate_endpoint_error": "Por favor, introduce una URL vÃĄlida", "variables": "Variables", "version": "VersiÃŗn", "version_announcement_closing": "Tu amigo, Alex", @@ -1888,6 +1896,6 @@ "years_ago": "Hace {years, plural, one {# aÃąo} other {# aÃąos}}", "yes": "Sí", "you_dont_have_any_shared_links": "No tienes ningÃēn enlace compartido", - "your_wifi_name": "Your WiFi name", + "your_wifi_name": "El nombre de tu WiFi", "zoom_image": "Acercar Imagen" } diff --git a/i18n/et.json b/i18n/et.json index 673d2ea63a..98b829bc97 100644 --- a/i18n/et.json +++ b/i18n/et.json @@ -4,6 +4,7 @@ "account_settings": "Konto seaded", "acknowledge": "Sain aru", "action": "Tegevus", + "action_common_update": "Uuenda", "actions": "Tegevused", "active": "Aktiivne", "activity": "Aktiivsus", @@ -13,6 +14,7 @@ "add_a_location": "Lisa asukoht", "add_a_name": "Lisa nimi", "add_a_title": "Lisa pealkiri", + "add_endpoint": "Lisa lÃĩpp-punkt", "add_exclusion_pattern": "Lisa välistamismuster", "add_import_path": "Lisa imporditee", "add_location": "Lisa asukoht", @@ -22,6 +24,8 @@ "add_photos": "Lisa fotosid", "add_to": "Lisa kohtaâ€Ļ", "add_to_album": "Lisa albumisse", + "add_to_album_bottom_sheet_added": "Lisatud albumisse {album}", + "add_to_album_bottom_sheet_already_exists": "On juba albumis {album}", "add_to_shared_album": "Lisa jagatud albumisse", "add_url": "Lisa URL", "added_to_archive": "Lisatud arhiivi", @@ -35,11 +39,11 @@ "authentication_settings_disable_all": "Kas oled kindel, et soovid kÃĩik sisselogimismeetodid välja lÃŧlitada? Sisselogimine lÃŧlitatakse täielikult välja.", "authentication_settings_reenable": "Et taas lubada, kasuta serveri käsku.", "background_task_job": "Tausttegumid", - "backup_database": "Varunda andmebaas", - "backup_database_enable_description": "Luba andmebaasi varundamine", - "backup_keep_last_amount": "Varukoopiate arv, mida alles hoida", - "backup_settings": "Varundamise seaded", - "backup_settings_description": "Halda andmebaasi varundamise seadeid", + "backup_database": "Loo andmebaasi tÃĩmmis", + "backup_database_enable_description": "Luba andmebaasi tÃĩmmised", + "backup_keep_last_amount": "Eelmiste tÃĩmmiste arv, mida alles hoida", + "backup_settings": "Andmebaasi tÃĩmmiste seaded", + "backup_settings_description": "Halda andmebaasi tÃĩmmiste seadeid. Märkus: Neid tÃļÃļteid ei jälgita ning ebaÃĩnnestumisest ei hoiatata.", "check_all": "Märgi kÃĩik", "cleanup": "Koristus", "cleared_jobs": "TÃļÃļted eemaldatud: {job}", @@ -367,6 +371,10 @@ "admin_password": "Administraatori parool", "administration": "Administratsioon", "advanced": "Täpsemad valikud", + "advanced_settings_log_level_title": "Logimistase: {}", + "advanced_settings_proxy_headers_title": "Vaheserveri päised", + "advanced_settings_self_signed_ssl_title": "Luba endasigneeritud SSL-sertifikaadid", + "advanced_settings_troubleshooting_title": "TÃĩrkeotsing", "age_months": "Vanus {months, plural, one {# kuu} other {# kuud}}", "age_year_months": "Vanus 1 aasta, {months, plural, one {# kuu} other {# kuud}}", "age_years": "{years, plural, other {Vanus #}}", @@ -375,6 +383,8 @@ "album_cover_updated": "Albumi kaanepilt muudetud", "album_delete_confirmation": "Kas oled kindel, et soovid albumi {album} kustutada?", "album_delete_confirmation_description": "Kui see album on jagatud, ei pääse teised kasutajad sellele enam ligi.", + "album_info_card_backup_album_excluded": "VÄLJA JÄETUD", + "album_info_card_backup_album_included": "LISATUD", "album_info_updated": "Albumi info muudetud", "album_leave": "Lahku albumist?", "album_leave_confirmation": "Kas oled kindel, et soovid albumist {album} lahkuda?", @@ -383,10 +393,21 @@ "album_remove_user": "Eemalda kasutaja?", "album_remove_user_confirmation": "Kas oled kindel, et soovid kasutaja {user} eemaldada?", "album_share_no_users": "Paistab, et oled seda albumit kÃĩikide kasutajatega jaganud, vÃĩi pole Ãŧhtegi kasutajat, kellega jagada.", + "album_thumbnail_card_item": "1 Ãŧksus", + "album_thumbnail_card_items": "{} Ãŧksust", + "album_thumbnail_card_shared": " ¡ Jagatud", + "album_thumbnail_shared_by": "Jagas {}", "album_updated": "Album muudetud", "album_updated_setting_description": "Saa teavitus e-posti teel, kui jagatud albumis on uusi Ãŧksuseid", "album_user_left": "Lahkutud albumist {album}", "album_user_removed": "Kasutaja {user} eemaldatud", + "album_viewer_appbar_delete_confirm": "Kas oled kindel, et soovid selle albumi oma kontolt kustutada?", + "album_viewer_appbar_share_err_delete": "Albumi kustutamine ebaÃĩnnestus", + "album_viewer_appbar_share_err_leave": "Albumist lahkumine ebaÃĩnnestus", + "album_viewer_appbar_share_err_remove": "Üksuste albumist eemaldamisel tekkis probleeme", + "album_viewer_appbar_share_err_title": "Albumi pealkirja muutmine ebaÃĩnnestus", + "album_viewer_appbar_share_leave": "Lahku albumist", + "album_viewer_page_share_add_users": "Lisa kasutajaid", "album_with_link_access": "Luba kÃĩigil, kellel on link, näha selle albumi fotosid ja isikuid.", "albums": "Albumid", "albums_count": "{count, plural, one {{count, number} album} other {{count, number} albumit}}", @@ -404,23 +425,36 @@ "api_key_description": "Seda väärtust kuvatakse ainult Ãŧks kord. Kopeeri see enne akna sulgemist.", "api_key_empty": "Su API vÃĩtme nimi ei tohiks olla tÃŧhi", "api_keys": "API vÃĩtmed", + "app_bar_signout_dialog_content": "Kas oled kindel, et soovid välja logida?", + "app_bar_signout_dialog_ok": "Jah", + "app_bar_signout_dialog_title": "Logi välja", "app_settings": "Rakenduse seaded", "appears_in": "Albumid", "archive": "Arhiiv", "archive_or_unarchive_photo": "Arhiveeri vÃĩi taasta foto", + "archive_page_no_archived_assets": "Arhiveeritud Ãŧksuseid ei leitud", "archive_size": "Arhiivi suurus", "archive_size_description": "Seadista arhiivi suurus allalaadimiseks (GiB)", + "archived": "Arhiveeritud", "archived_count": "{count, plural, other {# arhiveeritud}}", "are_these_the_same_person": "Kas need on sama isik?", "are_you_sure_to_do_this": "Kas oled kindel, et soovid seda teha?", + "asset_action_delete_err_read_only": "Kirjutuskaitstud Ãŧksuseid ei saa kustutada, jätan vahele", "asset_added_to_album": "Lisatud albumisse", "asset_adding_to_album": "Albumisse lisamineâ€Ļ", "asset_description_updated": "Üksuse kirjeldus on muudetud", "asset_filename_is_offline": "Üksus {filename} ei ole kättesaadav", "asset_has_unassigned_faces": "Üksusel on seostamata nägusid", "asset_hashing": "Räsimineâ€Ļ", + "asset_list_group_by_sub_title": "Grupeeri", + "asset_list_layout_settings_dynamic_layout_title": "DÃŧnaamiline asetus", + "asset_list_layout_settings_group_automatically": "Automaatne", + "asset_list_layout_settings_group_by": "Grupeeri Ãŧksused", + "asset_list_layout_settings_group_by_month_day": "Kuu + päev", + "asset_list_layout_sub_title": "Asetus", "asset_offline": "Üksus pole kättesaadav", "asset_offline_description": "Seda välise kogu Ãŧksust ei leitud kettalt. Abi saamiseks palun vÃĩta Ãŧhendust oma Immich'i administraatoriga.", + "asset_restored_successfully": "Üksus edukalt taastatud", "asset_skipped": "Vahele jäetud", "asset_skipped_in_trash": "PrÃŧgikastis", "asset_uploaded": "Üleslaaditud", @@ -438,8 +472,26 @@ "assets_trashed_count": "{count, plural, one {# Ãŧksus} other {# Ãŧksust}} liigutatud prÃŧgikasti", "assets_were_part_of_album_count": "{count, plural, one {Üksus oli} other {Üksused olid}} juba osa albumist", "authorized_devices": "Autoriseeritud seadmed", + "automatic_endpoint_switching_subtitle": "Ühendu lokaalselt Ãŧle valitud WiFi-vÃĩrgu, kui see on saadaval, ja kasuta mujal alternatiivseid Ãŧhendusi", "back": "Tagasi", "back_close_deselect": "Tagasi, sulge vÃĩi tÃŧhista valik", + "backup_album_selection_page_select_albums": "Vali albumid", + "backup_album_selection_page_selection_info": "Valiku info", + "backup_album_selection_page_total_assets": "Unikaalseid Ãŧksuseid kokku", + "backup_all": "KÃĩik", + "backup_background_service_default_notification": "Uute Ãŧksuste kontrollimineâ€Ļ", + "backup_background_service_error_title": "Varundamise viga", + "backup_controller_page_background_battery_info_ok": "OK", + "backup_controller_page_background_wifi": "Ainult WiFi-vÃĩrgus", + "backup_controller_page_backup_sub": "Varundatud fotod ja videod", + "backup_controller_page_desc_backup": "LÃŧlita sisse esiplaanil varundamine, et rakenduse avamisel uued Ãŧksused automaatselt serverisse Ãŧles laadida.", + "backup_controller_page_to_backup": "Albumid, mida varundada", + "backup_controller_page_total_sub": "KÃĩik unikaalsed fotod ja videod valitud albumitest", + "backup_err_only_album": "Ei saa ainsat albumit eemaldada", + "backup_info_card_assets": "Ãŧksused", + "backup_manual_cancelled": "TÃŧhistatud", + "backup_manual_title": "Üleslaadimise staatus", + "backup_setting_subtitle": "Halda taustal ja esiplaanil Ãŧleslaadimise seadeid", "backward": "Tagasi", "birthdate_saved": "SÃŧnnikuupäev salvestatud", "birthdate_set_description": "SÃŧnnikuupäeva kasutatakse isiku vanuse arvutamiseks foto tegemise hetkel.", @@ -451,11 +503,14 @@ "bulk_keep_duplicates_confirmation": "Kas oled kindel, et soovid {count, plural, one {# dubleeritud Ãŧksuse} other {# dubleeritud Ãŧksust}} alles jätta? Sellega märgitakse kÃĩik duplikaadigrupid lahendatuks ilma midagi kustutamata.", "bulk_trash_duplicates_confirmation": "Kas oled kindel, et soovid {count, plural, one {# dubleeritud Ãŧksuse} other {# dubleeritud Ãŧksust}} masskustutada? Sellega jäetakse alles iga grupi suurim Ãŧksus ning duplikaadid liigutatakse prÃŧgikasti.", "buy": "Osta Immich", + "cache_settings_clear_cache_button": "TÃŧhjenda puhver", + "cache_settings_statistics_title": "Puhvri kasutus", "camera": "Kaamera", "camera_brand": "Kaamera mark", "camera_model": "Kaamera mudel", "cancel": "Katkesta", "cancel_search": "Katkesta otsing", + "canceled": "TÃŧhistatud", "cannot_merge_people": "Ei saa isikuid Ãŧhendada", "cannot_undo_this_action": "Sa ei saa seda tagasi vÃĩtta!", "cannot_update_the_description": "Kirjelduse muutmine ebaÃĩnnestus", @@ -466,6 +521,10 @@ "change_name_successfully": "Nimi edukalt muudetud", "change_password": "Parooli muutmine", "change_password_description": "See on su esimene kord sÃŧsteemi siseneda, vÃĩi on tehtud taotlus parooli muutmiseks. Palun sisesta allpool uus parool.", + "change_password_form_confirm_password": "Kinnita parool", + "change_password_form_new_password": "Uus parool", + "change_password_form_password_mismatch": "Paroolid ei klapi", + "change_password_form_reenter_new_password": "Korda uut parooli", "change_your_password": "Muuda oma parooli", "changed_visibility_successfully": "Nähtavus muudetud", "check_all": "Märgi kÃĩik", @@ -477,6 +536,14 @@ "clear_all_recent_searches": "TÃŧhjenda hiljutised otsingud", "clear_message": "TÃŧhjenda sÃĩnum", "clear_value": "TÃŧhjenda väärtus", + "client_cert_dialog_msg_confirm": "OK", + "client_cert_enter_password": "Sisesta parool", + "client_cert_import": "Impordi", + "client_cert_import_success_msg": "Klientsertifikaat on imporditud", + "client_cert_invalid_msg": "Vigane sertifikaadi fail vÃĩi vale parool", + "client_cert_remove_msg": "Klientsertifikaat on eemaldatud", + "client_cert_subtitle": "Toetab ainult PKCS12 (.p12, .pfx) formaati. Sertifikaadi importimine/eemaldamine on saadaval ainult enne sisselogimist", + "client_cert_title": "SSL klientsertifikaat", "clockwise": "Päripäeva", "close": "Sulge", "collapse": "Peida", @@ -487,6 +554,8 @@ "comment_options": "Kommentaari valikud", "comments_and_likes": "Kommentaarid ja meeldimised", "comments_are_disabled": "Kommentaarid on keelatud", + "common_create_new_album": "Lisa uus album", + "completed": "LÃĩpetatud", "confirm": "Kinnita", "confirm_admin_password": "Kinnita administraatori parool", "confirm_delete_face": "Kas oled kindel, et soovid isiku {name} näo Ãŧksuselt kustutada?", @@ -496,6 +565,10 @@ "contain": "Mahuta ära", "context": "Kontekst", "continue": "Jätka", + "control_bottom_app_bar_create_new_album": "Lisa uus album", + "control_bottom_app_bar_delete_from_local": "Kustuta seadmest", + "control_bottom_app_bar_edit_location": "Muuda asukohta", + "control_bottom_app_bar_edit_time": "Muuda kuupäeva ja aega", "copied_image_to_clipboard": "Pilt kopeeritud lÃĩikelauale.", "copied_to_clipboard": "Kopeeritud lÃĩikelauale!", "copy_error": "Kopeeri viga", @@ -517,6 +590,7 @@ "create_new_person": "Lisa uus isik", "create_new_person_hint": "Seosta valitud Ãŧksused uue isikuga", "create_new_user": "Lisa uus kasutaja", + "create_shared_album_page_share_select_photos": "Vali fotod", "create_tag": "Lisa silt", "create_tag_description": "Lisa uus silt. Pesastatud siltide jaoks sisesta täielik tee koos kaldkriipsudega.", "create_user": "Lisa kasutaja", @@ -541,19 +615,23 @@ "delete": "Kustuta", "delete_album": "Kustuta album", "delete_api_key_prompt": "Kas oled kindel, et soovid selle API vÃĩtme kustutada?", + "delete_dialog_title": "Kustuta jäädavalt", "delete_duplicates_confirmation": "Kas oled kindel, et soovid need duplikaadid jäädavalt kustutada?", "delete_face": "Kustuta nägu", "delete_key": "Kustuta vÃĩti", "delete_library": "Kustuta kogu", "delete_link": "Kustuta link", + "delete_local_dialog_ok_backed_up_only": "Kustuta ainult varundatud", "delete_others": "Kustuta teised", "delete_shared_link": "Kustuta jagatud link", + "delete_shared_link_dialog_title": "Kustuta jagatud link", "delete_tag": "Kustuta silt", "delete_tag_confirmation_prompt": "Kas oled kindel, et soovid sildi {tagName} kustutada?", "delete_user": "Kustuta kasutaja", "deleted_shared_link": "Jagatud link kustutatud", "deletes_missing_assets": "Kustutab Ãŧksused, mis on kettalt puudu", "description": "Kirjeldus", + "description_input_hint_text": "Lisa kirjeldus...", "details": "Üksikasjad", "direction": "Suund", "disabled": "Välja lÃŧlitatud", @@ -570,10 +648,20 @@ "documentation": "Dokumentatsioon", "done": "Tehtud", "download": "Laadi alla", + "download_canceled": "Allalaadimine katkestatud", + "download_complete": "Allalaadimine lÃĩpetatud", + "download_enqueue": "Allalaadimine ootel", + "download_error": "Allalaadimise viga", + "download_failed": "Allalaadimine ebaÃĩnnestus", + "download_finished": "Allalaadimine lÃĩpetatud", "download_include_embedded_motion_videos": "Manustatud videod", "download_include_embedded_motion_videos_description": "Lisa liikuvatesse fotodesse manustatud videod eraldi failidena", + "download_paused": "Allalaadimine peatatud", "download_settings": "Allalaadimine", "download_settings_description": "Halda Ãŧksuste allalaadimise seadeid", + "download_started": "Allalaadimine alustatud", + "download_sucess": "Allalaadimine Ãĩnnestus", + "download_sucess_android": "Meediumid laaditi alla kataloogi DCIM/Immich", "downloading": "Allalaadimine", "downloading_asset_filename": "Üksuse {filename} allalaadimine", "drop_files_to_upload": "Failide Ãŧleslaadimiseks sikuta need ÃŧkskÃĩik kuhu", @@ -592,6 +680,7 @@ "edit_key": "Muuda vÃĩtit", "edit_link": "Muuda linki", "edit_location": "Muuda asukohta", + "edit_location_dialog_title": "Asukoht", "edit_name": "Muuda nime", "edit_people": "Muuda isikuid", "edit_tag": "Muuda silti", @@ -604,12 +693,15 @@ "editor_crop_tool_h2_aspect_ratios": "Kuvasuhted", "editor_crop_tool_h2_rotation": "PÃļÃļre", "email": "E-post", + "empty_folder": "See kaust on tÃŧhi", "empty_trash": "TÃŧhjenda prÃŧgikast", "empty_trash_confirmation": "Kas oled kindel, et soovid prÃŧgikasti tÃŧhjendada? See eemaldab kÃĩik seal olevad Ãŧksused Immich'ist jäädavalt.\nSeda tegevust ei saa tagasi vÃĩtta!", "enable": "Luba", "enabled": "Lubatud", "end_date": "LÃĩppkuupäev", + "enter_wifi_name": "Sisesta WiFi-vÃĩrgu nimi", "error": "Viga", + "error_change_sort_album": "Albumi sorteerimisjärjestuse muutmine ebaÃĩnnestus", "error_delete_face": "Viga näo kustutamisel", "error_loading_image": "Viga pildi laadimisel", "error_title": "Viga - midagi läks valesti", @@ -740,8 +832,14 @@ "unable_to_upload_file": "Faili Ãŧleslaadimine ebaÃĩnnestus" }, "exif": "Exif", + "exif_bottom_sheet_description": "Lisa kirjeldus...", + "exif_bottom_sheet_details": "ÜKSIKASJAD", + "exif_bottom_sheet_location": "ASUKOHT", + "exif_bottom_sheet_people": "ISIKUD", + "exif_bottom_sheet_person_add_person": "Lisa nimi", "exit_slideshow": "Sulge slaidiesitlus", "expand_all": "Näita kÃĩik", + "experimental_settings_title": "Eksperimentaalne", "expire_after": "Aegub", "expired": "Aegunud", "expires_date": "Aegub {date}", @@ -752,6 +850,7 @@ "extension": "Laiend", "external": "Väline", "external_libraries": "Välised kogud", + "external_network_sheet_info": "Kui seade ei ole eelistatud WiFi-vÃĩrgus, Ãŧhendub rakendus serveriga allolevatest URL-idest esimese kättesaadava kaudu, alustades Ãŧlevalt", "face_unassigned": "Seostamata", "failed_to_load_assets": "Üksuste laadimine ebaÃĩnnestus", "favorite": "Lemmik", @@ -767,6 +866,8 @@ "filter_people": "Filtreeri isikuid", "find_them_fast": "Leia teda kiiresti nime järgi otsides", "fix_incorrect_match": "Paranda ebaÃĩige vaste", + "folder": "Kaust", + "folder_not_found": "Kausta ei leitud", "folders": "Kaustad", "folders_feature_description": "Kaustavaate abil failisÃŧsteemis olevate fotode ja videote sirvimine", "forward": "Edasi", @@ -783,6 +884,10 @@ "group_places_by": "Grupeeri kohad...", "group_year": "Grupeeri aasta kaupa", "has_quota": "On kvoot", + "header_settings_add_header_tip": "Lisa päis", + "header_settings_field_validator_msg": "Väärtus ei saa olla tÃŧhi", + "header_settings_header_name_input": "Päise nimi", + "header_settings_header_value_input": "Päise väärtus", "hi_user": "Tere {name} ({email})", "hide_all_people": "Peida kÃĩik isikud", "hide_gallery": "Peida galerii", @@ -790,8 +895,20 @@ "hide_password": "Peida parool", "hide_person": "Peida isik", "hide_unnamed_people": "Peida nimetud isikud", + "home_page_add_to_album_conflicts": "{added} Ãŧksust lisati albumisse {album}. {failed} Ãŧksust oli juba albumis.", + "home_page_add_to_album_err_local": "Lokaalseid Ãŧksuseid ei saa veel albumisse lisada, jätan vahele", + "home_page_add_to_album_success": "{added} Ãŧksust lisati albumisse {album}.", + "home_page_album_err_partner": "Partneri Ãŧksuseid ei saa veel albumisse lisada, jätan vahele", + "home_page_archive_err_local": "Lokaalseid Ãŧksuseid ei saa veel arhiveerida, jätan vahele", + "home_page_archive_err_partner": "Partneri Ãŧksuseid ei saa arhiveerida, jätan vahele", + "home_page_building_timeline": "Ajajoone koostamine", + "home_page_delete_err_partner": "Partneri Ãŧksuseid ei saa kustutada, jätan vahele", + "home_page_favorite_err_local": "Lokaalseid Ãŧksuseid ei saa lemmikuks märkida, jätan vahele", + "home_page_favorite_err_partner": "Partneri Ãŧksuseid ei saa lemmikuks märkida, jätan vahele", + "home_page_share_err_local": "Lokaalseid Ãŧksuseid ei saa lingiga jagada, jätan vahele", "host": "Host", "hour": "Tund", + "ignore_icloud_photos": "Ignoreeri iCloud fotosid", "image": "Pilt", "image_alt_text_date": "{isVideo, select, true {Video} other {Pilt}} tehtud {date}", "image_alt_text_date_1_person": "{isVideo, select, true {Video} other {Pilt}} tehtud {date} koos isikuga {person1}", @@ -803,6 +920,8 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {Video} other {Pilt}} tehtud {date} kohas {city}, {country} koos isikutega {person1} ja {person2}", "image_alt_text_date_place_3_people": "{isVideo, select, true {Video} other {Pilt}} tehtud {date} kohas {city}, {country} koos isikutega {person1}, {person2} ja {person3}", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Video} other {Pilt}} tehtud {date} kohas {city}, {country} koos {person1}, {person2} ja veel {additionalCount, number} isikuga", + "image_viewer_page_state_provider_download_started": "Allalaadimine alustatud", + "image_viewer_page_state_provider_download_success": "Allalaadimine Ãĩnnestus", "immich_logo": "Immich'i logo", "immich_web_interface": "Immich'i veebiliides", "import_from_json": "Impordi JSON-formaadist", @@ -821,6 +940,8 @@ "night_at_midnight": "Iga päev keskÃļÃļl", "night_at_twoam": "Iga ÃļÃļ kell 2" }, + "invalid_date": "Vigane kuupäev", + "invalid_date_format": "Vigane kuupäevaformaat", "invite_people": "Kutsu inimesi", "invite_to_album": "Kutsu albumisse", "items_count": "{count, plural, one {# Ãŧksus} other {# Ãŧksust}}", @@ -841,6 +962,9 @@ "level": "Tase", "library": "Kogu", "library_options": "Kogu seaded", + "library_page_new_album": "Uus album", + "library_page_sort_asset_count": "Üksuste arv", + "library_page_sort_title": "Albumi pealkiri", "light": "Hele", "like_deleted": "Meeldimine kustutatud", "link_motion_video": "Lingi liikuv video", @@ -850,12 +974,24 @@ "list": "Loend", "loading": "Laadimine", "loading_search_results_failed": "Otsitulemuste laadimine ebaÃĩnnestus", + "local_network_sheet_info": "Rakendus Ãŧhendub valitud Wi-Fi vÃĩrgus olles serveriga selle URL-i kaudu", + "location_permission_content": "Automaatseks ÃŧmberlÃŧlitumiseks vajab Immich täpse asukoha luba, et saaks lugeda aktiivse WiFi-vÃĩrgu nime", + "location_picker_choose_on_map": "Vali kaardil", "log_out": "Logi välja", "log_out_all_devices": "Logi kÃĩigist seadmetest välja", "logged_out_all_devices": "KÃĩigist seadmetest välja logitud", "logged_out_device": "Seadmest välja logitud", "login": "Logi sisse", + "login_form_back_button_text": "Tagasi", + "login_form_email_hint": "sinunimi@email.com", + "login_form_endpoint_hint": "http://serveri-ip:port", + "login_form_endpoint_url": "Serveri lÃĩpp-punkti URL", + "login_form_err_http": "Palun täpsusta http:// vÃĩi https://", + "login_form_err_invalid_email": "Vigane e-posti aadress", + "login_form_err_invalid_url": "Vigane URL", + "login_form_password_hint": "parool", "login_has_been_disabled": "Sisselogimine on keelatud.", + "login_password_changed_success": "Parool edukalt uuendatud", "logout_all_device_confirmation": "Kas oled kindel, et soovid kÃĩigist seadmetest välja logida?", "logout_this_device_confirmation": "Kas oled kindel, et soovid sellest seadmest välja logida?", "longitude": "Pikkuskraad", @@ -876,10 +1012,14 @@ "map_marker_for_images": "Kaardimarker kohas {city}, {country} tehtud piltide jaoks", "map_marker_with_image": "Kaardimarker pildiga", "map_settings": "Kaardi seaded", + "map_settings_date_range_option_day": "Viimased 24 tundi", + "map_settings_date_range_option_year": "Viimane aasta", + "map_settings_dialog_title": "Kaardi seaded", "matches": "Ühtivad failid", - "media_type": "Meedia tÃŧÃŧp", + "media_type": "Meediumi tÃŧÃŧp", "memories": "Mälestused", "memories_setting_description": "Halda, mida sa oma mälestustes näed", + "memories_year_ago": "Aasta tagasi", "memory": "Mälestus", "memory_lane_title": "Mälestus {title}", "menu": "MenÃŧÃŧ", @@ -896,10 +1036,14 @@ "month": "Kuu", "more": "Rohkem", "moved_to_trash": "Liigutatud prÃŧgikasti", + "multiselect_grid_edit_date_time_err_read_only": "Kirjutuskaitsega Ãŧksus(t)e kuupäeva ei saa muuta, jätan vahele", + "multiselect_grid_edit_gps_err_read_only": "Kirjutuskaitsega Ãŧksus(t)e asukohta ei saa muuta, jätan vahele", "mute_memories": "Vaigista mälestused", "my_albums": "Minu albumid", "name": "Nimi", "name_or_nickname": "Nimi vÃĩi hÃŧÃŧdnimi", + "networking_settings": "VÃĩrguÃŧhendus", + "networking_subtitle": "Halda serveri lÃĩpp-punkti seadeid", "never": "Mitte kunagi", "new_album": "Uus album", "new_api_key": "Uus API vÃĩti", @@ -962,6 +1106,9 @@ "partner_can_access": "{partner} pääseb ligi", "partner_can_access_assets": "KÃĩik su fotod ja videod, välja arvatud arhiveeritud ja kustutatud", "partner_can_access_location": "Asukohad, kus su fotod tehti", + "partner_list_view_all": "Vaata kÃĩiki", + "partner_page_partner_add_failed": "Partneri lisamine ebaÃĩnnestus", + "partner_page_select_partner": "Vali partner", "partner_sharing": "Partneriga jagamine", "partners": "Partnerid", "password": "Parool", @@ -990,6 +1137,7 @@ "permanently_delete_assets_prompt": "Kas oled kindel, et soovid {count, plural, one {selle Ãŧksuse} other {need # Ãŧksust}} jäädavalt kustutada? Sellega eemaldatakse {count, plural, one {see} other {need}} ka oma albumi(te)st.", "permanently_deleted_asset": "Üksus jäädavalt kustutatud", "permanently_deleted_assets_count": "{count, plural, one {# Ãŧksus} other {# Ãŧksust}} jäädavalt kustutatud", + "permission_onboarding_back": "Tagasi", "person": "Isik", "person_birthdate": "SÃŧndinud {date}", "person_hidden": "{name}{hidden, select, true { (peidetud)} other {}}", @@ -1007,6 +1155,7 @@ "play_motion_photo": "Esita liikuv foto", "play_or_pause_video": "Esita vÃĩi peata video", "port": "Port", + "preferences_settings_title": "Eelistused", "preset": "Eelseadistus", "preview": "Eelvaade", "previous": "Eelmine", @@ -1014,6 +1163,8 @@ "previous_or_next_photo": "Eelmine vÃĩi järgmine foto", "primary": "Peamine", "privacy": "Privaatsus", + "profile_drawer_app_logs": "Logid", + "profile_drawer_github": "GitHub", "profile_image_of_user": "Kasutaja {user} profiilipilt", "profile_picture_set": "Profiilipilt määratud.", "public_album": "Avalik album", @@ -1063,6 +1214,8 @@ "recent": "Hiljutine", "recent-albums": "Hiljutised albumid", "recent_searches": "Hiljutised otsingud", + "recently_added": "Hiljuti lisatud", + "recently_added_page_title": "Hiljuti lisatud", "refresh": "Värskenda", "refresh_encoded_videos": "Värskenda kodeeritud videod", "refresh_faces": "Värskenda näod", @@ -1119,6 +1272,7 @@ "role_editor": "Muutja", "role_viewer": "Vaataja", "save": "Salvesta", + "save_to_gallery": "Salvesta galeriisse", "saved_api_key": "API vÃĩti salvestatud", "saved_profile": "Profiil salvestatud", "saved_settings": "Seaded salvestatud", @@ -1138,14 +1292,32 @@ "search_camera_model": "Otsi kaamera mudelit...", "search_city": "Otsi linna...", "search_country": "Otsi riiki...", + "search_filter_camera_title": "Vali kaamera tÃŧÃŧp", + "search_filter_date": "Kuupäev", + "search_filter_date_interval": "{start} kuni {end}", + "search_filter_date_title": "Vali kuupäevavahemik", + "search_filter_display_options": "Kuva valikud", + "search_filter_filename": "Otsi failinime alusel", + "search_filter_location": "Asukoht", + "search_filter_location_title": "Vali asukoht", + "search_filter_media_type": "Meediumi tÃŧÃŧp", + "search_filter_media_type_title": "Vali meediumi tÃŧÃŧp", + "search_filter_people_title": "Vali isikud", "search_for": "Otsi", "search_for_existing_person": "Otsi olemasolevat isikut", "search_no_people": "Isikuid ei ole", "search_no_people_named": "Ei ole isikuid nimega \"{name}\"", "search_options": "Otsingu valikud", + "search_page_categories": "Kategooriad", + "search_page_screenshots": "Ekraanipildid", + "search_page_search_photos_videos": "Otsi oma fotosid ja videosid", + "search_page_selfies": "Selfid", + "search_page_things": "Asjad", + "search_page_view_all_button": "Vaata kÃĩiki", "search_people": "Otsi inimesi", "search_places": "Otsi kohti", "search_rating": "Otsi hinnangu järgi...", + "search_result_page_new_search_hint": "Uus otsing", "search_settings": "Otsi seadeid", "search_state": "Otsi osariiki...", "search_tags": "Otsi silte...", @@ -1168,10 +1340,14 @@ "select_new_face": "Vali uus nägu", "select_photos": "Vali fotod", "select_trash_all": "Vali kÃĩik prÃŧgikasti", + "select_user_for_sharing_page_err_album": "Albumi lisamine ebaÃĩnnestus", "selected": "Valitud", "selected_count": "{count, plural, other {# valitud}}", "send_message": "Saada sÃĩnum", "send_welcome_email": "Saada tervituskiri", + "server_endpoint": "Serveri lÃĩpp-punkt", + "server_info_box_app_version": "Rakenduse versioon", + "server_info_box_server_url": "Serveri URL", "server_offline": "Serveriga Ãŧhendus puudub", "server_online": "Server Ãŧhendatud", "server_stats": "Serveri statistika", @@ -1183,22 +1359,42 @@ "set_date_of_birth": "Määra sÃŧnnikuupäev", "set_profile_picture": "Sea profiilipilt", "set_slideshow_to_fullscreen": "Kuva slaidiesitlus täisekraanil", + "setting_languages_apply": "Rakenda", + "setting_languages_title": "Keeled", + "setting_notifications_notify_immediately": "kohe", + "setting_notifications_notify_never": "mitte kunagi", "settings": "Seaded", "settings_saved": "Seaded salvestatud", "share": "Jaga", "shared": "Jagatud", + "shared_album_section_people_action_error": "Viga albumist eemaldamisel/lahkumisel", + "shared_album_section_people_action_leave": "Eemalda kasutaja albumist", + "shared_album_section_people_action_remove_user": "Eemalda kasutaja albumist", + "shared_album_section_people_title": "ISIKUD", "shared_by": "Jagas", "shared_by_user": "Jagas {user}", "shared_by_you": "Jagasid sina", "shared_from_partner": "Fotod partnerilt {partner}", + "shared_link_app_bar_title": "Jagatud lingid", + "shared_link_clipboard_copied_massage": "Kopeeritud lÃĩikelauale", + "shared_link_create_error": "Viga jagatud lingi loomisel", + "shared_link_edit_expire_after_option_day": "1 päev", + "shared_link_edit_expire_after_option_hour": "1 tund", + "shared_link_edit_expire_after_option_minute": "1 minut", + "shared_link_info_chip_metadata": "EXIF", + "shared_link_manage_links": "Halda jagatud linke", "shared_link_options": "Jagatud lingi valikud", "shared_links": "Jagatud lingid", "shared_links_description": "Jaga fotosid ja videosid lingiga", "shared_photos_and_videos_count": "{assetCount, plural, other {# jagatud fotot ja videot.}}", + "shared_with_me": "Minuga jagatud", "shared_with_partner": "Jagatud partneriga {partner}", "sharing": "Jagamine", "sharing_enter_password": "Palun sisesta selle lehe vaatamiseks salasÃĩna.", + "sharing_page_album": "Jagatud albumid", "sharing_sidebar_description": "Kuva kÃŧlgmenÃŧÃŧs Jagamise linki", + "sharing_silver_appbar_create_shared_album": "Uus jagatud album", + "sharing_silver_appbar_share_partner": "Jaga partneriga", "shift_to_permanent_delete": "vajuta ⇧, et Ãŧksus jäädavalt kustutada", "show_album_options": "Näita albumi valikuid", "show_albums": "Näita albumeid", @@ -1265,6 +1461,7 @@ "support_third_party_description": "Sinu Immich'i install on kolmanda osapoole pakendatud. Probleemid, mida täheldad, vÃĩivad olla pÃĩhjustatud selle pakendamise poolt, seega vÃĩta esmajärjekorras nendega Ãŧhendust, kasutades allolevaid linke.", "swap_merge_direction": "Muuda Ãŧhendamise suunda", "sync": "SÃŧnkrooni", + "sync_albums": "SÃŧnkrooni albumid", "tag": "Silt", "tag_assets": "Sildista Ãŧksuseid", "tag_created": "Lisatud silt: {tag}", @@ -1278,6 +1475,9 @@ "theme": "Teema", "theme_selection": "Teema valik", "theme_selection_description": "Sea automaatselt hele vÃĩi tume teema vastavalt veebilehitseja eelistustele", + "theme_setting_primary_color_title": "PÃĩhivärv", + "theme_setting_system_primary_color_title": "Kasuta sÃŧsteemset värvi", + "theme_setting_system_theme_switch": "Automaatne (järgi sÃŧsteemi seadet)", "they_will_be_merged_together": "Nad Ãŧhendatakse kokku", "third_party_resources": "Kolmanda osapoole ressursid", "time_based_memories": "AjapÃĩhised mälestused", @@ -1298,6 +1498,9 @@ "trash_count": "Liiguta {count, number} prÃŧgikasti", "trash_delete_asset": "Kustuta Ãŧksus", "trash_no_results_message": "Siia ilmuvad prÃŧgikasti liigutatud fotod ja videod.", + "trash_page_delete_all": "Kustuta kÃĩik", + "trash_page_restore_all": "Taasta kÃĩik", + "trash_page_select_assets_btn": "Vali Ãŧksused", "trashed_items_will_be_permanently_deleted_after": "PrÃŧgikasti tÃĩstetud Ãŧksused kustutatakse jäädavalt {days, plural, one {# päeva} other {# päeva}} pärast.", "type": "TÃŧÃŧp", "unarchive": "Taasta arhiivist", @@ -1333,6 +1536,7 @@ "upload_status_errors": "Vead", "upload_status_uploaded": "Üleslaaditud", "upload_success": "Üleslaadimine Ãĩnnestus, uute Ãŧksuste nägemiseks värskenda lehte.", + "uploading": "Üleslaadimine", "url": "URL", "usage": "Kasutus", "use_custom_date_range": "Kasuta kohandatud kuupäevavahemikku", @@ -1372,15 +1576,19 @@ "view_previous_asset": "Vaata eelmist Ãŧksust", "view_qr_code": "Vaata QR-koodi", "view_stack": "Vaata virna", + "viewer_remove_from_stack": "Eemalda virnast", + "viewer_unstack": "Eralda", "visibility_changed": "{count, plural, one {# isiku} other {# isiku}} nähtavus muudetud", "waiting": "Ootel", "warning": "Hoiatus", "week": "Nädal", "welcome": "Tere tulemast", "welcome_to_immich": "Tere tulemast Immich'isse", + "wifi_name": "WiFi-vÃĩrgu nimi", "year": "Aasta", "years_ago": "{years, plural, one {# aasta} other {# aastat}} tagasi", "yes": "Jah", "you_dont_have_any_shared_links": "Sul pole Ãŧhtegi jagatud linki", + "your_wifi_name": "Sinu WiFi-vÃĩrgu nimi", "zoom_image": "Suumi pilti" } diff --git a/i18n/fi.json b/i18n/fi.json index 8ca468fbab..8e64c372de 100644 --- a/i18n/fi.json +++ b/i18n/fi.json @@ -520,11 +520,11 @@ "backup_controller_page_background_turn_on": "Kytke taustapalvelu päälle", "backup_controller_page_background_wifi": "Vain WiFi-verkossa", "backup_controller_page_backup": "Varmuuskopiointi", - "backup_controller_page_backup_selected": "Valittu:", + "backup_controller_page_backup_selected": "Valittu: ", "backup_controller_page_backup_sub": "Varmuuskopioidut kuvat ja videot", "backup_controller_page_created": "Luotu: {}", "backup_controller_page_desc_backup": "Kytke varmuuskopiointi päälle lähettääksesi uudet kohteet palvelimelle automaattisesti.", - "backup_controller_page_excluded": "Jätetty pois:", + "backup_controller_page_excluded": "Jätetty pois: ", "backup_controller_page_failed": "Epäonnistui ({})", "backup_controller_page_filename": "Tiedoston nimi: {} [{}]", "backup_controller_page_id": "ID: {}", diff --git a/i18n/fr.json b/i18n/fr.json index c116ee261a..00a4a281b5 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -87,9 +87,9 @@ "image_resolution_description": "Les rÊsolutions plus ÊlevÊes permettent de prÊserver davantage de dÊtails, mais l'encodage est plus long, les fichiers sont plus volumineux et la rÊactivitÊ de l'application peut s'en trouver rÊduite.", "image_settings": "Paramètres d'image", "image_settings_description": "Gestion de la qualitÊ et rÊsolution des images gÊnÊrÊes", - "image_thumbnail_description": "Petite vignette avec mÊtadonnÊes retirÊes, utilisÊe lors de la visualisation de groupes de photos comme sur la vue chronologique principale", - "image_thumbnail_quality_description": "QualitÊ des vignettes : de 1 à 100. Une valeur ÊlevÊe produit de meilleurs rÊsultats, mais elle produit des fichiers plus volumineux et peut rÊduire la rÊactivitÊ de l'application.", - "image_thumbnail_title": "Paramètres des vignettes", + "image_thumbnail_description": "Petite miniature avec les mÊtadonnÊes retirÊes, utilisÊe lors de la visualisation de groupes de photos comme sur la vue chronologique principale", + "image_thumbnail_quality_description": "QualitÊ des miniatures : de 1 à 100. Une valeur ÊlevÊe produit de meilleurs rÊsultats, mais elle produit des fichiers plus volumineux et peut rÊduire la rÊactivitÊ de l'application.", + "image_thumbnail_title": "Paramètres des miniatures", "job_concurrency": "{job} : nombre de tÃĸches simultanÊes", "job_created": "TÃĸche crÊÊe", "job_not_concurrency_safe": "Cette tÃĸche ne peut pas ÃĒtre exÊcutÊe en multitÃĸche de façon sÃģre.", @@ -345,7 +345,7 @@ "trash_settings": "Corbeille", "trash_settings_description": "GÊrer les paramètres de la corbeille", "untracked_files": "Fichiers non suivis", - "untracked_files_description": "Ces fichiers ne sont pas suivis par l'application. Ils peuvent ÃĒtre le rÊsultat d'erreurs de dÊplacement, d'envois interrompus, ou d'abandons en raison d'un bug", + "untracked_files_description": "Ces fichiers ne sont pas suivis par l'application. Ils peuvent ÃĒtre le rÊsultat d'Êchecs de dÊplacement, d'envois interrompus, ou d'abandons en raison d'un bug", "user_cleanup_job": "Nettoyage des utilisateurs", "user_delete_delay": "La suppression dÊfinitive du compte et des mÊdias de {user} sera programmÊe dans {delay, plural, one {# jour} other {# jours}}.", "user_delete_delay_settings": "DÊlai de suppression", @@ -371,13 +371,17 @@ "admin_password": "Mot de passe Admin", "administration": "Administration", "advanced": "AvancÊ", - "advanced_settings_log_level_title": "Niveau de log : {}", - "advanced_settings_prefer_remote_subtitle": "Certains appareils sont très lents à charger des vignettes à partir de ressources prÊsentes sur l'appareil. Activez ce paramètre pour charger des images externes à la place.", + "advanced_settings_enable_alternate_media_filter_subtitle": "Utilisez cette option pour filtrer les mÊdia durant la synchronisation avec des critères alternatifs. N'utilisez cela que lorsque l'application n'arrive pas à dÊtecter tout les albums.", + "advanced_settings_enable_alternate_media_filter_title": "[EXEPRIMENTAL] Utiliser le filtre de synchronisation d'album alternatif", + "advanced_settings_log_level_title": "Niveau de journalisation : {}", + "advanced_settings_prefer_remote_subtitle": "Certains appareils sont très lents à charger des miniatures à partir de ressources prÊsentes sur l'appareil. Activez ce paramètre pour charger des images externes à la place.", "advanced_settings_prefer_remote_title": "PrÊfÊrer les images externes", "advanced_settings_proxy_headers_subtitle": "Ajoutez des en-tÃĒtes personnalisÊs à chaque requÃĒte rÊseau", "advanced_settings_proxy_headers_title": "En-tÃĒtes de proxy", "advanced_settings_self_signed_ssl_subtitle": "Permet d'ignorer la vÊrification du certificat SSL pour le point d'accès du serveur. Requis pour les certificats auto-signÊs.", "advanced_settings_self_signed_ssl_title": "Autoriser les certificats SSL auto-signÊs", + "advanced_settings_sync_remote_deletions_subtitle": "Supprimer ou restaurer automatiquement un mÊdia sur cet appareil lorsqu'une action a ÊtÊ faite sur le web", + "advanced_settings_sync_remote_deletions_title": "Synchroniser les suppressions depuis le serveur [EXPERIMENTAL]", "advanced_settings_tile_subtitle": "Paramètres d'utilisateur avancÊs", "advanced_settings_troubleshooting_subtitle": "Activer des fonctions supplÊmentaires pour le dÊpannage", "advanced_settings_troubleshooting_title": "DÊpannage", @@ -506,11 +510,11 @@ "backup_all": "Tout", "backup_background_service_backup_failed_message": "Échec de la sauvegarde des ÊlÊments. Nouvelle tentative...", "backup_background_service_connection_failed_message": "Impossible de se connecter au serveur. Nouvelle tentative...", - "backup_background_service_current_upload_notification": "Transfert {}", + "backup_background_service_current_upload_notification": "Envoi {}", "backup_background_service_default_notification": "Recherche de nouveaux ÊlÊments...", "backup_background_service_error_title": "Erreur de sauvegarde", "backup_background_service_in_progress_notification": "Sauvegarde de vos ÊlÊments...", - "backup_background_service_upload_failure_notification": "Impossible de transfÊrer {}", + "backup_background_service_upload_failure_notification": "Échec lors de l'envoi {}", "backup_controller_page_albums": "Sauvegarder les albums", "backup_controller_page_background_app_refresh_disabled_content": "Activez le rafraÃŽchissement de l'application en arrière-plan dans Paramètres > GÊnÊral > RafraÃŽchissement de l'application en arrière-plan afin d'utiliser la sauvegarde en arrière-plan.", "backup_controller_page_background_app_refresh_disabled_title": "RafraÃŽchissement de l'application en arrière-plan dÊsactivÊ", @@ -521,7 +525,7 @@ "backup_controller_page_background_battery_info_title": "Optimisation de la batterie", "backup_controller_page_background_charging": "Seulement pendant la charge", "backup_controller_page_background_configure_error": "Échec de la configuration du service d'arrière-plan", - "backup_controller_page_background_delay": "Retarder la sauvegarde des nouveaux ÊlÊments d'actif: {}", + "backup_controller_page_background_delay": "Retarder la sauvegarde des nouveaux ÊlÊments : {}", "backup_controller_page_background_description": "Activez le service d'arrière-plan pour sauvegarder automatiquement tous les nouveaux ÊlÊments sans avoir à ouvrir l'application.", "backup_controller_page_background_is_off": "La sauvegarde automatique en arrière-plan est dÊsactivÊe", "backup_controller_page_background_is_on": "La sauvegarde automatique en arrière-plan est activÊe", @@ -531,12 +535,12 @@ "backup_controller_page_backup": "SauvegardÊ", "backup_controller_page_backup_selected": "SÊlectionnÊ: ", "backup_controller_page_backup_sub": "Photos et vidÊos sauvegardÊes", - "backup_controller_page_created": "CrÊÊ le: {}", + "backup_controller_page_created": "CrÊÊ le : {}", "backup_controller_page_desc_backup": "Activez la sauvegarde pour envoyer automatiquement les nouveaux ÊlÊments sur le serveur.", "backup_controller_page_excluded": "Exclus: ", "backup_controller_page_failed": "Échec de l'opÊration ({})", - "backup_controller_page_filename": "Nom du fichier: {} [{}]", - "backup_controller_page_id": "ID: {}", + "backup_controller_page_filename": "Nom du fichier : {} [{}]", + "backup_controller_page_id": "ID : {}", "backup_controller_page_info": "Informations de sauvegarde", "backup_controller_page_none_selected": "Aucune sÊlection", "backup_controller_page_remainder": "Restant", @@ -545,7 +549,7 @@ "backup_controller_page_start_backup": "DÊmarrer la sauvegarde", "backup_controller_page_status_off": "La sauvegarde est dÊsactivÊe", "backup_controller_page_status_on": "La sauvegarde est activÊe", - "backup_controller_page_storage_format": "{} de {} utilisÊ", + "backup_controller_page_storage_format": "{} sur {} utilisÊs", "backup_controller_page_to_backup": "Albums à sauvegarder", "backup_controller_page_total_sub": "Toutes les photos et vidÊos uniques des albums sÊlectionnÊs", "backup_controller_page_turn_off": "DÊsactiver la sauvegarde", @@ -570,21 +574,21 @@ "bulk_keep_duplicates_confirmation": "Êtes-vous sÃģr de vouloir conserver {count, plural, one {# doublon} other {# doublons}} ? Cela rÊsoudra tous les groupes de doublons sans rien supprimer.", "bulk_trash_duplicates_confirmation": "Êtes-vous sÃģr de vouloir mettre à la corbeille {count, plural, one {# doublon} other {# doublons}} ? Cette opÊration permet de conserver le plus grand mÊdia de chaque groupe et de mettre à la corbeille tous les autres doublons.", "buy": "Acheter Immich", - "cache_settings_album_thumbnails": "vignettes de la page bibliothèque ({} ÊlÊments)", + "cache_settings_album_thumbnails": "Page des miniatures de la bibliothèque ({} ÊlÊments)", "cache_settings_clear_cache_button": "Effacer le cache", "cache_settings_clear_cache_button_title": "Efface le cache de l'application. Cela aura un impact significatif sur les performances de l'application jusqu'à ce que le cache soit reconstruit.", "cache_settings_duplicated_assets_clear_button": "EFFACER", "cache_settings_duplicated_assets_subtitle": "Photos et vidÊos qui sont exclues par l'application", "cache_settings_duplicated_assets_title": "ÉlÊments dupliquÊs ({})", "cache_settings_image_cache_size": "Taille du cache des images ({} ÊlÊments)", - "cache_settings_statistics_album": "vignettes de la bibliothèque", + "cache_settings_statistics_album": "Miniatures de la bibliothèque", "cache_settings_statistics_assets": "{} ÊlÊments ({})", "cache_settings_statistics_full": "Images complètes", - "cache_settings_statistics_shared": "vignettes d'albums partagÊs", - "cache_settings_statistics_thumbnail": "vignettes", + "cache_settings_statistics_shared": "Miniatures de l'album partagÊ", + "cache_settings_statistics_thumbnail": "Miniatures", "cache_settings_statistics_title": "Utilisation du cache", "cache_settings_subtitle": "Contrôler le comportement de mise en cache de l'application mobile Immich", - "cache_settings_thumbnail_size": "Taille du cache des vignettes ({} ÊlÊments)", + "cache_settings_thumbnail_size": "Taille du cache des miniatures ({} ÊlÊments)", "cache_settings_tile_subtitle": "Contrôler le comportement du stockage local", "cache_settings_tile_title": "Stockage local", "cache_settings_title": "Paramètres de mise en cache", @@ -654,7 +658,7 @@ "contain": "Contenu", "context": "Contexte", "continue": "Continuer", - "control_bottom_app_bar_album_info_shared": "{} ÊlÊments - PartagÊs", + "control_bottom_app_bar_album_info_shared": "{} ÊlÊments ¡ PartagÊs", "control_bottom_app_bar_create_new_album": "CrÊer un nouvel album", "control_bottom_app_bar_delete_from_immich": "Supprimer de Immich", "control_bottom_app_bar_delete_from_local": "Supprimer de l'appareil", @@ -763,7 +767,7 @@ "download_enqueue": "TÊlÊchargement en attente", "download_error": "Erreur de tÊlÊchargement", "download_failed": "TÊlÊchargement ÊchouÊ", - "download_filename": "fichier : {}", + "download_filename": "fichier : {}", "download_finished": "TÊlÊchargement terminÊ", "download_include_embedded_motion_videos": "VidÊos intÊgrÊes", "download_include_embedded_motion_videos_description": "Inclure des vidÊos intÊgrÊes dans les photos de mouvement comme un fichier sÊparÊ", @@ -819,7 +823,7 @@ "error_change_sort_album": "Impossible de modifier l'ordre de tri des albums", "error_delete_face": "Erreur lors de la suppression du visage pour le mÊdia", "error_loading_image": "Erreur de chargement de l'image", - "error_saving_image": "Erreur : {}", + "error_saving_image": "Erreur : {}", "error_title": "Erreur - Quelque chose s'est mal passÊ", "errors": { "cannot_navigate_next_asset": "Impossible de naviguer jusqu'au prochain mÊdia", @@ -907,7 +911,7 @@ "unable_to_log_out_all_devices": "Incapable de dÊconnecter tous les appareils", "unable_to_log_out_device": "Impossible de dÊconnecter l'appareil", "unable_to_login_with_oauth": "Impossible de se connecter avec OAuth", - "unable_to_play_video": "Impossible de jouer la vidÊo", + "unable_to_play_video": "Impossible de lancer la vidÊo", "unable_to_reassign_assets_existing_person": "Impossible de rÊattribuer les mÊdias à {name, select, null {une personne existante} other {{name}}}", "unable_to_reassign_assets_new_person": "Impossible de rÊattribuer les mÊdias à une nouvelle personne", "unable_to_refresh_user": "Impossible d'actualiser l'utilisateur", @@ -954,9 +958,9 @@ "exif_bottom_sheet_people": "PERSONNES", "exif_bottom_sheet_person_add_person": "Ajouter un nom", "exif_bottom_sheet_person_age": "Âge {}", - "exif_bottom_sheet_person_age_months": "Age {} months", - "exif_bottom_sheet_person_age_year_months": "Age 1 year, {} months", - "exif_bottom_sheet_person_age_years": "Age {}", + "exif_bottom_sheet_person_age_months": "Âge {} mois", + "exif_bottom_sheet_person_age_year_months": "Âge 1 an, {} mois", + "exif_bottom_sheet_person_age_years": "Âge {}", "exit_slideshow": "Quitter le diaporama", "expand_all": "Tout dÊvelopper", "experimental_settings_new_asset_list_subtitle": "En cours de dÊveloppement", @@ -978,7 +982,7 @@ "face_unassigned": "Non attribuÊ", "failed": "Échec", "failed_to_load_assets": "Échec du chargement des ressources", - "failed_to_load_folder": "Impossible d'ouvrir le dossier", + "failed_to_load_folder": "Échec de chargement du dossier", "favorite": "Favori", "favorite_or_unfavorite_photo": "Ajouter ou supprimer des favoris", "favorites": "Favoris", @@ -1282,6 +1286,7 @@ "onboarding_welcome_user": "Bienvenue {user}", "online": "En ligne", "only_favorites": "Uniquement les favoris", + "open": "Ouvert", "open_in_map_view": "Montrer sur la carte", "open_in_openstreetmap": "Ouvrir dans OpenStreetMap", "open_the_search_filters": "Ouvrir les filtres de recherche", @@ -1354,10 +1359,10 @@ "place": "Lieu", "places": "Lieux", "places_count": "{count, plural, one {{count, number} Lieu} other {{count, number} Lieux}}", - "play": "Jouer", + "play": "Lancer", "play_memories": "Lancer les souvenirs", "play_motion_photo": "Jouer la photo animÊe", - "play_or_pause_video": "Jouer ou mettre en pause la vidÊo", + "play_or_pause_video": "Lancer ou mettre en pause la vidÊo", "port": "Port", "preferences_settings_subtitle": "GÊrer les prÊfÊrences de l'application", "preferences_settings_title": "PrÊfÊrences", @@ -1390,7 +1395,7 @@ "purchase_button_reminder": "Me le rappeler dans 30 jours", "purchase_button_remove_key": "Supprimer la clÊ", "purchase_button_select": "SÊlectionner", - "purchase_failed_activation": "Erreur à l'activation. Veuillez vÊrifier votre courriel pour obtenir la clÊ du produit correcte !", + "purchase_failed_activation": "Échec de l'activation. Veuillez vÊrifier votre courriel pour obtenir la clÊ correcte du produit !", "purchase_individual_description_1": "Pour un utilisateur", "purchase_individual_description_2": "Statut de contributeur", "purchase_individual_title": "Utilisateur", @@ -1430,13 +1435,13 @@ "refresh_encoded_videos": "Actualiser les vidÊos encodÊes", "refresh_faces": "Actualiser les visages", "refresh_metadata": "Actualiser les mÊtadonnÊes", - "refresh_thumbnails": "Actualiser les vignettes", + "refresh_thumbnails": "Actualiser les miniatures", "refreshed": "ActualisÊ", "refreshes_every_file": "Actualise tous les fichiers (existants et nouveaux)", "refreshing_encoded_video": "Actualisation de la vidÊo encodÊe", "refreshing_faces": "Actualisation des visages", "refreshing_metadata": "Actualisation des mÊtadonnÊes", - "regenerating_thumbnails": "RegÊnÊration des vignettes", + "regenerating_thumbnails": "RegÊnÊration des miniatures", "remove": "Supprimer", "remove_assets_album_confirmation": "Êtes-vous sÃģr de vouloir supprimer {count, plural, one {# mÊdia} other {# mÊdias}} de l'album ?", "remove_assets_shared_link_confirmation": "Êtes-vous sÃģr de vouloir supprimer {count, plural, one {# mÊdia} other {# mÊdias}} de ce lien partagÊ ?", @@ -1581,16 +1586,16 @@ "set_date_of_birth": "Changer la date de naissance", "set_profile_picture": "DÊfinir la photo de profil", "set_slideshow_to_fullscreen": "Afficher le diaporama en plein Êcran", - "setting_image_viewer_help": "Le visualiseur de dÊtails charge d'abord la petite vignette, puis l'aperçu de taille moyenne (s'il est activÊ), enfin l'original (s'il est activÊ).", + "setting_image_viewer_help": "Le visualiseur de dÊtails charge d'abord la petite miniature, puis l'aperçu de taille moyenne (s'il est activÊ), enfin l'original (s'il est activÊ).", "setting_image_viewer_original_subtitle": "Activez cette option pour charger l'image en rÊsolution originale (volumineux!). DÊsactiver pour rÊduire l'utilisation des donnÊes (rÊseau et cache de l'appareil).", "setting_image_viewer_original_title": "Charger l'image originale", - "setting_image_viewer_preview_subtitle": "Activer pour charger une image de rÊsolution moyenne. DÊsactiver pour charger directement l'original ou utiliser uniquement la vignette.", + "setting_image_viewer_preview_subtitle": "Activer pour charger une image de rÊsolution moyenne. DÊsactiver pour charger directement l'original ou utiliser uniquement la miniature.", "setting_image_viewer_preview_title": "Charger l'image d'aperçu", "setting_image_viewer_title": "Images", "setting_languages_apply": "Appliquer", "setting_languages_subtitle": "Changer la langue de l'application", "setting_languages_title": "Langues", - "setting_notifications_notify_failures_grace_period": "Notifier les Êchecs de la sauvegarde en arrière-plan: {}", + "setting_notifications_notify_failures_grace_period": "Notifier les Êchecs de sauvegarde en arrière-plan : {}", "setting_notifications_notify_hours": "{} heures", "setting_notifications_notify_immediately": "immÊdiatement", "setting_notifications_notify_minutes": "{} minutes", @@ -1609,7 +1614,7 @@ "settings_saved": "Paramètres sauvegardÊs", "share": "Partager", "share_add_photos": "Ajouter des photos", - "share_assets_selected": "{} sÊlÊctionnÊ(s)", + "share_assets_selected": "{} sÊlectionnÊ(s)", "share_dialog_preparing": "PrÊparation...", "shared": "PartagÊ", "shared_album_activities_input_disable": "Les commentaires sont dÊsactivÊs", @@ -1623,10 +1628,10 @@ "shared_by_user": "PartagÊ par {user}", "shared_by_you": "PartagÊ par vous", "shared_from_partner": "Photos de {partner}", - "shared_intent_upload_button_progress_text": "{} / {} TÊlÊversÊ", + "shared_intent_upload_button_progress_text": "{} / {} EnvoyÊs", "shared_link_app_bar_title": "Liens partagÊs", "shared_link_clipboard_copied_massage": "CopiÊ dans le presse-papier\n", - "shared_link_clipboard_text": "\nLien : {}\nMot de passe : {}", + "shared_link_clipboard_text": "Lien : {}\nMot de passe : {}", "shared_link_create_error": "Erreur pendant la crÊation du lien partagÊ", "shared_link_edit_description_hint": "Saisir la description du partage", "shared_link_edit_expire_after_option_day": "1 jour", @@ -1636,7 +1641,7 @@ "shared_link_edit_expire_after_option_minute": "1 minute", "shared_link_edit_expire_after_option_minutes": "{} minutes", "shared_link_edit_expire_after_option_months": "{} mois", - "shared_link_edit_expire_after_option_year": "{} ans", + "shared_link_edit_expire_after_option_year": "{} annÊes", "shared_link_edit_password_hint": "Saisir le mot de passe de partage", "shared_link_edit_submit_button": "Mettre à jour le lien", "shared_link_error_server_url_fetch": "Impossible de rÊcupÊrer l'url du serveur", @@ -1826,7 +1831,7 @@ "upload_status_errors": "Erreurs", "upload_status_uploaded": "EnvoyÊ", "upload_success": "Envoi rÊussi. RafraÃŽchir la page pour voir les nouveaux mÊdias envoyÊs.", - "upload_to_immich": "TÊlÊverser vers Immich ({})", + "upload_to_immich": "Envoyer vers Immich ({})", "uploading": "TÊlÊversement en cours", "url": "URL", "usage": "Utilisation", @@ -1859,7 +1864,7 @@ "version_history_item": "Version {version} installÊe le {date}", "video": "VidÊo", "video_hover_setting": "Lire la miniature des vidÊos au survol", - "video_hover_setting_description": "Jouer la prÊvisualisation vidÊo au survol. Si dÊsactivÊ, la lecture peut quand mÃĒme ÃĒtre dÊmarrÊe en survolant le bouton Play.", + "video_hover_setting_description": "Lancer la prÊvisualisation vidÊo au survol. Si dÊsactivÊ, la lecture peut quand mÃĒme ÃĒtre dÊmarrÊe en survolant le bouton Play.", "videos": "VidÊos", "videos_count": "{count, plural, one {# VidÊo} other {# VidÊos}}", "view": "Voir", diff --git a/i18n/gl.json b/i18n/gl.json index 72cf8d540a..d03294c778 100644 --- a/i18n/gl.json +++ b/i18n/gl.json @@ -4,576 +4,1896 @@ "account_settings": "ConfiguraciÃŗn da conta", "acknowledge": "De acordo", "action": "AcciÃŗn", - "action_common_update": "Update", + "action_common_update": "Actualizar", "actions": "AcciÃŗns", "active": "Activo", "activity": "Actividade", - "activity_changed": "A actividade estÃĄ {enabled, select, true {habilitada} other {deshabilitada}}", + "activity_changed": "A actividade estÃĄ {enabled, select, true {activada} other {desactivada}}", "add": "Engadir", "add_a_description": "Engadir unha descriciÃŗn", - "add_a_location": "Engadir unha localizaciÃŗn", + "add_a_location": "Engadir unha ubicaciÃŗn", "add_a_name": "Engadir un nome", "add_a_title": "Engadir un título", - "add_endpoint": "Add endpoint", + "add_endpoint": "Engadir endpoint", "add_exclusion_pattern": "Engadir patrÃŗn de exclusiÃŗn", "add_import_path": "Engadir ruta de importaciÃŗn", - "add_location": "Engadir localizaciÃŗn", + "add_location": "Engadir ubicaciÃŗn", "add_more_users": "Engadir mÃĄis usuarios", - "add_partner": "Engadir compaÃąeiro", + "add_partner": "Engadir compaÃąeiro/a", "add_path": "Engadir ruta", "add_photos": "Engadir fotos", "add_to": "Engadir aâ€Ļ", "add_to_album": "Engadir ao ÃĄlbum", - "add_to_album_bottom_sheet_added": "Added to {album}", - "add_to_album_bottom_sheet_already_exists": "Already in {album}", + "add_to_album_bottom_sheet_added": "Engadido a {album}", + "add_to_album_bottom_sheet_already_exists": "Xa estÃĄ en {album}", "add_to_shared_album": "Engadir ao ÃĄlbum compartido", "add_url": "Engadir URL", "added_to_archive": "Engadido ao arquivo", "added_to_favorites": "Engadido a favoritos", - "added_to_favorites_count": "Engadidos {count, number} a favoritos", + "added_to_favorites_count": "Engadido {count, number} a favoritos", "admin": { + "add_exclusion_pattern_description": "Engadir patrÃŗns de exclusiÃŗn. Admítense caracteres comodín usando *, ** e ?. Para ignorar todos os ficheiros en calquera directorio chamado \"Raw\", emprega \"**/Raw/**\". Para ignorar todos os ficheiros que rematen en \".tif\", usa \"**/*.tif\". Para ignorar unha ruta absoluta, emprega \"/ruta/a/ignorar/**\".", + "asset_offline_description": "Este activo da biblioteca externa xa non se atopa no disco e moveuse ao lixo. Se o ficheiro se moveu dentro da biblioteca, comproba a tÃēa liÃąa de tempo para o novo activo correspondente. Para restaurar este activo, asegÃērate de que Immich poida acceder ÃĄ ruta do ficheiro a continuaciÃŗn e escanee a biblioteca.", "authentication_settings": "ConfiguraciÃŗn de autenticaciÃŗn", - "authentication_settings_description": "Xestionar contrasinal, OAuth e outros parÃĄmetros de autenticaciÃŗn", - "authentication_settings_disable_all": "EstÃĄs seguro de deshabilitar todos os mÊtodos de inicio de sesiÃŗn? Iniciar a sesiÃŗn quedarÃĄ completamente deshabilitado.", - "authentication_settings_reenable": "Para rehabilitala, usa un Comando do servidor.", + "authentication_settings_description": "Xestionar contrasinal, OAuth e outras configuraciÃŗns de autenticaciÃŗn", + "authentication_settings_disable_all": "EstÃĄs seguro de que queres desactivar todos os mÊtodos de inicio de sesiÃŗn? O inicio de sesiÃŗn desactivarase completamente.", + "authentication_settings_reenable": "Para reactivalo, use un Comando de servidor.", "background_task_job": "Tarefas en segundo plano", - "backup_database": "Respaldo da base de datos", - "backup_database_enable_description": "Habilitar as copias de seguridade da base de datos", - "backup_keep_last_amount": "Cantidade de copias de seguridade previas a manter", - "backup_settings": "ConfiguraciÃŗn de copias de seguridade", - "backup_settings_description": "Xestionar a configuraciÃŗn das copias de seguridade da base de datos", - "check_all": "Comprobar todo", + "backup_database": "Copia de seguridade da base de datos", + "backup_database_enable_description": "Activar copias de seguridade da base de datos", + "backup_keep_last_amount": "Cantidade de copias de seguridade anteriores a conservar", + "backup_settings": "ConfiguraciÃŗn da copia de seguridade", + "backup_settings_description": "Xestionar a configuraciÃŗn da copia de seguridade da base de datos", + "check_all": "Marcar todo", + "cleanup": "Limpeza", "cleared_jobs": "Traballos borrados para: {job}", - "config_set_by_file": "As configuraciÃŗns estÃĄn actualmente seleccionadas por un ficheiro de configuraciÃŗns", + "config_set_by_file": "A configuraciÃŗn establÊcese actualmente mediante un ficheiro de configuraciÃŗn", "confirm_delete_library": "EstÃĄs seguro de que queres eliminar a biblioteca {library}?", - "exclusion_pattern_description": "Os patrÃŗns de exclusiÃŗn permítenche ignorar ficheiros e cartafoles ao escanear a tÃēa biblioteca. Isto Ê Ãētil se tes cartafoles que conteÃąen ficheiros que non queres importar, coma ficheiros RAW.", + "confirm_delete_library_assets": "EstÃĄs seguro de que queres eliminar esta biblioteca? Isto eliminarÃĄ {count, plural, one {# activo contido} other {todos os # activos contidos}} de Immich e non se pode desfacer. Os ficheiros permanecerÃĄn no disco.", + "confirm_email_below": "Para confirmar, escriba \"{email}\" a continuaciÃŗn", + "confirm_reprocess_all_faces": "EstÃĄs seguro de que queres reprocesar todas as caras? Isto tamÊn borrarÃĄ as persoas nomeadas.", + "confirm_user_password_reset": "EstÃĄs seguro de que queres restablecer o contrasinal de {user}?", + "create_job": "Crear traballo", + "cron_expression": "ExpresiÃŗn Cron", + "cron_expression_description": "Estableza o intervalo de escaneo usando o formato cron. Para obter mÃĄis informaciÃŗn, consulte por exemplo Crontab Guru", + "cron_expression_presets": "Preaxustes de expresiÃŗn Cron", + "disable_login": "Desactivar inicio de sesiÃŗn", + "duplicate_detection_job_description": "Executar aprendizaxe automÃĄtica nos activos para detectar imaxes similares. Depende da Busca Intelixente", + "exclusion_pattern_description": "Os patrÃŗns de exclusiÃŗn permítenche ignorar ficheiros e cartafoles ao escanear a tÃēa biblioteca. Isto Ê Ãētil se tes cartafoles que conteÃąen ficheiros que non queres importar, como ficheiros RAW.", "external_library_created_at": "Biblioteca externa (creada o {date})", - "external_library_management": "XestiÃŗn de bibliotecas externas", + "external_library_management": "XestiÃŗn da biblioteca externa", "face_detection": "DetecciÃŗn de caras", - "job_settings": "ConfiguraciÃŗn de tarefas", - "job_settings_description": "Administrar tarefas simultÃĄneas", - "job_status": "Estado da tarefa", - "jobs_failed": "{jobCount, one {# errado}, plural, other {# errados}}", - "note_cannot_be_changed_later": "NOTA: Non editable posteriormente!", - "notification_email_host_description": "Host do servidor de correo electrÃŗnico (p. ex.: smtp.immich.app)", + "face_detection_description": "Detectar as caras nos activos usando aprendizaxe automÃĄtica. Para vídeos, sÃŗ se considera a miniatura. \"Actualizar\" (re)procesa todos os activos. \"Restablecer\" ademais borra todos os datos de caras actuais. \"Faltantes\" pon en cola os activos que aínda non foron procesados. As caras detectadas poranse en cola para o RecoÃąecemento Facial despois de completar a DetecciÃŗn de Caras, agrupÃĄndoas en persoas existentes ou novas.", + "facial_recognition_job_description": "Agrupar caras detectadas en persoas. Este paso execÃētase despois de completar a DetecciÃŗn de Caras. \"Restablecer\" (re)agrupa todas as caras. \"Faltantes\" pon en cola as caras que non teÃąen unha persoa asignada.", + "failed_job_command": "O comando {command} fallou para o traballo: {job}", + "force_delete_user_warning": "AVISO: Isto eliminarÃĄ inmediatamente o usuario e todos os activos. Isto non se pode desfacer e os ficheiros non se poden recuperar.", + "forcing_refresh_library_files": "Forzando a actualizaciÃŗn de todos os ficheiros da biblioteca", + "image_format": "Formato", + "image_format_description": "WebP produce ficheiros mÃĄis pequenos que JPEG, pero Ê mÃĄis lento de codificar.", + "image_fullsize_description": "Imaxe a tamaÃąo completo con metadatos eliminados, usada ao facer zoom", + "image_fullsize_enabled": "Activar a xeraciÃŗn de imaxes a tamaÃąo completo", + "image_fullsize_enabled_description": "Xerar imaxe a tamaÃąo completo para formatos non compatibles coa web. Cando \"Preferir vista previa incrustada\" estÃĄ activado, as vistas previas incrustadas utilízanse directamente sen conversiÃŗn. Non afecta a formatos compatibles coa web como JPEG.", + "image_fullsize_quality_description": "Calidade da imaxe a tamaÃąo completo de 1 a 100. MÃĄis alto Ê mellor, pero produce ficheiros mÃĄis grandes.", + "image_fullsize_title": "ConfiguraciÃŗn da imaxe a tamaÃąo completo", + "image_prefer_embedded_preview": "Preferir vista previa incrustada", + "image_prefer_embedded_preview_setting_description": "Usar vistas previas incrustadas en fotos RAW como entrada para o procesamento de imaxes e cando estean dispoÃąibles. Isto pode producir cores mÃĄis precisas para algunhas imaxes, pero a calidade da vista previa depende da cÃĄmara e a imaxe pode ter mÃĄis artefactos de compresiÃŗn.", + "image_prefer_wide_gamut": "Preferir gama ampla", + "image_prefer_wide_gamut_setting_description": "Usar Display P3 para as miniaturas. Isto preserva mellor a viveza das imaxes con espazos de cor amplos, pero as imaxes poden aparecer de forma diferente en dispositivos antigos cunha versiÃŗn de navegador antiga. As imaxes sRGB mantÃŠÃąense como sRGB para evitar cambios de cor.", + "image_preview_description": "Imaxe de tamaÃąo medio con metadatos eliminados, usada ao ver un Ãēnico activo e para aprendizaxe automÃĄtica", + "image_preview_quality_description": "Calidade da vista previa de 1 a 100. MÃĄis alto Ê mellor, pero produce ficheiros mÃĄis grandes e pode reducir a capacidade de resposta da aplicaciÃŗn. Establecer un valor baixo pode afectar ÃĄ calidade da aprendizaxe automÃĄtica.", + "image_preview_title": "ConfiguraciÃŗn da vista previa", + "image_quality": "Calidade", + "image_resolution": "ResoluciÃŗn", + "image_resolution_description": "ResoluciÃŗns mÃĄis altas poden preservar mÃĄis detalles pero tardan mÃĄis en codificarse, teÃąen tamaÃąos de ficheiro mÃĄis grandes e poden reducir a capacidade de resposta da aplicaciÃŗn.", + "image_settings": "ConfiguraciÃŗn da imaxe", + "image_settings_description": "Xestionar a calidade e resoluciÃŗn das imaxes xeradas", + "image_thumbnail_description": "Miniatura pequena con metadatos eliminados, usada ao ver grupos de fotos como a liÃąa de tempo principal", + "image_thumbnail_quality_description": "Calidade da miniatura de 1 a 100. MÃĄis alto Ê mellor, pero produce ficheiros mÃĄis grandes e pode reducir a capacidade de resposta da aplicaciÃŗn.", + "image_thumbnail_title": "ConfiguraciÃŗn da miniatura", + "job_concurrency": "concorrencia de {job}", + "job_created": "Traballo creado", + "job_not_concurrency_safe": "Este traballo non Ê seguro para concorrencia.", + "job_settings": "ConfiguraciÃŗn de traballos", + "job_settings_description": "Xestionar a concorrencia de traballos", + "job_status": "Estado do traballo", + "jobs_delayed": "{jobCount, plural, other {# atrasados}}", + "jobs_failed": "{jobCount, plural, other {# fallados}}", + "library_created": "Biblioteca creada: {library}", + "library_deleted": "Biblioteca eliminada", + "library_import_path_description": "Especifique un cartafol para importar. Este cartafol, incluídos os subcartafoles, escanearase en busca de imaxes e vídeos.", + "library_scanning": "Escaneo periÃŗdico", + "library_scanning_description": "Configurar o escaneo periÃŗdico da biblioteca", + "library_scanning_enable_description": "Activar o escaneo periÃŗdico da biblioteca", + "library_settings": "Biblioteca externa", + "library_settings_description": "Xestionar a configuraciÃŗn da biblioteca externa", + "library_tasks_description": "Escanear bibliotecas externas en busca de activos novos e/ou modificados", + "library_watching_enable_description": "Vixiar bibliotecas externas para cambios nos ficheiros", + "library_watching_settings": "Vixilancia da biblioteca (EXPERIMENTAL)", + "library_watching_settings_description": "Vixiar automaticamente os ficheiros modificados", + "logging_enable_description": "Activar rexistro", + "logging_level_description": "Cando estea activado, que nivel de rexistro usar.", + "logging_settings": "Rexistro", + "machine_learning_clip_model": "Modelo CLIP", + "machine_learning_clip_model_description": "O nome dun modelo CLIP listado aquí. Ten en conta que debe volver executar o traballo 'Busca Intelixente' para todas as imaxes ao cambiar un modelo.", + "machine_learning_duplicate_detection": "DetecciÃŗn de duplicados", + "machine_learning_duplicate_detection_enabled": "Activar detecciÃŗn de duplicados", + "machine_learning_duplicate_detection_enabled_description": "Se estÃĄ desactivado, os activos exactamente idÊnticos aínda se eliminarÃĄn duplicados.", + "machine_learning_duplicate_detection_setting_description": "Usar incrustaciÃŗns CLIP para atopar posibles duplicados", + "machine_learning_enabled": "Activar aprendizaxe automÃĄtica", + "machine_learning_enabled_description": "Se estÃĄ desactivado, todas as funciÃŗns de ML desactivaranse independentemente da configuraciÃŗn a continuaciÃŗn.", + "machine_learning_facial_recognition": "RecoÃąecemento facial", + "machine_learning_facial_recognition_description": "Detectar, recoÃąecer e agrupar caras en imaxes", + "machine_learning_facial_recognition_model": "Modelo de recoÃąecemento facial", + "machine_learning_facial_recognition_model_description": "Os modelos estÃĄn listados en orde descendente de tamaÃąo. Os modelos mÃĄis grandes son mÃĄis lentos e usan mÃĄis memoria, pero producen mellores resultados. TeÃąa en conta que debes volver executar o traballo de DetecciÃŗn de Caras para todas as imaxes ao cambiar un modelo.", + "machine_learning_facial_recognition_setting": "Activar recoÃąecemento facial", + "machine_learning_facial_recognition_setting_description": "Se estÃĄ desactivado, as imaxes non se codificarÃĄn para o recoÃąecemento facial e non encherÃĄn a secciÃŗn Persoas na pÃĄxina Explorar.", + "machine_learning_max_detection_distance": "Distancia mÃĄxima de detecciÃŗn", + "machine_learning_max_detection_distance_description": "Distancia mÃĄxima entre dÃēas imaxes para consideralas duplicadas, variando de 0.001 a 0.1. Valores mÃĄis altos detectarÃĄn mÃĄis duplicados, pero poden resultar en falsos positivos.", + "machine_learning_max_recognition_distance": "Distancia mÃĄxima de recoÃąecemento", + "machine_learning_max_recognition_distance_description": "Distancia mÃĄxima entre dÃēas caras para ser consideradas a mesma persoa, variando de 0 a 2. Baixar isto pode evitar etiquetar dÃēas persoas como a mesma persoa, mentres que subilo pode evitar etiquetar a mesma persoa como dÃēas persoas diferentes. TeÃąa en conta que Ê mÃĄis fÃĄcil fusionar dÃēas persoas que dividir unha persoa en dÃēas, así que erre polo lado dun limiar mÃĄis baixo cando sexa posible.", + "machine_learning_min_detection_score": "PuntuaciÃŗn mínima de detecciÃŗn", + "machine_learning_min_detection_score_description": "PuntuaciÃŗn mínima de confianza para que unha cara sexa detectada, de 0 a 1. Valores mÃĄis baixos detectarÃĄn mÃĄis caras pero poden resultar en falsos positivos.", + "machine_learning_min_recognized_faces": "Mínimo de caras recoÃąecidas", + "machine_learning_min_recognized_faces_description": "O nÃēmero mínimo de caras recoÃąecidas para que se cree unha persoa. Aumentar isto fai que o RecoÃąecemento Facial sexa mÃĄis preciso a costa de aumentar a posibilidade de que unha cara non se asigne a unha persoa.", + "machine_learning_settings": "ConfiguraciÃŗn da Aprendizaxe AutomÃĄtica", + "machine_learning_settings_description": "Xestionar funciÃŗns e configuraciÃŗns da aprendizaxe automÃĄtica", + "machine_learning_smart_search": "Busca Intelixente", + "machine_learning_smart_search_description": "Buscar imaxes semanticamente usando incrustaciÃŗns CLIP", + "machine_learning_smart_search_enabled": "Activar busca intelixente", + "machine_learning_smart_search_enabled_description": "Se estÃĄ desactivado, as imaxes non se codificarÃĄn para a busca intelixente.", + "machine_learning_url_description": "A URL do servidor de aprendizaxe automÃĄtica. Se se proporciona mÃĄis dunha URL, intentarase con cada servidor un por un ata que un responda correctamente, en orde do primeiro ao Ãēltimo. Os servidores que non respondan ignoraranse temporalmente ata que volvan estar en liÃąa.", + "manage_concurrency": "Xestionar Concorrencia", + "manage_log_settings": "Xestionar configuraciÃŗn de rexistro", + "map_dark_style": "Estilo escuro", + "map_enable_description": "Activar funciÃŗns do mapa", + "map_gps_settings": "ConfiguraciÃŗn do Mapa e GPS", + "map_gps_settings_description": "Xestionar a configuraciÃŗn do Mapa e GPS (XeocodificaciÃŗn Inversa)", + "map_implications": "A funciÃŗn do mapa depende dun servizo de teselas externo (tiles.immich.cloud)", + "map_light_style": "Estilo claro", + "map_manage_reverse_geocoding_settings": "Xestionar configuraciÃŗn de XeocodificaciÃŗn Inversa", + "map_reverse_geocoding": "XeocodificaciÃŗn Inversa", + "map_reverse_geocoding_enable_description": "Activar xeocodificaciÃŗn inversa", + "map_reverse_geocoding_settings": "ConfiguraciÃŗn da XeocodificaciÃŗn Inversa", + "map_settings": "Mapa", + "map_settings_description": "Xestionar a configuraciÃŗn do mapa", + "map_style_description": "URL a un tema de mapa style.json", + "memory_cleanup_job": "Limpeza de recordos", + "memory_generate_job": "XeraciÃŗn de recordos", + "metadata_extraction_job": "Extraer metadatos", + "metadata_extraction_job_description": "Extraer informaciÃŗn de metadatos de cada activo, como GPS, caras e resoluciÃŗn", + "metadata_faces_import_setting": "Activar importaciÃŗn de caras", + "metadata_faces_import_setting_description": "Importar caras dos datos EXIF da imaxe e ficheiros sidecar", + "metadata_settings": "ConfiguraciÃŗn de Metadatos", + "metadata_settings_description": "Xestionar a configuraciÃŗn de metadatos", + "migration_job": "MigraciÃŗn", + "migration_job_description": "Migrar miniaturas de activos e caras ÃĄ Ãēltima estrutura de cartafoles", + "no_paths_added": "Non se engadiron rutas", + "no_pattern_added": "Non se engadiu ningÃēn padrÃŗn", + "note_apply_storage_label_previous_assets": "Nota: Para aplicar a Etiqueta de Almacenamento a activos cargados previamente, execute o", + "note_cannot_be_changed_later": "NOTA: Isto non se pode cambiar mÃĄis tarde!", + "notification_email_from_address": "Enderezo do remitente", + "notification_email_from_address_description": "Enderezo de correo electrÃŗnico do remitente, por exemplo: \"Servidor de Fotos Immich \"", + "notification_email_host_description": "Host do servidor de correo electrÃŗnico (p. ex. smtp.immich.app)", "notification_email_ignore_certificate_errors": "Ignorar erros de certificado", - "notification_email_ignore_certificate_errors_description": "Ignorar erros de validaciÃŗn de certificados TLS (non recomendado)", - "notification_settings": "ConfiguraciÃŗn de notificaciÃŗns" + "notification_email_ignore_certificate_errors_description": "Ignorar erros de validaciÃŗn do certificado TLS (non recomendado)", + "notification_email_password_description": "Contrasinal a usar ao autenticarse co servidor de correo electrÃŗnico", + "notification_email_port_description": "Porto do servidor de correo electrÃŗnico (p. ex. 25, 465 ou 587)", + "notification_email_sent_test_email_button": "Enviar correo de proba e gardar", + "notification_email_setting_description": "ConfiguraciÃŗn para enviar notificaciÃŗns por correo electrÃŗnico", + "notification_email_test_email": "Enviar correo de proba", + "notification_email_test_email_failed": "Erro ao enviar correo de proba, comproba os teus valores", + "notification_email_test_email_sent": "Enviouse un correo electrÃŗnico de proba a {email}. Por favor, comproba a tÃēa caixa de entrada.", + "notification_email_username_description": "Nome de usuario a usar ao autenticarse co servidor de correo electrÃŗnico", + "notification_enable_email_notifications": "Activar notificaciÃŗns por correo electrÃŗnico", + "notification_settings": "ConfiguraciÃŗn de NotificaciÃŗns", + "notification_settings_description": "Xestionar a configuraciÃŗn de notificaciÃŗns, incluído o correo electrÃŗnico", + "oauth_auto_launch": "Lanzamento automÃĄtico", + "oauth_auto_launch_description": "Iniciar o fluxo de inicio de sesiÃŗn OAuth automaticamente ao navegar ÃĄ pÃĄxina de inicio de sesiÃŗn", + "oauth_auto_register": "Rexistro automÃĄtico", + "oauth_auto_register_description": "Rexistrar automaticamente novos usuarios despois de iniciar sesiÃŗn con OAuth", + "oauth_button_text": "Texto do botÃŗn", + "oauth_client_id": "ID de cliente", + "oauth_client_secret": "Segredo do cliente", + "oauth_enable_description": "Iniciar sesiÃŗn con OAuth", + "oauth_issuer_url": "URL do emisor", + "oauth_mobile_redirect_uri": "URI de redirecciÃŗn mÃŗbil", + "oauth_mobile_redirect_uri_override": "SubstituciÃŗn de URI de redirecciÃŗn mÃŗbil", + "oauth_mobile_redirect_uri_override_description": "Activar cando o provedor OAuth non permite un URI mÃŗbil, como '{callback}'", + "oauth_profile_signing_algorithm": "Algoritmo de sinatura do perfil", + "oauth_profile_signing_algorithm_description": "Algoritmo usado para asinar o perfil do usuario.", + "oauth_scope": "Ámbito", + "oauth_settings": "OAuth", + "oauth_settings_description": "Xestionar a configuraciÃŗn de inicio de sesiÃŗn OAuth", + "oauth_settings_more_details": "Para mÃĄis detalles sobre esta funciÃŗn, consulte a documentaciÃŗn.", + "oauth_signing_algorithm": "Algoritmo de sinatura", + "oauth_storage_label_claim": "DeclaraciÃŗn de etiqueta de almacenamento", + "oauth_storage_label_claim_description": "Establecer automaticamente a etiqueta de almacenamento do usuario ao valor desta declaraciÃŗn.", + "oauth_storage_quota_claim": "DeclaraciÃŗn de cota de almacenamento", + "oauth_storage_quota_claim_description": "Establecer automaticamente a cota de almacenamento do usuario ao valor desta declaraciÃŗn.", + "oauth_storage_quota_default": "Cota de almacenamento predeterminada (GiB)", + "oauth_storage_quota_default_description": "Cota en GiB a usar cando non se proporciona ningunha declaraciÃŗn (Introduza 0 para cota ilimitada).", + "offline_paths": "Rutas fÃŗra de liÃąa", + "offline_paths_description": "Estes resultados poden deberse ÃĄ eliminaciÃŗn manual de ficheiros que non forman parte dunha biblioteca externa.", + "password_enable_description": "Iniciar sesiÃŗn con correo electrÃŗnico e contrasinal", + "password_settings": "Inicio de sesiÃŗn con contrasinal", + "password_settings_description": "Xestionar a configuraciÃŗn de inicio de sesiÃŗn con contrasinal", + "paths_validated_successfully": "Todas as rutas validadas correctamente", + "person_cleanup_job": "Limpeza de persoas", + "quota_size_gib": "TamaÃąo da cota (GiB)", + "refreshing_all_libraries": "Actualizando todas as bibliotecas", + "registration": "Rexistro do administrador", + "registration_description": "Dado que ti es o primeiro usuario no sistema, asignarÃĄsete como Administrador e serÃĄs responsable das tarefas administrativas, e os usuarios adicionais serÃĄn creados por ti.", + "repair_all": "Reparar todo", + "repair_matched_items": "Coincidiron {count, plural, one {# elemento} other {# elementos}}", + "repaired_items": "ReparÃĄronse {count, plural, one {# elemento} other {# elementos}}", + "require_password_change_on_login": "Requirir que o usuario cambie o contrasinal no primeiro inicio de sesiÃŗn", + "reset_settings_to_default": "Restablecer a configuraciÃŗn aos valores predeterminados", + "reset_settings_to_recent_saved": "Restablecer a configuraciÃŗn ÃĄ configuraciÃŗn gardada recentemente", + "scanning_library": "Escaneando biblioteca", + "search_jobs": "Buscar traballosâ€Ļ", + "send_welcome_email": "Enviar correo electrÃŗnico de benvida", + "server_external_domain_settings": "Dominio externo", + "server_external_domain_settings_description": "Dominio para ligazÃŗns pÃēblicas compartidas, incluíndo http(s)://", + "server_public_users": "Usuarios pÃēblicos", + "server_public_users_description": "Todos os usuarios (nome e correo electrÃŗnico) listanse ao engadir un usuario a ÃĄlbums compartidos. Cando estÃĄ desactivado, a lista de usuarios sÃŗ estarÃĄ dispoÃąible para os usuarios administradores.", + "server_settings": "ConfiguraciÃŗn do servidor", + "server_settings_description": "Xestionar a configuraciÃŗn do servidor", + "server_welcome_message": "Mensaxe de benvida", + "server_welcome_message_description": "Unha mensaxe que se mostra na pÃĄxina de inicio de sesiÃŗn.", + "sidecar_job": "Metadatos Sidecar", + "sidecar_job_description": "Descubrir ou sincronizar metadatos sidecar desde o sistema de ficheiros", + "slideshow_duration_description": "NÃēmero de segundos para mostrar cada imaxe", + "smart_search_job_description": "Executar aprendizaxe automÃĄtica nos activos para soportar a busca intelixente", + "storage_template_date_time_description": "A marca de tempo de creaciÃŗn do activo Ãēsase para a informaciÃŗn de data e hora", + "storage_template_date_time_sample": "Tempo de mostra {date}", + "storage_template_enable_description": "Activar o motor de modelos de almacenamento", + "storage_template_hash_verification_enabled": "VerificaciÃŗn de hash activada", + "storage_template_hash_verification_enabled_description": "Activa a verificaciÃŗn de hash, non desactives isto a menos que esteas seguro das implicaciÃŗns", + "storage_template_migration": "MigraciÃŗn do modelo de almacenamento", + "storage_template_migration_description": "Aplicar o {template} actual aos activos cargados previamente", + "storage_template_migration_info": "O modelo de almacenamento converterÃĄ todas as extensiÃŗns a minÃēsculas. Os cambios no modelo sÃŗ se aplicarÃĄn aos activos novos. Para aplicar retroactivamente o modelo aos activos cargados previamente, execute o {job}.", + "storage_template_migration_job": "Traballo de MigraciÃŗn do Modelo de Almacenamento", + "storage_template_more_details": "Para mÃĄis detalles sobre esta funciÃŗn, consulte o Modelo de Almacenamento e as sÃēas implicaciÃŗns", + "storage_template_onboarding_description": "Cando estea activada, esta funciÃŗn autoorganizarÃĄ os ficheiros baseÃĄndose nun modelo definido polo usuario. Debido a problemas de estabilidade, a funciÃŗn desactivouse por defecto. Para obter mÃĄis informaciÃŗn, consulte a documentaciÃŗn.", + "storage_template_path_length": "Límite aproximado da lonxitude da ruta: {length, number}/{limit, number}", + "storage_template_settings": "Modelo de Almacenamento", + "storage_template_settings_description": "Xestionar a estrutura de cartafoles e o nome de ficheiro do activo cargado", + "storage_template_user_label": "{label} Ê a Etiqueta de Almacenamento do usuario", + "system_settings": "ConfiguraciÃŗn do Sistema", + "tag_cleanup_job": "Limpeza de etiquetas", + "template_email_available_tags": "Podes usar as seguintes variables no teu modelo: {tags}", + "template_email_if_empty": "Se o modelo estÃĄ baleiro, usarase o correo electrÃŗnico predeterminado.", + "template_email_invite_album": "Modelo de InvitaciÃŗn a Álbum", + "template_email_preview": "Vista previa", + "template_email_settings": "Modelos de Correo ElectrÃŗnico", + "template_email_settings_description": "Xestionar modelos personalizados de notificaciÃŗn por correo electrÃŗnico", + "template_email_update_album": "Modelo de ActualizaciÃŗn de Álbum", + "template_email_welcome": "Modelo de correo electrÃŗnico de benvida", + "template_settings": "Modelos de NotificaciÃŗn", + "template_settings_description": "Xestionar modelos personalizados para notificaciÃŗns.", + "theme_custom_css_settings": "CSS Personalizado", + "theme_custom_css_settings_description": "As Follas de Estilo en Cascada permiten personalizar o deseÃąo de Immich.", + "theme_settings": "ConfiguraciÃŗn do Tema", + "theme_settings_description": "Xestionar a personalizaciÃŗn da interface web de Immich", + "these_files_matched_by_checksum": "Estes ficheiros coinciden polas sÃēas sumas de verificaciÃŗn", + "thumbnail_generation_job": "Xerar Miniaturas", + "thumbnail_generation_job_description": "Xerar miniaturas grandes, pequenas e borrosas para cada activo, así como miniaturas para cada persoa", + "transcoding_acceleration_api": "API de aceleraciÃŗn", + "transcoding_acceleration_api_description": "A API que interactuarÃĄ co teu dispositivo para acelerar a transcodificaciÃŗn. Esta configuraciÃŗn Ê de 'mellor esforzo': recurrirÃĄ ÃĄ transcodificaciÃŗn por software en caso de fallo. VP9 pode funcionar ou non dependendo do teu hardware.", + "transcoding_acceleration_nvenc": "NVENC (require GPU NVIDIA)", + "transcoding_acceleration_qsv": "Quick Sync (require CPU Intel de 7ÂĒ xeraciÃŗn ou posterior)", + "transcoding_acceleration_rkmpp": "RKMPP (sÃŗ en SOCs Rockchip)", + "transcoding_acceleration_vaapi": "VAAPI", + "transcoding_accepted_audio_codecs": "CÃŗdecs de audio aceptados", + "transcoding_accepted_audio_codecs_description": "Seleccione que cÃŗdecs de audio non necesitan ser transcodificados. SÃŗ se usa para certas políticas de transcodificaciÃŗn.", + "transcoding_accepted_containers": "Contedores aceptados", + "transcoding_accepted_containers_description": "Seleccione que formatos de contedor non necesitan ser remuxados a MP4. SÃŗ se usa para certas políticas de transcodificaciÃŗn.", + "transcoding_accepted_video_codecs": "CÃŗdecs de vídeo aceptados", + "transcoding_accepted_video_codecs_description": "Seleccione que cÃŗdecs de vídeo non necesitan ser transcodificados. SÃŗ se usa para certas políticas de transcodificaciÃŗn.", + "transcoding_advanced_options_description": "OpciÃŗns que a maioría dos usuarios non deberían necesitar cambiar", + "transcoding_audio_codec": "CÃŗdec de audio", + "transcoding_audio_codec_description": "Opus Ê a opciÃŗn de maior calidade, pero ten menor compatibilidade con dispositivos ou software antigos.", + "transcoding_bitrate_description": "Vídeos cun bitrate superior ao mÃĄximo ou que non estean nun formato aceptado", + "transcoding_codecs_learn_more": "Para saber mÃĄis sobre a terminoloxía usada aquí, consulte a documentaciÃŗn de FFmpeg para cÃŗdec H.264, cÃŗdec HEVC e cÃŗdec VP9.", + "transcoding_constant_quality_mode": "Modo de calidade constante", + "transcoding_constant_quality_mode_description": "ICQ Ê mellor que CQP, pero algÃēns dispositivos de aceleraciÃŗn por hardware non admiten este modo. Establecer esta opciÃŗn preferirÃĄ o modo especificado ao usar codificaciÃŗn baseada na calidade. Ignorado por NVENC xa que non admite ICQ.", + "transcoding_constant_rate_factor": "Factor de taxa constante (-crf)", + "transcoding_constant_rate_factor_description": "Nivel de calidade do vídeo. Valores típicos son 23 para H.264, 28 para HEVC, 31 para VP9 e 35 para AV1. MÃĄis baixo Ê mellor, pero produce ficheiros mÃĄis grandes.", + "transcoding_disabled_description": "Non transcodificar ningÃēn vídeo, pode romper a reproduciÃŗn nalgÃēns clientes", + "transcoding_encoding_options": "OpciÃŗns de CodificaciÃŗn", + "transcoding_encoding_options_description": "Establecer cÃŗdecs, resoluciÃŗn, calidade e outras opciÃŗns para os vídeos codificados", + "transcoding_hardware_acceleration": "AceleraciÃŗn por Hardware", + "transcoding_hardware_acceleration_description": "Experimental; moito mÃĄis rÃĄpido, pero terÃĄ menor calidade co mesmo bitrate", + "transcoding_hardware_decoding": "DecodificaciÃŗn por hardware", + "transcoding_hardware_decoding_setting_description": "Activa a aceleraciÃŗn de extremo a extremo en lugar de sÃŗ acelerar a codificaciÃŗn. Pode non funcionar en todos os vídeos.", + "transcoding_hevc_codec": "CÃŗdec HEVC", + "transcoding_max_b_frames": "MÃĄximo de B-frames", + "transcoding_max_b_frames_description": "Valores mÃĄis altos melloran a eficiencia da compresiÃŗn, pero ralentizan a codificaciÃŗn. Pode non ser compatible coa aceleraciÃŗn por hardware en dispositivos mÃĄis antigos. 0 desactiva os B-frames, mentres que -1 establece este valor automaticamente.", + "transcoding_max_bitrate": "Bitrate mÃĄximo", + "transcoding_max_bitrate_description": "Establecer un bitrate mÃĄximo pode facer que os tamaÃąos dos ficheiros sexan mÃĄis predicibles a un custo menor para a calidade. A 720p, os valores típicos son 2600 kbit/s para VP9 ou HEVC, ou 4500 kbit/s para H.264. Desactivado se se establece en 0.", + "transcoding_max_keyframe_interval": "Intervalo mÃĄximo de fotogramas clave", + "transcoding_max_keyframe_interval_description": "Establece a distancia mÃĄxima de fotogramas entre fotogramas clave. Valores mÃĄis baixos empeoran a eficiencia da compresiÃŗn, pero melloran os tempos de busca e poden mellorar a calidade en escenas con movemento rÃĄpido. 0 establece este valor automaticamente.", + "transcoding_optimal_description": "Vídeos cunha resoluciÃŗn superior ÃĄ obxectivo ou que non estean nun formato aceptado", + "transcoding_policy": "Política de TranscodificaciÃŗn", + "transcoding_policy_description": "Establecer cando se transcodificarÃĄ un vídeo", + "transcoding_preferred_hardware_device": "Dispositivo de hardware preferido", + "transcoding_preferred_hardware_device_description": "Aplícase sÃŗ a VAAPI e QSV. Establece o nodo dri usado para a transcodificaciÃŗn por hardware.", + "transcoding_preset_preset": "Preaxuste (-preset)", + "transcoding_preset_preset_description": "Velocidade de compresiÃŗn. Preaxustes mÃĄis lentos producen ficheiros mÃĄis pequenos e aumentan a calidade ao apuntar a un certo bitrate. VP9 ignora velocidades superiores a 'faster'.", + "transcoding_reference_frames": "Fotogramas de referencia", + "transcoding_reference_frames_description": "O nÃēmero de fotogramas aos que facer referencia ao comprimir un fotograma dado. Valores mÃĄis altos melloran a eficiencia da compresiÃŗn, pero ralentizan a codificaciÃŗn. 0 establece este valor automaticamente.", + "transcoding_required_description": "SÃŗ vídeos que non estean nun formato aceptado", + "transcoding_settings": "ConfiguraciÃŗn da TranscodificaciÃŗn de Vídeo", + "transcoding_settings_description": "Xestionar que vídeos transcodificar e como procesalos", + "transcoding_target_resolution": "ResoluciÃŗn obxectivo", + "transcoding_target_resolution_description": "ResoluciÃŗns mÃĄis altas poden preservar mÃĄis detalles pero tardan mÃĄis en codificarse, teÃąen tamaÃąos de ficheiro mÃĄis grandes e poden reducir a capacidade de resposta da aplicaciÃŗn.", + "transcoding_temporal_aq": "AQ Temporal", + "transcoding_temporal_aq_description": "Aplícase sÃŗ a NVENC. Aumenta a calidade de escenas de alto detalle e baixo movemento. Pode non ser compatible con dispositivos mÃĄis antigos.", + "transcoding_threads": "Fíos", + "transcoding_threads_description": "Valores mÃĄis altos levan a unha codificaciÃŗn mÃĄis rÃĄpida, pero deixan menos marxe para que o servidor procese outras tarefas mentres estÃĄ activo. Este valor non debería ser maior que o nÃēmero de nÃēcleos da CPU. Maximiza a utilizaciÃŗn se se establece en 0.", + "transcoding_tone_mapping": "Mapeo de tons", + "transcoding_tone_mapping_description": "Intenta preservar a aparencia dos vídeos HDR cando se converten a SDR. Cada algoritmo fai diferentes compromisos para cor, detalle e brillo. Hable preserva o detalle, Mobius preserva a cor e Reinhard preserva o brillo.", + "transcoding_transcode_policy": "Política de transcodificaciÃŗn", + "transcoding_transcode_policy_description": "Política para cando un vídeo debe ser transcodificado. Os vídeos HDR sempre serÃĄn transcodificados (excepto se a transcodificaciÃŗn estÃĄ desactivada).", + "transcoding_two_pass_encoding": "CodificaciÃŗn en dous pasos", + "transcoding_two_pass_encoding_setting_description": "Transcodificar en dous pasos para producir vídeos codificados mellor. Cando o bitrate mÃĄximo estÃĄ activado (requirido para que funcione con H.264 e HEVC), este modo usa un rango de bitrate baseado no bitrate mÃĄximo e ignora CRF. Para VP9, pÃŗdese usar CRF se o bitrate mÃĄximo estÃĄ desactivado.", + "transcoding_video_codec": "CÃŗdec de vídeo", + "transcoding_video_codec_description": "VP9 ten alta eficiencia e compatibilidade web, pero tarda mÃĄis en transcodificarse. HEVC ten un rendemento similar, pero ten menor compatibilidade web. H.264 Ê amplamente compatible e rÃĄpido de transcodificar, pero produce ficheiros moito mÃĄis grandes. AV1 Ê o cÃŗdec mÃĄis eficiente pero carece de soporte en dispositivos mÃĄis antigos.", + "trash_enabled_description": "Activar funciÃŗns do Lixo", + "trash_number_of_days": "NÃēmero de días", + "trash_number_of_days_description": "NÃēmero de días para manter os activos no lixo antes de eliminalos permanentemente", + "trash_settings": "ConfiguraciÃŗn do Lixo", + "trash_settings_description": "Xestionar a configuraciÃŗn do lixo", + "untracked_files": "Ficheiros non rastrexados", + "untracked_files_description": "Estes ficheiros non son rastrexados pola aplicaciÃŗn. Poden ser o resultado de movementos fallidos, cargas interrompidas ou deixados atrÃĄs debido a un erro", + "user_cleanup_job": "Limpeza de usuarios", + "user_delete_delay": "A conta e os activos de {user} programaranse para a sÃēa eliminaciÃŗn permanente en {delay, plural, one {# día} other {# días}}.", + "user_delete_delay_settings": "Atraso na eliminaciÃŗn", + "user_delete_delay_settings_description": "NÃēmero de días despois da eliminaciÃŗn para eliminar permanentemente a conta e os activos dun usuario. O traballo de eliminaciÃŗn de usuarios execÃētase ÃĄ medianoite para comprobar os usuarios que estÃĄn listos para a eliminaciÃŗn. Os cambios nesta configuraciÃŗn avaliaranse na prÃŗxima execuciÃŗn.", + "user_delete_immediately": "A conta e os activos de {user} poranse en cola para a sÃēa eliminaciÃŗn permanente inmediatamente.", + "user_delete_immediately_checkbox": "PoÃąer en cola o usuario e os activos para a sÃēa eliminaciÃŗn inmediata", + "user_management": "XestiÃŗn de Usuarios", + "user_password_has_been_reset": "Restableceuse o contrasinal do usuario:", + "user_password_reset_description": "Proporcione o contrasinal temporal ao usuario e infÃŗrmelle de que necesitarÃĄ cambiar o contrasinal no seu prÃŗximo inicio de sesiÃŗn.", + "user_restore_description": "Restaurarase a conta de {user}.", + "user_restore_scheduled_removal": "Restaurar usuario - eliminaciÃŗn programada o {date, date, long}", + "user_settings": "ConfiguraciÃŗn do Usuario", + "user_settings_description": "Xestionar a configuraciÃŗn do usuario", + "user_successfully_removed": "Usuario {email} eliminado correctamente.", + "version_check_enabled_description": "Activar comprobaciÃŗn de versiÃŗn", + "version_check_implications": "A funciÃŗn de comprobaciÃŗn de versiÃŗn depende da comunicaciÃŗn periÃŗdica con github.com", + "version_check_settings": "ComprobaciÃŗn de VersiÃŗn", + "version_check_settings_description": "Activar/desactivar a notificaciÃŗn de nova versiÃŗn", + "video_conversion_job": "Transcodificar vídeos", + "video_conversion_job_description": "Transcodificar vídeos para unha maior compatibilidade con navegadores e dispositivos" }, - "advanced_settings_log_level_title": "Log level: {}", - "advanced_settings_prefer_remote_subtitle": "Some devices are painfully slow to load thumbnails from assets on the device. Activate this setting to load remote images instead.", - "advanced_settings_prefer_remote_title": "Prefer remote images", - "advanced_settings_proxy_headers_subtitle": "Define proxy headers Immich should send with each network request", - "advanced_settings_proxy_headers_title": "Proxy Headers", - "advanced_settings_self_signed_ssl_subtitle": "Skips SSL certificate verification for the server endpoint. Required for self-signed certificates.", - "advanced_settings_self_signed_ssl_title": "Allow self-signed SSL certificates (EXPERIMENTAL)", - "advanced_settings_tile_subtitle": "Advanced user's settings", - "advanced_settings_troubleshooting_subtitle": "Enable additional features for troubleshooting", - "advanced_settings_troubleshooting_title": "Troubleshooting", - "album_info_card_backup_album_excluded": "EXCLUDED", - "album_info_card_backup_album_included": "INCLUDED", - "album_thumbnail_card_item": "1 item", - "album_thumbnail_card_items": "{} items", - "album_thumbnail_card_shared": " ¡ Shared", - "album_thumbnail_shared_by": "Shared by {}", - "album_viewer_appbar_delete_confirm": "Are you sure you want to delete this album from your account?", - "album_viewer_appbar_share_err_delete": "Failed to delete album", - "album_viewer_appbar_share_err_leave": "Failed to leave album", - "album_viewer_appbar_share_err_remove": "There are problems in removing assets from album", - "album_viewer_appbar_share_err_title": "Failed to change album title", - "album_viewer_appbar_share_leave": "Leave album", - "album_viewer_appbar_share_to": "Share To", - "album_viewer_page_share_add_users": "Add users", - "albums": "Albums", - "all": "All", - "app_bar_signout_dialog_content": "Are you sure you want to sign out?", - "app_bar_signout_dialog_ok": "Yes", - "app_bar_signout_dialog_title": "Sign out", - "archive_page_no_archived_assets": "No archived assets found", - "archive_page_title": "Archive ({})", - "archived": "Archived", - "asset_action_delete_err_read_only": "Cannot delete read only asset(s), skipping", - "asset_action_share_err_offline": "Cannot fetch offline asset(s), skipping", - "asset_list_group_by_sub_title": "Group by", - "asset_list_layout_settings_dynamic_layout_title": "Dynamic layout", - "asset_list_layout_settings_group_automatically": "Automatic", - "asset_list_layout_settings_group_by": "Group assets by", - "asset_list_layout_settings_group_by_month_day": "Month + day", - "asset_list_layout_sub_title": "Layout", - "asset_list_settings_subtitle": "Photo grid layout settings", - "asset_list_settings_title": "Photo Grid", - "asset_restored_successfully": "Asset restored successfully", - "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", - "asset_viewer_settings_title": "Asset Viewer", - "assets_deleted_permanently": "{} asset(s) deleted permanently", - "assets_deleted_permanently_from_server": "{} asset(s) deleted permanently from the Immich server", - "assets_removed_permanently_from_device": "{} asset(s) removed permanently from your device", - "assets_restored_successfully": "{} asset(s) restored successfully", - "assets_trashed": "{} asset(s) trashed", - "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", - "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", - "automatic_endpoint_switching_title": "Automatic URL switching", - "background_location_permission": "Background location permission", - "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", - "backup_album_selection_page_albums_device": "Albums on device ({})", - "backup_album_selection_page_albums_tap": "Tap to include, double tap to exclude", - "backup_album_selection_page_assets_scatter": "Assets can scatter across multiple albums. Thus, albums can be included or excluded during the backup process.", - "backup_album_selection_page_select_albums": "Select albums", - "backup_album_selection_page_selection_info": "Selection Info", - "backup_album_selection_page_total_assets": "Total unique assets", - "backup_all": "All", - "backup_background_service_backup_failed_message": "Failed to backup assets. Retryingâ€Ļ", - "backup_background_service_connection_failed_message": "Failed to connect to the server. Retryingâ€Ļ", - "backup_background_service_current_upload_notification": "Uploading {}", - "backup_background_service_default_notification": "Checking for new assetsâ€Ļ", - "backup_background_service_error_title": "Backup error", - "backup_background_service_in_progress_notification": "Backing up your assetsâ€Ļ", - "backup_background_service_upload_failure_notification": "Failed to upload {}", - "backup_controller_page_albums": "Backup Albums", - "backup_controller_page_background_app_refresh_disabled_content": "Enable background app refresh in Settings > General > Background App Refresh in order to use background backup.", - "backup_controller_page_background_app_refresh_disabled_title": "Background app refresh disabled", - "backup_controller_page_background_app_refresh_enable_button_text": "Go to settings", - "backup_controller_page_background_battery_info_link": "Show me how", - "backup_controller_page_background_battery_info_message": "For the best background backup experience, please disable any battery optimizations restricting background activity for Immich.\n\nSince this is device-specific, please lookup the required information for your device manufacturer.", - "backup_controller_page_background_battery_info_ok": "OK", - "backup_controller_page_background_battery_info_title": "Battery optimizations", - "backup_controller_page_background_charging": "Only while charging", - "backup_controller_page_background_configure_error": "Failed to configure the background service", - "backup_controller_page_background_delay": "Delay new assets backup: {}", - "backup_controller_page_background_description": "Turn on the background service to automatically backup any new assets without needing to open the app", - "backup_controller_page_background_is_off": "Automatic background backup is off", - "backup_controller_page_background_is_on": "Automatic background backup is on", - "backup_controller_page_background_turn_off": "Turn off background service", - "backup_controller_page_background_turn_on": "Turn on background service", - "backup_controller_page_background_wifi": "Only on WiFi", - "backup_controller_page_backup": "Backup", - "backup_controller_page_backup_selected": "Selected: ", - "backup_controller_page_backup_sub": "Backed up photos and videos", - "backup_controller_page_created": "Created on: {}", - "backup_controller_page_desc_backup": "Turn on foreground backup to automatically upload new assets to the server when opening the app.", - "backup_controller_page_excluded": "Excluded: ", - "backup_controller_page_failed": "Failed ({})", - "backup_controller_page_filename": "File name: {} [{}]", + "admin_email": "Correo electrÃŗnico do administrador", + "admin_password": "Contrasinal do administrador", + "administration": "AdministraciÃŗn", + "advanced": "Avanzado", + "advanced_settings_enable_alternate_media_filter_subtitle": "Usa esta opciÃŗn para filtrar medios durante a sincronizaciÃŗn baseÃĄndose en criterios alternativos. SÃŗ proba isto se tes problemas coa aplicaciÃŗn detectando todos os ÃĄlbums.", + "advanced_settings_enable_alternate_media_filter_title": "[EXPERIMENTAL] Usar filtro alternativo de sincronizaciÃŗn de ÃĄlbums do dispositivo", + "advanced_settings_log_level_title": "Nivel de rexistro: {}", + "advanced_settings_prefer_remote_subtitle": "AlgÃēns dispositivos son extremadamente lentos para cargar miniaturas de activos no dispositivo. Active esta configuraciÃŗn para cargar imaxes remotas no seu lugar.", + "advanced_settings_prefer_remote_title": "Preferir imaxes remotas", + "advanced_settings_proxy_headers_subtitle": "Definir cabeceiras de proxy que Immich debería enviar con cada solicitude de rede", + "advanced_settings_proxy_headers_title": "Cabeceiras de Proxy", + "advanced_settings_self_signed_ssl_subtitle": "Omite a verificaciÃŗn do certificado SSL para o punto final do servidor. Requirido para certificados autofirmados.", + "advanced_settings_self_signed_ssl_title": "Permitir certificados SSL autofirmados", + "advanced_settings_sync_remote_deletions_subtitle": "Eliminar ou restaurar automaticamente un activo neste dispositivo cando esa acciÃŗn se realiza na web", + "advanced_settings_sync_remote_deletions_title": "Sincronizar eliminaciÃŗns remotas [EXPERIMENTAL]", + "advanced_settings_tile_subtitle": "ConfiguraciÃŗn de usuario avanzado", + "advanced_settings_troubleshooting_subtitle": "Activar funciÃŗns adicionais para a resoluciÃŗn de problemas", + "advanced_settings_troubleshooting_title": "ResoluciÃŗn de problemas", + "age_months": "Idade {months, plural, one {# mes} other {# meses}}", + "age_year_months": "Idade 1 ano, {months, plural, one {# mes} other {# meses}}", + "age_years": "{years, plural, other {Idade #}}", + "album_added": "Álbum engadido", + "album_added_notification_setting_description": "Recibir unha notificaciÃŗn por correo electrÃŗnico cando sexas engadido a un ÃĄlbum compartido", + "album_cover_updated": "Portada do ÃĄlbum actualizada", + "album_delete_confirmation": "EstÃĄs seguro de que queres eliminar o ÃĄlbum {album}?", + "album_delete_confirmation_description": "Se este ÃĄlbum estÃĄ compartido, outros usuarios non poderÃĄn acceder a el.", + "album_info_card_backup_album_excluded": "EXCLUÍDO", + "album_info_card_backup_album_included": "INCLUÍDO", + "album_info_updated": "InformaciÃŗn do ÃĄlbum actualizada", + "album_leave": "Saír do ÃĄlbum?", + "album_leave_confirmation": "EstÃĄs seguro de que queres saír de {album}?", + "album_name": "Nome do Álbum", + "album_options": "OpciÃŗns do ÃĄlbum", + "album_remove_user": "Eliminar usuario?", + "album_remove_user_confirmation": "EstÃĄs seguro de que queres eliminar a {user}?", + "album_share_no_users": "Parece que compartiches este ÃĄlbum con todos os usuarios ou non tes ningÃēn usuario co que compartir.", + "album_thumbnail_card_item": "1 elemento", + "album_thumbnail_card_items": "{} elementos", + "album_thumbnail_card_shared": " ¡ Compartido", + "album_thumbnail_shared_by": "Compartido por {}", + "album_updated": "Álbum actualizado", + "album_updated_setting_description": "Recibir unha notificaciÃŗn por correo electrÃŗnico cando un ÃĄlbum compartido teÃąa novos activos", + "album_user_left": "Saíu de {album}", + "album_user_removed": "Eliminado {user}", + "album_viewer_appbar_delete_confirm": "EstÃĄs seguro de que queres eliminar este ÃĄlbum da tÃēa conta?", + "album_viewer_appbar_share_err_delete": "Erro ao eliminar o ÃĄlbum", + "album_viewer_appbar_share_err_leave": "Erro ao saír do ÃĄlbum", + "album_viewer_appbar_share_err_remove": "Hai problemas ao eliminar activos do ÃĄlbum", + "album_viewer_appbar_share_err_title": "Erro ao cambiar o título do ÃĄlbum", + "album_viewer_appbar_share_leave": "Saír do ÃĄlbum", + "album_viewer_appbar_share_to": "Compartir con", + "album_viewer_page_share_add_users": "Engadir usuarios", + "album_with_link_access": "Permitir que calquera persoa coa ligazÃŗn vexa fotos e persoas neste ÃĄlbum.", + "albums": "Álbums", + "albums_count": "{count, plural, one {{count, number} Álbum} other {{count, number} Álbums}}", + "all": "Todo", + "all_albums": "Todos os ÃĄlbums", + "all_people": "Todas as persoas", + "all_videos": "Todos os vídeos", + "allow_dark_mode": "Permitir modo escuro", + "allow_edits": "Permitir ediciÃŗns", + "allow_public_user_to_download": "Permitir que o usuario pÃēblico descargue", + "allow_public_user_to_upload": "Permitir que o usuario pÃēblico cargue", + "alt_text_qr_code": "Imaxe de cÃŗdigo QR", + "anti_clockwise": "Sentido antihorario", + "api_key": "Chave API", + "api_key_description": "Este valor sÃŗ se mostrarÃĄ unha vez. AsegÃērese de copialo antes de pechar a xanela.", + "api_key_empty": "O nome da sÃēa chave API non pode estar baleiro", + "api_keys": "Chaves API", + "app_bar_signout_dialog_content": "EstÃĄs seguro de que queres pechar sesiÃŗn?", + "app_bar_signout_dialog_ok": "Si", + "app_bar_signout_dialog_title": "Pechar sesiÃŗn", + "app_settings": "ConfiguraciÃŗn da AplicaciÃŗn", + "appears_in": "Aparece en", + "archive": "Arquivo", + "archive_or_unarchive_photo": "Arquivar ou desarquivar foto", + "archive_page_no_archived_assets": "Non se atoparon activos arquivados", + "archive_page_title": "Arquivo ({})", + "archive_size": "TamaÃąo do arquivo", + "archive_size_description": "Configurar o tamaÃąo do arquivo para descargas (en GiB)", + "archived": "Arquivado", + "archived_count": "{count, plural, other {Arquivados #}}", + "are_these_the_same_person": "Son estas a mesma persoa?", + "are_you_sure_to_do_this": "EstÃĄs seguro de que queres facer isto?", + "asset_action_delete_err_read_only": "Non se poden eliminar activo(s) de sÃŗ lectura, omitindo", + "asset_action_share_err_offline": "Non se poden obter activo(s) fÃŗra de liÃąa, omitindo", + "asset_added_to_album": "Engadido ao ÃĄlbum", + "asset_adding_to_album": "Engadindo ao ÃĄlbumâ€Ļ", + "asset_description_updated": "A descriciÃŗn do activo actualizouse", + "asset_filename_is_offline": "O activo {filename} estÃĄ fÃŗra de liÃąa", + "asset_has_unassigned_faces": "O activo ten caras non asignadas", + "asset_hashing": "Calculando hashâ€Ļ", + "asset_list_group_by_sub_title": "Agrupar por", + "asset_list_layout_settings_dynamic_layout_title": "DeseÃąo dinÃĄmico", + "asset_list_layout_settings_group_automatically": "AutomÃĄtico", + "asset_list_layout_settings_group_by": "Agrupar activos por", + "asset_list_layout_settings_group_by_month_day": "Mes + día", + "asset_list_layout_sub_title": "DeseÃąo", + "asset_list_settings_subtitle": "ConfiguraciÃŗn do deseÃąo da grella de fotos", + "asset_list_settings_title": "Grella de Fotos", + "asset_offline": "Activo FÃŗra de LiÃąa", + "asset_offline_description": "Este activo externo xa non se atopa no disco. Por favor, contacta co teu administrador de Immich para obter axuda.", + "asset_restored_successfully": "Activo restaurado correctamente", + "asset_skipped": "Omitido", + "asset_skipped_in_trash": "No lixo", + "asset_uploaded": "Subido", + "asset_uploading": "Subindoâ€Ļ", + "asset_viewer_settings_subtitle": "Xestionar a tÃēa configuraciÃŗn do visor da galería", + "asset_viewer_settings_title": "Visor de Activos", + "assets": "Activos", + "assets_added_count": "Engadido {count, plural, one {# activo} other {# activos}}", + "assets_added_to_album_count": "Engadido {count, plural, one {# activo} other {# activos}} ao ÃĄlbum", + "assets_added_to_name_count": "Engadido {count, plural, one {# activo} other {# activos}} a {hasName, select, true {{name}} other {novo ÃĄlbum}}", + "assets_count": "{count, plural, one {# activo} other {# activos}}", + "assets_deleted_permanently": "{} activo(s) eliminado(s) permanentemente", + "assets_deleted_permanently_from_server": "{} activo(s) eliminado(s) permanentemente do servidor Immich", + "assets_moved_to_trash_count": "Movido {count, plural, one {# activo} other {# activos}} ao lixo", + "assets_permanently_deleted_count": "Eliminados permanentemente {count, plural, one {# activo} other {# activos}}", + "assets_removed_count": "Eliminados {count, plural, one {# activo} other {# activos}}", + "assets_removed_permanently_from_device": "{} activo(s) eliminado(s) permanentemente do teu dispositivo", + "assets_restore_confirmation": "EstÃĄs seguro de que queres restaurar todos os seus activos no lixo? Non podes desfacer esta acciÃŗn! Ten en conta que calquera activo fÃŗra de liÃąa non pode ser restaurado desta maneira.", + "assets_restored_count": "Restaurados {count, plural, one {# activo} other {# activos}}", + "assets_restored_successfully": "{} activo(s) restaurado(s) correctamente", + "assets_trashed": "{} activo(s) movido(s) ao lixo", + "assets_trashed_count": "Movido {count, plural, one {# activo} other {# activos}} ao lixo", + "assets_trashed_from_server": "{} activo(s) movido(s) ao lixo desde o servidor Immich", + "assets_were_part_of_album_count": "{count, plural, one {O activo xa era} other {Os activos xa eran}} parte do ÃĄlbum", + "authorized_devices": "Dispositivos Autorizados", + "automatic_endpoint_switching_subtitle": "Conectar localmente a travÊs de Wi-Fi designada cando estea dispoÃąible e usar conexiÃŗns alternativas noutros lugares", + "automatic_endpoint_switching_title": "Cambio automÃĄtico de URL", + "back": "AtrÃĄs", + "back_close_deselect": "AtrÃĄs, pechar ou deseleccionar", + "background_location_permission": "Permiso de ubicaciÃŗn en segundo plano", + "background_location_permission_content": "Para cambiar de rede cando se executa en segundo plano, Immich debe ter *sempre* acceso ÃĄ ubicaciÃŗn precisa para que a aplicaciÃŗn poida ler o nome da rede Wi-Fi", + "backup_album_selection_page_albums_device": "Álbums no dispositivo ({})", + "backup_album_selection_page_albums_tap": "Tocar para incluír, dobre toque para excluír", + "backup_album_selection_page_assets_scatter": "Os activos poden dispersarse por varios ÃĄlbums. Polo tanto, os ÃĄlbums poden incluírse ou excluírse durante o proceso de copia de seguridade.", + "backup_album_selection_page_select_albums": "Seleccionar ÃĄlbums", + "backup_album_selection_page_selection_info": "InformaciÃŗn da selecciÃŗn", + "backup_album_selection_page_total_assets": "Total de activos Ãēnicos", + "backup_all": "Todo", + "backup_background_service_backup_failed_message": "Erro ao facer copia de seguridade dos activos. Reintentandoâ€Ļ", + "backup_background_service_connection_failed_message": "Erro ao conectar co servidor. Reintentandoâ€Ļ", + "backup_background_service_current_upload_notification": "Subindo {}", + "backup_background_service_default_notification": "Comprobando novos activosâ€Ļ", + "backup_background_service_error_title": "Erro na copia de seguridade", + "backup_background_service_in_progress_notification": "Facendo copia de seguridade dos teus activosâ€Ļ", + "backup_background_service_upload_failure_notification": "Erro ao subir {}", + "backup_controller_page_albums": "Álbums da Copia de Seguridade", + "backup_controller_page_background_app_refresh_disabled_content": "Active a actualizaciÃŗn de aplicaciÃŗns en segundo plano en Axustes > Xeral > ActualizaciÃŗn en segundo plano para usar a copia de seguridade en segundo plano.", + "backup_controller_page_background_app_refresh_disabled_title": "ActualizaciÃŗn de aplicaciÃŗns en segundo plano desactivada", + "backup_controller_page_background_app_refresh_enable_button_text": "Ir a axustes", + "backup_controller_page_background_battery_info_link": "MÃŗstrame como", + "backup_controller_page_background_battery_info_message": "Para a mellor experiencia de copia de seguridade en segundo plano, desactiva calquera optimizaciÃŗn de batería que restrinxa a actividade en segundo plano para Immich.\n\nDado que isto Ê específico do dispositivo, busque a informaciÃŗn requirida para o fabricante do teu dispositivo.", + "backup_controller_page_background_battery_info_ok": "Aceptar", + "backup_controller_page_background_battery_info_title": "OptimizaciÃŗns da batería", + "backup_controller_page_background_charging": "SÃŗ mentres se carga", + "backup_controller_page_background_configure_error": "Erro ao configurar o servizo en segundo plano", + "backup_controller_page_background_delay": "Atrasar copia de seguridade de novos activos: {}", + "backup_controller_page_background_description": "Active o servizo en segundo plano para facer copia de seguridade automaticamente de calquera activo novo sen necesidade de abrir a aplicaciÃŗn", + "backup_controller_page_background_is_off": "A copia de seguridade automÃĄtica en segundo plano estÃĄ desactivada", + "backup_controller_page_background_is_on": "A copia de seguridade automÃĄtica en segundo plano estÃĄ activada", + "backup_controller_page_background_turn_off": "Desactivar servizo en segundo plano", + "backup_controller_page_background_turn_on": "Activar servizo en segundo plano", + "backup_controller_page_background_wifi": "SÃŗ con WiFi", + "backup_controller_page_backup": "Copia de Seguridade", + "backup_controller_page_backup_selected": "Seleccionado: ", + "backup_controller_page_backup_sub": "Fotos e vídeos con copia de seguridade", + "backup_controller_page_created": "Creado o: {}", + "backup_controller_page_desc_backup": "Active a copia de seguridade en primeiro plano para cargar automaticamente novos activos ao servidor ao abrir a aplicaciÃŗn.", + "backup_controller_page_excluded": "Excluído: ", + "backup_controller_page_failed": "Fallado ({})", + "backup_controller_page_filename": "Nome do ficheiro: {} [{}]", "backup_controller_page_id": "ID: {}", - "backup_controller_page_info": "Backup Information", - "backup_controller_page_none_selected": "None selected", - "backup_controller_page_remainder": "Remainder", - "backup_controller_page_remainder_sub": "Remaining photos and videos to back up from selection", - "backup_controller_page_server_storage": "Server Storage", - "backup_controller_page_start_backup": "Start Backup", - "backup_controller_page_status_off": "Automatic foreground backup is off", - "backup_controller_page_status_on": "Automatic foreground backup is on", - "backup_controller_page_storage_format": "{} of {} used", - "backup_controller_page_to_backup": "Albums to be backed up", - "backup_controller_page_total_sub": "All unique photos and videos from selected albums", - "backup_controller_page_turn_off": "Turn off foreground backup", - "backup_controller_page_turn_on": "Turn on foreground backup", - "backup_controller_page_uploading_file_info": "Uploading file info", - "backup_err_only_album": "Cannot remove the only album", - "backup_info_card_assets": "assets", - "backup_manual_cancelled": "Cancelled", - "backup_manual_in_progress": "Upload already in progress. Try after some time", - "backup_manual_success": "Success", - "backup_manual_title": "Upload status", - "backup_options_page_title": "Backup options", - "backup_setting_subtitle": "Manage background and foreground upload settings", - "cache_settings_album_thumbnails": "Library page thumbnails ({} assets)", - "cache_settings_clear_cache_button": "Clear cache", - "cache_settings_clear_cache_button_title": "Clears the app's cache. This will significantly impact the app's performance until the cache has rebuilt.", - "cache_settings_duplicated_assets_clear_button": "CLEAR", - "cache_settings_duplicated_assets_subtitle": "Photos and videos that are black listed by the app", - "cache_settings_duplicated_assets_title": "Duplicated Assets ({})", - "cache_settings_image_cache_size": "Image cache size ({} assets)", - "cache_settings_statistics_album": "Library thumbnails", - "cache_settings_statistics_assets": "{} assets ({})", - "cache_settings_statistics_full": "Full images", - "cache_settings_statistics_shared": "Shared album thumbnails", - "cache_settings_statistics_thumbnail": "Thumbnails", - "cache_settings_statistics_title": "Cache usage", - "cache_settings_subtitle": "Control the caching behaviour of the Immich mobile application", - "cache_settings_thumbnail_size": "Thumbnail cache size ({} assets)", - "cache_settings_tile_subtitle": "Control the local storage behaviour", - "cache_settings_tile_title": "Local Storage", - "cache_settings_title": "Caching Settings", - "cancel": "Cancel", - "canceled": "Canceled", - "change_display_order": "Change display order", - "change_password_form_confirm_password": "Confirm Password", - "change_password_form_description": "Hi {name},\n\nThis is either the first time you are signing into the system or a request has been made to change your password. Please enter the new password below.", - "change_password_form_new_password": "New Password", - "change_password_form_password_mismatch": "Passwords do not match", - "change_password_form_reenter_new_password": "Re-enter New Password", - "check_corrupt_asset_backup": "Check for corrupt asset backups", - "check_corrupt_asset_backup_button": "Perform check", - "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", - "client_cert_dialog_msg_confirm": "OK", - "client_cert_enter_password": "Enter Password", - "client_cert_import": "Import", - "client_cert_import_success_msg": "Client certificate is imported", - "client_cert_invalid_msg": "Invalid certificate file or wrong password", - "client_cert_remove_msg": "Client certificate is removed", - "client_cert_subtitle": "Supports PKCS12 (.p12, .pfx) format only. Certificate Import/Remove is available only before login", - "client_cert_title": "SSL Client Certificate (EXPERIMENTAL)", - "common_create_new_album": "Create new album", - "common_server_error": "Please check your network connection, make sure the server is reachable and app/server versions are compatible.", - "completed": "Completed", - "control_bottom_app_bar_album_info_shared": "{} items ¡ Shared", - "control_bottom_app_bar_create_new_album": "Create new album", - "control_bottom_app_bar_delete_from_immich": "Delete from Immich", - "control_bottom_app_bar_delete_from_local": "Delete from device", - "control_bottom_app_bar_edit_location": "Edit Location", - "control_bottom_app_bar_edit_time": "Edit Date & Time", - "control_bottom_app_bar_share_to": "Share To", - "control_bottom_app_bar_trash_from_immich": "Move to Trash", - "create_album": "Create album", - "create_album_page_untitled": "Untitled", - "create_new": "CREATE NEW", - "create_shared_album_page_share_add_assets": "ADD ASSETS", - "create_shared_album_page_share_select_photos": "Select Photos", - "crop": "Crop", - "curated_object_page_title": "Things", - "current_server_address": "Current server address", - "daily_title_text_date": "E, MMM dd", - "daily_title_text_date_year": "E, MMM dd, yyyy", - "date_format": "E, LLL d, y â€ĸ h:mm a", - "delete_dialog_alert": "These items will be permanently deleted from Immich and from your device", - "delete_dialog_alert_local": "These items will be permanently removed from your device but still be available on the Immich server", - "delete_dialog_alert_local_non_backed_up": "Some of the items aren't backed up to Immich and will be permanently removed from your device", - "delete_dialog_alert_remote": "These items will be permanently deleted from the Immich server", - "delete_dialog_ok_force": "Delete Anyway", - "delete_dialog_title": "Delete Permanently", - "delete_local_dialog_ok_backed_up_only": "Delete Backed Up Only", - "delete_local_dialog_ok_force": "Delete Anyway", - "delete_shared_link_dialog_title": "Delete Shared Link", - "description_input_hint_text": "Add description...", - "description_input_submit_error": "Error updating description, check the log for more details", - "download_canceled": "Download canceled", - "download_complete": "Download complete", - "download_enqueue": "Download enqueued", - "download_error": "Download Error", - "download_failed": "Download failed", - "download_filename": "file: {}", - "download_finished": "Download finished", - "download_notfound": "Download not found", - "download_paused": "Download paused", - "download_started": "Download started", - "download_sucess": "Download success", - "download_sucess_android": "The media has been downloaded to DCIM/Immich", - "download_waiting_to_retry": "Waiting to retry", - "downloading": "Downloading...", - "downloading_media": "Downloading media", - "edit_location_dialog_title": "Location", - "end_date": "End date", - "enqueued": "Enqueued", - "enter_wifi_name": "Enter WiFi name", - "error_change_sort_album": "Failed to change album sort order", - "error_saving_image": "Error: {}", - "exif_bottom_sheet_description": "Add Description...", - "exif_bottom_sheet_details": "DETAILS", - "exif_bottom_sheet_location": "LOCATION", - "exif_bottom_sheet_people": "PEOPLE", - "exif_bottom_sheet_person_add_person": "Add name", - "experimental_settings_new_asset_list_subtitle": "Work in progress", - "experimental_settings_new_asset_list_title": "Enable experimental photo grid", - "experimental_settings_subtitle": "Use at your own risk!", + "backup_controller_page_info": "InformaciÃŗn da Copia de Seguridade", + "backup_controller_page_none_selected": "NingÃēn seleccionado", + "backup_controller_page_remainder": "Restante", + "backup_controller_page_remainder_sub": "Fotos e vídeos restantes para facer copia de seguridade da selecciÃŗn", + "backup_controller_page_server_storage": "Almacenamento do Servidor", + "backup_controller_page_start_backup": "Iniciar Copia de Seguridade", + "backup_controller_page_status_off": "A copia de seguridade automÃĄtica en primeiro plano estÃĄ desactivada", + "backup_controller_page_status_on": "A copia de seguridade automÃĄtica en primeiro plano estÃĄ activada", + "backup_controller_page_storage_format": "{} de {} usado", + "backup_controller_page_to_backup": "Álbums para facer copia de seguridade", + "backup_controller_page_total_sub": "Todas as fotos e vídeos Ãēnicos dos ÃĄlbums seleccionados", + "backup_controller_page_turn_off": "Desactivar copia de seguridade en primeiro plano", + "backup_controller_page_turn_on": "Activar copia de seguridade en primeiro plano", + "backup_controller_page_uploading_file_info": "Subindo informaciÃŗn do ficheiro", + "backup_err_only_album": "Non se pode eliminar o Ãēnico ÃĄlbum", + "backup_info_card_assets": "activos", + "backup_manual_cancelled": "Cancelado", + "backup_manual_in_progress": "Subida xa en progreso. Intenta despois dun tempo", + "backup_manual_success": "Éxito", + "backup_manual_title": "Estado da subida", + "backup_options_page_title": "OpciÃŗns da copia de seguridade", + "backup_setting_subtitle": "Xestionar a configuraciÃŗn de carga en segundo plano e primeiro plano", + "backward": "AtrÃĄs", + "birthdate_saved": "Data de nacemento gardada correctamente", + "birthdate_set_description": "A data de nacemento Ãēsase para calcular a idade desta persoa no momento dunha foto.", + "blurred_background": "Fondo borroso", + "bugs_and_feature_requests": "Erros e Solicitudes de FunciÃŗns", + "build": "CompilaciÃŗn", + "build_image": "Construír Imaxe", + "bulk_delete_duplicates_confirmation": "EstÃĄs seguro de que queres eliminar masivamente {count, plural, one {# activo duplicado} other {# activos duplicados}}? Isto conservarÃĄ o activo mÃĄis grande de cada grupo e eliminarÃĄ permanentemente todos os demais duplicados. Non pode desfacer esta acciÃŗn!", + "bulk_keep_duplicates_confirmation": "EstÃĄs seguro de que queres conservar {count, plural, one {# activo duplicado} other {# activos duplicados}}? Isto resolverÃĄ todos os grupos duplicados sen eliminar nada.", + "bulk_trash_duplicates_confirmation": "EstÃĄs seguro de que queres mover masivamente ao lixo {count, plural, one {# activo duplicado} other {# activos duplicados}}? Isto conservarÃĄ o activo mÃĄis grande de cada grupo e moverÃĄ ao lixo todos os demais duplicados.", + "buy": "Comprar Immich", + "cache_settings_album_thumbnails": "Miniaturas da pÃĄxina da biblioteca ({} activos)", + "cache_settings_clear_cache_button": "Borrar cachÊ", + "cache_settings_clear_cache_button_title": "Borra a cachÊ da aplicaciÃŗn. Isto afectarÃĄ significativamente o rendemento da aplicaciÃŗn ata que a cachÊ se reconstruíu.", + "cache_settings_duplicated_assets_clear_button": "BORRAR", + "cache_settings_duplicated_assets_subtitle": "Fotos e vídeos que estÃĄn na lista negra da aplicaciÃŗn", + "cache_settings_duplicated_assets_title": "Activos Duplicados ({})", + "cache_settings_image_cache_size": "TamaÃąo da cachÊ de imaxes ({} activos)", + "cache_settings_statistics_album": "Miniaturas da biblioteca", + "cache_settings_statistics_assets": "{} activos ({})", + "cache_settings_statistics_full": "Imaxes completas", + "cache_settings_statistics_shared": "Miniaturas de ÃĄlbums compartidos", + "cache_settings_statistics_thumbnail": "Miniaturas", + "cache_settings_statistics_title": "Uso da cachÊ", + "cache_settings_subtitle": "Controlar o comportamento da cachÊ da aplicaciÃŗn mÃŗbil Immich", + "cache_settings_thumbnail_size": "TamaÃąo da cachÊ de miniaturas ({} activos)", + "cache_settings_tile_subtitle": "Controlar o comportamento do almacenamento local", + "cache_settings_tile_title": "Almacenamento Local", + "cache_settings_title": "ConfiguraciÃŗn da CachÊ", + "camera": "CÃĄmara", + "camera_brand": "Marca da cÃĄmara", + "camera_model": "Modelo da cÃĄmara", + "cancel": "Cancelar", + "cancel_search": "Cancelar busca", + "canceled": "Cancelado", + "cannot_merge_people": "Non se poden fusionar persoas", + "cannot_undo_this_action": "Non pode desfacer esta acciÃŗn!", + "cannot_update_the_description": "Non se pode actualizar a descriciÃŗn", + "change_date": "Cambiar data", + "change_display_order": "Cambiar orde de visualizaciÃŗn", + "change_expiration_time": "Cambiar hora de caducidade", + "change_location": "Cambiar ubicaciÃŗn", + "change_name": "Cambiar nome", + "change_name_successfully": "Nome cambiado correctamente", + "change_password": "Cambiar Contrasinal", + "change_password_description": "Esta Ê a primeira vez que inicias sesiÃŗn no sistema ou solicitouse un cambio do teu contrasinal. Introduza o novo contrasinal a continuaciÃŗn.", + "change_password_form_confirm_password": "Confirmar Contrasinal", + "change_password_form_description": "Ola {name},\n\nEsta Ê a primeira vez que inicias sesiÃŗn no sistema ou solicitouse un cambio do teu contrasinal. Introduza o novo contrasinal a continuaciÃŗn.", + "change_password_form_new_password": "Novo Contrasinal", + "change_password_form_password_mismatch": "Os contrasinais non coinciden", + "change_password_form_reenter_new_password": "Reintroducir Novo Contrasinal", + "change_your_password": "Cambiar o teu contrasinal", + "changed_visibility_successfully": "Visibilidade cambiada correctamente", + "check_all": "Marcar todo", + "check_corrupt_asset_backup": "Comprobar copias de seguridade de activos corruptos", + "check_corrupt_asset_backup_button": "Realizar comprobaciÃŗn", + "check_corrupt_asset_backup_description": "Execute esta comprobaciÃŗn sÃŗ a travÊs de Wi-Fi e unha vez que todos os activos teÃąan copia de seguridade. O procedemento pode tardar uns minutos.", + "check_logs": "Comprobar Rexistros", + "choose_matching_people_to_merge": "Elixir persoas coincidentes para fusionar", + "city": "Cidade", + "clear": "Limpar", + "clear_all": "Limpar todo", + "clear_all_recent_searches": "Limpar todas as buscas recentes", + "clear_message": "Limpar mensaxe", + "clear_value": "Limpar valor", + "client_cert_dialog_msg_confirm": "Aceptar", + "client_cert_enter_password": "Introducir Contrasinal", + "client_cert_import": "Importar", + "client_cert_import_success_msg": "Certificado de cliente importado", + "client_cert_invalid_msg": "Ficheiro de certificado invÃĄlido ou contrasinal incorrecto", + "client_cert_remove_msg": "Certificado de cliente eliminado", + "client_cert_subtitle": "SÃŗ admite o formato PKCS12 (.p12, .pfx). A importaciÃŗn/eliminaciÃŗn de certificados sÃŗ estÃĄ dispoÃąible antes de iniciar sesiÃŗn", + "client_cert_title": "Certificado de Cliente SSL", + "clockwise": "Sentido horario", + "close": "Pechar", + "collapse": "Contraer", + "collapse_all": "Contraer todo", + "color": "Cor", + "color_theme": "Tema de cor", + "comment_deleted": "Comentario eliminado", + "comment_options": "OpciÃŗns de comentario", + "comments_and_likes": "Comentarios e GÃēstames", + "comments_are_disabled": "Os comentarios estÃĄn desactivados", + "common_create_new_album": "Crear novo ÃĄlbum", + "common_server_error": "Por favor, comprobe a tÃēa conexiÃŗn de rede, asegÃērache de que o servidor sexa accesible e que as versiÃŗns da aplicaciÃŗn/servidor sexan compatibles.", + "completed": "Completado", + "confirm": "Confirmar", + "confirm_admin_password": "Confirmar Contrasinal do Administrador", + "confirm_delete_face": "EstÃĄs seguro de que queres eliminar a cara de {name} do activo?", + "confirm_delete_shared_link": "EstÃĄs seguro de que queres eliminar esta ligazÃŗn compartida?", + "confirm_keep_this_delete_others": "Todos os demais activos na pila eliminaranse excepto este activo. EstÃĄs seguro de que queres continuar?", + "confirm_password": "Confirmar contrasinal", + "contain": "Conter", + "context": "Contexto", + "continue": "Continuar", + "control_bottom_app_bar_album_info_shared": "{} elementos ¡ Compartidos", + "control_bottom_app_bar_create_new_album": "Crear novo ÃĄlbum", + "control_bottom_app_bar_delete_from_immich": "Eliminar de Immich", + "control_bottom_app_bar_delete_from_local": "Eliminar do dispositivo", + "control_bottom_app_bar_edit_location": "Editar ubicaciÃŗn", + "control_bottom_app_bar_edit_time": "Editar Data e Hora", + "control_bottom_app_bar_share_link": "Compartir LigazÃŗn", + "control_bottom_app_bar_share_to": "Compartir Con", + "control_bottom_app_bar_trash_from_immich": "Mover ao Lixo", + "copied_image_to_clipboard": "Imaxe copiada ao portapapeis.", + "copied_to_clipboard": "Copiado ao portapapeis!", + "copy_error": "Erro ao copiar", + "copy_file_path": "Copiar ruta do ficheiro", + "copy_image": "Copiar Imaxe", + "copy_link": "Copiar ligazÃŗn", + "copy_link_to_clipboard": "Copiar ligazÃŗn ao portapapeis", + "copy_password": "Copiar contrasinal", + "copy_to_clipboard": "Copiar ao Portapapeis", + "country": "País", + "cover": "Portada", + "covers": "Portadas", + "create": "Crear", + "create_album": "Crear ÃĄlbum", + "create_album_page_untitled": "Sen título", + "create_library": "Crear Biblioteca", + "create_link": "Crear ligazÃŗn", + "create_link_to_share": "Crear ligazÃŗn para compartir", + "create_link_to_share_description": "Permitir que calquera persoa coa ligazÃŗn vexa a(s) foto(s) seleccionada(s)", + "create_new": "CREAR NOVO", + "create_new_person": "Crear nova persoa", + "create_new_person_hint": "Asignar activos seleccionados a unha nova persoa", + "create_new_user": "Crear novo usuario", + "create_shared_album_page_share_add_assets": "ENGADIR ACTIVOS", + "create_shared_album_page_share_select_photos": "Seleccionar Fotos", + "create_tag": "Crear etiqueta", + "create_tag_description": "Crear unha nova etiqueta. Para etiquetas aniÃąadas, introduza a ruta completa da etiqueta incluíndo barras inclinadas.", + "create_user": "Crear usuario", + "created": "Creado", + "crop": "Recortar", + "curated_object_page_title": "Cousas", + "current_device": "Dispositivo actual", + "current_server_address": "Enderezo do servidor actual", + "custom_locale": "ConfiguraciÃŗn Rexional Personalizada", + "custom_locale_description": "Formatar datas e nÃēmeros baseÃĄndose na lingua e a rexiÃŗn", + "daily_title_text_date": "E, dd MMM", + "daily_title_text_date_year": "E, dd MMM, yyyy", + "dark": "Escuro", + "date_after": "Data posterior a", + "date_and_time": "Data e Hora", + "date_before": "Data anterior a", + "date_format": "E, d LLL, y â€ĸ H:mm", + "date_of_birth_saved": "Data de nacemento gardada correctamente", + "date_range": "Rango de datas", + "day": "Día", + "deduplicate_all": "Eliminar Duplicados Todos", + "deduplication_criteria_1": "TamaÃąo da imaxe en bytes", + "deduplication_criteria_2": "Reconto de datos EXIF", + "deduplication_info": "InformaciÃŗn de DeduplicaciÃŗn", + "deduplication_info_description": "Para preseleccionar automaticamente activos e eliminar duplicados masivamente, miramos:", + "default_locale": "ConfiguraciÃŗn Rexional Predeterminada", + "default_locale_description": "Formatar datas e nÃēmeros baseÃĄndose na configuraciÃŗn rexional do teu navegador", + "delete": "Eliminar", + "delete_album": "Eliminar ÃĄlbum", + "delete_api_key_prompt": "EstÃĄs seguro de que queres eliminar esta chave API?", + "delete_dialog_alert": "Estes elementos eliminaranse permanentemente de Immich e do teu dispositivo", + "delete_dialog_alert_local": "Estes elementos eliminaranse permanentemente do teu dispositivo pero aínda estarÃĄn dispoÃąibles no servidor Immich", + "delete_dialog_alert_local_non_backed_up": "AlgÃēns dos elementos non teÃąen copia de seguridade en Immich e eliminaranse permanentemente do teu dispositivo", + "delete_dialog_alert_remote": "Estes elementos eliminaranse permanentemente do servidor Immich", + "delete_dialog_ok_force": "Eliminar Igualmente", + "delete_dialog_title": "Eliminar Permanentemente", + "delete_duplicates_confirmation": "EstÃĄs seguro de que queres eliminar permanentemente estes duplicados?", + "delete_face": "Eliminar cara", + "delete_key": "Eliminar chave", + "delete_library": "Eliminar Biblioteca", + "delete_link": "Eliminar ligazÃŗn", + "delete_local_dialog_ok_backed_up_only": "Eliminar SÃŗ con Copia de Seguridade", + "delete_local_dialog_ok_force": "Eliminar Igualmente", + "delete_others": "Eliminar outros", + "delete_shared_link": "Eliminar ligazÃŗn compartida", + "delete_shared_link_dialog_title": "Eliminar LigazÃŗn Compartida", + "delete_tag": "Eliminar etiqueta", + "delete_tag_confirmation_prompt": "EstÃĄs seguro de que queres eliminar a etiqueta {tagName}?", + "delete_user": "Eliminar usuario", + "deleted_shared_link": "LigazÃŗn compartida eliminada", + "deletes_missing_assets": "Elimina activos que faltan no disco", + "description": "DescriciÃŗn", + "description_input_hint_text": "Engadir descriciÃŗn...", + "description_input_submit_error": "Erro ao actualizar a descriciÃŗn, comprobe o rexistro para mÃĄis detalles", + "details": "Detalles", + "direction": "DirecciÃŗn", + "disabled": "Desactivado", + "disallow_edits": "Non permitir ediciÃŗns", + "discord": "Discord", + "discover": "Descubrir", + "dismiss_all_errors": "Descartar todos os erros", + "dismiss_error": "Descartar erro", + "display_options": "OpciÃŗns de visualizaciÃŗn", + "display_order": "Orde de visualizaciÃŗn", + "display_original_photos": "Mostrar fotos orixinais", + "display_original_photos_setting_description": "Preferir mostrar a foto orixinal ao ver un activo en lugar de miniaturas cando o activo orixinal Ê compatible coa web. Isto pode resultar en velocidades de visualizaciÃŗn de fotos mÃĄis lentas.", + "do_not_show_again": "Non mostrar esta mensaxe de novo", + "documentation": "DocumentaciÃŗn", + "done": "Feito", + "download": "Descargar", + "download_canceled": "Descarga cancelada", + "download_complete": "Descarga completada", + "download_enqueue": "Descarga en cola", + "download_error": "Erro na Descarga", + "download_failed": "Descarga fallada", + "download_filename": "ficheiro: {}", + "download_finished": "Descarga finalizada", + "download_include_embedded_motion_videos": "Vídeos incrustados", + "download_include_embedded_motion_videos_description": "Incluír vídeos incrustados en fotos en movemento como un ficheiro separado", + "download_notfound": "Descarga non atopada", + "download_paused": "Descarga pausada", + "download_settings": "Descarga", + "download_settings_description": "Xestionar configuraciÃŗns relacionadas coa descarga de activos", + "download_started": "Descarga iniciada", + "download_sucess": "Descarga exitosa", + "download_sucess_android": "Os medios descargÃĄronse en DCIM/Immich", + "download_waiting_to_retry": "Agardando para reintentar", + "downloading": "Descargando", + "downloading_asset_filename": "Descargando activo {filename}", + "downloading_media": "Descargando medios", + "drop_files_to_upload": "Solte ficheiros en calquera lugar para cargar", + "duplicates": "Duplicados", + "duplicates_description": "Resolve cada grupo indicando cales, se os houber, son duplicados", + "duration": "DuraciÃŗn", + "edit": "Editar", + "edit_album": "Editar ÃĄlbum", + "edit_avatar": "Editar avatar", + "edit_date": "Editar data", + "edit_date_and_time": "Editar data e hora", + "edit_exclusion_pattern": "Editar padrÃŗn de exclusiÃŗn", + "edit_faces": "Editar caras", + "edit_import_path": "Editar ruta de importaciÃŗn", + "edit_import_paths": "Editar Rutas de ImportaciÃŗn", + "edit_key": "Editar chave", + "edit_link": "Editar ligazÃŗn", + "edit_location": "Editar ubicaciÃŗn", + "edit_location_dialog_title": "UbicaciÃŗn", + "edit_name": "Editar nome", + "edit_people": "Editar persoas", + "edit_tag": "Editar etiqueta", + "edit_title": "Editar Título", + "edit_user": "Editar usuario", + "edited": "Editado", + "editor": "Editor", + "editor_close_without_save_prompt": "Os cambios non se gardarÃĄn", + "editor_close_without_save_title": "Pechar editor?", + "editor_crop_tool_h2_aspect_ratios": "ProporciÃŗns de aspecto", + "editor_crop_tool_h2_rotation": "RotaciÃŗn", + "email": "Correo electrÃŗnico", + "empty_folder": "Este cartafol estÃĄ baleiro", + "empty_trash": "Baleirar lixo", + "empty_trash_confirmation": "EstÃĄs seguro de que queres baleirar o lixo? Isto eliminarÃĄ permanentemente todos os activos no lixo de Immich. Non podes desfacer esta acciÃŗn!", + "enable": "Activar", + "enabled": "Activado", + "end_date": "Data de fin", + "enqueued": "En cola", + "enter_wifi_name": "Introducir nome da WiFi", + "error": "Erro", + "error_change_sort_album": "Erro ao cambiar a orde de clasificaciÃŗn do ÃĄlbum", + "error_delete_face": "Erro ao eliminar a cara do activo", + "error_loading_image": "Erro ao cargar a imaxe", + "error_saving_image": "Erro: {}", + "error_title": "Erro - Algo saíu mal", + "errors": { + "cannot_navigate_next_asset": "Non se pode navegar ao seguinte activo", + "cannot_navigate_previous_asset": "Non se pode navegar ao activo anterior", + "cant_apply_changes": "Non se poden aplicar os cambios", + "cant_change_activity": "Non se pode {enabled, select, true {desactivar} other {activar}} a actividade", + "cant_change_asset_favorite": "Non se pode cambiar o favorito do activo", + "cant_change_metadata_assets_count": "Non se poden cambiar os metadatos de {count, plural, one {# activo} other {# activos}}", + "cant_get_faces": "Non se poden obter caras", + "cant_get_number_of_comments": "Non se pode obter o nÃēmero de comentarios", + "cant_search_people": "Non se poden buscar persoas", + "cant_search_places": "Non se poden buscar lugares", + "cleared_jobs": "Traballos borrados para: {job}", + "error_adding_assets_to_album": "Erro ao engadir activos ao ÃĄlbum", + "error_adding_users_to_album": "Erro ao engadir usuarios ao ÃĄlbum", + "error_deleting_shared_user": "Erro ao eliminar o usuario compartido", + "error_downloading": "Erro ao descargar {filename}", + "error_hiding_buy_button": "Erro ao ocultar o botÃŗn de compra", + "error_removing_assets_from_album": "Erro ao eliminar activos do ÃĄlbum, comprobe a consola para mÃĄis detalles", + "error_selecting_all_assets": "Erro ao seleccionar todos os activos", + "exclusion_pattern_already_exists": "Este padrÃŗn de exclusiÃŗn xa existe.", + "failed_job_command": "O comando {command} fallou para o traballo: {job}", + "failed_to_create_album": "Erro ao crear o ÃĄlbum", + "failed_to_create_shared_link": "Erro ao crear a ligazÃŗn compartida", + "failed_to_edit_shared_link": "Erro ao editar a ligazÃŗn compartida", + "failed_to_get_people": "Erro ao obter persoas", + "failed_to_keep_this_delete_others": "Erro ao conservar este activo e eliminar os outros activos", + "failed_to_load_asset": "Erro ao cargar o activo", + "failed_to_load_assets": "Erro ao cargar activos", + "failed_to_load_people": "Erro ao cargar persoas", + "failed_to_remove_product_key": "Erro ao eliminar a chave do produto", + "failed_to_stack_assets": "Erro ao apilar activos", + "failed_to_unstack_assets": "Erro ao desapilar activos", + "import_path_already_exists": "Esta ruta de importaciÃŗn xa existe.", + "incorrect_email_or_password": "Correo electrÃŗnico ou contrasinal incorrectos", + "paths_validation_failed": "{paths, plural, one {# ruta fallou} other {# rutas fallaron}} na validaciÃŗn", + "profile_picture_transparent_pixels": "As imaxes de perfil non poden ter píxeles transparentes. Por favor, faga zoom e/ou mova a imaxe.", + "quota_higher_than_disk_size": "Estableceu unha cota superior ao tamaÃąo do disco", + "repair_unable_to_check_items": "Non se puideron comprobar {count, select, one {elemento} other {elementos}}", + "unable_to_add_album_users": "Non se puideron engadir usuarios ao ÃĄlbum", + "unable_to_add_assets_to_shared_link": "Non se puideron engadir activos ÃĄ ligazÃŗn compartida", + "unable_to_add_comment": "Non se puido engadir o comentario", + "unable_to_add_exclusion_pattern": "Non se puido engadir o padrÃŗn de exclusiÃŗn", + "unable_to_add_import_path": "Non se puido engadir a ruta de importaciÃŗn", + "unable_to_add_partners": "Non se puideron engadir compaÃąeiros/as", + "unable_to_add_remove_archive": "Non se puido {archived, select, true {eliminar activo do} other {engadir activo ao}} arquivo", + "unable_to_add_remove_favorites": "Non se puido {favorite, select, true {engadir activo a} other {eliminar activo de}} favoritos", + "unable_to_archive_unarchive": "Non se puido {archived, select, true {arquivar} other {desarquivar}}", + "unable_to_change_album_user_role": "Non se puido cambiar o rol do usuario do ÃĄlbum", + "unable_to_change_date": "Non se puido cambiar a data", + "unable_to_change_favorite": "Non se puido cambiar o favorito do activo", + "unable_to_change_location": "Non se puido cambiar a ubicaciÃŗn", + "unable_to_change_password": "Non se puido cambiar o contrasinal", + "unable_to_change_visibility": "Non se puido cambiar a visibilidade para {count, plural, one {# persoa} other {# persoas}}", + "unable_to_complete_oauth_login": "Non se puido completar o inicio de sesiÃŗn OAuth", + "unable_to_connect": "Non se puido conectar", + "unable_to_connect_to_server": "Non se puido conectar ao servidor", + "unable_to_copy_to_clipboard": "Non se puido copiar ao portapapeis, asegÃērate de acceder ÃĄ pÃĄxina a travÊs de https", + "unable_to_create_admin_account": "Non se puido crear a conta de administrador", + "unable_to_create_api_key": "Non se puido crear unha nova Chave API", + "unable_to_create_library": "Non se puido crear a biblioteca", + "unable_to_create_user": "Non se puido crear o usuario", + "unable_to_delete_album": "Non se puido eliminar o ÃĄlbum", + "unable_to_delete_asset": "Non se puido eliminar o activo", + "unable_to_delete_assets": "Erro ao eliminar activos", + "unable_to_delete_exclusion_pattern": "Non se puido eliminar o padrÃŗn de exclusiÃŗn", + "unable_to_delete_import_path": "Non se puido eliminar a ruta de importaciÃŗn", + "unable_to_delete_shared_link": "Non se puido eliminar a ligazÃŗn compartida", + "unable_to_delete_user": "Non se puido eliminar o usuario", + "unable_to_download_files": "Non se puideron descargar os ficheiros", + "unable_to_edit_exclusion_pattern": "Non se puido editar o padrÃŗn de exclusiÃŗn", + "unable_to_edit_import_path": "Non se puido editar a ruta de importaciÃŗn", + "unable_to_empty_trash": "Non se puido baleirar o lixo", + "unable_to_enter_fullscreen": "Non se puido entrar en pantalla completa", + "unable_to_exit_fullscreen": "Non se puido saír da pantalla completa", + "unable_to_get_comments_number": "Non se puido obter o nÃēmero de comentarios", + "unable_to_get_shared_link": "Erro ao obter a ligazÃŗn compartida", + "unable_to_hide_person": "Non se puido ocultar a persoa", + "unable_to_link_motion_video": "Non se puido ligar o vídeo en movemento", + "unable_to_link_oauth_account": "Non se puido ligar a conta OAuth", + "unable_to_load_album": "Non se puido cargar o ÃĄlbum", + "unable_to_load_asset_activity": "Non se puido cargar a actividade do activo", + "unable_to_load_items": "Non se puideron cargar os elementos", + "unable_to_load_liked_status": "Non se puido cargar o estado de gustar", + "unable_to_log_out_all_devices": "Non se puido pechar sesiÃŗn en todos os dispositivos", + "unable_to_log_out_device": "Non se puido pechar sesiÃŗn no dispositivo", + "unable_to_login_with_oauth": "Non se puido iniciar sesiÃŗn con OAuth", + "unable_to_play_video": "Non se puido reproducir o vídeo", + "unable_to_reassign_assets_existing_person": "Non se puideron reasignar activos a {name, select, null {unha persoa existente} other {{name}}}", + "unable_to_reassign_assets_new_person": "Non se puideron reasignar activos a unha nova persoa", + "unable_to_refresh_user": "Non se puido actualizar o usuario", + "unable_to_remove_album_users": "Non se puideron eliminar usuarios do ÃĄlbum", + "unable_to_remove_api_key": "Non se puido eliminar a Chave API", + "unable_to_remove_assets_from_shared_link": "Non se puideron eliminar activos da ligazÃŗn compartida", + "unable_to_remove_deleted_assets": "Non se puideron eliminar ficheiros fÃŗra de liÃąa", + "unable_to_remove_library": "Non se puido eliminar a biblioteca", + "unable_to_remove_partner": "Non se puido eliminar o/a compaÃąeiro/a", + "unable_to_remove_reaction": "Non se puido eliminar a reacciÃŗn", + "unable_to_repair_items": "Non se puideron reparar os elementos", + "unable_to_reset_password": "Non se puido restablecer o contrasinal", + "unable_to_resolve_duplicate": "Non se puido resolver o duplicado", + "unable_to_restore_assets": "Non se puideron restaurar os activos", + "unable_to_restore_trash": "Non se puido restaurar o lixo", + "unable_to_restore_user": "Non se puido restaurar o usuario", + "unable_to_save_album": "Non se puido gardar o ÃĄlbum", + "unable_to_save_api_key": "Non se puido gardar a Chave API", + "unable_to_save_date_of_birth": "Non se puido gardar a data de nacemento", + "unable_to_save_name": "Non se puido gardar o nome", + "unable_to_save_profile": "Non se puido gardar o perfil", + "unable_to_save_settings": "Non se puido gardar a configuraciÃŗn", + "unable_to_scan_libraries": "Non se puideron escanear as bibliotecas", + "unable_to_scan_library": "Non se puido escanear a biblioteca", + "unable_to_set_feature_photo": "Non se puido establecer a foto destacada", + "unable_to_set_profile_picture": "Non se puido establecer a imaxe de perfil", + "unable_to_submit_job": "Non se puido enviar o traballo", + "unable_to_trash_asset": "Non se puido mover o activo ao lixo", + "unable_to_unlink_account": "Non se puido desvincular a conta", + "unable_to_unlink_motion_video": "Non se puido desvincular o vídeo en movemento", + "unable_to_update_album_cover": "Non se puido actualizar a portada do ÃĄlbum", + "unable_to_update_album_info": "Non se puido actualizar a informaciÃŗn do ÃĄlbum", + "unable_to_update_library": "Non se puido actualizar a biblioteca", + "unable_to_update_location": "Non se puido actualizar a ubicaciÃŗn", + "unable_to_update_settings": "Non se puido actualizar a configuraciÃŗn", + "unable_to_update_timeline_display_status": "Non se puido actualizar o estado de visualizaciÃŗn da liÃąa de tempo", + "unable_to_update_user": "Non se puido actualizar o usuario", + "unable_to_upload_file": "Non se puido cargar o ficheiro" + }, + "exif": "Exif", + "exif_bottom_sheet_description": "Engadir DescriciÃŗn...", + "exif_bottom_sheet_details": "DETALLES", + "exif_bottom_sheet_location": "UBICACIÓN", + "exif_bottom_sheet_people": "PERSOAS", + "exif_bottom_sheet_person_add_person": "Engadir nome", + "exif_bottom_sheet_person_age": "Idade {}", + "exif_bottom_sheet_person_age_months": "Idade {} meses", + "exif_bottom_sheet_person_age_year_months": "Idade 1 ano, {} meses", + "exif_bottom_sheet_person_age_years": "Idade {}", + "exit_slideshow": "Saír da PresentaciÃŗn", + "expand_all": "Expandir todo", + "experimental_settings_new_asset_list_subtitle": "Traballo en progreso", + "experimental_settings_new_asset_list_title": "Activar grella de fotos experimental", + "experimental_settings_subtitle": "Use baixo o teu propio risco!", "experimental_settings_title": "Experimental", - "external_network": "External network", - "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", - "failed": "Failed", - "favorites": "Favorites", - "favorites_page_no_favorites": "No favorite assets found", - "filter": "Filter", - "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", - "grant_permission": "Grant permission", - "haptic_feedback_switch": "Enable haptic feedback", - "haptic_feedback_title": "Haptic Feedback", - "header_settings_add_header_tip": "Add Header", - "header_settings_field_validator_msg": "Value cannot be empty", - "header_settings_header_name_input": "Header name", - "header_settings_header_value_input": "Header value", - "headers_settings_tile_subtitle": "Define proxy headers the app should send with each network request", - "headers_settings_tile_title": "Custom proxy headers", - "home_page_add_to_album_conflicts": "Added {added} assets to album {album}. {failed} assets are already in the album.", - "home_page_add_to_album_err_local": "Can not add local assets to albums yet, skipping", - "home_page_add_to_album_success": "Added {added} assets to album {album}.", - "home_page_album_err_partner": "Can not add partner assets to an album yet, skipping", - "home_page_archive_err_local": "Can not archive local assets yet, skipping", - "home_page_archive_err_partner": "Can not archive partner assets, skipping", - "home_page_building_timeline": "Building the timeline", - "home_page_delete_err_partner": "Can not delete partner assets, skipping", - "home_page_delete_remote_err_local": "Local assets in delete remote selection, skipping", - "home_page_favorite_err_local": "Can not favorite local assets yet, skipping", - "home_page_favorite_err_partner": "Can not favorite partner assets yet, skipping", - "home_page_first_time_notice": "If this is your first time using the app, please make sure to choose a backup album(s) so that the timeline can populate photos and videos in the album(s).", - "home_page_share_err_local": "Can not share local assets via link, skipping", - "home_page_upload_err_limit": "Can only upload a maximum of 30 assets at a time, skipping", - "ignore_icloud_photos": "Ignore iCloud photos", - "ignore_icloud_photos_description": "Photos that are stored on iCloud will not be uploaded to the Immich server", - "image_saved_successfully": "Image saved", - "image_viewer_page_state_provider_download_started": "Download Started", - "image_viewer_page_state_provider_download_success": "Download Success", - "image_viewer_page_state_provider_share_error": "Share Error", - "invalid_date": "Invalid date", - "invalid_date_format": "Invalid date format", - "library": "Library", - "library_page_device_albums": "Albums on Device", - "library_page_new_album": "New album", - "library_page_sort_asset_count": "Number of assets", - "library_page_sort_created": "Created date", - "library_page_sort_last_modified": "Last modified", - "library_page_sort_title": "Album title", - "local_network": "Local network", - "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", - "location_permission": "Location permission", - "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", - "location_picker_choose_on_map": "Choose on map", - "location_picker_latitude_error": "Enter a valid latitude", - "location_picker_latitude_hint": "Enter your latitude here", - "location_picker_longitude_error": "Enter a valid longitude", - "location_picker_longitude_hint": "Enter your longitude here", - "login_disabled": "Login has been disabled", - "login_form_api_exception": "API exception. Please check the server URL and try again.", - "login_form_back_button_text": "Back", - "login_form_email_hint": "youremail@email.com", - "login_form_endpoint_hint": "http://your-server-ip:port", - "login_form_endpoint_url": "Server Endpoint URL", - "login_form_err_http": "Please specify http:// or https://", - "login_form_err_invalid_email": "Invalid Email", - "login_form_err_invalid_url": "Invalid URL", - "login_form_err_leading_whitespace": "Leading whitespace", - "login_form_err_trailing_whitespace": "Trailing whitespace", - "login_form_failed_get_oauth_server_config": "Error logging using OAuth, check server URL", - "login_form_failed_get_oauth_server_disable": "OAuth feature is not available on this server", - "login_form_failed_login": "Error logging you in, check server URL, email and password", - "login_form_handshake_exception": "There was an Handshake Exception with the server. Enable self-signed certificate support in the settings if you are using a self-signed certificate.", - "login_form_password_hint": "password", - "login_form_save_login": "Stay logged in", - "login_form_server_empty": "Enter a server URL.", - "login_form_server_error": "Could not connect to server.", - "login_password_changed_error": "There was an error updating your password", - "login_password_changed_success": "Password updated successfully", - "map_assets_in_bound": "{} photo", - "map_assets_in_bounds": "{} photos", - "map_cannot_get_user_location": "Cannot get user's location", - "map_location_dialog_yes": "Yes", - "map_location_picker_page_use_location": "Use this location", - "map_location_service_disabled_content": "Location service needs to be enabled to display assets from your current location. Do you want to enable it now?", - "map_location_service_disabled_title": "Location Service disabled", - "map_no_assets_in_bounds": "No photos in this area", - "map_no_location_permission_content": "Location permission is needed to display assets from your current location. Do you want to allow it now?", - "map_no_location_permission_title": "Location Permission denied", - "map_settings_dark_mode": "Dark mode", - "map_settings_date_range_option_day": "Past 24 hours", - "map_settings_date_range_option_days": "Past {} days", - "map_settings_date_range_option_year": "Past year", - "map_settings_date_range_option_years": "Past {} years", - "map_settings_dialog_title": "Map Settings", - "map_settings_include_show_archived": "Include Archived", - "map_settings_include_show_partners": "Include Partners", - "map_settings_only_show_favorites": "Show Favorite Only", - "map_settings_theme_settings": "Map Theme", - "map_zoom_to_see_photos": "Zoom out to see photos", - "memories_all_caught_up": "All caught up", - "memories_check_back_tomorrow": "Check back tomorrow for more memories", - "memories_start_over": "Start Over", - "memories_swipe_to_close": "Swipe up to close", - "memories_year_ago": "A year ago", - "memories_years_ago": "{} years ago", + "expire_after": "Caduca despois de", + "expired": "Caducado", + "expires_date": "Caduca o {date}", + "explore": "Explorar", + "explorer": "Explorador", + "export": "Exportar", + "export_as_json": "Exportar como JSON", + "extension": "ExtensiÃŗn", + "external": "Externo", + "external_libraries": "Bibliotecas Externas", + "external_network": "Rede externa", + "external_network_sheet_info": "Cando non estea na rede WiFi preferida, a aplicaciÃŗn conectarase ao servidor a travÊs da primeira das seguintes URLs que poida alcanzar, comezando de arriba a abaixo", + "face_unassigned": "Sen asignar", + "failed": "Fallado", + "failed_to_load_assets": "Erro ao cargar activos", + "failed_to_load_folder": "Erro ao cargar o cartafol", + "favorite": "Favorito", + "favorite_or_unfavorite_photo": "Marcar ou desmarcar como favorito", + "favorites": "Favoritos", + "favorites_page_no_favorites": "Non se atoparon activos favoritos", + "feature_photo_updated": "Foto destacada actualizada", + "features": "FunciÃŗns", + "features_setting_description": "Xestionar as funciÃŗns da aplicaciÃŗn", + "file_name": "Nome do ficheiro", + "file_name_or_extension": "Nome do ficheiro ou extensiÃŗn", + "filename": "Nome do ficheiro", + "filetype": "Tipo de ficheiro", + "filter": "Filtro", + "filter_people": "Filtrar persoas", + "filter_places": "Filtrar lugares", + "find_them_fast": "AtÃŗpaos rÃĄpido por nome coa busca", + "fix_incorrect_match": "Corrixir coincidencia incorrecta", + "folder": "Cartafol", + "folder_not_found": "Cartafol non atopado", + "folders": "Cartafoles", + "folders_feature_description": "Navegar pola vista de cartafoles para as fotos e vídeos no sistema de ficheiros", + "forward": "Adiante", + "general": "Xeral", + "get_help": "Obter Axuda", + "get_wifiname_error": "Non se puido obter o nome da Wi-Fi. AsegÃērate de que concedeu os permisos necesarios e estÃĄ conectado a unha rede Wi-Fi", + "getting_started": "Primeiros Pasos", + "go_back": "Volver", + "go_to_folder": "Ir ao cartafol", + "go_to_search": "Ir ÃĄ busca", + "grant_permission": "Conceder permiso", + "group_albums_by": "Agrupar ÃĄlbums por...", + "group_country": "Agrupar por país", + "group_no": "Sen agrupaciÃŗn", + "group_owner": "Agrupar por propietario", + "group_places_by": "Agrupar lugares por...", + "group_year": "Agrupar por ano", + "haptic_feedback_switch": "Activar resposta hÃĄptica", + "haptic_feedback_title": "Resposta HÃĄptica", + "has_quota": "Ten cota", + "header_settings_add_header_tip": "Engadir Cabeceira", + "header_settings_field_validator_msg": "O valor non pode estar baleiro", + "header_settings_header_name_input": "Nome da cabeceira", + "header_settings_header_value_input": "Valor da cabeceira", + "headers_settings_tile_subtitle": "Definir cabeceiras de proxy que a aplicaciÃŗn debería enviar con cada solicitude de rede", + "headers_settings_tile_title": "Cabeceiras de proxy personalizadas", + "hi_user": "Ola {name} ({email})", + "hide_all_people": "Ocultar todas as persoas", + "hide_gallery": "Ocultar galería", + "hide_named_person": "Ocultar persoa {name}", + "hide_password": "Ocultar contrasinal", + "hide_person": "Ocultar persoa", + "hide_unnamed_people": "Ocultar persoas sen nome", + "home_page_add_to_album_conflicts": "Engadidos {added} activos ao ÃĄlbum {album}. {failed} activos xa estÃĄn no ÃĄlbum.", + "home_page_add_to_album_err_local": "Non se poden engadir activos locais a ÃĄlbums aínda, omitindo", + "home_page_add_to_album_success": "Engadidos {added} activos ao ÃĄlbum {album}.", + "home_page_album_err_partner": "Non se poden engadir activos de compaÃąeiro/a a un ÃĄlbum aínda, omitindo", + "home_page_archive_err_local": "Non se poden arquivar activos locais aínda, omitindo", + "home_page_archive_err_partner": "Non se poden arquivar activos de compaÃąeiro/a, omitindo", + "home_page_building_timeline": "Construíndo a liÃąa de tempo", + "home_page_delete_err_partner": "Non se poden eliminar activos de compaÃąeiro/a, omitindo", + "home_page_delete_remote_err_local": "Activos locais na selecciÃŗn de eliminaciÃŗn remota, omitindo", + "home_page_favorite_err_local": "Non se poden marcar como favoritos activos locais aínda, omitindo", + "home_page_favorite_err_partner": "Non se poden marcar como favoritos activos de compaÃąeiro/a aínda, omitindo", + "home_page_first_time_notice": "Se esta Ê a primeira vez que usas a aplicaciÃŗn, asegÃērate de elixir un ÃĄlbum de copia de seguridade para que a liÃąa de tempo poida encherse con fotos e vídeos nel", + "home_page_share_err_local": "Non se poden compartir activos locais mediante ligazÃŗn, omitindo", + "home_page_upload_err_limit": "SÃŗ se pode cargar un mÃĄximo de 30 activos ÃĄ vez, omitindo", + "host": "Host", + "hour": "Hora", + "ignore_icloud_photos": "Ignorar fotos de iCloud", + "ignore_icloud_photos_description": "As fotos que estÃĄn almacenadas en iCloud non se cargarÃĄn ao servidor Immich", + "image": "Imaxe", + "image_alt_text_date": "{isVideo, select, true {Vídeo} other {Imaxe}} tomado/a o {date}", + "image_alt_text_date_1_person": "{isVideo, select, true {Vídeo} other {Imaxe}} tomado/a con {person1} o {date}", + "image_alt_text_date_2_people": "{isVideo, select, true {Vídeo} other {Imaxe}} tomado/a con {person1} e {person2} o {date}", + "image_alt_text_date_3_people": "{isVideo, select, true {Vídeo} other {Imaxe}} tomado/a con {person1}, {person2} e {person3} o {date}", + "image_alt_text_date_4_or_more_people": "{isVideo, select, true {Vídeo} other {Imaxe}} tomado/a con {person1}, {person2} e {additionalCount, number} outros/as o {date}", + "image_alt_text_date_place": "{isVideo, select, true {Vídeo} other {Imaxe}} tomado/a en {city}, {country} o {date}", + "image_alt_text_date_place_1_person": "{isVideo, select, true {Vídeo} other {Imaxe}} tomado/a en {city}, {country} con {person1} o {date}", + "image_alt_text_date_place_2_people": "{isVideo, select, true {Vídeo} other {Imaxe}} tomado/a en {city}, {country} con {person1} e {person2} o {date}", + "image_alt_text_date_place_3_people": "{isVideo, select, true {Vídeo} other {Imaxe}} tomado/a en {city}, {country} con {person1}, {person2} e {person3} o {date}", + "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Vídeo} other {Imaxe}} tomado/a en {city}, {country} con {person1}, {person2} e {additionalCount, number} outros/as o {date}", + "image_saved_successfully": "Imaxe gardada", + "image_viewer_page_state_provider_download_started": "Descarga Iniciada", + "image_viewer_page_state_provider_download_success": "Descarga Exitosa", + "image_viewer_page_state_provider_share_error": "Erro ao Compartir", + "immich_logo": "Logo de Immich", + "immich_web_interface": "Interface Web de Immich", + "import_from_json": "Importar desde JSON", + "import_path": "Ruta de importaciÃŗn", + "in_albums": "En {count, plural, one {# ÃĄlbum} other {# ÃĄlbums}}", + "in_archive": "No arquivo", + "include_archived": "Incluír arquivados", + "include_shared_albums": "Incluír ÃĄlbums compartidos", + "include_shared_partner_assets": "Incluír activos de compaÃąeiro/a compartidos", + "individual_share": "Compartir individual", + "individual_shares": "Compartires individuais", + "info": "InformaciÃŗn", + "interval": { + "day_at_onepm": "Todos os días ÃĄs 13:00", + "hours": "Cada {hours, plural, one {hora} other {{hours, number} horas}}", + "night_at_midnight": "Todas as noites ÃĄ medianoite", + "night_at_twoam": "Todas as noites ÃĄs 2:00" + }, + "invalid_date": "Data invÃĄlida", + "invalid_date_format": "Formato de data invÃĄlido", + "invite_people": "Invitar Persoas", + "invite_to_album": "Invitar ao ÃĄlbum", + "items_count": "{count, plural, one {# elemento} other {# elementos}}", + "jobs": "Traballos", + "keep": "Conservar", + "keep_all": "Conservar Todo", + "keep_this_delete_others": "Conservar este, eliminar outros", + "kept_this_deleted_others": "Conservouse este activo e eliminÃĄronse {count, plural, one {# activo} other {# activos}}", + "keyboard_shortcuts": "Atallos de teclado", + "language": "Lingua", + "language_setting_description": "Seleccione a tÃēa lingua preferida", + "last_seen": "Visto por Ãēltima vez", + "latest_version": "Última VersiÃŗn", + "latitude": "Latitude", + "leave": "Saír", + "lens_model": "Modelo da lente", + "let_others_respond": "Permitir que outros respondan", + "level": "Nivel", + "library": "Biblioteca", + "library_options": "OpciÃŗns da biblioteca", + "library_page_device_albums": "Álbums no Dispositivo", + "library_page_new_album": "Novo ÃĄlbum", + "library_page_sort_asset_count": "NÃēmero de activos", + "library_page_sort_created": "Data de creaciÃŗn", + "library_page_sort_last_modified": "Última modificaciÃŗn", + "library_page_sort_title": "Título do ÃĄlbum", + "light": "Claro", + "like_deleted": "GÃēstame eliminado", + "link_motion_video": "Ligar vídeo en movemento", + "link_options": "OpciÃŗns da ligazÃŗn", + "link_to_oauth": "Ligar a OAuth", + "linked_oauth_account": "Conta OAuth ligada", + "list": "Lista", + "loading": "Cargando", + "loading_search_results_failed": "Erro ao cargar os resultados da busca", + "local_network": "Rede local", + "local_network_sheet_info": "A aplicaciÃŗn conectarase ao servidor a travÊs desta URL cando use a rede Wi-Fi especificada", + "location_permission": "Permiso de ubicaciÃŗn", + "location_permission_content": "Para usar a funciÃŗn de cambio automÃĄtico, Immich necesita permiso de ubicaciÃŗn precisa para poder ler o nome da rede WiFi actual", + "location_picker_choose_on_map": "Elixir no mapa", + "location_picker_latitude_error": "Introducir unha latitude vÃĄlida", + "location_picker_latitude_hint": "Introduza a tÃēa latitude aquí", + "location_picker_longitude_error": "Introducir unha lonxitude vÃĄlida", + "location_picker_longitude_hint": "Introduza a tÃēa lonxitude aquí", + "log_out": "Pechar sesiÃŗn", + "log_out_all_devices": "Pechar SesiÃŗn en Todos os Dispositivos", + "logged_out_all_devices": "Pechouse sesiÃŗn en todos os dispositivos", + "logged_out_device": "Pechouse sesiÃŗn no dispositivo", + "login": "Iniciar sesiÃŗn", + "login_disabled": "O inicio de sesiÃŗn foi desactivado", + "login_form_api_exception": "ExcepciÃŗn da API. Por favor, comprobe a URL do servidor e intÊnteo de novo.", + "login_form_back_button_text": "AtrÃĄs", + "login_form_email_hint": "oteuemail@email.com", + "login_form_endpoint_hint": "http://ip-do-teu-servidor:porto", + "login_form_endpoint_url": "URL do Punto Final do Servidor", + "login_form_err_http": "Por favor, especifique http:// ou https://", + "login_form_err_invalid_email": "Correo electrÃŗnico invÃĄlido", + "login_form_err_invalid_url": "URL invÃĄlida", + "login_form_err_leading_whitespace": "Espazo en branco inicial", + "login_form_err_trailing_whitespace": "Espazo en branco final", + "login_form_failed_get_oauth_server_config": "Erro ao iniciar sesiÃŗn usando OAuth, comprobe a URL do servidor", + "login_form_failed_get_oauth_server_disable": "A funciÃŗn OAuth non estÃĄ dispoÃąible neste servidor", + "login_form_failed_login": "Erro ao iniciar sesiÃŗn, comproba a URL do servidor, correo electrÃŗnico e contrasinal", + "login_form_handshake_exception": "Houbo unha ExcepciÃŗn de Handshake co servidor. Activa o soporte para certificados autofirmados nas configuraciÃŗns se estÃĄs a usar un certificado autofirmado.", + "login_form_password_hint": "contrasinal", + "login_form_save_login": "Manter sesiÃŗn iniciada", + "login_form_server_empty": "Introduza unha URL do servidor.", + "login_form_server_error": "Non se puido conectar co servidor.", + "login_has_been_disabled": "O inicio de sesiÃŗn foi desactivado.", + "login_password_changed_error": "Houbo un erro ao actualizar o teu contrasinal", + "login_password_changed_success": "Contrasinal actualizado correctamente", + "logout_all_device_confirmation": "EstÃĄs seguro de que queres pechar sesiÃŗn en todos os dispositivos?", + "logout_this_device_confirmation": "EstÃĄs seguro de que queres pechar sesiÃŗn neste dispositivo?", + "longitude": "Lonxitude", + "look": "Ollar", + "loop_videos": "Reproducir vídeos en bucle", + "loop_videos_description": "Activar para reproducir automaticamente un vídeo en bucle no visor de detalles.", + "main_branch_warning": "EstÃĄ a usar unha versiÃŗn de desenvolvemento; recomendamos encarecidamente usar unha versiÃŗn de lanzamento!", + "main_menu": "MenÃē principal", + "make": "Marca", + "manage_shared_links": "Xestionar ligazÃŗns compartidas", + "manage_sharing_with_partners": "Xestionar comparticiÃŗn con compaÃąeiros/as", + "manage_the_app_settings": "Xestionar a configuraciÃŗn da aplicaciÃŗn", + "manage_your_account": "Xestionar a tÃēa conta", + "manage_your_api_keys": "Xestionar as tÃēas claves API", + "manage_your_devices": "Xestionar os teus dispositivos con sesiÃŗn iniciada", + "manage_your_oauth_connection": "Xestionar a tÃēa conexiÃŗn OAuth", + "map": "Mapa", + "map_assets_in_bound": "{} foto", + "map_assets_in_bounds": "{} fotos", + "map_cannot_get_user_location": "Non se pode obter a ubicaciÃŗn do usuario", + "map_location_dialog_yes": "Si", + "map_location_picker_page_use_location": "Usar esta ubicaciÃŗn", + "map_location_service_disabled_content": "O servizo de ubicaciÃŗn debe estar activado para mostrar activos da tÃēa ubicaciÃŗn actual. Queres activalo agora?", + "map_location_service_disabled_title": "Servizo de ubicaciÃŗn deshabilitado", + "map_marker_for_images": "Marcador de mapa para imaxes tomadas en {city}, {country}", + "map_marker_with_image": "Marcador de mapa con imaxe", + "map_no_assets_in_bounds": "Non hai fotos nesta ÃĄrea", + "map_no_location_permission_content": "Necesítase permiso de ubicaciÃŗn para mostrar activos da sÃēa ubicaciÃŗn actual. Queres permitilo agora?", + "map_no_location_permission_title": "Permiso de ubicaciÃŗn denegado", + "map_settings": "ConfiguraciÃŗn do mapa", + "map_settings_dark_mode": "Modo escuro", + "map_settings_date_range_option_day": "Últimas 24 horas", + "map_settings_date_range_option_days": "Últimos {} días", + "map_settings_date_range_option_year": "Último ano", + "map_settings_date_range_option_years": "Últimos {} anos", + "map_settings_dialog_title": "ConfiguraciÃŗn do Mapa", + "map_settings_include_show_archived": "Incluír Arquivados", + "map_settings_include_show_partners": "Incluír CompaÃąeiros/as", + "map_settings_only_show_favorites": "Mostrar SÃŗ Favoritos", + "map_settings_theme_settings": "Tema do Mapa", + "map_zoom_to_see_photos": "Alonxe o zoom para ver fotos", + "matches": "Coincidencias", + "media_type": "Tipo de medio", + "memories": "Recordos", + "memories_all_caught_up": "Todo ao día", + "memories_check_back_tomorrow": "Volva maÃąÃĄ para mÃĄis recordos", + "memories_setting_description": "Xestionar o que ves nos teus recordos", + "memories_start_over": "Comezar de novo", + "memories_swipe_to_close": "Deslizar cara arriba para pechar", + "memories_year_ago": "Hai un ano", + "memories_years_ago": "Hai {} anos", + "memory": "Recordo", + "memory_lane_title": "CamiÃąo dos Recordos {title}", + "menu": "MenÃē", + "merge": "Fusionar", + "merge_people": "Fusionar persoas", + "merge_people_limit": "SÃŗ pode fusionar ata 5 caras ÃĄ vez", + "merge_people_prompt": "Queres fusionar estas persoas? Esta acciÃŗn Ê irreversible.", + "merge_people_successfully": "Persoas fusionadas correctamente", + "merged_people_count": "Fusionadas {count, plural, one {# persoa} other {# persoas}}", + "minimize": "Minimizar", + "minute": "Minuto", + "missing": "Faltantes", + "model": "Modelo", + "month": "Mes", "monthly_title_text_date_format": "MMMM y", - "multiselect_grid_edit_date_time_err_read_only": "Cannot edit date of read only asset(s), skipping", - "multiselect_grid_edit_gps_err_read_only": "Cannot edit location of read only asset(s), skipping", - "my_albums": "My albums", - "networking_settings": "Networking", - "networking_subtitle": "Manage the server endpoint settings", - "no_assets_to_show": "No assets to show", - "no_name": "No name", - "not_selected": "Not selected", - "notification_permission_dialog_content": "To enable notifications, go to Settings and select allow.", - "notification_permission_list_tile_content": "Grant permission to enable notifications.", - "notification_permission_list_tile_enable_button": "Enable Notifications", - "notification_permission_list_tile_title": "Notification Permission", - "on_this_device": "On this device", - "partner_list_user_photos": "{user}'s photos", - "partner_list_view_all": "View all", - "partner_page_empty_message": "Your photos are not yet shared with any partner.", - "partner_page_no_more_users": "No more users to add", - "partner_page_partner_add_failed": "Failed to add partner", - "partner_page_select_partner": "Select partner", - "partner_page_shared_to_title": "Shared to", - "partner_page_stop_sharing_content": "{} will no longer be able to access your photos.", - "partners": "Partners", - "paused": "Paused", - "people": "People", - "permission_onboarding_back": "Back", - "permission_onboarding_continue_anyway": "Continue anyway", - "permission_onboarding_get_started": "Get started", - "permission_onboarding_go_to_settings": "Go to settings", - "permission_onboarding_permission_denied": "Permission denied. To use Immich, grant photo and video permissions in Settings.", - "permission_onboarding_permission_granted": "Permission granted! You are all set.", - "permission_onboarding_permission_limited": "Permission limited. To let Immich backup and manage your entire gallery collection, grant photo and video permissions in Settings.", - "permission_onboarding_request": "Immich requires permission to view your photos and videos.", - "places": "Places", - "preferences_settings_subtitle": "Manage the app's preferences", - "preferences_settings_title": "Preferences", - "profile_drawer_app_logs": "Logs", - "profile_drawer_client_out_of_date_major": "Mobile App is out of date. Please update to the latest major version.", - "profile_drawer_client_out_of_date_minor": "Mobile App is out of date. Please update to the latest minor version.", - "profile_drawer_client_server_up_to_date": "Client and Server are up-to-date", + "more": "MÃĄis", + "moved_to_trash": "Movido ao lixo", + "multiselect_grid_edit_date_time_err_read_only": "Non se pode editar a data de activo(s) de sÃŗ lectura, omitindo", + "multiselect_grid_edit_gps_err_read_only": "Non se pode editar a ubicaciÃŗn de activo(s) de sÃŗ lectura, omitindo", + "mute_memories": "Silenciar Recordos", + "my_albums": "Os meus ÃĄlbums", + "name": "Nome", + "name_or_nickname": "Nome ou alcume", + "networking_settings": "Rede", + "networking_subtitle": "Xestionar a configuraciÃŗn do punto final do servidor", + "never": "Nunca", + "new_album": "Novo Álbum", + "new_api_key": "Nova Chave API", + "new_password": "Novo contrasinal", + "new_person": "Nova persoa", + "new_user_created": "Novo usuario creado", + "new_version_available": "NOVA VERSIÓN DISPOÑIBLE", + "newest_first": "MÃĄis recentes primeiro", + "next": "Seguinte", + "next_memory": "Seguinte recordo", + "no": "Non", + "no_albums_message": "Crea un ÃĄlbum para organizar as tÃēas fotos e vídeos", + "no_albums_with_name_yet": "Parece que aínda non tes ningÃēn ÃĄlbum con este nome.", + "no_albums_yet": "Parece que aínda non tes ningÃēn ÃĄlbum.", + "no_archived_assets_message": "Arquiva fotos e vídeos para ocultalos da tÃēa vista de Fotos", + "no_assets_message": "PREMA PARA CARGAR A SÚA PRIMEIRA FOTO", + "no_assets_to_show": "Non hai activos para mostrar", + "no_duplicates_found": "Non se atoparon duplicados.", + "no_exif_info_available": "Non hai informaciÃŗn exif dispoÃąible", + "no_explore_results_message": "Suba mÃĄis fotos para explorar a tÃēa colecciÃŗn.", + "no_favorites_message": "Engade favoritos para atopar rapidamente as tÃēas mellores fotos e vídeos", + "no_libraries_message": "Crea unha biblioteca externa para ver as tÃēas fotos e vídeos", + "no_name": "Sen Nome", + "no_places": "Sen lugares", + "no_results": "Sen resultados", + "no_results_description": "Proba cun sinÃŗnimo ou palabra chave mÃĄis xeral", + "no_shared_albums_message": "Crea un ÃĄlbum para compartir fotos e vídeos con persoas na tÃēa rede", + "not_in_any_album": "Non estÃĄ en ningÃēn ÃĄlbum", + "not_selected": "Non seleccionado", + "note_apply_storage_label_to_previously_uploaded assets": "Nota: Para aplicar a Etiqueta de Almacenamento a activos cargados previamente, execute o", + "notes": "Notas", + "notification_permission_dialog_content": "Para activar as notificaciÃŗns, vaia a Axustes e seleccione permitir.", + "notification_permission_list_tile_content": "Conceda permiso para activar as notificaciÃŗns.", + "notification_permission_list_tile_enable_button": "Activar NotificaciÃŗns", + "notification_permission_list_tile_title": "Permiso de NotificaciÃŗn", + "notification_toggle_setting_description": "Activar notificaciÃŗns por correo electrÃŗnico", + "notifications": "NotificaciÃŗns", + "notifications_setting_description": "Xestionar notificaciÃŗns", + "oauth": "OAuth", + "official_immich_resources": "Recursos Oficiais de Immich", + "offline": "FÃŗra de liÃąa", + "offline_paths": "Rutas fÃŗra de liÃąa", + "offline_paths_description": "Estes resultados poden deberse ÃĄ eliminaciÃŗn manual de ficheiros que non forman parte dunha biblioteca externa.", + "ok": "Aceptar", + "oldest_first": "MÃĄis antigos primeiro", + "on_this_device": "Neste dispositivo", + "onboarding": "IncorporaciÃŗn", + "onboarding_privacy_description": "As seguintes funciÃŗns (opcionais) dependen de servizos externos e poden desactivarse en calquera momento na configuraciÃŗn da administraciÃŗn.", + "onboarding_theme_description": "Elixe un tema de cor para a tÃēa instancia. Podes cambialo mÃĄis tarde na tÃēa configuraciÃŗn.", + "onboarding_welcome_description": "Imos configurar a tÃēa instancia con algunhas configuraciÃŗns comÃēns.", + "onboarding_welcome_user": "Benvido/a, {user}", + "online": "En liÃąa", + "only_favorites": "SÃŗ favoritos", + "open": "Abrir", + "open_in_map_view": "Abrir na vista de mapa", + "open_in_openstreetmap": "Abrir en OpenStreetMap", + "open_the_search_filters": "Abrir os filtros de busca", + "options": "OpciÃŗns", + "or": "ou", + "organize_your_library": "Organizar a tÃēa biblioteca", + "original": "orixinal", + "other": "Outro", + "other_devices": "Outros dispositivos", + "other_variables": "Outras variables", + "owned": "Propio", + "owner": "Propietario", + "partner": "CompaÃąeiro/a", + "partner_can_access": "{partner} pode acceder a", + "partner_can_access_assets": "Todas as tÃēas fotos e vídeos excepto os de Arquivo e Eliminados", + "partner_can_access_location": "A ubicaciÃŗn onde se tomaron as tÃēas fotos", + "partner_list_user_photos": "Fotos de {user}", + "partner_list_view_all": "Ver todo", + "partner_page_empty_message": "As sÃēas fotos aínda non estÃĄn compartidas con ningÃēn compaÃąeiro/a.", + "partner_page_no_more_users": "Non hai mÃĄis usuarios para engadir", + "partner_page_partner_add_failed": "Erro ao engadir compaÃąeiro/a", + "partner_page_select_partner": "Seleccionar compaÃąeiro/a", + "partner_page_shared_to_title": "Compartido con", + "partner_page_stop_sharing_content": "{} xa non poderÃĄs acceder ÃĄs tÃēas fotos.", + "partner_sharing": "ComparticiÃŗn con CompaÃąeiro/a", + "partners": "CompaÃąeiros/as", + "password": "Contrasinal", + "password_does_not_match": "O contrasinal non coincide", + "password_required": "Requírese Contrasinal", + "password_reset_success": "Contrasinal restablecido correctamente", + "past_durations": { + "days": "Últimos {days, plural, one {día} other {# días}}", + "hours": "Últimas {hours, plural, one {hora} other {# horas}}", + "years": "Últimos {years, plural, one {ano} other {# anos}}" + }, + "path": "Ruta", + "pattern": "PadrÃŗn", + "pause": "Pausa", + "pause_memories": "Pausar recordos", + "paused": "Pausado", + "pending": "Pendente", + "people": "Persoas", + "people_edits_count": "Editadas {count, plural, one {# persoa} other {# persoas}}", + "people_feature_description": "Navegar por fotos e vídeos agrupados por persoas", + "people_sidebar_description": "Mostrar unha ligazÃŗn a Persoas na barra lateral", + "permanent_deletion_warning": "Aviso de eliminaciÃŗn permanente", + "permanent_deletion_warning_setting_description": "Mostrar un aviso ao eliminar permanentemente activos", + "permanently_delete": "Eliminar permanentemente", + "permanently_delete_assets_count": "Eliminar permanentemente {count, plural, one {activo} other {activos}}", + "permanently_delete_assets_prompt": "EstÃĄs seguro de que queres eliminar permanentemente {count, plural, one {este activo?} other {estes # activos?}} Isto tamÊn {count, plural, one {o eliminarÃĄ do teu} other {os eliminarÃĄ dos teus}} ÃĄlbum(s).", + "permanently_deleted_asset": "Activo eliminado permanentemente", + "permanently_deleted_assets_count": "Eliminados permanentemente {count, plural, one {# activo} other {# activos}}", + "permission_onboarding_back": "AtrÃĄs", + "permission_onboarding_continue_anyway": "Continuar de todos os xeitos", + "permission_onboarding_get_started": "Comezar", + "permission_onboarding_go_to_settings": "Ir a axustes", + "permission_onboarding_permission_denied": "Permiso denegado. Para usar Immich, conceda permisos de fotos e vídeos en Axustes.", + "permission_onboarding_permission_granted": "Permiso concedido! Xa estÃĄ todo listo.", + "permission_onboarding_permission_limited": "Permiso limitado. Para permitir que Immich faga copia de seguridade e xestione toda a tÃēa colecciÃŗn da galería, conceda permisos de fotos e vídeos en ConfiguraciÃŗn.", + "permission_onboarding_request": "Immich require permiso para ver as tÃēas fotos e vídeos.", + "person": "Persoa", + "person_birthdate": "Nacido/a o {date}", + "person_hidden": "{name}{hidden, select, true { (oculto)} other {}}", + "photo_shared_all_users": "Parece que compartiches as tÃēas fotos con todos os usuarios ou non tes ningÃēn usuario co que compartir.", + "photos": "Fotos", + "photos_and_videos": "Fotos e Vídeos", + "photos_count": "{count, plural, one {{count, number} Foto} other {{count, number} Fotos}}", + "photos_from_previous_years": "Fotos de anos anteriores", + "pick_a_location": "Elixir unha ubicaciÃŗn", + "place": "Lugar", + "places": "Lugares", + "places_count": "{count, plural, one {{count, number} Lugar} other {{count, number} Lugares}}", + "play": "Reproducir", + "play_memories": "Reproducir recordos", + "play_motion_photo": "Reproducir Foto en Movemento", + "play_or_pause_video": "Reproducir ou pausar vídeo", + "port": "Porto", + "preferences_settings_subtitle": "Xestionar as preferencias da aplicaciÃŗn", + "preferences_settings_title": "Preferencias", + "preset": "Preaxuste", + "preview": "Vista previa", + "previous": "Anterior", + "previous_memory": "Recordo anterior", + "previous_or_next_photo": "Foto anterior ou seguinte", + "primary": "Principal", + "privacy": "Privacidade", + "profile_drawer_app_logs": "Rexistros", + "profile_drawer_client_out_of_date_major": "A aplicaciÃŗn mÃŗbil estÃĄ desactualizada. Por favor, actualice ÃĄ Ãēltima versiÃŗn maior.", + "profile_drawer_client_out_of_date_minor": "A aplicaciÃŗn mÃŗbil estÃĄ desactualizada. Por favor, actualice ÃĄ Ãēltima versiÃŗn menor.", + "profile_drawer_client_server_up_to_date": "Cliente e Servidor estÃĄn actualizados", "profile_drawer_github": "GitHub", - "profile_drawer_server_out_of_date_major": "Server is out of date. Please update to the latest major version.", - "profile_drawer_server_out_of_date_minor": "Server is out of date. Please update to the latest minor version.", - "recently_added": "Recently added", - "recently_added_page_title": "Recently Added", - "save": "Save", - "save_to_gallery": "Save to gallery", - "scaffold_body_error_occurred": "Error occurred", - "search_albums": "Search albums", - "search_filter_apply": "Apply filter", - "search_filter_camera_title": "Select camera type", - "search_filter_date": "Date", - "search_filter_date_interval": "{start} to {end}", - "search_filter_date_title": "Select a date range", - "search_filter_display_option_not_in_album": "Not in album", - "search_filter_display_options": "Display Options", - "search_filter_location": "Location", - "search_filter_location_title": "Select location", - "search_filter_media_type": "Media Type", - "search_filter_media_type_title": "Select media type", - "search_filter_people_title": "Select people", - "search_page_categories": "Categories", - "search_page_motion_photos": "Motion Photos", - "search_page_no_objects": "No Objects Info Available", - "search_page_no_places": "No Places Info Available", - "search_page_screenshots": "Screenshots", - "search_page_search_photos_videos": "Search for your photos and videos", + "profile_drawer_server_out_of_date_major": "O servidor estÃĄ desactualizado. Por favor, actualice ÃĄ Ãēltima versiÃŗn maior.", + "profile_drawer_server_out_of_date_minor": "O servidor estÃĄ desactualizado. Por favor, actualice ÃĄ Ãēltima versiÃŗn menor.", + "profile_image_of_user": "Imaxe de perfil de {user}", + "profile_picture_set": "Imaxe de perfil establecida.", + "public_album": "Álbum pÃēblico", + "public_share": "Compartir PÃēblico", + "purchase_account_info": "Seguidor/a", + "purchase_activated_subtitle": "Grazas por apoiar Immich e o software de cÃŗdigo aberto", + "purchase_activated_time": "Activado o {date, date}", + "purchase_activated_title": "A sÃēa chave activouse correctamente", + "purchase_button_activate": "Activar", + "purchase_button_buy": "Comprar", + "purchase_button_buy_immich": "Comprar Immich", + "purchase_button_never_show_again": "Non mostrar nunca mÃĄis", + "purchase_button_reminder": "Lembrarme en 30 días", + "purchase_button_remove_key": "Eliminar chave", + "purchase_button_select": "Seleccionar", + "purchase_failed_activation": "Erro ao activar! Por favor, comproba o teu correo electrÃŗnico para a chave do produto correcta!", + "purchase_individual_description_1": "Para un individuo", + "purchase_individual_description_2": "Estado de seguidor/a", + "purchase_individual_title": "Individual", + "purchase_input_suggestion": "Ten unha chave de produto? Introduza a chave a continuaciÃŗn", + "purchase_license_subtitle": "Compre Immich para apoiar o desenvolvemento continuado do servizo", + "purchase_lifetime_description": "Compra vitalicia", + "purchase_option_title": "OPCIÓNS DE COMPRA", + "purchase_panel_info_1": "Construír Immich leva moito tempo e esforzo, e temos enxeÃąeiros a tempo completo traballando nel para facelo o mellor posible. A nosa misiÃŗn Ê que o software de cÃŗdigo aberto e as prÃĄcticas comerciais Êticas se convertan nunha fonte de ingresos sostible para os desenvolvedores e crear un ecosistema respectuoso coa privacidade con alternativas reais aos servizos na nube explotadores.", + "purchase_panel_info_2": "Como estamos comprometidos a non engadir muros de pago, esta compra non che outorgarÃĄ ningunha funciÃŗn adicional en Immich. Dependemos de usuarios coma ti para apoiar o desenvolvemento continuo de Immich.", + "purchase_panel_title": "Apoiar o proxecto", + "purchase_per_server": "Por servidor", + "purchase_per_user": "Por usuario", + "purchase_remove_product_key": "Eliminar Chave do Produto", + "purchase_remove_product_key_prompt": "EstÃĄs seguro de que queres eliminar a chave do produto?", + "purchase_remove_server_product_key": "Eliminar chave do produto do Servidor", + "purchase_remove_server_product_key_prompt": "EstÃĄs seguro de que queres eliminar a chave do produto do Servidor?", + "purchase_server_description_1": "Para todo o servidor", + "purchase_server_description_2": "Estado de seguidor/a", + "purchase_server_title": "Servidor", + "purchase_settings_server_activated": "A chave do produto do servidor Ê xestionada polo administrador", + "rating": "ClasificaciÃŗn por estrelas", + "rating_clear": "Borrar clasificaciÃŗn", + "rating_count": "{count, plural, one {# estrela} other {# estrelas}}", + "rating_description": "Mostrar a clasificaciÃŗn EXIF no panel de informaciÃŗn", + "reaction_options": "OpciÃŗns de reacciÃŗn", + "read_changelog": "Ler Rexistro de Cambios", + "reassign": "Reasignar", + "reassigned_assets_to_existing_person": "Reasignados {count, plural, one {# activo} other {# activos}} a {name, select, null {unha persoa existente} other {{name}}}", + "reassigned_assets_to_new_person": "Reasignados {count, plural, one {# activo} other {# activos}} a unha nova persoa", + "reassing_hint": "Asignar activos seleccionados a unha persoa existente", + "recent": "Recente", + "recent-albums": "Álbums recentes", + "recent_searches": "Buscas recentes", + "recently_added": "Engadido recentemente", + "recently_added_page_title": "Engadido Recentemente", + "refresh": "Actualizar", + "refresh_encoded_videos": "Actualizar vídeos codificados", + "refresh_faces": "Actualizar caras", + "refresh_metadata": "Actualizar metadatos", + "refresh_thumbnails": "Actualizar miniaturas", + "refreshed": "Actualizado", + "refreshes_every_file": "Volve ler todos os ficheiros existentes e novos", + "refreshing_encoded_video": "Actualizando vídeo codificado", + "refreshing_faces": "Actualizando caras", + "refreshing_metadata": "Actualizando metadatos", + "regenerating_thumbnails": "Rexenerando miniaturas", + "remove": "Eliminar", + "remove_assets_album_confirmation": "EstÃĄs seguro de que queres eliminar {count, plural, one {# activo} other {# activos}} do ÃĄlbum?", + "remove_assets_shared_link_confirmation": "EstÃĄs seguro de que queres eliminar {count, plural, one {# activo} other {# activos}} desta ligazÃŗn compartida?", + "remove_assets_title": "Eliminar activos?", + "remove_custom_date_range": "Eliminar rango de datas personalizado", + "remove_deleted_assets": "Eliminar Activos Eliminados", + "remove_from_album": "Eliminar do ÃĄlbum", + "remove_from_favorites": "Eliminar de favoritos", + "remove_from_shared_link": "Eliminar da ligazÃŗn compartida", + "remove_memory": "Eliminar recordo", + "remove_photo_from_memory": "Eliminar foto deste recordo", + "remove_url": "Eliminar URL", + "remove_user": "Eliminar usuario", + "removed_api_key": "Chave API eliminada: {name}", + "removed_from_archive": "Eliminado do arquivo", + "removed_from_favorites": "Eliminado de favoritos", + "removed_from_favorites_count": "{count, plural, other {Eliminados #}} de favoritos", + "removed_memory": "Recordo eliminado", + "removed_photo_from_memory": "Foto eliminada do recordo", + "removed_tagged_assets": "Etiqueta eliminada de {count, plural, one {# activo} other {# activos}}", + "rename": "Renomear", + "repair": "Reparar", + "repair_no_results_message": "Os ficheiros non rastrexados e faltantes aparecerÃĄn aquí", + "replace_with_upload": "Substituír con carga", + "repository": "Repositorio", + "require_password": "Requirir contrasinal", + "require_user_to_change_password_on_first_login": "Requirir que o usuario cambie o contrasinal no primeiro inicio de sesiÃŗn", + "rescan": "Volver escanear", + "reset": "Restablecer", + "reset_password": "Restablecer contrasinal", + "reset_people_visibility": "Restablecer visibilidade das persoas", + "reset_to_default": "Restablecer ao predeterminado", + "resolve_duplicates": "Resolver duplicados", + "resolved_all_duplicates": "ResolvÊronse todos os duplicados", + "restore": "Restaurar", + "restore_all": "Restaurar todo", + "restore_user": "Restaurar usuario", + "restored_asset": "Activo restaurado", + "resume": "Reanudar", + "retry_upload": "Reintentar carga", + "review_duplicates": "Revisar duplicados", + "role": "Rol", + "role_editor": "Editor", + "role_viewer": "Visor", + "save": "Gardar", + "save_to_gallery": "Gardar na galería", + "saved_api_key": "Chave API gardada", + "saved_profile": "Perfil gardado", + "saved_settings": "ConfiguraciÃŗn gardada", + "say_something": "Dicir algo", + "scaffold_body_error_occurred": "Ocorreu un erro", + "scan_all_libraries": "Escanear Todas as Bibliotecas", + "scan_library": "Escanear", + "scan_settings": "ConfiguraciÃŗn de Escaneo", + "scanning_for_album": "Escaneando ÃĄlbum...", + "search": "Buscar", + "search_albums": "Buscar ÃĄlbums", + "search_by_context": "Buscar por contexto", + "search_by_description": "Buscar por descriciÃŗn", + "search_by_description_example": "Día de sendeirismo en Sapa", + "search_by_filename": "Buscar por nome de ficheiro ou extensiÃŗn", + "search_by_filename_example": "p. ex. IMG_1234.JPG ou PNG", + "search_camera_make": "Buscar marca de cÃĄmara...", + "search_camera_model": "Buscar modelo de cÃĄmara...", + "search_city": "Buscar cidade...", + "search_country": "Buscar país...", + "search_filter_apply": "Aplicar filtro", + "search_filter_camera_title": "Seleccionar tipo de cÃĄmara", + "search_filter_date": "Data", + "search_filter_date_interval": "{start} a {end}", + "search_filter_date_title": "Seleccionar un rango de datas", + "search_filter_display_option_not_in_album": "Non nun ÃĄlbum", + "search_filter_display_options": "OpciÃŗns de VisualizaciÃŗn", + "search_filter_filename": "Buscar por nome de ficheiro", + "search_filter_location": "UbicaciÃŗn", + "search_filter_location_title": "Seleccionar ubicaciÃŗn", + "search_filter_media_type": "Tipo de Medio", + "search_filter_media_type_title": "Seleccionar tipo de medio", + "search_filter_people_title": "Seleccionar persoas", + "search_for": "Buscar por", + "search_for_existing_person": "Buscar persoa existente", + "search_no_more_result": "Non hai mÃĄis resultados", + "search_no_people": "Sen persoas", + "search_no_people_named": "Sen persoas chamadas \"{name}\"", + "search_no_result": "Non se atoparon resultados, probe cun termo de busca ou combinaciÃŗn diferente", + "search_options": "OpciÃŗns de busca", + "search_page_categories": "Categorías", + "search_page_motion_photos": "Fotos en Movemento", + "search_page_no_objects": "Non hai InformaciÃŗn de Obxectos DispoÃąible", + "search_page_no_places": "Non hai InformaciÃŗn de Lugares DispoÃąible", + "search_page_screenshots": "Capturas de pantalla", + "search_page_search_photos_videos": "Busca as tÃēas fotos e vídeos", "search_page_selfies": "Selfies", - "search_page_things": "Things", - "search_page_view_all_button": "View all", - "search_page_your_activity": "Your activity", - "search_page_your_map": "Your Map", - "search_result_page_new_search_hint": "New Search", - "search_suggestion_list_smart_search_hint_1": "Smart search is enabled by default, to search for metadata use the syntax ", - "search_suggestion_list_smart_search_hint_2": "m:your-search-term", - "select_user_for_sharing_page_err_album": "Failed to create album", - "server_endpoint": "Server Endpoint", - "server_info_box_app_version": "App Version", - "server_info_box_server_url": "Server URL", - "setting_image_viewer_help": "The detail viewer loads the small thumbnail first, then loads the medium-size preview (if enabled), finally loads the original (if enabled).", - "setting_image_viewer_original_subtitle": "Enable to load the original full-resolution image (large!). Disable to reduce data usage (both network and on device cache).", - "setting_image_viewer_original_title": "Load original image", - "setting_image_viewer_preview_subtitle": "Enable to load a medium-resolution image. Disable to either directly load the original or only use the thumbnail.", - "setting_image_viewer_preview_title": "Load preview image", - "setting_image_viewer_title": "Images", - "setting_languages_apply": "Apply", - "setting_languages_subtitle": "Change the app's language", - "setting_languages_title": "Languages", - "setting_notifications_notify_failures_grace_period": "Notify background backup failures: {}", - "setting_notifications_notify_hours": "{} hours", - "setting_notifications_notify_immediately": "immediately", - "setting_notifications_notify_minutes": "{} minutes", - "setting_notifications_notify_never": "never", - "setting_notifications_notify_seconds": "{} seconds", - "setting_notifications_single_progress_subtitle": "Detailed upload progress information per asset", - "setting_notifications_single_progress_title": "Show background backup detail progress", - "setting_notifications_subtitle": "Adjust your notification preferences", - "setting_notifications_total_progress_subtitle": "Overall upload progress (done/total assets)", - "setting_notifications_total_progress_title": "Show background backup total progress", - "setting_video_viewer_looping_title": "Looping", - "setting_video_viewer_original_video_subtitle": "When streaming a video from the server, play the original even when a transcode is available. May lead to buffering. Videos available locally are played in original quality regardless of this setting.", - "setting_video_viewer_original_video_title": "Force original video", - "settings_require_restart": "Please restart Immich to apply this setting", - "share_add_photos": "Add photos", - "share_assets_selected": "{} selected", - "share_dialog_preparing": "Preparing...", - "shared_album_activities_input_disable": "Comment is disabled", - "shared_album_activity_remove_content": "Do you want to delete this activity?", - "shared_album_activity_remove_title": "Delete Activity", - "shared_album_section_people_action_error": "Error leaving/removing from album", - "shared_album_section_people_action_leave": "Remove user from album", - "shared_album_section_people_action_remove_user": "Remove user from album", - "shared_album_section_people_title": "PEOPLE", - "shared_intent_upload_button_progress_text": "{} / {} Uploaded", - "shared_link_app_bar_title": "Shared Links", - "shared_link_clipboard_copied_massage": "Copied to clipboard", - "shared_link_clipboard_text": "Link: {}\nPassword: {}", - "shared_link_create_error": "Error while creating shared link", - "shared_link_edit_description_hint": "Enter the share description", - "shared_link_edit_expire_after_option_day": "1 day", - "shared_link_edit_expire_after_option_days": "{} days", - "shared_link_edit_expire_after_option_hour": "1 hour", - "shared_link_edit_expire_after_option_hours": "{} hours", - "shared_link_edit_expire_after_option_minute": "1 minute", - "shared_link_edit_expire_after_option_minutes": "{} minutes", - "shared_link_edit_expire_after_option_months": "{} months", - "shared_link_edit_expire_after_option_year": "{} year", - "shared_link_edit_password_hint": "Enter the share password", - "shared_link_edit_submit_button": "Update link", - "shared_link_error_server_url_fetch": "Cannot fetch the server url", - "shared_link_expires_day": "Expires in {} day", - "shared_link_expires_days": "Expires in {} days", - "shared_link_expires_hour": "Expires in {} hour", - "shared_link_expires_hours": "Expires in {} hours", - "shared_link_expires_minute": "Expires in {} minute", - "shared_link_expires_minutes": "Expires in {} minutes", - "shared_link_expires_never": "Expires ∞", - "shared_link_expires_second": "Expires in {} second", - "shared_link_expires_seconds": "Expires in {} seconds", - "shared_link_individual_shared": "Individual shared", + "search_page_things": "Cousas", + "search_page_view_all_button": "Ver todo", + "search_page_your_activity": "A tÃēa actividade", + "search_page_your_map": "O teu Mapa", + "search_people": "Buscar persoas", + "search_places": "Buscar lugares", + "search_rating": "Buscar por clasificaciÃŗn...", + "search_result_page_new_search_hint": "Nova Busca", + "search_settings": "ConfiguraciÃŗn da busca", + "search_state": "Buscar estado...", + "search_suggestion_list_smart_search_hint_1": "A busca intelixente estÃĄ activada por defecto, para buscar metadatos use a sintaxe ", + "search_suggestion_list_smart_search_hint_2": "m:o-teu-termo-de-busca", + "search_tags": "Buscar etiquetas...", + "search_timezone": "Buscar fuso horario...", + "search_type": "Tipo de busca", + "search_your_photos": "Buscar as tÃēas fotos", + "searching_locales": "Buscando configuraciÃŗns rexionais...", + "second": "Segundo", + "see_all_people": "Ver todas as persoas", + "select": "Seleccionar", + "select_album_cover": "Seleccionar portada do ÃĄlbum", + "select_all": "Seleccionar todo", + "select_all_duplicates": "Seleccionar todos os duplicados", + "select_avatar_color": "Seleccionar cor do avatar", + "select_face": "Seleccionar cara", + "select_featured_photo": "Seleccionar foto destacada", + "select_from_computer": "Seleccionar do ordenador", + "select_keep_all": "Seleccionar conservar todo", + "select_library_owner": "Seleccionar propietario da biblioteca", + "select_new_face": "Seleccionar nova cara", + "select_photos": "Seleccionar fotos", + "select_trash_all": "Seleccionar mover todo ao lixo", + "select_user_for_sharing_page_err_album": "Erro ao crear o ÃĄlbum", + "selected": "Seleccionado", + "selected_count": "{count, plural, other {# seleccionados}}", + "send_message": "Enviar mensaxe", + "send_welcome_email": "Enviar correo electrÃŗnico de benvida", + "server_endpoint": "Punto Final do Servidor", + "server_info_box_app_version": "VersiÃŗn da AplicaciÃŗn", + "server_info_box_server_url": "URL do Servidor", + "server_offline": "Servidor FÃŗra de LiÃąa", + "server_online": "Servidor En LiÃąa", + "server_stats": "Estatísticas do Servidor", + "server_version": "VersiÃŗn do Servidor", + "set": "Establecer", + "set_as_album_cover": "Establecer como portada do ÃĄlbum", + "set_as_featured_photo": "Establecer como foto destacada", + "set_as_profile_picture": "Establecer como imaxe de perfil", + "set_date_of_birth": "Establecer data de nacemento", + "set_profile_picture": "Establecer imaxe de perfil", + "set_slideshow_to_fullscreen": "PoÃąer PresentaciÃŗn a pantalla completa", + "setting_image_viewer_help": "O visor de detalles carga primeiro a miniatura pequena, despois carga a vista previa de tamaÃąo medio (se estÃĄ activada), finalmente carga o orixinal (se estÃĄ activado).", + "setting_image_viewer_original_subtitle": "Activar para cargar a imaxe orixinal a resoluciÃŗn completa (grande!). Desactivar para reducir o uso de datos (tanto na rede como na cachÊ do dispositivo).", + "setting_image_viewer_original_title": "Cargar imaxe orixinal", + "setting_image_viewer_preview_subtitle": "Activar para cargar unha imaxe de resoluciÃŗn media. Desactivar para cargar directamente o orixinal ou usar sÃŗ a miniatura.", + "setting_image_viewer_preview_title": "Cargar imaxe de vista previa", + "setting_image_viewer_title": "Imaxes", + "setting_languages_apply": "Aplicar", + "setting_languages_subtitle": "Cambiar a lingua da aplicaciÃŗn", + "setting_languages_title": "Linguas", + "setting_notifications_notify_failures_grace_period": "Notificar fallos da copia de seguridade en segundo plano: {}", + "setting_notifications_notify_hours": "{} horas", + "setting_notifications_notify_immediately": "inmediatamente", + "setting_notifications_notify_minutes": "{} minutos", + "setting_notifications_notify_never": "nunca", + "setting_notifications_notify_seconds": "{} segundos", + "setting_notifications_single_progress_subtitle": "InformaciÃŗn detallada do progreso da carga por activo", + "setting_notifications_single_progress_title": "Mostrar progreso detallado da copia de seguridade en segundo plano", + "setting_notifications_subtitle": "Axustar as tÃēas preferencias de notificaciÃŗn", + "setting_notifications_total_progress_subtitle": "Progreso xeral da carga (feitos/total activos)", + "setting_notifications_total_progress_title": "Mostrar progreso total da copia de seguridade en segundo plano", + "setting_video_viewer_looping_title": "Bucle", + "setting_video_viewer_original_video_subtitle": "Ao transmitir un vídeo desde o servidor, reproducir o orixinal aínda que haxa unha transcodificaciÃŗn dispoÃąible. Pode provocar buffering. Os vídeos dispoÃąibles localmente reprÃŗdÃēcense en calidade orixinal independentemente desta configuraciÃŗn.", + "setting_video_viewer_original_video_title": "Forzar vídeo orixinal", + "settings": "ConfiguraciÃŗn", + "settings_require_restart": "Por favor, reinicie Immich para aplicar esta configuraciÃŗn", + "settings_saved": "ConfiguraciÃŗn gardada", + "share": "Compartir", + "share_add_photos": "Engadir fotos", + "share_assets_selected": "{} seleccionados", + "share_dialog_preparing": "Preparando...", + "shared": "Compartido", + "shared_album_activities_input_disable": "O comentario estÃĄ desactivado", + "shared_album_activity_remove_content": "Queres eliminar esta actividade?", + "shared_album_activity_remove_title": "Eliminar Actividade", + "shared_album_section_people_action_error": "Erro ao saír/eliminar do ÃĄlbum", + "shared_album_section_people_action_leave": "Eliminar usuario do ÃĄlbum", + "shared_album_section_people_action_remove_user": "Eliminar usuario do ÃĄlbum", + "shared_album_section_people_title": "PERSOAS", + "shared_by": "Compartido por", + "shared_by_user": "Compartido por {user}", + "shared_by_you": "Compartido por ti", + "shared_from_partner": "Fotos de {partner}", + "shared_intent_upload_button_progress_text": "{} / {} Subidos", + "shared_link_app_bar_title": "LigazÃŗns Compartidas", + "shared_link_clipboard_copied_massage": "Copiado ao portapapeis", + "shared_link_clipboard_text": "LigazÃŗn: {}\nContrasinal: {}", + "shared_link_create_error": "Erro ao crear ligazÃŗn compartida", + "shared_link_edit_description_hint": "Introduza a descriciÃŗn da comparticiÃŗn", + "shared_link_edit_expire_after_option_day": "1 día", + "shared_link_edit_expire_after_option_days": "{} días", + "shared_link_edit_expire_after_option_hour": "1 hora", + "shared_link_edit_expire_after_option_hours": "{} horas", + "shared_link_edit_expire_after_option_minute": "1 minuto", + "shared_link_edit_expire_after_option_minutes": "{} minutos", + "shared_link_edit_expire_after_option_months": "{} meses", + "shared_link_edit_expire_after_option_year": "{} ano", + "shared_link_edit_password_hint": "Introduza o contrasinal da comparticiÃŗn", + "shared_link_edit_submit_button": "Actualizar ligazÃŗn", + "shared_link_error_server_url_fetch": "Non se pode obter a url do servidor", + "shared_link_expires_day": "Caduca en {} día", + "shared_link_expires_days": "Caduca en {} días", + "shared_link_expires_hour": "Caduca en {} hora", + "shared_link_expires_hours": "Caduca en {} horas", + "shared_link_expires_minute": "Caduca en {} minuto", + "shared_link_expires_minutes": "Caduca en {} minutos", + "shared_link_expires_never": "Caduca ∞", + "shared_link_expires_second": "Caduca en {} segundo", + "shared_link_expires_seconds": "Caduca en {} segundos", + "shared_link_individual_shared": "Compartido individualmente", "shared_link_info_chip_metadata": "EXIF", - "shared_link_manage_links": "Manage Shared links", - "shared_links": "Shared links", - "shared_with_me": "Shared with me", - "sharing_page_album": "Shared albums", - "sharing_page_description": "Create shared albums to share photos and videos with people in your network.", - "sharing_page_empty_list": "EMPTY LIST", - "sharing_silver_appbar_create_shared_album": "New shared album", - "sharing_silver_appbar_share_partner": "Share with partner", - "start_date": "Start date", - "sync": "Sync", - "sync_albums": "Sync albums", - "sync_albums_manual_subtitle": "Sync all uploaded videos and photos to the selected backup albums", - "sync_upload_album_setting_subtitle": "Create and upload your photos and videos to the selected albums on Immich", - "theme_setting_asset_list_storage_indicator_title": "Show storage indicator on asset tiles", - "theme_setting_asset_list_tiles_per_row_title": "Number of assets per row ({})", - "theme_setting_colorful_interface_subtitle": "Apply primary color to background surfaces.", - "theme_setting_colorful_interface_title": "Colorful interface", - "theme_setting_image_viewer_quality_subtitle": "Adjust the quality of the detail image viewer", - "theme_setting_image_viewer_quality_title": "Image viewer quality", - "theme_setting_primary_color_subtitle": "Pick a color for primary actions and accents.", - "theme_setting_primary_color_title": "Primary color", - "theme_setting_system_primary_color_title": "Use system color", - "theme_setting_system_theme_switch": "Automatic (Follow system setting)", - "theme_setting_theme_subtitle": "Choose the app's theme setting", - "theme_setting_three_stage_loading_subtitle": "Three-stage loading might increase the loading performance but causes significantly higher network load", - "theme_setting_three_stage_loading_title": "Enable three-stage loading", - "trash": "Trash", - "trash_emptied": "Emptied trash", - "trash_page_delete_all": "Delete All", - "trash_page_empty_trash_dialog_content": "Do you want to empty your trashed assets? These items will be permanently removed from Immich", - "trash_page_info": "Trashed items will be permanently deleted after {} days", - "trash_page_no_assets": "No trashed assets", - "trash_page_restore_all": "Restore All", - "trash_page_select_assets_btn": "Select assets", - "trash_page_title": "Trash ({})", - "upload": "Upload", - "upload_dialog_info": "Do you want to backup the selected Asset(s) to the server?", - "upload_dialog_title": "Upload Asset", - "upload_to_immich": "Upload to Immich ({})", - "uploading": "Uploading", - "use_current_connection": "use current connection", - "validate_endpoint_error": "Please enter a valid URL", - "version_announcement_overlay_release_notes": "release notes", - "version_announcement_overlay_text_1": "Hi friend, there is a new release of", - "version_announcement_overlay_text_2": "please take your time to visit the ", - "version_announcement_overlay_text_3": " and ensure your docker-compose and .env setup is up-to-date to prevent any misconfigurations, especially if you use WatchTower or any mechanism that handles updating your server application automatically.", - "version_announcement_overlay_title": "New Server Version Available 🎉", - "videos": "Videos", - "viewer_remove_from_stack": "Remove from Stack", - "viewer_stack_use_as_main_asset": "Use as Main Asset", - "viewer_unstack": "Un-Stack", - "wifi_name": "WiFi Name", + "shared_link_manage_links": "Xestionar ligazÃŗns Compartidas", + "shared_link_options": "OpciÃŗns da ligazÃŗn compartida", + "shared_links": "LigazÃŗns compartidas", + "shared_links_description": "Compartir fotos e vídeos cunha ligazÃŗn", + "shared_photos_and_videos_count": "{assetCount, plural, other {# fotos e vídeos compartidos.}}", + "shared_with_me": "Compartido comigo", + "shared_with_partner": "Compartido con {partner}", + "sharing": "Compartir", + "sharing_enter_password": "Por favor, introduza o contrasinal para ver esta pÃĄxina.", + "sharing_page_album": "Álbums compartidos", + "sharing_page_description": "Crea ÃĄlbums compartidos para compartir fotos e vídeos con persoas na tÃēa rede.", + "sharing_page_empty_list": "LISTA BALEIRA", + "sharing_sidebar_description": "Mostrar unha ligazÃŗn a Compartir na barra lateral", + "sharing_silver_appbar_create_shared_album": "Novo ÃĄlbum compartido", + "sharing_silver_appbar_share_partner": "Compartir con compaÃąeiro/a", + "shift_to_permanent_delete": "prema ⇧ para eliminar permanentemente o activo", + "show_album_options": "Mostrar opciÃŗns do ÃĄlbum", + "show_albums": "Mostrar ÃĄlbums", + "show_all_people": "Mostrar todas as persoas", + "show_and_hide_people": "Mostrar e ocultar persoas", + "show_file_location": "Mostrar ubicaciÃŗn do ficheiro", + "show_gallery": "Mostrar galería", + "show_hidden_people": "Mostrar persoas ocultas", + "show_in_timeline": "Mostrar na liÃąa de tempo", + "show_in_timeline_setting_description": "Mostrar fotos e vídeos deste usuario na tÃēa liÃąa de tempo", + "show_keyboard_shortcuts": "Mostrar atallos de teclado", + "show_metadata": "Mostrar metadatos", + "show_or_hide_info": "Mostrar ou ocultar informaciÃŗn", + "show_password": "Mostrar contrasinal", + "show_person_options": "Mostrar opciÃŗns da persoa", + "show_progress_bar": "Mostrar Barra de Progreso", + "show_search_options": "Mostrar opciÃŗns de busca", + "show_shared_links": "Mostrar ligazÃŗns compartidas", + "show_slideshow_transition": "Mostrar transiciÃŗn da presentaciÃŗn", + "show_supporter_badge": "Insignia de seguidor/a", + "show_supporter_badge_description": "Mostrar unha insignia de seguidor/a", + "shuffle": "Aleatorio", + "sidebar": "Barra lateral", + "sidebar_display_description": "Mostrar unha ligazÃŗn ÃĄ vista na barra lateral", + "sign_out": "Pechar SesiÃŗn", + "sign_up": "Rexistrarse", + "size": "TamaÃąo", + "skip_to_content": "Saltar ao contido", + "skip_to_folders": "Saltar a cartafoles", + "skip_to_tags": "Saltar a etiquetas", + "slideshow": "PresentaciÃŗn", + "slideshow_settings": "ConfiguraciÃŗn da presentaciÃŗn", + "sort_albums_by": "Ordenar ÃĄlbums por...", + "sort_created": "Data de creaciÃŗn", + "sort_items": "NÃēmero de elementos", + "sort_modified": "Data de modificaciÃŗn", + "sort_oldest": "Foto mÃĄis antiga", + "sort_people_by_similarity": "Ordenar persoas por similitude", + "sort_recent": "Foto mÃĄis recente", + "sort_title": "Título", + "source": "Fonte", + "stack": "Apilar", + "stack_duplicates": "Apilar duplicados", + "stack_select_one_photo": "Seleccionar unha foto principal para a pila", + "stack_selected_photos": "Apilar fotos seleccionadas", + "stacked_assets_count": "Apilados {count, plural, one {# activo} other {# activos}}", + "stacktrace": "Rastro da Pila", + "start": "Iniciar", + "start_date": "Data de inicio", + "state": "Estado", + "status": "Estado", + "stop_motion_photo": "Deter Foto en Movemento", + "stop_photo_sharing": "Deixar de compartir as tÃēas fotos?", + "stop_photo_sharing_description": "{partner} xa non poderÃĄ acceder ÃĄs tÃēas fotos.", + "stop_sharing_photos_with_user": "Deixar de compartir as tÃēas fotos con este usuario", + "storage": "Espazo de almacenamento", + "storage_label": "Etiqueta de almacenamento", + "storage_usage": "{used} de {available} usado", + "submit": "Enviar", + "suggestions": "SuxestiÃŗns", + "sunrise_on_the_beach": "Amencer na praia", + "support": "Soporte", + "support_and_feedback": "Soporte e Comentarios", + "support_third_party_description": "A tÃēa instalaciÃŗn de Immich foi empaquetada por un terceiro. Os problemas que experimente poden ser causados por ese paquete, así que por favor, comunica os problemas con eles en primeira instancia usando as ligazÃŗns a continuaciÃŗn.", + "swap_merge_direction": "Intercambiar direcciÃŗn de fusiÃŗn", + "sync": "Sincronizar", + "sync_albums": "Sincronizar ÃĄlbums", + "sync_albums_manual_subtitle": "Sincronizar todos os vídeos e fotos cargados aos ÃĄlbums de copia de seguridade seleccionados", + "sync_upload_album_setting_subtitle": "Crear e suba as tÃēas fotos e vídeos aos ÃĄlbums seleccionados en Immich", + "tag": "Etiqueta", + "tag_assets": "Etiquetar activos", + "tag_created": "Etiqueta creada: {tag}", + "tag_feature_description": "Navegar por fotos e vídeos agrupados por temas de etiquetas lÃŗxicas", + "tag_not_found_question": "Non atopa unha etiqueta? Crear unha nova etiqueta.", + "tag_people": "Etiquetar Persoas", + "tag_updated": "Etiqueta actualizada: {tag}", + "tagged_assets": "Etiquetados {count, plural, one {# activo} other {# activos}}", + "tags": "Etiquetas", + "template": "Modelo", + "theme": "Tema", + "theme_selection": "SelecciÃŗn de tema", + "theme_selection_description": "Establecer automaticamente o tema a claro ou escuro baseÃĄndose na preferencia do sistema do teu navegador", + "theme_setting_asset_list_storage_indicator_title": "Mostrar indicador de almacenamento nas tellas de activos", + "theme_setting_asset_list_tiles_per_row_title": "NÃēmero de activos por fila ({})", + "theme_setting_colorful_interface_subtitle": "Aplicar cor primaria ÃĄs superficies de fondo.", + "theme_setting_colorful_interface_title": "Interface colorida", + "theme_setting_image_viewer_quality_subtitle": "Axustar a calidade do visor de imaxes de detalle", + "theme_setting_image_viewer_quality_title": "Calidade do visor de imaxes", + "theme_setting_primary_color_subtitle": "Elixa unha cor para acciÃŗns primarias e acentos.", + "theme_setting_primary_color_title": "Cor primaria", + "theme_setting_system_primary_color_title": "Usar cor do sistema", + "theme_setting_system_theme_switch": "AutomÃĄtico (Seguir configuraciÃŗn do sistema)", + "theme_setting_theme_subtitle": "Elixir a configuraciÃŗn do tema da aplicaciÃŗn", + "theme_setting_three_stage_loading_subtitle": "A carga en tres etapas pode aumentar o rendemento da carga pero causa unha carga de rede significativamente maior", + "theme_setting_three_stage_loading_title": "Activar carga en tres etapas", + "they_will_be_merged_together": "Fusionaranse xuntos", + "third_party_resources": "Recursos de Terceiros", + "time_based_memories": "Recordos baseados no tempo", + "timeline": "LiÃąa de tempo", + "timezone": "Fuso horario", + "to_archive": "Arquivar", + "to_change_password": "Cambiar contrasinal", + "to_favorite": "Favorito", + "to_login": "Iniciar sesiÃŗn", + "to_parent": "Ir ao pai", + "to_trash": "Lixo", + "toggle_settings": "Alternar configuraciÃŗn", + "toggle_theme": "Alternar tema escuro", + "total": "Total", + "total_usage": "Uso total", + "trash": "Lixo", + "trash_all": "Mover Todo ao Lixo", + "trash_count": "Lixo {count, number}", + "trash_delete_asset": "Mover ao Lixo/Eliminar Activo", + "trash_emptied": "Lixo baleirado", + "trash_no_results_message": "As fotos e vídeos movidos ao lixo aparecerÃĄn aquí.", + "trash_page_delete_all": "Eliminar Todo", + "trash_page_empty_trash_dialog_content": "Queres baleirar os teus activos no lixo? Estes elementos eliminaranse permanentemente de Immich", + "trash_page_info": "Os elementos no lixo eliminaranse permanentemente despois de {} días", + "trash_page_no_assets": "Non hai activos no lixo", + "trash_page_restore_all": "Restaurar Todo", + "trash_page_select_assets_btn": "Seleccionar activos", + "trash_page_title": "Lixo ({})", + "trashed_items_will_be_permanently_deleted_after": "Os elementos no lixo eliminaranse permanentemente despois de {days, plural, one {# día} other {# días}}.", + "type": "Tipo", + "unarchive": "Desarquivar", + "unarchived_count": "{count, plural, other {Desarquivados #}}", + "unfavorite": "Desmarcar como favorito", + "unhide_person": "Mostrar persoa", + "unknown": "DescoÃąecido", + "unknown_country": "País DescoÃąecido", + "unknown_year": "Ano DescoÃąecido", + "unlimited": "Ilimitado", + "unlink_motion_video": "Desvincular vídeo en movemento", + "unlink_oauth": "Desvincular OAuth", + "unlinked_oauth_account": "Conta OAuth desvinculada", + "unmute_memories": "Desilenciar Recordos", + "unnamed_album": "Álbum Sen Nome", + "unnamed_album_delete_confirmation": "EstÃĄs seguro de que queres eliminar este ÃĄlbum?", + "unnamed_share": "Compartir Sen Nome", + "unsaved_change": "Cambio sen gardar", + "unselect_all": "Deseleccionar todo", + "unselect_all_duplicates": "Deseleccionar todos os duplicados", + "unstack": "Desapilar", + "unstacked_assets_count": "Desapilados {count, plural, one {# activo} other {# activos}}", + "untracked_files": "Ficheiros non rastrexados", + "untracked_files_decription": "Estes ficheiros non son rastrexados pola aplicaciÃŗn. Poden ser o resultado de movementos fallidos, cargas interrompidas ou deixados atrÃĄs debido a un erro", + "up_next": "A continuaciÃŗn", + "updated_password": "Contrasinal actualizado", + "upload": "Subir", + "upload_concurrency": "Concorrencia de subida", + "upload_dialog_info": "Queres facer copia de seguridade do(s) Activo(s) seleccionado(s) no servidor?", + "upload_dialog_title": "Subir Activo", + "upload_errors": "Subida completada con {count, plural, one {# erro} other {# erros}}, actualice a pÃĄxina para ver os novos activos subidos.", + "upload_progress": "Restantes {remaining, number} - Procesados {processed, number}/{total, number}", + "upload_skipped_duplicates": "Omitidos {count, plural, one {# activo duplicado} other {# activos duplicados}}", + "upload_status_duplicates": "Duplicados", + "upload_status_errors": "Erros", + "upload_status_uploaded": "Subido", + "upload_success": "Subida exitosa, actualice a pÃĄxina para ver os novos activos subidos.", + "upload_to_immich": "Subir a Immich ({})", + "uploading": "Subindo", + "url": "URL", + "usage": "Uso", + "use_current_connection": "usar conexiÃŗn actual", + "use_custom_date_range": "Usar rango de datas personalizado no seu lugar", + "user": "Usuario", + "user_id": "ID de Usuario", + "user_liked": "A {user} gustoulle {type, select, photo {esta foto} video {este vídeo} asset {este activo} other {isto}}", + "user_purchase_settings": "Compra", + "user_purchase_settings_description": "Xestionar a tÃēa compra", + "user_role_set": "Establecer {user} como {role}", + "user_usage_detail": "Detalle de uso do usuario", + "user_usage_stats": "Estatísticas de uso da conta", + "user_usage_stats_description": "Ver estatísticas de uso da conta", + "username": "Nome de usuario", + "users": "Usuarios", + "utilities": "Utilidades", + "validate": "Validar", + "validate_endpoint_error": "Por favor, introduza unha URL vÃĄlida", + "variables": "Variables", + "version": "VersiÃŗn", + "version_announcement_closing": "O seu amigo, Alex", + "version_announcement_message": "Ola! Unha nova versiÃŗn de Immich estÃĄ dispoÃąible. Por favor, toma un tempo para ler as notas de lanzamento para asegurarse de que a tÃēa configuraciÃŗn estÃĄ actualizada para evitar calquera configuraciÃŗn incorrecta, especialmente se usas WatchTower ou calquera mecanismo que xestione a actualizaciÃŗn automÃĄtica da tÃēa instancia de Immich.", + "version_announcement_overlay_release_notes": "notas de lanzamento", + "version_announcement_overlay_text_1": "Ola amigo/a, hai unha nova versiÃŗn de", + "version_announcement_overlay_text_2": "por favor, toma o teu tempo para visitar as ", + "version_announcement_overlay_text_3": " e asegÃērate de que a tÃēa configuraciÃŗn de docker-compose e .env estÃĄ actualizada para evitar calquera configuraciÃŗn incorrecta, especialmente se usa WatchTower ou calquera mecanismo que xestione a actualizaciÃŗn automÃĄtica da tÃēa aplicaciÃŗn de servidor.", + "version_announcement_overlay_title": "Nova VersiÃŗn do Servidor DispoÃąible 🎉", + "version_history": "Historial de VersiÃŗns", + "version_history_item": "Instalado {version} o {date}", + "video": "Vídeo", + "video_hover_setting": "Reproducir miniatura do vídeo ao pasar o rato por riba", + "video_hover_setting_description": "Reproducir miniatura do vídeo cando o rato estÃĄ sobre o elemento. Mesmo cando estÃĄ desactivado, a reproduciÃŗn pode iniciarse pasando o rato sobre a icona de reproduciÃŗn.", + "videos": "Vídeos", + "videos_count": "{count, plural, one {# Vídeo} other {# Vídeos}}", + "view": "Ver", + "view_album": "Ver Álbum", + "view_all": "Ver Todo", + "view_all_users": "Ver todos os usuarios", + "view_in_timeline": "Ver na liÃąa de tempo", + "view_link": "Ver ligazÃŗn", + "view_links": "Ver ligazÃŗns", + "view_name": "Vista", + "view_next_asset": "Ver seguinte activo", + "view_previous_asset": "Ver activo anterior", + "view_qr_code": "Ver cÃŗdigo QR", + "view_stack": "Ver Pila", + "viewer_remove_from_stack": "Eliminar da Pila", + "viewer_stack_use_as_main_asset": "Usar como Activo Principal", + "viewer_unstack": "Desapilar", + "visibility_changed": "Visibilidade cambiada para {count, plural, one {# persoa} other {# persoas}}", + "waiting": "Agardando", + "warning": "Aviso", + "week": "Semana", + "welcome": "Benvido/a", + "welcome_to_immich": "Benvido/a a Immich", + "wifi_name": "Nome da WiFi", "year": "Ano", + "years_ago": "Hai {years, plural, one {# ano} other {# anos}}", "yes": "Si", - "your_wifi_name": "Your WiFi name", - "zoom_image": "Acercar imaxe" + "you_dont_have_any_shared_links": "Non tes ningunha ligazÃŗn compartida", + "your_wifi_name": "O nome da tÃēa WiFi", + "zoom_image": "Ampliar Imaxe" } diff --git a/i18n/he.json b/i18n/he.json index 6a743ad6f7..927a43f020 100644 --- a/i18n/he.json +++ b/i18n/he.json @@ -33,7 +33,7 @@ "added_to_favorites_count": "{count, number} נוספו למו×ĸדפים", "admin": { "add_exclusion_pattern_description": "הוספ×Ē ×“×¤×•×Ą×™ החרגה. × ×Ēמכ×Ē ×”×Ēאמ×Ē ×“×¤×•×Ą×™× באמ×Ļ×ĸו×Ē *, ** ו-?. כדי לה×Ē×ĸלם מכל הקב×Ļים ב×Ēיקיה כלשהי בשם \"Raw\", יש להש×Ēמ׊ ב \"**/Raw/**\". כדי לה×Ē×ĸלם מכל הקב×Ļים המס×Ēיימים ב \"tif.\", יש להש×Ēמ׊ ב \"tif.*/**\". כדי לה×Ē×ĸלם מנ×Ēיב מוחלט, יש להש×Ēמ׊ ב \"**/× ×Ēיב/לה×Ē×ĸלמו×Ē\".", - "asset_offline_description": "נכס ספרייה חי×Ļוני×Ē ×–×” לא נמ×Ļא יו×Ēר בדיסק והו×ĸבר לאשפה. אם הקוב×Ĩ הו×ĸבר מ×Ēוך הספרייה, נא לבדוק א×Ē ×Ļיר הזמן שלך ×ĸבור הנכס המקביל החדש. כדי לשחזר נכס זה, נא לוודא ׊-Immich יכול לגש×Ē ××œ × ×Ēיב הקוב×Ĩ למטה ולסרוק מחדש א×Ē ×”×Ą×¤×¨×™×™×”.", + "asset_offline_description": "×Ēמונה מספרייה חי×Ļוני×Ē ×–×• לא נמ×Ļא×Ē ×™×•×Ēר בדיסק והו×ĸברה לאשפה. אם הקוב×Ĩ הו×ĸבר מ×Ēוך הספרייה, נא לבדוק א×Ē ×Ļיר הזמן שלך ×ĸבור ה×Ēמונה המקבילה החדש. כדי לשחזר ×Ēמונה זו, נא לוודא ׊-Immich יכול לגש×Ē ××œ × ×Ēיב הקוב×Ĩ למטה ולסרוק מחדש א×Ē ×”×Ą×¤×¨×™×™×”.", "authentication_settings": "הגדרו×Ē ×”×Ēחברו×Ē", "authentication_settings_description": "ניהול סיסמה, OAuth, והגדרו×Ē ×”×Ēחברו×Ē ××—×¨×•×Ē", "authentication_settings_disable_all": "האם בר×Ļונך להשבי×Ē ××Ē ×›×œ שיטו×Ē ×”×”×Ēחברו×Ē? כניסה למ×ĸרכ×Ē ×Ēהיה מושב×Ē×Ē ×œ×—×œ×•×˜×™×Ÿ.", @@ -49,7 +49,7 @@ "cleared_jobs": "נוקו משימו×Ē ×ĸבור: {job}", "config_set_by_file": "ה×Ē×Ļורה מוגדר×Ē ×›×ĸ×Ē ×ĸל ידי קוב×Ĩ ×Ē×Ļורה", "confirm_delete_library": "האם באמ×Ē ×‘×¨×Ļונך למחוק א×Ē ×”×Ą×¤×¨×™×™×” {library}?", - "confirm_delete_library_assets": "האם באמ×Ē ×‘×¨×Ļונך למחוק א×Ē ×”×Ą×¤×¨×™×™×” הזו? זה ימחק א×Ē {count, plural, one {נכס # המוכל} other {כל # הנכסים המוכלים}} בה מ-Immich ואינו ני×Ēן לביטול. קב×Ļים יישארו בדיסק.", + "confirm_delete_library_assets": "האם באמ×Ē ×‘×¨×Ļונך למחוק א×Ē ×”×Ą×¤×¨×™×™×” הזו? זה ימחק א×Ē {count, plural, one {×Ēמונה # המוכל×Ē} other {כל # ×Ēמונו×Ē ×”×ž×•×›×œ×™×}} בה מ-Immich ואינו ני×Ēן לביטול. קב×Ļים יישארו בדיסק.", "confirm_email_below": "כדי לאשר, יש להקליד \"{email}\" למטה", "confirm_reprocess_all_faces": "האם באמ×Ē ×‘×¨×Ļונך ל×ĸבד מחדש א×Ē ×›×œ הפנים? זה גם ינקה אנשים ב×ĸלי ׊ם.", "confirm_user_password_reset": "האם באמ×Ē ×‘×¨×Ļונך לאפס א×Ē ×”×Ą×™×Ą×ž×” של המש×Ēמ׊ {user}?", @@ -58,15 +58,15 @@ "cron_expression_description": "הגדר א×Ē ×ž×¨×•×•×— הסריקה באמ×Ļ×ĸו×Ē ×Ēבני×Ē ×”- cron. למיד×ĸ × ×•×Ą×Ŗ נא לפנו×Ē ×œ×ž×Š×œ אל Crontab Guru", "cron_expression_presets": "הגדרו×Ē ×§×‘×•×ĸו×Ē ×ž×¨××Š של ביטוי cron", "disable_login": "השב×Ē ×›× ×™×Ą×”", - "duplicate_detection_job_description": "הפ×ĸל למיד×Ē ×ž×›×•× ×” ×ĸל נכסים כדי לזהו×Ē ×Ēמונו×Ē ×“×•×ž×•×Ē. נ׊×ĸן ×ĸל חיפוש חכם", + "duplicate_detection_job_description": "הפ×ĸל למיד×Ē ×ž×›×•× ×” ×ĸל ×Ēמונו×Ē ×›×“×™ לזהו×Ē ×Ēמונו×Ē ×“×•×ž×•×Ē. נ׊×ĸן ×ĸל חיפוש חכם", "exclusion_pattern_description": "דפוסי החרגה מאפשרים לך לה×Ē×ĸלם מקב×Ļים ומ×Ēיקיו×Ē ×‘×ĸ×Ē ×Ą×¨×™×§×Ē ×”×Ą×¤×¨×™×™×” שלך. זה שימושי אם יש לך ×Ēיקיו×Ē ×”×ž×›×™×œ×•×Ē ×§×‘×Ļים שאינך רו×Ļה לייבא, כגון קוב×Ļי RAW.", "external_library_created_at": "ספרייה חי×Ļוני×Ē (נו×Ļרה ב-{date})", "external_library_management": "ניהול ספרייה חי×Ļוני×Ē", "face_detection": "אי×Ēור פנים", - "face_detection_description": "א×Ēר א×Ē ×”×¤× ×™× בנכסים באמ×Ļ×ĸו×Ē ×œ×ž×™×“×Ē ×ž×›×•× ×”. ×ĸבור סרטונים, רק ה×Ēמונה הממוז×ĸר×Ē × ×œ×§×—×Ē ×‘×—×Š×‘×•×Ÿ. \"ר×ĸנון\" מ×ĸבד (מחדש) א×Ē ×›×œ הנכסים. \"איפוס\" מנקה ×‘× ×•×Ą×Ŗ א×Ē ×›×œ × ×Ēוני הפנים הנוכחיים. \"חסרים\" ×ž×•×Ą×™×Ŗ ל×Ēור נכסים שלא ×ĸובדו ×ĸדיין. לאחר שאי×Ēור הפנים הושלם, פנים שאו×Ēרו י×ĸמדו ב×Ēור לזיהוי פנים המשייך או×Ēן לאנשים קיימים או חדשים.", + "face_detection_description": "א×Ēר א×Ē ×”×¤× ×™× ב×Ēמונו×Ē ×‘××ž×Ļ×ĸו×Ē ×œ×ž×™×“×Ē ×ž×›×•× ×”. ×ĸבור סרטונים, רק ה×Ēמונה הממוז×ĸר×Ē × ×œ×§×—×Ē ×‘×—×Š×‘×•×Ÿ. \"ר×ĸנון\" מ×ĸבד (מחדש) א×Ē ×›×œ ה×Ēמונו×Ē. \"איפוס\" מנקה ×‘× ×•×Ą×Ŗ א×Ē ×›×œ × ×Ēוני הפנים הנוכחיים. \"חסרים\" ×ž×•×Ą×™×Ŗ ל×Ēור ×Ēמונו×Ē ×Š×œ× ×ĸובדו ×ĸדיין. לאחר שאי×Ēור הפנים הושלם, פנים שאו×Ēרו י×ĸמדו ב×Ēור לזיהוי פנים המשייך או×Ēן לאנשים קיימים או חדשים.", "facial_recognition_job_description": "קב×Ĩ פנים שאו×Ēרו ל×Ēוך אנשים. שלב זה מור×Ĩ לאחר השלמ×Ē ××™×Ēור פנים. \"איפוס\" מקב×Ĩ (מחדש) א×Ē ×›×œ הפר×Ļופים. \"חסרים\" ×ž×•×Ą×™×Ŗ ל×Ēור פנים שלא הוק×Ļה להם אדם.", "failed_job_command": "הפקודה {command} נכשלה ×ĸבור המשימה: {job}", - "force_delete_user_warning": "אזהרה: פ×ĸולה זו ×Ēסיר מיד א×Ē ×”×ž×Š×Ēמ׊ וא×Ē ×›×œ הנכסים. לא ני×Ēן לבטל פ×ĸולה זו והקב×Ļים לא ני×Ēנים לשחזור.", + "force_delete_user_warning": "אזהרה: פ×ĸולה זו ×Ēסיר מיד א×Ē ×”×ž×Š×Ēמ׊ וא×Ē ×›×œ ה×Ēמונו×Ē. לא ני×Ēן לבטל פ×ĸולה זו והקב×Ļים לא ני×Ēנים לשחזור.", "forcing_refresh_library_files": "כפיי×Ē ×¨×ĸנון של כל קב×Ļי הספרייה", "image_format": "פורמט", "image_format_description": "WebP מפיק קב×Ļים קטנים יו×Ēר מ JPEG, אך הוא איטי יו×Ēר לקידוד.", @@ -79,7 +79,7 @@ "image_prefer_embedded_preview_setting_description": "הש×Ēמ׊ ב×Ē×Ļוגו×Ē ×ž×§×“×™×ž×•×Ē ×ž×•×˜×ž×ĸו×Ē ×‘×Ēמונו×Ē RAW כקלט ל×ĸיבוד ×Ēמונה וכאשר זמינו×Ē. זה יכול להפיק ×Ļב×ĸים מדויקים יו×Ēר ×ĸבור ×Ēמונו×Ē ×ž×Ą×•×™×ž×•×Ē, אבל האיכו×Ē ×Š×œ ה×Ē×Ļוגה המקדימה היא ×Ēלוי×Ē ×ž×Ļלמה ול×Ēמונה ×ĸשויים להיו×Ē ×™×•×Ēר פגמי דחיסה.", "image_prefer_wide_gamut": "ה×ĸדת סולם ×Ļב×ĸים רחב", "image_prefer_wide_gamut_setting_description": "הש×Ēמ׊ ב-Display P3 ל×Ēמונו×Ē ×ž×ž×•×–×ĸרו×Ē. זה מ׊מר טוב יו×Ēר א×Ē ×”×—×™×•× ×™×•×Ē ×Š×œ ×Ēמונו×Ē ×ĸם מרחבי ×Ļב×ĸ רחבים, אבל ×Ēמונו×Ē ×ĸשויו×Ē ×œ×”×•×¤×™×ĸ אחר×Ē ×‘×ž×›×Š×™×¨×™× ישנים ×ĸם גרס×Ē ×“×¤×“×¤×Ÿ ישנה. ×Ēמונו×Ē sRGB נשמרו×Ē ×›-sRGB כדי למנו×ĸ שינויי ×Ļב×ĸ.", - "image_preview_description": "×Ēמונה בגודל בינוני ×ĸם מטא-× ×Ēונים שהוסרו, מ׊מ׊×Ē ×‘×ĸ×Ē ×Ļפייה בנכס בודד ו×ĸבור למיד×Ē ×ž×›×•× ×”", + "image_preview_description": "×Ēמונה בגודל בינוני ×ĸם מטא-× ×Ēונים שהוסרו, מ׊מ׊×Ē ×‘×ĸ×Ē ×Ļפייה ב×Ēמונה בודד×Ē ×•×ĸבור למיד×Ē ×ž×›×•× ×”", "image_preview_quality_description": "איכו×Ē ×Ē×Ļוגה מקדימה מ-1 ×ĸד 100. איכו×Ē ×’×‘×•×”×” יו×Ēר היא טובה יו×Ēר, אבל מיי×Ļר×Ē ×§×‘×Ļים גדולים יו×Ēר ויכולה להפחי×Ē ××Ē ×Ēגוב×Ēיו×Ē ×”×™×™×Š×•×. הגדר×Ē ×ĸרך נמוך ×ĸשויה להשפי×ĸ ×ĸל איכו×Ē ×Ēו×Ļאו×Ē ×Š×œ למיד×Ē ×ž×›×•× ×”.", "image_preview_title": "הגדרו×Ē ×Ē×Ļוגה מקדימה", "image_quality": "איכו×Ē", @@ -106,7 +106,7 @@ "library_scanning_enable_description": "אפ׊ר סריק×Ē ×Ą×¤×¨×™×™×” ×Ēקופ×Ēי×Ē", "library_settings": "ספרייה חי×Ļוני×Ē", "library_settings_description": "ניהול הגדרו×Ē ×Ą×¤×¨×™×™×” חי×Ļוני×Ē", - "library_tasks_description": "סרוק ספריו×Ē ×—×™×Ļוניו×Ē ×ĸבור נכסים חדשים ו/או שהש×Ēנו", + "library_tasks_description": "סרוק ספריו×Ē ×—×™×Ļוניו×Ē ×ĸבור ×Ēמונו×Ē ×—×“×Š×•×Ē ×•/או שהש×Ēנו", "library_watching_enable_description": "×ĸקוב אחר שינויי קב×Ļים בספריו×Ē ×—×™×Ļוניו×Ē", "library_watching_settings": "×Ļפיי×Ē ×Ą×¤×¨×™×™×” (ניסיוני)", "library_watching_settings_description": "×ĸקוב אוטומטי×Ē ××—×¨ שינויי קב×Ļים", @@ -117,7 +117,7 @@ "machine_learning_clip_model_description": "שמו של מודל CLIP רשום כאן. שים לב ׊×ĸליך להפ×ĸיל מחדש א×Ē ×”×ž×Š×™×ž×” 'חיפוש חכם' ×ĸבור כל ה×Ēמונו×Ē ×‘×ĸ×Ē ×Š×™× ×•×™ מודל.", "machine_learning_duplicate_detection": "אי×Ēור כפילויו×Ē", "machine_learning_duplicate_detection_enabled": "אפ׊ר אי×Ēור כפילויו×Ē", - "machine_learning_duplicate_detection_enabled_description": "אם מושב×Ē, נכסים זהים בדיוק ×ĸדיין י×ĸברו ביטול כפילויו×Ē.", + "machine_learning_duplicate_detection_enabled_description": "אם מושב×Ē, ×Ēמונו×Ē ×–×”×•×Ē ×‘×“×™×•×§ ×ĸדיין י×ĸברו ביטול כפילויו×Ē.", "machine_learning_duplicate_detection_setting_description": "הש×Ēמ׊ בהטמ×ĸו×Ē ×Š×œ CLIP כדי למ×Ļוא כפילויו×Ē ××¤×Š×¨×™×•×Ē", "machine_learning_enabled": "אפ׊ר למיד×Ē ×ž×›×•× ×”", "machine_learning_enabled_description": "אם מושב×Ē, כל ×Ēכונו×Ē ×œ×ž×™×“×Ē ×ž×›×•× ×” יהיו מושב×Ēו×Ē ×œ×œ× ק׊ר להגדרו×Ē ×Š×œ×”×œ×Ÿ.", @@ -160,16 +160,16 @@ "memory_cleanup_job": "ניקוי זיכרון", "memory_generate_job": "י×Ļיר×Ē ×–×™×›×¨×•×Ÿ", "metadata_extraction_job": "חל×Ĩ מטא-× ×Ēונים", - "metadata_extraction_job_description": "חל×Ĩ מיד×ĸ מטא-× ×Ēונים מכל נכס, כגון GPS, פנים ורזולו×Ļיה", + "metadata_extraction_job_description": "חל×Ĩ מטא-× ×Ēונים מכל ×Ēמונה, כגון GPS, פנים ורזולו×Ļיה", "metadata_faces_import_setting": "אפ׊ר יבוא פנים", "metadata_faces_import_setting_description": "יבא פנים מנ×Ēוני EXIF של ×Ēמונה ומקב×Ļים נלווים", "metadata_settings": "הגדרו×Ē ×ž×˜×-× ×Ēונים", "metadata_settings_description": "ניהול הגדרו×Ē ×ž×˜×-× ×Ēונים", "migration_job": "ה×ĸברה", - "migration_job_description": "ה×ĸבר ×Ēמונו×Ē ×ž×ž×•×–×ĸרו×Ē ×Š×œ נכסים ופנים למבנה ה×Ēיקיו×Ē ×”×ĸדכני ביו×Ēר", + "migration_job_description": "ה×ĸבר ×Ēמונו×Ē ×ž×ž×•×–×ĸרו×Ē ×Š×œ ×Ēמונו×Ē ×•×¤× ×™× למבנה ה×Ēיקיו×Ē ×”×ĸדכני ביו×Ēר", "no_paths_added": "לא נוספו × ×Ēיבים", "no_pattern_added": "לא נוספה ×Ēבני×Ē", - "note_apply_storage_label_previous_assets": "ה×ĸרה: כדי להחיל א×Ē ×Ēווי×Ē ×”××—×Ą×•×Ÿ ×ĸל נכסים שהו×ĸלו ב×ĸבר, הפ×ĸל א×Ē", + "note_apply_storage_label_previous_assets": "ה×ĸרה: כדי להחיל א×Ē ×Ēווי×Ē ×”××—×Ą×•×Ÿ ×ĸל ×Ēמונו×Ē ×Š×”×•×ĸלו ב×ĸבר, הפ×ĸל א×Ē", "note_cannot_be_changed_later": "ה×ĸרה: אי אפ׊ר לשנו×Ē ×–××Ē ×ž××•×—×¨ יו×Ēר!", "notification_email_from_address": "מכ×Ēוב×Ē", "notification_email_from_address_description": "כ×Ēוב×Ē ×“×•×\"ל של השולח, לדוגמה: \"Immich ׊ר×Ē ×Ēמונו×Ē \"", @@ -243,21 +243,21 @@ "sidecar_job": "מטא-× ×Ēונים נלווים", "sidecar_job_description": "גלה או סנכרן מטא-× ×Ēונים נלווים ממ×ĸרכ×Ē ×”×§×‘×Ļים", "slideshow_duration_description": "מספר שניו×Ē ×œ×”×Ļג×Ē ×›×œ ×Ēמונה", - "smart_search_job_description": "הפ×ĸל למיד×Ē ×ž×›×•× ×” ×ĸל נכסים כדי ל×Ēמוך בחיפוש חכם", - "storage_template_date_time_description": "חו×Ēמ×Ē ×–×ž×Ÿ י×Ļיר×Ē ×”× ×›×Ą מ׊מ׊×Ē ×œ×ž×™×“×ĸ ×ĸל ה×Ēאריך והש×ĸה", + "smart_search_job_description": "הפ×ĸל למיד×Ē ×ž×›×•× ×” ×ĸל ×Ēמונו×Ē ×›×“×™ ל×Ēמוך בחיפוש חכם", + "storage_template_date_time_description": "חו×Ēמ×Ē ×–×ž×Ÿ י×Ļיר×Ē ×”×Ēמונה מ׊מ׊×Ē ×œ×ž×™×“×ĸ ×ĸל ה×Ēאריך והש×ĸה", "storage_template_date_time_sample": "זמן לדוגמא {date}", "storage_template_enable_description": "הפ×ĸל מנו×ĸ ×Ēבני×Ē ××—×Ą×•×Ÿ", "storage_template_hash_verification_enabled": "אימו×Ē ×’×™×‘×•×‘ מופ×ĸל", "storage_template_hash_verification_enabled_description": "מאפ׊ר אימו×Ē ×’×™×‘×•×‘, אין להשבי×Ē ×–××Ē ××œ× אם יש לך ודאו×Ē ×œ×’×‘×™ ההשלכו×Ē", "storage_template_migration": "ה×ĸבר×Ē ×Ēבני×Ē ××—×Ą×•×Ÿ", - "storage_template_migration_description": "החל א×Ē ×”{template} הנוכחי×Ē ×ĸל נכסים שהו×ĸלו ב×ĸבר", - "storage_template_migration_info": "×Ēבני×Ē ×”××—×Ą×•×Ÿ ×Ēמיר א×Ē ×›×œ ההרחבו×Ē ×œ××•×Ēיו×Ē ×§×˜× ×•×Ē. שינויים ב×Ēבני×Ē ×™×—×•×œ×• רק ×ĸל נכסים חדשים. כדי להחיל באופן רטרואקטיבי א×Ē ×”×Ēבני×Ē ×ĸל נכסים שהו×ĸלו ב×ĸבר, הפ×ĸל א×Ē {job}.", + "storage_template_migration_description": "החל א×Ē ×”{template} הנוכחי×Ē ×ĸל ×Ēמונו×Ē ×Š×”×•×ĸלו ב×ĸבר", + "storage_template_migration_info": "×Ēבני×Ē ×”××—×Ą×•×Ÿ ×Ēמיר א×Ē ×›×œ ההרחבו×Ē ×œ××•×Ēיו×Ē ×§×˜× ×•×Ē. שינויים ב×Ēבני×Ē ×™×—×•×œ×• רק ×ĸל ×Ēמונו×Ē ×—×“×Š×•×Ē. כדי להחיל באופן רטרואקטיבי א×Ē ×”×Ēבני×Ē ×ĸל ×Ēמונו×Ē ×Š×”×•×ĸלו ב×ĸבר, הפ×ĸל א×Ē {job}.", "storage_template_migration_job": "משימ×Ē ×”×ĸבר×Ē ×Ēבני×Ē ××—×Ą×•×Ÿ", "storage_template_more_details": "לפרטים נוספים אודו×Ē ×Ēכונה זו, ×ĸיין ב×Ēבני×Ē ×”××—×Ą×•×Ÿ ובהשלכו×Ēיה", "storage_template_onboarding_description": "כאשר מופ×ĸל×Ē, ×Ēכונה זו ×Ēארגן אוטומטי×Ē ×§×‘×Ļים בה×Ēבסס ×ĸל ×Ēבני×Ē ×Š×”×ž×Š×Ēמ׊ הגדיר. ×ĸקב ב×ĸיו×Ē ×™×Ļיבו×Ē ×”×Ēכונה כבויה כבריר×Ē ×ž×—×“×œ. למיד×ĸ × ×•×Ą×Ŗ, נא לראו×Ē ××Ē ×”×Ēי×ĸוד.", "storage_template_path_length": "מגבל×Ē ××•×¨×š × ×Ēיב משו×ĸר×Ē: {length, number}/{limit, number}", "storage_template_settings": "×Ēבני×Ē ××—×Ą×•×Ÿ", - "storage_template_settings_description": "ניהול מבנה ה×Ēיקיו×Ē ×•××Ē ×Š× הקוב×Ĩ של נכס הה×ĸלאה", + "storage_template_settings_description": "ניהול מבנה ה×Ēיקיו×Ē ×•××Ē ×Š× הקוב×Ĩ של ה×Ēמונה שהו×ĸל×Ēה", "storage_template_user_label": "{label} היא ×Ēווי×Ē ×”××—×Ą×•×Ÿ של המש×Ēמ׊", "system_settings": "הגדרו×Ē ×ž×ĸרכ×Ē", "tag_cleanup_job": "ניקוי ×Ēגים", @@ -277,7 +277,7 @@ "theme_settings_description": "ניהול ה×Ēאמה אישי×Ē ×Š×œ ממ׊ק האינטרנט של Immich", "these_files_matched_by_checksum": "קב×Ļים אלה ×Ēואמים לפי סיכומי הביקור×Ē ×Š×œ×”×", "thumbnail_generation_job": "×Ļור ×Ēמונו×Ē ×ž×ž×•×–×ĸרו×Ē", - "thumbnail_generation_job_description": "יו×Ļר ×Ēמונו×Ē ×ž×ž×•×–×ĸרו×Ē ×’×“×•×œ×•×Ē, קטנו×Ē ×•×ž×˜×•×Š×˜×Š×•×Ē ×ĸבור כל נכס, כמו גם ×Ēמונו×Ē ×ž×ž×•×–×ĸרו×Ē ×ĸבור כל אדם", + "thumbnail_generation_job_description": "יו×Ļר ×Ēמונו×Ē ×ž×ž×•×–×ĸרו×Ē ×’×“×•×œ×•×Ē, קטנו×Ē ×•×ž×˜×•×Š×˜×Š×•×Ē ×ĸבור כל ×Ēמונה, כמו גם ×Ēמונו×Ē ×ž×ž×•×–×ĸרו×Ē ×ĸבור כל אדם", "transcoding_acceleration_api": "API הא×Ļה", "transcoding_acceleration_api_description": "ה-API שיי×Ļור אינטראק×Ļיה ×ĸם המכשיר שלך כדי להאי×Ĩ א×Ē ×”×ž×¨×Ē ×”×§×™×“×•×“. הגדרה זו היא 'המאמ×Ĩ הטוב ביו×Ēר': היא ×Ēחזור לקידוד ×Ēוכנה במקרה של כשל. VP9 ×ĸשוי ל×ĸבוד או לא, ×Ēלוי בחומרה שלך.", "transcoding_acceleration_nvenc": "NVENC (דורש כרטיס מסך של NVIDIA)", @@ -341,17 +341,17 @@ "transcoding_video_codec_description": "ל-VP9 יש י×ĸילו×Ē ×’×‘×•×”×” ו×Ēאימו×Ē ×¨×Š×Ē, אבל לוקח יו×Ēר זמן להמיר א×Ē ×”×§×™×“×•×“ ×ĸבורו. HEVC מ×Ēפקד באופן דומה, אך ב×ĸל ×Ēאימו×Ē ×¨×Š×Ē × ×ž×•×›×” יו×Ēר. H.264 ×Ēואם באופן נרחב ומהיר להמיר א×Ē ×§×™×“×•×“×•, אבל הוא מיי×Ļר קב×Ļים גדולים בהרבה. AV1 הוא הקידוד הי×ĸיל ביו×Ēר אך לוקה ב×Ēמיכה במכשירים ישנים יו×Ēר.", "trash_enabled_description": "הפ×ĸל א×Ē ×Ēכונו×Ē ×”××Š×¤×”", "trash_number_of_days": "מספר הימים", - "trash_number_of_days_description": "מספר הימים לשמירה ×ĸל הנכסים באשפה לפני הסר×Ēם ל×Ļמי×Ēו×Ē", + "trash_number_of_days_description": "מספר הימים לשמירה של ×Ēמונו×Ē ×‘××Š×¤×” לפני הסר×Ēם ל×Ļמי×Ēו×Ē", "trash_settings": "הגדרו×Ē ×”××Š×¤×”", "trash_settings_description": "ניהול הגדרו×Ē ×”××Š×¤×”", "untracked_files": "קב×Ļים ללא מ×ĸקב", "untracked_files_description": "קב×Ļים אלה אינם נמ×Ļאים במ×ĸקב של היישום. הם יכולים להיו×Ē ×Ēו×Ļאו×Ē ×Š×œ ה×ĸברו×Ē ×›×•×Š×œ×•×Ē, ה×ĸלאו×Ē ×Š× ×§×˜×ĸו, או שנו×Ēרו מאחור בגלל שיבוש ב×Ēוכנה", "user_cleanup_job": "ניקוי מ׊×Ēמשים", - "user_delete_delay": "החשבון והנכסים של {user} י×Ēוזמנו למחיקה ל×Ļמי×Ēו×Ē ×‘×ĸוד {delay, plural, one {יום #} other {# ימים}}.", + "user_delete_delay": "החשבון וה×Ēמונו×Ē ×Š×œ {user} י×Ēוזמנו למחיקה ל×Ļמי×Ēו×Ē ×‘×ĸוד {delay, plural, one {יום #} other {# ימים}}.", "user_delete_delay_settings": "×ĸיכוב מחיקה", - "user_delete_delay_settings_description": "מספר הימים לאחר ההסרה ×ĸד מחיקה ל×Ļמי×Ēו×Ē ×Š×œ החשבון והנכסים של המש×Ēמ׊. משימ×Ē ×ž×—×™×§×Ē ×”×ž×Š×Ēמ׊ פו×ĸל×Ē ×‘×—×Ļו×Ē ×›×“×™ לבדוק אם יש מ׊×Ēמשים שמוכנים למחיקה. שינויים בהגדרה זו יו×ĸרכו בבי×Ļו×ĸ הבא.", - "user_delete_immediately": "החשבון והנכסים של {user} י×ĸמדו ב×Ēור למחיקה ל×Ļמי×Ēו×Ē ×‘××•×¤×Ÿ מיידי.", - "user_delete_immediately_checkbox": "ה×ĸמד מ׊×Ēמ׊ ונכסים ב×Ēור למחיקה מיידי×Ē", + "user_delete_delay_settings_description": "מספר הימים לאחר ההסרה ×ĸד מחיקה ל×Ļמי×Ēו×Ē ×Š×œ החשבון וה×Ēמונו×Ē ×Š×œ המש×Ēמ׊. משימ×Ē ×ž×—×™×§×Ē ×”×ž×Š×Ēמ׊ פו×ĸל×Ē ×‘×—×Ļו×Ē ×›×“×™ לבדוק אם יש מ׊×Ēמשים שמוכנים למחיקה. שינויים בהגדרה זו יו×ĸרכו בבי×Ļו×ĸ הבא.", + "user_delete_immediately": "החשבון וה×Ēמונו×Ē ×Š×œ {user} י×ĸמדו ב×Ēור למחיקה ל×Ļמי×Ēו×Ē ×‘××•×¤×Ÿ מיידי.", + "user_delete_immediately_checkbox": "ה×Ļב מ׊×Ēמ׊ ו×Ēמונו×Ē ×‘×Ēור למחיקה מיידי×Ē", "user_management": "ניהול מ׊×Ēמשים", "user_password_has_been_reset": "סיסמ×Ē ×”×ž×Š×Ēמ׊ אופסה:", "user_password_reset_description": "אנא ץפק א×Ē ×”×Ą×™×Ą×ž×” הזמני×Ē ×œ×ž×Š×Ēמ׊ והוד×ĸ לו שיש ×Ļורך לשנו×Ē ××Ē ×”×Ą×™×Ą×ž×” בכניסה הבאה שלו.", @@ -371,13 +371,17 @@ "admin_password": "סיסמ×Ē ×ž× ×”×œ", "administration": "ניהול", "advanced": "מ×Ēקדם", - "advanced_settings_log_level_title": "רמ×Ē ×Ēי×ĸוד אירו×ĸים: {}", - "advanced_settings_prefer_remote_subtitle": "חלק מהמכשירים הם איטיים מאד לט×ĸון ×Ēמונו×Ē ×ž×ž×•×–×ĸרו×Ē ×ž× ×›×Ą×™× שבמכשיר. הפ×ĸל הגדרה זו כדי לט×ĸון ×Ēמונו×Ē ×ž×¨×•×—×§×•×Ē ×‘×ž×§×•×", + "advanced_settings_enable_alternate_media_filter_subtitle": "הש×Ēמ׊ באפשרו×Ē ×–×• כדי לסנן מדיה במהלך הסנכרון לפי קריטריונים חלופיים. מומל×Ĩ להש×Ēמ׊ בזה רק אם יש ב×ĸיה בזיהוי כל האלבומים באפליק×Ļיה.", + "advanced_settings_enable_alternate_media_filter_title": "[ניסיוני] הש×Ēמ׊ במסנן סנכרון אלבום חלופי שמבכשיר", + "advanced_settings_log_level_title": "רמ×Ē ×¨×™×Š×•× ביומן: {}", + "advanced_settings_prefer_remote_subtitle": "חלק מהמכשירים הם איטיים מאד לט×ĸינה של ×Ēמונו×Ē ×ž×ž×•×–×ĸרו×Ē ×ž×Ēמונו×Ē ×Š×‘×ž×›×Š×™×¨. הפ×ĸל הגדרה זו כדי לט×ĸון ×Ēמונו×Ē ×ž×¨×•×—×§×•×Ē ×‘×ž×§×•×.", "advanced_settings_prefer_remote_title": "ה×ĸדת ×Ēמונו×Ē ×ž×¨×•×—×§×•×Ē", - "advanced_settings_proxy_headers_subtitle": "הגדר כו×Ēרו×Ē ×¤×¨×•×§×Ą×™ שהיישום ×Ļריך לשלוח ×ĸם כל בקש×Ē ×¨×Š×Ē", + "advanced_settings_proxy_headers_subtitle": "הגדר proxy headers שהיישום ×Ļריך לשלוח ×ĸם כל בקש×Ē ×¨×Š×Ē", "advanced_settings_proxy_headers_title": "כו×Ēרו×Ē ×¤×¨×•×§×Ą×™", - "advanced_settings_self_signed_ssl_subtitle": "מדלג ×ĸל אימו×Ē ×Ē×ĸוד×Ē SSL ×ĸבור נקוד×Ē ×”×§×Ļה של השר×Ē. דרוש ×ĸבור ×Ē×ĸודו×Ē ×‘×—×Ēימה ×ĸ×Ļמי×Ē", + "advanced_settings_self_signed_ssl_subtitle": "מדלג ×ĸל אימו×Ē ×Ē×ĸוד×Ē SSL ×ĸבור נקוד×Ē ×”×§×Ļה של השר×Ē. דרוש ×ĸבור ×Ē×ĸודו×Ē ×‘×—×Ēימה ×ĸ×Ļמי×Ē.", "advanced_settings_self_signed_ssl_title": "ה×Ēר ×Ē×ĸודו×Ē SSL בח×Ēימה ×ĸ×Ļמי×Ē", + "advanced_settings_sync_remote_deletions_subtitle": "מחק או שחזר ×Ēמונה במכשיר זה באופן אוטומטי כאשר פ×ĸולה זו × ×ĸשי×Ē ×‘×“×¤×“×¤×Ÿ", + "advanced_settings_sync_remote_deletions_title": "סנכרן מחיקו×Ē ×Š×‘×•×Ļ×ĸו במכשירים אחרים [נסיוני]", "advanced_settings_tile_subtitle": "הגדרו×Ē ×ž×Š×Ēמ׊ מ×Ēקדם", "advanced_settings_troubleshooting_subtitle": "אפ׊ר ×Ēכונו×Ē × ×•×Ą×¤×•×Ē ×œ×¤×Ēרון ב×ĸיו×Ē", "advanced_settings_troubleshooting_title": "פ×Ēרון ב×ĸיו×Ē", @@ -402,15 +406,15 @@ "album_thumbnail_card_item": "פריט 1", "album_thumbnail_card_items": "{} פריטים", "album_thumbnail_card_shared": " ¡ משו×Ē×Ŗ", - "album_thumbnail_shared_by": "משו×Ē×Ŗ ×ĸל ידי {}", + "album_thumbnail_shared_by": "שו×Ē×Ŗ ×ĸל ידי {}", "album_updated": "אלבום ×ĸודכן", - "album_updated_setting_description": "קבל הוד×ĸ×Ē ×“×•×\"ל כאשר לאלבום משו×Ē×Ŗ יש נכסים חדשים", + "album_updated_setting_description": "קבל הוד×ĸ×Ē ×“×•×\"ל כאשר לאלבום משו×Ē×Ŗ יש ×Ēמונו×Ē ×—×“×Š×•×Ē", "album_user_left": "×ĸזב א×Ē {album}", "album_user_removed": "{user} הוסר", "album_viewer_appbar_delete_confirm": "האם א×Ē/ה בטוח/ה שבר×Ļונך למחוק א×Ē ×”××œ×‘×•× הזה מהחשבון שלך?", "album_viewer_appbar_share_err_delete": "מחיק×Ē ××œ×‘×•× נכשלה", "album_viewer_appbar_share_err_leave": "×ĸזיב×Ē ×”××œ×‘×•× נכשלה", - "album_viewer_appbar_share_err_remove": "יש ב×ĸיו×Ē ×‘×”×Ą×¨×Ē ×”× ×›×Ą×™× מהאלבום", + "album_viewer_appbar_share_err_remove": "יש ב×ĸיו×Ē ×‘×”×Ą×¨×Ē ×”×Ēמונו×Ē ×ž×”××œ×‘×•×", "album_viewer_appbar_share_err_title": "נכשל בשינוי כו×Ēר×Ē ×”××œ×‘×•×", "album_viewer_appbar_share_leave": "×ĸזוב אלבום", "album_viewer_appbar_share_to": "׊×Ē×Ŗ ×ĸם", @@ -439,57 +443,57 @@ "appears_in": "מופי×ĸ ב", "archive": "ארכיון", "archive_or_unarchive_photo": "ה×ĸבר ×Ēמונה לארכיון או הו×Ļא או×Ēה מ׊ם", - "archive_page_no_archived_assets": "לא נמ×Ļאו נכסים בארכיון", - "archive_page_title": "ארכיון ({})", + "archive_page_no_archived_assets": "לא נמ×Ļאו ×Ēמונו×Ē ×‘××¨×›×™×•×Ÿ", + "archive_page_title": "בארכיון ({})", "archive_size": "גודל הארכיון", "archive_size_description": "הגדר א×Ē ×’×•×“×œ הארכיון להורדו×Ē (ב-GiB)", "archived": "בארכיון", "archived_count": "{count, plural, other {# הו×ĸברו לארכיון}}", "are_these_the_same_person": "האם אלה או×Ēו האדם?", "are_you_sure_to_do_this": "האם באמ×Ē ×‘×¨×Ļונך ל×ĸשו×Ē ××Ē ×–×”?", - "asset_action_delete_err_read_only": "לא ני×Ēן למחוק נכס(ים) לקריאה בלבד, מדלג", - "asset_action_share_err_offline": "לא ני×Ēן להשיג נכס(ים) לא מקוונ(ים), מדלג ", + "asset_action_delete_err_read_only": "לא ני×Ēן למחוק ×Ēמונו×Ē ×œ×§×¨×™××” בלבד, מדלג", + "asset_action_share_err_offline": "לא ני×Ēן להשיג ×Ēמונו×Ē ×œ× מקוונו×Ē, מדלג", "asset_added_to_album": "× ×•×Ą×Ŗ לאלבום", "asset_adding_to_album": "×ž×•×Ą×™×Ŗ לאלבוםâ€Ļ", - "asset_description_updated": "×Ēיאור הנכס ×ĸודכן", - "asset_filename_is_offline": "הנכס {filename} אינו מקוון", - "asset_has_unassigned_faces": "לנכס יש פנים שלא הוק×Ļו", + "asset_description_updated": "×Ēיאור ה×Ēמונה ×ĸודכן", + "asset_filename_is_offline": "ה×Ēמונה {filename} אינה מקוונ×Ē", + "asset_has_unassigned_faces": "ל×Ēמונה יש פנים שלא הוק×Ļו", "asset_hashing": "מגבבâ€Ļ", "asset_list_group_by_sub_title": "קב×Ĩ לפי", "asset_list_layout_settings_dynamic_layout_title": "פריסה דינמי×Ē", "asset_list_layout_settings_group_automatically": "אוטומטי", - "asset_list_layout_settings_group_by": "קב×Ĩ נכסים לפי", + "asset_list_layout_settings_group_by": "קב×Ĩ ×Ēמונו×Ē ×œ×¤×™", "asset_list_layout_settings_group_by_month_day": "חודש + יום", "asset_list_layout_sub_title": "פריסה", "asset_list_settings_subtitle": "הגדרו×Ē ×Ēבני×Ē ×¨×Š×Ē ×Ēמונו×Ē", "asset_list_settings_title": "ר׊×Ē ×Ēמונו×Ē", - "asset_offline": "נכס לא מקוון", - "asset_offline_description": "הנכס החי×Ļוני הזה כבר לא נמ×Ļא בדיסק. נא לי×Ļור ק׊ר ×ĸם מנהל Immich שלך לקבל×Ē ×ĸזרה.", - "asset_restored_successfully": "נכס שוחזר בה×Ļלחה", + "asset_offline": "×Ēמונה לא מקוונ×Ē", + "asset_offline_description": "ה×Ēמונה החי×Ļוני×Ē ×”×–××Ē ×›×‘×¨ לא נמ×Ļא×Ē ×‘×“×™×Ą×§. נא לי×Ļור ק׊ר ×ĸם מנהל Immich שלך לקבל×Ē ×ĸזרה.", + "asset_restored_successfully": "×Ēמונה שוחזרה בה×Ļלחה", "asset_skipped": "דילג", "asset_skipped_in_trash": "באשפה", "asset_uploaded": "הו×ĸלה", "asset_uploading": "מ×ĸלהâ€Ļ", "asset_viewer_settings_subtitle": "ניהול הגדרו×Ē ×ž×Ļיג הגלריה שלך", - "asset_viewer_settings_title": "מ×Ļיג הנכסים", - "assets": "נכסים", - "assets_added_count": "{count, plural, one {× ×•×Ą×Ŗ נכס #} other {נוספו # נכסים}}", - "assets_added_to_album_count": "{count, plural, one {× ×•×Ą×Ŗ נכס #} other {נוספו # נכסים}} לאלבום", - "assets_added_to_name_count": "{count, plural, one {נכס # × ×•×Ą×Ŗ} other {# נכסים נוספו}} אל {hasName, select, true {{name}} other {אלבום חדש}}", - "assets_count": "{count, plural, one {נכס #} other {# נכסים}}", - "assets_deleted_permanently": "{} נכס(ים) נמחקו ל×Ļמי×Ēו×Ē", - "assets_deleted_permanently_from_server": "{} נכס(ים) נמחקו ל×Ļמי×Ēו×Ē ×ž×Š×¨×Ē ×”-Immich", - "assets_moved_to_trash_count": "{count, plural, one {נכס # הו×ĸבר} other {# נכסים הו×ĸברו}} לאשפה", - "assets_permanently_deleted_count": "{count, plural, one {נכס # נמחק} other {# נכסים נמחקו}} ל×Ļמי×Ēו×Ē", - "assets_removed_count": "{count, plural, one {נכס # הוסר} other {# נכסים הוסרו}}", - "assets_removed_permanently_from_device": "{} נכס(ים) נמחקו ל×Ļמי×Ēו×Ē ×ž×”×ž×›×Š×™×¨ שלך", - "assets_restore_confirmation": "האם באמ×Ē ×‘×¨×Ļונך לשחזר א×Ē ×›×œ הנכסים שבאשפה? אין באפשרו×Ēך לבטל א×Ē ×”×¤×ĸולה הזו! יש לשים לב שלא ני×Ēן לשחזר נכסים לא מקוונים בדרך זו.", - "assets_restored_count": "{count, plural, one {נכס # שוחזר} other {# נכסים שוחזרו}}", - "assets_restored_successfully": "{} נכס(ים) שוחזרו בה×Ļלחה", - "assets_trashed": "{} נכס(ים) הו×ĸברו לאשפה", - "assets_trashed_count": "{count, plural, one {נכס # הושלך} other {# נכסים הושלכו}} לאשפה", - "assets_trashed_from_server": "{} נכס(ים) הו×ĸברו לאשפה מ׊ר×Ē ×”-Immich", - "assets_were_part_of_album_count": "{count, plural, one {נכס היה} other {נכסים היו}} כבר חלק מהאלבום", + "asset_viewer_settings_title": "מ×Ļיג ה×Ēמונו×Ē", + "assets": "×Ēמונו×Ē", + "assets_added_count": "{count, plural, one {נוספה ×Ēומנה #} other {נוספו # ×Ēמונו×Ē}}", + "assets_added_to_album_count": "{count, plural, one {נוספה ×Ēמונה #} other {נוספו # ×Ēמונו×Ē}} לאלבום", + "assets_added_to_name_count": "{count, plural, one {×Ēמונה # נוספה} other {# ×Ēמונו×Ē × ×•×Ą×¤×•}} אל {hasName, select, true {{name}} other {אלבום חדש}}", + "assets_count": "{count, plural, one {×Ēמונה #} other {# ×Ēמונו×Ē}}", + "assets_deleted_permanently": "{} ×Ēמונו×Ē × ×ž×—×§×• ל×Ļמי×Ēו×Ē", + "assets_deleted_permanently_from_server": "{} ×Ēמונו×Ē × ×ž×—×§×• ל×Ļמי×Ēו×Ē ×ž×Š×¨×Ē ×”-Immich", + "assets_moved_to_trash_count": "{count, plural, one {×Ēמונה # הו×ĸברה} other {# ×Ēמונו×Ē ×”×•×ĸברו}} לאשפה", + "assets_permanently_deleted_count": "{count, plural, one {×Ēמונה # נמחקה} other {# ×Ēמונו×Ē × ×ž×—×§×•}} ל×Ļמי×Ēו×Ē", + "assets_removed_count": "{count, plural, one {×Ēמונה # הוסרה} other {# ×Ēמונו×Ē ×”×•×Ą×¨×•}}", + "assets_removed_permanently_from_device": "{} ×Ēמונו×Ē × ×ž×—×§×• ל×Ļמי×Ēו×Ē ×ž×”×ž×›×Š×™×¨ שלך", + "assets_restore_confirmation": "האם באמ×Ē ×‘×¨×Ļונך לשחזר א×Ē ×›×œ ה×Ēמונו×Ē ×Š×‘××Š×¤×”? אין באפשרו×Ēך לבטל א×Ē ×”×¤×ĸולה הזו! יש לשים לב שלא ני×Ēן לשחזר ×Ēמונו×Ē ×œ× מקוונו×Ē ×‘×“×¨×š זו.", + "assets_restored_count": "{count, plural, one {×Ēמונה # שוחזרה} other {# ×Ēמונו×Ē ×Š×•×—×–×¨×•}}", + "assets_restored_successfully": "{} ×Ēמונו×Ē ×Š×•×—×–×¨×• בה×Ļלחה", + "assets_trashed": "{} ×Ēמונו×Ē ×”×•×ĸברו לאשפה", + "assets_trashed_count": "{count, plural, one {×Ēמונה # הושלכה} other {# ×Ēמונו×Ē ×”×•×Š×œ×›×•}} לאשפה", + "assets_trashed_from_server": "{} ×Ēמונו×Ē ×”×•×ĸברו לאשפה מהשר×Ē", + "assets_were_part_of_album_count": "{count, plural, one {×Ēמונה היי×Ēה} other {×Ēמונו×Ē ×”×™×•}} כבר חלק מהאלבום", "authorized_devices": "מכשירים מורשים", "automatic_endpoint_switching_subtitle": "ה×Ēחבר מקומי×Ē ×“×¨×š אינטרנט אלחוטי יי×ĸודי כאשר זמין והש×Ēמ׊ בחיבורים חלופיים במקומו×Ē ××—×¨×™×", "automatic_endpoint_switching_title": "החלפ×Ē ×›×Ēוב×Ē ××•×˜×•×ž×˜×™×Ē", @@ -497,22 +501,22 @@ "back_close_deselect": "חזור, סגור, או בטל בחירה", "background_location_permission": "הרשא×Ē ×ž×™×§×•× ברק×ĸ", "background_location_permission_content": "כדי ×œ×”×—×œ×™×Ŗ ר׊×Ēו×Ē ×‘×ĸ×Ē ×¨×™×Ļה ברק×ĸ, היישום ×Ļריך *×Ēמיד* גישה למיקום מדויק ×ĸל מנ×Ē ×œ×§×¨×•× א×Ē ×”×Š× של ר׊×Ē ×”××™× ×˜×¨× ×˜ האלחוטי", - "backup_album_selection_page_albums_device": "אלבומים במכשיר ({})", + "backup_album_selection_page_albums_device": "({}) אלבומים במכשיר", "backup_album_selection_page_albums_tap": "הקש כדי לכלול, הקש פ×ĸמיים כדי להחריג", - "backup_album_selection_page_assets_scatter": "נכסים יכולים לה×Ēפזר ×ĸל פני אלבומים מרובים. לפיכך, ני×Ēן לכלול או להחריג אלבומים במהלך ×Ēהליך הגיבוי", + "backup_album_selection_page_assets_scatter": "×Ēמונו×Ē ×™×›×•×œ×•×Ē ×œ×”×Ēפזר ×ĸל פני אלבומים מרובים. לפיכך, ני×Ēן לכלול או להחריג אלבומים במהלך ×Ēהליך הגיבוי.", "backup_album_selection_page_select_albums": "בחיר×Ē ××œ×‘×•×ž×™×", "backup_album_selection_page_selection_info": "פרטי בחירה", - "backup_album_selection_page_total_assets": "סה״כ נכסים ייחודיים", + "backup_album_selection_page_total_assets": "סה״כ ×Ēמונו×Ē ×™×™×—×•×“×™×•×Ē", "backup_all": "הכל", - "backup_background_service_backup_failed_message": "נכשל בגיבוי נכסים. מנסה שוב...", - "backup_background_service_connection_failed_message": "נכשל בה×Ēחברו×Ē ×œ×Š×¨×Ē. מנסה שוב...", + "backup_background_service_backup_failed_message": "נכשל בגיבוי ×Ēמונו×Ē. מנסה שובâ€Ļ", + "backup_background_service_connection_failed_message": "נכשל בה×Ēחברו×Ē ×œ×Š×¨×Ē. מנסה שובâ€Ļ", "backup_background_service_current_upload_notification": "מ×ĸלה {}", - "backup_background_service_default_notification": "מחפש נכסים חדשים...", + "backup_background_service_default_notification": "מחפש ×Ēמונו×Ē ×—×“×Š×•×Ēâ€Ļ", "backup_background_service_error_title": "שגיא×Ē ×’×™×‘×•×™", - "backup_background_service_in_progress_notification": "מגבה א×Ē ×”× ×›×Ą×™× שלך...", - "backup_background_service_upload_failure_notification": "נכשל לה×ĸלו×Ē {}", + "backup_background_service_in_progress_notification": "מגבה א×Ē ×”×Ēמונו×Ē ×Š×œ×šâ€Ļ", + "backup_background_service_upload_failure_notification": "{} נכשל בה×ĸלאה", "backup_controller_page_albums": "אלבומים לגיבוי", - "backup_controller_page_background_app_refresh_disabled_content": "אפ׊ר ר×ĸנון אפליק×Ļיה ברק×ĸ בהגדרו×Ē > כללי > ר×ĸנון אפליק×Ļיה ברק×ĸ כדי להש×Ēמ׊ בגיבוי ברק×ĸ", + "backup_controller_page_background_app_refresh_disabled_content": "אפ׊ר ר×ĸנון אפליק×Ļיה ברק×ĸ בהגדרו×Ē > כללי > ר×ĸנון אפליק×Ļיה ברק×ĸ כדי להש×Ēמ׊ בגיבוי ברק×ĸ.", "backup_controller_page_background_app_refresh_disabled_title": "ר×ĸנון אפליק×Ļיה ברק×ĸ מושב×Ē", "backup_controller_page_background_app_refresh_enable_button_text": "לך להגדרו×Ē", "backup_controller_page_background_battery_info_link": "הראה לי איך", @@ -521,8 +525,8 @@ "backup_controller_page_background_battery_info_title": "מיטובי סוללה", "backup_controller_page_background_charging": "רק בט×ĸינה", "backup_controller_page_background_configure_error": "נכשל בהגדר×Ē ×Ē×Ļור×Ē ×Š×™×¨×•×Ē ×”×¨×§×ĸ", - "backup_controller_page_background_delay": "דחה גיבוי נכסים חדשים: {}", - "backup_controller_page_background_description": "הפ×ĸל א×Ē ×”×Š×™×¨×•×Ē ×¨×§×ĸ כדי לגבו×Ē ×‘××•×¤×Ÿ אוטומטי כל נכס חדש מבלי לה×Ļטרך לפ×Ēוח א×Ē ×”×™×™×Š×•×", + "backup_controller_page_background_delay": "השהה גיבוי של ×Ēמונו×Ē ×—×“×Š×•×Ē: {}", + "backup_controller_page_background_description": "הפ×ĸל א×Ē ×”×Š×™×¨×•×Ē ×¨×§×ĸ כדי לגבו×Ē ×‘××•×¤×Ÿ אוטומטי כל ×Ēמונה חדשה מבלי לה×Ļטרך לפ×Ēוח א×Ē ×”×™×™×Š×•×", "backup_controller_page_background_is_off": "גיבוי אוטומטי ברק×ĸ כבוי", "backup_controller_page_background_is_on": "גיבוי אוטומטי ברק×ĸ מופ×ĸל", "backup_controller_page_background_turn_off": "כבה שירו×Ē ×’×™×‘×•×™ ברק×ĸ", @@ -532,10 +536,10 @@ "backup_controller_page_backup_selected": "נבחרו: ", "backup_controller_page_backup_sub": "×Ēמונו×Ē ×•×Ą×¨×˜×•× ×™× מגובים", "backup_controller_page_created": "נו×Ļר ב: {}", - "backup_controller_page_desc_backup": "הפ×ĸל גיבוי חזי×Ē ×›×“×™ לה×ĸלו×Ē ×‘××•×¤×Ÿ אוטומטי נכסים חדשים לשר×Ē ×›×Š×¤×•×Ēחים א×Ē ×”×™×™×Š×•×", + "backup_controller_page_desc_backup": "הפ×ĸל גיבוי חזי×Ē ×›×“×™ לה×ĸלו×Ē ×‘××•×¤×Ÿ אוטומטי ×Ēמונו×Ē ×—×“×Š×•×Ē ×œ×Š×¨×Ē ×›×Š×¤×•×Ēחים א×Ē ×”×™×™×Š×•×.", "backup_controller_page_excluded": "הוחרגו: ", - "backup_controller_page_failed": "נכשל ({})", - "backup_controller_page_filename": "׊ם קוב×Ĩ: {} [{}]", + "backup_controller_page_failed": "({}) נכשלו", + "backup_controller_page_filename": "׊ם הקוב×Ĩ: {} [{}]", "backup_controller_page_id": "מזהה: {}", "backup_controller_page_info": "פרטי גיבוי", "backup_controller_page_none_selected": "אין בחירה", @@ -545,14 +549,14 @@ "backup_controller_page_start_backup": "ה×Ēחל גיבוי", "backup_controller_page_status_off": "גיבוי חזי×Ē ××•×˜×•×ž×˜×™ כבוי", "backup_controller_page_status_on": "גיבוי חזי×Ē ××•×˜×•×ž×˜×™ מופ×ĸל", - "backup_controller_page_storage_format": "{} מ×Ēוך {} נו×Ļלו", + "backup_controller_page_storage_format": "{} מ×Ēוך {} בשימוש", "backup_controller_page_to_backup": "אלבומים לגבו×Ē", "backup_controller_page_total_sub": "כל ה×Ēמונו×Ē ×•×”×Ą×¨×˜×•× ×™× הייחודיים מאלבומים שנבחרו", "backup_controller_page_turn_off": "כיבוי גיבוי חזי×Ē", "backup_controller_page_turn_on": "הפ×ĸל גיבוי חזי×Ē", "backup_controller_page_uploading_file_info": "מ×ĸלה מיד×ĸ ×ĸל הקוב×Ĩ", "backup_err_only_album": "לא ני×Ēן להסיר א×Ē ×”××œ×‘×•× היחיד", - "backup_info_card_assets": "נכסים", + "backup_info_card_assets": "×Ēמונו×Ē", "backup_manual_cancelled": "בוטל", "backup_manual_in_progress": "ה×ĸלאה כבר ב×Ēהליך. נסה אחרי זמן מה", "backup_manual_success": "ה×Ļלחה", @@ -566,25 +570,25 @@ "bugs_and_feature_requests": "באגים & בקשו×Ē ×œ×Ēכונו×Ē", "build": "גרס×Ē ×‘× ×™×™×”", "build_image": "גרס×Ē ×Ēוכנה", - "bulk_delete_duplicates_confirmation": "האם באמ×Ē ×‘×¨×Ļונך למחוק בכמו×Ē ×’×“×•×œ×” {count, plural, one {נכס # כפול} other {# נכסים כפולים}}? זה ישמור ×ĸל הנכס הכי גדול של כל קבו×Ļה וימחק ל×Ļמי×Ēו×Ē ××Ē ×›×œ ׊אר הכפילויו×Ē. אין באפשרו×Ēך לבטל א×Ē ×”×¤×ĸולה הזו!", - "bulk_keep_duplicates_confirmation": "האם באמ×Ē ×‘×¨×Ļונך להשאיר {count, plural, one {נכס # כפול} other {# נכסים כפולים}}? זה יפ×Ēור א×Ē ×›×œ הקבו×Ļו×Ē ×”×›×¤×•×œ×•×Ē ×ž×‘×œ×™ למחוק דבר.", - "bulk_trash_duplicates_confirmation": "האם באמ×Ē ×‘×¨×Ļונך לה×ĸביר לאשפה בכמו×Ē ×’×“×•×œ×” {count, plural, one {נכס # כפול} other {# נכסים כפולים}}? זה ישמור ×ĸל הנכס הגדול ביו×Ēר של כל קבו×Ļה וי×ĸביר לאשפה א×Ē ×›×œ ׊אר הכפילויו×Ē.", + "bulk_delete_duplicates_confirmation": "האם באמ×Ē ×‘×¨×Ļונך למחוק בכמו×Ē ×’×“×•×œ×” {count, plural, one {×Ēמונה # כפולה} other {# ×Ēמונו×Ē ×›×¤×•×œ×•×Ē}}? זה ישמור ×ĸל ה×Ēמונה הכי גדולה של כל קבו×Ļה וימחק ל×Ļמי×Ēו×Ē ××Ē ×›×œ ׊אר הכפילויו×Ē. אין באפשרו×Ēך לבטל א×Ē ×”×¤×ĸולה הזו!", + "bulk_keep_duplicates_confirmation": "האם באמ×Ē ×‘×¨×Ļונך להשאיר {count, plural, one {×Ēמונה # כפולה} other {# ×Ēמונו×Ē ×›×¤×•×œ×•×Ē}}? זה יסגור א×Ē ×›×œ הקבו×Ļו×Ē ×”×›×¤×•×œ×•×Ē ×ž×‘×œ×™ למחוק דבר.", + "bulk_trash_duplicates_confirmation": "האם באמ×Ē ×‘×¨×Ļונך לה×ĸביר לאשפה בכמו×Ē ×’×“×•×œ×” {count, plural, one {×Ēמונה # כפולה} other {# ×Ēמונו×Ē ×›×¤×•×œ×•×Ē}}? זה ישמור ×ĸל ה×Ēמונה הגדולה ביו×Ēר של כל קבו×Ļה וי×ĸביר לאשפה א×Ē ×›×œ ׊אר הכפילויו×Ē.", "buy": "רכוש א×Ē Immich", - "cache_settings_album_thumbnails": "×Ēמונו×Ē ×ž×ž×•×–×ĸרו×Ē ×Š×œ דת ספרייה ({} נכסים)", + "cache_settings_album_thumbnails": "×Ēמונו×Ē ×ž×ž×•×–×ĸרו×Ē ×Š×œ דת ספרייה ({} ×Ēמונו×Ē)", "cache_settings_clear_cache_button": "ניקוי מטמון", - "cache_settings_clear_cache_button_title": "מנקה א×Ē ×”×ž×˜×ž×•×Ÿ של היישום. זה ישפי×ĸ באופן מ׊מ×ĸו×Ēי ×ĸל הבי×Ļו×ĸים של היישום ×ĸד שהמטמון נבנה מחדש", + "cache_settings_clear_cache_button_title": "מנקה א×Ē ×”×ž×˜×ž×•×Ÿ של היישום. זה ישפי×ĸ באופן מ׊מ×ĸו×Ēי ×ĸל הבי×Ļו×ĸים של היישום ×ĸד שהמטמון מ×Ēמלא מחדש.", "cache_settings_duplicated_assets_clear_button": "נקה", "cache_settings_duplicated_assets_subtitle": "×Ēמונו×Ē ×•×Ą×¨×˜×•× ×™× ׊נמ×Ļאים ברשימה השחורה של היישום", - "cache_settings_duplicated_assets_title": "נכסים משוכפלים ({})", - "cache_settings_image_cache_size": "גודל מטמון ×Ēמונה ({} נכסים)", + "cache_settings_duplicated_assets_title": "({}) ×Ēמונו×Ē ×ž×Š×•×›×¤×œ×•×Ē", + "cache_settings_image_cache_size": "גודל מטמון ה×Ēמונה ({} ×Ēמונו×Ē)", "cache_settings_statistics_album": "×Ēמונו×Ē ×ž×ž×•×–×ĸרו×Ē ×Š×œ ספרייה", - "cache_settings_statistics_assets": "{} נכסים ({})", + "cache_settings_statistics_assets": "{} ×Ēמונו×Ē ({})", "cache_settings_statistics_full": "×Ēמונו×Ē ×ž×œ××•×Ē", "cache_settings_statistics_shared": "×Ēמונו×Ē ×ž×ž×•×–×ĸרו×Ē ×Š×œ אלבום משו×Ē×Ŗ", "cache_settings_statistics_thumbnail": "×Ēמונו×Ē ×ž×ž×•×–×ĸרו×Ē", "cache_settings_statistics_title": "שימוש במטמון", - "cache_settings_subtitle": "שלוט בה×Ēנהגו×Ē ×Š×ž×™×¨×Ē ×”×ž×˜×ž×•×Ÿ של היישום הנייד", - "cache_settings_thumbnail_size": "גודל מטמון ×Ēמונה ממוז×ĸר×Ē ({} נכסים)", + "cache_settings_subtitle": "הגדר כי×Ļד אפליק×Ļיי×Ē Immich שומר×Ē × ×Ēונים באופן זמני", + "cache_settings_thumbnail_size": "גודל מטמון ×Ēמונה ממוז×ĸר×Ē ({} ×Ēמונו×Ē)", "cache_settings_tile_subtitle": "שלוט בה×Ēנהגו×Ē ×”××—×Ą×•×Ÿ המקומי", "cache_settings_tile_title": "אחסון מקומי", "cache_settings_title": "הגדרו×Ē ×Š×ž×™×¨×Ē ×ž×˜×ž×•×Ÿ", @@ -613,9 +617,9 @@ "change_your_password": "×”×—×œ×Ŗ א×Ē ×”×Ą×™×Ą×ž×” שלך", "changed_visibility_successfully": "הנראו×Ē ×Š×•× ×Ēה בה×Ļלחה", "check_all": "לסמן הכל", - "check_corrupt_asset_backup": "בדוק גיבויים פגומים של נכסים", + "check_corrupt_asset_backup": "בדוק גיבויים פגומים של ×Ēמונו×Ē", "check_corrupt_asset_backup_button": "ב×Ļ×ĸ בדיקה", - "check_corrupt_asset_backup_description": "הר×Ĩ בדיקה זו רק ×ĸל Wi-Fi ולאחר שכל הנכסים גובו. ההליך ×ĸשוי לקח×Ē ×›×ž×” דקו×Ē.", + "check_corrupt_asset_backup_description": "הר×Ĩ בדיקה זו רק ×ĸל Wi-Fi ולאחר שכל ה×Ēמונו×Ē ×’×•×‘×•. ההליך ×ĸשוי לקח×Ē ×›×ž×” דקו×Ē.", "check_logs": "בדוק יומני רישום", "choose_matching_people_to_merge": "בחר אנשים ×Ēואמים למיזוג", "city": "×ĸיר", @@ -643,13 +647,13 @@ "comments_and_likes": "×Ēגובו×Ē & לייקים", "comments_are_disabled": "×Ēגובו×Ē ×ž×•×Š×‘×Ēו×Ē", "common_create_new_album": "×Ļור אלבום חדש", - "common_server_error": "נא לבדוק א×Ē ×—×™×‘×•×¨ הרש×Ē ×Š×œ×š, ×Ēוודא/י שהשר×Ē × ×’×™×Š ושגרסאו×Ē ××¤×œ×™×§×Ļיה/׊ר×Ē ×Ēואמו×Ē", + "common_server_error": "נא לבדוק א×Ē ×—×™×‘×•×¨ הרש×Ē ×Š×œ×š, ×Ēוודא/י שהשר×Ē × ×’×™×Š ושגרסאו×Ē ××¤×œ×™×§×Ļיה/׊ר×Ē ×Ēואמו×Ē.", "completed": "הושלמו", "confirm": "אישור", "confirm_admin_password": "אישור סיסמ×Ē ×ž× ×”×œ", - "confirm_delete_face": "האם באמ×Ē ×‘×¨×Ļונך למחוק א×Ē ×”×¤× ×™× של {name} מהנכס?", + "confirm_delete_face": "האם באמ×Ē ×‘×¨×Ļונך למחוק א×Ē ×”×¤× ×™× של {name} מה×Ēמונה?", "confirm_delete_shared_link": "האם באמ×Ē ×‘×¨×Ļונך למחוק א×Ē ×”×§×™×Š×•×¨ המשו×Ē×Ŗ הזה?", - "confirm_keep_this_delete_others": "כל ׊אר הנכסים ב×ĸרימה יימחקו למ×ĸט נכס זה. האם באמ×Ē ×‘×¨×Ļונך להמשיך?", + "confirm_keep_this_delete_others": "כל ׊אר ×Ēמונו×Ē ×Š×‘×ĸרימה יימחקו למ×ĸט ×Ēמונה זא×Ē. האם באמ×Ē ×‘×¨×Ļונך להמשיך?", "confirm_password": "א׊ר סיסמה", "contain": "מכיל", "context": "הקשר", @@ -684,9 +688,9 @@ "create_link_to_share_description": "אפ׊ר לכל אחד ×ĸם הקישור לראו×Ē ××Ē ×”×Ēמונו×Ē ×Š× ×‘×—×¨×•", "create_new": "×Ļור חדש", "create_new_person": "×Ļור אדם חדש", - "create_new_person_hint": "הק×Ļה א×Ē ×”× ×›×Ą×™× שנבחרו לאדם חדש", + "create_new_person_hint": "הק×Ļה א×Ē ×”×Ēמונו×Ē ×Š× ×‘×—×¨×• לאדם חדש", "create_new_user": "×Ļור מ׊×Ēמ׊ חדש", - "create_shared_album_page_share_add_assets": "×”×•×Ą×Ŗ נכסים", + "create_shared_album_page_share_add_assets": "×”×•×Ą×Ŗ ×Ēמונו×Ē", "create_shared_album_page_share_select_photos": "בחיר×Ē ×Ēמונו×Ē", "create_tag": "×Ļור ×Ēג", "create_tag_description": "×Ļור ×Ēג חדש. ×ĸבור ×Ēגים מקוננים, נא להזין א×Ē ×”× ×Ēיב המלא של ה×Ēג כולל קווים נטויים.", @@ -712,12 +716,12 @@ "deduplication_criteria_1": "גודל ×Ēמונה בב×Ēים", "deduplication_criteria_2": "ספיר×Ē × ×Ēוני EXIF", "deduplication_info": "מיד×ĸ ×ĸל ביטול כפילויו×Ē", - "deduplication_info_description": "כדי לבחור מרא׊ נכסים באופן אוטומטי ולהסיר כפילויו×Ē ×‘×›×ž×•×Ē ×’×“×•×œ×”, אנו מס×Ēכלים ×ĸל:", + "deduplication_info_description": "כדי לבחור מרא׊ ×Ēמונו×Ē ×‘××•×¤×Ÿ אוטומטי ולהסיר כפילויו×Ē ×‘×›×ž×•×Ē ×’×“×•×œ×”, אנו מס×Ēכלים ×ĸל:", "default_locale": "׊פ×Ē ×‘×¨×™×¨×Ē ×ž×—×“×œ", "default_locale_description": "פורמט ×Ēאריכים ומספרים מבוסס ׊פ×Ē ×”×“×¤×“×¤×Ÿ שלך", "delete": "מחק", "delete_album": "מחק אלבום", - "delete_api_key_prompt": "האם באמ×Ē ×‘×¨×Ļונך למחוק מפ×Ēח ה-API הזה?", + "delete_api_key_prompt": "האם א×Ēה בטוח שבר×Ļונך למחוק מפ×Ēח ה-API הזה?", "delete_dialog_alert": "הפריטים האלה ימחקו ל×Ļמי×Ēו×Ē ×ž×”×Š×¨×Ē ×•×ž×”×ž×›×Š×™×¨ שלך", "delete_dialog_alert_local": "הפריטים האלה יוסרו ל×Ļמי×Ēו×Ē ×ž×”×ž×›×Š×™×¨ שלך אבל ×ĸדיין יהיו זמינים בשר×Ē", "delete_dialog_alert_local_non_backed_up": "חלק מהפריטים לא מגובים לשר×Ē ×•×™×•×Ą×¨×• ל×Ļמי×Ēו×Ē ×ž×”×ž×›×Š×™×¨ שלך", @@ -738,7 +742,7 @@ "delete_tag_confirmation_prompt": "האם באמ×Ē ×‘×¨×Ļונך למחוק ×Ēג {tagName}?", "delete_user": "מחק מ׊×Ēמ׊", "deleted_shared_link": "קישור משו×Ē×Ŗ נמחק", - "deletes_missing_assets": "מוחק נכסים שחסרים בדיסק", + "deletes_missing_assets": "מוחק ×Ēמונו×Ē ×Š×—×Ą×¨×•×Ē ×‘×“×™×Ą×§", "description": "×Ēיאור", "description_input_hint_text": "×”×•×Ą×Ŗ ×Ēיאור...", "description_input_submit_error": "שגיאה ב×ĸדכון ×Ēיאור, בדוק א×Ē ×”×™×•×ž×Ÿ לפרטים נוספים", @@ -753,7 +757,7 @@ "display_options": "ה×Ļג×Ē ××¤×Š×¨×•×™×•×Ē", "display_order": "סדר ×Ē×Ļוגה", "display_original_photos": "ה×Ļג×Ē ×Ēמונו×Ē ×ž×§×•×¨×™×•×Ē", - "display_original_photos_setting_description": "ה×ĸדת לה×Ļיג א×Ē ×”×Ēמונה המקורי×Ē ×‘×ĸ×Ē ×Ļפיי×Ē × ×›×Ą במקום ×Ēמונו×Ē ×ž×ž×•×–×ĸרו×Ē ×›××Š×¨ הנכס המקורי ×Ēומך ב×Ē×Ļוגה בדפדפן. זה ×ĸלול לגרום ל×Ēמונו×Ē ×œ×”×™×•×Ē ×ž×•×Ļגו×Ē ×‘××™×˜×™×•×Ē.", + "display_original_photos_setting_description": "ה×Ļג ×Ēמונה מקורי×Ē ×‘×ĸ×Ē ×Ļפייה ב×Ēמונה במקום ×Ēמונו×Ē ×ž×ž×•×–×ĸרו×Ē ×›××Š×¨ ה×Ēמונה המקורי×Ē ×Ēומכ×Ē ×‘×Ē×Ļוגה בדפדפן. זה ×ĸלול לגרום ל×Ēמונו×Ē ×œ×”×™×•×Ē ×ž×•×Ļגו×Ē ×‘××™×˜×™×•×Ē.", "do_not_show_again": "אל ×Ē×Ļיג א×Ē ×”×”×•×“×ĸה הזא×Ē ×Š×•×‘", "documentation": "×Ēי×ĸוד", "done": "סיום", @@ -770,13 +774,13 @@ "download_notfound": "הורדה לא נמ×Ļא", "download_paused": "הורדה הופסקה", "download_settings": "הורדה", - "download_settings_description": "ניהול הגדרו×Ē ×”×§×Š×•×¨×•×Ē ×œ×”×•×¨×“×Ē × ×›×Ą×™×", + "download_settings_description": "ניהול הגדרו×Ē ×”×§×Š×•×¨×•×Ē ×œ×”×•×¨×“×Ē ×Ēמונו×Ē", "download_started": "הורדה החלה", "download_sucess": "ה×Ļלח×Ē ×”×•×¨×“×”", "download_sucess_android": "המדיה הורדה אל DCIM/Immich", "download_waiting_to_retry": "מחכה כדי לנסו×Ē ×Š×•×‘", "downloading": "מוריד", - "downloading_asset_filename": "מוריד נכס {filename}", + "downloading_asset_filename": "מוריד ×Ēמונה {filename}", "downloading_media": "מוריד מדיה", "drop_files_to_upload": "שחרר קב×Ļים בכל מקום כדי לה×ĸלו×Ē", "duplicates": "כפילויו×Ē", @@ -809,7 +813,7 @@ "email": "דוא\"ל", "empty_folder": "×Ēיקיה זו ריקה", "empty_trash": "רוקן אשפה", - "empty_trash_confirmation": "האם באמ×Ē ×‘×¨×Ļונך לרוקן א×Ē ×”××Š×¤×”? זה יסיר ל×Ļמי×Ēו×Ē ××Ē ×›×œ הנכסים באשפה מImmich.\nאין באפשרו×Ēך לבטל פ×ĸולה זו!", + "empty_trash_confirmation": "האם באמ×Ē ×‘×¨×Ļונך לרוקן א×Ē ×”××Š×¤×”? זה יסיר ל×Ļמי×Ēו×Ē ××Ē ×›×œ ה×Ēמונו×Ē ×ž×”××Š×¤×” של השר×Ē.\nאין באפשרו×Ēך לבטל פ×ĸולה זו!", "enable": "אפ׊ר", "enabled": "מופ×ĸל", "end_date": "×Ēאריך סיום", @@ -817,42 +821,42 @@ "enter_wifi_name": "הזן ׊ם אינטרנט אלחוטי", "error": "שגיאה", "error_change_sort_album": "שינוי סדר מיון אלבום נכשל", - "error_delete_face": "שגיאה במחיק×Ē ×¤× ×™× מנכס", + "error_delete_face": "שגיאה במחיק×Ē ×¤× ×™× מ×Ēמונה", "error_loading_image": "שגיאה בט×ĸינ×Ē ×”×Ēמונה", "error_saving_image": "שגיאה: {}", "error_title": "שגיאה - משהו הש×Ēבש", "errors": { - "cannot_navigate_next_asset": "לא ני×Ēן לנווט לנכס הבא", - "cannot_navigate_previous_asset": "לא ני×Ēן לנווט לנכס הקודם", + "cannot_navigate_next_asset": "לא ני×Ēן לנווט ל×Ēמונה הבאה", + "cannot_navigate_previous_asset": "לא ני×Ēן לנווט ל×Ēמונה הקודמ×Ē", "cant_apply_changes": "לא ני×Ēן להחיל שינויים", "cant_change_activity": "לא ני×Ēן {enabled, select, true {להשבי×Ē} other {לאפשר}} פ×ĸילו×Ē", - "cant_change_asset_favorite": "לא ני×Ēן לשנו×Ē ×ž×Ļב מו×ĸדת ×ĸבור נכס", - "cant_change_metadata_assets_count": "לא ני×Ēן לשנו×Ē ××Ē ×”×ž×˜×-× ×Ēונים של {count, plural, one {נכס #} other {# נכסים}}", + "cant_change_asset_favorite": "לא ני×Ēן לשנו×Ē ×Ą×™×ž×•×Ÿ מו×ĸדת ×ĸבור ה×Ēמונה", + "cant_change_metadata_assets_count": "לא ני×Ēן לשנו×Ē ××Ē ×”×ž×˜×-× ×Ēונים של {count, plural, one {×Ēמונה #} other {# ×Ēמונו×Ē}}", "cant_get_faces": "לא ני×Ēן לקבל פנים", "cant_get_number_of_comments": "לא ני×Ēן לקבל א×Ē ×ž×Ą×¤×¨ ה×Ēגובו×Ē", "cant_search_people": "לא ני×Ēן לחפש אנשים", "cant_search_places": "לא ני×Ēן לחפש מקומו×Ē", "cleared_jobs": "משימו×Ē × ×•×§×• ×ĸבור: {job}", - "error_adding_assets_to_album": "שגיאה בהוספ×Ē × ×›×Ą×™× לאלבום", + "error_adding_assets_to_album": "שגיאה בהוספ×Ē ×Ēמונו×Ē ×œ××œ×‘×•×", "error_adding_users_to_album": "שגיאה בהוספ×Ē ×ž×Š×Ēמשים לאלבום", "error_deleting_shared_user": "שגיאה במחיק×Ē ×ž×Š×Ēמ׊ משו×Ē×Ŗ", "error_downloading": "שגיאה בהורד×Ē {filename}", "error_hiding_buy_button": "שגיאה בהס×Ēר×Ē ×œ×—×Ļן 'קנה'", - "error_removing_assets_from_album": "שגיאה בהסר×Ē × ×›×Ą×™× מאלבום, בדוק א×Ē ×”×ž×Ą×•×Ŗ לפרטים נוספים", - "error_selecting_all_assets": "שגיאה בבחיר×Ē ×›×œ הנכסים", + "error_removing_assets_from_album": "שגיאה בהסר×Ē ×Ēמונו×Ē ×ž×”××œ×‘×•×, בדוק א×Ē ×”×™×•×ž× ×™× לפרטים נוספים", + "error_selecting_all_assets": "שגיאה בבחיר×Ē ×›×œ ה×Ēמונו×Ē", "exclusion_pattern_already_exists": "דפוס החרגה זה כבר קיים.", "failed_job_command": "הפקודה {command} נכשלה ×ĸבור המשימה: â€Ēâ€Ē{job}", "failed_to_create_album": "י×Ļיר×Ē ××œ×‘×•× נכשלה", "failed_to_create_shared_link": "י×Ļיר×Ē ×§×™×Š×•×¨ משו×Ē×Ŗ נכשלה", "failed_to_edit_shared_link": "×ĸריכ×Ē ×§×™×Š×•×¨ משו×Ē×Ŗ נכשלה", "failed_to_get_people": "קבל×Ē ×× ×Š×™× נכשלה", - "failed_to_keep_this_delete_others": "נכשל לשמור א×Ē ×”× ×›×Ą הזה ולמחוק א×Ē ×”× ×›×Ą×™× האחרים", - "failed_to_load_asset": "ט×ĸינ×Ē × ×›×Ą נכשלה", - "failed_to_load_assets": "ט×ĸינ×Ē × ×›×Ą×™× נכשלה", + "failed_to_keep_this_delete_others": "הפ×ĸולה נכשלה לא ני×Ēן היה לשמור א×Ē ×”×Ēמונה הזו ולמחוק א×Ē ×Š××¨ ה×Ēמונו×Ē", + "failed_to_load_asset": "ט×ĸינ×Ē ×”×Ēמונה נכשלה", + "failed_to_load_assets": "ט×ĸינ×Ē ×”×Ēמונו×Ē × ×›×Š×œ×”", "failed_to_load_people": "נכשל באחזור אנשים", "failed_to_remove_product_key": "הסר×Ē ×ž×¤×Ēח מו×Ļר נכשלה", - "failed_to_stack_assets": "י×Ļיר×Ē ×ĸרימ×Ē × ×›×Ą×™× נכשלה", - "failed_to_unstack_assets": "ביטול ×ĸרימ×Ē × ×›×Ą×™× נכשל", + "failed_to_stack_assets": "י×Ļיר×Ē ×ĸרימ×Ē ×Ēמונו×Ē × ×›×Š×œ×”", + "failed_to_unstack_assets": "ביטול ×ĸרימ×Ē ×Ēמונו×Ē × ×›×Š×œ×”", "import_path_already_exists": "× ×Ēיב הייבוא הזה כבר קיים.", "incorrect_email_or_password": "דוא\"ל או סיסמה שגויים", "paths_validation_failed": "{paths, plural, one {× ×Ēיב # נכשל} other {# × ×Ēיבים נכשלו}} אימו×Ē", @@ -860,17 +864,17 @@ "quota_higher_than_disk_size": "הגדר×Ē ×ž×›×Ą×” גבוהה יו×Ēר מגודל הדיסק", "repair_unable_to_check_items": "לא ני×Ēן לסמן {count, select, one {פריט} other {פריטים}}", "unable_to_add_album_users": "לא ני×Ēן ×œ×”×•×Ą×™×Ŗ מ׊×Ēמשים לאלבום", - "unable_to_add_assets_to_shared_link": "לא ני×Ēן ×œ×”×•×Ą×™×Ŗ נכסים לקישור משו×Ē×Ŗ", + "unable_to_add_assets_to_shared_link": "לא ני×Ēן ×œ×”×•×Ą×™×Ŗ ×Ēמונו×Ē ×œ×§×™×Š×•×¨ משו×Ē×Ŗ", "unable_to_add_comment": "לא ני×Ēן ×œ×”×•×Ą×™×Ŗ ×Ēגובה", "unable_to_add_exclusion_pattern": "לא ני×Ēן ×œ×”×•×Ą×™×Ŗ דפוס החרגה", "unable_to_add_import_path": "לא ני×Ēן ×œ×”×•×Ą×™×Ŗ × ×Ēיב ייבוא", "unable_to_add_partners": "לא ני×Ēן ×œ×”×•×Ą×™×Ŗ שו×Ēפים", - "unable_to_add_remove_archive": "לא ני×Ēן {archived, select, true {להסיר נכס מ} other {×œ×”×•×Ą×™×Ŗ נכס ל}}ארכיון", - "unable_to_add_remove_favorites": "לא ני×Ēן {favorite, select, true {×œ×”×•×Ą×™×Ŗ נכס ל} other {להסיר נכס מ}}מו×ĸדפים", + "unable_to_add_remove_archive": "לא ני×Ēן {archived, select, true {להסיר ×Ēמונה מ} other {×œ×”×•×Ą×™×Ŗ ×Ēמונה ל}}ארכיון", + "unable_to_add_remove_favorites": "לא ני×Ēן {favorite, select, true {×œ×”×•×Ą×™×Ŗ ×Ēמונה ל} other {להסיר ×Ēמונה מ}}מו×ĸדפים", "unable_to_archive_unarchive": "לא ני×Ēן {archived, select, true {לה×ĸביר לארכיון} other {להו×Ļיא מארכיון}}", "unable_to_change_album_user_role": "לא ני×Ēן לשנו×Ē ××Ē ×”×Ēפקיד של מ׊×Ēמ׊ האלבום", "unable_to_change_date": "לא ני×Ēן לשנו×Ē ×Ēאריך", - "unable_to_change_favorite": "לא ני×Ēן לשנו×Ē ×ž×Ļב מו×ĸדת ×ĸבור נכס", + "unable_to_change_favorite": "לא ני×Ēן לשנו×Ē ×ž×Ļב מו×ĸדת ×ĸבור ה×Ēמונה", "unable_to_change_location": "לא ני×Ēן לשנו×Ē ×ž×™×§×•×", "unable_to_change_password": "לא ני×Ēן לשנו×Ē ×Ą×™×Ą×ž×”", "unable_to_change_visibility": "לא ני×Ēן לשנו×Ē ××Ē ×”× ×¨××•×Ē ×ĸבור {count, plural, one {אדם #} other {# אנשים}}", @@ -883,8 +887,8 @@ "unable_to_create_library": "לא ני×Ēן לי×Ļור ספרייה", "unable_to_create_user": "לא ני×Ēן לי×Ļור מ׊×Ēמ׊", "unable_to_delete_album": "לא ני×Ēן למחוק אלבום", - "unable_to_delete_asset": "לא ני×Ēן למחוק נכס", - "unable_to_delete_assets": "שגיאה במחיק×Ē × ×›×Ą×™×", + "unable_to_delete_asset": "לא ני×Ēן למחוק א×Ē ×”×Ēמונה", + "unable_to_delete_assets": "שגיאה במחיק×Ē ×”×Ēמונו×Ē", "unable_to_delete_exclusion_pattern": "לא ני×Ēן למחוק דפוס החרגה", "unable_to_delete_import_path": "לא ני×Ēן למחוק א×Ē × ×Ēיב הייבוא", "unable_to_delete_shared_link": "לא ני×Ēן למחוק קישור משו×Ē×Ŗ", @@ -901,19 +905,19 @@ "unable_to_link_motion_video": "לא ני×Ēן לקשר סרטון ×Ēנו×ĸה", "unable_to_link_oauth_account": "לא ני×Ēן לקשר חשבון OAuth", "unable_to_load_album": "לא ני×Ēן לט×ĸון אלבום", - "unable_to_load_asset_activity": "לא ני×Ēן לט×ĸון א×Ē ×¤×ĸילו×Ē ×”× ×›×Ą", + "unable_to_load_asset_activity": "לא ני×Ēן לט×ĸון א×Ē ×”×¤×ĸילו×Ē ×‘×Ēמונה", "unable_to_load_items": "לא ני×Ēן לט×ĸון פריטים", "unable_to_load_liked_status": "לא ני×Ēן לט×ĸון מ×Ļב 'אהב×Ēי'", "unable_to_log_out_all_devices": "לא ני×Ēן לנ×Ē×§ א×Ē ×›×œ המכשירים", "unable_to_log_out_device": "לא ני×Ēן לנ×Ē×§ מכשיר", "unable_to_login_with_oauth": "לא ני×Ēן לה×Ēחבר באמ×Ļ×ĸו×Ē OAuth", "unable_to_play_video": "לא ני×Ēן לנגן סרטון", - "unable_to_reassign_assets_existing_person": "לא ני×Ēן להק×Ļו×Ē ×ž×—×“×Š נכסים ל{name, select, null {אדם קיים} other {{name}}}", - "unable_to_reassign_assets_new_person": "לא ני×Ēן להק×Ļו×Ē ×ž×—×“×Š נכסים לאדם חדש", + "unable_to_reassign_assets_existing_person": "לא ני×Ēן להק×Ļו×Ē ×ž×—×“×Š ×Ēמונו×Ē ×œ{name, select, null {אדם קיים} other {{name}}}", + "unable_to_reassign_assets_new_person": "לא ני×Ēן להק×Ļו×Ē ×ž×—×“×Š ×Ēמונו×Ē ×œ××“× חדש", "unable_to_refresh_user": "לא ני×Ēן לר×ĸנן א×Ē ×”×ž×Š×Ēמ׊", "unable_to_remove_album_users": "לא ני×Ēן להסיר מ׊×Ēמשים מהאלבום", "unable_to_remove_api_key": "לא ני×Ēן להסיר מפ×Ēח API", - "unable_to_remove_assets_from_shared_link": "לא ני×Ēן להסיר נכסים מקישור משו×Ē×Ŗ", + "unable_to_remove_assets_from_shared_link": "לא ני×Ēן להסיר ×Ēמונו×Ē ×ž×§×™×Š×•×¨ משו×Ē×Ŗ", "unable_to_remove_deleted_assets": "לא ני×Ēן להסיר קב×Ļים לא מקוונים", "unable_to_remove_library": "לא ני×Ēן להסיר ספרייה", "unable_to_remove_partner": "לא ני×Ēן להסיר שו×Ē×Ŗ", @@ -921,7 +925,7 @@ "unable_to_repair_items": "לא ני×Ēן ל×Ēקן פריטים", "unable_to_reset_password": "לא ני×Ēן לאפס סיסמה", "unable_to_resolve_duplicate": "לא ני×Ēן לפ×Ēור כפילו×Ē", - "unable_to_restore_assets": "לא ני×Ēן לשחזר נכסים", + "unable_to_restore_assets": "לא ני×Ēן לשחזר ×Ēמונו×Ē", "unable_to_restore_trash": "לא ני×Ēן לשחזר אשפה", "unable_to_restore_user": "לא ני×Ēן לשחזר מ׊×Ēמ׊", "unable_to_save_album": "לא ני×Ēן לשמור אלבום", @@ -935,7 +939,7 @@ "unable_to_set_feature_photo": "לא ני×Ēן להגדיר ×Ēמונה מיי×Ļג×Ē", "unable_to_set_profile_picture": "לא ני×Ēן להגדיר ×Ēמונ×Ē ×¤×¨×•×¤×™×œ", "unable_to_submit_job": "לא ני×Ēן לשלוח משימה", - "unable_to_trash_asset": "לא ני×Ēן לה×ĸביר נכס לאשפה", + "unable_to_trash_asset": "לא ני×Ēן לה×ĸביר ×Ēמונה לאשפה", "unable_to_unlink_account": "לא ני×Ēן לבטל קישור חשבון", "unable_to_unlink_motion_video": "לא ני×Ēן לבטל קישור סרטון ×Ēנו×ĸה", "unable_to_update_album_cover": "לא ני×Ēן ל×ĸדכן ×ĸטיפ×Ē ××œ×‘×•×", @@ -955,7 +959,7 @@ "exif_bottom_sheet_person_add_person": "×”×•×Ą×Ŗ ׊ם", "exif_bottom_sheet_person_age": "גיל {}", "exif_bottom_sheet_person_age_months": "גיל {} חודשים", - "exif_bottom_sheet_person_age_year_months": "גיל שנה, {} חודשים", + "exif_bottom_sheet_person_age_year_months": "גיל שנה ו-{} חודשים", "exif_bottom_sheet_person_age_years": "גיל {}", "exit_slideshow": "×Ļא ממ×Ļג×Ē ×Š×§×•×¤×™×•×Ē", "expand_all": "הרחב הכל", @@ -977,12 +981,12 @@ "external_network_sheet_info": "כאשר לא ×ĸל ר׊×Ē ×”××™× ×˜×¨× ×˜ האלחוטי המו×ĸדפ×Ē, היישום י×Ēחבר לשר×Ē ×“×¨×š הכ×Ēוב×Ē ×”×¨××Š×•× ×” שני×Ēן להשיג מהכ×Ēובו×Ē ×Š×œ×”×œ×Ÿ, החל מלמ×ĸלה למטה", "face_unassigned": "לא מוק×Ļה", "failed": "נכשלו", - "failed_to_load_assets": "ט×ĸינ×Ē × ×›×Ą×™× נכשלה", + "failed_to_load_assets": "ט×ĸינ×Ē ×Ēמונו×Ē × ×›×Š×œ×”", "failed_to_load_folder": "ט×ĸינ×Ē ×Ēיקיה נכשלה", "favorite": "מו×ĸדת", "favorite_or_unfavorite_photo": "×”×•×Ą×Ŗ או הסר ×Ēמונה מהמו×ĸדפים", "favorites": "מו×ĸדפים", - "favorites_page_no_favorites": "לא נמ×Ļאו נכסים מו×ĸדפים", + "favorites_page_no_favorites": "לא נמ×Ļאו ×Ēמונו×Ē ×ž×•×ĸדפים", "feature_photo_updated": "×Ēמונה מיי×Ļג×Ē ×ĸודכנה", "features": "×Ēכונו×Ē", "features_setting_description": "ניהול ×Ēכונו×Ē ×”×™×™×Š×•×", @@ -992,6 +996,7 @@ "filetype": "סוג קוב×Ĩ", "filter": "סנן", "filter_people": "סנן אנשים", + "filter_places": "סינון מקומו×Ē", "find_them_fast": "מ×Ļא או×Ēם מהר לפי ׊ם ×ĸם חיפוש", "fix_incorrect_match": "×Ēקן ה×Ēאמה שגויה", "folder": "×Ēיקיה", @@ -1029,24 +1034,24 @@ "hide_password": "הס×Ēר סיסמה", "hide_person": "הס×Ēר אדם", "hide_unnamed_people": "הס×Ēר אנשים ללא ׊ם", - "home_page_add_to_album_conflicts": "{added} נכסים נוספו לאלבום {album}. {failed} נכסים כבר נמ×Ļאים באלבום", - "home_page_add_to_album_err_local": "לא ני×Ēן ×œ×”×•×Ą×™×Ŗ נכסים מקומיים לאלבום ×ĸדיין, מדלג", - "home_page_add_to_album_success": "{added} נכסים נוספו לאלבום {album}", - "home_page_album_err_partner": "לא ני×Ēן ×œ×”×•×Ą×™×Ŗ נכסי שו×Ē×Ŗ לאלבום ×ĸדיין, מדלג", - "home_page_archive_err_local": "לא ני×Ēן לה×ĸביר לארכיון נכסים מקומיים ×ĸדיין, מדלג", - "home_page_archive_err_partner": "לא ני×Ēן לה×ĸביר לארכיון נכסי שו×Ē×Ŗ, מדלג", + "home_page_add_to_album_conflicts": "{added} ×Ēמונו×Ē × ×•×Ą×¤×• לאלבום {album}. {failed} ×Ēמונו×Ē ×›×‘×¨ נמ×Ļאו×Ē ×‘××œ×‘×•×.", + "home_page_add_to_album_err_local": "לא ני×Ēן ×œ×”×•×Ą×™×Ŗ ×Ēמונו×Ē ×ž×§×•×ž×™×•×Ē ×œ××œ×‘×•× ×ĸדיין, מדלג", + "home_page_add_to_album_success": "{added} ×Ēמונו×Ē × ×•×Ą×¤×• לאלבום {album}.", + "home_page_album_err_partner": "לא ני×Ēן ×œ×”×•×Ą×™×Ŗ ×Ēמונ×Ē ×Š×•×Ē×Ŗ לאלבום ×ĸדיין, מדלג", + "home_page_archive_err_local": "לא ני×Ēן לה×ĸביר לארכיון ×Ēמונו×Ē ×ž×§×•×ž×™×•×Ē ×ĸדיין, מדלג", + "home_page_archive_err_partner": "לא ני×Ēן לה×ĸביר לארכיון ×Ēמונו×Ē ×Š×œ השו×Ē×Ŗ, מדלג", "home_page_building_timeline": "בונה א×Ē ×Ļיר הזמן", - "home_page_delete_err_partner": "לא ני×Ēן למחוק נכסי שו×Ē×Ŗ, מדלג", - "home_page_delete_remote_err_local": "נכסים מקומיים נבחרו מרחוק למחיקה, מדלג", - "home_page_favorite_err_local": "לא ני×Ēן ×œ×”×•×Ą×™×Ŗ למו×ĸדפים נכסים מקומיים ×ĸדיין, מדלג", - "home_page_favorite_err_partner": "לא ני×Ēן ×œ×”×•×Ą×™×Ŗ למו×ĸדפים נכסי שו×Ē×Ŗ ×ĸדיין, מדלג", + "home_page_delete_err_partner": "לא ני×Ēן למחוק ×Ēמונו×Ē ×Š×œ השו×Ē×Ŗ, מדלג", + "home_page_delete_remote_err_local": "×Ēמונו×Ē ×ž×§×•×ž×™×•×Ē × ×‘×—×¨×• מרחוק למחיקה, מדלג", + "home_page_favorite_err_local": "לא ני×Ēן ×œ×”×•×Ą×™×Ŗ למו×ĸדפים ×Ēמונו×Ē ×ž×§×•×ž×™×•×Ē ×ĸדיין, מדלג", + "home_page_favorite_err_partner": "לא ני×Ēן ×œ×”×•×Ą×™×Ŗ למו×ĸדפים ×Ēמונו×Ē ×Š×œ השו×Ē×Ŗ ×ĸדיין, מדלג", "home_page_first_time_notice": "אם זא×Ē ×”×¤×ĸם הראשונה ׊א×Ē/ה מ׊×Ēמ׊/×Ē ×‘×™×™×Š×•×, נא להקפיד לבחור אלבומ(ים) לגיבוי כך ׊×Ļיר הזמן יוכל לאכלס ×Ēמונו×Ē ×•×Ą×¨×˜×•× ×™× באלבומ(ים)", - "home_page_share_err_local": "לא ני×Ēן לש×Ē×Ŗ נכסים מקומיים ×ĸל ידי קישור, מדלג", - "home_page_upload_err_limit": "ני×Ēן לה×ĸלו×Ē ×¨×§ מקסימום של 30 נכסים בכל פ×ĸם, מדלג", + "home_page_share_err_local": "לא ני×Ēן לש×Ē×Ŗ ×Ēמונו×Ē ×ž×§×•×ž×™×•×Ē ×ĸל ידי קישור, מדלג", + "home_page_upload_err_limit": "ני×Ēן לה×ĸלו×Ē ×¨×§ מקסימום של 30 ×Ēמונו×Ē ×‘×›×œ פ×ĸם, מדלג", "host": "מארח", "hour": "׊×ĸה", "ignore_icloud_photos": "ה×Ē×ĸלם מ×Ēמונו×Ē iCloud", - "ignore_icloud_photos_description": "×Ēמונו×Ē ×Š×ž××•×—×Ą× ×•×Ē ×‘-iCloud לא יו×ĸלו לשר×Ē ×”-Immich", + "ignore_icloud_photos_description": "×Ēמונו×Ē ×Š×ž××•×—×Ą× ×•×Ē ×‘-iCloud לא יו×ĸלו לשר×Ē", "image": "×Ēמונה", "image_alt_text_date": "{isVideo, select, true {סרטון ׊×Ļולם} other {×Ēמונה ׊×Ļולמה}} ב-{date}", "image_alt_text_date_1_person": "{isVideo, select, true {סרטון ׊×Ļולם} other {×Ēמונה ׊×Ļולמה}} ×ĸם {person1} ב-{date}", @@ -1070,7 +1075,7 @@ "in_archive": "בארכיון", "include_archived": "כלול ארכיון", "include_shared_albums": "כלול אלבומים משו×Ēפים", - "include_shared_partner_assets": "כלול נכסי שו×Ē×Ŗ משו×Ēפים", + "include_shared_partner_assets": "כלול ×Ēמונו×Ē ×Š×Š×•×Ēפו ×ĸ\"י השו×Ē×Ŗ", "individual_share": "שי×Ēות יחיד", "individual_shares": "שי×Ēופים בודדים", "info": "מיד×ĸ", @@ -1089,7 +1094,7 @@ "keep": "שמור", "keep_all": "שמור הכל", "keep_this_delete_others": "שמור ×ĸל זה, מחק אחרים", - "kept_this_deleted_others": "נכס זה נ׊מר ונמחקו {count, plural, one {נכס #} other {# נכסים}}", + "kept_this_deleted_others": "×Ēמונה זו נשמרה ונמחקו {count, plural, one {×Ēמונה #} other {# ×Ēמונו×Ē}}", "keyboard_shortcuts": "קי×Ļורי מקלד×Ē", "language": "שפה", "language_setting_description": "בחר א×Ē ×”×Š×¤×” המו×ĸדפ×Ē ×ĸליך", @@ -1104,7 +1109,7 @@ "library_options": "אפשרויו×Ē ×Ą×¤×¨×™×™×”", "library_page_device_albums": "אלבומים במכשיר", "library_page_new_album": "אלבום חדש", - "library_page_sort_asset_count": "מספר נכסים", + "library_page_sort_asset_count": "מספר ×Ēמונו×Ē", "library_page_sort_created": "×Ēאריך י×Ļירה", "library_page_sort_last_modified": "שונה לאחרונה", "library_page_sort_title": "כו×Ēר×Ē ××œ×‘×•×", @@ -1132,7 +1137,7 @@ "logged_out_device": "מכשיר מנו×Ē×§", "login": "כניסה", "login_disabled": "כניסה למ×ĸרכ×Ē ×”×•×Š×‘×Ēה", - "login_form_api_exception": "חריג×Ē API. נא לבדוק א×Ē ×›×Ēוב×Ē ×”×Š×¨×Ē ×•×œ× ×Ą×•×Ē ×Š×•×‘", + "login_form_api_exception": "חריג×Ē API. נא לבדוק א×Ē ×›×Ēוב×Ē ×”×Š×¨×Ē ×•×œ× ×Ą×•×Ē ×Š×•×‘.", "login_form_back_button_text": "חזרה", "login_form_email_hint": "yourmail@email.com", "login_form_endpoint_hint": "http://your-server-ip:port", @@ -1145,11 +1150,11 @@ "login_form_failed_get_oauth_server_config": "שגיאה בה×Ēחברו×Ē ×‘××ž×Ļ×ĸו×Ē OAuth, בדוק א×Ē ×›×Ēוב×Ē ×”×Š×¨×Ē", "login_form_failed_get_oauth_server_disable": "×Ēכונ×Ē OAuth לא זמינה בשר×Ē ×–×”", "login_form_failed_login": "שגיאה בכניסה למ×ĸרכ×Ē, בדוק א×Ē ×›×Ēוב×Ē ×”×Š×¨×Ē, דוא\"ל וסיסמה", - "login_form_handshake_exception": "איר×ĸה חריג×Ē ×œ×—×™×Ļ×Ē ×™×“ ×ĸם השר×Ē. אפ׊ר ×Ēמיכה ב×Ē×ĸודה בח×Ēימה ×ĸ×Ļמי×Ē ×‘×”×’×“×¨×•×Ē ×× א×Ē/ה מ׊×Ēמ׊/×Ē ×‘×Ē×ĸודה בח×Ēימה ×ĸ×Ļמי×Ē", + "login_form_handshake_exception": "איר×ĸה חריגה ב×ĸ×Ē ×‘×™×Ļו×ĸ Handshake ×ĸם השר×Ē. אפ׊ר ×Ēמיכה ב×Ē×ĸודה בח×Ēימה ×ĸ×Ļמי×Ē ×‘×”×’×“×¨×•×Ē ×× א×Ē/ה מ׊×Ēמ׊/×Ē ×‘×Ē×ĸודה בח×Ēימה ×ĸ×Ļמי×Ē.", "login_form_password_hint": "סיסמה", "login_form_save_login": "הישאר/י מחובר/×Ē", - "login_form_server_empty": "הכנס כ×Ēוב×Ē ×Š×¨×Ē", - "login_form_server_error": "לא היה ני×Ēן לה×Ēחבר לשר×Ē", + "login_form_server_empty": "הכנס כ×Ēוב×Ē ×Š×¨×Ē.", + "login_form_server_error": "לא היה ני×Ēן לה×Ēחבר לשר×Ē.", "login_has_been_disabled": "הכניסה הושב×Ēה.", "login_password_changed_error": "היי×Ēה שגיאה ב×ĸדכון הסיסמה שלך", "login_password_changed_success": "סיסמה ×ĸודכנה בה×Ļלחה", @@ -1170,24 +1175,24 @@ "manage_your_devices": "ניהול המכשירים המחוברים שלך", "manage_your_oauth_connection": "ניהול חיבור ה-OAuth שלך", "map": "מפה", - "map_assets_in_bound": "{} ×Ēמונה", + "map_assets_in_bound": "×Ēמונה {}", "map_assets_in_bounds": "{} ×Ēמונו×Ē", "map_cannot_get_user_location": "לא ני×Ēן לקבל א×Ē ×ž×™×§×•× המש×Ēמ׊", "map_location_dialog_yes": "כן", "map_location_picker_page_use_location": "הש×Ēמ׊ במיקום הזה", - "map_location_service_disabled_content": "שירו×Ē ×ž×™×§×•× ×Ļריך להיו×Ē ×ž×•×¤×ĸל כדי לה×Ļיג נכסים מהמיקום הנוכחי שלך. האם בר×Ļונך להפ×ĸיל או×Ēו ×ĸכשיו?", + "map_location_service_disabled_content": "שירו×Ē ×”×ž×™×§×•× ×Ļריך להיו×Ē ×ž×•×¤×ĸל כדי לה×Ļיג ×Ēמונו×Ē ×ž×”×ž×™×§×•× הנוכחי שלך. האם בר×Ļונך להפ×ĸיל או×Ēו ×ĸכשיו?", "map_location_service_disabled_title": "שירו×Ē ×ž×™×§×•× מבוטל", "map_marker_for_images": "סמן מפה ל×Ēמונו×Ē ×Š×Ļולמו ב{city}, {country}", "map_marker_with_image": "סמן מפה ×ĸם ×Ēמונה", "map_no_assets_in_bounds": "אין ×Ēמונו×Ē ×‘××–×•×¨ זה", - "map_no_location_permission_content": "יש ×Ļורך בהרשאה למיקום כדי לה×Ļיג נכסים מהמיקום הנוכחי שלך. האם בר×Ļונך לאפשר זא×Ē ×ĸכשיו?", + "map_no_location_permission_content": "יש ×Ļורך בהרשאה למיקום כדי לה×Ļיג ×Ēמונו×Ē ×ž×”×ž×™×§×•× הנוכחי שלך. האם בר×Ļונך לאפשר זא×Ē ×ĸכשיו?", "map_no_location_permission_title": "הרשאה למיקום נדח×Ēה", "map_settings": "הגדרו×Ē ×ž×¤×”", "map_settings_dark_mode": "מ×Ļב כהה", "map_settings_date_range_option_day": "24 ׊×ĸו×Ē ××—×¨×•× ×•×Ē", - "map_settings_date_range_option_days": "{} ימים אחרונים", + "map_settings_date_range_option_days": "ב-{} ימים אחרונים", "map_settings_date_range_option_year": "שנה אחרונה", - "map_settings_date_range_option_years": "{} שנים אחרונו×Ē", + "map_settings_date_range_option_years": "ב-{} שנים אחרונו×Ē", "map_settings_dialog_title": "הגדרו×Ē ×ž×¤×”", "map_settings_include_show_archived": "כלול ארכיון", "map_settings_include_show_partners": "כלול שו×Ēפים", @@ -1221,8 +1226,8 @@ "monthly_title_text_date_format": "MMMM y", "more": "×ĸוד", "moved_to_trash": "הו×ĸבר לאשפה", - "multiselect_grid_edit_date_time_err_read_only": "לא ני×Ēן ל×ĸרוך ×Ēאריך של נכס(ים) לקריאה בלבד, מדלג", - "multiselect_grid_edit_gps_err_read_only": "לא ני×Ēן ל×ĸרוך מיקום של נכס(ים) לקריאה בלבד, מדלג", + "multiselect_grid_edit_date_time_err_read_only": "לא ני×Ēן ל×ĸרוך ×Ēאריך של ×Ēמונו×Ē ×œ×§×¨×™××” בלבד, מדלג", + "multiselect_grid_edit_gps_err_read_only": "לא ני×Ēן ל×ĸרוך מיקום של ×Ēמונו×Ē ×œ×§×¨×™××” בלבד, מדלג", "mute_memories": "הש×Ē×§×Ē ×–×™×›×¨×•× ×•×Ē", "my_albums": "האלבומים שלי", "name": "׊ם", @@ -1245,7 +1250,7 @@ "no_albums_yet": "זה נראה שאין לך ×ĸדיין אלבומים.", "no_archived_assets_message": "ה×ĸבר ×Ēמונו×Ē ×•×Ą×¨×˜×•× ×™× לארכיון כדי להס×Ēיר או×Ēם מ×Ē×Ļוג×Ē ×”×Ēמונו×Ē ×Š×œ×š", "no_assets_message": "לח×Ĩ כדי לה×ĸלו×Ē ××Ē ×”×Ēמונה הראשונה שלך", - "no_assets_to_show": "אין נכסים לה×Ļיג", + "no_assets_to_show": "אין ×Ēמונו×Ē ×œ×”×Ļגה", "no_duplicates_found": "לא נמ×Ļאו כפילויו×Ē.", "no_exif_info_available": "אין מיד×ĸ זמין ×ĸל מטא-× ×Ēונים (exif)", "no_explore_results_message": "ה×ĸלה ×Ēמונו×Ē × ×•×Ą×¤×•×Ē ×›×“×™ לחקור א×Ē ×”××•×Ą×Ŗ שלך.", @@ -1258,17 +1263,17 @@ "no_shared_albums_message": "×Ļור אלבום כדי לש×Ē×Ŗ ×Ēמונו×Ē ×•×Ą×¨×˜×•× ×™× ×ĸם אנשים ברש×Ē ×Š×œ×š", "not_in_any_album": "לא בשום אלבום", "not_selected": "לא נבחרו", - "note_apply_storage_label_to_previously_uploaded assets": "ה×ĸרה: כדי להחיל א×Ē ×Ēווי×Ē ×”××—×Ą×•×Ÿ ×ĸל נכסים שהו×ĸלו ב×ĸבר, הפ×ĸל א×Ē", + "note_apply_storage_label_to_previously_uploaded assets": "ה×ĸרה: כדי להחיל א×Ē ×Ēווי×Ē ×”××—×Ą×•×Ÿ ×ĸל ×Ēמונו×Ē ×Š×”×•×ĸלו ב×ĸבר, הפ×ĸל א×Ē", "notes": "ה×ĸרו×Ē", - "notification_permission_dialog_content": "כדי לאפשר ה×Ēראו×Ē, לך להגדרו×Ē ×•×‘×—×¨ ה×Ēר", - "notification_permission_list_tile_content": "ה×ĸ× ×§ הרשאה כדי לאפשר ה×Ēראו×Ē", + "notification_permission_dialog_content": "כדי לאפשר ה×Ēראו×Ē, לך להגדרו×Ē ×”×ž×›×Š×™×¨ ובחר אפ׊ר.", + "notification_permission_list_tile_content": "ה×ĸ× ×§ הרשאה כדי לאפשר ה×Ēראו×Ē.", "notification_permission_list_tile_enable_button": "אפ׊ר ה×Ēראו×Ē", "notification_permission_list_tile_title": "הרשא×Ē ×”×Ēראה", "notification_toggle_setting_description": "אפ׊ר ה×Ēראו×Ē ×“×•×\"ל", "notifications": "ה×Ēראו×Ē", "notifications_setting_description": "ניהול ה×Ēראו×Ē", "oauth": "OAuth", - "official_immich_resources": "משאבי Immich רשמיים", + "official_immich_resources": "מקורו×Ē ×¨×Š×ž×™×™× של Immich", "offline": "לא מקוון", "offline_paths": "× ×Ēיבים לא מקוונים", "offline_paths_description": "×Ēו×Ļאו×Ē ××œ×• ×ĸשויו×Ē ×œ×”×™×•×Ē ×ĸקב מחיקה ידני×Ē ×Š×œ קב×Ļים שאינם חלק מספרייה חי×Ļוני×Ē.", @@ -1282,6 +1287,7 @@ "onboarding_welcome_user": "ברוך בואך, {user}", "online": "מקוון", "only_favorites": "רק מו×ĸדפים", + "open": "פ×Ēח", "open_in_map_view": "פ×Ēח ב×Ē×Ļוג×Ē ×ž×¤×”", "open_in_openstreetmap": "פ×Ēח ב-OpenStreetMap", "open_the_search_filters": "פ×Ēח א×Ē ×ž×Ą× × ×™ החיפוש", @@ -1300,12 +1306,12 @@ "partner_can_access_location": "המיקום שבו ×Ļולמו ה×Ēמונו×Ē ×Š×œ×š", "partner_list_user_photos": "×Ēמונו×Ē ×Š×œ {user}", "partner_list_view_all": "ה×Ļג הכל", - "partner_page_empty_message": "ה×Ēמונו×Ē ×Š×œ×š ×ĸדיין לא משו×Ēפו×Ē ×ĸם את שו×Ē×Ŗ", + "partner_page_empty_message": "ה×Ēמונו×Ē ×Š×œ×š ×ĸדיין לא משו×Ēפו×Ē ×ĸם את שו×Ē×Ŗ.", "partner_page_no_more_users": "אין ×ĸוד מ׊×Ēמשים ×œ×”×•×Ą×™×Ŗ", "partner_page_partner_add_failed": "הוספ×Ē ×Š×•×Ē×Ŗ נכשלה", "partner_page_select_partner": "בחיר×Ē ×Š×•×Ē×Ŗ", "partner_page_shared_to_title": "משו×Ē×Ŗ ×ĸם", - "partner_page_stop_sharing_content": "{} לא יוכל יו×Ēר לגש×Ē ×œ×Ēמונו×Ē ×Š×œ×š", + "partner_page_stop_sharing_content": "{} לא יוכל יו×Ēר לגש×Ē ×œ×Ēמונו×Ē ×Š×œ×š.", "partner_sharing": "שי×Ēות שו×Ēפים", "partners": "שו×Ēפים", "password": "סיסמה", @@ -1328,20 +1334,20 @@ "people_feature_description": "×ĸיון ב×Ēמונו×Ē ×•×Ą×¨×˜×•× ×™× שקוב×Ļו ×ĸל ידי אנשים", "people_sidebar_description": "ה×Ļג קישור אל אנשים בסרגל ה×Ļד", "permanent_deletion_warning": "אזהר×Ē ×ž×—×™×§×” ל×Ļמי×Ēו×Ē", - "permanent_deletion_warning_setting_description": "ה×Ļג אזהרה ב×ĸ×Ē ×ž×—×™×§×Ē × ×›×Ą×™× ל×Ļמי×Ēו×Ē", + "permanent_deletion_warning_setting_description": "ה×Ļג אזהרה ב×ĸ×Ē ×ž×—×™×§×Ē ×Ēמונו×Ē ×œ×Ļמי×Ēו×Ē", "permanently_delete": "מחק ל×Ļמי×Ēו×Ē", - "permanently_delete_assets_count": "מחק ל×Ļמי×Ēו×Ē {count, plural, one {נכס} other {נכסים}}", - "permanently_delete_assets_prompt": "האם באמ×Ē ×‘×¨×Ļונך למחוק ל×Ļמי×Ēו×Ē {count, plural, one {נכס זה?} other {# נכסים אלה?}}זה גם יסיר {count, plural, one {או×Ēו מאלבומו} other {או×Ēם מאלבומם}}.", - "permanently_deleted_asset": "נכס נמחק ל×Ļמי×Ēו×Ē", - "permanently_deleted_assets_count": "{count, plural, one {נכס # נמחק} other {# נכסים נמחקו}} ל×Ļמי×Ēו×Ē", + "permanently_delete_assets_count": "מחק ל×Ļמי×Ēו×Ē {count, plural, one {×Ēמונה} other {×Ēמונו×Ē}}", + "permanently_delete_assets_prompt": "האם באמ×Ē ×‘×¨×Ļונך למחוק ל×Ļמי×Ēו×Ē {count, plural, one {×Ēמונה זא×Ē?} other {# ×Ēמונו×Ē ××œ×•?}}זה גם יסיר {count, plural, one {או×Ēו מאלבומו} other {או×Ēם מאלבומים}}.", + "permanently_deleted_asset": "ה×Ēמונה נמחקה ל×Ļמי×Ēו×Ē", + "permanently_deleted_assets_count": "{count, plural, one {×Ēמונה # נמחקה} other {# ×Ēמונו×Ē × ×ž×—×§×•}} ל×Ļמי×Ēו×Ē", "permission_onboarding_back": "חזרה", "permission_onboarding_continue_anyway": "המשך בכל זא×Ē", "permission_onboarding_get_started": "לה×Ēחיל", "permission_onboarding_go_to_settings": "לך להגדרו×Ē", - "permission_onboarding_permission_denied": "הרשאה נדח×Ēה. כדי להש×Ēמ׊ ביישום, ה×ĸ× ×§ הרשאה ל×Ēמונו×Ē ×•×Ą×¨×˜×•× ×™× בהגדרו×Ē", - "permission_onboarding_permission_granted": "ההרשאה ני×Ēנה! א×Ē/ה מוכנ/ה", - "permission_onboarding_permission_limited": "הרשאה מוגבל×Ē. כדי ל×Ē×Ē ×œ×™×™×Š×•× לגבו×Ē ×•×œ× ×”×œ א×Ē ×›×œ ××•×Ą×Ŗ הגלריה שלך, ה×ĸ× ×§ הרשאה ל×Ēמונו×Ē ×•×Ą×¨×˜×•× ×™× בהגדרו×Ē", - "permission_onboarding_request": "היישום דורש הרשאה כדי לראו×Ē ××Ē ×”×Ēמונו×Ē ×•×”×Ą×¨×˜×•× ×™× שלך", + "permission_onboarding_permission_denied": "הרשאה נדח×Ēה. כדי להש×Ēמ׊ ביישום, ה×ĸ× ×§ הרשאה ל×Ēמונו×Ē ×•×Ą×¨×˜×•× ×™× בהגדרו×Ē.", + "permission_onboarding_permission_granted": "ההרשאה ני×Ēנה! הכל מוכן.", + "permission_onboarding_permission_limited": "הרשאה מוגבל×Ē. כדי ל×Ē×Ē ×œ×™×™×Š×•× לגבו×Ē ×•×œ× ×”×œ א×Ē ×›×œ ××•×Ą×Ŗ הגלריה שלך, ה×ĸ× ×§ הרשאה ל×Ēמונו×Ē ×•×Ą×¨×˜×•× ×™× בהגדרו×Ē.", + "permission_onboarding_request": "היישום דורש הרשאה כדי לראו×Ē ××Ē ×”×Ēמונו×Ē ×•×”×Ą×¨×˜×•× ×™× שלך.", "person": "אדם", "person_birthdate": "נולד ב×Ēאריך {date}", "person_hidden": "{name}{hidden, select, true { (מוס×Ēר)} other {}}", @@ -1369,12 +1375,12 @@ "primary": "ראשי", "privacy": "פרטיו×Ē", "profile_drawer_app_logs": "יומן", - "profile_drawer_client_out_of_date_major": "האפליק×Ļיה לנייד היא מיושנ×Ē. נא ל×ĸדכן לגרסה הראשי×Ē ×”××—×¨×•× ×”", - "profile_drawer_client_out_of_date_minor": "האפליק×Ļיה לנייד היא מיושנ×Ē. נא ל×ĸדכן לגרסה המשני×Ē ×”××—×¨×•× ×”", + "profile_drawer_client_out_of_date_major": "גרס×Ē ×”×™×™×Š×•× לנייד מיושנ×Ē. נא ל×ĸדכן לגרסה הראשי×Ē ×”××—×¨×•× ×”.", + "profile_drawer_client_out_of_date_minor": "גרס×Ē ×”×™×™×Š×•× לנייד מיושנ×Ē. נא ל×ĸדכן לגרסה המשני×Ē ×”××—×¨×•× ×”.", "profile_drawer_client_server_up_to_date": "הלקוח והשר×Ē ×”× מ×ĸודכנים", "profile_drawer_github": "GitHub", - "profile_drawer_server_out_of_date_major": "השר×Ē ××™× ×• מ×ĸודכן. נא ל×ĸדכן לגרסה הראשי×Ē ×”××—×¨×•× ×”", - "profile_drawer_server_out_of_date_minor": "השר×Ē ××™× ×• מ×ĸודכן. נא ל×ĸדכן לגרסה המשני×Ē ×”××—×¨×•× ×”", + "profile_drawer_server_out_of_date_major": "השר×Ē ××™× ×• מ×ĸודכן. נא ל×ĸדכן לגרסה הראשי×Ē ×”××—×¨×•× ×”.", + "profile_drawer_server_out_of_date_minor": "השר×Ē ××™× ×• מ×ĸודכן. נא ל×ĸדכן לגרסה המשני×Ē ×”××—×¨×•× ×”.", "profile_image_of_user": "×Ēמונ×Ē ×¤×¨×•×¤×™×œ של {user}", "profile_picture_set": "×Ēמונ×Ē ×¤×¨×•×¤×™×œ נבחרה.", "public_album": "אלבום ×Ļיבורי", @@ -1418,9 +1424,9 @@ "reaction_options": "אפשרויו×Ē ×”×’×‘×”", "read_changelog": "קרא א×Ē ×™×•×ž×Ÿ השינויים", "reassign": "הק×Ļה מחדש", - "reassigned_assets_to_existing_person": "{count, plural, one {נכס # הוק×Ļה} other {# נכסים הוק×Ļו}} מחדש אל {name, select, null {אדם קיים} other {{name}}}", - "reassigned_assets_to_new_person": "{count, plural, one {נכס # הוק×Ļה} other {# נכסים הוק×Ļו}} מחדש לאדם חדש", - "reassing_hint": "הק×Ļה נכסים שנבחרו לאדם קיים", + "reassigned_assets_to_existing_person": "{count, plural, one {×Ēמונה # הוק×Ļ×Ēה} other {# ×Ēמונו×Ē ×”×•×§×Ļו}} מחדש אל {name, select, null {אדם קיים} other {{name}}}", + "reassigned_assets_to_new_person": "{count, plural, one {×Ēמונה # הוק×Ļ×Ēה} other {# ×Ēמונו×Ē ×”×•×§×Ļו}} מחדש לאדם חדש", + "reassing_hint": "הק×Ļה ×Ēמונו×Ē ×Š× ×‘×—×¨×• לאדם קיים", "recent": "חדש", "recent-albums": "אלבומים אחרונים", "recent_searches": "חיפושים אחרונים", @@ -1438,9 +1444,9 @@ "refreshing_metadata": "מר×ĸנן מטא-× ×Ēונים", "regenerating_thumbnails": "מחדש ×Ēמונו×Ē ×ž×ž×•×–×ĸרו×Ē", "remove": "הסר", - "remove_assets_album_confirmation": "האם באמ×Ē ×‘×¨×Ļונך להסיר {count, plural, one {נכס #} other {# נכסים}} מהאלבום?", - "remove_assets_shared_link_confirmation": "האם באמ×Ē ×‘×¨×Ļונך להסיר {count, plural, one {נכס #} other {# נכסים}} מהקישור המשו×Ē×Ŗ הזה?", - "remove_assets_title": "הסר נכסים?", + "remove_assets_album_confirmation": "האם באמ×Ē ×‘×¨×Ļונך להסיר {count, plural, one {×Ēמונה #} other {# ×Ēמונו×Ē}} מהאלבום?", + "remove_assets_shared_link_confirmation": "האם א×Ēה בטוח שבר×Ļונך להסיר {count, plural, one {×Ēמונה #} other {# ×Ēמונו×Ē}} מהקישור המשו×Ē×Ŗ הזה?", + "remove_assets_title": "להסיר ×Ēמונו×Ē?", "remove_custom_date_range": "הסר טווח ×Ēאריכים מו×Ēאם", "remove_deleted_assets": "הסר קב×Ļים לא מקוונים", "remove_from_album": "הסר מאלבום", @@ -1456,7 +1462,7 @@ "removed_from_favorites_count": "{count, plural, other {הוסרו #}} מהמו×ĸדפים", "removed_memory": "זיכרון הוסר", "removed_photo_from_memory": "ה×Ēמונה הוסרה מהזיכרון", - "removed_tagged_assets": "×Ēג הוסר מ{count, plural, one {נכס #} other {# נכסים}}", + "removed_tagged_assets": "×Ēג הוסר מ{count, plural, one {×Ēמונה #} other {# ×Ēמונו×Ē}}", "rename": "שנה ׊ם", "repair": "×Ēיקון", "repair_no_results_message": "קב×Ļים חסרי מ×ĸקב וחסרים יופי×ĸו כאן", @@ -1474,7 +1480,7 @@ "restore": "שחזר", "restore_all": "שחזר הכל", "restore_user": "שחזר מ׊×Ēמ׊", - "restored_asset": "נכס משוחזר", + "restored_asset": "ה×Ēמונה שוחזרה", "resume": "המשך", "retry_upload": "נסה שוב לה×ĸלו×Ē", "review_duplicates": "בדוק כפילויו×Ē", @@ -1540,7 +1546,7 @@ "search_result_page_new_search_hint": "חיפוש חדש", "search_settings": "הגדרו×Ē ×—×™×¤×•×Š", "search_state": "חיפוש מדינה...", - "search_suggestion_list_smart_search_hint_1": "חיפוש חכם מופ×ĸל כבריר×Ē ×ž×—×“×œ, כדי לחפש מטא-× ×Ēונים הש×Ēמ׊ ב×Ēחביר", + "search_suggestion_list_smart_search_hint_1": "חיפוש חכם מופ×ĸל כבריר×Ē ×ž×—×“×œ, כדי לחפש מטא-× ×Ēונים הש×Ēמ׊ ב×Ēחביר ", "search_suggestion_list_smart_search_hint_2": "×Ēנאי-החיפוש-שלך:m", "search_tags": "חיפוש ×Ēגים...", "search_timezone": "חיפוש אזור זמן...", @@ -1581,10 +1587,10 @@ "set_date_of_birth": "הגדר ×Ēאריך לידה", "set_profile_picture": "הגדר ×Ēמונ×Ē ×¤×¨×•×¤×™×œ", "set_slideshow_to_fullscreen": "הגדר מ×Ļג×Ē ×Š×§×•×¤×™×•×Ē ×œ×ž×Ą×š מלא", - "setting_image_viewer_help": "מ×Ļיג הפרטים טו×ĸן א×Ē ×”×Ēמונה הממוז×ĸר×Ē ×”×§×˜× ×” קודם, לאחר מכן טו×ĸן א×Ē ×”×Ē×Ļוגה המקדימה בגודל בינוני (אם מופ×ĸל×Ē), ×œ×‘×Ą×•×Ŗ טו×ĸן א×Ē ×”×ž×§×•×¨×™×Ē (אם מופ×ĸל×Ē)", - "setting_image_viewer_original_subtitle": "אפ׊ר לט×ĸון א×Ē ×”×Ēמונה המקורי×Ē ×‘×¨×–×œ×•×Ļיה מלאה (גדולה!). השב×Ē ×›×“×™ להקטין שימוש בנ×Ēונים (גם בשר×Ē ×•×’× בזיכרון המטמון שבמכשיר)", + "setting_image_viewer_help": "מ×Ļיג הפרטים טו×ĸן א×Ē ×”×Ēמונה הממוז×ĸר×Ē ×”×§×˜× ×” קודם, לאחר מכן טו×ĸן א×Ē ×”×Ē×Ļוגה המקדימה בגודל בינוני (אם מופ×ĸל), ×œ×‘×Ą×•×Ŗ טו×ĸן א×Ē ×”×ž×§×•×¨×™×Ē (אם מופ×ĸל).", + "setting_image_viewer_original_subtitle": "אפ׊ר לט×ĸון א×Ē ×”×Ēמונה המקורי×Ē ×‘×¨×–×œ×•×Ļיה מלאה (גדולה!). השב×Ē ×›×“×™ להקטין שימוש בנ×Ēונים (גם בשר×Ē ×•×’× בזיכרון המטמון שבמכשיר).", "setting_image_viewer_original_title": "ט×ĸן ×Ēמונה מקורי×Ē", - "setting_image_viewer_preview_subtitle": "אפ׊ר לט×ĸון ×Ēמונה ברזלו×Ļיה בינוני×Ē. השב×Ē ×›×“×™ או לט×ĸון א×Ē ×”×ž×§×•×¨×™×Ē ××• רק להש×Ēמ׊ ב×Ēמונה הממוז×ĸר×Ē", + "setting_image_viewer_preview_subtitle": "אפ׊ר לט×ĸון ×Ēמונה ברזלו×Ļיה בינוני×Ē. השב×Ē ×›×“×™ או לט×ĸון א×Ē ×”×ž×§×•×¨×™×Ē ××• רק להש×Ēמ׊ ב×Ēמונה הממוז×ĸר×Ē.", "setting_image_viewer_preview_title": "ט×ĸן ×Ēמונ×Ē ×Ē×Ļוגה מקדימה", "setting_image_viewer_title": "×Ēמונו×Ē", "setting_languages_apply": "החל", @@ -1596,10 +1602,10 @@ "setting_notifications_notify_minutes": "{} דקו×Ē", "setting_notifications_notify_never": "את פ×ĸם", "setting_notifications_notify_seconds": "{} שניו×Ē", - "setting_notifications_single_progress_subtitle": "מיד×ĸ מפורט ×ĸל ה×Ēקדמו×Ē ×”×ĸלאה לכל נכס", + "setting_notifications_single_progress_subtitle": "מיד×ĸ מפורט ×ĸל ה×Ēקדמו×Ē ×”×ĸלאה לכל ×Ēמונה", "setting_notifications_single_progress_title": "הראה פרטי ה×Ēקדמו×Ē ×’×™×‘×•×™ ברק×ĸ", "setting_notifications_subtitle": "ה×Ēאם א×Ē ×”×ĸדפו×Ē ×”×”×Ēראה שלך", - "setting_notifications_total_progress_subtitle": "ה×Ēקדמו×Ē ×”×ĸלאה כללי×Ē (בו×Ļ×ĸ/סה״כ נכסים)", + "setting_notifications_total_progress_subtitle": "ה×Ēקדמו×Ē ×”×ĸלאה כללי×Ē (בו×Ļ×ĸ/סה״כ ×Ēמונו×Ē)", "setting_notifications_total_progress_title": "הראה סה״כ ה×Ēקדמו×Ē ×’×™×‘×•×™ ברק×ĸ", "setting_video_viewer_looping_title": "הפ×ĸלה חוזר×Ē", "setting_video_viewer_original_video_subtitle": "כאשר מזרימים סרטון מהשר×Ē, נגן א×Ē ×”×ž×§×•×¨×™ אפילו כשהמר×Ē ×§×™×“×•×“ זמינה. ×ĸלול להוביל ל×Ēקי×ĸו×Ē. סרטונים זמינים מקומי×Ē ×ž× ×•×’× ×™× באיכו×Ē ×ž×§×•×¨×™×Ē ×œ×œ× ק׊ר להגדרה זו.", @@ -1623,7 +1629,7 @@ "shared_by_user": "משו×Ē×Ŗ ×ĸל ידי {user}", "shared_by_you": "משו×Ē×Ŗ ×ĸל ידך", "shared_from_partner": "×Ēמונו×Ē ×ž××Ē {partner}", - "shared_intent_upload_button_progress_text": "הו×ĸלו {} / {}", + "shared_intent_upload_button_progress_text": "{} / {} הו×ĸלו", "shared_link_app_bar_title": "קישורים משו×Ēפים", "shared_link_clipboard_copied_massage": "הו×ĸ×Ē×§ ללוח", "shared_link_clipboard_text": "קישור: {}\nסיסמה: {}", @@ -1640,14 +1646,14 @@ "shared_link_edit_password_hint": "הכנס א×Ē ×Ą×™×Ą×ž×Ē ×”×Š×™×Ēות", "shared_link_edit_submit_button": "×ĸדכן קישור", "shared_link_error_server_url_fetch": "לא ני×Ēן להשיג א×Ē ×›×Ēוב×Ē ×”××™× ×˜×¨× ×˜ של השר×Ē", - "shared_link_expires_day": "יפוג ב×ĸוד {} יום", + "shared_link_expires_day": "יפוג ב×ĸוד יום {}", "shared_link_expires_days": "יפוג ב×ĸוד {} ימים", - "shared_link_expires_hour": "יפוג ב×ĸוד {} ׊×ĸה", + "shared_link_expires_hour": "יפוג ב×ĸוד ׊×ĸה {}", "shared_link_expires_hours": "יפוג ב×ĸוד {} ׊×ĸו×Ē", - "shared_link_expires_minute": "יפוג ב×ĸוד {} דקה", + "shared_link_expires_minute": "יפוג ב×ĸוד דקה {}", "shared_link_expires_minutes": "יפוג ב×ĸוד {} דקו×Ē", "shared_link_expires_never": "יפוג ∞", - "shared_link_expires_second": "יפוג ב×ĸוד {} שניה", + "shared_link_expires_second": "יפוג ב×ĸוד שנייה {}", "shared_link_expires_seconds": "יפוג ב×ĸוד {} שניו×Ē", "shared_link_individual_shared": "משו×Ē×Ŗ ליחיד", "shared_link_info_chip_metadata": "EXIF", @@ -1661,12 +1667,12 @@ "sharing": "שי×Ēות", "sharing_enter_password": "נא להזין א×Ē ×”×Ą×™×Ą×ž×” כדי ל×Ļפו×Ē ×‘×“×Ŗ זה.", "sharing_page_album": "אלבומים משו×Ēפים", - "sharing_page_description": "×Ļור אלבומים משו×Ēפים כדי לש×Ē×Ŗ ×Ēמונו×Ē ×•×Ą×¨×˜×•× ×™× ×ĸם אנשים ברש×Ē ×Š×œ×š", + "sharing_page_description": "×Ļור אלבומים משו×Ēפים כדי לש×Ē×Ŗ ×Ēמונו×Ē ×•×Ą×¨×˜×•× ×™× ×ĸם אנשים ברש×Ē ×Š×œ×š.", "sharing_page_empty_list": "רשימה ריקה", "sharing_sidebar_description": "ה×Ļג קישור אל שי×Ēות בסרגל ה×Ļד", "sharing_silver_appbar_create_shared_album": "אלבום משו×Ē×Ŗ חדש", "sharing_silver_appbar_share_partner": "שי×Ēות ×ĸם שו×Ē×Ŗ", - "shift_to_permanent_delete": "לח×Ĩ ⇧ כדי למחוק ל×Ļמי×Ēו×Ē × ×›×Ą", + "shift_to_permanent_delete": "לח×Ĩ ⇧ כדי למחוק ×Ēמונה ל×Ļמי×Ēו×Ē", "show_album_options": "ה×Ļג אפשרויו×Ē ××œ×‘×•×", "show_albums": "ה×Ļג אלבומים", "show_all_people": "ה×Ļג א×Ē ×›×œ האנשים", @@ -1711,7 +1717,7 @@ "stack_duplicates": "×Ļור ×ĸרימ×Ē ×›×¤×™×œ×•×™×•×Ē", "stack_select_one_photo": "בחר ×Ēמונה ראשי×Ē ××—×Ē ×ĸבור ה×ĸרימה", "stack_selected_photos": "×Ļור ×ĸרימ×Ē ×Ēמונו×Ē × ×‘×—×¨×•×Ē", - "stacked_assets_count": "{count, plural, one {נכס # × ×ĸרם} other {# נכסים × ×ĸרמו}}", + "stacked_assets_count": "{count, plural, one {×Ēמונה # × ×ĸרמה} other {# ×Ēמונו×Ē × ×ĸרמו}}", "stacktrace": "Stack trace", "start": "ה×Ēחל", "start_date": "×Ēאריך ה×Ēחלה", @@ -1736,25 +1742,25 @@ "sync_albums_manual_subtitle": "סנכרן א×Ē ×›×œ הסרטונים וה×Ēמונו×Ē ×Š×”×•×ĸלו לאלבומי הגיבוי שנבחרו", "sync_upload_album_setting_subtitle": "×Ļור וה×ĸלה ×Ēמונו×Ē ×•×Ą×¨×˜×•× ×™× שלך לאלבומים שנבחרו ביישום", "tag": "×Ēג", - "tag_assets": "×Ēיוג נכסים", + "tag_assets": "×Ēיוג ×Ēמונו×Ē", "tag_created": "נו×Ļר ×Ēג: {tag}", "tag_feature_description": "×ĸיון ב×Ēמונו×Ē ×•×Ą×¨×˜×•× ×™× שקוב×Ļו ×ĸל ידי נושאי ×Ēג לוגיים", "tag_not_found_question": "לא מ×Ļליח למ×Ļוא ×Ēג? ×Ļור ×Ēג חדש", "tag_people": "×Ēייג אנשים", "tag_updated": "×Ēג מ×ĸודכן: {tag}", - "tagged_assets": "×Ēויגו {count, plural, one {נכס #} other {# נכסים}}", + "tagged_assets": "×Ēויגו {count, plural, one {×Ēמונה #} other {# ×Ēמונו×Ē}}", "tags": "×Ēגים", "template": "×Ēבני×Ē", "theme": "×ĸרכ×Ē × ×•×Š×", "theme_selection": "בחיר×Ē ×ĸרכ×Ē × ×•×Š×", "theme_selection_description": "הגדר אוטומטי×Ē ××Ē ×ĸרכ×Ē ×”× ×•×Š× לבהיר או כהה בה×Ēבסס ×ĸל ה×ĸדפ×Ē ×”×ž×ĸרכ×Ē ×Š×œ הדפדפן שלך", - "theme_setting_asset_list_storage_indicator_title": "הראה מחוון אחסון ×ĸל אריחי נכסים", - "theme_setting_asset_list_tiles_per_row_title": "מספר נכסים בכל שורה ({})", - "theme_setting_colorful_interface_subtitle": "החל א×Ē ×”×Ļב×ĸ ה×ĸיקרי למשטחי רק×ĸ", + "theme_setting_asset_list_storage_indicator_title": "ה×Ļג סטטוס אחסון ×ĸל גבי ה×Ēמונו×Ē", + "theme_setting_asset_list_tiles_per_row_title": "מספר ×Ēמונו×Ē ×‘×›×œ שורה ({})", + "theme_setting_colorful_interface_subtitle": "החל א×Ē ×”×Ļב×ĸ ה×ĸיקרי למשטחי רק×ĸ.", "theme_setting_colorful_interface_title": "ממ׊ק ×Ļב×ĸוני", "theme_setting_image_viewer_quality_subtitle": "ה×Ēאם א×Ē ×”××™×›×•×Ē ×Š×œ מ×Ļיג פרטי ה×Ēמונו×Ē", "theme_setting_image_viewer_quality_title": "איכו×Ē ×ž×Ļיג ×Ēמונו×Ē", - "theme_setting_primary_color_subtitle": "בחר ×Ļב×ĸ לפ×ĸולו×Ē ×ĸיקריו×Ē ×•×”×“×’×Š×•×Ē", + "theme_setting_primary_color_subtitle": "בחר ×Ļב×ĸ לפ×ĸולו×Ē ×ĸיקריו×Ē ×•×”×“×’×Š×•×Ē.", "theme_setting_primary_color_title": "×Ļב×ĸ ×ĸיקרי", "theme_setting_system_primary_color_title": "הש×Ēמ׊ ב×Ļב×ĸ המ×ĸרכ×Ē", "theme_setting_system_theme_switch": "אוטומטי (×ĸקוב אחרי הגדר×Ē ×ž×ĸרכ×Ē)", @@ -1779,15 +1785,15 @@ "trash": "אשפה", "trash_all": "ה×ĸבר הכל לאשפה", "trash_count": "ה×ĸבר לאשפה {count, number}", - "trash_delete_asset": "ה×ĸבר לאשפה/מחק נכס", + "trash_delete_asset": "ה×ĸבר לאשפה/מחק ×Ēמונה", "trash_emptied": "האשפה רוקנה", "trash_no_results_message": "×Ēמונו×Ē ×•×Ą×¨×˜×•× ×™× שהו×ĸברו לאשפה יופי×ĸו כאן.", "trash_page_delete_all": "מחק הכל", - "trash_page_empty_trash_dialog_content": "האם בר×Ļונך לרוקן א×Ē ×”× ×›×Ą×™× שבאשפה? הפריטים האלה ימחקו ל×Ļמי×Ēו×Ē ×ž×”×Š×¨×Ē", + "trash_page_empty_trash_dialog_content": "האם בר×Ļונך לרוקן א×Ē ×”×Ēמונו×Ē ×Š×‘××Š×¤×”? הפריטים האלה ימחקו ל×Ļמי×Ēו×Ē ×ž×”×Š×¨×Ē", "trash_page_info": "פריטים באשפה ימחקו ל×Ļמי×Ēו×Ē ×œ××—×¨ {} ימים", - "trash_page_no_assets": "אין נכסים באשפה", + "trash_page_no_assets": "אין ×Ēמונו×Ē ×‘××Š×¤×”", "trash_page_restore_all": "שחזר הכל", - "trash_page_select_assets_btn": "בחר נכסים", + "trash_page_select_assets_btn": "בחר ×Ēמונו×Ē", "trash_page_title": "אשפה ({})", "trashed_items_will_be_permanently_deleted_after": "פריטים באשפה ימחקו ל×Ļמי×Ēו×Ē ×œ××—×¨ {days, plural, one {יום #} other {# ימים}}.", "type": "סוג", @@ -1810,22 +1816,22 @@ "unselect_all": "בטל בחירה בהכל", "unselect_all_duplicates": "בטל בחיר×Ē ×›×œ הכפילויו×Ē", "unstack": "בטל ×ĸרימה", - "unstacked_assets_count": "{count, plural, one {נכס # הוסר} other {# נכסים הוסרו}} מ×ĸרימה", + "unstacked_assets_count": "{count, plural, one {×Ēמונה # הוסרה} other {# ×Ēמונו×Ē ×”×•×Ą×¨×•}} מה×ĸרימה", "untracked_files": "קב×Ļים ללא מ×ĸקב", "untracked_files_decription": "קב×Ļים אלה אינם נמ×Ļאים במ×ĸקב של היישום. הם יכולים להיו×Ē ×Ēו×Ļאו×Ē ×Š×œ ה×ĸברו×Ē ×›×•×Š×œ×•×Ē, ה×ĸלאו×Ē ×Š× ×§×˜×ĸו, או שנו×Ēרו מאחור בגלל שיבוש ב×Ēוכנה", "up_next": "הבא ב×Ēור", "updated_password": "סיסמה ×ĸודכנה", "upload": "ה×ĸלאה", "upload_concurrency": "בו-זמניו×Ē ×Š×œ ה×ĸלאה", - "upload_dialog_info": "האם בר×Ļונך לגבו×Ē ××Ē ×”× ×›×Ą(ים) שנבחרו לשר×Ē?", - "upload_dialog_title": "ה×ĸלא×Ē × ×›×Ą", - "upload_errors": "ה×ĸלאה הושלמה ×ĸם {count, plural, one {שגיאה #} other {# שגיאו×Ē}}, ר×ĸנן א×Ē ×”×“×Ŗ כדי לראו×Ē × ×›×Ą×™ ה×ĸלאה חדשים.", + "upload_dialog_info": "האם בר×Ļונך לגבו×Ē ××Ē ×”×Ēמונו×Ē ×Š× ×‘×—×¨×• לשר×Ē?", + "upload_dialog_title": "ה×ĸלא×Ē ×Ēמונה", + "upload_errors": "ה×ĸלאה הושלמה ×ĸם {count, plural, one {שגיאה #} other {# שגיאו×Ē}}, ר×ĸנן א×Ē ×”×“×Ŗ כדי לראו×Ē ×Ēמונו×Ē ×Š×”×•×ĸלו.", "upload_progress": "נו×Ēרו {remaining, number} - טופלו {processed, number}/{total, number}", - "upload_skipped_duplicates": "דילג ×ĸל {count, plural, one {נכס כפול #} other {# נכסים כפולים}}", + "upload_skipped_duplicates": "דילג ×ĸל {count, plural, one {×Ēמונה כפולה #} other {# ×Ēמונו×Ē ×›×¤×•×œ×•×Ē}}", "upload_status_duplicates": "כפילויו×Ē", "upload_status_errors": "שגיאו×Ē", "upload_status_uploaded": "הו×ĸלה", - "upload_success": "הה×ĸלאה ה×Ļליחה, ר×ĸנן א×Ē ×”×“×Ŗ כדי לראו×Ē × ×›×Ą×™ ה×ĸלאה חדשים.", + "upload_success": "הה×ĸלאה בו×Ļ×ĸה בה×Ļלחה. ר×ĸנן א×Ē ×”×“×Ŗ כדי ל×Ļפו×Ē ×‘×Ēמונו×Ē ×Š×”×•×ĸלו.", "upload_to_immich": "ה×ĸלה לשר×Ē ({})", "uploading": "מ×ĸלה", "url": "URL", @@ -1834,7 +1840,7 @@ "use_custom_date_range": "הש×Ēמ׊ בטווח ×Ēאריכים מו×Ēאם במקום", "user": "מ׊×Ēמ׊", "user_id": "מזהה מ׊×Ēמ׊", - "user_liked": "{user} אהב א×Ē {type, select, photo {ה×Ēמונה הזא×Ē} video {הסרטון הזה} asset {הנכס הזה} other {זה}}", + "user_liked": "{user} אהב א×Ē {type, select, photo {ה×Ēמונה הזא×Ē} video {הסרטון הזה} asset {ה×Ēמונה הזא×Ē} other {זה}}", "user_purchase_settings": "רכישה", "user_purchase_settings_description": "ניהול הרכישה שלך", "user_role_set": "הגדר א×Ē {user} ב×Ēור {role}", @@ -1853,7 +1859,7 @@ "version_announcement_overlay_release_notes": "ה×ĸרו×Ē ×¤×¨×Ą×•×", "version_announcement_overlay_text_1": "הי חבר/ה, יש מהדורה חדשה של", "version_announcement_overlay_text_2": "אנא קח/י א×Ē ×”×–×ž×Ÿ שלך לבקר ב ", - "version_announcement_overlay_text_3": " ולוודא שמבנה ה docker-compose וה env. שלך ×ĸדכני כדי למנו×ĸ ×Ē×Ļורו×Ē ×Š×’×•×™×•×Ē, במיוחד אם א×Ē/ה מ׊×Ēמ׊/×Ē ×‘ WatchTower או בכל מנגנון שמטפל ב×ĸדכון יישום השר×Ē ×Š×œ×š באופן אוטומטי", + "version_announcement_overlay_text_3": " ולוודא שמבנה ה docker-compose וה env. שלך ×ĸדכני כדי למנו×ĸ ×Ē×Ļורו×Ē ×Š×’×•×™×•×Ē, במיוחד אם א×Ēה מ׊×Ēמ׊ ב WatchTower או במנגנון שמטפל ב×ĸדכון השר×Ē ×‘××•×¤×Ÿ אוטומטי.", "version_announcement_overlay_title": "גרס×Ē ×Š×¨×Ē ×—×“×Š×” זמינה 🎉", "version_history": "היסטוריי×Ē ×’×¨×Ą××•×Ē", "version_history_item": "{version} הו×Ēקנה ב-{date}", @@ -1870,11 +1876,12 @@ "view_link": "ה×Ļג קישור", "view_links": "ה×Ļג קישורים", "view_name": "ה×Ļג", - "view_next_asset": "ה×Ļג א×Ē ×”× ×›×Ą הבא", - "view_previous_asset": "ה×Ļג א×Ē ×”× ×›×Ą הקודם", + "view_next_asset": "ה×Ļג א×Ē ×”×Ēמונה הבאה", + "view_previous_asset": "ה×Ļג א×Ē ×”×Ēמונה הקודמ×Ē", + "view_qr_code": "ה×Ļג ברקוד", "view_stack": "ה×Ļג ×ĸרימה", "viewer_remove_from_stack": "הסר מ×ĸרימה", - "viewer_stack_use_as_main_asset": "הש×Ēמ׊ כנכס ראשי", + "viewer_stack_use_as_main_asset": "הש×Ēמ׊ כ×Ēמונה ראשי×Ē", "viewer_unstack": "ביטול ×ĸרימה", "visibility_changed": "הנראו×Ē ×”×Š×Ē× ×Ēה ×ĸבור {count, plural, one {אדם #} other {# אנשים}}", "waiting": "ממ×Ēין", @@ -1882,7 +1889,7 @@ "week": "שבו×ĸ", "welcome": "ברוכים הבאים", "welcome_to_immich": "ברוכים הבאים אל immich", - "wifi_name": "׊ם אינטרנט אלחוטי", + "wifi_name": "׊ם הרש×Ē ×”××œ×—×•×˜×™×Ē", "year": "שנה", "years_ago": "לפני {years, plural, one {שנה #} other {# שנים}}", "yes": "כן", diff --git a/i18n/hi.json b/i18n/hi.json index 7f50906791..50c17d9e5d 100644 --- a/i18n/hi.json +++ b/i18n/hi.json @@ -1142,7 +1142,7 @@ "partner_page_partner_add_failed": "Failed to add partner", "partner_page_select_partner": "Select partner", "partner_page_shared_to_title": "Shared to", - "partner_page_stop_sharing_content": "{} will no longer be able to access your photos.", + "partner_page_stop_sharing_content": "{} will no longer be able to access your photosāĨ¤", "partner_sharing": "ā¤Ēā¤žā¤°āĨā¤Ÿā¤¨ā¤° ā¤ļāĨ‡ā¤¯ā¤°ā¤ŋ⤂⤗", "partners": "ā¤­ā¤žā¤—āĨ€ā¤Ļā¤žā¤°āĨ‹ā¤‚", "password": "ā¤Ēā¤žā¤¸ā¤ĩ⤰āĨā¤Ą", diff --git a/i18n/hr.json b/i18n/hr.json index 53a7cc2640..a30de885cd 100644 --- a/i18n/hr.json +++ b/i18n/hr.json @@ -4,6 +4,7 @@ "account_settings": "Postavke računa", "acknowledge": "Potvrdi", "action": "Akcija", + "action_common_update": "AÅžuriranje", "actions": "Akcije", "active": "Aktivno", "activity": "Aktivnost", @@ -13,6 +14,7 @@ "add_a_location": "Dodaj lokaciju", "add_a_name": "Dodaj ime", "add_a_title": "Dodaj naslov", + "add_endpoint": "Dodaj krajnju točnu", "add_exclusion_pattern": "Dodaj uzorak izuzimanja", "add_import_path": "Dodaj import folder", "add_location": "Dodaj lokaciju", @@ -20,8 +22,10 @@ "add_partner": "Dodaj partnera", "add_path": "Dodaj putanju", "add_photos": "Dodaj slike", - "add_to": "Dodaj u...", + "add_to": "Dodaj uâ€Ļ", "add_to_album": "Dodaj u album", + "add_to_album_bottom_sheet_added": "Dodano u {album}", + "add_to_album_bottom_sheet_already_exists": "Već u {album}", "add_to_shared_album": "Dodaj u dijeljeni album", "add_url": "Dodaj URL", "added_to_archive": "Dodano u arhivu", @@ -41,6 +45,7 @@ "backup_settings": "Postavke sigurnosne kopije", "backup_settings_description": "Upravljanje postavkama sigurnosne kopije baze podataka", "check_all": "Provjeri sve", + "cleanup": "ČiÅĄÄ‡enje", "cleared_jobs": "Izbrisani poslovi za: {job}", "config_set_by_file": "Konfiguracija je trenutno postavljena konfiguracijskom datotekom", "confirm_delete_library": "Jeste li sigurni da Åželite izbrisati biblioteku {library}?", @@ -65,8 +70,13 @@ "forcing_refresh_library_files": "Prisilno osvjeÅžavanje svih datoteka knjiÅžnice", "image_format": "Format", "image_format_description": "WebP proizvodi manje datoteke od JPEG-a, ali se sporije kodira.", + "image_fullsize_description": "Slika pune veličine bez meta podataka, koristi se prilikom zumiranja", + "image_fullsize_enabled": "Omogući generiranje slike pune veličine", + "image_fullsize_enabled_description": "Generiraj sliku pune veličine za formate koji nisu prilagođeni webu. Kada je opcija \"Preferiraj ugrađeni pregled\" omogućena, ugrađeni pregledi koriste se izravno bez konverzije. Ne utječe na formate prilagođene webu kao ÅĄto je JPEG.", + "image_fullsize_quality_description": "Kvaliteta slike pune veličine od 1 do 100. Veća vrijednost znači bolja kvaliteta, ali stvara veće datoteke.", + "image_fullsize_title": "Postavke slike pune veličine", "image_prefer_embedded_preview": "Preferiraj ugrađeni pregled", - "image_prefer_embedded_preview_setting_description": "Koristite ugrađene preglede u RAW fotografije kao ulaz za obradu slike kada su dostupni. To moÅže proizvesti preciznije boje za neke slike, ali kvaliteta pregleda ovisi o kameri i slika moÅže imati viÅĄe artefakata kompresije.", + "image_prefer_embedded_preview_setting_description": "Koristite ugrađene preglede u RAW fotografije kao ulaz za obradu slike kada su dostupni. To moÅže proizvesti preciznije boje za neke slike, ali kvaliteta pregleda ovisi o kameri i slika moÅže imati viÅĄe artifakta kompresije.", "image_prefer_wide_gamut": "Preferirajte ÅĄiroku gamu", "image_prefer_wide_gamut_setting_description": "Koristite Display P3 za sličice. Ovo bolje čuva Åživost slika sa ÅĄirokim prostorima boja, ali slike mogu izgledati drugačije na starim uređajima sa starom verzijom preglednika. sRGB slike čuvaju se kao sRGB kako bi se izbjegle promjene boja.", "image_preview_description": "Slika srednje veličine s ogoljenim metapodacima, koristi se prilikom pregledavanja jednog sredstva i za strojno učenje", @@ -96,7 +106,7 @@ "library_scanning_enable_description": "Omogući periodično skeniranje biblioteke", "library_settings": "Externa biblioteka", "library_settings_description": "Upravljajte postavkama vanjske biblioteke", - "library_tasks_description": "Obavljati bibliotekne zadatke", + "library_tasks_description": "Skeniraj eksterne biblioteke za nove i/ili promijenjene resurse", "library_watching_enable_description": "Pratite vanjske biblioteke za promjena datoteke", "library_watching_settings": "Gledanje biblioteke (EKSPERIMENTALNO)", "library_watching_settings_description": "Automatsko praćenje promijenjenih datoteke", @@ -131,7 +141,7 @@ "machine_learning_smart_search_description": "PretraÅžujte slike semantički koristeći CLIP ugradnje", "machine_learning_smart_search_enabled": "Omogući pametno pretraÅživanje", "machine_learning_smart_search_enabled_description": "Ako je onemogućeno, slike neće biti kodirane za pametno pretraÅživanje.", - "machine_learning_url_description": "URL posluÅžitelja strojnog učenja. Ako ste dodali viÅĄe od jednog URLa, svaki server će biti kontaktiraj jedanput dok jedan ne odgovori uspjeÅĄno, u redu od prvog do zadnjeg.", + "machine_learning_url_description": "URL posluÅžitelja strojnog učenja. Ako ste dodali viÅĄe od jednog URLa, svaki server će biti kontaktiraj jedanput dok jedan ne odgovori uspjeÅĄno, u redu od prvog do zadnjeg. Serveri koji ne odgovore će privremeno biti ignorirani dok ponovo ne postanu dostupni.", "manage_concurrency": "Upravljanje IstovremenoÅĄÄ‡u", "manage_log_settings": "Upravljanje postavkama zapisivanje", "map_dark_style": "Tamni stil", @@ -147,6 +157,8 @@ "map_settings": "Karta", "map_settings_description": "Upravljanje postavkama karte", "map_style_description": "URL na style.json temu karte", + "memory_cleanup_job": "ČiÅĄÄ‡enje memorije", + "memory_generate_job": "Generiranje memorije", "metadata_extraction_job": "Izdvoj metapodatke", "metadata_extraction_job_description": "Izdvojite podatke o metapodacima iz svakog sredstva, kao ÅĄto su GPS, lica i rezolucija", "metadata_faces_import_setting": "Omogući uvoz lica", @@ -239,7 +251,7 @@ "storage_template_hash_verification_enabled_description": "Omogućuje hash provjeru, nemojte je onemogućiti osim ako niste sigurni u implikacije", "storage_template_migration": "Migracija predloÅĄka za pohranu", "storage_template_migration_description": "Primijenite trenutni {template} na prethodno prenesena sredstva", - "storage_template_migration_info": "Promjene predloÅĄka primjenjivat će se samo na nova sredstva. Za retroaktivnu primjenu predloÅĄka na prethodno prenesena sredstva, pokrenite {job}.", + "storage_template_migration_info": "PredloÅžak za pohranu će sve nastavke (ekstenzije) pretvoriti u mala slova. Promjene predloÅĄka primjenjivat će se samo na nova sredstva. Za retroaktivnu primjenu predloÅĄka na prethodno prenesena sredstva, pokrenite {job}.", "storage_template_migration_job": "Posao Migracije PredloÅĄka Pohrane", "storage_template_more_details": "Za viÅĄe pojedinosti o ovoj značajci pogledajte PredloÅžak pohrane i njegove implikacije", "storage_template_onboarding_description": "Kada je omogućena, ova će značajka automatski organizirati datoteke na temelju korisnički definiranog predloÅĄka. Zbog problema sa stabilnoÅĄÄ‡u značajka je isključena prema zadanim postavkama. Za viÅĄe informacija pogledajte dokumentaciju.", @@ -250,6 +262,15 @@ "system_settings": "Postavke Sustava", "tag_cleanup_job": "ČiÅĄÄ‡enje oznaka", "template_email_available_tags": "MoÅžete koristiti sljedeće varijable u vaÅĄem predloÅĄku:{tags}", + "template_email_if_empty": "Ukoliko je predloÅžak prazan, koristit će se zadana e-mail adresa.", + "template_email_invite_album": "PredloÅžak za pozivnicu u album", + "template_email_preview": "Pregled", + "template_email_settings": "E-mail PredloÅĄci", + "template_email_settings_description": "Upravljanje prilagođenim predloÅĄcima za obavijesti putem e-maila", + "template_email_update_album": "AÅžuriraj Album PredloÅžak", + "template_email_welcome": "PredloÅžak e-maila dobrodoÅĄlice", + "template_settings": "PredloÅžak Obavijesti", + "template_settings_description": "Upravljaj prilagođenim predloÅĄcima za obavijesti.", "theme_custom_css_settings": "Prilagođeni CSS", "theme_custom_css_settings_description": "Kaskadni listovi stilova (CSS) omogućuju prilagođavanje dizajna Immicha.", "theme_settings": "Postavke tema", @@ -279,6 +300,8 @@ "transcoding_constant_rate_factor": "Faktor konstantne stope (-crf)", "transcoding_constant_rate_factor_description": "Razina kvalitete videa. Uobičajene vrijednosti su 23 za H.264, 28 za HEVC, 31 za VP9 i 35 za AV1. NiÅže je bolje, ali stvara veće datoteke.", "transcoding_disabled_description": "Nemojte transkodirati nijedan videozapis, moÅže prekinuti reprodukciju na nekim klijentima", + "transcoding_encoding_options": "Opcije Kodiranja", + "transcoding_encoding_options_description": "Postavi kodeke, rezoluciju, kvalitetu i druge opcije za kodirane videje", "transcoding_hardware_acceleration": "Hardversko Ubrzanje", "transcoding_hardware_acceleration_description": "Eksperimentalno; puno brÅže, ali će imati niÅžu kvalitetu pri istoj bitrate postavci", "transcoding_hardware_decoding": "Hardversko dekodiranje", @@ -291,6 +314,8 @@ "transcoding_max_keyframe_interval": "Maksimalni interval ključnih sličica", "transcoding_max_keyframe_interval_description": "Postavlja maksimalnu udaljenost slika između ključnih kadrova. NiÅže vrijednosti pogorÅĄavaju učinkovitost kompresije, ali poboljÅĄavaju vrijeme traÅženja i mogu poboljÅĄati kvalitetu u scenama s brzim kretanjem. 0 automatski postavlja ovu vrijednost.", "transcoding_optimal_description": "Videozapisi koji su veći od ciljne rezolucije ili nisu u prihvatljivom formatu", + "transcoding_policy": "Politika Transkodiranja", + "transcoding_policy_description": "Postavi kada će video biti transkodiran", "transcoding_preferred_hardware_device": "Preferirani hardverski uređaj", "transcoding_preferred_hardware_device_description": "Odnosi se samo na VAAPI i QSV. Postavlja dri node koji se koristi za hardversko transkodiranje.", "transcoding_preset_preset": "Preset (-preset)", @@ -299,7 +324,7 @@ "transcoding_reference_frames_description": "Broj slika za referencu prilikom komprimiranja određene slike. ViÅĄe vrijednosti poboljÅĄavaju učinkovitost kompresije, ali usporavaju kodiranje. 0 automatski postavlja ovu vrijednost.", "transcoding_required_description": "Samo videozapisi koji nisu u prihvaćenom formatu", "transcoding_settings": "Postavke Video Transkodiranja", - "transcoding_settings_description": "Upravljajte informacijama o razlučivosti i kodiranju video datoteka", + "transcoding_settings_description": "Upravljaj koji videozapisi će se transkodirati i kako ih obraditi", "transcoding_target_resolution": "Ciljana rezolucija", "transcoding_target_resolution_description": "Veće razlučivosti mogu sačuvati viÅĄe detalja, ali trebaju dulje za kodiranje, imaju veće veličine datoteka i mogu smanjiti odziv aplikacije.", "transcoding_temporal_aq": "Vremenski AQ", @@ -312,7 +337,7 @@ "transcoding_transcode_policy_description": "Pravila o tome kada se video treba transkodirati. HDR videozapisi uvijek će biti transkodirani (osim ako je transkodiranje onemogućeno).", "transcoding_two_pass_encoding": "Kodiranje u dva prolaza", "transcoding_two_pass_encoding_setting_description": "Transkodiranje u dva prolaza za proizvodnju bolje kodiranih videozapisa. Kada je omogućena maksimalna brzina prijenosa (potrebna za rad s H.264 i HEVC), ovaj način rada koristi raspon brzine prijenosa na temelju maksimalne brzine prijenosa i zanemaruje CRF. Za VP9, CRF se moÅže koristiti ako je maksimalna brzina prijenosa onemogućena.", - "transcoding_video_codec": "Video Kodek", + "transcoding_video_codec": "Video kodek", "transcoding_video_codec_description": "VP9 ima visoku učinkovitost i web-kompatibilnost, ali treba dulje za transkodiranje. HEVC ima sličnu izvedbu, ali ima slabiju web kompatibilnost. H.264 ÅĄiroko je kompatibilan i brzo se transkodira, ali proizvodi mnogo veće datoteke. AV1 je najučinkovitiji kodek, ali nema podrÅĄku na starijim uređajima.", "trash_enabled_description": "Omogućite značajke Smeća", "trash_number_of_days": "Broj dana", @@ -346,6 +371,20 @@ "admin_password": "Admin Lozinka", "administration": "Administracija", "advanced": "Napredno", + "advanced_settings_enable_alternate_media_filter_subtitle": "Koristite ovu opciju za filtriranje medija tijekom sinkronizacije na temelju alternativnih kriterija. PokuÅĄajte ovo samo ako imate problema s aplikacijom koja ne prepoznaje sve albume.", + "advanced_settings_enable_alternate_media_filter_title": "[EKSPERIMENTALNO] Koristite alternativni filter za sinkronizaciju albuma na uređaju", + "advanced_settings_log_level_title": "Razina zapisivanja: {}", + "advanced_settings_prefer_remote_subtitle": "Neki uređaji sporo učitavaju sličice s resursa na uređaju. Aktivirajte ovu postavku kako biste umjesto toga učitali slike s udaljenih izvora.", + "advanced_settings_prefer_remote_title": "Preferiraj udaljene slike", + "advanced_settings_proxy_headers_subtitle": "Definirajte zaglavlja posrednika koja Immich treba slati sa svakim mreÅžnim zahtjevom.", + "advanced_settings_proxy_headers_title": "Zaglavlja Posrednika", + "advanced_settings_self_signed_ssl_subtitle": "Preskoči provjeru SSL certifikata za krajnju točku posluÅžitelja. Potrebno za samo-potpisane certifikate.", + "advanced_settings_self_signed_ssl_title": "Dopusti samo-potpisane SSL certifikate", + "advanced_settings_sync_remote_deletions_subtitle": "Automatski izbriÅĄi ili obnovi resurs na ovom uređaju kada se ta radnja izvrÅĄi na webu", + "advanced_settings_sync_remote_deletions_title": "Sinkroniziraj udaljena brisanja [EKSPERIMENTALNO]", + "advanced_settings_tile_subtitle": "Postavke za napredne korisnike", + "advanced_settings_troubleshooting_subtitle": "Omogući dodatne značajke za rjeÅĄavanje problema", + "advanced_settings_troubleshooting_title": "RjeÅĄavanje problema", "age_months": "Dob {months, plural, one {# month} other {# months}}", "age_year_months": "Dob 1 godina, {months, plural, one {# month} other {# months}}", "age_years": "{years, plural, other {Age #}}", @@ -354,6 +393,8 @@ "album_cover_updated": "Naslovnica albuma aÅžurirana", "album_delete_confirmation": "Jeste li sigurni da Åželite izbrisati album {album}?", "album_delete_confirmation_description": "Ako se ovaj album dijeli, drugi korisnici mu viÅĄe neće moći pristupiti.", + "album_info_card_backup_album_excluded": "IZUZETO", + "album_info_card_backup_album_included": "UKLJUČENO", "album_info_updated": "Podaci o albumu aÅžurirani", "album_leave": "Napustiti album?", "album_leave_confirmation": "Jeste li sigurni da Åželite napustiti {album}?", @@ -362,10 +403,22 @@ "album_remove_user": "Ukloni korisnika?", "album_remove_user_confirmation": "Jeste li sigurni da Åželite ukloniti {user}?", "album_share_no_users": "Čini se da ste podijelili ovaj album sa svim korisnicima ili nemate nijednog korisnika s kojim biste ga dijelili.", + "album_thumbnail_card_item": "1 stavka", + "album_thumbnail_card_items": "{} stavki", + "album_thumbnail_card_shared": " ¡ Podijeljeno", + "album_thumbnail_shared_by": "Podijeljeno sa {}", "album_updated": "Album aÅžuriran", "album_updated_setting_description": "Primite obavijest e-poÅĄtom kada dijeljeni album ima nova sredstva", "album_user_left": "NapuÅĄten {album}", "album_user_removed": "Uklonjen {user}", + "album_viewer_appbar_delete_confirm": "Jeste li sigurni da Åželite izbrisati ovaj album s vaÅĄeg računa?", + "album_viewer_appbar_share_err_delete": "NeuspjeÅĄno brisanje albuma", + "album_viewer_appbar_share_err_leave": "NeuspjeÅĄno napuÅĄtanje albuma", + "album_viewer_appbar_share_err_remove": "Postoje problemi s uklanjanjem resursa iz albuma", + "album_viewer_appbar_share_err_title": "NeuspjeÅĄno mijenjanje naslova albuma", + "album_viewer_appbar_share_leave": "Napusti album", + "album_viewer_appbar_share_to": "Podijeli s", + "album_viewer_page_share_add_users": "Dodaj korisnike", "album_with_link_access": "Dopusti svima s poveznicom pristup fotografijama i osobama u ovom albumu.", "albums": "Albumi", "albums_count": "{count, plural, one {{count, number} Album} other {{count, number} Albumi}}", @@ -377,47 +430,139 @@ "allow_edits": "Dozvoli izmjene", "allow_public_user_to_download": "Dopusti javnom korisniku preuzimanje", "allow_public_user_to_upload": "Dopusti javnom korisniku učitavanje", + "alt_text_qr_code": "Slika QR koda", "anti_clockwise": "Suprotno smjeru kazaljke na satu", "api_key": "API Ključ", "api_key_description": "Ova će vrijednost biti prikazana samo jednom. Obavezno ju kopirajte prije zatvaranja prozora.", "api_key_empty": "Naziv vaÅĄeg API ključa ne smije biti prazan", "api_keys": "API Ključevi", + "app_bar_signout_dialog_content": "Jeste li sigurni da se Åželite odjaviti?", + "app_bar_signout_dialog_ok": "Da", + "app_bar_signout_dialog_title": "Odjavi se", "app_settings": "Postavke Aplikacije", "appears_in": "Pojavljuje se u", "archive": "Arhiva", "archive_or_unarchive_photo": "Arhivirajte ili dearhivirajte fotografiju", + "archive_page_no_archived_assets": "Nema arhiviranih resursa", + "archive_page_title": "Arhiviraj {{}}", "archive_size": "Veličina arhive", "archive_size_description": "Konfigurirajte veličinu arhive za preuzimanja (u GiB)", + "archived": "Ahrivirano", "archived_count": "{count, plural, other {Archived #}}", "are_these_the_same_person": "Je li ovo ista osoba?", "are_you_sure_to_do_this": "Jeste li sigurni da to Åželite učiniti?", + "asset_action_delete_err_read_only": "Nije moguće izbrisati resurse samo za čitanje, preskačem", + "asset_action_share_err_offline": "Nije moguće dohvatiti izvanmreÅžne resurse, preskačem", "asset_added_to_album": "Dodano u album", - "asset_adding_to_album": "Dodavanje u album...", + "asset_adding_to_album": "Dodavanje u albumâ€Ļ", "asset_description_updated": "Opis imovine je aÅžuriran", "asset_filename_is_offline": "Sredstvo {filename} je izvan mreÅže", "asset_has_unassigned_faces": "Materijal ima nedodijeljena lica", - "asset_hashing": "Hashiranje...", + "asset_hashing": "SaÅžimanjeâ€Ļ", + "asset_list_group_by_sub_title": "Grupiraj po", + "asset_list_layout_settings_dynamic_layout_title": "Dinamički raspored", + "asset_list_layout_settings_group_automatically": "Automatski", + "asset_list_layout_settings_group_by": "Grupiraj resurse po", + "asset_list_layout_settings_group_by_month_day": "Mjesec + dan", + "asset_list_layout_sub_title": "Raspored", + "asset_list_settings_subtitle": "Postavke izgleda mreÅže fotografija", + "asset_list_settings_title": "MreÅža Fotografija", "asset_offline": "Sredstvo izvan mreÅže", "asset_offline_description": "Ovaj materijal je izvan mreÅže. Immich ne moÅže pristupiti lokaciji datoteke. Provjerite je li sredstvo dostupno, a zatim ponovno skenirajte biblioteku.", + "asset_restored_successfully": "Resurs uspjeÅĄno obnovljen", "asset_skipped": "Preskočeno", "asset_skipped_in_trash": "U smeću", "asset_uploaded": "Učitano", - "asset_uploading": "Učitavanje...", + "asset_uploading": "Å aljemâ€Ļ", + "asset_viewer_settings_subtitle": "Upravljajte postavkama preglednika vaÅĄe galerije", + "asset_viewer_settings_title": "Preglednik Resursa", "assets": "Sredstva", "assets_added_count": "Dodano {count, plural, one {# asset} other {# assets}}", "assets_added_to_album_count": "Dodano {count, plural, one {# asset} other {# assets}} u album", "assets_added_to_name_count": "Dodano {count, plural, one {# asset} other {# assets}} u {hasName, select, true {{name}} other {new album}}", "assets_count": "{count, plural, one {# asset} other {# assets}}", + "assets_deleted_permanently": "{} resurs(i) uspjeÅĄno uklonjeni", + "assets_deleted_permanently_from_server": "{} resurs(i) trajno obrisan(i) sa Immich posluÅžitelja", "assets_moved_to_trash_count": "{count, plural, one {# asset} other {# asset}} premjeÅĄteno u smeće", "assets_permanently_deleted_count": "Trajno izbrisano {count, plural, one {# asset} other {# assets}}", "assets_removed_count": "Uklonjeno {count, plural, one {# asset} other {# assets}}", - "assets_restore_confirmation": "Jeste li sigurni da Åželite vratiti sve svoje resurse bačene u otpad? Ne moÅžete poniÅĄtiti ovu radnju!", + "assets_removed_permanently_from_device": "{} resurs(i) trajno uklonjen(i) s vaÅĄeg uređaja", + "assets_restore_confirmation": "Jeste li sigurni da Åželite obnoviti sve svoje resurse bačene u otpad? Ne moÅžete poniÅĄtiti ovu radnju! Imajte na umu da se bilo koji izvanmreÅžni resursi ne mogu obnoviti na ovaj način.", "assets_restored_count": "Vraćeno {count, plural, one {# asset} other {# assets}}", + "assets_restored_successfully": "{} resurs(i) uspjeÅĄno obnovljen(i)", + "assets_trashed": "{} resurs(i) premjeÅĄten(i) u smeće", "assets_trashed_count": "Bačeno u smeće {count, plural, one {# asset} other {# assets}}", + "assets_trashed_from_server": "{} resurs(i) premjeÅĄten(i) u smeće s Immich posluÅžitelja", "assets_were_part_of_album_count": "{count, plural, one {Asset was} other {Assets were}} već dio albuma", "authorized_devices": "OvlaÅĄteni Uređaji", + "automatic_endpoint_switching_subtitle": "PoveÅžite se lokalno preko naznačene Wi-Fi mreÅže kada je dostupna i koristite alternativne veze na drugim lokacijama", + "automatic_endpoint_switching_title": "Automatsko prebacivanje URL-a", "back": "Nazad", "back_close_deselect": "Natrag, zatvorite ili poniÅĄtite odabir", + "background_location_permission": "Dozvola za lokaciju u pozadini", + "background_location_permission_content": "Kako bi prebacivao mreÅže dok radi u pozadini, Immich mora *uvijek* imati pristup preciznoj lokaciji kako bi aplikacija mogla pročitati naziv Wi-Fi mreÅže", + "backup_album_selection_page_albums_device": "Albumi na uređaju {{}}", + "backup_album_selection_page_albums_tap": "Dodirnite za uključivanje, dvostruki dodir za isključivanje", + "backup_album_selection_page_assets_scatter": "Resursi mogu biti raspoređeni u viÅĄe albuma. Stoga, albumi mogu biti uključeni ili isključeni tijekom procesa sigurnosnog kopiranja.", + "backup_album_selection_page_select_albums": "Odabrani albumi", + "backup_album_selection_page_selection_info": "Informacije o odabiru", + "backup_album_selection_page_total_assets": "Ukupan broj jedinstvenih resursa", + "backup_all": "Sve", + "backup_background_service_backup_failed_message": "NeuspjeÅĄno sigurnosno kopiranje resursa. PokuÅĄavam ponovoâ€Ļ", + "backup_background_service_connection_failed_message": "NeuspjeÅĄno povezivanje s posluÅžiteljem. PokuÅĄavam ponovoâ€Ļ", + "backup_background_service_current_upload_notification": "Å aljem {}", + "backup_background_service_default_notification": "Provjera novih resursaâ€Ļ", + "backup_background_service_error_title": "PogreÅĄka pri sigurnosnom kopiranju", + "backup_background_service_in_progress_notification": "Sigurnosno kopiranje vaÅĄih resursaâ€Ļ", + "backup_background_service_upload_failure_notification": "NeuspjeÅĄno slanje {}", + "backup_controller_page_albums": "Sigurnosno kopiranje albuma", + "backup_controller_page_background_app_refresh_disabled_content": "Omogućite osvjeÅžavanje aplikacije u pozadini u Postavke > Opće Postavke > OsvjeÅžavanje Aplikacija u Pozadini kako biste koristili sigurnosno kopiranje u pozadini.", + "backup_controller_page_background_app_refresh_disabled_title": "OsvjeÅžavanje aplikacija u pozadini je onemogućeno", + "backup_controller_page_background_app_refresh_enable_button_text": "Idite u postavke", + "backup_controller_page_background_battery_info_link": "PokaÅži mi kako", + "backup_controller_page_background_battery_info_message": "Za najbolje iskustvo sigurnosnog kopiranja u pozadini, molimo onemogućite sve optimizacije baterije koje ograničavaju pozadinsku aktivnost Immicha.\n\nBudući da je ovo specifično za uređaj, molimo potraÅžite potrebne informacije za proizvođača vaÅĄeg uređaja.", + "backup_controller_page_background_battery_info_ok": "U redu", + "backup_controller_page_background_battery_info_title": "Optimizacije baterije", + "backup_controller_page_background_charging": "Samo tijekom punjenja", + "backup_controller_page_background_configure_error": "NeuspjeÅĄno konfiguriranje pozadinske usluge", + "backup_controller_page_background_delay": "Odgođeno sigurnosno kopiranje novih resursa: {}", + "backup_controller_page_background_description": "Uključite pozadinsku uslugu kako biste automatski sigurnosno kopirali nove resurse bez potrebe za otvaranjem aplikacije", + "backup_controller_page_background_is_off": "Automatsko sigurnosno kopiranje u pozadini je isključeno", + "backup_controller_page_background_is_on": "Automatsko sigurnosno kopiranje u pozadini je uključeno", + "backup_controller_page_background_turn_off": "Isključite pozadinsku uslugu", + "backup_controller_page_background_turn_on": "Uključite pozadinsku uslugu", + "backup_controller_page_background_wifi": "Samo na Wi-Fi mreÅži", + "backup_controller_page_backup": "Sigurnosna kopija", + "backup_controller_page_backup_selected": "Odabrani: ", + "backup_controller_page_backup_sub": "Sigurnosno kopirane fotografije i videozapisi", + "backup_controller_page_created": "Kreirano: {}", + "backup_controller_page_desc_backup": "Uključite sigurnosno kopiranje u prvom planu kako biste automatski prenijeli nove resurse na posluÅžitelj prilikom otvaranja aplikacije.", + "backup_controller_page_excluded": "Izuzeto: ", + "backup_controller_page_failed": "NeuspjeÅĄno ({})", + "backup_controller_page_filename": "Naziv datoteke: {} [{}]", + "backup_controller_page_id": "ID: {}", + "backup_controller_page_info": "Informacije o sigurnosnom kopiranju", + "backup_controller_page_none_selected": "Nema odabranih", + "backup_controller_page_remainder": "Podsjetnik", + "backup_controller_page_remainder_sub": "Preostale fotografije i videozapisi za sigurnosno kopiranje iz odabira", + "backup_controller_page_server_storage": "Pohrana na posluÅžitelju", + "backup_controller_page_start_backup": "Pokreni Sigurnosno Kopiranje", + "backup_controller_page_status_off": "Automatsko sigurnosno kopiranje u prvom planu je isključeno", + "backup_controller_page_status_on": "Automatsko sigurnosno kopiranje u prvom planu je uključeno", + "backup_controller_page_storage_format": "{} od {} iskoriÅĄteno", + "backup_controller_page_to_backup": "Albumi za sigurnosno kopiranje", + "backup_controller_page_total_sub": "Sve jedinstvene fotografije i videozapisi iz odabranih albuma", + "backup_controller_page_turn_off": "Isključite sigurnosno kopiranje u prvom planu", + "backup_controller_page_turn_on": "Uključite sigurnosno kopiranje u prvom planu", + "backup_controller_page_uploading_file_info": "Slanje informacija o datoteci", + "backup_err_only_album": "Nije moguće ukloniti jedini album", + "backup_info_card_assets": "resursi", + "backup_manual_cancelled": "Otkazano", + "backup_manual_in_progress": "Slanje već u tijeku. PokÅĄuajte nakon nekog vremena", + "backup_manual_success": "Uspijeh", + "backup_manual_title": "Status slanja", + "backup_options_page_title": "Opcije sigurnosnog kopiranja", + "backup_setting_subtitle": "Upravljajte postavkama učitavanja u pozadini i prvom planu", "backward": "Unazad", "birthdate_saved": "Datum rođenja uspjeÅĄno spremljen", "birthdate_set_description": "Datum rođenja se koristi za izračunavanje godina ove osobe u trenutku fotografije.", @@ -429,6 +574,16 @@ "bulk_keep_duplicates_confirmation": "Jeste li sigurni da Åželite zadrÅžati {count, plural, one {# duplicate asset} other {# duplicate asset}}? Ovo će rijeÅĄiti sve duplicirane grupe bez brisanja ičega.", "bulk_trash_duplicates_confirmation": "Jeste li sigurni da Åželite na veliko baciti u smeće {count, plural, one {# duplicate asset} other {# duplicate asset}}? Ovo će zadrÅžati najveće sredstvo svake grupe i baciti sve ostale duplikate u smeće.", "buy": "Kupi Immich", + "cache_settings_album_thumbnails": "Sličice na stranici biblioteke ({} resursa)", + "cache_settings_clear_cache_button": "Očisti predmemoriju", + "cache_settings_clear_cache_button_title": "BriÅĄe predmemoriju aplikacije. Ovo će značajno utjecati na performanse aplikacije dok se predmemorija ponovno ne izgradi.", + "cache_settings_duplicated_assets_clear_button": "OČISTI", + "cache_settings_duplicated_assets_subtitle": "Fotografije i videozapisi koje je aplikacija stavila na crnu listu", + "cache_settings_duplicated_assets_title": "Duplicirani Resursi ({})", + "cache_settings_image_cache_size": "Veličina predmemorije slika ({} resursa)", + "cache_settings_statistics_album": "Sličice biblioteke", + "cache_settings_statistics_assets": "{} resursa ({})", + "cache_settings_statistics_full": "Pune slike", "camera": "Kamera", "camera_brand": "Marka kamere", "camera_model": "Model kamere", @@ -760,6 +915,8 @@ "hide_unnamed_people": "Sakrij neimenovane osobe", "host": "Domaćin", "hour": "Sat", + "ignore_icloud_photos": "Ignoriraj iCloud fotografije", + "ignore_icloud_photos_description": "Fotografije pohranjene na iCloudu neće biti učitane na Immich posluÅžitelj", "image": "Slika", "image_alt_text_date": "{isVideo, select, true {Video} other {Image}} snimljeno {date}", "image_alt_text_date_1_person": "{isVideo, select, true {Video} other {Image}} snimljeno s {person1} {date}", @@ -771,6 +928,10 @@ "image_alt_text_date_place_2_people": "{isVideo, select, true {Video} other {Image}} snimljeno u {city}, {country} s {person1} i {person2} {date}", "image_alt_text_date_place_3_people": "{isVideo, select, true {Video} other {Image}} snimljeno u {city}, {country} s {person1}, {person2} i {person3} {date}", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Video} other {Image}} snimljeno u {city}, {country} s {person1}, {person2} i {additionalCount, number} drugih {date}", + "image_saved_successfully": "Slika je spremljena", + "image_viewer_page_state_provider_download_started": "Preuzimanje započelo", + "image_viewer_page_state_provider_download_success": "UspjeÅĄno Preuzimanje", + "image_viewer_page_state_provider_share_error": "GreÅĄka pri dijeljenju", "immich_logo": "Immich Logo", "immich_web_interface": "Immich Web Sučelje", "import_from_json": "Uvoz iz JSON-a", diff --git a/i18n/hu.json b/i18n/hu.json index 68dec7d036..88ce6033f8 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -529,11 +529,11 @@ "backup_controller_page_background_turn_on": "HÃĄttÊrszolgÃĄltatÃĄs bekapcsolÃĄsa", "backup_controller_page_background_wifi": "Csak WiFi-n", "backup_controller_page_backup": "MentÊs", - "backup_controller_page_backup_selected": "KivÃĄlasztva:", + "backup_controller_page_backup_selected": "KivÃĄlasztva: ", "backup_controller_page_backup_sub": "Mentett fotÃŗk Ês videÃŗk", "backup_controller_page_created": "LÊtrehozva: {}", "backup_controller_page_desc_backup": "Ha bekapcsolod az előtÊrben mentÊst, akkor az Ãēj elemek automatikusan feltÃļltődnek a szerverre, amikor megyitod az alkalmazÃĄst.", - "backup_controller_page_excluded": "KivÊve:", + "backup_controller_page_excluded": "KivÊve: ", "backup_controller_page_failed": "Sikertelen ({})", "backup_controller_page_filename": "FÃĄjlnÊv: {}[{}]", "backup_controller_page_id": "AzonosítÃŗ: {}", @@ -1540,7 +1540,7 @@ "search_result_page_new_search_hint": "Új KeresÊs", "search_settings": "KeresÊsi beÃĄllítÃĄsok", "search_state": "Megye/Állam keresÊse...", - "search_suggestion_list_smart_search_hint_1": "Az intelligens keresÊs alapÊrtelmezetten be van kapcsolva, metaadatokat így kereshetsz:", + "search_suggestion_list_smart_search_hint_1": "Az intelligens keresÊs alapÊrtelmezetten be van kapcsolva, metaadatokat így kereshetsz: ", "search_suggestion_list_smart_search_hint_2": "m:keresÊsi-kifejezÊs", "search_tags": "CímkÊk keresÊse...", "search_timezone": "IdőzÃŗna keresÊse...", diff --git a/i18n/id.json b/i18n/id.json index e07e79faff..1d500654dc 100644 --- a/i18n/id.json +++ b/i18n/id.json @@ -39,11 +39,11 @@ "authentication_settings_disable_all": "Anda yakin untuk menonaktifkan semua cara login? Login akan dinonaktikan secara menyeluruh.", "authentication_settings_reenable": "Untuk mengaktifkan ulang, gunakan Perintah Server.", "background_task_job": "Tugas Latar Belakang", - "backup_database": "Basis Data Cadangan", + "backup_database": "Buat Cadangan Basis Data", "backup_database_enable_description": "Aktifkan pencadangan basis data", "backup_keep_last_amount": "Jumlah cadangan untuk disimpan", - "backup_settings": "Pengaturan Pencadangan", - "backup_settings_description": "Kelola pengaturan pencadangan basis data", + "backup_settings": "Pengaturan Pencadangan Basis Data", + "backup_settings_description": "Kelola pengaturan pencadangan basis data. Catatan: Tugas ini tidak dipantau dan Anda tidak akan diberi tahu jika ada kesalahan.", "check_all": "Periksa Semua", "cleanup": "Pembersihan", "cleared_jobs": "Tugas terselesaikan untuk: {job}", @@ -70,8 +70,13 @@ "forcing_refresh_library_files": "Memaksakan penyegaran semua berkas pustaka", "image_format": "Format", "image_format_description": "WebP menghasilkan ukuran berkas yang lebih kecil daripada JPEG, tetapi lebih lambat untuk dienkode.", + "image_fullsize_description": "Gambar berukuran penuh tanpa metadata, digunakan ketika diperbesar", + "image_fullsize_enabled": "Aktifkan pembuatan gambar berukuran penuh", + "image_fullsize_enabled_description": "Buat gambar berukuran penuh untuk format yang tidak ramah web. Ketika \"Utamakan pratinjau tersemat\" diaktifkan, pratinjau tersema digunakan secara langsung tanpa konversi. Tidak memengaruhi format ramah web seperti JPEG.", + "image_fullsize_quality_description": "Kualitas gambar berukuran penuh dari 1-100. Lebih tinggi lebih baik, tetapi menghasilkan berkas lebih besar.", + "image_fullsize_title": "Pengaturan Gambar Berukuran Penuh", "image_prefer_embedded_preview": "Utamakan pratinjau tersemat", - "image_prefer_embedded_preview_setting_description": "Gunakan pratinjau tersemat dalam foto RAW sebagai masukan dalam pemrosesan gambar ketika tersedia. Ini dapat menghasilkan warna yang lebih akurat untuk beberapa gambar, tetapi kualitas pratinjau bergantung pada kamera dan gambarnya dapat memiliki lebih banyak artefak kompresi.", + "image_prefer_embedded_preview_setting_description": "Gunakan pratinjau tersemat dalam foto RAW sebagai masukan dalam pemrosesan gambar dan ketika tersedia. Ini dapat menghasilkan warna yang lebih akurat untuk beberapa gambar, tetapi kualitas pratinjau bergantung pada kamera dan gambarnya dapat memiliki lebih banyak artefak kompresi.", "image_prefer_wide_gamut": "Utamakan gamut luas", "image_prefer_wide_gamut_setting_description": "Gunakan Display P3 untuk gambar kecil. Ini menjaga kecerahan gambar dengan ruang warna yang luas, tetapi gambar dapat terlihat beda pada perangkat lawas dengan versi peramban yang lawas. Gambar sRGB tetap dalam sRGB untuk menghindari perubahan warna.", "image_preview_description": "Gambar berukuran sedang tanpa metadata, digunakan ketika melihat aset satuan dan untuk pembelajaran mesin", @@ -366,13 +371,17 @@ "admin_password": "Kata Sandi Admin", "administration": "Administrasi", "advanced": "Tingkat lanjut", - "advanced_settings_log_level_title": "Log level: {}", + "advanced_settings_enable_alternate_media_filter_subtitle": "Gunakan opsi ini untuk menyaring media saat sinkronisasi berdasarkan kriteria alternatif. Hanya coba ini dengan aplikasi mendeteksi semua album.", + "advanced_settings_enable_alternate_media_filter_title": "[EKSPERIMENTAL] Gunakan saringan sinkronisasi album perangkat alternatif", + "advanced_settings_log_level_title": "Tingkat log: {}", "advanced_settings_prefer_remote_subtitle": "Beberapa perangkat tidak dapat memuat thumbnail dengan cepat.\nMenyalakan ini akan memuat thumbnail dari server.", "advanced_settings_prefer_remote_title": "Prefer remote images", "advanced_settings_proxy_headers_subtitle": "Define proxy headers Immich should send with each network request", "advanced_settings_proxy_headers_title": "Proxy Headers", "advanced_settings_self_signed_ssl_subtitle": "Skips SSL certificate verification for the server endpoint. Required for self-signed certificates.", "advanced_settings_self_signed_ssl_title": "Allow self-signed SSL certificates", + "advanced_settings_sync_remote_deletions_subtitle": "Hapus atau pulihkan aset pada perangkat ini secara otomatis ketika tindakan dilakukan di web", + "advanced_settings_sync_remote_deletions_title": "Sinkronisasi penghapusan jarak jauh [EKSPERIMENTAL]", "advanced_settings_tile_subtitle": "Advanced user's settings", "advanced_settings_troubleshooting_subtitle": "Enable additional features for troubleshooting", "advanced_settings_troubleshooting_title": "Troubleshooting", @@ -472,7 +481,7 @@ "assets_added_to_album_count": "Ditambahkan {count, plural, one {# aset} other {# aset}} ke album", "assets_added_to_name_count": "Ditambahkan {count, plural, one {# aset} other {# aset}} ke {hasName, select, true {{name}} other {album baru}}", "assets_count": "{count, plural, one {# aset} other {# aset}}", - "assets_deleted_permanently": "{} asset(s) deleted permanently", + "assets_deleted_permanently": "{} asset dihapus secara permanen", "assets_deleted_permanently_from_server": "{} asset(s) deleted permanently from the Immich server", "assets_moved_to_trash_count": "Dipindahkan {count, plural, one {# aset} other {# aset}} ke sampah", "assets_permanently_deleted_count": "{count, plural, one {# aset} other {# aset}} dihapus secara permanen", @@ -505,7 +514,7 @@ "backup_background_service_default_notification": "Memeriksa aset baru...", "backup_background_service_error_title": "Backup error", "backup_background_service_in_progress_notification": "Mencadangkan asetmu...", - "backup_background_service_upload_failure_notification": "Gagal unggah {}", + "backup_background_service_upload_failure_notification": "Gagal mengunggah {}", "backup_controller_page_albums": "Cadangkan album", "backup_controller_page_background_app_refresh_disabled_content": "Enable background app refresh in Settings > General > Background App Refresh in order to use background backup.", "backup_controller_page_background_app_refresh_disabled_title": "Background app refresh disabled", @@ -524,11 +533,11 @@ "backup_controller_page_background_turn_on": "Nyalakan layanan latar belakang", "backup_controller_page_background_wifi": "Hanya melalui WiFi", "backup_controller_page_backup": "Cadangkan", - "backup_controller_page_backup_selected": "Terpilih:", + "backup_controller_page_backup_selected": "Terpilih: ", "backup_controller_page_backup_sub": "Foto dan video yang dicadangkan", "backup_controller_page_created": "Dibuat pada: {}", "backup_controller_page_desc_backup": "Aktifkan pencadangan di latar depan untuk mengunggah otomatis aset baru ke server secara otomatis saat aplikasi terbuka.", - "backup_controller_page_excluded": "Dikecualikan:", + "backup_controller_page_excluded": "Dikecualikan: ", "backup_controller_page_failed": "Gagal ({})", "backup_controller_page_filename": "Nama file: {} [{}]", "backup_controller_page_id": "ID: {}", @@ -601,7 +610,7 @@ "change_password": "Ubah Kata Sandi", "change_password_description": "Ini merupakan pertama kali Anda masuk ke sistem atau ada permintaan untuk mengubah kata sandi Anda. Silakan masukkan kata sandi baru di bawah.", "change_password_form_confirm_password": "Konfirmasi Sandi", - "change_password_form_description": "Halo {},\n\nIni pertama kali anda masuk ke dalam sistem atau terdapat permintaan penggantian password.\nHarap masukkan password baru.", + "change_password_form_description": "Halo {name},\n\nIni pertama kali anda masuk ke dalam sistem atau terdapat permintaan penggantian password.\nHarap masukkan password baru.", "change_password_form_new_password": "Sandi Baru", "change_password_form_password_mismatch": "Sandi tidak cocok", "change_password_form_reenter_new_password": "Masukkan Ulang Sandi Baru", @@ -814,7 +823,7 @@ "error_change_sort_album": "Failed to change album sort order", "error_delete_face": "Terjadi kesalahan menghapus wajah dari aset", "error_loading_image": "Terjadi eror memuat gambar", - "error_saving_image": "Error: {}", + "error_saving_image": "Kesalahan: {}", "error_title": "Eror - Ada yang salah", "errors": { "cannot_navigate_next_asset": "Tidak dapat menuju ke aset berikutnya", @@ -948,10 +957,10 @@ "exif_bottom_sheet_location": "LOKASI", "exif_bottom_sheet_people": "ORANG", "exif_bottom_sheet_person_add_person": "Tambah nama", - "exif_bottom_sheet_person_age": "Age {}", - "exif_bottom_sheet_person_age_months": "Age {} months", - "exif_bottom_sheet_person_age_year_months": "Age 1 year, {} months", - "exif_bottom_sheet_person_age_years": "Age {}", + "exif_bottom_sheet_person_age": "Umur {}", + "exif_bottom_sheet_person_age_months": "Umur {} months", + "exif_bottom_sheet_person_age_year_months": "Umur 1 tahun, {} bulan", + "exif_bottom_sheet_person_age_years": "Umur {}", "exit_slideshow": "Keluar dari Salindia", "expand_all": "Buka semua", "experimental_settings_new_asset_list_subtitle": "Memproses", @@ -969,7 +978,7 @@ "external": "Eksternal", "external_libraries": "Pustaka Eksternal", "external_network": "External network", - "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", + "external_network_sheet_info": "When not on the preferred Wi-Fi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "face_unassigned": "Tidak ada nama", "failed": "Failed", "failed_to_load_assets": "Gagal memuat aset", @@ -987,6 +996,7 @@ "filetype": "Jenis berkas", "filter": "Filter", "filter_people": "Saring orang", + "filter_places": "Saring tempat", "find_them_fast": "Temukan dengan cepat berdasarkan nama dengan pencarian", "fix_incorrect_match": "Perbaiki pencocokan salah", "folder": "Folder", @@ -1155,6 +1165,7 @@ "loop_videos": "Ulangi video", "loop_videos_description": "Aktifkan untuk mengulangi video secara otomatis dalam penampil detail.", "main_branch_warning": "Anda menggunakan versi pengembangan; kami sangat menyarankan menggunakan versi rilis!", + "main_menu": "Menu utama", "make": "Merek", "manage_shared_links": "Kelola tautan terbagi", "manage_sharing_with_partners": "Kelola pembagian dengan partner", @@ -1276,6 +1287,7 @@ "onboarding_welcome_user": "Selamat datang, {user}", "online": "Daring", "only_favorites": "Hanya favorit", + "open": "Buka", "open_in_map_view": "Buka dalam tampilan peta", "open_in_openstreetmap": "Buka di OpenStreetMap", "open_the_search_filters": "Buka saringan pencarian", @@ -1299,7 +1311,7 @@ "partner_page_partner_add_failed": "Gagal menambahkan partner", "partner_page_select_partner": "Pilih partner", "partner_page_shared_to_title": "Dibagikan dengan", - "partner_page_stop_sharing_content": "{} tidak akan bisa mengakses foto kamu lagi.", + "partner_page_stop_sharing_content": "{} tidak akan bisa mengakses foto Anda lagi.", "partner_sharing": "Pembagian Partner", "partners": "Partner", "password": "Kata sandi", @@ -1420,6 +1432,8 @@ "recent_searches": "Pencarian terkini", "recently_added": "Recently added", "recently_added_page_title": "Baru Ditambahkan", + "recently_taken": "Diambil terkini", + "recently_taken_page_title": "Diambil Terkini", "refresh": "Segarkan", "refresh_encoded_videos": "Segarkan video terenkode", "refresh_faces": "Segarkan wajah", @@ -1620,7 +1634,7 @@ "shared_intent_upload_button_progress_text": "{} / {} Uploaded", "shared_link_app_bar_title": "Link Berbagi", "shared_link_clipboard_copied_massage": "Tersalin ke papan klip", - "shared_link_clipboard_text": "Link: {}\nSandi: {}", + "shared_link_clipboard_text": "Tautan: {}\nSandi: {}", "shared_link_create_error": "Terjadi kesalahan saat membuat link berbagi", "shared_link_edit_description_hint": "Masukkan deskripsi link", "shared_link_edit_expire_after_option_day": "1 hari", @@ -1866,6 +1880,7 @@ "view_name": "Tampilkan", "view_next_asset": "Tampilkan aset berikutnya", "view_previous_asset": "Tampilkan aset sebelumnya", + "view_qr_code": "Tampilkan kode QR", "view_stack": "Tampilkan Tumpukan", "viewer_remove_from_stack": "Keluarkan dari Tumpukan", "viewer_stack_use_as_main_asset": "Gunakan sebagai aset utama", diff --git a/i18n/it.json b/i18n/it.json index 01aeb93721..987ad34d2d 100644 --- a/i18n/it.json +++ b/i18n/it.json @@ -371,13 +371,17 @@ "admin_password": "Password Amministratore", "administration": "Amministrazione", "advanced": "Avanzate", + "advanced_settings_enable_alternate_media_filter_subtitle": "Usa questa opzione per filtrare i contenuti multimediali durante la sincronizzazione in base a criteri alternativi. Prova questa opzione solo se riscontri problemi con il rilevamento di tutti gli album da parte dell'app.", + "advanced_settings_enable_alternate_media_filter_title": "[SPERIMENTALE] Usa un filtro alternativo per la sincronizzazione degli album del dispositivo", "advanced_settings_log_level_title": "Livello log: {}", "advanced_settings_prefer_remote_subtitle": "Alcuni dispositivi sono molto lenti a caricare le anteprime delle immagini dal dispositivo. Attivare questa impostazione per caricare invece le immagini remote.", - "advanced_settings_prefer_remote_title": "Preferisci immagini remote.", - "advanced_settings_proxy_headers_subtitle": "Define proxy headers Immich should send with each network request", + "advanced_settings_prefer_remote_title": "Preferisci immagini remote", + "advanced_settings_proxy_headers_subtitle": "Definisci gli header per i proxy che Immich dovrebbe inviare con ogni richiesta di rete", "advanced_settings_proxy_headers_title": "Proxy Headers", "advanced_settings_self_signed_ssl_subtitle": "Salta la verifica dei certificati SSL del server. Richiesto con l'uso di certificati self-signed.", "advanced_settings_self_signed_ssl_title": "Consenti certificati SSL self-signed", + "advanced_settings_sync_remote_deletions_subtitle": "Rimuovi o ripristina automaticamente un elemento su questo dispositivo se l'azione è stata fatta via web", + "advanced_settings_sync_remote_deletions_title": "Sincronizza le cancellazioni remote [SPERIMENTALE]", "advanced_settings_tile_subtitle": "Impostazioni aggiuntive utenti", "advanced_settings_troubleshooting_subtitle": "Attiva funzioni addizionali per la risoluzione dei problemi", "advanced_settings_troubleshooting_title": "Risoluzione problemi", @@ -399,19 +403,19 @@ "album_remove_user": "Rimuovi l'utente?", "album_remove_user_confirmation": "Sicuro di voler rimuovere l'utente {user}?", "album_share_no_users": "Sembra che tu abbia condiviso questo album con tutti gli utenti oppure non hai nessun utente con cui condividere.", - "album_thumbnail_card_item": "1 elemento ", + "album_thumbnail_card_item": "1 elemento", "album_thumbnail_card_items": "{} elementi", - "album_thumbnail_card_shared": "Condiviso", + "album_thumbnail_card_shared": " ¡ Condiviso", "album_thumbnail_shared_by": "Condiviso da {}", "album_updated": "Album aggiornato", "album_updated_setting_description": "Ricevi una notifica email quando un album condiviso ha nuovi media", "album_user_left": "{album} abbandonato", "album_user_removed": "Utente {user} rimosso", "album_viewer_appbar_delete_confirm": "Sei sicuro di voler rimuovere questo album dal tuo account?", - "album_viewer_appbar_share_err_delete": "Impossibile eliminare l'album ", - "album_viewer_appbar_share_err_leave": "Impossibile lasciare l'album ", - "album_viewer_appbar_share_err_remove": "Ci sono problemi nel rimuovere oggetti dall'album ", - "album_viewer_appbar_share_err_title": "Impossibile cambiare il titolo dell'album ", + "album_viewer_appbar_share_err_delete": "Impossibile eliminare l'album", + "album_viewer_appbar_share_err_leave": "Impossibile lasciare l'album", + "album_viewer_appbar_share_err_remove": "Ci sono problemi nel rimuovere oggetti dall'album", + "album_viewer_appbar_share_err_title": "Impossibile cambiare il titolo dell'album", "album_viewer_appbar_share_leave": "Lascia album", "album_viewer_appbar_share_to": "Condividi a", "album_viewer_page_share_add_users": "Aggiungi utenti", @@ -440,7 +444,7 @@ "archive": "Archivio", "archive_or_unarchive_photo": "Archivia o ripristina foto", "archive_page_no_archived_assets": "Nessuna oggetto archiviato", - "archive_page_title": "Archivia ({})", + "archive_page_title": "Archivio ({})", "archive_size": "Dimensioni Archivio", "archive_size_description": "Imposta le dimensioni dell'archivio per i download (in GiB)", "archived": "Archiviati", @@ -477,18 +481,18 @@ "assets_added_to_album_count": "{count, plural, one {# asset aggiunto} other {# asset aggiunti}} all'album", "assets_added_to_name_count": "Aggiunti {count, plural, one {# asset} other {# assets}} a {hasName, select, true {{name}} other {new album}}", "assets_count": "{count, plural, other {# asset}}", - "assets_deleted_permanently": "{} asset(s) deleted permanently", - "assets_deleted_permanently_from_server": "{} asset(s) deleted permanently from the Immich server", + "assets_deleted_permanently": "{} elementi rimossi definitivamente", + "assets_deleted_permanently_from_server": "{} elementi rimossi definitivamente dal server Immich", "assets_moved_to_trash_count": "{count, plural, one {# asset spostato} other {# asset spostati}} nel cestino", "assets_permanently_deleted_count": "{count, plural, one {# asset cancellato} other {# asset cancellati}} definitivamente", "assets_removed_count": "{count, plural, one {# asset rimosso} other {# asset rimossi}}", - "assets_removed_permanently_from_device": "{} asset(s) removed permanently from your device", + "assets_removed_permanently_from_device": "{} elementi rimossi definitivamente dal tuo dispositivo", "assets_restore_confirmation": "Sei sicuro di voler ripristinare tutti gli asset cancellati? Non puoi annullare questa azione! Tieni presente che eventuali risorse offline NON possono essere ripristinate in questo modo.", "assets_restored_count": "{count, plural, one {# asset ripristinato} other {# asset ripristinati}}", - "assets_restored_successfully": "{} asset(s) restored successfully", - "assets_trashed": "{} asset(s) trashed", + "assets_restored_successfully": "{} elementi ripristinati", + "assets_trashed": "{} elementi cestinati", "assets_trashed_count": "{count, plural, one {Spostato # asset} other {Spostati # assets}} nel cestino", - "assets_trashed_from_server": "{} asset(s) trashed from the Immich server", + "assets_trashed_from_server": "{} elementi cestinati dal server Immich", "assets_were_part_of_album_count": "{count, plural, one {L'asset era} other {Gli asset erano}} già parte dell'album", "authorized_devices": "Dispositivi autorizzati", "automatic_endpoint_switching_subtitle": "Connetti localmente quando la rete Wi-Fi specificata è disponibile e usa le connessioni alternative negli altri casi", @@ -498,7 +502,7 @@ "background_location_permission": "Permesso di localizzazione in background", "background_location_permission_content": "Per fare in modo che sia possibile cambiare rete quando è in esecuzione in background, Immich deve *sempre* avere accesso alla tua posizione precisa in modo da poter leggere il nome della rete Wi-Fi", "backup_album_selection_page_albums_device": "Album sul dispositivo ({})", - "backup_album_selection_page_albums_tap": "Tap per includere, doppio tap per escludere.", + "backup_album_selection_page_albums_tap": "Tap per includere, doppio tap per escludere", "backup_album_selection_page_assets_scatter": "Visto che le risorse possono trovarsi in piÚ album, questi possono essere inclusi o esclusi dal backup.", "backup_album_selection_page_select_albums": "Seleziona gli album", "backup_album_selection_page_selection_info": "Informazioni sulla selezione", @@ -529,11 +533,11 @@ "backup_controller_page_background_turn_on": "Abilita servizi in background", "backup_controller_page_background_wifi": "Solo su WiFi", "backup_controller_page_backup": "Backup", - "backup_controller_page_backup_selected": "Selezionati:", + "backup_controller_page_backup_selected": "Selezionati: ", "backup_controller_page_backup_sub": "Foto e video caricati", "backup_controller_page_created": "Creato il: {}", "backup_controller_page_desc_backup": "Attiva il backup per eseguire il caricamento automatico sul server all'apertura dell'applicazione.", - "backup_controller_page_excluded": "Esclusi:", + "backup_controller_page_excluded": "Esclusi: ", "backup_controller_page_failed": "Falliti: ({})", "backup_controller_page_filename": "Nome file: {} [{}]", "backup_controller_page_id": "ID: {}", @@ -543,18 +547,18 @@ "backup_controller_page_remainder_sub": "Foto e video che devono essere ancora caricati", "backup_controller_page_server_storage": "Spazio sul server", "backup_controller_page_start_backup": "Avvia backup", - "backup_controller_page_status_off": "Backup è disattivato ", + "backup_controller_page_status_off": "Backup è disattivato", "backup_controller_page_status_on": "Backup è attivato", "backup_controller_page_storage_format": "{} di {} usati", "backup_controller_page_to_backup": "Album da caricare", - "backup_controller_page_total_sub": "Tutte le foto e i video unici caricati dagli album selezionati ", + "backup_controller_page_total_sub": "Tutte le foto e i video unici caricati dagli album selezionati", "backup_controller_page_turn_off": "Disattiva backup", - "backup_controller_page_turn_on": "Attiva backup ", + "backup_controller_page_turn_on": "Attiva backup", "backup_controller_page_uploading_file_info": "Caricamento informazioni file", "backup_err_only_album": "Non è possibile rimuovere l'unico album", "backup_info_card_assets": "risorse", "backup_manual_cancelled": "Annullato", - "backup_manual_in_progress": "Caricamento già in corso. Riprova piÚ tardi.", + "backup_manual_in_progress": "Caricamento già in corso. Riprova piÚ tardi", "backup_manual_success": "Successo", "backup_manual_title": "Stato del caricamento", "backup_options_page_title": "Opzioni di Backup", @@ -570,21 +574,21 @@ "bulk_keep_duplicates_confirmation": "Sei sicuro di voler tenere {count, plural, one {# asset duplicato} other {# assets duplicati}}? Questa operazione risolverà tutti i gruppi duplicati senza cancellare nulla.", "bulk_trash_duplicates_confirmation": "Sei davvero sicuro di voler cancellare {count, plural, one {# asset duplicato} other {# assets duplicati}}? Questa operazione manterrà l'asset piÚ pesante di ogni gruppo e cancellerà permanentemente tutti gli altri duplicati.", "buy": "Acquista Immich", - "cache_settings_album_thumbnails": "Anteprime pagine librerie ({} risorse)", + "cache_settings_album_thumbnails": "Anteprime pagine librerie ({} elementi)", "cache_settings_clear_cache_button": "Pulisci cache", "cache_settings_clear_cache_button_title": "Pulisce la cache dell'app. Questo impatterà significativamente le prestazioni dell''app fino a quando la cache non sarà rigenerata.", "cache_settings_duplicated_assets_clear_button": "PULISCI", "cache_settings_duplicated_assets_subtitle": "Foto e video che sono nella black list dell'applicazione", "cache_settings_duplicated_assets_title": "Elementi duplicati ({})", - "cache_settings_image_cache_size": "Dimensione cache delle immagini ({} risorse)", + "cache_settings_image_cache_size": "Dimensione cache delle immagini ({} elementi)", "cache_settings_statistics_album": "Anteprime librerie", - "cache_settings_statistics_assets": "{} risorse ({})", + "cache_settings_statistics_assets": "{} elementi ({})", "cache_settings_statistics_full": "Immagini complete", "cache_settings_statistics_shared": "Anteprime album condivisi", "cache_settings_statistics_thumbnail": "Anteprime", "cache_settings_statistics_title": "Uso della cache", "cache_settings_subtitle": "Controlla il comportamento della cache dell'applicazione mobile immich", - "cache_settings_thumbnail_size": "Dimensione cache dei thumbnail ({} assets)", + "cache_settings_thumbnail_size": "Dimensione cache anteprime ({} elementi)", "cache_settings_tile_subtitle": "Controlla il comportamento dello storage locale", "cache_settings_tile_title": "Archiviazione locale", "cache_settings_title": "Impostazioni della Cache", @@ -593,7 +597,7 @@ "camera_model": "Modello fotocamera", "cancel": "Annulla", "cancel_search": "Annulla ricerca", - "canceled": "Canceled", + "canceled": "Annullato", "cannot_merge_people": "Impossibile unire le persone", "cannot_undo_this_action": "Non puoi annullare questa azione!", "cannot_update_the_description": "Impossibile aggiornare la descrizione", @@ -606,14 +610,14 @@ "change_password": "Modifica Password", "change_password_description": "È stato richiesto di cambiare la password (oppure è la prima volta che accedi). Inserisci la tua nuova password qui sotto.", "change_password_form_confirm_password": "Conferma Password", - "change_password_form_description": "Ciao {name},\n\nQuesto è la prima volta che accedi al sistema oppure è stato fatto una richiesta di cambiare la password. Per favore inserisca la nuova password qui sotto", + "change_password_form_description": "Ciao {name},\n\nQuesto è la prima volta che accedi al sistema oppure è stato fatto una richiesta di cambiare la password. Per favore inserisca la nuova password qui sotto.", "change_password_form_new_password": "Nuova Password", "change_password_form_password_mismatch": "Le password non coincidono", - "change_password_form_reenter_new_password": "Inserisci ancora la nuova password ", + "change_password_form_reenter_new_password": "Inserisci ancora la nuova password", "change_your_password": "Modifica la tua password", "changed_visibility_successfully": "Visibilità modificata con successo", "check_all": "Controlla Tutti", - "check_corrupt_asset_backup": "Verifica la presenza di backup di asset corrotti ", + "check_corrupt_asset_backup": "Verifica la presenza di backup di asset corrotti", "check_corrupt_asset_backup_button": "Effettua controllo", "check_corrupt_asset_backup_description": "Effettua questo controllo solo sotto rete Wi-Fi e quando tutti gli asset sono stati sottoposti a backup. La procedura potrebbe impiegare qualche minuto.", "check_logs": "Controlla i log", @@ -627,11 +631,11 @@ "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "Enter Password", "client_cert_import": "Import", - "client_cert_import_success_msg": "Client certificate is imported", - "client_cert_invalid_msg": "Invalid certificate file or wrong password", - "client_cert_remove_msg": "Client certificate is removed", - "client_cert_subtitle": "Supports PKCS12 (.p12, .pfx) format only. Certificate Import/Remove is available only before login", - "client_cert_title": "SSL Client Certificate", + "client_cert_import_success_msg": "Certificato client importato", + "client_cert_invalid_msg": "File certificato invalido o password errata", + "client_cert_remove_msg": "Certificato client rimosso", + "client_cert_subtitle": "Supporta solo il formato PKCS12 (.p12, .pfx). L'importazione/rimozione del certificato è disponibile solo prima del login", + "client_cert_title": "Certificato Client SSL", "clockwise": "Senso orario", "close": "Chiudi", "collapse": "Restringi", @@ -643,8 +647,8 @@ "comments_and_likes": "Commenti & mi piace", "comments_are_disabled": "I commenti sono disabilitati", "common_create_new_album": "Crea nuovo Album", - "common_server_error": "Si prega di controllare la connessione network, che il server sia raggiungibile e che le versione del server e app sono gli stessi", - "completed": "Completed", + "common_server_error": "Si prega di controllare la connessione network, che il server sia raggiungibile e che le versione del server e app sono gli stessi.", + "completed": "Completato", "confirm": "Conferma", "confirm_admin_password": "Conferma password dell'amministratore", "confirm_delete_face": "Sei sicuro di voler cancellare il volto di {name} dall'asset?", @@ -660,7 +664,7 @@ "control_bottom_app_bar_delete_from_local": "Elimina dal dispositivo", "control_bottom_app_bar_edit_location": "Modifica posizione", "control_bottom_app_bar_edit_time": "Modifica data e ora", - "control_bottom_app_bar_share_link": "Share Link", + "control_bottom_app_bar_share_link": "Condividi Link", "control_bottom_app_bar_share_to": "Condividi a", "control_bottom_app_bar_trash_from_immich": "Sposta nel cestino", "copied_image_to_clipboard": "Immagine copiata negli appunti.", @@ -772,12 +776,12 @@ "download_settings": "Scarica", "download_settings_description": "Gestisci le impostazioni relative al download delle risorse", "download_started": "Download avviato", - "download_sucess": "Download success", - "download_sucess_android": "The media has been downloaded to DCIM/Immich", + "download_sucess": "Download completato", + "download_sucess_android": "I contenuti multimediali sono stati scaricati in DCIM/Immich", "download_waiting_to_retry": "In attesa di riprovare", "downloading": "Scaricando", "downloading_asset_filename": "Scaricando la risorsa {filename}", - "downloading_media": "Downloading media", + "downloading_media": "Scaricamento file multimediali", "drop_files_to_upload": "Rilascia i file ovunque per caricarli", "duplicates": "Duplicati", "duplicates_description": "Risolvi ciascun gruppo indicando quali sono, se esistono, i duplicati", @@ -807,19 +811,19 @@ "editor_crop_tool_h2_aspect_ratios": "Proporzioni", "editor_crop_tool_h2_rotation": "Rotazione", "email": "Email", - "empty_folder": "This folder is empty", + "empty_folder": "La cartella è vuota", "empty_trash": "Svuota cestino", "empty_trash_confirmation": "Sei sicuro di volere svuotare il cestino? Questo rimuoverà tutte le risorse nel cestino in modo permanente da Immich.\nNon puoi annullare questa azione!", "enable": "Abilita", "enabled": "Abilitato", "end_date": "Data Fine", - "enqueued": "Enqueued", + "enqueued": "Accodato", "enter_wifi_name": "Inserisci il nome della rete Wi-Fi", "error": "Errore", "error_change_sort_album": "Errore nel cambiare l'ordine di degli album", "error_delete_face": "Errore nel cancellare la faccia dalla foto", "error_loading_image": "Errore nel caricamento dell'immagine", - "error_saving_image": "Error: {}", + "error_saving_image": "Errore: {}", "error_title": "Errore - Qualcosa è andato storto", "errors": { "cannot_navigate_next_asset": "Impossibile passare alla risorsa successiva", @@ -953,10 +957,10 @@ "exif_bottom_sheet_location": "POSIZIONE", "exif_bottom_sheet_people": "PERSONE", "exif_bottom_sheet_person_add_person": "Aggiungi nome", - "exif_bottom_sheet_person_age": "Age {}", - "exif_bottom_sheet_person_age_months": "Age {} months", - "exif_bottom_sheet_person_age_year_months": "Age 1 year, {} months", - "exif_bottom_sheet_person_age_years": "Age {}", + "exif_bottom_sheet_person_age": "Età {}", + "exif_bottom_sheet_person_age_months": "Età {} mesi", + "exif_bottom_sheet_person_age_year_months": "Età 1 anno e {} mesi", + "exif_bottom_sheet_person_age_years": "Età {}", "exit_slideshow": "Esci dalla presentazione", "expand_all": "Espandi tutto", "experimental_settings_new_asset_list_subtitle": "Lavori in corso", @@ -976,9 +980,9 @@ "external_network": "Rete esterna", "external_network_sheet_info": "Quando non si è connessi alla rete Wi-Fi preferita, l'app si collegherà al server tramite il primo degli indirizzi della lista che riuscirà a raggiungere, dall'alto verso il basso", "face_unassigned": "Non assegnata", - "failed": "Failed", + "failed": "Fallito", "failed_to_load_assets": "Impossibile caricare gli asset", - "failed_to_load_folder": "Failed to load folder", + "failed_to_load_folder": "Impossibile caricare la cartella", "favorite": "Preferito", "favorite_or_unfavorite_photo": "Aggiungi o rimuovi foto da preferiti", "favorites": "Preferiti", @@ -992,10 +996,11 @@ "filetype": "Tipo file", "filter": "Filtro", "filter_people": "Filtra persone", + "filter_places": "Filtra luoghi", "find_them_fast": "Trovale velocemente con la ricerca", "fix_incorrect_match": "Correggi corrispondenza errata", - "folder": "Folder", - "folder_not_found": "Folder not found", + "folder": "Cartella", + "folder_not_found": "Cartella non trovata", "folders": "Cartelle", "folders_feature_description": "Navigare la visualizzazione a cartelle per le foto e i video sul file system", "forward": "Avanti", @@ -1016,12 +1021,12 @@ "haptic_feedback_switch": "Abilita feedback aptico", "haptic_feedback_title": "Feedback aptico", "has_quota": "Ha limite", - "header_settings_add_header_tip": "Add Header", - "header_settings_field_validator_msg": "Value cannot be empty", - "header_settings_header_name_input": "Header name", - "header_settings_header_value_input": "Header value", - "headers_settings_tile_subtitle": "Define proxy headers the app should send with each network request", - "headers_settings_tile_title": "Custom proxy headers", + "header_settings_add_header_tip": "Aggiungi Header", + "header_settings_field_validator_msg": "Il valore non puÃ˛ essere vuoto", + "header_settings_header_name_input": "Nome header", + "header_settings_header_value_input": "Valore header", + "headers_settings_tile_subtitle": "Definisci gli header per i proxy che l'app deve inviare con ogni richiesta di rete", + "headers_settings_tile_title": "Header proxy personalizzati", "hi_user": "Ciao {name} ({email})", "hide_all_people": "Nascondi tutte le persone", "hide_gallery": "Nascondi galleria", @@ -1031,7 +1036,7 @@ "hide_unnamed_people": "Nascondi persone senza nome", "home_page_add_to_album_conflicts": "Aggiunti {added} elementi all'album {album}. {failed} elementi erano già presenti nell'album.", "home_page_add_to_album_err_local": "Non puoi aggiungere in album risorse non ancora caricate, azione ignorata", - "home_page_add_to_album_success": "Aggiunti {added} elementi all'album {album}", + "home_page_add_to_album_success": "Aggiunti {added} elementi all'album {album}.", "home_page_album_err_partner": "Non puoi aggiungere risorse del partner a un album, azione ignorata", "home_page_archive_err_local": "Non puoi archiviare immagini non ancora caricate, azione ignorata", "home_page_archive_err_partner": "Non puoi archiviare risorse del partner, azione ignorata", @@ -1040,7 +1045,7 @@ "home_page_delete_remote_err_local": "Risorse locali presenti nella selezione della eliminazione remota, azione ignorata", "home_page_favorite_err_local": "Non puoi aggiungere tra i preferiti delle risorse non ancora caricate, azione ignorata", "home_page_favorite_err_partner": "Non puoi mettere le risorse del partner nei preferiti, azione ignorata", - "home_page_first_time_notice": "Se è la prima volta che utilizzi l'app, assicurati di scegliere uno o piÚ album di backup, in modo che la timeline possa popolare le foto e i video presenti negli album.", + "home_page_first_time_notice": "Se è la prima volta che utilizzi l'app, assicurati di scegliere uno o piÚ album di backup, in modo che la timeline possa popolare le foto e i video presenti negli album", "home_page_share_err_local": "Non puoi condividere una risorsa locale tramite link, azione ignorata", "home_page_upload_err_limit": "Puoi caricare al massimo 30 file per volta, ignora quelli in eccesso", "host": "Host", @@ -1059,7 +1064,7 @@ "image_alt_text_date_place_3_people": "{isVideo, select, true {Video girato} other {Foto scattata}} a {city}, {country} con {person1}, {person2}, e {person3} il giorno {date}", "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Video girato} other {Foto scattata}} a {city}, {country} con {person1}, {person2} e {additionalCount, number} altre persone il {date}", "image_saved_successfully": "Immagine salvata", - "image_viewer_page_state_provider_download_started": "Download Started", + "image_viewer_page_state_provider_download_started": "Download iniziato", "image_viewer_page_state_provider_download_success": "Download con successo", "image_viewer_page_state_provider_share_error": "Errore di condivisione", "immich_logo": "Logo Immich", @@ -1080,8 +1085,8 @@ "night_at_midnight": "Ogni notte a mezzanotte", "night_at_twoam": "Ogni notte alle 2" }, - "invalid_date": "Invalid date", - "invalid_date_format": "Invalid date format", + "invalid_date": "Data invalida", + "invalid_date_format": "Formato data invalido", "invite_people": "Invita Persone", "invite_to_album": "Invita nell'album", "items_count": "{count, plural, one {# elemento} other {# elementi}}", @@ -1132,24 +1137,24 @@ "logged_out_device": "Disconnesso dal dispositivo", "login": "Login", "login_disabled": "L'accesso è stato disattivato", - "login_form_api_exception": "API error, per favore ricontrolli URL del server e riprovi", + "login_form_api_exception": "API error, per favore ricontrolli URL del server e riprovi.", "login_form_back_button_text": "Indietro", "login_form_email_hint": "tuaemail@email.com", "login_form_endpoint_hint": "http://ip-del-tuo-server:port", - "login_form_endpoint_url": "Server Endpoint URL", + "login_form_endpoint_url": "URL dell'Endpoint del Server", "login_form_err_http": "Per favore specificare http:// o https://", "login_form_err_invalid_email": "Email non valida", "login_form_err_invalid_url": "URL invalido", - "login_form_err_leading_whitespace": "Whitespace all'inizio ", + "login_form_err_leading_whitespace": "Whitespace all'inizio", "login_form_err_trailing_whitespace": "Whitespace alla fine", "login_form_failed_get_oauth_server_config": "Errore di login usando OAuth, controlla l'URL del server", "login_form_failed_get_oauth_server_disable": "OAuth non è disponibile su questo server", "login_form_failed_login": "Errore nel login, controlla URL del server e le credenziali (email e password)", "login_form_handshake_exception": "Si è verificata un'eccezione di handshake con il server. Abilita il supporto del certificato self-signed nelle impostazioni se si utilizza questo tipo di certificato.", - "login_form_password_hint": "password ", - "login_form_save_login": "Rimani connesso ", - "login_form_server_empty": "Inserisci URL del server", - "login_form_server_error": "Non è possibile connettersi al server", + "login_form_password_hint": "password", + "login_form_save_login": "Rimani connesso", + "login_form_server_empty": "Inserisci URL del server.", + "login_form_server_error": "Non è possibile connettersi al server.", "login_has_been_disabled": "Il login è stato disabilitato.", "login_password_changed_error": "C'è stato un errore durante l'aggiornamento della password", "login_password_changed_success": "Password aggiornata con successo", @@ -1202,8 +1207,8 @@ "memories_setting_description": "Gestisci cosa vedi nei tuoi ricordi", "memories_start_over": "Ricomincia", "memories_swipe_to_close": "Scorri sopra per chiudere", - "memories_year_ago": "A year ago", - "memories_years_ago": "{} years ago", + "memories_year_ago": "Una anno fa", + "memories_years_ago": "{} anni fa", "memory": "Memoria", "memory_lane_title": "Sentiero dei Ricordi {title}", "menu": "Menu", @@ -1257,11 +1262,11 @@ "no_results_description": "Prova ad usare un sinonimo oppure una parola chiave piÚ generica", "no_shared_albums_message": "Crea un album per condividere foto e video con le persone nella tua rete", "not_in_any_album": "In nessun album", - "not_selected": "Not selected", + "not_selected": "Non selezionato", "note_apply_storage_label_to_previously_uploaded assets": "Nota: Per aggiungere l'etichetta dell'archiviazione agli asset caricati in precedenza, esegui", "notes": "Note", - "notification_permission_dialog_content": "Per attivare le notifiche, vai alle Impostazioni e seleziona concedi", - "notification_permission_list_tile_content": "Concedi i permessi per attivare le notifiche", + "notification_permission_dialog_content": "Per attivare le notifiche, vai alle Impostazioni e seleziona concedi.", + "notification_permission_list_tile_content": "Concedi i permessi per attivare le notifiche.", "notification_permission_list_tile_enable_button": "Attiva notifiche", "notification_permission_list_tile_title": "Permessi delle Notifiche", "notification_toggle_setting_description": "Attiva le notifiche via email", @@ -1282,6 +1287,7 @@ "onboarding_welcome_user": "Benvenuto, {user}", "online": "Online", "only_favorites": "Solo preferiti", + "open": "Apri", "open_in_map_view": "Apri nella visualizzazione mappa", "open_in_openstreetmap": "Apri su OpenStreetMap", "open_the_search_filters": "Apri filtri di ricerca", @@ -1301,9 +1307,9 @@ "partner_list_user_photos": "Foto di {user}", "partner_list_view_all": "Mostra tutto", "partner_page_empty_message": "Le tue foto non sono ancora condivise con alcun partner.", - "partner_page_no_more_users": "Nessun altro utente da aggiungere.", - "partner_page_partner_add_failed": "Aggiunta del partner non riuscita.", - "partner_page_select_partner": "Seleziona partner.", + "partner_page_no_more_users": "Nessun altro utente da aggiungere", + "partner_page_partner_add_failed": "Aggiunta del partner non riuscita", + "partner_page_select_partner": "Seleziona partner", "partner_page_shared_to_title": "Condividi con", "partner_page_stop_sharing_content": "{} non sarà piÚ in grado di accedere alle tue foto.", "partner_sharing": "Condivisione Compagno", @@ -1338,10 +1344,10 @@ "permission_onboarding_continue_anyway": "Continua lo stesso", "permission_onboarding_get_started": "Inizia", "permission_onboarding_go_to_settings": "Vai a Impostazioni", - "permission_onboarding_permission_denied": "Permessi negati. Per usare Immich concedi i permessi ai video e foto dalle impostazioni", - "permission_onboarding_permission_granted": "Concessi i permessi! Ora sei tutto apposto", + "permission_onboarding_permission_denied": "Permessi negati. Per usare Immich concedi i permessi ai video e foto dalle impostazioni.", + "permission_onboarding_permission_granted": "Concessi i permessi! Ora sei tutto apposto.", "permission_onboarding_permission_limited": "Permessi limitati. Per consentire a Immich di gestire e fare i backup di tutta la galleria, concedi i permessi Foto e Video dalle Impostazioni.", - "permission_onboarding_request": "Immich richiede i permessi per vedere le tue foto e video", + "permission_onboarding_request": "Immich richiede i permessi per vedere le tue foto e video.", "person": "Persona", "person_birthdate": "Nato il {date}", "person_hidden": "{name}{hidden, select, true { (nascosto)} other {}}", @@ -1368,7 +1374,7 @@ "previous_or_next_photo": "Precedente o prossima foto", "primary": "Primario", "privacy": "Privacy", - "profile_drawer_app_logs": "Logs", + "profile_drawer_app_logs": "Registri", "profile_drawer_client_out_of_date_major": "L'applicazione non è aggiornata. Per favore aggiorna all'ultima versione principale.", "profile_drawer_client_out_of_date_minor": "L'applicazione non è aggiornata. Per favore aggiorna all'ultima versione minore.", "profile_drawer_client_server_up_to_date": "Client e server sono aggiornati", @@ -1487,7 +1493,7 @@ "saved_profile": "Profilo salvato", "saved_settings": "Impostazioni salvate", "say_something": "Dici qualcosa", - "scaffold_body_error_occurred": "Si è verificato un errore.", + "scaffold_body_error_occurred": "Si è verificato un errore", "scan_all_libraries": "Analizza tutte le librerie", "scan_library": "Scansione", "scan_settings": "Impostazioni Analisi", @@ -1504,24 +1510,24 @@ "search_city": "Cerca città...", "search_country": "Cerca paese...", "search_filter_apply": "Applica filtro", - "search_filter_camera_title": "Select camera type", + "search_filter_camera_title": "Seleziona il tipo di camera", "search_filter_date": "Date", "search_filter_date_interval": "{start} to {end}", - "search_filter_date_title": "Select a date range", + "search_filter_date_title": "Scegli un range di date", "search_filter_display_option_not_in_album": "Non nell'album", - "search_filter_display_options": "Display Options", - "search_filter_filename": "Search by file name", - "search_filter_location": "Location", - "search_filter_location_title": "Select location", + "search_filter_display_options": "Opzioni di Visualizzazione", + "search_filter_filename": "Cerca per nome file", + "search_filter_location": "Posizione", + "search_filter_location_title": "Seleziona posizione", "search_filter_media_type": "Media Type", "search_filter_media_type_title": "Seleziona il tipo di media", "search_filter_people_title": "Seleziona persone", "search_for": "Cerca per", "search_for_existing_person": "Cerca per persona esistente", - "search_no_more_result": "No more results", + "search_no_more_result": "Non ci sono altri risultati", "search_no_people": "Nessuna persona", "search_no_people_named": "Nessuna persona chiamate \"{name}\"", - "search_no_result": "No results found, try a different search term or combination", + "search_no_result": "Nessun risultato trovato, prova con un termine o combinazione diversi", "search_options": "Opzioni Ricerca", "search_page_categories": "Categoria", "search_page_motion_photos": "Foto in movimento", @@ -1532,16 +1538,16 @@ "search_page_selfies": "Selfie", "search_page_things": "Oggetti", "search_page_view_all_button": "Guarda tutto", - "search_page_your_activity": "Tua attività ", + "search_page_your_activity": "Le tua attività", "search_page_your_map": "La tua mappa", "search_people": "Cerca persone", "search_places": "Cerca luoghi", "search_rating": "Cerca per valutazione...", - "search_result_page_new_search_hint": "Nuova ricerca ", + "search_result_page_new_search_hint": "Nuova ricerca", "search_settings": "Cerca Impostazioni", "search_state": "Cerca stato...", - "search_suggestion_list_smart_search_hint_1": "\nRicerca Smart è attiva di default, per usare la ricerca con i metadata usare la seguente sintassi", - "search_suggestion_list_smart_search_hint_2": "m:your-search-term", + "search_suggestion_list_smart_search_hint_1": "Ricerca Smart è attiva di default, per usare la ricerca con i metadata usare la seguente sintassi ", + "search_suggestion_list_smart_search_hint_2": "m:termine-di-ricerca", "search_tags": "Cerca tag...", "search_timezone": "Cerca fuso orario...", "search_type": "Cerca tipo", @@ -1562,7 +1568,7 @@ "select_new_face": "Seleziona nuovo volto", "select_photos": "Seleziona foto", "select_trash_all": "Seleziona cestina tutto", - "select_user_for_sharing_page_err_album": "Impossibile nel creare l'album ", + "select_user_for_sharing_page_err_album": "Impossibile nel creare l'album", "selected": "Selezionato", "selected_count": "{count, plural, one {# selezionato} other {# selezionati}}", "send_message": "Manda messaggio", @@ -1584,9 +1590,9 @@ "setting_image_viewer_help": "Il visualizzatore dettagliato carica una piccola thumbnail per prima, per poi caricare un immagine di media grandezza (se abilitato). Ed infine carica l'originale (se abilitato).", "setting_image_viewer_original_subtitle": "Abilita per caricare l'immagine originale a risoluzione massima (grande!). Disabilita per ridurre l'utilizzo di banda (sia sul network che nella cache del dispositivo).", "setting_image_viewer_original_title": "Carica l'immagine originale", - "setting_image_viewer_preview_subtitle": "Abilita per caricare un'immagine a risoluzione media.\nDisabilita per caricare direttamente l'immagine originale o usare la thumbnail.", + "setting_image_viewer_preview_subtitle": "Abilita per caricare un'immagine a risoluzione media. Disabilita per caricare direttamente l'immagine originale o usare la thumbnail.", "setting_image_viewer_preview_title": "Carica immagine di anteprima", - "setting_image_viewer_title": "Images", + "setting_image_viewer_title": "Immagini", "setting_languages_apply": "Applica", "setting_languages_subtitle": "Cambia la lingua dell'app", "setting_languages_title": "Lingue", @@ -1609,7 +1615,7 @@ "settings_saved": "Impostazioni salvate", "share": "Condivisione", "share_add_photos": "Aggiungi foto", - "share_assets_selected": "{} selected", + "share_assets_selected": "{} selezionati", "share_dialog_preparing": "Preparoâ€Ļ", "shared": "Condivisi", "shared_album_activities_input_disable": "I commenti sono disabilitati", @@ -1623,7 +1629,7 @@ "shared_by_user": "Condiviso da {user}", "shared_by_you": "Condiviso da te", "shared_from_partner": "Foto da {partner}", - "shared_intent_upload_button_progress_text": "{} / {} Uploaded", + "shared_intent_upload_button_progress_text": "{} / {} Inviati", "shared_link_app_bar_title": "Link condivisi", "shared_link_clipboard_copied_massage": "Copiato negli appunti", "shared_link_clipboard_text": "Link: {}\nPassword: {}", @@ -1635,8 +1641,8 @@ "shared_link_edit_expire_after_option_hours": "{} ore", "shared_link_edit_expire_after_option_minute": "1 minuto", "shared_link_edit_expire_after_option_minutes": "{} minuti", - "shared_link_edit_expire_after_option_months": "{} months", - "shared_link_edit_expire_after_option_year": "{} year", + "shared_link_edit_expire_after_option_months": "{} mesi", + "shared_link_edit_expire_after_option_year": "{} anno", "shared_link_edit_password_hint": "Inserire la password di condivisione", "shared_link_edit_submit_button": "Aggiorna link", "shared_link_error_server_url_fetch": "Non è possibile trovare l'indirizzo del server", @@ -1649,7 +1655,7 @@ "shared_link_expires_never": "Scadenza ∞", "shared_link_expires_second": "Scade tra {} secondo", "shared_link_expires_seconds": "Scade tra {} secondi", - "shared_link_individual_shared": "Individual shared", + "shared_link_individual_shared": "Condiviso individualmente", "shared_link_info_chip_metadata": "EXIF", "shared_link_manage_links": "Gestisci link condivisi", "shared_link_options": "Opzioni link condiviso", @@ -1732,9 +1738,9 @@ "support_third_party_description": "La tua installazione di Immich è stata costruita da terze parti. I problemi che riscontri potrebbero essere causati da altri pacchetti, quindi ti preghiamo di sollevare il problema in prima istanza utilizzando i link sottostanti.", "swap_merge_direction": "Scambia direzione di unione", "sync": "Sincronizza", - "sync_albums": "Sync albums", - "sync_albums_manual_subtitle": "Sync all uploaded videos and photos to the selected backup albums", - "sync_upload_album_setting_subtitle": "Create and upload your photos and videos to the selected albums on Immich", + "sync_albums": "Sincronizza album", + "sync_albums_manual_subtitle": "Sincronizza tutti i video e le foto caricate sull'album di backup selezionato", + "sync_upload_album_setting_subtitle": "Crea e carica le tue foto e video sull'album selezionato in Immich", "tag": "Tag", "tag_assets": "Tagga risorse", "tag_created": "Tag creata: {tag}", @@ -1749,12 +1755,12 @@ "theme_selection": "Selezione tema", "theme_selection_description": "Imposta automaticamente il tema chiaro o scuro in base all'impostazione del tuo browser", "theme_setting_asset_list_storage_indicator_title": "Mostra indicatore dello storage nei titoli dei contenuti", - "theme_setting_asset_list_tiles_per_row_title": "Numero di contenuti per riga ({})", - "theme_setting_colorful_interface_subtitle": "Apply primary color to background surfaces.", - "theme_setting_colorful_interface_title": "Colorful interface", + "theme_setting_asset_list_tiles_per_row_title": "Numero di elementi per riga ({})", + "theme_setting_colorful_interface_subtitle": "Applica il colore primario alle superfici di sfondo.", + "theme_setting_colorful_interface_title": "Interfaccia colorata", "theme_setting_image_viewer_quality_subtitle": "Cambia la qualità del dettaglio dell'immagine", "theme_setting_image_viewer_quality_title": "Qualità immagine", - "theme_setting_primary_color_subtitle": "Pick a color for primary actions and accents.", + "theme_setting_primary_color_subtitle": "Scegli un colore per le azioni primarie e accentate.", "theme_setting_primary_color_title": "Colore primario", "theme_setting_system_primary_color_title": "Usa colori di sistema", "theme_setting_system_theme_switch": "Automatico (Segue le impostazioni di sistema)", @@ -1780,7 +1786,7 @@ "trash_all": "Cestina Tutto", "trash_count": "Cancella {count, number}", "trash_delete_asset": "Cestina/Cancella Asset", - "trash_emptied": "Emptied trash", + "trash_emptied": "Cestino svuotato", "trash_no_results_message": "Le foto cestinate saranno mostrate qui.", "trash_page_delete_all": "Elimina tutti", "trash_page_empty_trash_dialog_content": "Vuoi eliminare gli elementi nel cestino? Questi elementi saranno eliminati definitivamente da Immich", @@ -1826,8 +1832,8 @@ "upload_status_errors": "Errori", "upload_status_uploaded": "Caricato", "upload_success": "Caricamento completato con successo, aggiorna la pagina per vedere i nuovi asset caricati.", - "upload_to_immich": "Upload to Immich ({})", - "uploading": "Uploading", + "upload_to_immich": "Invio ad Immich ({})", + "uploading": "Caricamento", "url": "URL", "usage": "Utilizzo", "use_current_connection": "usa la connessione attuale", @@ -1853,7 +1859,7 @@ "version_announcement_overlay_release_notes": "note di rilascio", "version_announcement_overlay_text_1": "Ciao, c'è una nuova versione di", "version_announcement_overlay_text_2": "per favore prenditi il tuo tempo per visitare le ", - "version_announcement_overlay_text_3": " e verifica che il tuo docker-compose e il file .env siano aggiornati per impedire qualsiasi errore di configurazione, specialmente se utilizzate WatchTower o altri strumenti per l'aggiornamento automatico dell'applicativo", + "version_announcement_overlay_text_3": " e verifica che il tuo docker-compose e il file .env siano aggiornati per impedire qualsiasi errore di configurazione, specialmente se utilizzate WatchTower o altri strumenti per l'aggiornamento automatico dell'applicativo.", "version_announcement_overlay_title": "Nuova versione del server disponibile 🎉", "version_history": "Storico delle Versioni", "version_history_item": "Versione installata {version} il {date}", diff --git a/i18n/ja.json b/i18n/ja.json index 39496cc7f5..eb6b355615 100644 --- a/i18n/ja.json +++ b/i18n/ja.json @@ -496,7 +496,7 @@ "back_close_deselect": "æˆģã‚‹ã€é–‰ã˜ã‚‹ã€é¸æŠžč§Ŗé™¤", "background_location_permission": "バックグナã‚Ļãƒŗãƒ‰äŊįŊŽæƒ…å ąã‚ĸクã‚ģ゚", "background_location_permission_content": "æ­Ŗå¸¸ãĢWi-Fiぎ名前(SSID)ã‚’į˛åž—ã™ã‚‹ãĢはã‚ĸプãƒĒが常ãĢčŠŗį´°ãĒäŊįŊŽæƒ…å ąãĢã‚ĸクã‚ģ゚できるåŋ…čĻãŒã‚ã‚Šãžã™", - "backup_album_selection_page_albums_device": "į̝æœĢ上ぎã‚ĸãƒĢバム数: {} ", + "backup_album_selection_page_albums_device": "į̝æœĢ上ぎã‚ĸãƒĢバム数: {}", "backup_album_selection_page_albums_tap": "ã‚ŋップで選択、ダブãƒĢã‚ŋップで除外", "backup_album_selection_page_assets_scatter": "ã‚ĸãƒĢバムを選択ãƒģ除外しãĻバックã‚ĸãƒƒãƒ—ã™ã‚‹å†™įœŸã‚’é¸ãļ (åŒã˜å†™įœŸãŒč¤‡æ•°ãŽã‚ĸãƒĢバムãĢį™ģéŒ˛ã•ã‚ŒãĻいることがあるため)", "backup_album_selection_page_select_albums": "ã‚ĸãƒĢバムを選択", @@ -505,7 +505,7 @@ "backup_all": "すずãĻ", "backup_background_service_backup_failed_message": "ã‚ĸップロãƒŧドãĢå¤ąæ•—ã—ãžã—ãŸã€‚ãƒĒトナイ中", "backup_background_service_connection_failed_message": "ã‚ĩãƒŧバãƒŧãĢæŽĨįļšã§ããžã›ã‚“。ãƒĒトナイ中", - "backup_background_service_current_upload_notification": " {}をã‚ĸップロãƒŧド中", + "backup_background_service_current_upload_notification": "{}をã‚ĸップロãƒŧド中", "backup_background_service_default_notification": "æ–°ã—ã„å†™įœŸã‚’įĸēčĒä¸­", "backup_background_service_error_title": "バックã‚ĸップエナãƒŧ", "backup_background_service_in_progress_notification": "バックã‚ĸップ中", @@ -534,7 +534,7 @@ "backup_controller_page_desc_backup": "ã‚ĸプãƒĒを開いãĻいるときãĢå†™įœŸã¨å‹•į”ģをバックã‚ĸップしぞす", "backup_controller_page_excluded": "除外中ぎã‚ĸãƒĢバム:", "backup_controller_page_failed": "å¤ąæ•—: ({})", - "backup_controller_page_filename": "ãƒ•ã‚Ąã‚¤ãƒĢ名: {} [{}] ", + "backup_controller_page_filename": "ãƒ•ã‚Ąã‚¤ãƒĢ名: {} [{}]", "backup_controller_page_id": "ID: {}", "backup_controller_page_info": "バックã‚ĸãƒƒãƒ—æƒ…å ą", "backup_controller_page_none_selected": "ãĒし", @@ -575,7 +575,7 @@ "cache_settings_duplicated_assets_clear_button": "クãƒĒã‚ĸ", "cache_settings_duplicated_assets_subtitle": "ã‚ĩãƒŧバãƒŧãĢã‚ĸップロãƒŧド済ãŋとčĒč­˜ã•ã‚ŒãŸå†™įœŸã‚„å‹•į”ģぎ数", "cache_settings_duplicated_assets_title": "{}é …į›ŽãŽé‡č¤‡", - "cache_settings_image_cache_size": "ã‚­ãƒŖãƒƒã‚ˇãƒĨぎã‚ĩイã‚ē ({}枚) ", + "cache_settings_image_cache_size": "ã‚­ãƒŖãƒƒã‚ˇãƒĨぎã‚ĩイã‚ē ({}枚)", "cache_settings_statistics_album": "ナイブナãƒĒぎã‚ĩムネイãƒĢ", "cache_settings_statistics_assets": "{}枚 ({}枚中)", "cache_settings_statistics_full": "フãƒĢį”ģ像", diff --git a/i18n/ka.json b/i18n/ka.json index a521539d11..b07dcfe6fa 100644 --- a/i18n/ka.json +++ b/i18n/ka.json @@ -30,11 +30,11 @@ "authentication_settings_disable_all": "ნამდვილად გინდა ავáƒĸორიზაáƒĒიიქ ყველა მეთოდის გამორთვა? ავáƒĸორიზაáƒĒიაქ ვეáƒĻარანაირად შეáƒĢლებ.", "authentication_settings_reenable": "რეაáƒĨáƒĸივაáƒĒიისთვის, გამოიყენე სერვერის ბრáƒĢანება.", "background_task_job": "áƒ¤áƒáƒœáƒŖáƒ áƒ˜ დავალებები", - "backup_database": "შეáƒĨმენი სარეზერვო ასლი", - "backup_database_enable_description": "ჩართე სარეზერვო ასლების áƒ¤áƒŖáƒœáƒĨáƒĒია", - "backup_keep_last_amount": "შესანახი სარეზერვო ასლების რაოდენობა", - "backup_settings": "სარეზერვო ასლების პარამეáƒĸრები", - "backup_settings_description": "მონაáƒĒემთა ბაზის სარეზერვო ასლების პარამეáƒĸრების მართვა", + "backup_database": "ბაზის დამპის შეáƒĨმნა", + "backup_database_enable_description": "ბაზის დამპების ჩართვა", + "backup_keep_last_amount": "áƒŦინა დამპების áƒ¨áƒ”áƒĄáƒáƒœáƒáƒ áƒŠáƒŖáƒœáƒ”áƒ‘áƒ”áƒšáƒ˜ რაოდენობა", + "backup_settings": "მონაáƒĒემთა ბაზის დამპის მორგება", + "backup_settings_description": "მონაáƒĒემთა ბაზის პარამეáƒĸრების ამრთვა. შენიშვნა: ამ დავალებების მონიáƒĸორინგი არ ხდება და თáƒĨვენ არ მოგივათ შეáƒĸყობინება, áƒ—áƒŖ იქ ჩავარდება.", "check_all": "შეამოáƒŦმე ყველა", "cleanup": "áƒ’áƒáƒĄáƒŖáƒ¤áƒ—áƒáƒ•áƒ”áƒ‘áƒ", "confirm_delete_library": "ნამდვილად გინდა {library} ბიბლიოთეკის áƒŦაშლა?", diff --git a/i18n/kk.json b/i18n/kk.json index 0967ef424b..e3a1f51c3e 100644 --- a/i18n/kk.json +++ b/i18n/kk.json @@ -1 +1,16 @@ -{} +{ + "add_photos": "ŅŅƒŅ€Đĩ҂҂ĐĩŅ€Đ´Ņ– Ō›ĐžŅŅƒ", + "add_to": "Ō›ĐžŅŅƒâ€Ļ", + "add_to_album": "аĐģŅŒĐąĐžĐŧŌ“Đ° Ō›ĐžŅŅƒ", + "add_to_album_bottom_sheet_added": "{album}'Ō“Đ° Ō›ĐžŅŅ‹ĐģŌ“Đ°ĐŊ", + "add_to_album_bottom_sheet_already_exists": "ОĐŊŅŅ‹Đˇ да {album} йОĐģŌ“Đ°ĐŊ", + "add_to_shared_album": "ĐąĶŠĐģҖҁĐēĐĩĐŊ аĐģŅŒĐąĐžĐŧŌ“Đ° Ō›ĐžŅŅƒ", + "add_url": "URL Ņ‚Đ°ŌŖĐ´Đ°Ņƒ", + "added_to_archive": "ĐŅ€Ņ…Đ¸Đ˛ĐēĐĩ ĐļŅ–ĐąĐĩҀҖĐģĐŗĐĩĐŊ", + "added_to_favorites": "Ņ‚Đ°ŌŖĐ´Đ°ŅƒĐģŅ‹ĐģĐ°Ņ€Ō“Đ° Ō›ĐžŅŅ‹ĐģŌ“Đ°ĐŊ", + "admin": { + "check_all": "Đ‘Ķ™Ņ€Ņ–ĐŊ Ņ‚ĐĩĐēҁĐĩҀҖĐŋ аĐģ҃", + "create_job": "Đ–ŌąĐŧҋҁ҂ҋ ĐąĐ°ŅŅ‚Đ°Ņƒ" + }, + "zoom_image": "ŅŅƒŅ€Đĩ҂҂Җ Ō¯ĐģĐēĐĩĐšŅ‚Ņƒ" +} diff --git a/i18n/ko.json b/i18n/ko.json index def2ad2a5e..03db17c396 100644 --- a/i18n/ko.json +++ b/i18n/ko.json @@ -14,7 +14,7 @@ "add_a_location": "ėœ„ėš˜ ėļ”ę°€", "add_a_name": "ė´ëĻ„ ėļ”ę°€", "add_a_title": "렜ëĒŠ ėļ”ę°€", - "add_endpoint": "Add endpoint", + "add_endpoint": "ė—”ë“œíŦė¸íŠ¸ ėļ”ę°€", "add_exclusion_pattern": "ė œė™¸ ęˇœėš™ ėļ”ę°€", "add_import_path": "氀렏ė˜Ŧ ę˛Ŋ로 ėļ”ę°€", "add_location": "ėœ„ėš˜ ėļ”ę°€", @@ -25,29 +25,29 @@ "add_to": "ė•¨ë˛”ė— ėļ”ę°€â€Ļ", "add_to_album": "ė•¨ë˛”ė— ėļ”ę°€", "add_to_album_bottom_sheet_added": "{album}뗐 ėļ”ę°€ë˜ė—ˆėŠĩ니다.", - "add_to_album_bottom_sheet_already_exists": "{album}뗐 ė´ë¯¸ ėĄ´ėžŦ하는 항ëĒŠėž…ë‹ˆë‹¤.", + "add_to_album_bottom_sheet_already_exists": "{album}뗐 ė´ë¯¸ ėĄ´ėžŦ합니다.", "add_to_shared_album": "ęŗĩ뜠 ė•¨ë˛”ė— ėļ”ę°€", "add_url": "URL ėļ”ę°€", "added_to_archive": "ëŗ´ę´€í•¨ė— ėļ”ę°€ë˜ė—ˆėŠĩ니다.", "added_to_favorites": "ėĻę˛¨ė°žę¸°ė— ėļ”ę°€ë˜ė—ˆėŠĩ니다.", - "added_to_favorites_count": "ėĻę˛¨ė°žę¸°ė— 항ëĒŠ {count, number}氜 ėļ”가됨", + "added_to_favorites_count": "ėĻę˛¨ė°žę¸°ė— {count, number}氜 ėļ”가됨", "admin": { "add_exclusion_pattern_description": "ęˇœėš™ė— *, ** 및 ? ëĨŧ ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다. ė´ëĻ„ė´ \"Raw\"ė¸ 디렉터ëĻŦė˜ ëĒ¨ë“  파ėŧė„ ė œė™¸í•˜ë ¤ëŠ´ \"**/Raw/**\"ëĨŧ, \".tif\"로 끝나는 ëĒ¨ë“  파ėŧė„ ė œė™¸í•˜ë ¤ëŠ´ \"**/*.tif\"ëĨŧ ė‚ŦėšŠí•˜ęŗ , ė ˆëŒ€ ę˛ŊëĄœė˜ ę˛Ŋ뚰 \"/path/to/ignore/**\"뙀 ę°™ė€ ë°Šė‹ėœŧ로 ė‚ŦėšŠí•Šë‹ˆë‹¤.", - "asset_offline_description": "뙏ëļ€ ëŧė´ë¸ŒëŸŦëĻŦ뗐 íŦ함된 ė´ 항ëĒŠė„ ë””ėŠ¤íŦė—ė„œ ë”ė´ėƒ ė°žė„ 눘 뗆떴 íœ´ė§€í†ĩėœŧ로 ė´ë™ë˜ė—ˆėŠĩ니다. 파ėŧė´ ëŧė´ë¸ŒëŸŦëĻŦ ë‚´ė—ė„œ ė´ë™ëœ ę˛Ŋ뚰 íƒ€ėž„ëŧė¸ė—ė„œ ėƒˆëĄœ ė—°ę˛°ëœ 항ëĒŠė„ í™•ė¸í•˜ė„¸ėš”. ė´ 항ëĒŠė„ ëŗĩė›í•˜ë ¤ëŠ´ ė•„ëž˜ 파ėŧ ę˛ŊëĄœė— Immich가 ė ‘ęˇŧ할 눘 ėžˆëŠ”ė§€ í™•ė¸í•˜ęŗ  ëŧė´ë¸ŒëŸŦëĻŦ 늤ėē”ė„ ė§„í–‰í•˜ė„¸ėš”.", + "asset_offline_description": "뙏ëļ€ ëŧė´ë¸ŒëŸŦëĻŦ뗐 íŦ함된 ė´ 항ëĒŠė„ ë””ėŠ¤íŦė—ė„œ ë”ė´ėƒ ė°žė„ 눘 뗆떴 íœ´ė§€í†ĩėœŧ로 ė´ë™ë˜ė—ˆėŠĩ니다. 파ėŧė´ ëŧė´ë¸ŒëŸŦëĻŦ ë‚´ė—ė„œ ė´ë™ëœ ę˛Ŋ뚰 íƒ€ėž„ëŧė¸ė—ė„œ ėƒˆëĄœ ė—°ę˛°ëœ 항ëĒŠė„ í™•ė¸í•˜ė„¸ėš”. 항ëĒŠė„ ëŗĩė›í•˜ë ¤ëŠ´ ė•„ëž˜ė˜ 파ėŧ ę˛ŊëĄœė— Immich가 ė ‘ęˇŧ할 눘 ėžˆëŠ”ė§€ í™•ė¸í•˜ęŗ  ëŧė´ë¸ŒëŸŦëĻŦ 늤ėē”ė„ ė§„í–‰í•˜ė„¸ėš”.", "authentication_settings": "ė¸ėĻ 네렕", "authentication_settings_description": "비밀번호, OAuth 및 기타 ė¸ėĻ 네렕 관ëĻŦ", - "authentication_settings_disable_all": "ëĄœęˇ¸ė¸ 기ëŠĨė„ ëĒ¨ë‘ ëš„í™œė„ąí™”í•˜ė‹œę˛ ėŠĩ니까? ëĄœęˇ¸ė¸í•˜ė§€ ė•Šė•„ë„ ė„œë˛„ė— ė ‘ęˇŧ할 눘 ėžˆėŠĩ니다.", - "authentication_settings_reenable": "ë‹¤ė‹œ í™œė„ąí™”í•˜ë ¤ëŠ´ ė„œë˛„ ėģ¤ë§¨ë“œëĨŧ ė‚ŦėšŠí•˜ė„¸ėš”.", + "authentication_settings_disable_all": "ëĄœęˇ¸ė¸ ėˆ˜ë‹¨ė„ ëĒ¨ë‘ ëš„í™œė„ąí™”í•˜ė‹œę˛ ėŠĩ니까? ëĄœęˇ¸ė¸ė´ ė™„ė „ížˆ ëš„í™œė„ąí™”ëŠë‹ˆë‹¤.", + "authentication_settings_reenable": "ë‹¤ė‹œ í™œė„ąí™”í•˜ë ¤ëŠ´ ė„œë˛„ ëĒ…ë šė–´ëĨŧ ė‚ŦėšŠí•˜ė„¸ėš”.", "background_task_job": "밹꡸ëŧėš´ë“œ ėž‘ė—…", - "backup_database": "ë°ė´í„°ë˛ ė´ėŠ¤ ë°ąė—…", - "backup_database_enable_description": "ë°ė´í„°ë˛ ė´ėŠ¤ ë°ąė—… í™œė„ąí™”", - "backup_keep_last_amount": "ëŗ´ę´€í•  ë°ąė—…ė˜ 氜눘", - "backup_settings": "ë°ąė—… 네렕", - "backup_settings_description": "ë°ė´í„°ë˛ ė´ėŠ¤ ë°ąė—… 네렕 관ëĻŦ", + "backup_database": "ë°ė´í„°ë˛ ė´ėŠ¤ 덤프 ėƒė„ą", + "backup_database_enable_description": "ë°ė´í„°ë˛ ė´ėŠ¤ 덤프 í™œė„ąí™”", + "backup_keep_last_amount": "ëŗ´ę´€í•  ė´ė „ ë¤í”„ė˜ 눘", + "backup_settings": "ë°ė´í„°ë˛ ė´ėŠ¤ 덤프 네렕", + "backup_settings_description": "ë°ė´í„°ë˛ ė´ėŠ¤ 덤프 ė„¤ė •ė„ 관ëĻŦ합니다. 및溠: ė´ ėž‘ė—…ë“¤ė€ ëĒ¨ë‹ˆí„°ë§ë˜ė§€ ė•Šėœŧ늰, ė‹¤íŒ¨ ė‹œ ė•ŒëĻŧė„ ë°›ė§€ ė•ŠėŠĩ니다.", "check_all": "ëĒ¨ë‘ í™•ė¸", "cleanup": "ė •ëĻŦ", "cleared_jobs": "ėž‘ė—… ė¤‘ë‹¨: {job}", - "config_set_by_file": "현ėžŦ ė„¤ė •ė€ ęĩŦė„ą 파ėŧ뗐 ė˜í•´ 관ëĻŦ됩니다.", + "config_set_by_file": "현ėžŦ ęĩŦė„ąė€ 네렕 파ėŧė„ í†ĩ해 ė§€ė •ë˜ė–´ ėžˆėŠĩ니다.", "confirm_delete_library": "{library} ëŧė´ë¸ŒëŸŦëĻŦëĨŧ ė‚­ė œí•˜ė‹œę˛ ėŠĩ니까?", "confirm_delete_library_assets": "ė´ ëŧė´ë¸ŒëŸŦëĻŦëĨŧ ė‚­ė œí•˜ė‹œę˛ ėŠĩ니까? Immichė—ė„œ 항ëĒŠ {count, plural, one {#氜} other {#氜}}가 ė‚­ė œë˜ëŠ° 되돌ëĻ´ 눘 ė—†ėŠĩ니다. ė›ëŗ¸ 파ėŧė€ ė‚­ė œë˜ė§€ ė•ŠėŠĩ니다.", "confirm_email_below": "ęŗ„ė† ė§„í–‰í•˜ë ¤ëŠ´ ė•„ëž˜ė— \"{email}\" ėž…ë Ĩ", @@ -59,40 +59,40 @@ "cron_expression_presets": "Cron í‘œí˜„ė‹ ė‚Ŧė „ 네렕", "disable_login": "ëĄœęˇ¸ė¸ ëš„í™œė„ąí™”", "duplicate_detection_job_description": "揰溄 학ėŠĩė„ í†ĩ해 뜠ė‚Ŧ한 ė´ë¯¸ė§€ëĨŧ ę°ė§€í•Šë‹ˆë‹¤. ėŠ¤ë§ˆíŠ¸ ę˛€ėƒ‰ė´ í™œė„ąí™”ë˜ė–´ ėžˆė–´ė•ŧ 합니다.", - "exclusion_pattern_description": "ė œė™¸ ęˇœėš™ė„ ė‚ŦėšŠí•˜ė—Ŧ ëŧė´ë¸ŒëŸŦëĻŦ 늤ėē” ė‹œ íŠšė • 파ėŧęŗŧ 폴더ëĨŧ ė œė™¸í•  눘 ėžˆėŠĩ니다. í´ë”ė— ė›í•˜ė§€ ė•ŠëŠ” 파ėŧ(RAW 파ėŧ 등)ė´ ėĄ´ėžŦ하는 ę˛Ŋ뚰 ėœ ėšŠí•Šë‹ˆë‹¤.", + "exclusion_pattern_description": "ė œė™¸ ęˇœėš™ė„ ė‚ŦėšŠí•˜ė—Ŧ íŠšė • 파ėŧęŗŧ 폴더ëĨŧ ëŧė´ë¸ŒëŸŦëĻŦ 늤ėē”ė—ė„œ ė œė™¸í•  눘 ėžˆėŠĩ니다. ę°€ė ¸ė˜¤ę¸° ė›í•˜ė§€ ė•ŠëŠ” 파ėŧ(RAW 파ėŧ 등)ė´ í´ë”ė— ėĄ´ėžŦ하는 ę˛Ŋ뚰 ėœ ėšŠí•Šë‹ˆë‹¤.", "external_library_created_at": "뙏ëļ€ ëŧė´ë¸ŒëŸŦëĻŦ ({date}뗐 ėƒė„ąë¨)", "external_library_management": "뙏ëļ€ ëŧė´ë¸ŒëŸŦëĻŦ 관ëĻŦ", "face_detection": "ė–ŧęĩ´ 氐맀", - "face_detection_description": "揰溄 학ėŠĩė„ í†ĩ해 항ëĒŠė— ėĄ´ėžŦ하는 ė–ŧęĩ´ė„ ę°ė§€í•Šë‹ˆë‹¤. ë™ė˜ėƒė˜ ę˛Ŋ뚰 ė„Ŧ네ėŧ만 ė‚ŦėšŠí•Šë‹ˆë‹¤. \"ėƒˆëĄœęŗ ėš¨\"ė€ ė´ë¯¸ 래ëĻŦ된 항ëĒŠė„ íŦ함한 ëĒ¨ë“  항ëĒŠė„ ë‹¤ė‹œ 래ëĻŦ합니다. \"ė´ˆę¸°í™”\"는 ëĒ¨ë“  ė–ŧęĩ´ ë°ė´í„°ëĨŧ ė‚­ė œí•Šë‹ˆë‹¤. \"누ëŊ\"ė€ 래ëĻŦë˜ė§€ ė•Šė€ 항ëĒŠė„ ëŒ€ę¸°ė—´ė— ėļ”ę°€í•Šë‹ˆë‹¤. ė–ŧęĩ´ 氐맀 ėž‘ė—…ė´ ė™„ëŖŒë˜ëŠ´ ė–ŧęĩ´ ė¸ė‹ ėž‘ė—…ė´ ė§„í–‰ë˜ė–´ ę°ė§€ëœ ė–ŧęĩ´ė„ ę¸°ėĄ´ ė¸ëŦŧė´ë‚˜ 냈 ė¸ëŦŧ로 ęˇ¸ëŖší™”í•Šë‹ˆë‹¤.", - "facial_recognition_job_description": "ę°ė§€ëœ ė–ŧęĩ´ė„ ė¸ëŦŧ로 ęˇ¸ëŖší™”í•Šë‹ˆë‹¤. ė´ ėž‘ė—…ė€ ė–ŧęĩ´ 氐맀 ėž‘ė—…ė´ ė™„ëŖŒëœ 후 ė§„í–‰ëŠë‹ˆë‹¤. \"ė´ˆę¸°í™”\"는 ëĒ¨ë“  ė–ŧęĩ´ė˜ ęˇ¸ëŖší™”ëĨŧ ë‹¤ė‹œ ė§„í–‰í•Šë‹ˆë‹¤. \"누ëŊ\"ė€ ęˇ¸ëŖší™”ë˜ė§€ ė•Šė€ ė–ŧęĩ´ė„ ëŒ€ę¸°ė—´ė— ėļ”ę°€í•Šë‹ˆë‹¤.", + "face_detection_description": "揰溄 학ėŠĩė„ í†ĩ해 항ëĒŠė—ė„œ ė–ŧęĩ´ė„ ę°ė§€í•Šë‹ˆë‹¤. ë™ė˜ėƒė˜ ę˛Ŋ뚰 ė„Ŧ네ėŧ만 ëļ„ė„ė— ė‚ŦėšŠëŠë‹ˆë‹¤. \"ėƒˆëĄœęŗ ėš¨\"ė€ ëĒ¨ë“  항ëĒŠė„ (ėžŦ)래ëĻŦ하며, \"ė´ˆę¸°í™”\"는 현ėžŦ ëĒ¨ë“  ė–ŧęĩ´ ë°ė´í„°ëĨŧ ėļ”ę°€ëĄœ ė‚­ė œí•Šë‹ˆë‹¤. \"누ëŊ됨\"ė€ 땄링 래ëĻŦë˜ė§€ ė•Šė€ 항ëĒŠė„ ëŒ€ę¸°ė—´ė— ėļ”ę°€í•Šë‹ˆë‹¤. ė–ŧęĩ´ 氐맀氀 ė™„ëŖŒë˜ëŠ´ ę°ė§€ëœ ė–ŧęĩ´ë“¤ė€ ė–ŧęĩ´ ė¸ė‹ ë‹¨ęŗ„ëĄœ ë„˜ė–´ę°€ëŠ°, ę¸°ėĄ´ ė¸ëŦŧė´ë‚˜ ėƒˆëĄœėš´ ė¸ëŦŧ로 ęˇ¸ëŖší™”ëŠë‹ˆë‹¤.", + "facial_recognition_job_description": "ę°ė§€ëœ ė–ŧęĩ´ė„ ė¸ëŦŧëŗ„ëĄœ ęˇ¸ëŖší™”í•Šë‹ˆë‹¤. ė´ ėž‘ė—…ė€ ė–ŧęĩ´ 氐맀 ėž‘ė—…ė´ ė™„ëŖŒëœ 후 ė§„í–‰ëŠë‹ˆë‹¤. \"ė´ˆę¸°í™”\"는 ëĒ¨ë“  ė–ŧęĩ´ė˜ ęˇ¸ëŖší™”ëĨŧ ë‹¤ė‹œ ė§„í–‰í•Šë‹ˆë‹¤. \"누ëŊ\"ė€ ęˇ¸ëŖší™”ë˜ė§€ ė•Šė€ ė–ŧęĩ´ė„ ëŒ€ę¸°ė—´ė— ėļ”ę°€í•Šë‹ˆë‹¤.", "failed_job_command": "{job} ėž‘ė—…ė—ė„œ {command} ė‹¤íŒ¨", - "force_delete_user_warning": "ę˛Ŋęŗ : ė‚ŦėšŠėž 및 ė‚ŦėšŠėžę°€ ė—…ëĄœë“œí•œ ëĒ¨ë“  항ëĒŠė´ ėĻ‰ė‹œ ė‚­ė œëŠë‹ˆë‹¤. ė´ ėž‘ė—…ė€ 되돌ëĻ´ 눘 ė—†ėœŧ늰 파ėŧė„ ëŗĩęĩŦ할 눘 ė—†ėŠĩ니다.", - "forcing_refresh_library_files": "ëŧė´ë¸ŒëŸŦëĻŦė˜ ëĒ¨ë“  파ėŧė„ ë‹¤ė‹œ 늤ėē”하는 뤑...", + "force_delete_user_warning": "ę˛Ŋęŗ : ė´ ėž‘ė—…ė€ 해당 ė‚ŦėšŠėžė™€ ꡸ ė‚ŦėšŠėžę°€ ė†Œėœ í•œ ëĒ¨ë“  항ëĒŠė„ ėĻ‰ė‹œ ė‚­ė œí•Šë‹ˆë‹¤. ė´ ėž‘ė—…ė€ 되돌ëĻ´ 눘 ė—†ėœŧ늰, ė‚­ė œëœ 파ėŧė€ ëŗĩęĩŦ할 눘 ė—†ėŠĩ니다.", + "forcing_refresh_library_files": "ëĒ¨ë“  ëŧė´ë¸ŒëŸŦëĻŦ 파ėŧ ę°•ė œ ėƒˆëĄœęŗ ėš¨ 뤑...", "image_format": "í˜•ė‹", - "image_format_description": "WebP는 JPEGëŗ´ë‹¤ 파ėŧ íŦ기가 ėž‘ė§€ë§Œ ëŗ€í™˜ė— 더 ë§Žė€ ė‹œę°„ė´ ė†Œėš”ëŠë‹ˆë‹¤.", - "image_fullsize_description": "ëŠ”íƒ€ë°ė´í„°ę°€ ė œęą°ëœ 풀ė‚Ŧė´ėψ ė´ë¯¸ė§€ (확대 ė‹œ ė‚ŦėšŠ)", - "image_fullsize_enabled": "풀ė‚Ŧė´ėψ ė´ë¯¸ė§€ ėƒė„ą í™œė„ąí™”", - "image_fullsize_enabled_description": "ė›š ėšœí™”ė ė´ė§€ ė•Šė€ í˜•ė‹ė˜ ę˛Ŋ뚰 풀ė‚Ŧė´ėψ ė´ë¯¸ė§€ëĨŧ ėƒė„ąí•Šë‹ˆë‹¤. 'ėž„ë˛ ë“œëœ 미ëĻŦëŗ´ę¸° ė„ í˜¸'ëĨŧ í™œė„ąí™”í•˜ëŠ´ ëŗ€í™˜ ė—†ė´ ėž„ë˛ ë“œëœ 미ëĻŦëŗ´ę¸°ę°€ 바로 ė‚ŦėšŠëŠë‹ˆë‹¤. JPEG뙀 ę°™ė€ ė›š ėšœí™”ė ė¸ í˜•ė‹ė—ëŠ” 똁í–Ĩė„ ë¯¸ėš˜ė§€ ė•ŠėŠĩ니다.", - "image_fullsize_quality_description": "풀ė‚Ŧė´ėψ ė´ë¯¸ė§€ í’ˆė§ˆė€ 1~100ėž…ë‹ˆë‹¤. ë†’ė„ėˆ˜ëĄ ėĸ‹ė§€ë§Œ 파ėŧė´ ėģ¤ė§‘니다.", - "image_fullsize_title": "풀ė‚Ŧė´ėψ ė´ë¯¸ė§€ 네렕", - "image_prefer_embedded_preview": "íŦ함된 미ëĻŦ ëŗ´ę¸° ė„ í˜¸", - "image_prefer_embedded_preview_setting_description": "가ëŠĨ한 ę˛Ŋ뚰 ė´ë¯¸ė§€ 래ëĻŦ ė‹œ RAW ė‚Ŧ맄뗐 íŦ함된 미ëĻŦ ëŗ´ę¸°ëĨŧ ė‚ŦėšŠí•Šë‹ˆë‹¤. íŦ함된 미ëĻŦ ëŗ´ę¸°ëŠ” ėš´ëŠ”ëŧė—ė„œ ėƒė„ąëœ 것ėœŧ로 ėš´ëŠ”ëŧ마다 í’ˆė§ˆė´ 다ëĻ…ë‹ˆë‹¤. ėŧëļ€ ė´ë¯¸ė§€ė˜ ę˛Ŋ뚰 더 ė •í™•í•œ ėƒ‰ėƒė´ 표현될 눘 ėžˆė§€ë§Œ 반대로 더 ë§Žė€ ė•„í‹°íŒŠíŠ¸ę°€ ėžˆė„ ėˆ˜ë„ ėžˆėŠĩ니다.", - "image_prefer_wide_gamut": "ë„“ė€ ėƒ‰ ė˜ė—­ ė„ í˜¸", - "image_prefer_wide_gamut_setting_description": "ė„Ŧ네ėŧ ė´ë¯¸ė§€ė— Display P3ëĨŧ ė‚ŦėšŠí•Šë‹ˆë‹¤. ë§Žė€ ėƒ‰ėƒė„ 표현할 눘 ėžˆė–´ 더 ė •í™•í•œ í‘œí˜„ė´ 가ëŠĨí•˜ė§€ë§Œ, ė˜¤ëž˜ëœ 브ëŧėš°ė €ëĨŧ ė‚ŦėšŠí•˜ëŠ” ę˛Ŋ뚰 ė´ë¯¸ė§€ę°€ 다ëĨ´ę˛Œ ëŗ´ėŧ 눘 ėžˆėŠĩ니다. ėƒ‰ėƒ ė™œęŗĄė„ ë°Šė§€í•˜ę¸° ėœ„í•´ sRGB ė´ë¯¸ė§€ëŠ” ė´ ė„¤ė •ė´ ė ėšŠë˜ė§€ ė•ŠėŠĩ니다.", - "image_preview_description": "ëŠ”íƒ€ë°ė´í„°ëĨŧ ė œęą°í•œ 뤑氄 íŦę¸°ė˜ ė´ë¯¸ė§€, 단ėŧ 항ëĒŠė„ ëŗ´ëŠ” ę˛Ŋ뚰 및 揰溄 학ėŠĩ뗐 ė‚ŦėšŠë¨", - "image_preview_quality_description": "1ëļ€í„° 100 ė‚Ŧė´ė˜ 미ëĻŦëŗ´ę¸° í’ˆė§ˆ. ę°’ė´ ë†’ė„ėˆ˜ëĄ ėĸ‹ė§€ë§Œ 파ėŧ íŦ기가 ėģ¤ė ¸ ė•ąė˜ ë°˜ė‘ė„ąė´ ë–¨ė–´ė§ˆ 눘 ėžˆėœŧ늰, ę°’ė´ 낮ėœŧ늴 揰溄 학ėŠĩė˜ í’ˆė§ˆė´ ë–¨ė–´ė§ˆ 눘 ėžˆėŠĩ니다.", + "image_format_description": "WebP는 JPEGëŗ´ë‹¤ 파ėŧ íŦ기가 ėž‘ė§€ë§Œ, ė¸ėŊ”ë”Šė— 더 ë§Žė€ ė‹œę°„ė´ ė†Œėš”ëŠë‹ˆë‹¤.", + "image_fullsize_description": "확대 ëŗ´ę¸° ė‹œ ė‚ŦėšŠë˜ëŠ”, ëŠ”íƒ€ë°ė´í„°ę°€ ė—†ëŠ” 렄랴 íŦ기 ė´ë¯¸ė§€", + "image_fullsize_enabled": "렄랴 íŦ기 ė´ë¯¸ė§€ ėƒė„ą í™œė„ąí™”", + "image_fullsize_enabled_description": "ė›šė— ė í•Ší•˜ė§€ ė•Šė€ í˜•ė‹ė¸ ę˛Ŋ뚰 렄랴 íŦ기 ė´ë¯¸ė§€ëĨŧ ėƒė„ąí•Šë‹ˆë‹¤. \"내ėžĨ 미ëĻŦëŗ´ę¸° ėš°ė„  ė‚ŦėšŠ\"ė´ í™œė„ąí™”ë˜ė–´ ėžˆėœŧ늴, ëŗ€í™˜ ė—†ė´ 내ėžĨ된 미ëĻŦëŗ´ę¸°ëĨŧ 그대로 ė‚ŦėšŠí•Šë‹ˆë‹¤. JPEGęŗŧ ę°™ė€ ė›š ėšœí™”ė ė¸ í˜•ė‹ė—ëŠ” 똁í–Ĩė„ ėŖŧė§€ ė•ŠėŠĩ니다.", + "image_fullsize_quality_description": "렄랴 íŦ기 ė´ë¯¸ė§€ė˜ í’ˆė§ˆ (1~100). ėˆĢėžę°€ ë†’ė„ėˆ˜ëĄ í’ˆė§ˆė´ ėĸ‹ė§€ë§Œ 파ėŧ íŦ기도 ėģ¤ė§‘니다.", + "image_fullsize_title": "렄랴 íŦ기 ė´ë¯¸ė§€ 네렕", + "image_prefer_embedded_preview": "내ėžĨ 미ëĻŦëŗ´ę¸° ėš°ė„  ė‚ŦėšŠ", + "image_prefer_embedded_preview_setting_description": "RAW ė‚Ŧ맄뗐 íŦ함된 내ėžĨ 미ëĻŦëŗ´ę¸°ëĨŧ ė´ë¯¸ė§€ 래ëĻŦ ė‹œ ėž…ë Ĩėœŧ로 ė‚ŦėšŠí•Šë‹ˆë‹¤(ė‚ŦėšŠ 가ëŠĨ한 ę˛Ŋėš°ė— 한함). ė´ ë°Šė‹ė€ ėŧëļ€ ė´ë¯¸ė§€ė—ė„œ 더 ė •í™•í•œ ėƒ‰ėƒė„ ė–ģė„ 눘 ėžˆė§€ë§Œ, 미ëĻŦëŗ´ę¸°ė˜ í’ˆė§ˆė€ ėš´ëŠ”ëŧ뗐 따ëŧ 다ëĨ´ëа ė••ėļ•ėœŧ로 ė¸í•œ í’ˆė§ˆ ė €í•˜ę°€ 나타날 눘 ėžˆėŠĩ니다.", + "image_prefer_wide_gamut": "ę´‘ėƒ‰ė—­ ėš°ė„  ė‚ŦėšŠ", + "image_prefer_wide_gamut_setting_description": "ė„Ŧ네ėŧ뗐 Display P3 ėƒ‰ė—­ė„ ė‚ŦėšŠí•Šë‹ˆë‹¤. ę´‘ėƒ‰ė—­ ė´ë¯¸ė§€ëĨŧ ëŗ´ë‹¤ ėƒėƒí•˜ę˛Œ 표현할 눘 ėžˆė§€ë§Œ, ęĩŦ형 브ëŧėš°ė €ë‚˜ ėžĨėš˜ė—ė„œëŠ” 다ëĨ´ę˛Œ ëŗ´ėŧ 눘 ėžˆėŠĩ니다. sRGB ė´ë¯¸ė§€ė˜ ę˛Ŋ뚰 ėƒ‰ėƒ ė™œęŗĄė„ ë°Šė§€í•˜ę¸° ėœ„í•´ 그대로 ėœ ė§€ëŠë‹ˆë‹¤.", + "image_preview_description": "단ėŧ 항ëĒŠė„ ëŗ´ęą°ë‚˜ 揰溄 학ėŠĩ뗐 ė‚ŦėšŠë˜ëŠ”, ëŠ”íƒ€ë°ė´í„°ę°€ ė œęą°ëœ 뤑氄 íŦ기 ė´ë¯¸ė§€", + "image_preview_quality_description": "미ëĻŦëŗ´ę¸° í’ˆė§ˆ (1~100). ėˆĢėžę°€ ë†’ė„ėˆ˜ëĄ í’ˆė§ˆė´ ėĸ‹ė•„ė§€ė§€ë§Œ, 파ėŧ íŦ기가 ėģ¤ė§€ęŗ  ė•ą ë°˜ė‘ ė†ë„ę°€ ëŠë ¤ė§ˆ 눘 ėžˆėŠĩ니다. 너ëŦ´ 낮게 ė„¤ė •í•˜ëŠ´ 揰溄 학ėŠĩ í’ˆė§ˆė— 똁í–Ĩė„ 뤄 눘 ėžˆėŠĩ니다.", "image_preview_title": "미ëĻŦëŗ´ę¸° 네렕", "image_quality": "í’ˆė§ˆ", "image_resolution": "í•´ėƒë„", - "image_resolution_description": "í•´ėƒë„ę°€ ë†’ė„ ėˆ˜ëĄ 디테ėŧė´ ëŗ´ėĄ´ë˜ė§€ë§Œ 파ėŧė´ íŦęŗ  ė¸ėŊ”ë”Šė´ ė˜¤ëž˜ 깸ëĻŦ늰 ė•ą ė‘ë‹ĩė„ąė´ ë–¨ė–´ė§ˆ 눘 ėžˆėŠĩ니다.", + "image_resolution_description": "í•´ėƒë„ę°€ ë†’ė„ėˆ˜ëĄ 넏ëļ€ ė •ëŗ´ę°€ ėž˜ ëŗ´ėĄ´ë˜ė§€ë§Œ, ė¸ėŊ”ë”Šė´ ëŠë ¤ė§€ęŗ  파ėŧė´ ėģ¤ė§€ëа ė•ą ë°˜ė‘ ė†ë„ę°€ ë–¨ė–´ė§ˆ 눘 ėžˆėŠĩ니다.", "image_settings": "ė´ë¯¸ė§€ 네렕", "image_settings_description": "ėƒė„ąëœ ė´ë¯¸ė§€ė˜ í’ˆė§ˆ 및 í•´ėƒë„ 관ëĻŦ", - "image_thumbnail_description": "ëŠ”íƒ€ë°ė´í„°ę°€ ė œęą°ëœ ėž‘ė€ ė„Ŧ네ėŧ ė´ë¯¸ė§€, íƒ€ėž„ëŧė¸ 등 ė‚Ŧė§„ė„ ęˇ¸ëŖší™”í•˜ė—Ŧ ëŗ´ëŠ” ę˛Ŋėš°ė— ė‚ŦėšŠë¨", - "image_thumbnail_quality_description": "ė„Ŧ네ėŧ í’ˆė§ˆ(1~100). ë†’ė„ėˆ˜ëĄ ėĸ‹ė§€ë§Œ 파ėŧíŦ기가 ėģ¤ė ¸ ė•ąė˜ ë°˜ė‘ė„ąė´ ë–¨ė–´ė§ˆ 눘 ėžˆėŠĩ니다.", + "image_thumbnail_description": "ëŠ”íƒ€ë°ė´í„°ę°€ ė œęą°ëœ ėž‘ė€ ė„Ŧ네ėŧ로, ëŠ”ė¸ íƒ€ėž„ëŧė¸ ë“ąė—ė„œ ė—ŦëŸŦ 항ëĒŠė„ ëŗŧ 때 ė‚ŦėšŠëŠë‹ˆë‹¤.", + "image_thumbnail_quality_description": "ė„Ŧ네ėŧ í’ˆė§ˆ (1~100). ėˆĢėžę°€ ë†’ė„ėˆ˜ëĄ í””ė§ˆė´ ėĸ‹ė§€ë§Œ, 파ėŧ íŦ기가 ėģ¤ė§€ęŗ  ė•ą ë°˜ė‘ ė†ë„ę°€ ëŠë ¤ė§ˆ 눘 ėžˆėŠĩ니다.", "image_thumbnail_title": "ė„Ŧ네ėŧ 네렕", "job_concurrency": "{job} ë™ė‹œė„ą", "job_created": "ėž‘ė—…ė´ ėƒė„ąë˜ė—ˆėŠĩ니다.", - "job_not_concurrency_safe": "ė´ ėž‘ė—…ė€ ë™ė‹œ ė‹¤í–‰ė´ ė œí•œëŠë‹ˆë‹¤.", + "job_not_concurrency_safe": "ė´ ėž‘ė—…ė€ ë™ė‹œ ė‹¤í–‰ė— ė•ˆė „í•˜ė§€ ė•ŠėŠĩ니다.", "job_settings": "ėž‘ė—… 네렕", "job_settings_description": "ėž‘ė—… ë™ė‹œė„ą 관ëĻŦ", "job_status": "ėž‘ė—… ėƒíƒœ", @@ -100,23 +100,23 @@ "jobs_failed": "{jobCount, plural, other {#氜}} ė‹¤íŒ¨", "library_created": "{library} ëŧė´ë¸ŒëŸŦëĻŦëĨŧ ėƒė„ąí–ˆėŠĩ니다.", "library_deleted": "ëŧė´ë¸ŒëŸŦëĻŦ가 ė‚­ė œë˜ė—ˆėŠĩ니다.", - "library_import_path_description": "氀렏ė˜Ŧ 폴더ëĨŧ ė„ íƒí•˜ė„¸ėš”. ė„ íƒí•œ 폴더 및 í•˜ėœ„ í´ë”ė—ė„œ ė‚Ŧė§„ęŗŧ ë™ė˜ėƒė„ 늤ėē”핊니다.", + "library_import_path_description": "氀렏ė˜Ŧ 폴더ëĨŧ ė§€ė •í•˜ė„¸ėš”. 해당 í´ë”ė™€ ëĒ¨ë“  í•˜ėœ„ í´ë”ė—ė„œ ė´ë¯¸ė§€ė™€ ë™ė˜ėƒė„ 늤ėē”핊니다.", "library_scanning": "ėŖŧ揰렁 늤ėē”", - "library_scanning_description": "ėŖŧę¸°ė ė¸ ëŧė´ë¸ŒëŸŦëĻŦ 늤ėē” ęĩŦė„ą", - "library_scanning_enable_description": "ėŖŧę¸°ė ė¸ ëŧė´ë¸ŒëŸŦëĻŦ 늤ėē” í™œė„ąí™”", + "library_scanning_description": "ëŧė´ë¸ŒëŸŦëĻŦ ėŖŧ揰렁 늤ėē” ęĩŦė„ą", + "library_scanning_enable_description": "ëŧė´ë¸ŒëŸŦëĻŦ ėŖŧ揰렁 늤ėē” í™œė„ąí™”", "library_settings": "뙏ëļ€ ëŧė´ë¸ŒëŸŦëĻŦ", "library_settings_description": "뙏ëļ€ ëŧė´ë¸ŒëŸŦëĻŦ 네렕 관ëĻŦ", - "library_tasks_description": "뙏ëļ€ ëŧė´ë¸ŒëŸŦëĻŦė—ė„œ 냈 ėžė‚° 및/또는 ëŗ€ę˛Ŋ된 ėžė‚°ė„ ę˛€ėƒ‰í•Šë‹ˆë‹¤", - "library_watching_enable_description": "뙏ëļ€ ëŧė´ë¸ŒëŸŦëĻŦė˜ 파ėŧ ëŗ€ę˛Ŋ ę°ė‹œ", - "library_watching_settings": "ëŧė´ë¸ŒëŸŦëĻŦ ę°ė‹œ (ė‹¤í—˜ 기ëŠĨ)", - "library_watching_settings_description": "파ėŧ ëŗ€ę˛…ė„ ėžë™ėœŧ로 氐맀", - "logging_enable_description": "로그 기록 í™œė„ąí™”", - "logging_level_description": "í™œė„ąí™”ëœ ę˛Ŋ뚰 ė‚ŦėšŠí•  로그 ë ˆë˛¨ė„ ė„ íƒí•Šë‹ˆë‹¤.", - "logging_settings": "로그 네렕", + "library_tasks_description": "뙏ëļ€ ëŧė´ë¸ŒëŸŦëĻŦė—ė„œ 냈 항ëĒŠ 또는 ëŗ€ę˛Ŋ된 항ëĒŠė„ 늤ėē”", + "library_watching_enable_description": "뙏ëļ€ ëŧė´ë¸ŒëŸŦëĻŦ 파ėŧ ëŗ€ę˛Ŋ ę°ė‹œ", + "library_watching_settings": "ëŧė´ë¸ŒëŸŦëĻŦ ę°ė‹œ (ė‹¤í—˜ė )", + "library_watching_settings_description": "파ėŧ ëŗ€ę˛Ŋ ėžë™ 氐맀", + "logging_enable_description": "로깅 í™œė„ąí™”", + "logging_level_description": "í™œė„ąí™” ė‹œ ė‚ŦėšŠí•  로그 ë ˆë˛¨ė„ ė„ íƒí•Šë‹ˆë‹¤.", + "logging_settings": "로깅", "machine_learning_clip_model": "CLIP ëĒ¨ë¸", - "machine_learning_clip_model_description": "CLIP ëĒ¨ë¸ė˜ ėĸ…ëĨ˜ëŠ” ė´ęŗŗė„ ė°¸ėĄ°í•˜ė„¸ėš”. 한ęĩ­ė–´ 등 다ęĩ­ė–´ ę˛€ėƒ‰ė„ ė‚ŦėšŠí•˜ë ¤ëŠ´ Multilingual CLIP ëĒ¨ë¸ė„ ė„ íƒí•˜ė„¸ėš”. ëĒ¨ë¸ė„ ëŗ€ę˛Ŋ한 후 ëĒ¨ë“  항ëĒŠė— 대한 ėŠ¤ë§ˆíŠ¸ ę˛€ėƒ‰ ėž‘ė—…ė„ ë‹¤ė‹œ ė§„í–‰í•´ė•ŧ 합니다.", - "machine_learning_duplicate_detection": "ëš„ėŠˇí•œ 항ëĒŠ 氐맀", - "machine_learning_duplicate_detection_enabled": "ëš„ėŠˇí•œ 항ëĒŠ 氐맀 í™œė„ąí™”", + "machine_learning_clip_model_description": "CLIP ëĒ¨ë¸ė˜ ėĸ…ëĨ˜ëŠ” ė´ęŗŗė„ ė°¸ėĄ°í•˜ė„¸ėš”. 한ęĩ­ė–´ëĨŧ íŦ함한 다ęĩ­ė–´ ę˛€ėƒ‰ė„ ė‚ŦėšŠí•˜ë ¤ëŠ´ Multilingual CLIP ëĒ¨ë¸ė„ ė„ íƒí•˜ė„¸ėš”. ëĒ¨ë¸ė„ ëŗ€ę˛Ŋ한 ę˛Ŋ뚰, ëĒ¨ë“  항ëĒŠė— 대해 'ėŠ¤ë§ˆíŠ¸ ę˛€ėƒ‰' ėž‘ė—…ė„ ë‹¤ė‹œ ė‹¤í–‰í•´ė•ŧ 합니다.", + "machine_learning_duplicate_detection": "뤑ëŗĩ 氐맀", + "machine_learning_duplicate_detection_enabled": "뤑ëŗĩ 氐맀 í™œė„ąí™”", "machine_learning_duplicate_detection_enabled_description": "ëš„í™œė„ąí™”ëœ ę˛Ŋėš°ė—ë„ ė™„ė „ížˆ 동ėŧ한 항ëĒŠė€ 뤑ëŗĩ ė œęą°ëŠë‹ˆë‹¤.", "machine_learning_duplicate_detection_setting_description": "CLIP ėž„ë˛ ë”Šė„ ė‚ŦėšŠí•˜ė—Ŧ ëš„ėŠˇí•œ 항ëĒŠ ė°žę¸°", "machine_learning_enabled": "揰溄 학ėŠĩ í™œė„ąí™”", @@ -128,7 +128,7 @@ "machine_learning_facial_recognition_setting": "ė–ŧęĩ´ ė¸ė‹ í™œė„ąí™”", "machine_learning_facial_recognition_setting_description": "ëš„í™œė„ąí™”ëœ ę˛Ŋ뚰 ė´ë¯¸ė§€ė—ė„œ ė–ŧęĩ´ ė¸ė‹ė„ ė§„í–‰í•˜ė§€ ė•Šėœŧ늰, íƒėƒ‰ íŽ˜ė´ė§€ė— ė¸ëŦŧ ëĒŠëĄė´ í‘œė‹œë˜ė§€ ė•ŠėŠĩ니다.", "machine_learning_max_detection_distance": "ėĩœëŒ€ 氐맀 ęą°ëĻŦ", - "machine_learning_max_detection_distance_description": "두 ė´ë¯¸ė§€ëĨŧ 뜠ė‚Ŧ한 ė´ë¯¸ė§€ëĄœ 간ėŖŧ하는 ęą°ëĻŦė˜ ėĩœëŒ“ę°’ė„ 0.001ė—ė„œ 0.1 ė‚Ŧė´ëĄœ ė„¤ė •í•Šë‹ˆë‹¤. ę°’ė´ 높ėœŧ늴 ë¯ŧ감도가 ë‚Žė•„ė ¸ 뜠ė‚Ŧ한 ė´ë¯¸ė§€ëĄœ ę°ė§€í•˜ëŠ” ëš„ėœ¨ė´ ë†’ė•„ė§€ë‚˜, ėž˜ëĒģ된 결ęŗŧëĨŧ ëŗ´ėŧ 눘 ėžˆėŠĩ니다.", + "machine_learning_max_detection_distance_description": "두 ė´ë¯¸ė§€ëĨŧ 뤑ëŗĩėœŧ로 간ėŖŧ하기 ėœ„í•œ ėĩœëŒ€ ęą°ëĻŋ값 (0.001~0.1). ę°’ė´ í´ėˆ˜ëĄ 더 ë§Žė€ 뤑ëŗĩė„ ę°ė§€í•  눘 ėžˆė§€ë§Œ, ėž˜ëĒģ된 氐맀氀 ë°œėƒí•  눘 ėžˆėŠĩ니다.", "machine_learning_max_recognition_distance": "ėĩœëŒ€ ė¸ė‹ ęą°ëĻŦ", "machine_learning_max_recognition_distance_description": "두 ė–ŧęĩ´ė„ 동ėŧė¸ėœŧ로 ė¸ė‹í•˜ëŠ” ęą°ëĻŦė˜ ėĩœëŒ“ę°’ė„ 0ė—ė„œ 2 ė‚Ŧė´ëĄœ ė„¤ė •í•Šë‹ˆë‹¤. ė´ ę°’ė„ 낮ėļ”늴 다ëĨ¸ ė¸ëŦŧė„ 동ėŧė¸ėœŧ로 ė¸ė‹í•˜ëŠ” ę˛ƒė„ ë°Šė§€í•  눘 ėžˆęŗ , ę°’ė„ ë†’ė´ëŠ´ 동ėŧė¸ė„ 다ëĨ¸ ė¸ëŦŧ로 ė¸ė‹í•˜ëŠ” ę˛ƒė„ ë°Šė§€í•  눘 ėžˆėŠĩ니다. 두 ė¸ëŦŧė„ ëŗ‘í•Ší•˜ëŠ” ę˛ƒė´ 한 ė¸ëŦŧė„ 두 ëĒ…ėœŧ로 ëļ„ëĻŦ하는 ę˛ƒëŗ´ë‹¤ ė‰Ŧėš°ë¯€ëĄœ, 가ëŠĨ한 ë‚Žė€ ėž„ęŗ„ę°’ė„ ė‚ŦėšŠí•˜ė„¸ėš”.", "machine_learning_min_detection_score": "ėĩœė†Œ ė‹ ëĸ°ë„ 렐눘", @@ -157,8 +157,8 @@ "map_settings": "ė§€ë„", "map_settings_description": "ė§€ë„ 네렕 관ëĻŦ", "map_style_description": "ė§€ë„ 테마 style.json URL", - "memory_cleanup_job": "메ëǍëĻŦ ė •ëĻŦ", - "memory_generate_job": "메ëǍëĻŦ ėƒė„ą", + "memory_cleanup_job": "ėļ”ė–ĩ ė •ëĻŦ", + "memory_generate_job": "ėļ”ė–ĩ ėƒė„ą", "metadata_extraction_job": "ëŠ”íƒ€ë°ė´í„° ėļ”ėļœ", "metadata_extraction_job_description": "각 항ëĒŠė—ė„œ GPS, ė¸ëŦŧ 및 í•´ėƒë„ ë“ąė˜ ëŠ”íƒ€ë°ė´í„° ė •ëŗ´ ėļ”ėļœ", "metadata_faces_import_setting": "ė–ŧęĩ´ ę°€ė ¸ė˜¤ę¸° í™œė„ąí™”", @@ -224,8 +224,8 @@ "registration": "관ëĻŦėž ęŗ„ė • ėƒė„ą", "registration_description": "ė˛Ģ ë˛ˆė§¸ëĄœ ėƒė„ąë˜ëŠ” ė‚ŦėšŠėžëŠ” 관ëĻŦėž ęļŒí•œė„ ëļ€ė—Ŧ받ėœŧ늰, 관ëĻŦ 및 ė‚ŦėšŠėž ėƒė„ąė´ 가ëŠĨ합니다.", "repair_all": "ëĒ¨ë‘ 눘ëĻŦ", - "repair_matched_items": "동ėŧ 항ëĒŠ {count, plural, one {#氜} other {#氜}}ëĨŧ í™•ė¸í–ˆėŠĩ니다.", - "repaired_items": "항ëĒŠ {count, plural, one {#氜} other {#氜}}ëĨŧ 눘ëĻŦ했ėŠĩ니다.", + "repair_matched_items": "항ëĒŠ {count, plural, one {#氜} other {#氜}}가 ėŧėš˜í•Šë‹ˆë‹¤.", + "repaired_items": "항ëĒŠ {count, plural, one {#氜} other {#氜}}ëĨŧ ëŗĩęĩŦ했ėŠĩ니다.", "require_password_change_on_login": "ė˛Ģ ëĄœęˇ¸ė¸ ė‹œ 비밀번호 ëŗ€ę˛Ŋ ėš”ęĩŦ", "reset_settings_to_default": "ė„¤ė •ė„ ę¸°ëŗ¸ę°’ėœŧ로 ëŗĩ뛐", "reset_settings_to_recent_saved": "ë§ˆė§€ë§‰ėœŧ로 ė €ėžĨ된 네렕ėœŧ로 ëŗĩ뛐", @@ -251,7 +251,7 @@ "storage_template_hash_verification_enabled_description": "í•´ė‹œ 검ėĻė„ í™œė„ąí™”í•Šë‹ˆë‹¤. ė´ ė„¤ė •ė˜ 결ęŗŧëĨŧ í™•ė‹¤ížˆ ė´í•´í•˜ė§€ ė•ŠëŠ” 한 ëš„í™œė„ąí™”í•˜ė§€ ë§ˆė„¸ėš”.", "storage_template_migration": "ėŠ¤í† ëĻŦė§€ 템플ëĻŋ ë§ˆė´ęˇ¸ë ˆė´ė…˜", "storage_template_migration_description": "ė´ė „ė— ė—…ëĄœë“œëœ 항ëĒŠė— 현ėžŦ {template} ė ėšŠ", - "storage_template_migration_info": "ė €ėžĨė†Œ 템플ëĻŋė€ ëĒ¨ë“  확ėžĨėžëĨŧ ė†ŒëŦ¸ėžëĄœ ëŗ€í™˜í•Šë‹ˆë‹¤. 템플ëĻŋ ëŗ€ę˛Ŋ ė‚Ŧí•­ė€ 냈 ėžė‚°ė—ë§Œ ė ėšŠëŠë‹ˆë‹¤. ė´ė „ė— ė—…ëĄœë“œí•œ ėžė‚°ė— 템플ëĻŋė„ ė ėšŠí•˜ë ¤ëŠ´ {job}ëĨŧ ė‹¤í–‰í•˜ė„¸ėš”.", + "storage_template_migration_info": "ėŠ¤í† ëĻŦė§€ 템플ëĻŋė€ ëĒ¨ë“  확ėžĨėžëĨŧ ė†ŒëŦ¸ėžëĄœ ëŗ€í™˜í•Šë‹ˆë‹¤. 템플ëĻŋ ëŗ€ę˛Ŋ ė‚Ŧí•­ė€ ėƒˆëĄœ ė—…ëĄœë“œí•œ 항ëĒŠė—ë§Œ ė ėšŠëŠë‹ˆë‹¤. ę¸°ėĄ´ė— ė—…ëĄœë“œëœ 항ëĒŠė— ė ėšŠí•˜ë ¤ëŠ´ {job}ė„ ė‹¤í–‰í•˜ė„¸ėš”.", "storage_template_migration_job": "ėŠ¤í† ëĻŦė§€ 템플ëĻŋ ë§ˆė´ęˇ¸ë ˆė´ė…˜ ėž‘ė—…", "storage_template_more_details": "ė´ 기ëŠĨ뗐 대한 ėžė„¸í•œ ë‚´ėšŠė€ ėŠ¤í† ëĻŦė§€ 템플ëĻŋ 및 네ëĒ…ė„ ė°¸ėĄ°í•˜ė„¸ėš”.", "storage_template_onboarding_description": "ė´ 기ëŠĨė„ í™œė„ąí™”í•˜ëŠ´ ė‚ŦėšŠėž ė •ė˜ 템플ëĻŋė„ ė‚ŦėšŠí•˜ė—Ŧ 파ėŧė„ ėžë™ėœŧ로 ė •ëĻŦ할 눘 ėžˆėŠĩ니다. ė•ˆė •ė„ą ëŦ¸ė œëĄœ ė¸í•´ 해당 기ëŠĨė€ ę¸°ëŗ¸ė ėœŧ로 ëš„í™œė„ąí™”ë˜ė–´ ėžˆėŠĩ니다. ėžė„¸í•œ ë‚´ėšŠė€ ëŦ¸ė„œëĨŧ ė°¸ėĄ°í•˜ė„¸ėš”.", @@ -263,12 +263,12 @@ "tag_cleanup_job": "태그 ė •ëĻŦ", "template_email_available_tags": "템플ëĻŋė—ė„œ ë‹¤ėŒ ëŗ€ėˆ˜ëĨŧ ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다: {tags}", "template_email_if_empty": "ëš„ė–´ ėžˆëŠ” ę˛Ŋ뚰 ę¸°ëŗ¸ 템플ëĻŋė´ ė‚ŦėšŠëŠë‹ˆë‹¤.", - "template_email_invite_album": "ė•¨ë˛” 템플ëĻŋ ė´ˆëŒ€", + "template_email_invite_album": "ė•¨ë˛” ė´ˆëŒ€ 템플ëĻŋ", "template_email_preview": "미ëĻŦëŗ´ę¸°", "template_email_settings": "ė´ëŠ”ėŧ 템플ëĻŋ", "template_email_settings_description": "ė‚ŦėšŠėž ė •ė˜ ė´ëŠ”ėŧ 템플ëĻŋ 관ëĻŦ", "template_email_update_album": "ė•¨ë˛” 템플ëĻŋ ė—…ë°ė´íŠ¸", - "template_email_welcome": "ė´ëŠ”ėŧ 템플ëĻŋ뗐 ė˜¤ė‹ ę˛ƒė„ í™˜ė˜í•Šë‹ˆë‹¤", + "template_email_welcome": "ė›°ėģ´ ëŠ”ėŧ 템플ëĻŋ", "template_settings": "ė•ŒëĻŧ 템플ëĻŋ", "template_settings_description": "ė•ŒëĻŧė„ ėœ„í•œ ė‚ŦėšŠėž 맀렕 템플ëĻŋė„ 관ëĻŦ합니다.", "theme_custom_css_settings": "ė‚ŦėšŠėž ė •ė˜ CSS", @@ -295,13 +295,13 @@ "transcoding_audio_codec_description": "Opus는 가ėžĨ ėĸ‹ė€ í’ˆė§ˆė˜ ė˜ĩė…˜ė´ė§€ë§Œ 기기 및 ė†Œí”„íŠ¸ė›¨ė–´ę°€ ė˜¤ëž˜ëœ ę˛Ŋ뚰 í˜¸í™˜ë˜ė§€ ė•Šė„ 눘 ėžˆėŠĩ니다.", "transcoding_bitrate_description": "ėĩœëŒ€ ëš„íŠ¸ë ˆė´íŠ¸ëĨŧ 봈ęŗŧ하는 ë™ė˜ėƒ 또는 í—ˆėšŠë˜ė§€ ė•ŠëŠ” í˜•ė‹ė˜ ë™ė˜ėƒ", "transcoding_codecs_learn_more": "ė—Ŧę¸°ė—ė„œ ė‚ŦėšŠë˜ëŠ” ėšŠė–´ė— 대한 ėžė„¸í•œ ë‚´ėšŠė€ FFmpeg ëŦ¸ė„œė˜ H.264 ėŊ”덱, HEVC ėŊ”덱 및 VP9 ėŊ”덱 항ëĒŠė„ ė°¸ėĄ°í•˜ė„¸ėš”.", - "transcoding_constant_quality_mode": "ęŗ ė • í’ˆė§ˆ ëĒ¨ë“œ", + "transcoding_constant_quality_mode": "Constant quality mode", "transcoding_constant_quality_mode_description": "ICQ는 CQPëŗ´ë‹¤ ë‚˜ė€ ė„ąëŠĨė„ ëŗ´ė´ë‚˜ ėŧëļ€ ę¸°ę¸°ė˜ í•˜ë“œė›¨ė–´ ę°€ė†ė—ė„œ ė§€ė›ë˜ė§€ ė•Šė„ 눘 ėžˆėŠĩ니다. ė´ ė˜ĩė…˜ė„ ė„¤ė •í•˜ëŠ´ í’ˆė§ˆ 기반 ė¸ėŊ”딊 ė‹œ ė§€ė •ëœ ëĒ¨ë“œëĨŧ ėš°ė„ ė ėœŧ로 ė‚ŦėšŠí•Šë‹ˆë‹¤. NVENCė—ė„œëŠ” ICQëĨŧ ė§€ė›í•˜ė§€ ė•Šė•„ ė´ ė„¤ė •ė´ ė ėšŠë˜ė§€ ė•ŠėŠĩ니다.", - "transcoding_constant_rate_factor": "냁눘 ëš„ėœ¨ ęŗ„ėˆ˜(-CRF)", + "transcoding_constant_rate_factor": "Constant rate factor (-crf)", "transcoding_constant_rate_factor_description": "ėŧë°˜ė ėœŧ로 H.264는 23, HEVC는 28, VP9는 31, AV1는 35ëĨŧ ė‚ŦėšŠí•Šë‹ˆë‹¤. ę°’ė´ 낮ėœŧ늴 í’ˆė§ˆė´ í–Ĩėƒë˜ė§€ë§Œ 파ėŧ íŦ기가 ėĻę°€í•Šë‹ˆë‹¤.", "transcoding_disabled_description": "ë™ė˜ėƒė„ íŠ¸ëžœėŠ¤ėŊ”ë”Ší•˜ė§€ ė•ŠėŒ. ėŧëļ€ ę¸°ę¸°ė—ė„œ ėžŦėƒė´ ëļˆę°€ëŠĨ할 눘 ėžˆėŠĩ니다.", "transcoding_encoding_options": "ė¸ėŊ”딊 ė˜ĩė…˜", - "transcoding_encoding_options_description": "ė¸ėŊ”딊된 ë™ė˜ėƒė˜ ėŊ”덱, í•´ėƒë„, í’ˆė§ˆ 및 기타 ė˜ĩė…˜ė„ ė„¤ė •í•Šë‹ˆë‹¤", + "transcoding_encoding_options_description": "ė¸ėŊ”딊된 ë™ė˜ėƒė˜ ėŊ”덱, í•´ėƒë„, í’ˆė§ˆ 및 기타 ė˜ĩė…˜ 네렕", "transcoding_hardware_acceleration": "í•˜ë“œė›¨ė–´ ę°€ė†", "transcoding_hardware_acceleration_description": "ė‹¤í—˜ė ė¸ 기ëŠĨėž…ë‹ˆë‹¤. ė†ë„ę°€ í–Ĩėƒë˜ė§€ë§Œ 동ėŧ ëš„íŠ¸ë ˆė´íŠ¸ė—ė„œ í’ˆė§ˆė´ ėƒëŒ€ė ėœŧ로 ë‚Žė„ 눘 ėžˆėŠĩ니다.", "transcoding_hardware_decoding": "í•˜ë“œė›¨ė–´ 디ėŊ”딊", @@ -315,7 +315,7 @@ "transcoding_max_keyframe_interval_description": "í‚¤í”„ë ˆėž„ ė‚Ŧė´ ėĩœëŒ€ í”„ë ˆėž„ ęą°ëĻŦëĨŧ ė„¤ė •í•Šë‹ˆë‹¤. ę°’ė´ 낮ėœŧ늴 ė••ėļ• íš¨ėœ¨ė´ ė €í•˜ë˜ė§€ë§Œ ę˛€ėƒ‰ ė‹œę°„ė´ ę°œė„ ë˜ęŗ  ëš ëĨ¸ ė›€ė§ėž„ė´ ėžˆëŠ” ėžĨëŠ´ė—ė„œ í’ˆė§ˆė´ í–ĨėƒëŠë‹ˆë‹¤. 0ė„ ėž…ë Ĩ한 ę˛Ŋ뚰 ėžë™ėœŧ로 ė„¤ė •í•Šë‹ˆë‹¤.", "transcoding_optimal_description": "ëĒŠí‘œ í•´ėƒë„ëŗ´ë‹¤ ë†’ė€ ë™ė˜ėƒ 또는 í—ˆėšŠë˜ė§€ ė•ŠëŠ” í˜•ė‹ė˜ ë™ė˜ėƒ", "transcoding_policy": "íŠ¸ëžœėŠ¤ėŊ”드 ė •ėą…", - "transcoding_policy_description": "ë™ė˜ėƒ íŠ¸ëžœėŠ¤ėŊ”딊 ė‹œę¸° ė„¤ė •í•˜ę¸°", + "transcoding_policy_description": "íŠ¸ëžœėŠ¤ėŊ”딊 ëŒ€ėƒ ë™ė˜ėƒ 네렕", "transcoding_preferred_hardware_device": "ė„ í˜¸í•˜ëŠ” í•˜ë“œė›¨ė–´ 기기", "transcoding_preferred_hardware_device_description": "í•˜ë“œė›¨ė–´ íŠ¸ëžœėŠ¤ėŊ”ë”Šė— ė‚ŦėšŠí•  dri 노드ëĨŧ ė„¤ė •í•Šë‹ˆë‹¤. (VAAPI뙀 QSV만 해당)", "transcoding_preset_preset": "프ëĻŦė…‹ (-preset)", @@ -324,10 +324,10 @@ "transcoding_reference_frames_description": "íŠšė • í”„ë ˆėž„ė„ ė••ėļ•í•  때 ė°¸ėĄ°í•˜ëŠ” í”„ë ˆėž„ 눘ëĨŧ ė„¤ė •í•Šë‹ˆë‹¤. ę°’ė´ 높ėœŧ늴 ė••ėļ• íš¨ėœ¨ė´ í–Ĩėƒë˜ë‚˜ ė¸ėŊ”딊 ė†ë„ę°€ ė €í•˜ëŠë‹ˆë‹¤. 0ė„ ėž…ë Ĩ한 ę˛Ŋ뚰 ėžë™ėœŧ로 ė„¤ė •í•Šë‹ˆë‹¤.", "transcoding_required_description": "í—ˆėšŠëœ í˜•ė‹ė´ ė•„ë‹Œ ë™ė˜ėƒë§Œ", "transcoding_settings": "ë™ė˜ėƒ íŠ¸ëžœėŠ¤ėŊ”딊 네렕", - "transcoding_settings_description": "íŠ¸ëžœėŠ¤ėŊ”딊할 ë™ė˜ėƒęŗŧ 래ëĻŦ 방법 관ëĻŦ하기", + "transcoding_settings_description": "íŠ¸ëžœėŠ¤ėŊ”딊할 ë™ė˜ėƒ 및 래ëĻŦ 방법 관ëĻŦ", "transcoding_target_resolution": "ëĒŠí‘œ í•´ėƒë„", "transcoding_target_resolution_description": "ë†’ė€ í•´ėƒë„ëĨŧ ė„ íƒí•œ ę˛Ŋ뚰 넏ëļ€ ëŦ˜ė‚Ŧė˜ ė†ė‹¤ė„ ėĩœė†Œí™”í•  눘 ėžˆė§€ë§Œ, ė¸ėŊ”딊 ė‹œę°„ęŗŧ 파ėŧ íŦ기가 ėĻę°€í•˜ė—Ŧ ė•ąė˜ ë°˜ė‘ ė†ë„ę°€ ëŠë ¤ė§ˆ 눘 ėžˆėŠĩ니다.", - "transcoding_temporal_aq": "ėŧė‹œė  AQ", + "transcoding_temporal_aq": "Temporal AQ", "transcoding_temporal_aq_description": "넏ëļ€ ëŦ˜ė‚Ŧ가 ë§Žęŗ  ė›€ė§ėž„ė´ ė ė€ ėžĨëŠ´ė˜ í’ˆė§ˆė´ í–ĨėƒëŠë‹ˆë‹¤. ė˜¤ëž˜ëœ 揰揰뙀 í˜¸í™˜ë˜ė§€ ė•Šė„ 눘 ėžˆėŠĩ니다. (NVENC만 해당)", "transcoding_threads": "ėŠ¤ë ˆë“œ", "transcoding_threads_description": "ę°’ė´ 높ėœŧ늴 ė¸ėŊ”딊 ė†ë„ę°€ í–Ĩėƒë˜ė§€ë§Œ ëĻŦė†ŒėŠ¤ ė‚ŦėšŠëŸ‰ė´ ėĻę°€í•Šë‹ˆë‹¤. ę°’ė€ CPU ėŊ”ė–´ ėˆ˜ëŗ´ë‹¤ ėž‘ė•„ė•ŧ 하며, ė„¤ė •í•˜ė§€ ė•Šėœŧ려늴 0ė„ ėž…ë Ĩ합니다.", @@ -371,13 +371,17 @@ "admin_password": "관ëĻŦėž 비밀번호", "administration": "관ëĻŦ", "advanced": "溠揉", + "advanced_settings_enable_alternate_media_filter_subtitle": "ė´ ė˜ĩė…˜ė„ ė‚ŦėšŠí•˜ëŠ´ 동기화 뤑 ë¯¸ë””ė–´ëĨŧ ëŒ€ė˛´ 揰뤀ėœŧ로 필터링할 눘 ėžˆėŠĩ니다. ė•ąė´ ëĒ¨ë“  ė•¨ë˛”ė„ ė œëŒ€ëĄœ ę°ė§€í•˜ė§€ ëĒģ할 때만 ė‚ŦėšŠí•˜ė„¸ėš”.", + "advanced_settings_enable_alternate_media_filter_title": "ëŒ€ė˛´ 기기 ė•¨ë˛” 동기화 필터 ė‚ŦėšŠ (ė‹¤í—˜ė )", "advanced_settings_log_level_title": "로그 레벨: {}", "advanced_settings_prefer_remote_subtitle": "ėŧëļ€ ę¸°ę¸°ė˜ ę˛Ŋ뚰 기기 ë‚´ė˜ ė„Ŧ네ėŧė„ 로드하는 ė†ë„ę°€ ë§¤ėš° 느ëĻŊ니다. ė„œë˛„ ė´ë¯¸ė§€ëĨŧ ëŒ€ė‹  로드하려면 ė´ ė„¤ė •ė„ í™œė„ąí™”í•˜ė„¸ėš”.", "advanced_settings_prefer_remote_title": "ė„œë˛„ ė´ë¯¸ė§€ ė„ í˜¸", - "advanced_settings_proxy_headers_subtitle": "각 ë„¤íŠ¸ė›ŒíŦ ėš”ė˛­ė„ ëŗ´ë‚ŧ 때 Immich가 ė‚ŦėšŠí•  í”„ëĄė‹œ 헤더ëĨŧ ė •ė˜í•Šë‹ˆë‹¤.", + "advanced_settings_proxy_headers_subtitle": "ë„¤íŠ¸ė›ŒíŦ ėš”ė˛­ė„ ëŗ´ë‚ŧ 때 Immich가 ė‚ŦėšŠí•  í”„ëĄė‹œ 헤더ëĨŧ ė •ė˜í•Šë‹ˆë‹¤.", "advanced_settings_proxy_headers_title": "í”„ëĄė‹œ 헤더", "advanced_settings_self_signed_ssl_subtitle": "ė„œë˛„ ė—”ë“œíŦė¸íŠ¸ė— 대한 SSL ė¸ėĻė„œ í™•ė¸ė„ 건너뜁니다. ėžė˛´ ė„œëĒ…ëœ ė¸ėĻė„œëĨŧ ė‚ŦėšŠí•˜ëŠ” ę˛Ŋ뚰 í™œė„ąí™”í•˜ė„¸ėš”.", "advanced_settings_self_signed_ssl_title": "ėžė˛´ ė„œëĒ…ëœ SSL ė¸ėĻė„œ í—ˆėšŠ", + "advanced_settings_sync_remote_deletions_subtitle": "ė›šė—ė„œ ė‚­ė œí•˜ęą°ë‚˜ ëŗĩė›í•œ 항ëĒŠė„ ė´ ę¸°ę¸°ė—ė„œë„ ėžë™ėœŧ로 래ëĻŦ하도록 네렕", + "advanced_settings_sync_remote_deletions_title": "ė›ę˛Š ė‚­ė œ 동기화 (ė‹¤í—˜ė )", "advanced_settings_tile_subtitle": "溠揉 ė‚ŦėšŠėž 네렕", "advanced_settings_troubleshooting_subtitle": "ëŦ¸ė œ í•´ę˛°ė„ ėœ„í•œ ėļ”ę°€ 기ëŠĨ ė‚ŦėšŠ", "advanced_settings_troubleshooting_title": "ëŦ¸ė œ 해결", @@ -408,10 +412,10 @@ "album_user_left": "{album} ė•¨ë˛”ė—ė„œ ë‚˜ė˜´", "album_user_removed": "{user}ë‹˜ė„ ė•¨ë˛”ė—ė„œ ė œęą°í•¨", "album_viewer_appbar_delete_confirm": "ė´ ė•¨ë˛”ė„ ė‚­ė œí•˜ė‹œę˛ ėŠĩ니까?", - "album_viewer_appbar_share_err_delete": "ė•¨ë˛” ė‚­ė œė— ė‹¤íŒ¨í–ˆėŠĩ니다.", - "album_viewer_appbar_share_err_leave": "ė•¨ë˛” ë‚˜ę°€ę¸°ė— ė‹¤íŒ¨í–ˆėŠĩ니다.", - "album_viewer_appbar_share_err_remove": "ė•¨ë˛”ė—ė„œ 항ëĒŠė„ ė œęą°í•˜ė§€ ëĒģ했ėŠĩ니다.", - "album_viewer_appbar_share_err_title": "ė•¨ë˛”ëĒ… ëŗ€ę˛Ŋ뗐 ė‹¤íŒ¨í–ˆėŠĩ니다.", + "album_viewer_appbar_share_err_delete": "ė•¨ë˛” ė‚­ė œ ė‹¤íŒ¨", + "album_viewer_appbar_share_err_leave": "ė•¨ë˛”ė—ė„œ ë‚˜ę°€ė§€ ëĒģ했ėŠĩ니다.", + "album_viewer_appbar_share_err_remove": "ė•¨ë˛”ė—ė„œ 항ëĒŠė„ ė œęą°í•˜ëŠ” 뤑 ëŦ¸ė œę°€ ë°œėƒí–ˆėŠĩ니다.", + "album_viewer_appbar_share_err_title": "ė•¨ë˛” 렜ëĒŠė„ ëŗ€ę˛Ŋí•˜ė§€ ëĒģ했ėŠĩ니다.", "album_viewer_appbar_share_leave": "ė•¨ë˛” 나가기", "album_viewer_appbar_share_to": "ęŗĩ뜠 ëŒ€ėƒ", "album_viewer_page_share_add_users": "ė‚ŦėšŠėž ėļ”ę°€", @@ -426,7 +430,7 @@ "allow_edits": "íŽ¸ė§‘ėžëĄœ 네렕", "allow_public_user_to_download": "ëĒ¨ë“  ė‚ŦėšŠėžė˜ ë‹¤ėš´ëĄœë“œ í—ˆėšŠ", "allow_public_user_to_upload": "ëĒ¨ë“  ė‚ŦėšŠėžė˜ ė—…ëĄœë“œ í—ˆėšŠ", - "alt_text_qr_code": "QRėŊ”드 ė´ë¯¸ė§€", + "alt_text_qr_code": "QR ėŊ”드 ė´ë¯¸ė§€", "anti_clockwise": "ë°˜ė‹œęŗ„ ë°Ší–Ĩ", "api_key": "API 키", "api_key_description": "ė´ ę°’ė€ 한 번만 í‘œė‹œëŠë‹ˆë‹¤. ė°Ŋė„ ë‹Ģ기 ė „ ë°˜ë“œė‹œ ëŗĩė‚Ŧ해ėŖŧė„¸ėš”.", @@ -444,11 +448,11 @@ "archive_size": "ė••ėļ• íŒŒėŧ íŦ기", "archive_size_description": "ë‹¤ėš´ëĄœë“œí•  ė••ėļ• íŒŒėŧė˜ íŦ기 ęĩŦė„ą (GiB ë‹¨ėœ„)", "archived": "ëŗ´ę´€í•¨", - "archived_count": "ëŗ´ę´€í•¨ėœŧ로 항ëĒŠ {count, plural, other {#氜}} ė´ë™ë¨", + "archived_count": "ëŗ´ę´€í•¨ėœŧ로 {count, plural, other {#氜}} 항ëĒŠ ė´ë™ë¨", "are_these_the_same_person": "동ėŧ한 ė¸ëŦŧė¸ę°€ėš”?", "are_you_sure_to_do_this": "ęŗ„ė† ė§„í–‰í•˜ė‹œę˛ ėŠĩ니까?", - "asset_action_delete_err_read_only": "ėŊ기 ė „ėšŠ 항ëĒŠė€ ė‚­ė œí•  눘 ė—†ėŠĩ니다. 건너뜁니다.", - "asset_action_share_err_offline": "누ëŊ된 항ëĒŠė„ ëļˆëŸŦė˜Ŧ 눘 ė—†ėŠĩ니다. 건너뜁니다.", + "asset_action_delete_err_read_only": "ėŊ기 ė „ėšŠ 항ëĒŠė€ ė‚­ė œí•  눘 ė—†ėœŧë¯€ëĄœ 건너뜁니다.", + "asset_action_share_err_offline": "ė˜¤í”„ëŧė¸ 항ëĒŠė„ 氀렏ė˜Ŧ 눘 ė—†ėœŧë¯€ëĄœ 건너뜁니다.", "asset_added_to_album": "ė•¨ë˛”ė— ėļ”ę°€ë˜ė—ˆėŠĩ니다.", "asset_adding_to_album": "ė•¨ë˛”ė— ėļ”ę°€ 뤑â€Ļ", "asset_description_updated": "항ëĒŠė˜ 네ëĒ…ė´ ė—…ë°ė´íŠ¸ë˜ė—ˆėŠĩ니다.", @@ -470,15 +474,15 @@ "asset_skipped_in_trash": "íœ´ė§€í†ĩė˜ 항ëĒŠ", "asset_uploaded": "ė—…ëĄœë“œ ė™„ëŖŒ", "asset_uploading": "ė—…ëĄœë“œ 뤑â€Ļ", - "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", + "asset_viewer_settings_subtitle": "ę°¤ëŸŦëĻŦ ëˇ°ė–´ 네렕 관ëĻŦ", "asset_viewer_settings_title": "ëŗ´ę¸° ė˜ĩė…˜", "assets": "항ëĒŠ", - "assets_added_count": "항ëĒŠ {count, plural, one {#氜} other {#氜}}가 ėļ”ę°€ë˜ė—ˆėŠĩ니다.", + "assets_added_count": "{count, plural, one {#氜} other {#氜}} 항ëĒŠ ėļ”가됨", "assets_added_to_album_count": "ė•¨ë˛”ė— 항ëĒŠ {count, plural, one {#氜} other {#氜}} ėļ”가됨", "assets_added_to_name_count": "{hasName, select, true {{name}} other {냈 ė•¨ë˛”}}뗐 항ëĒŠ {count, plural, one {#氜} other {#氜}} ėļ”가됨", "assets_count": "{count, plural, one {#氜} other {#氜}} 항ëĒŠ", "assets_deleted_permanently": "{}氜 항ëĒŠė´ 똁ęĩŦ렁ėœŧ로 ė‚­ė œë¨", - "assets_deleted_permanently_from_server": "Immichė—ė„œ 항ëĒŠ {}개가 똁ęĩŦ렁ėœŧ로 ė‚­ė œë¨", + "assets_deleted_permanently_from_server": "ė„œë˛„ė—ė„œ 항ëĒŠ {}개가 똁ęĩŦ렁ėœŧ로 ė‚­ė œë¨", "assets_moved_to_trash_count": "íœ´ė§€í†ĩėœŧ로 항ëĒŠ {count, plural, one {#氜} other {#氜}} ė´ë™ë¨", "assets_permanently_deleted_count": "항ëĒŠ {count, plural, one {#氜} other {#氜}}가 똁ęĩŦ렁ėœŧ로 ė‚­ė œë¨", "assets_removed_count": "항ëĒŠ {count, plural, one {#氜} other {#氜}}ëĨŧ ė œęą°í–ˆėŠĩ니다.", @@ -486,30 +490,30 @@ "assets_restore_confirmation": "íœ´ė§€í†ĩėœŧ로 ė´ë™ëœ 항ëĒŠė„ ëĒ¨ë‘ ëŗĩė›í•˜ė‹œę˛ ėŠĩ니까? ė´ ėž‘ė—…ė€ 되돌ëĻ´ 눘 ė—†ėŠĩ니다! 누ëŊ된 항ëĒŠė˜ ę˛Ŋ뚰 ëŗĩė›ë˜ė§€ ė•ŠėŠĩ니다.", "assets_restored_count": "항ëĒŠ {count, plural, one {#氜} other {#氜}}ëĨŧ ëŗĩė›í–ˆėŠĩ니다.", "assets_restored_successfully": "항ëĒŠ {}氜ëĨŧ ëŗĩė›í–ˆėŠĩ니다.", - "assets_trashed": "íœ´ė§€í†ĩėœŧ로 항ëĒŠ {}개가 ė´ë™ë˜ė—ˆėŠĩ니다.", + "assets_trashed": "íœ´ė§€í†ĩėœŧ로 항ëĒŠ {}氜 ė´ë™ë¨", "assets_trashed_count": "íœ´ė§€í†ĩėœŧ로 항ëĒŠ {count, plural, one {#氜} other {#氜}} ė´ë™ë¨", - "assets_trashed_from_server": "íœ´ė§€í†ĩėœŧ로 Immich 항ëĒŠ {}개가 ė´ë™ë˜ė—ˆėŠĩ니다.", + "assets_trashed_from_server": "íœ´ė§€í†ĩėœŧ로 ė„œë˛„ė— ėžˆëŠ” 항ëĒŠ {}개가 ė´ë™ë˜ė—ˆėŠĩ니다.", "assets_were_part_of_album_count": "ė•¨ë˛”ė— ė´ë¯¸ ėĄ´ėžŦ하는 {count, plural, one {항ëĒŠ} other {항ëĒŠ}}ėž…ë‹ˆë‹¤.", "authorized_devices": "ė¸ėĻëœ 기기", - "automatic_endpoint_switching_subtitle": "Connect locally over designated Wi-Fi when available and use alternative connections elsewhere", - "automatic_endpoint_switching_title": "Automatic URL switching", + "automatic_endpoint_switching_subtitle": "ė§€ė •ëœ Wi-Fi가 ė‚ŦėšŠ 가ëŠĨ한 ę˛Ŋ뚰 내ëļ€ë§ė„ í†ĩ해 ė—°ę˛°í•˜ęŗ , ęˇ¸ë ‡ė§€ ė•Šėœŧ늴 다ëĨ¸ 뗰枰 ë°Šė‹ė„ ė‚ŦėšŠí•Šë‹ˆë‹¤.", + "automatic_endpoint_switching_title": "ėžë™ URL ė „í™˜", "back": "뒤로", "back_close_deselect": "뒤로, ë‹Ģ기, ė„ íƒ ėˇ¨ė†Œ", - "background_location_permission": "Background location permission", - "background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name", + "background_location_permission": "밹꡸ëŧėš´ë“œ ėœ„ėš˜ ęļŒí•œ", + "background_location_permission_content": "밹꡸ëŧėš´ë“œė—ė„œ ë„¤íŠ¸ė›ŒíŦëĨŧ ė „í™˜í•˜ë ¤ëŠ´, Immich가 Wi-Fi ë„¤íŠ¸ė›ŒíŦ ė´ëĻ„ė„ í™•ė¸í•  눘 ėžˆë„ëĄ 'ė •í™•í•œ ėœ„ėš˜' ęļŒí•œė„ í•­ėƒ í—ˆėšŠí•´ė•ŧ 합니다.", "backup_album_selection_page_albums_device": "ę¸°ę¸°ė˜ ė•¨ë˛” ({})", - "backup_album_selection_page_albums_tap": "한 번 눌ëŸŦ ė„ íƒ, 두 번 눌ëŸŦ ė œė™¸í•˜ė„¸ėš”.", + "backup_album_selection_page_albums_tap": "한 번 탭하면 íŦí•¨ë˜ęŗ , 두 번 탭하면 ė œė™¸ëŠë‹ˆë‹¤.", "backup_album_selection_page_assets_scatter": "각 항ëĒŠė€ ė—ŦëŸŦ ė•¨ë˛”ė— íŦ함될 눘 ėžˆėœŧ늰, ë°ąė—… ė§„í–‰ ė¤‘ė—ë„ ëŒ€ėƒ ė•¨ë˛”ė„ íŦ함하거나 ė œė™¸í•  눘 ėžˆėŠĩ니다.", "backup_album_selection_page_select_albums": "ė•¨ë˛” ė„ íƒ", "backup_album_selection_page_selection_info": "ė„ íƒí•œ ė•¨ë˛”", "backup_album_selection_page_total_assets": "렄랴 항ëĒŠ", "backup_all": "ëĒ¨ë‘", - "backup_background_service_backup_failed_message": "항ëĒŠė„ ë°ąė—…í•˜ė§€ ëĒģ했ėŠĩ니다. ë‹¤ė‹œ ė‹œë„í•˜ëŠ” 뤑...", - "backup_background_service_connection_failed_message": "ė„œë˛„ė— ė—°ę˛°í•˜ė§€ ëĒģ했ėŠĩ니다. ë‹¤ė‹œ ė‹œë„í•˜ëŠ” 뤑...", + "backup_background_service_backup_failed_message": "항ëĒŠė„ ë°ąė—…í•˜ė§€ ëĒģ했ėŠĩ니다. ë‹¤ė‹œ ė‹œë„í•˜ëŠ” 뤑â€Ļ", + "backup_background_service_connection_failed_message": "ė„œë˛„ė— ė—°ę˛°í•˜ė§€ ëĒģ했ėŠĩ니다. ë‹¤ė‹œ ė‹œë„í•˜ëŠ” 뤑â€Ļ", "backup_background_service_current_upload_notification": "{} ė—…ëĄœë“œ 뤑", - "backup_background_service_default_notification": "ë°ąė—…í•  항ëĒŠė„ í™•ė¸í•˜ëŠ” 뤑...", + "backup_background_service_default_notification": "ėƒˆëĄœėš´ 항ëĒŠė„ í™•ė¸í•˜ëŠ” 뤑â€Ļ", "backup_background_service_error_title": "ë°ąė—… 똤ëĨ˜", - "backup_background_service_in_progress_notification": "ė„ íƒí•œ 항ëĒŠė„ ë°ąė—…í•˜ëŠ” 뤑...", + "backup_background_service_in_progress_notification": "항ëĒŠė„ ë°ąė—…í•˜ëŠ” 뤑â€Ļ", "backup_background_service_upload_failure_notification": "{} ė—…ëĄœë“œ ė‹¤íŒ¨", "backup_controller_page_albums": "ë°ąė—…í•  ė•¨ë˛”", "backup_controller_page_background_app_refresh_disabled_content": "밹꡸ëŧėš´ë“œ ë°ąė—…ė„ ė‚ŦėšŠí•˜ë ¤ëŠ´ 네렕 > ėŧ반 > 밹꡸ëŧėš´ë“œ ė•ą ėƒˆëĄœ ęŗ ėš¨ė—ė„œ 밹꡸ëŧėš´ë“œ ė•ą ėƒˆëĄœ ęŗ ėš¨ė„ í™œė„ąí™”í•˜ė„¸ėš”.", @@ -521,30 +525,30 @@ "backup_controller_page_background_battery_info_title": "배터ëĻŦ ėĩœė í™”", "backup_controller_page_background_charging": "ėļŠė „ ė¤‘ė—ë§Œ", "backup_controller_page_background_configure_error": "밹꡸ëŧėš´ë“œ ė„œëš„ėŠ¤ ęĩŦė„ą ė‹¤íŒ¨", - "backup_controller_page_background_delay": "냈 ėŊ˜í…ė¸  ë°ąė—… 간격: {}", - "backup_controller_page_background_description": "밹꡸ëŧėš´ë“œ ė„œëš„ėŠ¤ëĨŧ í™œė„ąí™”í•˜ė—Ŧ ė•ąė„ ė‹¤í–‰í•˜ė§€ ė•Šęŗ  냈 항ëĒŠė„ ėžë™ėœŧ로 ë°ąė—…í•˜ė„¸ėš”.", - "backup_controller_page_background_is_off": "밹꡸ëŧėš´ë“œ ë°ąė—…ė´ ëš„í™œė„ąí™”ë˜ė—ˆėŠĩ니다.", - "backup_controller_page_background_is_on": "밹꡸ëŧėš´ë“œ ë°ąė—…ė´ í™œė„ąí™”ë˜ė—ˆėŠĩ니다.", + "backup_controller_page_background_delay": "냈 ë¯¸ë””ė–´ ë°ąė—… 간격: {}", + "backup_controller_page_background_description": "ė•ąė„ ė—´ė§€ ė•Šė•„ë„ ėƒˆëĄœ ėļ”ę°€ëœ 항ëĒŠė´ ėžë™ėœŧ로 ë°ąė—…ë˜ë„ëĄ 하려면 밹꡸ëŧėš´ë“œ ė„œëš„ėŠ¤ëĨŧ í™œė„ąí™”í•˜ė„¸ėš”.", + "backup_controller_page_background_is_off": "밹꡸ëŧėš´ë“œ ėžë™ ë°ąė—…ė´ ëš„í™œė„ąí™”ë˜ė—ˆėŠĩ니다.", + "backup_controller_page_background_is_on": "밹꡸ëŧėš´ë“œ ėžë™ ë°ąė—…ė´ í™œė„ąí™”ë˜ė—ˆėŠĩ니다.", "backup_controller_page_background_turn_off": "밹꡸ëŧėš´ë“œ ė„œëš„ėŠ¤ ëš„í™œė„ąí™”", "backup_controller_page_background_turn_on": "밹꡸ëŧėš´ë“œ ė„œëš„ėŠ¤ í™œė„ąí™”", "backup_controller_page_background_wifi": "Wi-Fiė—ė„œë§Œ", "backup_controller_page_backup": "ë°ąė—…", - "backup_controller_page_backup_selected": "ė„ íƒë¨:", + "backup_controller_page_backup_selected": "ė„ íƒë¨: ", "backup_controller_page_backup_sub": "ë°ąė—…ëœ ė‚Ŧė§„ 및 ë™ė˜ėƒ", "backup_controller_page_created": "ėƒė„ąėŧ: {}", "backup_controller_page_desc_backup": "íŦ꡸ëŧėš´ë“œ ë°ąė—…ė„ í™œė„ąí™”í•˜ė—Ŧ ė•ąė„ ė‹œėž‘í•  때 냈 항ëĒŠė„ ė„œë˛„ė— ėžë™ėœŧ로 ė—…ëĄœë“œí•˜ė„¸ėš”.", - "backup_controller_page_excluded": "ė œė™¸ë¨:", + "backup_controller_page_excluded": "ė œė™¸ë¨: ", "backup_controller_page_failed": "ė‹¤íŒ¨ ({})", "backup_controller_page_filename": "파ėŧëĒ…: {} [{}]", "backup_controller_page_id": "ID: {}", "backup_controller_page_info": "ë°ąė—… ė •ëŗ´", - "backup_controller_page_none_selected": "ė„ íƒí•œ 항ëĒŠė´ ė—†ėŠĩ니다.", + "backup_controller_page_none_selected": "ė„ íƒëœ 항ëĒŠ ė—†ėŒ", "backup_controller_page_remainder": "ë‚¨ė€ 항ëĒŠ", "backup_controller_page_remainder_sub": "ë°ąė—… 대기 ė¤‘ė¸ ė‚Ŧė§„ 및 ë™ė˜ėƒ", "backup_controller_page_server_storage": "ė €ėžĨ ęŗĩ간", "backup_controller_page_start_backup": "ë°ąė—… ė‹œėž‘", - "backup_controller_page_status_off": "íŦ꡸ëŧėš´ë“œ ë°ąė—…ė´ ëš„í™œė„ąí™”ë˜ė—ˆėŠĩ니다.", - "backup_controller_page_status_on": "íŦ꡸ëŧėš´ë“œ ë°ąė—…ė´ í™œė„ąí™”ë˜ė—ˆėŠĩ니다.", + "backup_controller_page_status_off": "íŦ꡸ëŧėš´ë“œ ėžë™ ë°ąė—…ė´ ëš„í™œė„ąí™”ë˜ė—ˆėŠĩ니다.", + "backup_controller_page_status_on": "íŦ꡸ëŧėš´ë“œ ėžë™ ë°ąė—…ė´ í™œė„ąí™”ë˜ė—ˆėŠĩ니다.", "backup_controller_page_storage_format": "{} ė‚ŦėšŠ 뤑, 렄랴 {}", "backup_controller_page_to_backup": "ë°ąė—…í•  ė•¨ë˛” ëĒŠëĄ", "backup_controller_page_total_sub": "ė„ íƒí•œ ė•¨ë˛”ė˜ ęŗ ėœ í•œ ė‚Ŧė§„ 및 ë™ė˜ėƒ", @@ -558,7 +562,7 @@ "backup_manual_success": "ė„ąęŗĩ", "backup_manual_title": "ė—…ëĄœë“œ ėƒíƒœ", "backup_options_page_title": "ë°ąė—… ė˜ĩė…˜", - "backup_setting_subtitle": "Manage background and foreground upload settings", + "backup_setting_subtitle": "밹꡸ëŧėš´ë“œ 및 íŦ꡸ëŧėš´ë“œ ė—…ëĄœë“œ 네렕 관ëĻŦ", "backward": "뒤로", "birthdate_saved": "ėƒë…„ė›”ėŧė´ ė„ąęŗĩ렁ėœŧ로 ė €ėžĨë˜ė—ˆėŠĩ니다.", "birthdate_set_description": "ėƒë…„ė›”ėŧė€ ė‚Ŧė§„ ė´Ŧ똁 ë‹šė‹œ ė¸ëŦŧė˜ ë‚˜ė´ëĨŧ ęŗ„ė‚°í•˜ëŠ” 데 ė‚ŦėšŠëŠë‹ˆë‹¤.", @@ -593,12 +597,12 @@ "camera_model": "ėš´ëŠ”ëŧ ëĒ¨ë¸", "cancel": "ë‹Ģ기", "cancel_search": "ę˛€ėƒ‰ ë‹Ģ기", - "canceled": "Canceled", + "canceled": "ė¤‘ë‹¨ë¨", "cannot_merge_people": "ė¸ëŦŧė„ ëŗ‘í•Ší•  눘 ė—†ėŠĩ니다.", "cannot_undo_this_action": "ė´ ėž‘ė—…ė€ 되돌ëĻ´ 눘 ė—†ėŠĩ니다!", "cannot_update_the_description": "네ëĒ…ė„ ëŗ€ę˛Ŋ할 눘 ė—†ėŠĩ니다.", "change_date": "ë‚ ė§œ ëŗ€ę˛Ŋ", - "change_display_order": "Change display order", + "change_display_order": "í‘œė‹œ ėˆœė„œ ëŗ€ę˛Ŋ", "change_expiration_time": "ë§ŒëŖŒėŧ ëŗ€ę˛Ŋ", "change_location": "ėœ„ėš˜ ëŗ€ę˛Ŋ", "change_name": "ė´ëĻ„ ëŗ€ę˛Ŋ", @@ -613,9 +617,9 @@ "change_your_password": "비밀번호 ëŗ€ę˛Ŋ", "changed_visibility_successfully": "í‘œė‹œ ė—Ŧëļ€ę°€ ė„ąęŗĩ렁ėœŧ로 ëŗ€ę˛Ŋë˜ė—ˆėŠĩ니다.", "check_all": "ëĒ¨ë‘ í™•ė¸", - "check_corrupt_asset_backup": "Check for corrupt asset backups", - "check_corrupt_asset_backup_button": "Perform check", - "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", + "check_corrupt_asset_backup": "ë°ąė—…ëœ 항ëĒŠė˜ ė†ėƒ ė—Ŧëļ€ í™•ė¸", + "check_corrupt_asset_backup_button": "í™•ė¸ ėˆ˜í–‰", + "check_corrupt_asset_backup_description": "ė´ 검ė‚Ŧ는 ëĒ¨ë“  항ëĒŠė´ ë°ąė—…ëœ 후 Wi-Fi가 ė—°ę˛°ëœ ėƒíƒœė—ė„œë§Œ ė‹¤í–‰í•˜ė„¸ėš”. ė´ ėž‘ė—…ė€ ëLJ ëļ„ ė •ë„ ė†Œėš”ë  눘 ėžˆėŠĩ니다.", "check_logs": "로그 í™•ė¸", "choose_matching_people_to_merge": "ëŗ‘í•Ší•  ė¸ëŦŧ ė„ íƒ", "city": "ë„ė‹œ", @@ -627,10 +631,10 @@ "client_cert_dialog_msg_confirm": "í™•ė¸", "client_cert_enter_password": "비밀번호 ėž…ë Ĩ", "client_cert_import": "ę°€ė ¸ė˜¤ę¸°", - "client_cert_import_success_msg": "클ëŧė´ė–¸íŠ¸ ė¸ėĻė„œëĨŧ 氀렏뙔ėŠĩ니다.", - "client_cert_invalid_msg": "ėœ íš¨í•˜ė§€ ė•Šė€ ė¸ėĻė„œ 또는 íŒ¨ėŠ¤í”„ë ˆė´ėĻˆę°€ ėŧėš˜í•˜ė§€ ė•ŠėŠĩ니다.", - "client_cert_remove_msg": "클ëŧė´ė–¸íŠ¸ ė¸ėĻė„œę°€ ė œęą°ë˜ė—ˆėŠĩ니다.", - "client_cert_subtitle": "ė¸ėĻė„œ ę°€ė ¸ė˜¤ę¸°/ė œęą°ëŠ” ëĄœęˇ¸ė¸ ė „ė—ë§Œ 가ëŠĨ합니다. PKCS12 (.p12, .pfx) í˜•ė‹ė„ ė§€ė›í•Šë‹ˆë‹¤.", + "client_cert_import_success_msg": "클ëŧė´ė–¸íŠ¸ ė¸ėĻė„œ ę°€ė ¸ė˜¤ę¸° ė™„ëŖŒ", + "client_cert_invalid_msg": "ė¸ėĻė„œę°€ ėœ íš¨í•˜ė§€ ė•Šęą°ë‚˜ 비밀번호가 ė˜Ŧ바ëĨ´ė§€ ė•ŠėŒ", + "client_cert_remove_msg": "클ëŧė´ė–¸íŠ¸ ė¸ėĻė„œ ė œęą°ë¨", + "client_cert_subtitle": "PKCS12 (.p12, .pfx) í˜•ė‹ė„ ė§€ė›í•Šë‹ˆë‹¤. ė¸ėĻė„œ ę°€ė ¸ė˜¤ę¸° 및 ė œęą°ëŠ” ëĄœęˇ¸ė¸ ė „ė—ë§Œ 가ëŠĨ합니다.", "client_cert_title": "SSL 클ëŧė´ė–¸íŠ¸ ė¸ėĻė„œ", "clockwise": "ė‹œęŗ„ ë°Ší–Ĩ", "close": "ë‹Ģ기", @@ -644,12 +648,12 @@ "comments_are_disabled": "ëŒ“ę¸€ė´ ëš„í™œė„ąí™”ë˜ė—ˆėŠĩ니다.", "common_create_new_album": "ė•¨ë˛” ėƒė„ą", "common_server_error": "ë„¤íŠ¸ė›ŒíŦ 뗰枰 ėƒíƒœëĨŧ í™•ė¸í•˜ęŗ , ė„œë˛„ė— ė ‘ė†í•  눘 ėžˆëŠ”ė§€, ė•ą/ė„œë˛„ ë˛„ė „ė´ í˜¸í™˜ë˜ëŠ”ė§€ í™•ė¸í•´ėŖŧė„¸ėš”.", - "completed": "Completed", + "completed": "ė™„ëŖŒë¨", "confirm": "í™•ė¸", "confirm_admin_password": "관ëĻŦėž 비밀번호 í™•ė¸", - "confirm_delete_face": "ė—ė…‹ė—ė„œ {name} ė–ŧęĩ´ė„ ė‚­ė œí•˜ė‹œę˛ ėŠĩ니까?", + "confirm_delete_face": "항ëĒŠė—ė„œ {name}ė˜ ė–ŧęĩ´ė„ ė‚­ė œí•˜ė‹œę˛ ėŠĩ니까?", "confirm_delete_shared_link": "ė´ ęŗĩ뜠 링íŦëĨŧ ė‚­ė œí•˜ė‹œę˛ ėŠĩ니까?", - "confirm_keep_this_delete_others": "ė´ ė—ė…‹ė„ ė œė™¸í•œ ėŠ¤íƒė˜ 다ëĨ¸ ëĒ¨ë“  ė—ė…‹ė´ ė‚­ė œëŠë‹ˆë‹¤. ęŗ„ė†í•˜ė‹œę˛ ėŠĩ니까?", + "confirm_keep_this_delete_others": "ė´ 항ëĒŠė„ ė œė™¸í•œ ėŠ¤íƒė˜ ëĒ¨ë“  항ëĒŠė´ ė‚­ė œëŠë‹ˆë‹¤. ęŗ„ė†í•˜ė‹œę˛ ėŠĩ니까?", "confirm_password": "비밀번호 í™•ė¸", "contain": "맞ėļ¤", "context": "ë‚´ėšŠ", @@ -659,8 +663,8 @@ "control_bottom_app_bar_delete_from_immich": "Immichė—ė„œ ė‚­ė œ", "control_bottom_app_bar_delete_from_local": "ę¸°ę¸°ė—ė„œ ė‚­ė œ", "control_bottom_app_bar_edit_location": "ėœ„ėš˜ íŽ¸ė§‘", - "control_bottom_app_bar_edit_time": "ë‚ ė§œ 및 ė‹œę°„ ëŗ€ę˛Ŋ", - "control_bottom_app_bar_share_link": "Share Link", + "control_bottom_app_bar_edit_time": "ë‚ ė§œ ëŗ€ę˛Ŋ", + "control_bottom_app_bar_share_link": "ęŗĩ뜠 링íŦ", "control_bottom_app_bar_share_to": "ęŗĩ뜠 ëŒ€ėƒ", "control_bottom_app_bar_trash_from_immich": "íœ´ė§€í†ĩ", "copied_image_to_clipboard": "ė´ë¯¸ė§€ę°€ 클ëĻŊëŗ´ë“œė— ëŗĩė‚Ŧë˜ė—ˆėŠĩ니다.", @@ -695,7 +699,7 @@ "crop": "ėžëĨ´ę¸°", "curated_object_page_title": "ė‚ŦëŦŧ", "current_device": "현ėžŦ 기기", - "current_server_address": "Current server address", + "current_server_address": "현ėžŦ ė„œë˛„ ėŖŧė†Œ", "custom_locale": "ė‚ŦėšŠėž 맀렕 로ėŧ€ėŧ", "custom_locale_description": "떏떴 및 맀뗭뗐 따ëĨ¸ ë‚ ė§œ 및 ėˆĢėž í˜•ė‹ 맀렕", "daily_title_text_date": "Mė›” dėŧ EEEE", @@ -709,19 +713,19 @@ "date_range": "ë‚ ė§œ ë˛”ėœ„", "day": "ėŧ", "deduplicate_all": "ëĒ¨ë‘ ė‚­ė œ", - "deduplication_criteria_1": "ė´ë¯¸ė§€ íŦ기(ë°”ė´íŠ¸)", - "deduplication_criteria_2": "EXIF ë°ė´í„° 氜눘", + "deduplication_criteria_1": "ė´ë¯¸ė§€ íŦ기 (ë°”ė´íŠ¸)", + "deduplication_criteria_2": "EXIF ė •ëŗ´ 항ëĒŠ 눘", "deduplication_info": "뤑ëŗĩ ė œęą° ė •ëŗ´", - "deduplication_info_description": "ėžė‚°ė„ ėžë™ėœŧ로 미ëĻŦ ė„ íƒí•˜ęŗ  ėŧ洄렁ėœŧ로 뤑ëŗĩė„ ė œęą°í•˜ë ¤ëŠ´ ë‹¤ėŒė„ ė‚´íŽ´ëŗ´ė„¸ėš”:", + "deduplication_info_description": "항ëĒŠė„ ėžë™ėœŧ로 미ëĻŦ ė„ íƒí•˜ęŗ  뤑ëŗĩ 항ëĒŠė„ ėŧ괄 ė œęą°í•˜ë ¤ëŠ´ ë‹¤ėŒė„ í™•ė¸í•˜ė„¸ėš”:", "default_locale": "ę¸°ëŗ¸ 로ėŧ€ėŧ", "default_locale_description": "브ëŧėš°ė € 로ėŧ€ėŧ뗐 따ëĨ¸ ë‚ ė§œ 및 ėˆĢėž í˜•ė‹ 맀렕", "delete": "ė‚­ė œ", "delete_album": "ė•¨ë˛” ė‚­ė œ", "delete_api_key_prompt": "API 키ëĨŧ ė‚­ė œí•˜ė‹œę˛ ėŠĩ니까?", - "delete_dialog_alert": "ė´ 항ëĒŠė´ Immich 및 ę¸°ę¸°ė—ė„œ 똁ęĩŦ렁ėœŧ로 ė‚­ė œëŠë‹ˆë‹¤.", - "delete_dialog_alert_local": "ė´ 항ëĒŠė´ ę¸°ę¸°ė—ė„œ 똁ęĩŦ렁ėœŧ로 ė‚­ė œëŠë‹ˆë‹¤. Immichė—ė„œëŠ” ė‚­ė œë˜ė§€ ė•ŠėŠĩ니다.", - "delete_dialog_alert_local_non_backed_up": "ėŧëļ€ í•­ëĒŠė´ ë°ąė—…ë˜ė§€ ė•Šė•˜ėŠĩ니다. ë°ąė—…ë˜ė§€ ė•Šė€ 항ëĒŠė´ ę¸°ę¸°ė—ė„œ 똁ęĩŦ렁ėœŧ로 ė‚­ė œëŠë‹ˆë‹¤.", - "delete_dialog_alert_remote": "ė´ 항ëĒŠė´ Immichė—ė„œ 똁ęĩŦ렁ėœŧ로 ė‚­ė œëŠë‹ˆë‹¤.", + "delete_dialog_alert": "ė´ 항ëĒŠë“¤ė´ Immich뙀 ę¸°ę¸°ė—ė„œ 똁ęĩŦ렁ėœŧ로 ė‚­ė œëŠë‹ˆë‹¤.", + "delete_dialog_alert_local": "ė´ 항ëĒŠë“¤ė´ ę¸°ę¸°ė—ė„œ 똁ęĩŦ렁ėœŧ로 ė‚­ė œëŠë‹ˆë‹¤. Immich ė„œë˛„ė—ė„œëŠ” ė‚­ė œë˜ė§€ ė•ŠėŠĩ니다.", + "delete_dialog_alert_local_non_backed_up": "ėŧëļ€ í•­ëĒŠė´ Immich뗐 ë°ąė—…ë˜ė§€ ė•Šė•˜ėœŧ늰, ę¸°ę¸°ė—ė„œ 똁ęĩŦ렁ėœŧ로 ė‚­ė œëŠë‹ˆë‹¤.", + "delete_dialog_alert_remote": "ė´ 항ëĒŠë“¤ė´ Immich ė„œë˛„ė—ė„œ 똁ęĩŦ렁ėœŧ로 ė‚­ė œëŠë‹ˆë‹¤.", "delete_dialog_ok_force": "ëŦ´ė‹œí•˜ęŗ  ė‚­ė œ", "delete_dialog_title": "똁ęĩŦ렁ėœŧ로 ė‚­ė œ", "delete_duplicates_confirmation": "ëš„ėŠˇí•œ 항ëĒŠë“¤ė„ 똁ęĩŦ렁ėœŧ로 ė‚­ė œí•˜ė‹œę˛ ėŠĩ니까?", @@ -731,7 +735,7 @@ "delete_link": "링íŦ ė‚­ė œ", "delete_local_dialog_ok_backed_up_only": "ë°ąė—…ëœ 항ëĒŠë§Œ ė‚­ė œ", "delete_local_dialog_ok_force": "ëŦ´ė‹œí•˜ęŗ  ė‚­ė œ", - "delete_others": "다ëĨ¸ ė‚Ŧ람 ė‚­ė œ", + "delete_others": "다ëĨ¸ ė¸ëŦŧ ė‚­ė œ", "delete_shared_link": "ęŗĩ뜠 링íŦ ė‚­ė œ", "delete_shared_link_dialog_title": "ęŗĩ뜠 링íŦ ė‚­ė œ", "delete_tag": "태그 ė‚­ė œ", @@ -741,12 +745,12 @@ "deletes_missing_assets": "ë””ėŠ¤íŦ뗐 ėĄ´ėžŦí•˜ė§€ ė•ŠëŠ” 항ëĒŠ ė œęą°", "description": "네ëĒ…", "description_input_hint_text": "네ëĒ… ėļ”ę°€...", - "description_input_submit_error": "네ëĒ…ė„ ëŗ€ę˛Ŋ하는 뤑 ëŦ¸ė œę°€ ë°œėƒí–ˆėŠĩ니다. ėžė„¸í•œ ë‚´ėšŠė€ 로그ëĨŧ ė°¸ėĄ°í•˜ė„¸ėš”.", + "description_input_submit_error": "네ëĒ… ė—…ë°ė´íŠ¸ 뤑 똤ëĨ˜ę°€ ë°œėƒí–ˆėŠĩ니다. ėžė„¸í•œ ë‚´ėšŠė€ 로그ëĨŧ í™•ė¸í•˜ė„¸ėš”.", "details": "ėƒė„¸ ė •ëŗ´", "direction": "ë°Ší–Ĩ", "disabled": "ëš„í™œė„ąí™”ë¨", "disallow_edits": "ëˇ°ė–´ëĄœ 네렕", - "discord": "ë””ėŠ¤ėŊ”드", + "discord": "Discord", "discover": "íƒėƒ‰", "dismiss_all_errors": "ëĒ¨ë“  똤ëĨ˜ ëŦ´ė‹œ", "dismiss_error": "똤ëĨ˜ ëŦ´ė‹œ", @@ -761,8 +765,8 @@ "download_canceled": "ë‹¤ėš´ëĄœë“œę°€ ėˇ¨ė†Œë˜ė—ˆėŠĩ니다.", "download_complete": "ë‹¤ė€ëĄœë“œę°€ ė™„ëŖŒë˜ė—ˆėŠĩ니다.", "download_enqueue": "ëŒ€ę¸°ė—´ė— ë‹¤ėš´ëĄœë“œ", - "download_error": "ë‹¤ėš´ëĄœë“œ 뤑 ëŦ¸ė œę°€ ë°œėƒí–ˆėŠĩ니다.", - "download_failed": "ë‹¤ėš´ëĄœë“œė— ė‹¤íŒ¨í•˜ė˜€ėŠĩ니다.", + "download_error": "ë‹¤ėš´ëĄœë“œ 똤ëĨ˜", + "download_failed": "ë‹¤ėš´ëĄœë“œ ė‹¤íŒ¨", "download_filename": "파ėŧ: {}", "download_finished": "ë‹¤ėš´ëĄœë“œę°€ ė™„ëŖŒë˜ė—ˆėŠĩ니다.", "download_include_embedded_motion_videos": "내ėžĨ된 ë™ė˜ėƒ", @@ -773,7 +777,7 @@ "download_settings_description": "ë‹¤ėš´ëĄœë“œ 네렕 관ëĻŦ", "download_started": "ë‹¤ėš´ëĄœë“œę°€ ė‹œėž‘ë˜ė—ˆėŠĩ니다.", "download_sucess": "ë‹¤ėš´ëĄœë“œę°€ ė™„ëŖŒë˜ė—ˆėŠĩ니다.", - "download_sucess_android": "ë¯¸ë””ė–´ę°€ DCIM/Immich뗐 ė €ėžĨë˜ė—ˆėŠĩ니다.", + "download_sucess_android": "ë¯¸ë””ė–´ę°€ DCIM/Immich í´ë”ė— ė €ėžĨë˜ė—ˆėŠĩ니다.", "download_waiting_to_retry": "ėžŦė‹œë„ 대기 뤑", "downloading": "ë‹¤ėš´ëĄœë“œ", "downloading_asset_filename": "{filename} ë‹¤ėš´ëĄœë“œ 뤑...", @@ -807,17 +811,17 @@ "editor_crop_tool_h2_aspect_ratios": "ėĸ…횥뚄", "editor_crop_tool_h2_rotation": "íšŒė „", "email": "ė´ëŠ”ėŧ", - "empty_folder": "This folder is empty", + "empty_folder": "폴더가 ëš„ė–´ ėžˆėŒ", "empty_trash": "íœ´ė§€í†ĩ ëš„ėš°ę¸°", "empty_trash_confirmation": "íœ´ė§€í†ĩė„ ëš„ėš°ė‹œę˛ ėŠĩ니까? íœ´ė§€í†ĩ뗐 ėžˆëŠ” ëĒ¨ë“  항ëĒŠė´ Immichė—ė„œ 똁ęĩŦ렁ėœŧ로 ė‚­ė œëŠë‹ˆë‹¤.\nė´ ėž‘ė—…ė€ 되돌ëĻ´ 눘 ė—†ėŠĩ니다!", "enable": "í™œė„ąí™”", "enabled": "í™œė„ąí™”ë¨", "end_date": "ėĸ…ëŖŒėŧ", - "enqueued": "Enqueued", + "enqueued": "ëŒ€ę¸°ė—´ė— ėļ”가됨", "enter_wifi_name": "Enter WiFi name", "error": "똤ëĨ˜", - "error_change_sort_album": "Failed to change album sort order", - "error_delete_face": "ė—ė…‹ė—ė„œ ė–ŧęĩ´ ė‚­ė œ 똤ëĨ˜", + "error_change_sort_album": "ė•¨ë˛” í‘œė‹œ ėˆœė„œ ëŗ€ę˛Ŋ ė‹¤íŒ¨", + "error_delete_face": "ė–ŧęĩ´ ė‚­ė œ 뤑 똤ëĨ˜ę°€ ë°œėƒí–ˆėŠĩ니다.", "error_loading_image": "ė´ë¯¸ė§€ 로드 똤ëĨ˜", "error_saving_image": "똤ëĨ˜: {}", "error_title": "똤ëĨ˜ - ëŦ¸ė œę°€ ë°œėƒí–ˆėŠĩ니다", @@ -846,7 +850,7 @@ "failed_to_create_shared_link": "ęŗĩ뜠 링íŦëĨŧ ėƒė„ąí•˜ė§€ ëĒģ했ėŠĩ니다.", "failed_to_edit_shared_link": "ęŗĩ뜠 링íŦëĨŧ ėˆ˜ė •í•˜ė§€ ëĒģ했ėŠĩ니다.", "failed_to_get_people": "ė¸ëŦŧ 로드 ė‹¤íŒ¨", - "failed_to_keep_this_delete_others": "ė´ ėžė‚°ė„ ėœ ė§€í•˜ęŗ  다ëĨ¸ ėžė‚°ė„ ė‚­ė œí•˜ė§€ ëĒģ했ėŠĩ니다", + "failed_to_keep_this_delete_others": "ė´ 항ëĒŠė„ ėœ ė§€í•˜ęŗ  다ëĨ¸ 항ëĒŠė„ ė‚­ė œí•˜ė§€ ëĒģ했ėŠĩ니다.", "failed_to_load_asset": "항ëĒŠ 로드 ė‹¤íŒ¨", "failed_to_load_assets": "항ëĒŠ 로드 ė‹¤íŒ¨", "failed_to_load_people": "ė¸ëŦŧ 로드 ė‹¤íŒ¨", @@ -953,10 +957,10 @@ "exif_bottom_sheet_location": "ėœ„ėš˜", "exif_bottom_sheet_people": "ė¸ëŦŧ", "exif_bottom_sheet_person_add_person": "ė´ëĻ„ ėļ”ę°€", - "exif_bottom_sheet_person_age": "Age {}", - "exif_bottom_sheet_person_age_months": "Age {} months", - "exif_bottom_sheet_person_age_year_months": "Age 1 year, {} months", - "exif_bottom_sheet_person_age_years": "Age {}", + "exif_bottom_sheet_person_age": "{}넏", + "exif_bottom_sheet_person_age_months": "ėƒí›„ {}ę°œė›”", + "exif_bottom_sheet_person_age_year_months": "ėƒí›„ 1년 {}ę°œė›”", + "exif_bottom_sheet_person_age_years": "{}넏", "exit_slideshow": "ėŠŦëŧė´ë“œ ė‡ŧ ėĸ…ëŖŒ", "expand_all": "ëĒ¨ë‘ 확ėžĨ", "experimental_settings_new_asset_list_subtitle": "ė§„í–‰ 뤑", @@ -973,12 +977,12 @@ "extension": "확ėžĨėž", "external": "뙏ëļ€", "external_libraries": "뙏ëļ€ ëŧė´ë¸ŒëŸŦëĻŦ", - "external_network": "External network", + "external_network": "뙏ëļ€ ë„¤íŠ¸ė›ŒíŦ", "external_network_sheet_info": "When not on the preferred WiFi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "face_unassigned": "ė•Œ 눘 ė—†ėŒ", - "failed": "Failed", - "failed_to_load_assets": "뗐녋 ëĄœë“œė— ė‹¤íŒ¨í–ˆėŠĩ니다", - "failed_to_load_folder": "Failed to load folder", + "failed": "ė‹¤íŒ¨í•¨", + "failed_to_load_assets": "항ëĒŠ 로드 ė‹¤íŒ¨", + "failed_to_load_folder": "폴더 로드 ė‹¤íŒ¨", "favorite": "ėĻę˛¨ė°žę¸°", "favorite_or_unfavorite_photo": "ėĻę˛¨ė°žę¸° ėļ”ę°€/ė œęą°", "favorites": "ėĻę˛¨ė°žę¸°", @@ -992,26 +996,27 @@ "filetype": "파ėŧ í˜•ė‹", "filter": "필터", "filter_people": "ė¸ëŦŧ 필터", + "filter_places": "ėžĨė†Œ 필터링", "find_them_fast": "ė´ëĻ„ėœŧ로 ę˛€ėƒ‰í•˜ė—Ŧ ëš ëĨ´ę˛Œ ė°žę¸°", "fix_incorrect_match": "ėž˜ëĒģ된 ëļ„ëĨ˜ ėˆ˜ė •", - "folder": "Folder", - "folder_not_found": "Folder not found", + "folder": "폴더", + "folder_not_found": "폴더ëĨŧ ė°žė„ 눘 ė—†ėŒ", "folders": "폴더", "folders_feature_description": "파ėŧ ė‹œėŠ¤í…œė˜ ė‚Ŧė§„ 및 ë™ė˜ėƒė„ 폴더 뷰로 íƒėƒ‰", "forward": "ė•žėœŧ로", "general": "ėŧ반", "get_help": "ë„ė›€ ėš”ė˛­", - "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network", + "get_wifiname_error": "Wi-Fi ė´ëĻ„ė„ 氀렏ė˜Ŧ 눘 ė—†ėŠĩ니다. í•„ėš”í•œ ęļŒí•œė´ í—ˆėšŠë˜ė–´ ėžˆęŗ  Wi-Fi ë„¤íŠ¸ė›ŒíŦ뗐 ė—°ę˛°ë˜ė–´ ėžˆëŠ”ė§€ í™•ė¸í•˜ė„¸ėš”.", "getting_started": "ė‹œėž‘í•˜ę¸°", "go_back": "뒤로", "go_to_folder": "폴더로 ė´ë™", "go_to_search": "ę˛€ėƒ‰ėœŧ로 ė´ë™", - "grant_permission": "Grant permission", + "grant_permission": "ęļŒí•œ ëļ€ė—Ŧ", "group_albums_by": "ë‹¤ėŒėœŧ로 ė•¨ë˛” ęˇ¸ëŖší™”...", - "group_country": "ęĩ­ę°€ëŗ„ ęˇ¸ëŖší™”", + "group_country": "ęĩ­ę°€ëŗ„ëĄœ ęˇ¸ëŖší™”", "group_no": "ęˇ¸ëŖší™” ė—†ėŒ", "group_owner": "ė†Œėœ ėžëĄœ ęˇ¸ëŖší™”", - "group_places_by": "ėžĨė†Œ ęˇ¸ëŖší™” 揰뤀...", + "group_places_by": "ë‹¤ėŒėœŧ로 ėžĨė†Œ ęˇ¸ëŖší™”â€Ļ", "group_year": "ė—°ë„ëĄœ ęˇ¸ëŖší™”", "haptic_feedback_switch": "햅틱 í”ŧ드백 í™œė„ąí™”", "haptic_feedback_title": "햅틱 í”ŧ드백", @@ -1020,7 +1025,7 @@ "header_settings_field_validator_msg": "ę°’ė€ ëš„ė›Œë‘˜ 눘 ė—†ėŠĩ니다.", "header_settings_header_name_input": "헤더 ė´ëĻ„", "header_settings_header_value_input": "헤더 값", - "headers_settings_tile_subtitle": "각 ë„¤íŠ¸ė›ŒíŦ ėš”ė˛­ė„ ëŗ´ë‚ŧ 때 ė‚ŦėšŠí•  í”„ëĄė‹œ 헤더ëĨŧ ė •ė˜í•Šë‹ˆë‹¤.", + "headers_settings_tile_subtitle": "ė•ąė´ 각 ë„¤íŠ¸ė›ŒíŦ ėš”ė˛­ė— 함ęģ˜ ė „ė†Ąí•  í”„ëĄė‹œ 헤더ëĨŧ ė •ė˜í•Šë‹ˆë‹¤.", "headers_settings_tile_title": "ė‚ŦėšŠėž ė •ė˜ í”„ëĄė‹œ 헤더", "hi_user": "ė•ˆë…•í•˜ė„¸ėš” {name}님, ({email})", "hide_all_people": "ëĒ¨ë“  ė¸ëŦŧ 눍揰揰", @@ -1040,13 +1045,13 @@ "home_page_delete_remote_err_local": "ė„œë˛„ė—ė„œ ė‚­ė œëœ 항ëĒŠėž…ë‹ˆë‹¤. 건너뜁니다.", "home_page_favorite_err_local": "ę¸°ę¸°ė˜ 항ëĒŠė€ ėĻę˛¨ė°žę¸°ė— ėļ”가할 눘 ė—†ėŠĩ니다. 건너뜁니다.", "home_page_favorite_err_partner": "íŒŒíŠ¸ë„ˆė˜ 항ëĒŠė€ ėĻę˛¨ė°žę¸°ė— ėļ”가할 눘 ė—†ėŠĩ니다. 건너뜁니다.", - "home_page_first_time_notice": "ė•ąė„ ė˛˜ėŒ ė‚ŦėšŠí•˜ëŠ” ę˛Ŋ뚰 íƒ€ėž„ëŧė¸ė— ė•¨ë˛”ė˜ ė‚Ŧė§„ęŗŧ ë™ė˜ėƒė„ ėą„ėš¸ 눘 ėžˆë„ëĄ ë°ąė—…í•  ė•¨ë˛”ė„ ė„ íƒí•˜ė„¸ėš”.", - "home_page_share_err_local": "ę¸°ę¸°ė˜ 항ëĒŠė€ 링íŦ로 ęŗĩėœ í•  눘 ė—†ėŠĩ니다. 건너뜁니다.", + "home_page_first_time_notice": "ė•ąė„ ė˛˜ėŒ ė‚ŦėšŠí•˜ëŠ” ę˛Ŋ뚰, íƒ€ėž„ëŧė¸ė— ė‚Ŧė§„ęŗŧ ë™ė˜ėƒė´ í‘œė‹œë  눘 ėžˆë„ëĄ ë°ąė—… ė•¨ë˛”ė„ ė„ íƒí•´ėŖŧė„¸ėš”.", + "home_page_share_err_local": "ę¸°ę¸°ė—ë§Œ ė €ėžĨ된 항ëĒŠė€ 링íŦ로 ęŗĩėœ í•  눘 뗆떴 건너뜁니다.", "home_page_upload_err_limit": "한 ë˛ˆė— ėĩœëŒ€ 30ę°œė˜ 항ëĒŠë§Œ ė—…ëĄœë“œí•  눘 ėžˆėŠĩ니다.", "host": "í˜¸ėŠ¤íŠ¸", "hour": "ė‹œę°„", "ignore_icloud_photos": "iCloud ė‚Ŧė§„ ė œė™¸", - "ignore_icloud_photos_description": "iCloud뗐 ė €ėžĨ된 ė‚Ŧė§„ė€ Immich ė„œë˛„ė— ė—…ëĄœë“œë˜ė§€ ė•ŠėŠĩ니다.", + "ignore_icloud_photos_description": "iCloud뗐 ė €ėžĨ된 ė‚Ŧė§„ė€ Immich ė„œë˛„ëĄœ ė—…ëĄœë“œë˜ė§€ ė•ŠėŠĩ니다.", "image": "ė´ë¯¸ė§€", "image_alt_text_date": "{date} ė´Ŧė˜í•œ {isVideo, select, true {ë™ė˜ėƒ} other {ė‚Ŧė§„}}", "image_alt_text_date_1_person": "{date} {person1}님ęŗŧ 함ęģ˜í•œ {isVideo, select, true {ë™ė˜ėƒ} other {ė‚Ŧė§„}}", @@ -1080,16 +1085,16 @@ "night_at_midnight": "매ėŧ ë°¤ ėžė •", "night_at_twoam": "매ėŧ 냈ë˛Ŋ 2ė‹œ" }, - "invalid_date": "ėž˜ëĒģ된 ë‚ ė§œėž…ë‹ˆë‹¤.", - "invalid_date_format": "ėž˜ëĒģ된 ë‚ ė§œ í˜•ė‹ėž…ë‹ˆë‹¤.", + "invalid_date": "ėœ íš¨í•˜ė§€ ė•Šė€ ë‚ ė§œ", + "invalid_date_format": "ėœ íš¨í•˜ė§€ ė•Šė€ ë‚ ė§œ í˜•ė‹", "invite_people": "ė‚ŦėšŠėž ė´ˆëŒ€", "invite_to_album": "ė•¨ë˛”ėœŧ로 ė´ˆëŒ€", "items_count": "{count, plural, one {#氜} other {#氜}} 항ëĒŠ", "jobs": "ėž‘ė—…", "keep": "ėœ ė§€", "keep_all": "ëĒ¨ë‘ ėœ ė§€", - "keep_this_delete_others": "ė´ 항ëĒŠė€ ëŗ´ę´€í•˜ęŗ  다ëĨ¸ 항ëĒŠė€ ė‚­ė œ", - "kept_this_deleted_others": "ė´ ėžė‚°ė„ ėœ ė§€í•˜ęŗ  {count, plural, one {# asset} other {# assets}}ė„ ė‚­ė œí–ˆėŠĩ니다", + "keep_this_delete_others": "ė´ 항ëĒŠė€ ėœ ė§€í•˜ęŗ  ë‚˜ë¨¸ė§€ëŠ” ė‚­ė œ", + "kept_this_deleted_others": "ė´ 항ëĒŠė„ ėœ ė§€í•˜ęŗ  {count, plural, one {#ę°œė˜ 항ëĒŠ} other {#ę°œė˜ 항ëĒŠ}}ė„ ė‚­ė œí–ˆėŠĩ니다.", "keyboard_shortcuts": "í‚¤ëŗ´ë“œ 단ėļ•키", "language": "떏떴", "language_setting_description": "ė„ í˜¸í•˜ëŠ” 떏떴 ė„ íƒ", @@ -1118,9 +1123,9 @@ "loading": "로드 뤑", "loading_search_results_failed": "ę˛€ėƒ‰ 결ęŗŧ 로드 ė‹¤íŒ¨", "local_network": "Local network", - "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", - "location_permission": "Location permission", - "location_permission_content": "In order to use the auto-switching feature, Immich needs precise location permission so it can read the current WiFi network's name", + "local_network_sheet_info": "ė§€ė •í•œ Wi-Fi뗐 ė—°ę˛°ëœ ę˛Ŋ뚰 ė•ąė€ 해당 URLė„ í†ĩ해 ė„œë˛„ė— ė—°ę˛°í•Šë‹ˆë‹¤.", + "location_permission": "ėœ„ėš˜ ęļŒí•œ", + "location_permission_content": "ėžë™ ė „í™˜ 기ëŠĨė„ ė‚ŦėšŠí•˜ë ¤ëŠ´ Immich가 현ėžŦ Wi-Fi ë„¤íŠ¸ė›ŒíŦ ė´ëĻ„ė„ í™•ė¸í•˜ę¸° ėœ„í•œ 'ė •í™•í•œ ėœ„ėš˜' ęļŒí•œė´ í•„ėš”í•Šë‹ˆë‹¤.", "location_picker_choose_on_map": "ė§€ë„ė—ė„œ ė„ íƒ", "location_picker_latitude_error": "ėœ íš¨í•œ ėœ„ë„ëĨŧ ėž…ë Ĩí•˜ė„¸ėš”.", "location_picker_latitude_hint": "ė´ęŗŗė— ėœ„ë„ ėž…ë Ĩ", @@ -1140,11 +1145,11 @@ "login_form_err_http": "http:// 또는 https://로 ė‹œėž‘í•´ė•ŧ 합니다.", "login_form_err_invalid_email": "ėœ íš¨í•˜ė§€ ė•Šė€ ė´ëŠ”ėŧ", "login_form_err_invalid_url": "ėž˜ëĒģ된 URLėž…ë‹ˆë‹¤.", - "login_form_err_leading_whitespace": "ëŦ¸ėž ė‹œėž‘ė— ęŗĩë°ąė´ ėžˆėŠĩ니다.", - "login_form_err_trailing_whitespace": "ëŦ¸ėž ëė— ęŗĩë°ąė´ ėžˆėŠĩ니다.", - "login_form_failed_get_oauth_server_config": "OAuth ëĄœęˇ¸ė¸ 뤑 ëŦ¸ė œ ë°œėƒ, ė„œë˛„ URLė„ í™•ė¸í•˜ė„¸ėš”.", + "login_form_err_leading_whitespace": "ė„ í–‰ ęŗĩë°ąė„ í™•ė¸í•˜ė„¸ėš”.", + "login_form_err_trailing_whitespace": "후행 ęŗĩë°ąė„ í™•ė¸í•˜ė„¸ėš”.", + "login_form_failed_get_oauth_server_config": "OAuth ëĄœęˇ¸ė¸ 뤑 똤ëĨ˜ę°€ ë°œėƒí–ˆėŠĩ니다. ė„œë˛„ URLė„ í™•ė¸í•˜ė„¸ėš”.", "login_form_failed_get_oauth_server_disable": "ė´ ė„œë˛„ëŠ” OAuth 기ëŠĨė„ ė§€ė›í•˜ė§€ ė•ŠėŠĩ니다.", - "login_form_failed_login": "ëĄœęˇ¸ė¸ 똤ëĨ˜. ė„œë˛„ URL, ė´ëŠ”ėŧ 및 비밀번호ëĨŧ í™•ė¸í•˜ė„¸ėš”.", + "login_form_failed_login": "ëĄœęˇ¸ė¸ 뤑 똤ëĨ˜ę°€ ë°œėƒí–ˆėŠĩ니다. ė„œë˛„ URL, ė´ëŠ”ėŧ, 비밀번호ëĨŧ í™•ė¸í•˜ė„¸ėš”.", "login_form_handshake_exception": "ė„œë˛„ė™€ í†ĩė‹  뤑 ė¸ėĻė„œ ė˜ˆė™¸ę°€ ë°œėƒí–ˆėŠĩ니다. ėžė˛´ ė„œëĒ…ëœ ė¸ėĻė„œëĨŧ ė‚ŦėšŠ ė¤‘ė´ëŧ늴, ė„¤ė •ė—ė„œ ėžė˛´ ė„œëĒ…ëœ ė¸ėĻė„œ í—ˆėšŠė„ í™œė„ąí™”í•˜ė„¸ėš”.", "login_form_password_hint": "비밀번호", "login_form_save_login": "ëĄœęˇ¸ė¸ ėœ ė§€", @@ -1152,7 +1157,7 @@ "login_form_server_error": "ė„œë˛„ė— ė—°ę˛°í•  눘 ė—†ėŠĩ니다.", "login_has_been_disabled": "ëĄœęˇ¸ė¸ė´ ëš„í™œė„ąí™”ë˜ė—ˆėŠĩ니다.", "login_password_changed_error": "비밀번호ëĨŧ ëŗ€ę˛Ŋ하던 뤑 ëŦ¸ė œę°€ ë°œėƒí–ˆėŠĩ니다.", - "login_password_changed_success": "비밀번호가 ëŗ€ę˛Ŋë˜ė—ˆėŠĩ니다.", + "login_password_changed_success": "비밀번호가 ė„ąęŗĩ렁ėœŧ로 ëŗ€ę˛Ŋë˜ė—ˆėŠĩ니다.", "logout_all_device_confirmation": "ëĒ¨ë“  ę¸°ę¸°ė—ė„œ ëĄœęˇ¸ė•„ė›ƒí•˜ė‹œę˛ ėŠĩ니까?", "logout_this_device_confirmation": "ė´ ę¸°ę¸°ė—ė„œ ëĄœęˇ¸ė•„ė›ƒí•˜ė‹œę˛ ėŠĩ니까?", "longitude": "ę˛Ŋ도", @@ -1172,7 +1177,7 @@ "map": "ė§€ë„", "map_assets_in_bound": "ė‚Ŧė§„ {}氜", "map_assets_in_bounds": "ė‚Ŧė§„ {}氜", - "map_cannot_get_user_location": "ė‚ŦėšŠėžė˜ ėœ„ėš˜ëĨŧ ëļˆëŸŦė˜Ŧ 눘 ė—†ėŠĩ니다.", + "map_cannot_get_user_location": "ė‚ŦėšŠėžė˜ ėœ„ėš˜ëĨŧ 氀렏ė˜Ŧ 눘 ė—†ėŠĩ니다.", "map_location_dialog_yes": "똈", "map_location_picker_page_use_location": "ė´ ėœ„ėš˜ ė‚ŦėšŠ", "map_location_service_disabled_content": "현ėžŦ ėœ„ėš˜ė˜ 항ëĒŠė„ í‘œė‹œí•˜ë ¤ëŠ´ ėœ„ėš˜ ė„œëš„ėŠ¤ëĨŧ í™œė„ąí™”í•´ė•ŧ 합니다. ė§€ę¸ˆ í™œė„ąí™”í•˜ė‹œę˛ ėŠĩ니까?", @@ -1227,8 +1232,8 @@ "my_albums": "내 ė•¨ë˛”", "name": "ė´ëĻ„", "name_or_nickname": "ė´ëĻ„ 또는 ë‹‰ë„¤ėž„", - "networking_settings": "Networking", - "networking_subtitle": "Manage the server endpoint settings", + "networking_settings": "ë„¤íŠ¸ė›Œí‚š", + "networking_subtitle": "ė„œë˛„ ė—”ë“œíŦė¸íŠ¸ 네렕 관ëĻŦ", "never": "ė—†ėŒ", "new_album": "냈 ė•¨ë˛”", "new_api_key": "API 키 ėƒė„ą", @@ -1257,7 +1262,7 @@ "no_results_description": "ë™ė˜ė–´ 또는 더 ėŧë°˜ė ė¸ ë‹¨ė–´ëĨŧ ė‚ŦėšŠí•´ ëŗ´ė„¸ėš”.", "no_shared_albums_message": "ęŗĩ뜠 ė•¨ë˛”ė„ ë§Œë“¤ė–´ ėŖŧëŗ€ ė‚Ŧ람들ęŗŧ ė‚Ŧė§„ 및 ë™ė˜ėƒ ęŗĩ뜠", "not_in_any_album": "ė•¨ë˛”ė— ė—†ėŒ", - "not_selected": "Not selected", + "not_selected": "ė„ íƒë˜ė§€ ė•ŠėŒ", "note_apply_storage_label_to_previously_uploaded assets": "및溠: ė´ė „ė— ė—…ëĄœë“œí•œ 항ëĒŠė—ë„ ėŠ¤í† ëĻŦė§€ ë ˆė´ë¸”ė„ ė ėšŠí•˜ë ¤ëŠ´ ë‹¤ėŒė„ ė‹¤í–‰í•Šë‹ˆë‹¤,", "notes": "및溠", "notification_permission_dialog_content": "ė•ŒëĻŧė„ í™œė„ąí™”í•˜ë ¤ëŠ´ ė„¤ė •ė—ė„œ ė•ŒëĻŧ ęļŒí•œė„ í—ˆėšŠí•˜ė„¸ėš”.", @@ -1282,6 +1287,7 @@ "onboarding_welcome_user": "{user}님, í™˜ė˜í•Šë‹ˆë‹¤", "online": "똍ëŧė¸", "only_favorites": "ėĻę˛¨ė°žę¸°ë§Œ", + "open": "뗴揰", "open_in_map_view": "ė§€ë„ ëŗ´ę¸°ė—ė„œ 뗴揰", "open_in_openstreetmap": "OpenStreetMapė—ė„œ 뗴揰", "open_the_search_filters": "ę˛€ėƒ‰ 필터 뗴揰", @@ -1371,7 +1377,7 @@ "profile_drawer_app_logs": "로그", "profile_drawer_client_out_of_date_major": "ëĒ¨ë°”ėŧ ė•ąė´ ėĩœė‹  ë˛„ė „ė´ ė•„ë‹™ë‹ˆë‹¤. ėĩœė‹  ë˛„ė „ėœŧ로 ė—…ë°ė´íŠ¸í•˜ė„¸ėš”.", "profile_drawer_client_out_of_date_minor": "ëĒ¨ë°”ėŧ ė•ąė´ ėĩœė‹  ë˛„ė „ė´ ė•„ë‹™ë‹ˆë‹¤. ėĩœė‹  ë˛„ė „ėœŧ로 ė—…ë°ė´íŠ¸í•˜ė„¸ėš”.", - "profile_drawer_client_server_up_to_date": "클ëŧė´ė–¸íŠ¸ė™€ ė„œë˛„ę°€ ėĩœė‹ ėž…니다.", + "profile_drawer_client_server_up_to_date": "클ëŧė´ė–¸íŠ¸ė™€ ė„œë˛„ę°€ ėĩœė‹  ėƒíƒœėž…ë‹ˆë‹¤.", "profile_drawer_github": "Github", "profile_drawer_server_out_of_date_major": "ė„œë˛„ ë˛„ė „ė´ ėĩœė‹ ė´ ė•„ë‹™ë‹ˆë‹¤. ėĩœė‹  ë˛„ė „ėœŧ로 ė—…ë°ė´íŠ¸í•˜ė„¸ėš”.", "profile_drawer_server_out_of_date_minor": "ė„œë˛„ ë˛„ė „ė´ ėĩœė‹ ė´ ė•„ë‹™ë‹ˆë‹¤. ėĩœė‹  ë˛„ė „ėœŧ로 ė—…ë°ė´íŠ¸í•˜ė„¸ėš”.", @@ -1426,6 +1432,7 @@ "recent_searches": "ėĩœęˇŧ ę˛€ėƒ‰", "recently_added": "ėĩœęˇŧ ėļ”ę°€", "recently_added_page_title": "ėĩœęˇŧ ėļ”ę°€", + "recently_taken": "ėĩœęˇŧ ė´Ŧė˜ë¨", "refresh": "ėƒˆëĄœęŗ ėš¨", "refresh_encoded_videos": "ë™ė˜ėƒ ėžŦė¸ėŊ”딊", "refresh_faces": "ė–ŧęĩ´ ėƒˆëĄœęŗ ėš¨", @@ -1447,15 +1454,15 @@ "remove_from_favorites": "ėĻę˛¨ė°žę¸°ė—ė„œ ė œęą°", "remove_from_shared_link": "ęŗĩ뜠 링íŦė—ė„œ ė œęą°", "remove_memory": "ėļ”ė–ĩ ė œęą°", - "remove_photo_from_memory": "ė´ ėļ”ė–ĩė—ė„œ ė‚Ŧė§„ ė œęą°", + "remove_photo_from_memory": "ėļ”ė–ĩė—ė„œ ė‚Ŧė§„ ė œęą°", "remove_url": "URL ė œęą°", "remove_user": "ė‚ŦėšŠėž ė‚­ė œ", "removed_api_key": "API 키 ė‚­ė œ: {name}", "removed_from_archive": "ëŗ´ę´€í•¨ė—ė„œ ė œęą°ë˜ė—ˆėŠĩ니다.", "removed_from_favorites": "ėĻę˛¨ė°žę¸°ė—ė„œ ė œęą°ë˜ė—ˆėŠĩ니다.", "removed_from_favorites_count": "ėĻę˛¨ė°žę¸°ė—ė„œ 항ëĒŠ {count, plural, other {#氜}} ė œęą°ë¨", - "removed_memory": "ėļ”ė–ĩ ė œęą°", - "removed_photo_from_memory": "ė´ ėļ”ė–ĩė—ė„œ ė‚Ŧė§„ ė œęą°", + "removed_memory": "ėļ”ė–ĩė´ ė œęą°ë˜ė—ˆėŠĩ니다.", + "removed_photo_from_memory": "ėļ”ė–ĩė—ė„œ ė‚Ŧė§„ė„ ė œęą°í–ˆėŠĩ니다.", "removed_tagged_assets": "항ëĒŠ {count, plural, one {#氜} other {#氜}}ė—ė„œ 태그ëĨŧ ė œęą°í•¨", "rename": "ė´ëĻ„ 바꾸기", "repair": "눘ëĻŦ", @@ -1496,7 +1503,7 @@ "search_albums": "ė•¨ë˛” ę˛€ėƒ‰", "search_by_context": "ë‚´ėšŠ ę˛€ėƒ‰", "search_by_description": "네ëĒ…ėœŧ로 ę˛€ėƒ‰", - "search_by_description_example": "ė‚ŦíŒŒė—ė„œ ėĻę¸°ëŠ” í•˜ė´í‚š", + "search_by_description_example": "ė„¤ė•…ė‚°ė—ė„œ ėĻę¸°ëŠ” í•˜ė´í‚š", "search_by_filename": "파ėŧëĒ… 또는 확ėžĨėžëĄœ ę˛€ėƒ‰", "search_by_filename_example": "ė˜ˆė‹œ: IMG_1234.JPG or PNG", "search_camera_make": "ėš´ëŠ”ëŧ ė œėĄ°ė‚Ŧ ę˛€ėƒ‰...", @@ -1510,7 +1517,7 @@ "search_filter_date_title": "ë‚ ė§œ ë˛”ėœ„ ė„ íƒ", "search_filter_display_option_not_in_album": "ė•¨ë˛”ė— ė—†ėŒ", "search_filter_display_options": "í‘œė‹œ ė˜ĩė…˜", - "search_filter_filename": "Search by file name", + "search_filter_filename": "파ėŧëĒ…ėœŧ로 ę˛€ėƒ‰", "search_filter_location": "ėœ„ėš˜", "search_filter_location_title": "ėœ„ėš˜ ė„ íƒ", "search_filter_media_type": "ë¯¸ë””ė–´ ėĸ…ëĨ˜", @@ -1518,7 +1525,7 @@ "search_filter_people_title": "ė¸ëŦŧ ė„ íƒ", "search_for": "ę˛€ėƒ‰", "search_for_existing_person": "ėĄ´ėžŦ하는 ė¸ëŦŧ ę˛€ėƒ‰", - "search_no_more_result": "No more results", + "search_no_more_result": "ë”ė´ėƒ 결ęŗŧ ė—†ėŒ", "search_no_people": "ė¸ëŦŧė´ ė—†ėŠĩ니다.", "search_no_people_named": "\"{name}\" ė¸ëŦŧė„ ė°žė„ 눘 ė—†ėŒ", "search_no_result": "No results found, try a different search term or combination", @@ -1528,7 +1535,7 @@ "search_page_no_objects": "ė‚ŦėšŠ 가ëŠĨ한 ė‚ŦëŦŧ ė •ëŗ´ ė—†ėŒ", "search_page_no_places": "ė‚ŦėšŠ 가ëŠĨ한 ėœ„ėš˜ ė •ëŗ´ ė—†ėŒ", "search_page_screenshots": "늤íŦëϰ냎", - "search_page_search_photos_videos": "Search for your photos and videos", + "search_page_search_photos_videos": "ė‚Ŧė§„ 및 ë™ė˜ėƒė„ ę˛€ėƒ‰í•˜ė„¸ėš”", "search_page_selfies": "ė…€í”ŧ", "search_page_things": "ė‚ŦëŦŧ", "search_page_view_all_button": "ëĒ¨ë‘ ëŗ´ę¸°", @@ -1540,7 +1547,7 @@ "search_result_page_new_search_hint": "냈 ę˛€ėƒ‰", "search_settings": "네렕 ę˛€ėƒ‰", "search_state": "맀뗭 ę˛€ėƒ‰...", - "search_suggestion_list_smart_search_hint_1": "ėŠ¤ë§ˆíŠ¸ ę˛€ėƒ‰ė´ ę¸°ëŗ¸ė ėœŧ로 í™œė„ąí™”ë˜ė–´ ėžˆėŠĩ니다. ëŠ”íƒ€ë°ė´í„°ëĄœ ę˛€ėƒ‰í•˜ë ¤ëŠ´ ë‹¤ėŒ ęĩŦëŦ¸ė„ ė‚ŦėšŠí•˜ė„¸ėš”.", + "search_suggestion_list_smart_search_hint_1": "ėŠ¤ë§ˆíŠ¸ ę˛€ėƒ‰ė´ ę¸°ëŗ¸ė ėœŧ로 í™œė„ąí™”ë˜ė–´ ėžˆėŠĩ니다. ëŠ”íƒ€ë°ė´í„°ëĄœ ę˛€ėƒ‰í•˜ë ¤ëŠ´ ë‹¤ėŒė„ ė‚ŦėšŠí•˜ė„¸ėš”. ", "search_suggestion_list_smart_search_hint_2": "m:your-search-term", "search_tags": "태그로 ę˛€ėƒ‰...", "search_timezone": "ė‹œę°„ëŒ€ ę˛€ėƒ‰...", @@ -1564,10 +1571,10 @@ "select_trash_all": "ëĒ¨ë‘ ė‚­ė œ", "select_user_for_sharing_page_err_album": "ė•¨ë˛”ė„ ėƒė„ąí•˜ė§€ ëĒģ했ėŠĩ니다.", "selected": "ė„ íƒë¨", - "selected_count": "{count, plural, other {#氜}} 항ëĒŠ ė„ íƒë¨", + "selected_count": "{count, plural, other {#氜}} ė„ íƒë¨", "send_message": "ëŠ”ė‹œė§€ ė „ė†Ą", "send_welcome_email": "í™˜ė˜ ė´ëŠ”ėŧ ė „ė†Ą", - "server_endpoint": "Server Endpoint", + "server_endpoint": "ė„œë˛„ ė—”ë“œíŦė¸íŠ¸", "server_info_box_app_version": "ė•ą ë˛„ė „", "server_info_box_server_url": "ė„œë˛„ URL", "server_offline": "ė˜¤í”„ëŧė¸", @@ -1576,7 +1583,7 @@ "server_version": "ė„œë˛„ ë˛„ė „", "set": "네렕", "set_as_album_cover": "ė•¨ë˛” ėģ¤ë˛„ëĄœ 네렕", - "set_as_featured_photo": "ėļ”ė˛œ ė‚Ŧė§„ėœŧ로 네렕", + "set_as_featured_photo": "대표 ė‚Ŧė§„ėœŧ로 네렕", "set_as_profile_picture": "프로필 ė‚Ŧė§„ėœŧ로 네렕", "set_date_of_birth": "ėƒë…„ė›”ėŧ 네렕", "set_profile_picture": "프로필 ė‚Ŧė§„ėœŧ로 네렕", @@ -1588,7 +1595,7 @@ "setting_image_viewer_preview_title": "미ëĻŦ ëŗ´ę¸° ė´ë¯¸ė§€ ëļˆëŸŦ똤揰", "setting_image_viewer_title": "ė´ë¯¸ė§€", "setting_languages_apply": "ė ėšŠ", - "setting_languages_subtitle": "Change the app's language", + "setting_languages_subtitle": "ė•ą 떏떴 ëŗ€ę˛Ŋ", "setting_languages_title": "떏떴", "setting_notifications_notify_failures_grace_period": "밹꡸ëŧėš´ë“œ ë°ąė—… ė‹¤íŒ¨ ė•ŒëĻŧ: {}", "setting_notifications_notify_hours": "{}ė‹œę°„ 후", @@ -1603,13 +1610,13 @@ "setting_notifications_total_progress_title": "밹꡸ëŧėš´ë“œ ë°ąė—… 렄랴 ė§„í–‰ëĨ  í‘œė‹œ", "setting_video_viewer_looping_title": "반ëŗĩ", "setting_video_viewer_original_video_subtitle": "When streaming a video from the server, play the original even when a transcode is available. May lead to buffering. Videos available locally are played in original quality regardless of this setting.", - "setting_video_viewer_original_video_title": "Force original video", + "setting_video_viewer_original_video_title": "ė›ëŗ¸ ë™ė˜ėƒ ę°•ė œ ė‚ŦėšŠ", "settings": "네렕", "settings_require_restart": "ė„¤ė •ė„ ė ėšŠí•˜ë ¤ëŠ´ ImmichëĨŧ ë‹¤ė‹œ ė‹œėž‘í•˜ė„¸ėš”.", "settings_saved": "ė„¤ė •ė´ ė €ėžĨë˜ė—ˆėŠĩ니다.", "share": "ęŗĩ뜠", "share_add_photos": "ė‚Ŧė§„ ėļ”ę°€", - "share_assets_selected": "{}氜 항ëĒŠ ė„ íƒë¨", + "share_assets_selected": "{}氜 ė„ íƒë¨", "share_dialog_preparing": "ė¤€ëš„ 뤑...", "shared": "ęŗĩėœ ë¨", "shared_album_activities_input_disable": "ëŒ“ę¸€ė´ ëš„í™œė„ąí™”ë˜ė—ˆėŠĩ니다", @@ -1623,7 +1630,7 @@ "shared_by_user": "{user}ë‹˜ė´ ęŗĩėœ í•¨", "shared_by_you": "내가 ęŗĩėœ í•¨", "shared_from_partner": "{partner}ë‹˜ė˜ ė‚Ŧė§„", - "shared_intent_upload_button_progress_text": "{} / {} Uploaded", + "shared_intent_upload_button_progress_text": "{} / {} ė—…ëĄœë“œë¨", "shared_link_app_bar_title": "ęŗĩ뜠 링íŦ", "shared_link_clipboard_copied_massage": "클ëĻŊëŗ´ë“œė— ëŗĩė‚Ŧë˜ė—ˆėŠĩ니다.", "shared_link_clipboard_text": "링íŦ: {}\n비밀번호: {}", @@ -1703,7 +1710,7 @@ "sort_items": "항ëĒŠ 눘", "sort_modified": "ėˆ˜ė •ëœ ë‚ ė§œ", "sort_oldest": "ė˜¤ëž˜ëœ ė‚Ŧė§„", - "sort_people_by_similarity": "뜠ė‚Ŧė„ąė„ 揰뤀ėœŧ로 ė‚Ŧ람 ė •ë Ŧ", + "sort_people_by_similarity": "뜠ė‚Ŧė„ąė„ 揰뤀ėœŧ로 ė¸ëŦŧ ė •ë Ŧ", "sort_recent": "ėĩœęˇŧ ė‚Ŧė§„", "sort_title": "렜ëĒŠ", "source": "ė†ŒėŠ¤", @@ -1740,7 +1747,7 @@ "tag_created": "태그 ėƒė„ąë¨: {tag}", "tag_feature_description": "ė‚Ŧė§„ 및 ë™ė˜ėƒė„ ėŖŧė œëŗ„ ęˇ¸ëŖší™”ëœ 태그로 íƒėƒ‰", "tag_not_found_question": "태그ëĨŧ ė°žė„ 눘 ė—†ë‚˜ėš”? 냈 태그ëĨŧ ėƒė„ąí•˜ė„¸ėš”.", - "tag_people": "ė‚Ŧ람 태그", + "tag_people": "ė¸ëŦŧ 태그", "tag_updated": "태그 ė—…ë°ė´íŠ¸ë¨: {tag}", "tagged_assets": "항ëĒŠ {count, plural, one {#氜} other {#氜}}뗐 태그ëĨŧ ė ėšŠí•¨", "tags": "태그", @@ -1754,12 +1761,12 @@ "theme_setting_colorful_interface_title": "미려한 ė¸í„°íŽ˜ė´ėŠ¤", "theme_setting_image_viewer_quality_subtitle": "ėƒė„¸ ëŗ´ę¸° ė´ë¯¸ė§€ í’ˆė§ˆ ėĄ°ė •", "theme_setting_image_viewer_quality_title": "ė´ë¯¸ė§€ ëŗ´ę¸° í’ˆė§ˆ", - "theme_setting_primary_color_subtitle": "ėŖŧ 기ëŠĨ 및 ę°•ėĄ°ė— ė‚ŦėšŠë˜ëŠ” ėƒ‰ėƒ ė„ íƒ", + "theme_setting_primary_color_subtitle": "ėŖŧėš” 기ëŠĨęŗŧ ę°•ėĄ° ėƒ‰ėƒė— ė ėšŠí•  테마 ėƒ‰ėƒė„ ė„ íƒí•˜ė„¸ėš”.", "theme_setting_primary_color_title": "대표 ėƒ‰ėƒ", "theme_setting_system_primary_color_title": "ė‹œėŠ¤í…œ ėƒ‰ėƒ ė‚ŦėšŠ", "theme_setting_system_theme_switch": "ėžë™ (ė‹œėŠ¤í…œ 네렕)", "theme_setting_theme_subtitle": "ė•ą 테마 ė„ íƒ", - "theme_setting_three_stage_loading_subtitle": "ė´ 기ëŠĨė€ ė•ąė˜ 로드 ė„ąëŠĨė„ í–Ĩėƒė‹œí‚Ŧ 눘 ėžˆė§€ë§Œ 더 ë§Žė€ ë°ė´í„°ëĨŧ ė‚ŦėšŠí•Šë‹ˆë‹¤.", + "theme_setting_three_stage_loading_subtitle": "3ë‹¨ęŗ„ ëĄœë”Šė€ 로드 ė„ąëŠĨė„ í–Ĩėƒė‹œí‚Ŧ 눘 ėžˆėœŧ나, ë„¤íŠ¸ė›ŒíŦ ëļ€í•˜ę°€ íŦ枌 ėĻę°€í•  눘 ėžˆėŠĩ니다.", "theme_setting_three_stage_loading_title": "3ë‹¨ęŗ„ 로드 í™œė„ąí™”", "they_will_be_merged_together": "ė„ íƒí•œ ė¸ëŦŧë“¤ė´ ëŗ‘í•ŠëŠë‹ˆë‹¤.", "third_party_resources": "ė„œë“œ 파티 ëĻŦė†ŒėŠ¤", @@ -1802,7 +1809,7 @@ "unlink_motion_video": "ëĒ¨ė…˜ ëš„ë””ė˜¤ 링íŦ í•´ė œ", "unlink_oauth": "OAuth 뗰枰 í•´ė œ", "unlinked_oauth_account": "OAuth ęŗ„ė • ė—°ę˛°ė´ í•´ė œë˜ė—ˆėŠĩ니다.", - "unmute_memories": "ėļ”ė–ĩ ėŒė†Œęą° í•´ė œ", + "unmute_memories": "ėŒė†Œęą° í•´ė œ", "unnamed_album": "ė´ëĻ„ ė—†ëŠ” ė•¨ë˛”", "unnamed_album_delete_confirmation": "ė„ í…í•œ ė•¨ë˛”ė„ ė‚­ė œí•˜ė‹œę˛ ėŠĩ니까?", "unnamed_share": "ė´ëĻ„ ė—†ëŠ” ęŗĩ뜠", @@ -1826,11 +1833,11 @@ "upload_status_errors": "똤ëĨ˜", "upload_status_uploaded": "ė™„ëŖŒ", "upload_success": "ė—…ëĄœë“œę°€ ė™„ëŖŒë˜ė—ˆėŠĩ니다. ė—…ëĄœë“œëœ 항ëĒŠė„ ëŗ´ë ¤ëŠ´ íŽ˜ė´ė§€ëĨŧ ėƒˆëĄœęŗ ėš¨í•˜ė„¸ėš”.", - "upload_to_immich": "Upload to Immich ({})", - "uploading": "Uploading", + "upload_to_immich": "Immich뗐 ė—…ëĄœë“œ ({})", + "uploading": "ė—…ëĄœë“œ 뤑", "url": "URL", "usage": "ė‚ŦėšŠëŸ‰", - "use_current_connection": "use current connection", + "use_current_connection": "현ėžŦ ë„¤íŠ¸ė›ŒíŦ ė‚ŦėšŠ", "use_custom_date_range": "ëŒ€ė‹  맞ėļ¤ ę¸°ę°„ ė‚ŦėšŠ", "user": "ė‚ŦėšŠėž", "user_id": "ė‚ŦėšŠėž ID", @@ -1845,15 +1852,15 @@ "users": "ė‚ŦėšŠėž", "utilities": "도ęĩŦ", "validate": "검ėĻ", - "validate_endpoint_error": "Please enter a valid URL", + "validate_endpoint_error": "ėœ íš¨í•œ URLė„ ėž…ë Ĩí•˜ė„¸ėš”.", "variables": "ëŗ€ėˆ˜", "version": "ë˛„ė „", "version_announcement_closing": "ë‹šė‹ ė˜ ėšœęĩŦ, Alex가", "version_announcement_message": "ė•ˆë…•í•˜ė„¸ėš”! 냈 ë˛„ė „ė˜ ImmichëĨŧ ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다. ėž˜ëĒģ된 ęĩŦė„ąė„ ë°Šė§€í•˜ęŗ  ImmichëĨŧ ėĩœė‹  ėƒíƒœëĄœ ėœ ė§€í•˜ę¸° ėœ„í•´ ėž ė‹œ ė‹œę°„ė„ ë‚´ė–´ ëĻ´ëĻŦ늤 노트ëĨŧ ėŊė–´ëŗ´ëŠ” ę˛ƒė„ ęļŒėžĨ합니다. 특히 WatchTower ë“ąė˜ ėžë™ ė—…ë°ė´íŠ¸ 기ëŠĨė„ ė‚ŦėšŠí•˜ëŠ” ę˛Ŋ뚰 ė˜ë„í•˜ė§€ ė•Šė€ ë™ėž‘ė„ ë°Šė§€í•˜ę¸° ėœ„í•´ ë”ë”ėšą ęļŒėžĨ됩니다.", "version_announcement_overlay_release_notes": "ëĻ´ëĻŦ늤 노트", "version_announcement_overlay_text_1": "ė•ˆë…•í•˜ė„¸ėš”,", - "version_announcement_overlay_text_2": "냈 ë˛„ė „ė˜ ImmichëĨŧ ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다.", - "version_announcement_overlay_text_3": "WatchTower ë“ąė˜ ėžë™ ė—…ë°ė´íŠ¸ 기ëŠĨė„ ė‚ŦėšŠí•˜ëŠ” ę˛Ŋ뚰 ė˜ë„í•˜ė§€ ė•Šė€ ë™ėž‘ė„ ë°Šė§€í•˜ę¸° ėœ„í•´ docker-compose.yml 및 .env ęĩŦė„ąė´ ėĩœė‹ ė¸ė§€ í™•ė¸í•˜ė„¸ėš”.", + "version_announcement_overlay_text_2": "냈 ë˛„ė „ė˜ ImmichëĨŧ ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다. ", + "version_announcement_overlay_text_3": " WatchTower ë“ąė˜ ėžë™ ė—…ë°ė´íŠ¸ 기ëŠĨė„ ė‚ŦėšŠí•˜ëŠ” ę˛Ŋ뚰 ė˜ë„í•˜ė§€ ė•Šė€ ë™ėž‘ė„ ë°Šė§€í•˜ę¸° ėœ„í•´ docker-compose.yml 및 .env ęĩŦė„ąė´ ėĩœė‹ ė¸ė§€ í™•ė¸í•˜ė„¸ėš”.", "version_announcement_overlay_title": "냈 ė„œë˛„ ë˛„ė „ ė‚ŦėšŠ 가ëŠĨ 🎉", "version_history": "ë˛„ė „ 기록", "version_history_item": "{date} ë˛„ė „ {version} ė„¤ėš˜", @@ -1888,6 +1895,6 @@ "years_ago": "{years, plural, one {#년} other {#년}} ė „", "yes": "네", "you_dont_have_any_shared_links": "ėƒė„ąí•œ ęŗĩ뜠 링íŦ가 ė—†ėŠĩ니다.", - "your_wifi_name": "Your WiFi name", + "your_wifi_name": "Wi-Fi ë„¤íŠ¸ė›ŒíŦ ė´ëĻ„", "zoom_image": "ė´ë¯¸ė§€ 확대" } diff --git a/i18n/lv.json b/i18n/lv.json index fbefc9a521..c9002b559c 100644 --- a/i18n/lv.json +++ b/i18n/lv.json @@ -401,11 +401,11 @@ "backup_controller_page_background_turn_on": "Ieslēgt fona pakalpojumu", "backup_controller_page_background_wifi": "Tikai WiFi tÄĢklā", "backup_controller_page_backup": "DublÄ“ÅĄana", - "backup_controller_page_backup_selected": "AtlasÄĢts:", + "backup_controller_page_backup_selected": "AtlasÄĢts: ", "backup_controller_page_backup_sub": "Dublētie Fotoattēli un videoklipi", "backup_controller_page_created": "Izveidots: {}", "backup_controller_page_desc_backup": "Ieslēdziet priekÅĄplāna dublÄ“ÅĄanu, lai, atverot programmu, serverÄĢ automātiski augÅĄupielādētu jaunus aktÄĢvus.", - "backup_controller_page_excluded": "Izņemot:", + "backup_controller_page_excluded": "Izņemot: ", "backup_controller_page_failed": "Neizdevās ({})", "backup_controller_page_filename": "Faila nosaukums: {} [{}]", "backup_controller_page_id": "ID: {}", diff --git a/i18n/nb_NO.json b/i18n/nb_NO.json index df2fba7517..0995b81cc5 100644 --- a/i18n/nb_NO.json +++ b/i18n/nb_NO.json @@ -39,11 +39,11 @@ "authentication_settings_disable_all": "Er du sikker pÃĨ at du ønsker ÃĨ deaktivere alle innloggingsmetoder? Innlogging vil bli fullstendig deaktivert.", "authentication_settings_reenable": "For ÃĨ aktivere pÃĨ nytt, bruk en Server Command.", "background_task_job": "Bakgrunnsjobber", - "backup_database": "Backupdatabase", - "backup_database_enable_description": "Aktiver databasebackup", - "backup_keep_last_amount": "Antall backuper ÃĨ beholde", - "backup_settings": "Backupinnstillinger", - "backup_settings_description": "HÃĨndter innstillinger for databasebackup", + "backup_database": "Opprett database-dump", + "backup_database_enable_description": "Aktiver database-dump", + "backup_keep_last_amount": "Antall database-dumps ÃĨ beholde", + "backup_settings": "Database-dump instillinger", + "backup_settings_description": "HÃĨndter innstillinger for database-dump. Merk: Disse jobbene overvÃĨkes ikke, og du vil ikke bli varslet ved feil.", "check_all": "Merk Alle", "cleanup": "Opprydding", "cleared_jobs": "Ryddet opp jobber for: {job}", @@ -85,7 +85,7 @@ "image_quality": "Kvalitet", "image_resolution": "Oppløsning", "image_resolution_description": "Høyere oppløsninger kan bevare flere detaljer, men det tar lengre tid ÃĨ kode, har større filstørrelser og kan redusere appresponsen.", - "image_settings": "Bildeinnstilliinger", + "image_settings": "Bildeinnstillinger", "image_settings_description": "Administrer kvalitet og oppløsning pÃĨ genererte bilder", "image_thumbnail_description": "SmÃĨ miniatyrbilder med strippet metadata, brukt nÃĨr du ser pÃĨ grupper av bilder som hovedtidslinjen", "image_thumbnail_quality_description": "Miniatyrbildekvalitet fra 1-100. Høyere er bedre, men produserer større filer og kan redusere appens respons.", @@ -371,6 +371,8 @@ "admin_password": "Administrator Passord", "administration": "Administrasjon", "advanced": "Avansert", + "advanced_settings_enable_alternate_media_filter_subtitle": "Bruk denne innstillingen for ÃĨ filtrere mediefiler under synkronisering basert pÃĨ alternative kriterier. Bruk kun denne innstillingen dersom man opplever problemer med at applikasjonen ikke oppdager alle album.", + "advanced_settings_enable_alternate_media_filter_title": "[EKSPERIMENTELT] Bruk alternativ enhet album synk filter", "advanced_settings_log_level_title": "LoggnivÃĨ: {}", "advanced_settings_prefer_remote_subtitle": "Noen enheter er veldige trege til ÃĨ hente mikrobilder fra enheten. Aktiver denne innstillingen for ÃĨ hente de eksternt istedenfor.", "advanced_settings_prefer_remote_title": "Foretrekk eksterne bilder", @@ -378,6 +380,8 @@ "advanced_settings_proxy_headers_title": "Proxy headere", "advanced_settings_self_signed_ssl_subtitle": "Hopper over SSL sertifikatverifikasjon for server-endepunkt. PÃĨkrevet for selvsignerte sertifikater.", "advanced_settings_self_signed_ssl_title": "Tillat selvsignerte SSL sertifikater", + "advanced_settings_sync_remote_deletions_subtitle": "Automatisk slette eller gjenopprette filer pÃĨ denne enheten hvis den handlingen har blitt gjort pÃĨ nettsiden", + "advanced_settings_sync_remote_deletions_title": "Synk sletting fra nettsiden [EKSPERIMENTELT]", "advanced_settings_tile_subtitle": "Avanserte brukerinnstillinger", "advanced_settings_troubleshooting_subtitle": "Aktiver ekstra funksjoner for feilsøking", "advanced_settings_troubleshooting_title": "Feilsøking", @@ -529,11 +533,11 @@ "backup_controller_page_background_turn_on": "Skru pÃĨ bakgrunnstjenesten", "backup_controller_page_background_wifi": "Kun pÃĨ WiFi", "backup_controller_page_backup": "Sikkerhetskopier", - "backup_controller_page_backup_selected": "Valgte:", + "backup_controller_page_backup_selected": "Valgte: ", "backup_controller_page_backup_sub": "Opplastede bilder og videoer", "backup_controller_page_created": "Opprettet: {}", "backup_controller_page_desc_backup": "SlÃĨ pÃĨ sikkerhetskopiering i forgrunnen for automatisk ÃĨ laste opp nye objekter til serveren nÃĨr du ÃĨpner appen.", - "backup_controller_page_excluded": "Ekskludert:", + "backup_controller_page_excluded": "Ekskludert: ", "backup_controller_page_failed": "Feilet ({})", "backup_controller_page_filename": "Filnavn: {} [{}]", "backup_controller_page_id": "ID: {}", @@ -992,6 +996,7 @@ "filetype": "Filtype", "filter": "Filter", "filter_people": "Filtrer personer", + "filter_places": "Filtrer steder", "find_them_fast": "Finn dem raskt ved søking av navn", "fix_incorrect_match": "Fiks feilaktig match", "folder": "Folder", @@ -1282,6 +1287,7 @@ "onboarding_welcome_user": "Velkommen, {user}", "online": "Tilkoblet", "only_favorites": "Bare favoritter", + "open": "Åpne", "open_in_map_view": "Åpne i kartvisning", "open_in_openstreetmap": "Åpne i OpenStreetMap", "open_the_search_filters": "Åpne søkefiltrene", @@ -1426,6 +1432,8 @@ "recent_searches": "Nylige søk", "recently_added": "Nylig lagt til", "recently_added_page_title": "Nylig lagt til", + "recently_taken": "Nylig tatt", + "recently_taken_page_title": "Nylig tatt", "refresh": "Oppdater", "refresh_encoded_videos": "Oppdater kodete videoer", "refresh_faces": "Oppdater ansikter", diff --git a/i18n/nl.json b/i18n/nl.json index 609d2add5c..99fb554d5a 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -371,6 +371,8 @@ "admin_password": "Beheerder wachtwoord", "administration": "Beheer", "advanced": "Geavanceerd", + "advanced_settings_enable_alternate_media_filter_subtitle": "Gebruik deze optie om media te filteren tijdens de synchronisatie op basis van alternatieve criteria. Gebruik dit enkel als de app problemen heeft met het detecteren van albums.", + "advanced_settings_enable_alternate_media_filter_title": "[EXPERIMENTEEL] Gebruik een alternatieve album synchronisatie filter", "advanced_settings_log_level_title": "Log niveau: {}", "advanced_settings_prefer_remote_subtitle": "Sommige apparaten zijn traag met het laden van afbeeldingen die lokaal zijn opgeslagen op het apparaat. Activeer deze instelling om in plaats daarvan externe afbeeldingen te laden.", "advanced_settings_prefer_remote_title": "Externe afbeeldingen laden", @@ -378,6 +380,7 @@ "advanced_settings_proxy_headers_title": "Proxy headers", "advanced_settings_self_signed_ssl_subtitle": "Slaat SSL-certificaatverificatie voor de connectie met de server over. Deze optie is vereist voor zelfondertekende certificaten", "advanced_settings_self_signed_ssl_title": "Zelfondertekende SSL-certificaten toestaan", + "advanced_settings_sync_remote_deletions_title": "Synchroniseer verwijderingen op afstand [EXPERIMENTEEL]", "advanced_settings_tile_subtitle": "Geavanceerde gebruikersinstellingen", "advanced_settings_troubleshooting_subtitle": "Schakel extra functies voor probleemoplossing in ", "advanced_settings_troubleshooting_title": "Probleemoplossing", diff --git a/i18n/nn.json b/i18n/nn.json index 6de0f3401b..5fd9caa232 100644 --- a/i18n/nn.json +++ b/i18n/nn.json @@ -2,8 +2,9 @@ "about": "Om", "account": "Konto", "account_settings": "Kontoinnstillingar", - "acknowledge": "Bekreft", + "acknowledge": "Merk som lese", "action": "Handling", + "action_common_update": "Oppdater", "actions": "Handlingar", "active": "Aktive", "activity": "Aktivitet", @@ -121,7 +122,7 @@ "machine_learning_max_detection_distance_description": "Den største skilnaden mellom to bilete for ÃĨ rekne dei som duplikat, frÃĨ 0.001-0.1. Større verdiar finn fleire duplikat, men kan gje falske treff.", "machine_learning_max_recognition_distance": "Maksimal attkjenningsverdi", "machine_learning_min_detection_score": "Minimum deteksjonsresultat", - "machine_learning_min_detection_score_description": "Minimum tillitspoeng for at eit ansikt skal bli oppdaga, pÃĨ ein skala frÃĨ 0-1. LÃĨgare verdiar vil oppdaga fleire ansikt, men kan føre til falske positive", + "machine_learning_min_detection_score_description": "Minimum tillitspoeng for at eit ansikt skal bli oppdaga, pÃĨ ein skala frÃĨ 0 til 1. LÃĨgare verdiar vil oppdage fleire ansikt, men kan føre til feilaktige treff.", "machine_learning_min_recognized_faces": "Minimum gjenkjende ansikt", "machine_learning_settings": "Innstillingar for maskinlÃĻring", "machine_learning_settings_description": "Administrer maskinlÃĻringsfunksjonar og innstillingar", @@ -200,14 +201,45 @@ "backward": "Bakover", "camera": "Kamera", "cancel": "Avbryt", + "change_password_form_confirm_password": "Stadfest passord", "city": "By", - "clear": "Fjern", + "clear": "Tøm", + "clear_all": "Tøm alt", + "clear_all_recent_searches": "Tøm alle nylige søk", + "clear_message": "Tøm melding", + "clear_value": "Tøm verdi", + "client_cert_dialog_msg_confirm": "OK", + "client_cert_enter_password": "Oppgi passord", + "client_cert_import": "Importer", + "client_cert_import_success_msg": "Klientsertifikat vart importert", + "client_cert_invalid_msg": "Ugyldig sertifikatfil eller feil passord", + "client_cert_remove_msg": "Klientsertifikat er fjerna", + "client_cert_subtitle": "Støttar berre PKCS12-formatet (.p12, .pfx). Import og fjerning av sertifikat er berre tilgjengeleg før innlogging", + "client_cert_title": "SSL-klientsertifikat", "clockwise": "Med klokka", "close": "Lukk", + "collapse": "Gøym", + "collapse_all": "Gøym alle", "color": "Farge", - "confirm": "Bekreft", - "contain": "Inneheld", + "color_theme": "Fargetema", + "comment_deleted": "Kommentar vart sletta", + "comment_options": "Kommentarval", + "comments_and_likes": "Kommentarar og likerklikk", + "comments_are_disabled": "Kommentering er slÃĨtt av", + "common_create_new_album": "Lag nytt album", + "common_server_error": "Kontroller nettverkstilkoplinga di, sørg for at tenaren er tilgjengeleg, og at app- og tenarversjonane er kompatible.", + "completed": "Fullført", + "confirm": "Stadfest", + "confirm_admin_password": "Stadfest administratorpassord", + "confirm_delete_face": "Er du sikker pÃĨ at du vil slette {name} sitt ansikt frÃĨ ressursen?", + "confirm_delete_shared_link": "Er du sikker pÃĨ at du vil slette denne delte lenka?", + "confirm_keep_this_delete_others": "Alle andre ressursar i bunken vil bli sletta, bortsett frÃĨ denne. Er du sikker pÃĨ at du vil halde fram?", + "confirm_password": "Stadfest passord", + "contain": "Tilpass til vindauget", + "context": "Samanheng", "continue": "Hald fram", + "control_bottom_app_bar_album_info_shared": "{} element ¡ Delt", + "control_bottom_app_bar_create_new_album": "Lag nytt album", "country": "Land", "cover": "Dekk", "covers": "Dekker", @@ -313,21 +345,154 @@ "purchase_server_title": "Server", "reassign": "Vel pÃĨ nytt", "recent": "Nyleg", - "refresh": "Oppdater", + "refresh": "Last inn pÃĨ nytt", + "refresh_encoded_videos": "Oppfrisk ferdigbehandla videoa", + "refresh_faces": "Oppfrisk ansikt", + "refresh_metadata": "Oppfrisk metadata", + "refresh_thumbnails": "Oppfrisk miniatyrbilete", "refreshed": "Oppdatert", + "refreshes_every_file": "Les alle eksisterande og nye filer pÃĨ nytt", + "refreshing_encoded_video": "Lastar inn ferdigbehandla video pÃĨ nytt", + "refreshing_faces": "Oppfriskar ansiktsdata", + "refreshing_metadata": "Oppfriskar metadata", + "regenerating_thumbnails": "Regenererer miniatyrbilete", "remove": "Fjern", - "rename": "Endre namn", - "repair": "Reparasjon", + "remove_assets_album_confirmation": "Er du sikker pÃĨ at du vil fjerne {count, plural, one {# asset} other {# assets}} fra albumet?", + "remove_assets_shared_link_confirmation": "Er du sikker pÃĨ at du vil fjerne {count, plural, one {# asset} other {# assets}} frÃĨ denne delte lenka?", + "remove_assets_title": "Fjern ressursar?", + "remove_custom_date_range": "Fjern egendefinert datoperiode", + "remove_deleted_assets": "Fjern sletta ressursar", + "remove_from_album": "Fjern frÃĨ album", + "remove_from_favorites": "Fjern frÃĨ favorittar", + "remove_from_shared_link": "Fjern frÃĨ delt lenke", + "remove_memory": "Fjern minne", + "remove_photo_from_memory": "Fjern bilete frÃĨ dette minne", + "remove_url": "Fjern URL", + "remove_user": "Fjern brukar", + "removed_api_key": "Fjerna API-nøkkel: {name}", + "removed_from_archive": "Fjerna frÃĨ arkiv", + "removed_from_favorites": "Fjerna frÃĨ favorittar", + "removed_from_favorites_count": "{count, plural, other {Fjerna #}} frÃĨ favorittar", + "removed_memory": "Fjerna minne", + "removed_photo_from_memory": "Fjerna bilete frÃĨ minne", + "removed_tagged_assets": "Fjerna tagg frÃĨ {count, plural, one {# ressurs} other {# ressursar}}", + "rename": "Gi nytt namn", + "repair": "Reparer", + "repair_no_results_message": "Uspora og manglande filer vil visast her", + "replace_with_upload": "Erstatt med opplasting", + "repository": "Lager", + "require_password": "Krev passord", + "require_user_to_change_password_on_first_login": "Krev at brukaren endrar passord ved første innlogging", + "rescan": "Skann pÃĨ nytt", "reset": "Tilbakestill", - "restore": "Tilbakestill", - "resume": "Fortsett", + "reset_password": "Tilbakestill passord", + "reset_people_visibility": "Tilbakestill synlegheit for personar", + "reset_to_default": "Tilbakestill til standard", + "resolve_duplicates": "Handter duplikat", + "resolved_all_duplicates": "Alle duplikat er handterte", + "restore": "Gjenopprett", + "restore_all": "Gjenopprett alle", + "restore_user": "Gjenopprett brukar", + "restored_asset": "Ressurs gjenoppretta", + "resume": "Gjenoppta", + "retry_upload": "Prøv opplasting pÃĨ nytt", + "review_duplicates": "GÃĨ gjennom duplikat", "role": "Rolle", + "role_editor": "Redaktør", + "role_viewer": "Observatør", "save": "Lagre", + "save_to_gallery": "Lagre til galleri", + "saved_api_key": "API-nøkkel lagra", + "saved_profile": "Profil lagra", + "saved_settings": "Innstillingar lagra", + "say_something": "Skriv ein kommentar", + "scaffold_body_error_occurred": "Det oppstod ein feil", + "scan_all_libraries": "Skann gjennom alle bibliotek", "scan_library": "Skann", + "scan_settings": "Skann innstillingar", + "scanning_for_album": "Skanning for album...", "search": "Søk", + "search_albums": "Søk album", + "search_by_context": "Søk etter samanheng", + "search_by_description": "Søk etter beskrivelse", + "search_by_description_example": "Søndagstur med kvikklunsj", + "search_by_filename": "Søk etter filnamn eller filformat", + "search_by_filename_example": "t.d. IMG_1234.JPG eller PNG", + "search_camera_make": "Søk etter kamera produsent...", + "search_camera_model": "Søk etter kamera modell...", + "search_city": "Søk etter by...", + "search_country": "Søk etter land...", + "search_filter_apply": "Bruk filter", + "search_filter_camera_title": "Vel kameratype", + "search_filter_date": "Dato", + "search_filter_date_interval": "{start} til {end}", + "search_filter_date_title": "Vel eit datointervall", + "search_filter_display_option_not_in_album": "Ikkje i album", + "search_filter_display_options": "Visingsval", + "search_filter_filename": "Søk etter filnamn", + "search_filter_location": "Lokasjon", + "search_filter_location_title": "Vel lokasjon", + "search_filter_media_type": "Mediatype", + "search_filter_media_type_title": "Vel mediatype", + "search_filter_people_title": "Vel personar", + "search_for": "Søk etter", + "search_for_existing_person": "Søk etter ein eksisterande person", + "search_no_more_result": "Ingen fleire resultat", + "search_no_people": "Ingen personar", + "search_no_people_named": "Ingen personar ved namn \"{name}\"", + "search_no_result": "Fann ingen resultat – prøv eit anna søkjeord eller ei anna kombinasjon", + "search_options": "Søkjeval", + "search_page_categories": "Kategoriar", + "search_page_motion_photos": "Levande bilete", + "search_page_no_objects": "Ingen objektinformasjon tilgjengeleg", + "search_page_no_places": "Ingen stadinformasjon tilgjengeleg", + "search_page_screenshots": "Skjermbilete", + "search_page_search_photos_videos": "Søk etter bileta og videoane dine", + "search_page_selfies": "Sjølvbilete", + "search_page_things": "Ting", + "search_page_view_all_button": "Vis alle", + "search_page_your_activity": "Din aktivitet", + "search_page_your_map": "Ditt kart", + "search_people": "Søk etter personar", + "search_places": "Søk etter stad", + "search_rating": "Søk etter vurdering â€Ļ", + "search_result_page_new_search_hint": "Nytt søk", + "search_settings": "Søkjeinnstillingar", + "search_state": "Søk etter fylke â€Ļ", + "search_suggestion_list_smart_search_hint_1": "Smart søk er aktivert som standard. For ÃĨ søkje etter metadata, bruk denne syntaksen: ", + "search_suggestion_list_smart_search_hint_2": "m:søkjeord", + "search_tags": "Søk etter taggar â€Ļ", + "search_timezone": "Søk etter tidssone â€Ļ", + "search_type": "Søketype", "search_your_photos": "Søk i dine bilete", + "searching_locales": "Søkjer etter sprÃĨkinnstillingarâ€Ļ", "second": "Sekund", + "see_all_people": "SjÃĨ alle personar", + "select": "Vel", + "select_album_cover": "Vel forsidebilete", + "select_all": "Vel alle", + "select_all_duplicates": "Vel alle duplikatar", + "select_avatar_color": "Vel avatarfarge", + "select_face": "Vel ansikt", + "select_featured_photo": "Vel framheva bilete", + "select_from_computer": "Vel frÃĨ datamaskin", + "select_keep_all": "Vel ÃĨ behald alle", + "select_library_owner": "Vel bibliotekeigar", + "select_new_face": "Vel nytt ansikt", + "select_photos": "Vel bilete", + "select_trash_all": "Vel fjern alle", + "select_user_for_sharing_page_err_album": "Feil ved oppretting av album", "selected": "Valgt", + "selected_count": "{count, plural, other {# valgt}}", + "send_message": "Send melding", + "send_welcome_email": "Send velkomst-e-post", + "server_endpoint": "Tenar-endepunkt", + "server_info_box_app_version": "App Versjon", + "server_info_box_server_url": "Tenar URL", + "server_offline": "Tenar Frakopla", + "server_online": "Tenar i drift", + "server_stats": "Tenarstatistikk", + "server_version": "Tenarversjon", "set": "Sett", "settings": "Innstillingar", "share": "Del", diff --git a/i18n/pl.json b/i18n/pl.json index 1fc130ff56..eb48a69e51 100644 --- a/i18n/pl.json +++ b/i18n/pl.json @@ -478,14 +478,14 @@ "assets_added_to_name_count": "Dodano {count, plural, one {# zasÃŗb} few {# zasoby} many {# zasobÃŗw} other {# zasobÃŗw}} do {hasName, select, true {{name}} other {new album}}", "assets_count": "{count, plural, one {# zasÃŗb} few {# zasoby} many {# zasobÃŗw} other {# zasobÃŗw}}", "assets_deleted_permanently": "{} zasoby trwale usunięto", - "assets_deleted_permanently_from_server": " {} zasoby zostały trwale usunięte z serwera Immich", + "assets_deleted_permanently_from_server": "{} zasoby zostały trwale usunięte z serwera Immich", "assets_moved_to_trash_count": "Przeniesiono {count, plural, one {# zasÃŗb} few {# zasoby} many {# zasobÃŗw} other {# zasobÃŗw}} do kosza", "assets_permanently_deleted_count": "Trwale usunięto {count, plural, one {# zasÃŗb} few {# zasoby} many {# zasobÃŗw} other {# zasobÃŗw}}", "assets_removed_count": "Usunięto {count, plural, one {# zasÃŗb} few {# zasoby} many {# zasobÃŗw} other {# zasobÃŗw}}", - "assets_removed_permanently_from_device": " {} zasoby zostały trwale usunięte z Twojego urządzenia", + "assets_removed_permanently_from_device": "{} zasoby zostały trwale usunięte z Twojego urządzenia", "assets_restore_confirmation": "Na pewno chcesz przywrÃŗcić wszystkie zasoby z kosza? Nie da się tego cofnąć! NaleÅŧy pamiętać, Åŧe w ten sposÃŗb nie moÅŧna przywrÃŗcić zasobÃŗw offline.", "assets_restored_count": "PrzywrÃŗcono {count, plural, one {# zasÃŗb} few {# zasoby} many {# zasobÃŗw} other {# zasobÃŗw}}", - "assets_restored_successfully": " {} zasoby pomyślnie przywrÃŗcono", + "assets_restored_successfully": "{} zasoby pomyślnie przywrÃŗcono", "assets_trashed": "{} zasoby zostały usunięte", "assets_trashed_count": "Wrzucono do kosza {count, plural, one {# zasÃŗb} few {# zasoby} many {# zasobÃŗw} other {# zasobÃŗw}}", "assets_trashed_from_server": "{} zasoby usunięte z serwera Immich", @@ -1609,7 +1609,7 @@ "settings_saved": "Ustawienia zapisane", "share": "Udostępnij", "share_add_photos": "Dodaj zdjęcia", - "share_assets_selected": "{} wybrano ", + "share_assets_selected": "{} wybrano", "share_dialog_preparing": "Przygotowywanie...", "shared": "Udostępnione", "shared_album_activities_input_disable": "Komentarz jest wyłączony", diff --git a/i18n/pt.json b/i18n/pt.json index 3e1bd463ef..05b2ebfdd9 100644 --- a/i18n/pt.json +++ b/i18n/pt.json @@ -39,11 +39,11 @@ "authentication_settings_disable_all": "Tem a certeza que deseja desativar todos os mÊtodos de início de sessÃŖo? O início de sessÃŖo serÃĄ completamente desativado.", "authentication_settings_reenable": "Para reativar, use um Comando de servidor.", "background_task_job": "Tarefas em segundo plano", - "backup_database": "CÃŗpia de Segurança da Base de Dados", - "backup_database_enable_description": "Ativar cÃŗpias de segurança da base de dados", - "backup_keep_last_amount": "Quantidade de cÃŗpias de segurança anteriores a manter", - "backup_settings": "DefiniçÃĩes de CÃŗpia de Segurança", - "backup_settings_description": "Gerir definiçÃĩes de cÃŗpia de segurança da base de dados", + "backup_database": "Criar CÃŗpia da Base de Dados", + "backup_database_enable_description": "Ativar cÃŗpias da base de dados", + "backup_keep_last_amount": "Quantidade de cÃŗpias anteriores a manter", + "backup_settings": "DefiniçÃĩes de CÃŗpia da Base de Dados", + "backup_settings_description": "Gerir definiçÃĩes de cÃŗpia da base de dados. Aviso: Estas tarefas nÃŖo sÃŖo monitorizadas, pelo que nÃŖo serÃĄ notificado(a) em caso de erro.", "check_all": "Selecionar Tudo", "cleanup": "Limpeza", "cleared_jobs": "Eliminadas as tarefas de: {job}", @@ -371,13 +371,17 @@ "admin_password": "Palavra-passe do administrador", "administration": "AdministraÃ§ÃŖo", "advanced": "Avançado", - "advanced_settings_log_level_title": "Nível de log: {}", + "advanced_settings_enable_alternate_media_filter_subtitle": "Utilize esta definiÃ§ÃŖo para filtrar ficheiros durante a sincronizaÃ§ÃŖo baseada em critÊrios alternativos. Utilize apenas se a aplicaÃ§ÃŖo estiver com problemas a detetar todos os ÃĄlbuns.", + "advanced_settings_enable_alternate_media_filter_title": "[EXPERIMENTAL] Utilizar um filtro alternativo de sincronizaÃ§ÃŖo de ÃĄlbuns em dispositivos", + "advanced_settings_log_level_title": "Nível de registo: {}", "advanced_settings_prefer_remote_subtitle": "Alguns dispositivos sÃŖo extremamente lentos para carregar miniaturas da memÃŗria. Ative esta opÃ§ÃŖo para preferir imagens do servidor.", "advanced_settings_prefer_remote_title": "Preferir imagens do servidor", "advanced_settings_proxy_headers_subtitle": "Defina os cabeçalhos do proxy que o Immich deve enviar em todas comunicaçÃĩes com a rede", "advanced_settings_proxy_headers_title": "Cabeçalhos do Proxy", "advanced_settings_self_signed_ssl_subtitle": "NÃŖo validar o certificado SSL com o endereço do servidor. Isto Ê necessÃĄrio para certificados auto-assinados.", "advanced_settings_self_signed_ssl_title": "Permitir certificados SSL auto-assinados", + "advanced_settings_sync_remote_deletions_subtitle": "Automaticamente eliminar ou restaurar um ficheiro neste dispositivo quando essa mesma aÃ§ÃŖo for efetuada na web", + "advanced_settings_sync_remote_deletions_title": "Sincronizar ficheiros eliminados remotamente [EXPERIMENTAL]", "advanced_settings_tile_subtitle": "ConfiguraçÃĩes avançadas do usuÃĄrio", "advanced_settings_troubleshooting_subtitle": "Ativar funcionalidades adicionais para a resoluÃ§ÃŖo de problemas", "advanced_settings_troubleshooting_title": "ResoluÃ§ÃŖo de problemas", @@ -400,9 +404,9 @@ "album_remove_user_confirmation": "Tem a certeza de que quer remover {user}?", "album_share_no_users": "Parece que tem este ÃĄlbum partilhado com todos os utilizadores ou que nÃŖo existem utilizadores com quem o partilhar.", "album_thumbnail_card_item": "1 arquivo", - "album_thumbnail_card_items": "{} arquivos", + "album_thumbnail_card_items": "{} ficheiros", "album_thumbnail_card_shared": " ¡ Compartilhado", - "album_thumbnail_shared_by": "Compartilhado por {}", + "album_thumbnail_shared_by": "Partilhado por {}", "album_updated": "Álbum atualizado", "album_updated_setting_description": "Receber uma notificaÃ§ÃŖo por e-mail quando um ÃĄlbum partilhado tiver novos ficheiros", "album_user_left": "Saíu do {album}", @@ -440,7 +444,7 @@ "archive": "Arquivo", "archive_or_unarchive_photo": "Arquivar ou desarquivar foto", "archive_page_no_archived_assets": "Nenhum arquivo encontrado", - "archive_page_title": "Arquivado ({})", + "archive_page_title": "Arquivo ({})", "archive_size": "Tamanho do arquivo", "archive_size_description": "Configure o tamanho do arquivo para transferÃĒncias (em GiB)", "archived": "Arquivado", @@ -477,18 +481,18 @@ "assets_added_to_album_count": "{count, plural, one {# ficheiro adicionado} other {# ficheiros adicionados}} ao ÃĄlbum", "assets_added_to_name_count": "{count, plural, one {# ficheiro adicionado} other {# ficheiros adicionados}} a {hasName, select, true {{name}} other {novo ÃĄlbum}}", "assets_count": "{count, plural, one {# ficheiro} other {# ficheiros}}", - "assets_deleted_permanently": "{} arquivo(s) excluído permanentemente", - "assets_deleted_permanently_from_server": "{} arquivo(s) excluídos permanentemente do servidor", + "assets_deleted_permanently": "{} ficheiro(s) eliminado(s) permanentemente", + "assets_deleted_permanently_from_server": "{} ficheiro(s) eliminado(s) permanentemente do servidor Immich", "assets_moved_to_trash_count": "{count, plural, one {# ficheiro movido} other {# ficheiros movidos}} para a reciclagem", "assets_permanently_deleted_count": "{count, plural, one {# ficheiro} other {# ficheiros}} eliminados permanentemente", "assets_removed_count": "{count, plural, one {# ficheiro eliminado} other {# ficheiros eliminados}}", - "assets_removed_permanently_from_device": "{} arquivo(s) removidos permanentemente do seu dispositivo", + "assets_removed_permanently_from_device": "{} ficheiro(s) removido(s) permanentemente do seu dispositivo", "assets_restore_confirmation": "Tem a certeza de que quer recuperar todos os ficheiros apagados? NÃŖo Ê possível anular esta aÃ§ÃŖo! Tenha em conta de que quaisquer ficheiros indisponíveis nÃŖo podem ser restaurados desta forma.", "assets_restored_count": "{count, plural, one {# ficheiro restaurado} other {# ficheiros restaurados}}", - "assets_restored_successfully": "{} arquivo(s) restaurados com sucesso", - "assets_trashed": "{} arquivo(s) enviados para a lixeira", + "assets_restored_successfully": "{} ficheiro(s) restaurados com sucesso", + "assets_trashed": "{} ficheiro(s) enviado(s) para a reciclagem", "assets_trashed_count": "{count, plural, one {# ficheiro enviado} other {# ficheiros enviados}} para a reciclagem", - "assets_trashed_from_server": "{} arquivo(s) do servidor foram enviados para a lixeira", + "assets_trashed_from_server": "{} ficheiro(s) do servidor Immich foi/foram enviados para a reciclagem", "assets_were_part_of_album_count": "{count, plural, one {O ficheiro jÃĄ fazia} other {Os ficheiros jÃĄ faziam}} parte do ÃĄlbum", "authorized_devices": "Dispositivos Autorizados", "automatic_endpoint_switching_subtitle": "Conecte-se localmente quando estiver em uma rede uma Wi-Fi específica e use conexÃĩes alternativas em outras redes", @@ -506,11 +510,11 @@ "backup_all": "Tudo", "backup_background_service_backup_failed_message": "Falha ao fazer backup dos arquivos. Tentando novamenteâ€Ļ", "backup_background_service_connection_failed_message": "Falha na conexÃŖo com o servidor. Tentando novamente...", - "backup_background_service_current_upload_notification": "Enviando {}", + "backup_background_service_current_upload_notification": "A enviar {}", "backup_background_service_default_notification": "Verificando novos arquivosâ€Ļ", "backup_background_service_error_title": "Erro de backup", "backup_background_service_in_progress_notification": "Fazendo backup dos arquivosâ€Ļ", - "backup_background_service_upload_failure_notification": "Falha ao carregar {}", + "backup_background_service_upload_failure_notification": "Ocorreu um erro ao enviar {}", "backup_controller_page_albums": "Backup Álbuns", "backup_controller_page_background_app_refresh_disabled_content": "Para utilizar o backup em segundo plano, ative a atualizaÃ§ÃŖo da aplicaÃ§ÃŖo em segundo plano em ConfiguraçÃĩes > Geral > AtualizaÃ§ÃŖo do app em segundo plano ", "backup_controller_page_background_app_refresh_disabled_title": "AtualizaÃ§ÃŖo do app em segundo plano desativada", @@ -521,7 +525,7 @@ "backup_controller_page_background_battery_info_title": "OtimizaçÃĩes de bateria", "backup_controller_page_background_charging": "Apenas enquanto carrega a bateria", "backup_controller_page_background_configure_error": "Falha ao configurar o serviço em segundo plano", - "backup_controller_page_background_delay": "Atrasar o backup de novos arquivos: {}", + "backup_controller_page_background_delay": "Atrasar a cÃŗpia de segurança de novos ficheiros: {}", "backup_controller_page_background_description": "Ative o serviço em segundo plano para fazer backup automÃĄtico de novos arquivos sem precisar abrir o aplicativo", "backup_controller_page_background_is_off": "O backup automÃĄtico em segundo plano estÃĄ desativado", "backup_controller_page_background_is_on": "O backup automÃĄtico em segundo plano estÃĄ ativado", @@ -529,14 +533,14 @@ "backup_controller_page_background_turn_on": "Ativar o serviço em segundo plano", "backup_controller_page_background_wifi": "Apenas no WiFi", "backup_controller_page_backup": "Backup", - "backup_controller_page_backup_selected": "Selecionado:", + "backup_controller_page_backup_selected": "Selecionado: ", "backup_controller_page_backup_sub": "Fotos e vídeos salvos em backup", "backup_controller_page_created": "Criado em: {}", "backup_controller_page_desc_backup": "Ative o backup para enviar automÃĄticamente novos arquivos para o servidor.", - "backup_controller_page_excluded": "Excluídos:", + "backup_controller_page_excluded": "Eliminado: ", "backup_controller_page_failed": "Falhou ({})", - "backup_controller_page_filename": "Nome do arquivo: {} [{}]", - "backup_controller_page_id": "ID:{}", + "backup_controller_page_filename": "Nome do ficheiro: {} [{}]", + "backup_controller_page_id": "ID: {}", "backup_controller_page_info": "InformaçÃĩes do backup", "backup_controller_page_none_selected": "Nenhum selecionado", "backup_controller_page_remainder": "Restante", @@ -545,7 +549,7 @@ "backup_controller_page_start_backup": "Iniciar Backup", "backup_controller_page_status_off": "Backup automÃĄtico desativado", "backup_controller_page_status_on": "Backup automÃĄtico ativado", - "backup_controller_page_storage_format": "{} de {} usados", + "backup_controller_page_storage_format": "{} de {} utilizado", "backup_controller_page_to_backup": "Álbuns para fazer backup", "backup_controller_page_total_sub": "Todas as fotos e vídeos dos ÃĄlbuns selecionados", "backup_controller_page_turn_off": "Desativar backup", @@ -570,21 +574,21 @@ "bulk_keep_duplicates_confirmation": "Tem a certeza de que deseja manter {count, plural, one {# ficheiro duplicado} other {# ficheiros duplicados}}? Isto resolverÃĄ todos os grupos duplicados sem eliminar nada.", "bulk_trash_duplicates_confirmation": "Tem a certeza de que deseja mover para a reciclagem {count, plural, one {# ficheiro duplicado} other {# ficheiros duplicados}}? Isto manterÃĄ o maior ficheiro de cada grupo e irÃĄ mover para a reciclagem todos os outros duplicados.", "buy": "Comprar Immich", - "cache_settings_album_thumbnails": "Miniaturas da pÃĄgina da biblioteca ({} arquivos)", + "cache_settings_album_thumbnails": "Miniaturas da pÃĄgina da biblioteca ({} ficheiros)", "cache_settings_clear_cache_button": "Limpar cache", "cache_settings_clear_cache_button_title": "Limpa o cache do aplicativo. Isso afetarÃĄ significativamente o desempenho do aplicativo atÊ que o cache seja reconstruído.", "cache_settings_duplicated_assets_clear_button": "LIMPAR", "cache_settings_duplicated_assets_subtitle": "Fotos e vídeos que estÃŖo na lista negra da aplicaÃ§ÃŖo", - "cache_settings_duplicated_assets_title": "Arquivos duplicados ({})", - "cache_settings_image_cache_size": "Tamanho do cache de imagem ({} arquivos)", + "cache_settings_duplicated_assets_title": "Ficheiros duplicados ({})", + "cache_settings_image_cache_size": "Tamanho da cache de imagem ({} ficheiros)", "cache_settings_statistics_album": "Miniaturas da biblioteca", - "cache_settings_statistics_assets": "{} arquivos ({})", + "cache_settings_statistics_assets": "{} ficheiros ({})", "cache_settings_statistics_full": "Imagens completas", "cache_settings_statistics_shared": "Miniaturas de ÃĄlbuns compartilhados", "cache_settings_statistics_thumbnail": "Miniaturas", "cache_settings_statistics_title": "Uso de cache", "cache_settings_subtitle": "Controle o comportamento de cache do aplicativo Immich", - "cache_settings_thumbnail_size": "Tamanho do cache de miniaturas ({} arquivos)", + "cache_settings_thumbnail_size": "Tamanho da cache das miniaturas ({} ficheiros)", "cache_settings_tile_subtitle": "Controlar o comportamento do armazenamento local", "cache_settings_tile_title": "Armazenamento local", "cache_settings_title": "ConfiguraçÃĩes de cache", @@ -606,7 +610,7 @@ "change_password": "Alterar a palavra-passe", "change_password_description": "Esta Ê a primeira vez que estÃĄ a entrar no sistema ou um pedido foi feito para alterar a sua palavra-passe. Insira a nova palavra-passe abaixo.", "change_password_form_confirm_password": "Confirme a senha", - "change_password_form_description": "Esta Ê a primeira vez que vocÃĒ estÃĄ acessando o sistema ou foi feita uma solicitaÃ§ÃŖo para alterar sua senha. Por favor, insira a nova senha abaixo.", + "change_password_form_description": "OlÃĄ, {name}\n\nEsta Ê a primeira vez que estÃĄ a aceder ao sistema, ou entÃŖo foi feito um pedido para alterar a palavra-passe. Por favor insira uma nova palavra-passe abaixo.", "change_password_form_new_password": "Nova senha", "change_password_form_password_mismatch": "As senhas nÃŖo estÃŖo iguais", "change_password_form_reenter_new_password": "Confirme a nova senha", @@ -654,7 +658,7 @@ "contain": "Ajustar", "context": "Contexto", "continue": "Continuar", - "control_bottom_app_bar_album_info_shared": "{} arquivos ¡ Compartilhado", + "control_bottom_app_bar_album_info_shared": "{} ficheiros ¡ Partilhado", "control_bottom_app_bar_create_new_album": "Criar novo ÃĄlbum", "control_bottom_app_bar_delete_from_immich": "Excluir do Immich", "control_bottom_app_bar_delete_from_local": "Excluir do dispositivo", @@ -763,7 +767,7 @@ "download_enqueue": "Na fila", "download_error": "Erro ao baixar", "download_failed": "Falha", - "download_filename": "arquivo: {}", + "download_filename": "ficheiro: {}", "download_finished": "Concluído", "download_include_embedded_motion_videos": "Vídeos incorporados", "download_include_embedded_motion_videos_description": "Incluir vídeos incorporados em fotos em movimento como um ficheiro separado", @@ -953,10 +957,10 @@ "exif_bottom_sheet_location": "LOCALIZAÇÃO", "exif_bottom_sheet_people": "PESSOAS", "exif_bottom_sheet_person_add_person": "Adicionar nome", - "exif_bottom_sheet_person_age": "Age {}", - "exif_bottom_sheet_person_age_months": "Age {} months", - "exif_bottom_sheet_person_age_year_months": "Age 1 year, {} months", - "exif_bottom_sheet_person_age_years": "Age {}", + "exif_bottom_sheet_person_age": "Idade {}", + "exif_bottom_sheet_person_age_months": "Idade {} meses", + "exif_bottom_sheet_person_age_year_months": "Idade 1 ano, {} meses", + "exif_bottom_sheet_person_age_years": "Idade {}", "exit_slideshow": "Sair da apresentaÃ§ÃŖo", "expand_all": "Expandir tudo", "experimental_settings_new_asset_list_subtitle": "Trabalho em andamento", @@ -974,7 +978,7 @@ "external": "Externo", "external_libraries": "Bibliotecas externas", "external_network": "Rede externa", - "external_network_sheet_info": "Quando nÃŖo estiver na rede Wi-Fi especificada, o aplicativo irÃĄ se conectar usando a primeira URL abaixo que obtiver sucesso, começando do topo da lista para baixo.", + "external_network_sheet_info": "Quando nÃŖo estiver ligado à rede Wi-Fi especificada, a aplicaÃ§ÃŖo irÃĄ ligar-se utilizando o primeiro URL abaixo que conseguir aceder, a começar do topo da lista para baixo.", "face_unassigned": "Sem atribuiÃ§ÃŖo", "failed": "Falhou", "failed_to_load_assets": "Falha ao carregar ficheiros", @@ -992,6 +996,7 @@ "filetype": "Tipo de ficheiro", "filter": "Filtro", "filter_people": "Filtrar pessoas", + "filter_places": "Filtrar lugares", "find_them_fast": "Encontre-as mais rapidamente pelo nome numa pesquisa", "fix_incorrect_match": "Corrigir correspondÃĒncia incorreta", "folder": "Folder", @@ -1203,7 +1208,7 @@ "memories_start_over": "Ver de novo", "memories_swipe_to_close": "Deslize para cima para fechar", "memories_year_ago": "Um ano atrÃĄs", - "memories_years_ago": "{} anos atrÃĄs", + "memories_years_ago": "HÃĄ {} anos atrÃĄs", "memory": "MemÃŗria", "memory_lane_title": "MemÃŗrias {title}", "menu": "Menu", @@ -1282,6 +1287,7 @@ "onboarding_welcome_user": "Bem-vindo(a), {user}", "online": "Online", "only_favorites": "Apenas favoritos", + "open": "Abrir", "open_in_map_view": "Abrir na visualizaÃ§ÃŖo de mapa", "open_in_openstreetmap": "Abrir no OpenStreetMap", "open_the_search_filters": "Abrir os filtros de pesquisa", @@ -1305,7 +1311,7 @@ "partner_page_partner_add_failed": "Falha ao adicionar parceiro", "partner_page_select_partner": "Selecionar parceiro", "partner_page_shared_to_title": "Compartilhar com", - "partner_page_stop_sharing_content": "{} nÃŖo poderÃĄ mais acessar as suas fotos.", + "partner_page_stop_sharing_content": "{} irÃĄ deixar de ter acesso às suas fotos.", "partner_sharing": "Partilha com Parceiro", "partners": "Parceiros", "password": "Palavra-passe", @@ -1590,7 +1596,7 @@ "setting_languages_apply": "Aplicar", "setting_languages_subtitle": "Alterar o idioma do aplicativo", "setting_languages_title": "Idioma", - "setting_notifications_notify_failures_grace_period": "Notifique falhas de backup em segundo plano: {}", + "setting_notifications_notify_failures_grace_period": "Notificar erros da cÃŗpia de segurança em segundo plano: {}", "setting_notifications_notify_hours": "{} horas", "setting_notifications_notify_immediately": "imediatamente", "setting_notifications_notify_minutes": "{} minutos", @@ -1626,7 +1632,7 @@ "shared_intent_upload_button_progress_text": "Enviados {} de {}", "shared_link_app_bar_title": "Links compartilhados", "shared_link_clipboard_copied_massage": "Copiado para a ÃĄrea de transferÃĒncia", - "shared_link_clipboard_text": "Link: {}\nPassword: {}", + "shared_link_clipboard_text": "Link: {}\nPalavra-passe: {}", "shared_link_create_error": "Erro ao criar o link compartilhado", "shared_link_edit_description_hint": "Digite a descriÃ§ÃŖo do compartilhamento", "shared_link_edit_expire_after_option_day": "1 dia", @@ -1635,7 +1641,7 @@ "shared_link_edit_expire_after_option_hours": "{} horas", "shared_link_edit_expire_after_option_minute": "1 minuto", "shared_link_edit_expire_after_option_minutes": "{} minutos", - "shared_link_edit_expire_after_option_months": "{} MÃĒses", + "shared_link_edit_expire_after_option_months": "{} meses", "shared_link_edit_expire_after_option_year": "{} ano", "shared_link_edit_password_hint": "Digite uma senha para proteger este link", "shared_link_edit_submit_button": "Atualizar link", @@ -1749,7 +1755,7 @@ "theme_selection": "Selecionar tema", "theme_selection_description": "Definir automaticamente o tema como claro ou escuro com base na preferÃĒncia do sistema do seu navegador", "theme_setting_asset_list_storage_indicator_title": "Mostrar indicador de armazenamento na grade de fotos", - "theme_setting_asset_list_tiles_per_row_title": "Quantidade de arquivos por linha ({})", + "theme_setting_asset_list_tiles_per_row_title": "Quantidade de ficheiros por linha ({})", "theme_setting_colorful_interface_subtitle": "Aplica a cor primÃĄria ao fundo", "theme_setting_colorful_interface_title": "Interface colorida", "theme_setting_image_viewer_quality_subtitle": "Ajuste a qualidade do visualizador de imagens detalhadas", @@ -1784,11 +1790,11 @@ "trash_no_results_message": "Fotos e vídeos enviados para a reciclagem aparecem aqui.", "trash_page_delete_all": "Excluir tudo", "trash_page_empty_trash_dialog_content": "Deseja esvaziar a lixera? Estes arquivos serÃŖo apagados de forma permanente do Immich", - "trash_page_info": "Arquivos na lixeira sÃŖo excluídos de forma permanente apÃŗs {} dias", + "trash_page_info": "Ficheiros na reciclagem irÃŖo ser eliminados permanentemente apÃŗs {} dias", "trash_page_no_assets": "Lixeira vazia", "trash_page_restore_all": "Restaurar tudo", "trash_page_select_assets_btn": "Selecionar arquivos", - "trash_page_title": "Lixeira ({})", + "trash_page_title": "Reciclagem ({})", "trashed_items_will_be_permanently_deleted_after": "Os itens da reciclagem sÃŖo eliminados permanentemente apÃŗs {days, plural, one {# dia} other {# dias}}.", "type": "Tipo", "unarchive": "Desarquivar", diff --git a/i18n/pt_BR.json b/i18n/pt_BR.json index 982455a697..3db825d567 100644 --- a/i18n/pt_BR.json +++ b/i18n/pt_BR.json @@ -4,6 +4,7 @@ "account_settings": "ConfiguraçÃĩes da Conta", "acknowledge": "Entendi", "action": "AÃ§ÃŖo", + "action_common_update": "Atualizar", "actions": "AçÃĩes", "active": "Em execuÃ§ÃŖo", "activity": "Atividade", @@ -832,6 +833,7 @@ "filename": "Nome do arquivo", "filetype": "Tipo de arquivo", "filter_people": "Filtrar pessoas", + "filter_places": "Filtrar lugares", "find_them_fast": "Encontre pelo nome em uma pesquisa", "fix_incorrect_match": "Corrigir correspondÃĒncia incorreta", "folders": "Pastas", diff --git a/i18n/ro.json b/i18n/ro.json index 7b4913e348..82bdc6d1dd 100644 --- a/i18n/ro.json +++ b/i18n/ro.json @@ -371,6 +371,8 @@ "admin_password": "Parolă Administrator", "administration": "Administrare", "advanced": "Avansat", + "advanced_settings_enable_alternate_media_filter_subtitle": "Utilizați această opțiune pentru a filtra conținutul media ÃŽn timpul sincronizării pe baza unor criterii alternative. Încercați numai dacă ÃŽntÃĸmpinați probleme cu aplicația la detectarea tuturor albumelor.", + "advanced_settings_enable_alternate_media_filter_title": "[EXPERIMENTAL] Utilizați filtrul alternativ de sincronizare a albumelor de pe dispozitiv", "advanced_settings_log_level_title": "Nivel log: {}", "advanced_settings_prefer_remote_subtitle": "Unele dispozitive ÃŽntÃĸmpină dificultăți ÃŽn ÃŽncărcarea miniaturilor pentru resursele de pe dispozitiv. Activează această setare pentru a ÃŽncărca imaginile de la distanță ÃŽn schimb.", "advanced_settings_prefer_remote_title": "Preferă fotografii la distanță", @@ -378,6 +380,8 @@ "advanced_settings_proxy_headers_title": "Proxy Headers", "advanced_settings_self_signed_ssl_subtitle": "Omite verificare certificate SSL pentru distinația server-ului, necesar pentru certificate auto-semnate.", "advanced_settings_self_signed_ssl_title": "Permite certificate SSL auto-semnate", + "advanced_settings_sync_remote_deletions_subtitle": "Ștergeți sau restaurați automat un element de pe acest dispozitiv atunci cÃĸnd acțiunea este efectuată pe web", + "advanced_settings_sync_remote_deletions_title": "Sincronizează stergerile efectuate la distanță [EXPERIMENTAL]", "advanced_settings_tile_subtitle": "Setări avansate pentru utilizator", "advanced_settings_troubleshooting_subtitle": "Activează funcționalități suplimentare pentru depanare", "advanced_settings_troubleshooting_title": "Depanare", @@ -401,7 +405,7 @@ "album_share_no_users": "Se pare că ai partajat acest album cu toți utilizatorii sau nu ai niciun utilizator cu care să-l partajezi.", "album_thumbnail_card_item": "1 element", "album_thumbnail_card_items": "{} elemente", - "album_thumbnail_card_shared": "Distribuit", + "album_thumbnail_card_shared": " ¡ Distribuit", "album_thumbnail_shared_by": "Distribuit de {}", "album_updated": "Album actualizat", "album_updated_setting_description": "Primiți o notificare prin e-mail cÃĸnd un album partajat are elemente noi", @@ -504,12 +508,12 @@ "backup_album_selection_page_selection_info": "Informații selecție", "backup_album_selection_page_total_assets": "Total resurse unice", "backup_all": "Toate", - "backup_background_service_backup_failed_message": "Eșuare backup resurse. Re-ÃŽncercare...", - "backup_background_service_connection_failed_message": "Conectare la server eșuată. ReÃŽncercare...", + "backup_background_service_backup_failed_message": "Eșuare backup resurse. ReÃŽncercareâ€Ļ", + "backup_background_service_connection_failed_message": "Conectare la server eșuată. ReÃŽncercareâ€Ļ", "backup_background_service_current_upload_notification": "Încărcare {}", - "backup_background_service_default_notification": "Verificare resurse noi...", + "backup_background_service_default_notification": "Verificare resurse noiâ€Ļ", "backup_background_service_error_title": "Eroare backup", - "backup_background_service_in_progress_notification": "Se face backup al resurselor tale...", + "backup_background_service_in_progress_notification": "Se face backup al resurselor taleâ€Ļ", "backup_background_service_upload_failure_notification": "Încărcare eșuată {}", "backup_controller_page_albums": "Backup albume", "backup_controller_page_background_app_refresh_disabled_content": "Activează reÃŽmprospătarea aplicației ÃŽn fundal ÃŽn Setări > General > ReÃŽmprospătare aplicații ÃŽn fundal pentru a folosi copia de siguranță ÃŽn fundal.", @@ -529,11 +533,11 @@ "backup_controller_page_background_turn_on": "Activează serviciul ÃŽn fundal", "backup_controller_page_background_wifi": "Doar conectat la WiFi", "backup_controller_page_backup": "Backup", - "backup_controller_page_backup_selected": "Selectat(e):", + "backup_controller_page_backup_selected": "Selectat(e): ", "backup_controller_page_backup_sub": "S-a făcut backup pentru fotografii și videoclipuri", "backup_controller_page_created": "Creat la: {}", - "backup_controller_page_desc_backup": "Activează backup-ul ÃŽn prim-plan pentru a ÃŽncărca resursele pe server cÃĸnd deschizi aplicația ", - "backup_controller_page_excluded": "Exclus(e):", + "backup_controller_page_desc_backup": "Activează backup-ul ÃŽn prim-plan pentru a ÃŽncărca resursele pe server cÃĸnd deschizi aplicația.", + "backup_controller_page_excluded": "Exclus(e): ", "backup_controller_page_failed": "Eșuate ({})", "backup_controller_page_filename": "Nume fișier: {} [{}]", "backup_controller_page_id": "ID: {}", @@ -721,7 +725,7 @@ "delete_dialog_alert": "Aceste elemente vor fi șterse permanent de pe server-ul Immich și din dispozitivul tău", "delete_dialog_alert_local": "Aceste fișiere vor fi șterse permanent din dispozitiv, dar vor fi disponibile pe server-ul Immich", "delete_dialog_alert_local_non_backed_up": "Pentru unele fișere nu s-a făcut backup ÃŽn Immich și vor fi șterse permanent din dispozitiv", - "delete_dialog_alert_remote": "Aceste fișiere vor fi șterse permanent de pe server-ul Immich.", + "delete_dialog_alert_remote": "Aceste fișiere vor fi șterse permanent de pe server-ul Immich", "delete_dialog_ok_force": "Șterge oricum", "delete_dialog_title": "Șterge permanent", "delete_duplicates_confirmation": "Sunteți sigur că doriți să ștergeți permanent aceste duplicate?", @@ -960,7 +964,7 @@ "exit_slideshow": "Ieșire din Prezentare", "expand_all": "Extindeți-le pe toate", "experimental_settings_new_asset_list_subtitle": "Acțiune ÃŽn desfășurare", - "experimental_settings_new_asset_list_title": "Activează grila experimentală de fotografii.", + "experimental_settings_new_asset_list_title": "Activează grila experimentală de fotografii", "experimental_settings_subtitle": "Folosește pe propria răspundere!", "experimental_settings_title": "Experimental", "expire_after": "Expiră după", @@ -992,6 +996,7 @@ "filetype": "Tipul fișierului", "filter": "Filter", "filter_people": "Filtrați persoanele", + "filter_places": "Filtrează locurile", "find_them_fast": "Găsiți-le rapid prin căutare după nume", "fix_incorrect_match": "Remediați potrivirea incorectă", "folder": "Folder", @@ -1040,7 +1045,7 @@ "home_page_delete_remote_err_local": "Resursele locale sunt ÃŽn selecția pentru ștergere la distanță, omitere", "home_page_favorite_err_local": "Resursele locale nu pot fi adăugate la favorite ÃŽncă, omitere", "home_page_favorite_err_partner": "Momentan nu se pot adăuga fișierele partenerului la favorite, omitere", - "home_page_first_time_notice": "Dacă este prima dată cÃĸnd utilizezi aplicația, te rugăm să te asiguri că alegi unul sau mai multe albume de backup, astfel ÃŽncÃĸt cronologia să poată fi populată cu fotografiile și videoclipurile din aceste albume.", + "home_page_first_time_notice": "Dacă este prima dată cÃĸnd utilizezi aplicația, te rugăm să te asiguri că alegi unul sau mai multe albume de backup, astfel ÃŽncÃĸt cronologia să poată fi populată cu fotografiile și videoclipurile din aceste albume", "home_page_share_err_local": "Nu se pot distribui fișiere locale prin link, omitere", "home_page_upload_err_limit": "Se pot ÃŽncărca maxim 30 de resurse odată, omitere", "host": "Gazdă", @@ -1282,6 +1287,7 @@ "onboarding_welcome_user": "Bun venit, {user}", "online": "Online", "only_favorites": "Doar favorite", + "open": "Deschide", "open_in_map_view": "Deschideți ÃŽn vizualizarea hărții", "open_in_openstreetmap": "Deschideți ÃŽn OpenStreetMap", "open_the_search_filters": "Deschideți filtrele de căutare", @@ -1339,7 +1345,7 @@ "permission_onboarding_get_started": "Începe", "permission_onboarding_go_to_settings": "Mergi la setări", "permission_onboarding_permission_denied": "Permisiune refuzată. Pentru a utiliza Immich, acordă permisiuni pentru fotografii și videoclipuri ÃŽn Setări.", - "permission_onboarding_permission_granted": "Permisiune acordată!", + "permission_onboarding_permission_granted": "Permisiune acordată! Sunteți gata.", "permission_onboarding_permission_limited": "Permisiune limitată. Pentru a permite Immich să facă copii de siguranță și să gestioneze ÃŽntreaga colecție de galerii, acordă permisiuni pentru fotografii și videoclipuri ÃŽn Setări.", "permission_onboarding_request": "Immich necesită permisiunea de a vizualiza fotografiile și videoclipurile tale.", "person": "PersoanĮŽ", @@ -1526,7 +1532,7 @@ "search_page_categories": "Categorii", "search_page_motion_photos": "Fotografii ÃŽn mișcare", "search_page_no_objects": "Nu sunt informații disponibile despre obiecte", - "search_page_no_places": "Nici o informație disponibilă despre locuri ", + "search_page_no_places": "Nici o informație disponibilă despre locuri", "search_page_screenshots": "Capturi de ecran", "search_page_search_photos_videos": "Search for your photos and videos", "search_page_selfies": "Selfie-uri", @@ -1540,7 +1546,7 @@ "search_result_page_new_search_hint": "Căutare nouă", "search_settings": "Setări de căutare", "search_state": "Starea căutării...", - "search_suggestion_list_smart_search_hint_1": "Căutarea inteligentă este activată ÃŽn mod implicit, pentru a căuta metadata, utilizează sintaxa\n", + "search_suggestion_list_smart_search_hint_1": "Căutarea inteligentă este activată ÃŽn mod implicit, pentru a căuta metadata, utilizează sintaxa ", "search_suggestion_list_smart_search_hint_2": "m:termen-de-căutare", "search_tags": "Căutați etichete...", "search_timezone": "Căutați fusul orar...", @@ -1615,7 +1621,7 @@ "shared_album_activities_input_disable": "Cometariile sunt dezactivate", "shared_album_activity_remove_content": "Dorești să ștergi această activitate?", "shared_album_activity_remove_title": "Șterge activitate", - "shared_album_section_people_action_error": "Eroare la părăsirea/ștergerea din album.", + "shared_album_section_people_action_error": "Eroare la părăsirea/ștergerea din album", "shared_album_section_people_action_leave": "Șterge utilizator din album", "shared_album_section_people_action_remove_user": "Șterge utilizator din album", "shared_album_section_people_title": "PERSOANE", @@ -1852,9 +1858,9 @@ "version_announcement_message": "Bună! Este disponibilă o nouă versiune de Immich. Vă rugăm să vă faceți timp să citiți notele de lansare pentru a vă asigura că configurația dvs. este actualizată pentru a preveni orice configurare greșită, mai ales dacă utilizați WatchTower sau orice mecanism care se ocupă de actualizarea automată a instanței dvs. Immich.", "version_announcement_overlay_release_notes": "informații update", "version_announcement_overlay_text_1": "Salut, există un update nou pentru", - "version_announcement_overlay_text_2": "te rugăm verifică", - "version_announcement_overlay_text_3": "și asigură-te că fișierul .env și configurația ta docker-compose sunt actualizate pentru a preveni orice erori de configurație, ÃŽn special dacă folosești WatchTower sau orice mecanism care gestionează actualizarea automată a aplicației server-ului tău.", - "version_announcement_overlay_title": "O nouă versiune pentru server este disponibilă 🎉", + "version_announcement_overlay_text_2": "te rugăm verifică ", + "version_announcement_overlay_text_3": " și asigură-te că fișierul .env și configurația ta docker-compose sunt actualizate pentru a preveni orice erori de configurație, ÃŽn special dacă folosești WatchTower sau orice mecanism care gestionează actualizarea automată a aplicației server-ului tău.", + "version_announcement_overlay_title": "O nouă versiune pentru server este disponibilă 🎉", "version_history": "Istoric Versiuni", "version_history_item": "Instalat {version} pe data de {date}", "video": "Videoclip", diff --git a/i18n/ru.json b/i18n/ru.json index ab883f9aec..a78a9d6701 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -39,11 +39,11 @@ "authentication_settings_disable_all": "Đ’Ņ‹ ŅƒĐ˛ĐĩŅ€ĐĩĐŊŅ‹, Ņ‡Ņ‚Đž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ĐžŅ‚ĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ Đ˛ŅĐĩ ĐŧĐĩŅ‚ĐžĐ´Ņ‹ Đ˛Ņ…ĐžĐ´Đ°? Đ’Ņ…ĐžĐ´ ĐąŅƒĐ´ĐĩŅ‚ ĐŋĐžĐģĐŊĐžŅŅ‚ŅŒŅŽ ĐžŅ‚ĐēĐģŅŽŅ‡ĐĩĐŊ.", "authentication_settings_reenable": "Đ§Ņ‚ĐžĐąŅ‹ ҁĐŊОва вĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ, Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐšŅ‚Đĩ КоĐŧаĐŊĐ´Ņƒ ҁĐĩŅ€Đ˛ĐĩŅ€Đ°.", "background_task_job": "ФОĐŊĐžĐ˛Ņ‹Đĩ ĐˇĐ°Đ´Đ°Ņ‡Đ¸", - "backup_database": "Đ ĐĩСĐĩŅ€Đ˛ĐŊĐžĐĩ ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊиĐĩ ĐąĐ°ĐˇŅ‹ даĐŊĐŊҋ҅", - "backup_database_enable_description": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐĩ ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊиĐĩ ĐąĐ°ĐˇŅ‹ даĐŊĐŊҋ҅", - "backup_keep_last_amount": "КоĐģĐ¸Ņ‡ĐĩŅŅ‚Đ˛Đž Ņ…Ņ€Đ°ĐŊиĐŧҋ҅ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊҋ҅ ĐēĐžĐŋиК", - "backup_settings": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ", - "backup_settings_description": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēаĐŧи Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ ĐąĐ°ĐˇŅ‹ даĐŊĐŊҋ҅", + "backup_database": "ĐĄĐžĐˇĐ´Đ°Ņ‚ŅŒ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊŅƒŅŽ ĐēĐžĐŋĐ¸ŅŽ ĐąĐ°ĐˇŅ‹ даĐŊĐŊҋ҅", + "backup_database_enable_description": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ даĐŧĐŋŅ‹ ĐąĐ°ĐˇŅ‹ даĐŊĐŊҋ҅", + "backup_keep_last_amount": "КоĐģĐ¸Ņ‡ĐĩŅŅ‚Đ˛Đž Ņ…Ņ€Đ°ĐŊиĐŧҋ҅ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊҋ҅ ĐēĐžĐŋиК ĐąĐ°ĐˇŅ‹ даĐŊĐŊҋ҅", + "backup_settings": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ ĐąĐ°ĐˇŅ‹ даĐŊĐŊҋ҅", + "backup_settings_description": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐĩҁĐēĐžĐŗĐž ŅĐžĐˇĐ´Đ°ĐŊĐ¸Ņ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊҋ҅ ĐēĐžĐŋиК ĐąĐ°ĐˇŅ‹ даĐŊĐŊҋ҅. ĐŸŅ€Đ¸ĐŧĐĩŅ‡Đ°ĐŊиĐĩ: Đ˛Ņ‹ĐŋĐžĐģĐŊĐĩĐŊиĐĩ ĐŊĐĩ ĐēĐžĐŊŅ‚Ņ€ĐžĐģĐ¸Ņ€ŅƒĐĩŅ‚ŅŅ, Đ˛Ņ‹ ĐŊĐĩ ĐŋĐžĐģŅƒŅ‡Đ¸Ņ‚Đĩ ŅƒĐ˛ĐĩĐ´ĐžĐŧĐģĐĩĐŊиĐĩ в ҁĐģŅƒŅ‡Đ°Đĩ ŅĐąĐžŅ.", "check_all": "ĐŸŅ€ĐžĐ˛ĐĩŅ€Đ¸Ņ‚ŅŒ Đ˛ŅĐĩ", "cleanup": "ĐžŅ‡Đ¸ŅŅ‚Đēа", "cleared_jobs": "ĐžŅ‡Đ¸Ņ‰ĐĩĐŊŅ‹ ĐˇĐ°Đ´Đ°Ņ‡Đ¸ Đ´ĐģŅ: {job}", @@ -54,9 +54,9 @@ "confirm_reprocess_all_faces": "Đ’Ņ‹ ŅƒĐ˛ĐĩŅ€ĐĩĐŊŅ‹, Ņ‡Ņ‚Đž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ĐŋĐžĐ˛Ņ‚ĐžŅ€ĐŊĐž ĐžĐŋŅ€ĐĩĐ´ĐĩĐģĐ¸Ņ‚ŅŒ Đ˛ŅĐĩ ĐģĐ¸Ņ†Đ°? Đ‘ŅƒĐ´ŅƒŅ‚ Ņ‚Đ°ĐēĐļĐĩ ŅƒĐ´Đ°ĐģĐĩĐŊŅ‹ иĐŧĐĩĐŊа ŅĐž Đ˛ŅĐĩŅ… ĐģĐ¸Ņ†.", "confirm_user_password_reset": "Đ’Ņ‹ ŅƒĐ˛ĐĩŅ€ĐĩĐŊŅ‹, Ņ‡Ņ‚Đž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ŅĐąŅ€ĐžŅĐ¸Ņ‚ŅŒ ĐŋĐ°Ņ€ĐžĐģҌ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ {user}?", "create_job": "ĐĄĐžĐˇĐ´Đ°Ņ‚ŅŒ СадаĐŊиĐĩ", - "cron_expression": "Đ’Ņ‹Ņ€Đ°ĐļĐĩĐŊиĐĩ cron", - "cron_expression_description": "Đ—Đ°Đ´Đ°ĐšŅ‚Đĩ иĐŊŅ‚ĐĩŅ€Đ˛Đ°Đģ ҁĐēаĐŊĐ¸Ņ€ĐžĐ˛Đ°ĐŊиК в Ņ„ĐžŅ€ĐŧĐ°Ņ‚Đĩ cron. ДĐģŅ ĐŋĐžĐģŅƒŅ‡ĐĩĐŊĐ¸Ņ Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊОК иĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Đ¸, ОСĐŊаĐēĐžĐŧŅŒŅ‚ĐĩҁҌ ҁ Crontab Guru", - "cron_expression_presets": "ĐŸŅ€ĐĩĐ´ŅƒŅŅ‚Đ°ĐŊОвĐēи Đ˛Ņ‹Ņ€Đ°ĐļĐĩĐŊиК cron", + "cron_expression": "Đ Đ°ŅĐŋĐ¸ŅĐ°ĐŊиĐĩ (Đ˛Ņ‹Ņ€Đ°ĐļĐĩĐŊиĐĩ ĐŋĐģаĐŊĐ¸Ņ€ĐžĐ˛Ņ‰Đ¸Đēа cron)", + "cron_expression_description": "Đ§Đ°ŅŅ‚ĐžŅ‚Đ° и Đ˛Ņ€ĐĩĐŧŅ Đ˛Ņ‹ĐŋĐžĐģĐŊĐĩĐŊĐ¸Ņ СадаĐŊĐ¸Ņ в Ņ„ĐžŅ€ĐŧĐ°Ņ‚Đĩ ĐŋĐģаĐŊĐ¸Ņ€ĐžĐ˛Ņ‰Đ¸Đēа cron. Đ’ĐžŅĐŋĐžĐģŅŒĐˇŅƒĐšŅ‚ĐĩҁҌ ĐžĐŊĐģаКĐŊ ĐŗĐĩĐŊĐĩŅ€Đ°Ņ‚ĐžŅ€ĐžĐŧ Crontab Guru ĐŋŅ€Đ¸ ĐŊĐĩĐžĐąŅ…ĐžĐ´Đ¸ĐŧĐžŅŅ‚Đ¸.", + "cron_expression_presets": "Đ Đ°ŅĐŋĐ¸ŅĐ°ĐŊиĐĩ (ĐŋŅ€ĐĩĐ´ŅƒŅŅ‚Đ°ĐŊОвĐģĐĩĐŊĐŊŅ‹Đĩ Đ˛Đ°Ņ€Đ¸Đ°ĐŊ҂ҋ)", "disable_login": "ĐžŅ‚ĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ Đ˛Ņ…ĐžĐ´", "duplicate_detection_job_description": "ЗаĐŋ҃ҁĐēаĐĩŅ‚ ĐžĐŋŅ€ĐĩĐ´ĐĩĐģĐĩĐŊиĐĩ ĐŋĐžŅ…ĐžĐļĐ¸Ņ… Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиК ĐŋŅ€Đ¸ ĐŋĐžĐŧĐžŅ‰Đ¸ ĐŧĐ°ŅˆĐ¸ĐŊĐŊĐžĐŗĐž ĐˇŅ€ĐĩĐŊĐ¸Ņ (ĐˇĐ°Đ˛Đ¸ŅĐ¸Ņ‚ ĐžŅ‚ ҃ĐŧĐŊĐžĐŗĐž ĐŋĐžĐ¸ŅĐēа)", "exclusion_pattern_description": "ШайĐģĐžĐŊŅ‹ Đ¸ŅĐēĐģŅŽŅ‡ĐĩĐŊĐ¸Ņ ĐŋОСвОĐģŅŅŽŅ‚ Đ¸ĐŗĐŊĐžŅ€Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ Ņ„Đ°ĐšĐģŅ‹ и ĐŋаĐŋĐēи ĐŋŅ€Đ¸ ҁĐēаĐŊĐ¸Ņ€ĐžĐ˛Đ°ĐŊии Đ˛Đ°ŅˆĐĩĐš йийĐģĐ¸ĐžŅ‚ĐĩĐēи. Đ­Ņ‚Đž ĐŋĐžĐģĐĩСĐŊĐž, ĐĩҁĐģи ҃ Đ˛Đ°Ņ ĐĩŅŅ‚ŅŒ ĐŋаĐŋĐēи, ŅĐžĐ´ĐĩŅ€ĐļĐ°Ņ‰Đ¸Đĩ Ņ„Đ°ĐšĐģŅ‹, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ Đ˛Ņ‹ ĐŊĐĩ Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ иĐŧĐŋĐžŅ€Ņ‚Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ, ĐŊаĐŋŅ€Đ¸ĐŧĐĩŅ€, RAW-Ņ„Đ°ĐšĐģŅ‹.", @@ -371,13 +371,17 @@ "admin_password": "ĐŸĐ°Ņ€ĐžĐģҌ адĐŧиĐŊĐ¸ŅŅ‚Ņ€Đ°Ņ‚ĐžŅ€Đ°", "administration": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ҁĐĩŅ€Đ˛ĐĩŅ€ĐžĐŧ", "advanced": "Đ Đ°ŅŅˆĐ¸Ņ€ĐĩĐŊĐŊŅ‹Đĩ", - "advanced_settings_log_level_title": "ĐŖŅ€ĐžĐ˛ĐĩĐŊҌ ĐģĐžĐŗĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ:", + "advanced_settings_enable_alternate_media_filter_subtitle": "Đ˜ŅĐŋĐžĐģŅŒĐˇŅƒĐšŅ‚Đĩ ŅŅ‚ĐžŅ‚ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ Đ´ĐģŅ Ņ„Đ¸ĐģŅŒŅ‚Ņ€Đ°Ņ†Đ¸Đ¸ ĐŧĐĩĐ´Đ¸Đ°Ņ„Đ°ĐšĐģОв вО Đ˛Ņ€ĐĩĐŧŅ ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Đ¸ ĐŊа ĐžŅĐŊОвĐĩ аĐģŅŒŅ‚ĐĩŅ€ĐŊĐ°Ņ‚Đ¸Đ˛ĐŊҋ҅ ĐēŅ€Đ¸Ņ‚ĐĩŅ€Đ¸Đĩв. ĐŸŅ€ĐžĐąŅƒĐšŅ‚Đĩ Ņ‚ĐžĐģҌĐēĐž в Ņ‚ĐžĐŧ ҁĐģŅƒŅ‡Đ°Đĩ, ĐĩҁĐģи ҃ Đ˛Đ°Ņ ĐĩŅŅ‚ŅŒ ĐŋŅ€ĐžĐąĐģĐĩĐŧŅ‹ ҁ ОйĐŊĐ°Ņ€ŅƒĐļĐĩĐŊиĐĩĐŧ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩĐŧ Đ˛ŅĐĩŅ… аĐģŅŒĐąĐžĐŧОв.", + "advanced_settings_enable_alternate_media_filter_title": "[ЭКСПЕРИМЕНĐĸАЛĐŦНО] Đ˜ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°ĐŊиĐĩ Ņ„Đ¸ĐģŅŒŅ‚Ņ€Đ° ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Đ¸ аĐģŅŒĐąĐžĐŧОв аĐģŅŒŅ‚ĐĩŅ€ĐŊĐ°Ņ‚Đ¸Đ˛ĐŊҋ҅ ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛", + "advanced_settings_log_level_title": "ĐŖŅ€ĐžĐ˛ĐĩĐŊҌ ĐģĐžĐŗĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ: {}", "advanced_settings_prefer_remote_subtitle": "НĐĩĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đ° ĐžŅ‡ĐĩĐŊҌ ĐŧĐĩĐ´ĐģĐĩĐŊĐŊĐž ĐˇĐ°ĐŗŅ€ŅƒĐļĐ°ŅŽŅ‚ ĐģĐžĐēаĐģҌĐŊŅ‹Đĩ Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ. АĐēŅ‚Đ¸Đ˛Đ¸Ņ€ŅƒĐšŅ‚Đĩ ŅŅ‚Ņƒ ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐē҃, Ņ‡Ņ‚ĐžĐąŅ‹ Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ Đ˛ŅĐĩĐŗĐ´Đ° ĐˇĐ°ĐŗŅ€ŅƒĐļаĐģĐ¸ŅŅŒ ҁ ҁĐĩŅ€Đ˛ĐĩŅ€Đ°.", "advanced_settings_prefer_remote_title": "ĐŸŅ€ĐĩĐ´ĐŋĐžŅ‡Đ¸Ņ‚Đ°Ņ‚ŅŒ Ņ„ĐžŅ‚Đž ĐŊа ҁĐĩŅ€Đ˛ĐĩŅ€Đĩ", - "advanced_settings_proxy_headers_subtitle": "ОĐŋŅ€ĐĩĐ´ĐĩĐģĐ¸Ņ‚Đĩ ĐˇĐ°ĐŗĐžĐģОвĐēи ĐŋŅ€ĐžĐēŅĐ¸-ҁĐĩŅ€Đ˛ĐĩŅ€Đ°, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ Immich Đ´ĐžĐģĐļĐĩĐŊ ĐžŅ‚ĐŋŅ€Đ°Đ˛ĐģŅŅ‚ŅŒ ҁ ĐēаĐļĐ´Ņ‹Đŧ ҁĐĩŅ‚ĐĩĐ˛Ņ‹Đŧ СаĐŋŅ€ĐžŅĐžĐŧ.", + "advanced_settings_proxy_headers_subtitle": "ОĐŋŅ€ĐĩĐ´ĐĩĐģĐ¸Ņ‚Đĩ ĐˇĐ°ĐŗĐžĐģОвĐēи ĐŋŅ€ĐžĐēŅĐ¸-ҁĐĩŅ€Đ˛ĐĩŅ€Đ°, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ Immich Đ´ĐžĐģĐļĐĩĐŊ ĐžŅ‚ĐŋŅ€Đ°Đ˛ĐģŅŅ‚ŅŒ ҁ ĐēаĐļĐ´Ņ‹Đŧ ҁĐĩŅ‚ĐĩĐ˛Ņ‹Đŧ СаĐŋŅ€ĐžŅĐžĐŧ", "advanced_settings_proxy_headers_title": "Đ—Đ°ĐŗĐžĐģОвĐēи ĐŋŅ€ĐžĐēŅĐ¸", "advanced_settings_self_signed_ssl_subtitle": "ĐŸŅ€ĐžĐŋ҃ҁĐēĐ°Ņ‚ŅŒ ĐŋŅ€ĐžĐ˛ĐĩŅ€Đē҃ SSL-ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚Đ° ҁĐĩŅ€Đ˛ĐĩŅ€Đ°. ĐĸŅ€ĐĩĐąŅƒĐĩŅ‚ŅŅ Đ´ĐģŅ ŅĐ°ĐŧĐžĐŋОдĐŋĐ¸ŅĐ°ĐŊĐŊҋ҅ ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚ĐžĐ˛.", "advanced_settings_self_signed_ssl_title": "Đ Đ°ĐˇŅ€ĐĩŅˆĐ¸Ņ‚ŅŒ ŅĐ°ĐŧĐžĐŋОдĐŋĐ¸ŅĐ°ĐŊĐŊŅ‹Đĩ SSL-ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚Ņ‹", + "advanced_settings_sync_remote_deletions_subtitle": "ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐĩҁĐēи ŅƒĐ´Đ°ĐģŅŅ‚ŅŒ иĐģи Đ˛ĐžŅŅŅ‚Đ°ĐŊавĐģĐ¸Đ˛Đ°Ņ‚ŅŒ ĐžĐąŅŠĐĩĐēŅ‚ ĐŊа ŅŅ‚ĐžĐŧ ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đĩ, ĐēĐžĐŗĐ´Đ° ŅŅ‚Đž Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Đĩ Đ˛Ņ‹ĐŋĐžĐģĐŊŅĐĩŅ‚ŅŅ ҇ĐĩŅ€ĐĩС вĐĩĐą-иĐŊŅ‚ĐĩҀ҄ĐĩĐšŅ", + "advanced_settings_sync_remote_deletions_title": "ХиĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Ņ ŅƒĐ´Đ°ĐģĐĩĐŊĐŊҋ҅ ŅƒĐ´Đ°ĐģĐĩĐŊиК [ЭКСПЕРИМЕНĐĸАЛĐŦНО]", "advanced_settings_tile_subtitle": "Đ Đ°ŅŅˆĐ¸Ņ€ĐĩĐŊĐŊŅ‹Đĩ ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēи", "advanced_settings_troubleshooting_subtitle": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ Ņ€Đ°ŅŅˆĐ¸Ņ€ĐĩĐŊĐŊŅ‹Đĩ вОСĐŧĐžĐļĐŊĐžŅŅ‚Đ¸ Đ´ĐģŅ Ņ€Đĩ҈ĐĩĐŊĐ¸Ņ ĐŋŅ€ĐžĐąĐģĐĩĐŧ", "advanced_settings_troubleshooting_title": "Đ Đĩ҈ĐĩĐŊиĐĩ ĐŋŅ€ĐžĐąĐģĐĩĐŧ", @@ -401,7 +405,7 @@ "album_share_no_users": "ĐŸĐžŅ…ĐžĐļĐĩ, Đ˛Ņ‹ ĐŋОдĐĩĐģиĐģĐ¸ŅŅŒ ŅŅ‚Đ¸Đŧ аĐģŅŒĐąĐžĐŧĐžĐŧ ŅĐž Đ˛ŅĐĩĐŧи ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅĐŧи иĐģи ҃ Đ˛Đ°Ņ ĐŊĐĩŅ‚ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģĐĩĐš, ҁ ĐēĐžŅ‚ĐžŅ€Ņ‹Đŧи ĐŧĐžĐļĐŊĐž ĐŋОдĐĩĐģĐ¸Ņ‚ŅŒŅŅ.", "album_thumbnail_card_item": "1 ŅĐģĐĩĐŧĐĩĐŊŅ‚", "album_thumbnail_card_items": "{} ŅĐģĐĩĐŧĐĩĐŊŅ‚ĐžĐ˛", - "album_thumbnail_card_shared": "¡ ĐžĐąŅ‰Đ¸Đš", + "album_thumbnail_card_shared": " ¡ ĐžĐąŅ‰Đ¸Đš", "album_thumbnail_shared_by": "ПодĐĩĐģиĐģŅŅ {}", "album_updated": "АĐģŅŒĐąĐžĐŧ ОйĐŊОвĐģŅ‘ĐŊ", "album_updated_setting_description": "ПоĐģŅƒŅ‡Đ°Ņ‚ŅŒ ŅƒĐ˛ĐĩĐ´ĐžĐŧĐģĐĩĐŊиĐĩ ĐŋĐž ŅĐģĐĩĐēŅ‚Ņ€ĐžĐŊĐŊОК ĐŋĐžŅ‡Ņ‚Đĩ ĐŋŅ€Đ¸ дОйавĐģĐĩĐŊии ĐŊĐžĐ˛Ņ‹Ņ… Ņ€ĐĩŅŅƒŅ€ŅĐžĐ˛ в ĐžĐąŅ‰Đ¸Đš аĐģŅŒĐąĐžĐŧ", @@ -477,15 +481,15 @@ "assets_added_to_album_count": "В аĐģŅŒĐąĐžĐŧ дОйавĐģĐĩĐŊĐž {count, plural, one {# ĐžĐąŅŠĐĩĐēŅ‚} few {# ĐžĐąŅŠĐĩĐēŅ‚Đ°} other {# ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛}}", "assets_added_to_name_count": "ДобавĐģĐĩĐŊĐž {count, plural, one {# ĐžĐąŅŠĐĩĐēŅ‚} few {# ĐžĐąŅŠĐĩĐēŅ‚Đ°} other {# ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛}} в {hasName, select, true {{name}} other {ĐŊĐžĐ˛Ņ‹Đš аĐģŅŒĐąĐžĐŧ}}", "assets_count": "{count, plural, one {# ĐžĐąŅŠĐĩĐēŅ‚} few {# ĐžĐąŅŠĐĩĐēŅ‚Đ°} other {# ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛}}", - "assets_deleted_permanently": "{} ĐžĐąŅŠĐĩĐēŅ‚(Ņ‹) ŅƒĐ´Đ°ĐģĐĩĐŊ(Ņ‹) ĐŊĐ°Đ˛ŅĐĩĐŗĐ´Đ°", - "assets_deleted_permanently_from_server": "{} ĐžĐąŅŠĐĩĐēŅ‚(Ņ‹) ŅƒĐ´Đ°ĐģĐĩĐŊ(Ņ‹) ĐŊĐ°Đ˛ŅĐĩĐŗĐ´Đ° ҁ ҁĐĩŅ€Đ˛ĐĩŅ€Đ° Immich", + "assets_deleted_permanently": "{} ĐžĐąŅŠĐĩĐēŅ‚(Ņ‹) ŅƒĐ´Đ°ĐģĐĩĐŊ(Ņ‹) ĐŊĐ°Đ˛ŅĐĩĐŗĐ´Đ°", + "assets_deleted_permanently_from_server": "{} ĐžĐąŅŠĐĩĐēŅ‚(Ņ‹) ŅƒĐ´Đ°ĐģĐĩĐŊ(Ņ‹) ĐŊĐ°Đ˛ŅĐĩĐŗĐ´Đ° ҁ ҁĐĩŅ€Đ˛ĐĩŅ€Đ° Immich", "assets_moved_to_trash_count": "{count, plural, one {# ĐžĐąŅŠĐĩĐēŅ‚} few {# ĐžĐąŅŠĐĩĐēŅ‚Đ°} other {# ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛}} ĐŋĐĩŅ€ĐĩĐŧĐĩ҉ĐĩĐŊĐž в ĐēĐžŅ€ĐˇĐ¸ĐŊ҃", "assets_permanently_deleted_count": "{count, plural, one {# ĐžĐąŅŠĐĩĐēŅ‚} few {# ĐžĐąŅŠĐĩĐēŅ‚Đ°} other {# ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛}} ŅƒĐ´Đ°ĐģĐĩĐŊĐž ĐŊĐ°Đ˛ŅĐĩĐŗĐ´Đ°", "assets_removed_count": "{count, plural, one {# ĐžĐąŅŠĐĩĐēŅ‚} few {# ĐžĐąŅŠĐĩĐēŅ‚Đ°} other {# ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛}} ŅƒĐ´Đ°ĐģĐĩĐŊĐž", - "assets_removed_permanently_from_device": "{} ĐžĐąŅŠĐĩĐēŅ‚(Ņ‹) ŅƒĐ´Đ°ĐģĐĩĐŊ(Ņ‹) ĐŊĐ°Đ˛ŅĐĩĐŗĐ´Đ° ҁ Đ˛Đ°ŅˆĐĩĐŗĐž ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đ°", + "assets_removed_permanently_from_device": "{} ĐžĐąŅŠĐĩĐēŅ‚(Ņ‹) ŅƒĐ´Đ°ĐģĐĩĐŊ(Ņ‹) ĐŊĐ°Đ˛ŅĐĩĐŗĐ´Đ° ҁ Đ˛Đ°ŅˆĐĩĐŗĐž ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đ°", "assets_restore_confirmation": "Đ’Ņ‹ ŅƒĐ˛ĐĩŅ€ĐĩĐŊŅ‹, Ņ‡Ņ‚Đž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ Đ˛ĐžŅŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ Đ˛ŅĐĩ ĐžĐąŅŠĐĩĐē҂ҋ иС ĐēĐžŅ€ĐˇĐ¸ĐŊŅ‹? Đ­Ņ‚Đž Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Đĩ ĐŊĐĩĐģŅŒĐˇŅ ĐžŅ‚ĐŧĐĩĐŊĐ¸Ņ‚ŅŒ! ĐžĐąŅ€Đ°Ņ‚Đ¸Ņ‚Đĩ вĐŊиĐŧаĐŊиĐĩ, Ņ‡Ņ‚Đž ĐģŅŽĐąŅ‹Đĩ ĐžŅ„Ņ„ĐģаКĐŊ-ĐžĐąŅŠĐĩĐē҂ҋ ĐŊĐĩ ĐŧĐžĐŗŅƒŅ‚ ĐąŅ‹Ņ‚ŅŒ Đ˛ĐžŅŅŅ‚Đ°ĐŊОвĐģĐĩĐŊŅ‹ Ņ‚Đ°ĐēиĐŧ ҁĐŋĐžŅĐžĐąĐžĐŧ.", "assets_restored_count": "{count, plural, one {# ĐžĐąŅŠĐĩĐēŅ‚} few {# ĐžĐąŅŠĐĩĐēŅ‚Đ°} other {# ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛}} Đ˛ĐžŅŅŅ‚Đ°ĐŊОвĐģĐĩĐŊĐž", - "assets_restored_successfully": "{} ĐžĐąŅŠĐĩĐēŅ‚(Ņ‹) ҃ҁĐŋĐĩ҈ĐŊĐž Đ˛ĐžŅŅŅ‚Đ°ĐŊОвĐģĐĩĐŊ(Ņ‹)", + "assets_restored_successfully": "{} ĐžĐąŅŠĐĩĐēŅ‚(Ņ‹) ҃ҁĐŋĐĩ҈ĐŊĐž Đ˛ĐžŅŅŅ‚Đ°ĐŊОвĐģĐĩĐŊ(Ņ‹)", "assets_trashed": "{} ĐžĐąŅŠĐĩĐēŅ‚(Ņ‹) ĐŋĐžĐŧĐĩ҉ĐĩĐŊ(Ņ‹) в ĐēĐžŅ€ĐˇĐ¸ĐŊ҃", "assets_trashed_count": "{count, plural, one {# ĐžĐąŅŠĐĩĐēŅ‚} few {# ĐžĐąŅŠĐĩĐēŅ‚Đ°} other {# ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛}} ĐŋĐĩŅ€ĐĩĐŧĐĩ҉ĐĩĐŊĐž в ĐēĐžŅ€ĐˇĐ¸ĐŊ҃", "assets_trashed_from_server": "{} ĐžĐąŅŠĐĩĐēŅ‚(Ņ‹) ĐŋĐžĐŧĐĩ҉ĐĩĐŊ(Ņ‹) в ĐēĐžŅ€ĐˇĐ¸ĐŊ҃ ĐŊа ҁĐĩŅ€Đ˛ĐĩŅ€Đĩ Immich", @@ -498,14 +502,14 @@ "background_location_permission": "Đ”ĐžŅŅ‚ŅƒĐŋ Đē ĐŧĐĩŅŅ‚ĐžĐŋĐžĐģĐžĐļĐĩĐŊĐ¸ŅŽ в Ņ„ĐžĐŊĐĩ", "background_location_permission_content": "Đ§Ņ‚ĐžĐąŅ‹ ŅŅ‡Đ¸Ņ‚Ņ‹Đ˛Đ°Ņ‚ŅŒ иĐŧŅ Wi-Fi ҁĐĩŅ‚Đ¸ в Ņ„ĐžĐŊĐĩ, ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸ŅŽ *Đ˛ŅĐĩĐŗĐ´Đ°* ĐŊĐĩĐžĐąŅ…ĐžĐ´Đ¸Đŧ Đ´ĐžŅŅ‚ŅƒĐŋ Đē Ņ‚ĐžŅ‡ĐŊĐžĐŧ҃ ĐŧĐĩŅŅ‚ĐžĐŋĐžĐģĐžĐļĐĩĐŊĐ¸ŅŽ ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đ°", "backup_album_selection_page_albums_device": "АĐģŅŒĐąĐžĐŧŅ‹ ĐŊа ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đĩ ({})", - "backup_album_selection_page_albums_tap": "НаĐļĐŧĐ¸Ņ‚Đĩ, Ņ‡Ņ‚ĐžĐąŅ‹ вĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ,\nĐŊаĐļĐŧĐ¸Ņ‚Đĩ дваĐļĐ´Ņ‹, Ņ‡Ņ‚ĐžĐąŅ‹ Đ¸ŅĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ", + "backup_album_selection_page_albums_tap": "НаĐļĐŧĐ¸Ņ‚Đĩ, Ņ‡Ņ‚ĐžĐąŅ‹ вĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ, дваĐļĐ´Ņ‹, Ņ‡Ņ‚ĐžĐąŅ‹ Đ¸ŅĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ", "backup_album_selection_page_assets_scatter": "Đ’Đ°ŅˆĐ¸ Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ и видĐĩĐž ĐŧĐžĐŗŅƒŅ‚ ĐŊĐ°Ņ…ĐžĐ´Đ¸Ņ‚ŅŒŅŅ в Ņ€Đ°ĐˇĐŊҋ҅ аĐģŅŒĐąĐžĐŧĐ°Ņ…. Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ Đ˛Ņ‹ĐąŅ€Đ°Ņ‚ŅŒ, ĐēаĐēиĐĩ аĐģŅŒĐąĐžĐŧŅ‹ вĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ, а ĐēаĐēиĐĩ Đ¸ŅĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ иС Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ.", "backup_album_selection_page_select_albums": "Đ’Ņ‹ĐąĐžŅ€ аĐģŅŒĐąĐžĐŧОв", "backup_album_selection_page_selection_info": "ИĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Ņ Đž Đ˛Ņ‹ĐąĐžŅ€Đĩ", "backup_album_selection_page_total_assets": "Đ’ŅĐĩĐŗĐž ҃ĐŊиĐēаĐģҌĐŊҋ҅ ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛", "backup_all": "Đ’ŅĐĩ", "backup_background_service_backup_failed_message": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ Đ˛Ņ‹ĐŋĐžĐģĐŊĐ¸Ņ‚ŅŒ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐĩ ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊиĐĩ. ĐŸĐžĐ˛Ņ‚ĐžŅ€ĐŊĐ°Ņ ĐŋĐžĐŋҋ҂Đēаâ€Ļ", - "backup_background_service_connection_failed_message": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ ĐŋОдĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒŅŅ Đē ҁĐĩŅ€Đ˛ĐĩŅ€Ņƒ. ĐŸĐžĐ˛Ņ‚ĐžŅ€ĐŊĐ°Ņ ĐŋĐžĐŋҋ҂Đēа...", + "backup_background_service_connection_failed_message": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ ĐŋОдĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒŅŅ Đē ҁĐĩŅ€Đ˛ĐĩŅ€Ņƒ. ĐŸĐžĐ˛Ņ‚ĐžŅ€ĐŊĐ°Ņ ĐŋĐžĐŋҋ҂Đēаâ€Ļ", "backup_background_service_current_upload_notification": "Đ—Đ°ĐŗŅ€ŅƒĐļаĐĩŅ‚ŅŅ {}", "backup_background_service_default_notification": "ĐŸĐžĐ¸ŅĐē ĐŊĐžĐ˛Ņ‹Ņ… ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛â€Ļ", "backup_background_service_error_title": "ĐžŅˆĐ¸ĐąĐēа Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ", @@ -533,7 +537,7 @@ "backup_controller_page_backup_sub": "Đ—Đ°ĐŗŅ€ŅƒĐļĐĩĐŊĐŊŅ‹Đĩ Ņ„ĐžŅ‚Đž и видĐĩĐž", "backup_controller_page_created": "ХОСдаĐŊĐž: {}", "backup_controller_page_desc_backup": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚Đĩ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐĩ ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊиĐĩ в аĐēŅ‚Đ¸Đ˛ĐŊĐžĐŧ Ņ€ĐĩĐļиĐŧĐĩ, Ņ‡Ņ‚ĐžĐąŅ‹ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐĩҁĐēи ĐˇĐ°ĐŗŅ€ŅƒĐļĐ°Ņ‚ŅŒ ĐŊĐžĐ˛Ņ‹Đĩ ĐžĐąŅŠĐĩĐē҂ҋ ĐŋŅ€Đ¸ ĐžŅ‚ĐēŅ€Ņ‹Ņ‚Đ¸Đ¸ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸Ņ.", - "backup_controller_page_excluded": "Đ˜ŅĐēĐģŅŽŅ‡ĐĩĐŊŅ‹:", + "backup_controller_page_excluded": "Đ˜ŅĐēĐģŅŽŅ‡ĐĩĐŊŅ‹: ", "backup_controller_page_failed": "НĐĩŅƒĐ´Đ°Ņ‡ĐŊҋ҅ ({})", "backup_controller_page_filename": "ИĐŧŅ Ņ„Đ°ĐšĐģа: {} [{}]", "backup_controller_page_id": "ID: {}", @@ -615,7 +619,7 @@ "check_all": "Đ’Ņ‹ĐąŅ€Đ°Ņ‚ŅŒ Đ˛ŅŅ‘", "check_corrupt_asset_backup": "ĐŸŅ€ĐžĐ˛ĐĩŅ€Đēа ĐŋĐžĐ˛Ņ€ĐĩĐļĐ´ĐĩĐŊĐŊҋ҅ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊҋ҅ ĐēĐžĐŋиК", "check_corrupt_asset_backup_button": "ĐŸŅ€ĐžĐ˛ĐĩŅ€Đ¸Ņ‚ŅŒ", - "check_corrupt_asset_backup_description": "ĐŸŅ€ĐžĐ˛ĐžĐ´Đ¸Ņ‚Đĩ ĐŋŅ€ĐžĐ˛ĐĩŅ€Đē҃ Ņ‚ĐžĐģҌĐēĐž ҇ĐĩŅ€ĐĩС Wi-Fi и Ņ‚ĐžĐģҌĐēĐž ĐŋĐžŅĐģĐĩ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ Đ˛ŅĐĩŅ… ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛. Đ­Ņ‚Đ° ĐžĐŋĐĩŅ€Đ°Ņ†Đ¸Ņ ĐŧĐžĐļĐĩŅ‚ СаĐŊŅŅ‚ŅŒ ĐŊĐĩҁĐēĐžĐģҌĐēĐž ĐŧиĐŊŅƒŅ‚", + "check_corrupt_asset_backup_description": "ЗаĐŋ҃ҁĐēĐ°ĐšŅ‚Đĩ ĐŋŅ€ĐžĐ˛ĐĩŅ€Đē҃ Ņ‚ĐžĐģҌĐēĐž ҇ĐĩŅ€ĐĩС Wi-Fi и ĐŋĐžŅĐģĐĩ ŅĐžĐˇĐ´Đ°ĐŊĐ¸Ņ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊОК ĐēĐžĐŋии Đ˛ŅĐĩŅ… ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛. ОĐŋĐĩŅ€Đ°Ņ†Đ¸Ņ ĐŧĐžĐļĐĩŅ‚ СаĐŊŅŅ‚ŅŒ ĐŊĐĩҁĐēĐžĐģҌĐēĐž ĐŧиĐŊŅƒŅ‚.", "check_logs": "ĐŸŅ€ĐžĐ˛ĐĩŅ€Đ¸Ņ‚ŅŒ ĐļŅƒŅ€ĐŊаĐģŅ‹", "choose_matching_people_to_merge": "Đ’Ņ‹ĐąĐĩŅ€Đ¸Ņ‚Đĩ ĐŋĐžĐ´Ņ…ĐžĐ´ŅŅ‰Đ¸Ņ… ĐģŅŽĐ´ĐĩĐš Đ´ĐģŅ ҁĐģĐ¸ŅĐŊĐ¸Ņ", "city": "Đ“ĐžŅ€ĐžĐ´", @@ -631,7 +635,7 @@ "client_cert_invalid_msg": "НĐĩвĐĩŅ€ĐŊŅ‹Đš Ņ„Đ°ĐšĐģ ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚Đ° иĐģи ĐŊĐĩвĐĩŅ€ĐŊŅ‹Đš ĐŋĐ°Ņ€ĐžĐģҌ", "client_cert_remove_msg": "КĐģиĐĩĐŊ҂ҁĐēиК ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚ ŅƒĐ´Đ°ĐģĐĩĐŊ", "client_cert_subtitle": "ПоддĐĩŅ€ĐļиваĐĩŅ‚ŅŅ Ņ‚ĐžĐģҌĐēĐž Ņ„ĐžŅ€ĐŧĐ°Ņ‚ PKCS12 (.p12, .pfx). ИĐŧĐŋĐžŅ€Ņ‚/ŅƒĐ´Đ°ĐģĐĩĐŊиĐĩ ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚Đ° Đ´ĐžŅŅ‚ŅƒĐŋĐŊĐž Ņ‚ĐžĐģҌĐēĐž ĐŋĐĩŅ€ĐĩĐ´ Đ˛Ņ…ĐžĐ´ĐžĐŧ в ŅĐ¸ŅŅ‚ĐĩĐŧ҃", - "client_cert_title": "КĐģиĐĩĐŊ҂ҁĐēиК SSL-ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚ ", + "client_cert_title": "КĐģиĐĩĐŊ҂ҁĐēиК SSL-ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚", "clockwise": "По Ņ‡Đ°ŅĐžĐ˛ĐžĐš", "close": "ЗаĐēŅ€Ņ‹Ņ‚ŅŒ", "collapse": "ХвĐĩŅ€ĐŊŅƒŅ‚ŅŒ", @@ -656,11 +660,11 @@ "continue": "ĐŸŅ€ĐžĐ´ĐžĐģĐļĐ¸Ņ‚ŅŒ", "control_bottom_app_bar_album_info_shared": "{} ŅĐģĐĩĐŧĐĩĐŊŅ‚ĐžĐ˛ ¡ ĐžĐąŅ‰Đ¸Đš", "control_bottom_app_bar_create_new_album": "ĐĄĐžĐˇĐ´Đ°Ņ‚ŅŒ аĐģŅŒĐąĐžĐŧ", - "control_bottom_app_bar_delete_from_immich": "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ иС Immich\n", + "control_bottom_app_bar_delete_from_immich": "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ иС Immich", "control_bottom_app_bar_delete_from_local": "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ ҁ ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đ°", "control_bottom_app_bar_edit_location": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ĐŧĐĩŅŅ‚Đž", "control_bottom_app_bar_edit_time": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ Đ´Đ°Ņ‚Ņƒ", - "control_bottom_app_bar_share_link": "Share Link", + "control_bottom_app_bar_share_link": "ПодĐĩĐģĐ¸Ņ‚ŅŒŅŅ ҁҁҋĐģĐēОК", "control_bottom_app_bar_share_to": "ПодĐĩĐģĐ¸Ņ‚ŅŒŅŅ", "control_bottom_app_bar_trash_from_immich": "В ĐēĐžŅ€ĐˇĐ¸ĐŊ҃", "copied_image_to_clipboard": "Đ˜ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиĐĩ ҁĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐž в ĐąŅƒŅ„ĐĩŅ€ ОйĐŧĐĩĐŊа.", @@ -807,7 +811,7 @@ "editor_crop_tool_h2_aspect_ratios": "ĐĄĐžĐžŅ‚ĐŊĐžŅˆĐĩĐŊĐ¸Ņ ŅŅ‚ĐžŅ€ĐžĐŊ", "editor_crop_tool_h2_rotation": "Đ’Ņ€Đ°Ņ‰ĐĩĐŊиĐĩ", "email": "Đ­ĐģĐĩĐēŅ‚Ņ€ĐžĐŊĐŊĐ°Ņ ĐŋĐžŅ‡Ņ‚Đ°", - "empty_folder": "This folder is empty", + "empty_folder": "ĐŸŅƒŅŅ‚Đ°Ņ ĐŋаĐŋĐēа", "empty_trash": "ĐžŅ‡Đ¸ŅŅ‚Đ¸Ņ‚ŅŒ ĐēĐžŅ€ĐˇĐ¸ĐŊ҃", "empty_trash_confirmation": "Đ’Ņ‹ ŅƒĐ˛ĐĩŅ€ĐĩĐŊŅ‹, Ņ‡Ņ‚Đž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ĐžŅ‡Đ¸ŅŅ‚Đ¸Ņ‚ŅŒ ĐēĐžŅ€ĐˇĐ¸ĐŊ҃? Đ’ŅĐĩ ĐžĐąŅŠĐĩĐē҂ҋ в ĐēĐžŅ€ĐˇĐ¸ĐŊĐĩ ĐąŅƒĐ´ŅƒŅ‚ ĐŊĐ°Đ˛ŅĐĩĐŗĐ´Đ° ŅƒĐ´Đ°ĐģĐĩĐŊŅ‹ иС Immich.\nĐ’Ņ‹ ĐŊĐĩ ҁĐŧĐžĐļĐĩŅ‚Đĩ ĐžŅ‚ĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ŅŅ‚Đž Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Đĩ!", "enable": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ", @@ -953,10 +957,10 @@ "exif_bottom_sheet_location": "МЕСĐĸО", "exif_bottom_sheet_people": "ЛЮДИ", "exif_bottom_sheet_person_add_person": "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ иĐŧŅ", - "exif_bottom_sheet_person_age": "Age {}", - "exif_bottom_sheet_person_age_months": "Age {} months", - "exif_bottom_sheet_person_age_year_months": "Age 1 year, {} months", - "exif_bottom_sheet_person_age_years": "Age {}", + "exif_bottom_sheet_person_age": "Đ’ĐžĐˇŅ€Đ°ŅŅ‚ {}", + "exif_bottom_sheet_person_age_months": "Đ’ĐžĐˇŅ€Đ°ŅŅ‚ {} ĐŧĐĩŅŅŅ†Đĩв", + "exif_bottom_sheet_person_age_year_months": "Đ’ĐžĐˇŅ€Đ°ŅŅ‚ 1 ĐŗĐžĐ´, {} ĐŧĐĩŅŅŅ†Đĩв", + "exif_bottom_sheet_person_age_years": "Đ’ĐžĐˇŅ€Đ°ŅŅ‚ {}", "exit_slideshow": "Đ’Ņ‹ĐšŅ‚Đ¸ иС ҁĐģаКд-ŅˆĐžŅƒ", "expand_all": "РаСвĐĩŅ€ĐŊŅƒŅ‚ŅŒ Đ˛ŅŅ‘", "experimental_settings_new_asset_list_subtitle": "В Ņ€Đ°ĐˇŅ€Đ°ĐąĐžŅ‚ĐēĐĩ", @@ -978,7 +982,7 @@ "face_unassigned": "НĐĩ ĐŊаСĐŊĐ°Ņ‡ĐĩĐŊĐž", "failed": "ĐžŅˆĐ¸ĐąĐēа", "failed_to_load_assets": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐ¸Ņ‚ŅŒ ĐžĐąŅŠĐĩĐē҂ҋ", - "failed_to_load_folder": "Failed to load folder", + "failed_to_load_folder": "ĐžŅˆĐ¸ĐąĐēа ĐŋŅ€Đ¸ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēĐĩ ĐŋаĐŋĐēи", "favorite": "Đ˜ĐˇĐąŅ€Đ°ĐŊĐŊĐžĐĩ", "favorite_or_unfavorite_photo": "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ иĐģи ŅƒĐ´Đ°ĐģĐ¸Ņ‚ŅŒ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸ŅŽ иС Đ¸ĐˇĐąŅ€Đ°ĐŊĐŊĐžĐŗĐž", "favorites": "Đ˜ĐˇĐąŅ€Đ°ĐŊĐŊĐžĐĩ", @@ -992,10 +996,11 @@ "filetype": "ĐĸиĐŋ Ņ„Đ°ĐšĐģа", "filter": "ФиĐģŅŒŅ‚Ņ€", "filter_people": "ФиĐģŅŒŅ‚Ņ€ ĐŋĐž ĐģŅŽĐ´ŅĐŧ", + "filter_places": "ФиĐģŅŒŅ‚Ņ€ ĐŋĐž ĐŧĐĩŅŅ‚Đ°Đŧ", "find_them_fast": "Đ‘Ņ‹ŅŅ‚Ņ€Đž ĐŊĐ°ĐšĐ´Đ¸Ņ‚Đĩ Đ¸Ņ… ĐŋĐž иĐŧĐĩĐŊи ҁ ĐŋĐžĐŧĐžŅ‰ŅŒŅŽ ĐŋĐžĐ¸ŅĐēа", "fix_incorrect_match": "Đ˜ŅĐŋŅ€Đ°Đ˛Đ¸Ņ‚ŅŒ ĐŊĐĩĐŋŅ€Đ°Đ˛Đ¸ĐģҌĐŊĐžĐĩ ŅĐžĐžŅ‚Đ˛ĐĩŅ‚ŅŅ‚Đ˛Đ¸Đĩ", - "folder": "Folder", - "folder_not_found": "Folder not found", + "folder": "ПаĐŋĐēа", + "folder_not_found": "ПаĐŋĐēа ĐŊĐĩ ĐŊаКдĐĩĐŊа", "folders": "ПаĐŋĐēи", "folders_feature_description": "ĐŸŅ€ĐžŅĐŧĐžŅ‚Ņ€ ĐŋаĐŋĐžĐē ҁ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸ŅĐŧи и видĐĩĐž в Ņ„Đ°ĐšĐģОвОК ŅĐ¸ŅŅ‚ĐĩĐŧĐĩ", "forward": "ВĐŋĐĩŅ€Ņ‘Đ´", @@ -1040,7 +1045,7 @@ "home_page_delete_remote_err_local": "НĐĩвОСĐŧĐžĐļĐŊĐž ŅƒĐ´Đ°ĐģĐ¸Ņ‚ŅŒ ĐģĐžĐēаĐģҌĐŊŅ‹Đĩ Ņ„Đ°ĐšĐģŅ‹ ҁ ҁĐĩŅ€Đ˛ĐĩŅ€Đ°, ĐŋŅ€ĐžĐŋ҃ҁĐē", "home_page_favorite_err_local": "ПоĐēа ĐŊĐĩĐģŅŒĐˇŅ Đ´ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ в Đ¸ĐˇĐąŅ€Đ°ĐŊĐŊĐžĐĩ ĐģĐžĐēаĐģҌĐŊŅ‹Đĩ Ņ„Đ°ĐšĐģŅ‹, ĐŋŅ€ĐžĐŋ҃ҁĐē", "home_page_favorite_err_partner": "ПоĐēа ĐŊĐĩĐģŅŒĐˇŅ Đ´ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ в Đ¸ĐˇĐąŅ€Đ°ĐŊĐŊĐžĐĩ ĐŧĐĩдиа ĐŋĐ°Ņ€Ņ‚ĐŊĐĩŅ€Đ°, ĐŋŅ€ĐžĐŋ҃ҁĐē", - "home_page_first_time_notice": "Đ•ŅĐģи Đ˛Ņ‹ Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐĩŅ‚Đĩ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ вĐŋĐĩŅ€Đ˛Ņ‹Đĩ, Đ˛Ņ‹ĐąĐĩŅ€Đ¸Ņ‚Đĩ аĐģŅŒĐąĐžĐŧŅ‹ Đ´ĐģŅ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ иĐģи ĐˇĐ°ĐŗŅ€ŅƒĐˇĐ¸Ņ‚Đĩ Đ¸Ņ… Đ˛Ņ€ŅƒŅ‡ĐŊŅƒŅŽ, Ņ‡Ņ‚ĐžĐąŅ‹ СаĐŋĐžĐģĐŊĐ¸Ņ‚ŅŒ иĐŧи Đ˛Ņ€ĐĩĐŧĐĩĐŊĐŊŅƒŅŽ ҈ĐēаĐģ҃.", + "home_page_first_time_notice": "ПĐĩŅ€ĐĩĐ´ ĐŊĐ°Ņ‡Đ°ĐģĐžĐŧ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°ĐŊĐ¸Ņ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸Ņ Đ˛Ņ‹ĐąĐĩŅ€Đ¸Ņ‚Đĩ аĐģŅŒĐąĐžĐŧ ҁ ĐžĐąŅŠĐĩĐēŅ‚Đ°Đŧи Đ´ĐģŅ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ, Ņ‡Ņ‚ĐžĐąŅ‹ ĐžĐŊи ĐžŅ‚ĐžĐąŅ€Đ°ĐˇĐ¸ĐģĐ¸ŅŅŒ ĐŊа Đ˛Ņ€ĐĩĐŧĐĩĐŊĐŊОК ҈ĐēаĐģĐĩ", "home_page_share_err_local": "НĐĩĐģŅŒĐˇŅ ĐŋОдĐĩĐģĐ¸Ņ‚ŅŒŅŅ ĐģĐžĐēаĐģҌĐŊŅ‹Đŧи Ņ„Đ°ĐšĐģаĐŧи ĐŋĐž ҁҁҋĐģĐēĐĩ, ĐŋŅ€ĐžĐŋ҃ҁĐē", "home_page_upload_err_limit": "Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐ¸Ņ‚ŅŒ ĐŧаĐēŅĐ¸Đŧ҃Đŧ 30 Ņ„Đ°ĐšĐģОв Са Ņ€Đ°Đˇ, ĐŋŅ€ĐžĐŋ҃ҁĐē", "host": "ĐĨĐžŅŅ‚", @@ -1145,7 +1150,7 @@ "login_form_failed_get_oauth_server_config": "ĐžŅˆĐ¸ĐąĐēа Đ°Đ˛Ņ‚ĐžŅ€Đ¸ĐˇĐ°Ņ†Đ¸Đ¸ ҁ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°ĐŊиĐĩĐŧ OAuth, ĐŋŅ€ĐžĐ˛ĐĩŅ€ŅŒŅ‚Đĩ URL-Đ°Đ´Ņ€Đĩҁ ҁĐĩŅ€Đ˛ĐĩŅ€Đ°", "login_form_failed_get_oauth_server_disable": "ĐĐ˛Ņ‚ĐžŅ€Đ¸ĐˇĐ°Ņ†Đ¸Ņ ҇ĐĩŅ€ĐĩС OAuth ĐŊĐĩĐ´ĐžŅŅ‚ŅƒĐŋĐŊа ĐŊа ŅŅ‚ĐžĐŧ ҁĐĩŅ€Đ˛ĐĩŅ€Đĩ", "login_form_failed_login": "ĐžŅˆĐ¸ĐąĐēа ĐŋŅ€Đ¸ Đ˛Ņ…ĐžĐ´Đĩ, ĐŋŅ€ĐžĐ˛ĐĩŅ€ŅŒŅ‚Đĩ URL-Đ°Đ´Ņ€Đĩҁ ҁĐĩŅ€Đ˛ĐĩŅ€Đ°, Đ°Đ´Ņ€Đĩҁ ŅĐģĐĩĐēŅ‚Ņ€ĐžĐŊĐŊОК ĐŋĐžŅ‡Ņ‚Ņ‹ и ĐŋĐ°Ņ€ĐžĐģҌ", - "login_form_handshake_exception": "ĐžŅˆĐ¸ĐąĐēа ĐŋŅ€ĐžĐ˛ĐĩŅ€Đēи ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚Đ°. Đ•ŅĐģи Đ˛Ņ‹ Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐĩŅ‚Đĩ ŅĐ°ĐŧĐžĐŋОдĐŋĐ¸ŅĐ°ĐŊĐŊŅ‹Đš ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚, вĐēĐģŅŽŅ‡Đ¸Ņ‚Đĩ ĐŋОддĐĩŅ€ĐļĐē҃ ŅĐ°ĐŧĐžĐŋОдĐŋĐ¸ŅĐ°ĐŊĐŊҋ҅ ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚ĐžĐ˛ в ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēĐ°Ņ….", + "login_form_handshake_exception": "ĐžŅˆĐ¸ĐąĐēа ĐŋŅ€ĐžĐ˛ĐĩŅ€Đēи ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚Đ°. Đ•ŅĐģи Đ˛Ņ‹ Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐĩŅ‚Đĩ ŅĐ°ĐŧĐžĐŋОдĐŋĐ¸ŅĐ°ĐŊĐŊŅ‹Đš ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚, вĐēĐģŅŽŅ‡Đ¸Ņ‚Đĩ ĐŋОддĐĩŅ€ĐļĐē҃ ŅĐ°ĐŧĐžĐŋОдĐŋĐ¸ŅĐ°ĐŊĐŊҋ҅ ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚ĐžĐ˛ в ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēĐ°Ņ….", "login_form_password_hint": "ĐŋĐ°Ņ€ĐžĐģҌ", "login_form_save_login": "ĐžŅŅ‚Đ°Đ˛Đ°Ņ‚ŅŒŅŅ в ŅĐ¸ŅŅ‚ĐĩĐŧĐĩ", "login_form_server_empty": "ВвĐĩĐ´Đ¸Ņ‚Đĩ URL-Đ°Đ´Ņ€Đĩҁ ҁĐĩŅ€Đ˛ĐĩŅ€Đ°.", @@ -1185,7 +1190,7 @@ "map_settings": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи ĐēĐ°Ņ€Ņ‚Ņ‹", "map_settings_dark_mode": "ĐĸĐĩĐŧĐŊŅ‹Đš Ņ€ĐĩĐļиĐŧ", "map_settings_date_range_option_day": "24 Ņ‡Đ°ŅĐ°", - "map_settings_date_range_option_days": "{} Đ´ĐŊĐĩĐš", + "map_settings_date_range_option_days": "ĐŸĐžŅĐģĐĩĐ´ĐŊиĐĩ {} Đ´ĐŊĐĩĐš", "map_settings_date_range_option_year": "Год", "map_settings_date_range_option_years": "{} ĐŗĐžĐ´Đ°", "map_settings_dialog_title": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи ĐēĐ°Ņ€Ņ‚Ņ‹", @@ -1261,7 +1266,7 @@ "note_apply_storage_label_to_previously_uploaded assets": "ĐŸŅ€Đ¸ĐŧĐĩŅ‡Đ°ĐŊиĐĩ: Đ§Ņ‚ĐžĐąŅ‹ ĐŋŅ€Đ¸ĐŧĐĩĐŊĐ¸Ņ‚ŅŒ Ņ‚ĐĩĐŗ Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đ° Đē Ņ€Đ°ĐŊĐĩĐĩ ĐˇĐ°ĐŗŅ€ŅƒĐļĐĩĐŊĐŊŅ‹Đŧ Ņ€ĐĩŅŅƒŅ€ŅĐ°Đŧ, СаĐŋŅƒŅŅ‚Đ¸Ņ‚Đĩ", "notes": "ĐŸŅ€Đ¸ĐŧĐĩŅ‡Đ°ĐŊиĐĩ", "notification_permission_dialog_content": "Đ§Ņ‚ĐžĐąŅ‹ вĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ ŅƒĐ˛ĐĩĐ´ĐžĐŧĐģĐĩĐŊĐ¸Ņ, ĐŋĐĩŅ€ĐĩĐšĐ´Đ¸Ņ‚Đĩ в ÂĢĐĐ°ŅŅ‚Ņ€ĐžĐšĐēиÂģ и Đ˛Ņ‹ĐąĐĩŅ€Đ¸Ņ‚Đĩ ÂĢĐ Đ°ĐˇŅ€ĐĩŅˆĐ¸Ņ‚ŅŒÂģ.", - "notification_permission_list_tile_content": "ĐŸŅ€ĐĩĐ´ĐžŅŅ‚Đ°Đ˛ŅŒŅ‚Đĩ Ņ€Đ°ĐˇŅ€Đĩ҈ĐĩĐŊиĐĩ ĐŊа вĐēĐģŅŽŅ‡ĐĩĐŊиĐĩ ŅƒĐ˛ĐĩĐ´ĐžĐŧĐģĐĩĐŊиК", + "notification_permission_list_tile_content": "ĐŸŅ€ĐĩĐ´ĐžŅŅ‚Đ°Đ˛ŅŒŅ‚Đĩ Ņ€Đ°ĐˇŅ€Đĩ҈ĐĩĐŊиĐĩ ĐŊа ĐŋĐžĐēаС ŅƒĐ˛ĐĩĐ´ĐžĐŧĐģĐĩĐŊиК.", "notification_permission_list_tile_enable_button": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ ŅƒĐ˛ĐĩĐ´ĐžĐŧĐģĐĩĐŊĐ¸Ņ", "notification_permission_list_tile_title": "Đ Đ°ĐˇŅ€Đĩ҈ĐĩĐŊиĐĩ ĐŊа ŅƒĐ˛ĐĩĐ´ĐžĐŧĐģĐĩĐŊиĐĩ", "notification_toggle_setting_description": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ ŅƒĐ˛ĐĩĐ´ĐžĐŧĐģĐĩĐŊĐ¸Ņ ĐŋĐž ŅĐģĐĩĐēŅ‚Ņ€ĐžĐŊĐŊОК ĐŋĐžŅ‡Ņ‚Đĩ", @@ -1282,6 +1287,7 @@ "onboarding_welcome_user": "Đ”ĐžĐąŅ€Đž ĐŋĐžĐļаĐģĐžĐ˛Đ°Ņ‚ŅŒ, {user}", "online": "Đ”ĐžŅŅ‚ŅƒĐŋĐĩĐŊ", "only_favorites": "ĐĸĐžĐģҌĐēĐž Đ¸ĐˇĐąŅ€Đ°ĐŊĐŊĐžĐĩ", + "open": "ĐžŅ‚ĐēŅ€Ņ‹Ņ‚ŅŒ", "open_in_map_view": "ĐžŅ‚ĐēŅ€Ņ‹Ņ‚ŅŒ в Ņ€ĐĩĐļиĐŧĐĩ ĐŋŅ€ĐžŅĐŧĐžŅ‚Ņ€Đ° ĐēĐ°Ņ€Ņ‚Ņ‹", "open_in_openstreetmap": "ĐžŅ‚ĐēŅ€Ņ‹Ņ‚ŅŒ в OpenStreetMap", "open_the_search_filters": "ĐžŅ‚ĐēŅ€Ņ‹Ņ‚ŅŒ Ņ„Đ¸ĐģŅŒŅ‚Ņ€Ņ‹ ĐŋĐžĐ¸ŅĐēа", @@ -1298,14 +1304,14 @@ "partner_can_access": "{partner} иĐŧĐĩĐĩŅ‚ Đ´ĐžŅŅ‚ŅƒĐŋ", "partner_can_access_assets": "Đ’ŅĐĩ Đ˛Đ°ŅˆĐ¸ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đ¸ и видĐĩОСаĐŋĐ¸ŅĐ¸, ĐēŅ€ĐžĐŧĐĩ Ņ‚ĐĩŅ…, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ ĐŊĐ°Ņ…ĐžĐ´ŅŅ‚ŅŅ в ĐŅ€Ņ…Đ¸Đ˛Đĩ и ĐšĐžŅ€ĐˇĐ¸ĐŊĐĩ", "partner_can_access_location": "МĐĩŅŅ‚ĐžĐŋĐžĐģĐžĐļĐĩĐŊиĐĩ, ĐŗĐ´Đĩ ĐąŅ‹Đģи ŅĐ´ĐĩĐģаĐŊŅ‹ Đ˛Đ°ŅˆĐ¸ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đ¸", - "partner_list_user_photos": "Đ¤ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đ¸ {user}", + "partner_list_user_photos": "Đ¤ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đ¸ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ {user}", "partner_list_view_all": "ĐŸĐžŅĐŧĐžŅ‚Ņ€ĐĩŅ‚ŅŒ Đ˛ŅĐĩ", - "partner_page_empty_message": "ĐŖ Đ˛Đ°ŅˆĐĩĐŗĐž ĐŋĐ°Ņ€Ņ‚ĐŊŅ‘Ņ€Đ° Đĩ҉Đĩ ĐŊĐĩŅ‚ Đ´ĐžŅŅ‚ŅƒĐŋа Đē Đ˛Đ°ŅˆĐ¸Đŧ Ņ„ĐžŅ‚Đž", + "partner_page_empty_message": "ĐŖ Đ˛Đ°ŅˆĐĩĐŗĐž ĐŋĐ°Ņ€Ņ‚ĐŊŅ‘Ņ€Đ° Đĩ҉Đĩ ĐŊĐĩŅ‚ Đ´ĐžŅŅ‚ŅƒĐŋа Đē Đ˛Đ°ŅˆĐ¸Đŧ Ņ„ĐžŅ‚Đž.", "partner_page_no_more_users": "Đ’Ņ‹ĐąŅ€Đ°ĐŊŅ‹ Đ˛ŅĐĩ Đ´ĐžŅŅ‚ŅƒĐŋĐŊŅ‹Đĩ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģи", "partner_page_partner_add_failed": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ Đ´ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ ĐŋĐ°Ņ€Ņ‚ĐŊŅ‘Ņ€Đ°", "partner_page_select_partner": "Đ’Ņ‹ĐąŅ€Đ°Ņ‚ŅŒ ĐŋĐ°Ņ€Ņ‚ĐŊŅ‘Ņ€Đ°", "partner_page_shared_to_title": "ПодĐĩĐģĐ¸Ņ‚ŅŒŅŅ ҁ...", - "partner_page_stop_sharing_content": "{} йОĐģҌ҈Đĩ ĐŊĐĩ ҁĐŧĐžĐļĐĩŅ‚ ĐŋĐžĐģŅƒŅ‡Đ¸Ņ‚ŅŒ Đ´ĐžŅŅ‚ŅƒĐŋ Đē Đ˛Đ°ŅˆĐ¸Đŧ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸ŅĐŧ", + "partner_page_stop_sharing_content": "{} йОĐģҌ҈Đĩ ĐŊĐĩ ҁĐŧĐžĐļĐĩŅ‚ ĐŋĐžĐģŅƒŅ‡Đ¸Ņ‚ŅŒ Đ´ĐžŅŅ‚ŅƒĐŋ Đē Đ˛Đ°ŅˆĐ¸Đŧ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸ŅĐŧ.", "partner_sharing": "ХОвĐŧĐĩҁ҂ĐŊĐžĐĩ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°ĐŊиĐĩ", "partners": "ĐŸĐ°Ņ€Ņ‚ĐŊґҀҋ", "password": "ĐŸĐ°Ņ€ĐžĐģҌ", @@ -1341,7 +1347,7 @@ "permission_onboarding_permission_denied": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ ĐŋĐžĐģŅƒŅ‡Đ¸Ņ‚ŅŒ Đ´ĐžŅŅ‚ŅƒĐŋ. Đ§Ņ‚ĐžĐąŅ‹ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ, Ņ€Đ°ĐˇŅ€ĐĩŅˆĐ¸Ņ‚Đĩ Đ´ĐžŅŅ‚ŅƒĐŋ Đē \"Đ¤ĐžŅ‚Đž и видĐĩĐž\" в ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēĐ°Ņ….", "permission_onboarding_permission_granted": "Đ”ĐžŅŅ‚ŅƒĐŋ ĐŋĐžĐģŅƒŅ‡ĐĩĐŊ! Đ’ŅŅ‘ ĐŗĐžŅ‚ĐžĐ˛Đž.", "permission_onboarding_permission_limited": "Đ”ĐžŅŅ‚ŅƒĐŋ Đē Ņ„Đ°ĐšĐģаĐŧ ĐžĐŗŅ€Đ°ĐŊĐ¸Ņ‡ĐĩĐŊ. Đ§Ņ‚ĐžĐąŅ‹ Immich ĐŧĐžĐŗ ŅĐžĐˇĐ´Đ°Đ˛Đ°Ņ‚ŅŒ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊŅ‹Đĩ ĐēĐžĐŋии и ҃ĐŋŅ€Đ°Đ˛ĐģŅŅ‚ŅŒ Đ˛Đ°ŅˆĐĩĐš ĐŗĐ°ĐģĐĩŅ€ĐĩĐĩĐš, ĐŋĐžĐļаĐģŅƒĐšŅŅ‚Đ°, ĐŋŅ€ĐĩĐ´ĐžŅŅ‚Đ°Đ˛ŅŒŅ‚Đĩ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸ŅŽ Ņ€Đ°ĐˇŅ€Đĩ҈ĐĩĐŊиĐĩ ĐŊа Đ´ĐžŅŅ‚ŅƒĐŋ Đē \"Đ¤ĐžŅ‚Đž и видĐĩĐž\" в ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēĐ°Ņ….", - "permission_onboarding_request": "ĐŸŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸ŅŽ ĐŊĐĩĐžĐąŅ…ĐžĐ´Đ¸ĐŧĐž Ņ€Đ°ĐˇŅ€Đĩ҈ĐĩĐŊиĐĩ ĐŊа Đ´ĐžŅŅ‚ŅƒĐŋ Đē Đ˛Đ°ŅˆĐ¸Đŧ Ņ„ĐžŅ‚Đž и видĐĩĐž", + "permission_onboarding_request": "ĐŸŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸ŅŽ ĐŊĐĩĐžĐąŅ…ĐžĐ´Đ¸ĐŧĐž Ņ€Đ°ĐˇŅ€Đĩ҈ĐĩĐŊиĐĩ ĐŊа Đ´ĐžŅŅ‚ŅƒĐŋ Đē Đ˛Đ°ŅˆĐ¸Đŧ Ņ„ĐžŅ‚Đž и видĐĩĐž.", "person": "ЧĐĩĐģОвĐĩĐē", "person_birthdate": "Đ”Đ°Ņ‚Đ° Ņ€ĐžĐļĐ´ĐĩĐŊĐ¸Ņ: {date}", "person_hidden": "{name}{hidden, select, true { (ҁĐēҀҋ҂)} other {}}", @@ -1510,7 +1516,7 @@ "search_filter_date_title": "Đ’Ņ‹ĐąĐĩŅ€Đ¸Ņ‚Đĩ ĐŋŅ€ĐžĐŧĐĩĐļŅƒŅ‚ĐžĐē", "search_filter_display_option_not_in_album": "НĐĩ в аĐģŅŒĐąĐžĐŧĐĩ", "search_filter_display_options": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи ĐžŅ‚ĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ", - "search_filter_filename": "Search by file name", + "search_filter_filename": "ĐŸĐžĐ¸ŅĐē ĐŋĐž иĐŧĐĩĐŊи Ņ„Đ°ĐšĐģа", "search_filter_location": "МĐĩŅŅ‚Đž", "search_filter_location_title": "Đ’Ņ‹ĐąĐĩŅ€Đ¸Ņ‚Đĩ ĐŧĐĩŅŅ‚Đž", "search_filter_media_type": "ĐĸиĐŋ Ņ„Đ°ĐšĐģа", @@ -1518,10 +1524,10 @@ "search_filter_people_title": "Đ’Ņ‹ĐąĐĩŅ€Đ¸Ņ‚Đĩ ĐģŅŽĐ´ĐĩĐš", "search_for": "ĐŸĐžĐ¸ŅĐē ĐŋĐž", "search_for_existing_person": "ĐŸĐžĐ¸ŅĐē ŅŅƒŅ‰ĐĩŅŅ‚Đ˛ŅƒŅŽŅ‰ĐĩĐŗĐž ҇ĐĩĐģОвĐĩĐēа", - "search_no_more_result": "No more results", + "search_no_more_result": "БоĐģҌ҈Đĩ Ņ€ĐĩĐˇŅƒĐģŅŒŅ‚Đ°Ņ‚ĐžĐ˛ ĐŊĐĩŅ‚", "search_no_people": "НĐĩŅ‚ ĐģŅŽĐ´ĐĩĐš", "search_no_people_named": "НĐĩŅ‚ ĐģŅŽĐ´ĐĩĐš ҁ иĐŧĐĩĐŊĐĩĐŧ \"{name}\"", - "search_no_result": "No results found, try a different search term or combination", + "search_no_result": "ĐĐ¸Ņ‡ĐĩĐŗĐž ĐŊĐĩ ĐŊаКдĐĩĐŊĐž, ĐŋĐžĐŋŅ€ĐžĐąŅƒĐšŅ‚Đĩ иСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ĐŋĐžĐ¸ŅĐēĐžĐ˛Ņ‹Đš СаĐŋŅ€ĐžŅ", "search_options": "ĐŸĐ°Ņ€Đ°ĐŧĐĩ҂Ҁҋ ĐŋĐžĐ¸ŅĐēа", "search_page_categories": "ĐšĐ°Ņ‚ĐĩĐŗĐžŅ€Đ¸Đ¸", "search_page_motion_photos": "ДиĐŊаĐŧĐ¸Ņ‡ĐĩҁĐēиĐĩ Ņ„ĐžŅ‚Đž", @@ -1538,9 +1544,9 @@ "search_places": "ĐŸĐžĐ¸ŅĐē ĐŧĐĩҁ҂", "search_rating": "ĐŸĐžĐ¸ŅĐē ĐŋĐž Ņ€ĐĩĐšŅ‚Đ¸ĐŊĐŗŅƒ...", "search_result_page_new_search_hint": "ĐĐžĐ˛Ņ‹Đš ĐŋĐžĐ¸ŅĐē", - "search_settings": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи ĐŋĐžĐ¸ŅĐēа", + "search_settings": "ĐŸĐžĐ¸ŅĐē ĐŊĐ°ŅŅ‚Ņ€ĐžĐĩĐē", "search_state": "ĐŸĐžĐ¸ŅĐē Ņ€ĐĩĐŗĐ¸ĐžĐŊа...", - "search_suggestion_list_smart_search_hint_1": "ИĐŊŅ‚ĐĩĐģĐģĐĩĐēŅ‚ŅƒĐ°ĐģҌĐŊŅ‹Đš ĐŋĐžĐ¸ŅĐē вĐēĐģŅŽŅ‡ĐĩĐŊ ĐŋĐž ҃ĐŧĐžĐģŅ‡Đ°ĐŊĐ¸ŅŽ, Đ´ĐģŅ ĐŋĐžĐ¸ŅĐēа ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐŊҋ҅ Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐšŅ‚Đĩ ҁĐŋĐĩŅ†Đ¸Đ°ĐģҌĐŊŅ‹Đš ŅĐ¸ĐŊŅ‚Đ°ĐēŅĐ¸Ņ", + "search_suggestion_list_smart_search_hint_1": "ИĐŊŅ‚ĐĩĐģĐģĐĩĐēŅ‚ŅƒĐ°ĐģҌĐŊŅ‹Đš ĐŋĐžĐ¸ŅĐē вĐēĐģŅŽŅ‡ĐĩĐŊ ĐŋĐž ҃ĐŧĐžĐģŅ‡Đ°ĐŊĐ¸ŅŽ, Đ´ĐģŅ ĐŋĐžĐ¸ŅĐēа ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐŊҋ҅ Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐšŅ‚Đĩ ҁĐŋĐĩŅ†Đ¸Đ°ĐģҌĐŊŅ‹Đš ŅĐ¸ĐŊŅ‚Đ°ĐēŅĐ¸Ņ ", "search_suggestion_list_smart_search_hint_2": "m:Đ˛Đ°Ņˆ-ĐŋĐžĐ¸ŅĐēĐžĐ˛Ņ‹Đš-СаĐŋŅ€ĐžŅ", "search_tags": "ĐŸĐžĐ¸ŅĐē ĐŋĐž Ņ‚ĐĩĐŗĐ°Đŧ...", "search_timezone": "ĐŸĐžĐ¸ŅĐē Ņ‡Đ°ŅĐžĐ˛ĐžĐŗĐž ĐŋĐžŅŅĐ°...", @@ -1581,10 +1587,10 @@ "set_date_of_birth": "ĐŖŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ Đ´Đ°Ņ‚Ņƒ Ņ€ĐžĐļĐ´ĐĩĐŊĐ¸Ņ", "set_profile_picture": "ĐŖŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиĐĩ ĐŋŅ€ĐžŅ„Đ¸ĐģŅ", "set_slideshow_to_fullscreen": "ПĐĩŅ€ĐĩвĐĩĐ´Đ¸Ņ‚Đĩ ҁĐģаКд-ŅˆĐžŅƒ в ĐŋĐžĐģĐŊĐžŅĐēŅ€Đ°ĐŊĐŊŅ‹Đš Ņ€ĐĩĐļиĐŧ", - "setting_image_viewer_help": "ĐŸŅ€Đ¸ ĐŋŅ€ĐžŅĐŧĐžŅ‚Ņ€Đĩ Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ ҁĐŋĐĩŅ€Đ˛Đ° ĐˇĐ°ĐŗŅ€ŅƒĐļаĐĩŅ‚ŅŅ ĐŧиĐŊĐ¸Đ°Ņ‚ŅŽŅ€Đ°, ĐˇĐ°Ņ‚ĐĩĐŧ \n҃ĐŧĐĩĐŊҌ҈ĐĩĐŊĐŊĐžĐĩ Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиĐĩ ҁҀĐĩĐ´ĐŊĐĩĐŗĐž ĐēĐ°Ņ‡ĐĩŅŅ‚Đ˛Đ° (ĐĩҁĐģи вĐēĐģŅŽŅ‡ĐĩĐŊĐž), а ĐˇĐ°Ņ‚ĐĩĐŧ ĐžŅ€Đ¸ĐŗĐ¸ĐŊаĐģ (ĐĩҁĐģи вĐēĐģŅŽŅ‡ĐĩĐŊĐž).", - "setting_image_viewer_original_subtitle": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚Đĩ Đ´ĐģŅ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēи Đ¸ŅŅ…ĐžĐ´ĐŊĐžĐŗĐž Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ в ĐŋĐžĐģĐŊĐžĐŧ Ņ€Đ°ĐˇŅ€Đĩ҈ĐĩĐŊии (йОĐģŅŒŅˆĐžĐĩ!).\nĐžŅ‚ĐēĐģŅŽŅ‡Đ¸Ņ‚Đĩ, Ņ‡Ņ‚ĐžĐąŅ‹ ҃ĐŧĐĩĐŊŅŒŅˆĐ¸Ņ‚ŅŒ ĐžĐąŅŠĐĩĐŧ даĐŊĐŊҋ҅ (ĐēаĐē ҁĐĩŅ‚Đ¸, Ņ‚Đ°Đē и ĐēŅŅˆĐ° ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đ°).", + "setting_image_viewer_help": "ĐŸŅ€Đ¸ ĐŋŅ€ĐžŅĐŧĐžŅ‚Ņ€Đĩ Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ ҁĐŋĐĩŅ€Đ˛Đ° ĐˇĐ°ĐŗŅ€ŅƒĐļаĐĩŅ‚ŅŅ ĐŧиĐŊĐ¸Đ°Ņ‚ŅŽŅ€Đ°, ĐˇĐ°Ņ‚ĐĩĐŧ ҃ĐŧĐĩĐŊҌ҈ĐĩĐŊĐŊĐžĐĩ Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиĐĩ ҁҀĐĩĐ´ĐŊĐĩĐŗĐž ĐēĐ°Ņ‡ĐĩŅŅ‚Đ˛Đ° (ĐĩҁĐģи вĐēĐģŅŽŅ‡ĐĩĐŊĐž), а ĐˇĐ°Ņ‚ĐĩĐŧ ĐžŅ€Đ¸ĐŗĐ¸ĐŊаĐģ (ĐĩҁĐģи вĐēĐģŅŽŅ‡ĐĩĐŊĐž).", + "setting_image_viewer_original_subtitle": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚Đĩ Đ´ĐģŅ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēи Đ¸ŅŅ…ĐžĐ´ĐŊĐžĐŗĐž Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ в ĐŋĐžĐģĐŊĐžĐŧ Ņ€Đ°ĐˇŅ€Đĩ҈ĐĩĐŊии (йОĐģŅŒŅˆĐžĐĩ!). ĐžŅ‚ĐēĐģŅŽŅ‡Đ¸Ņ‚Đĩ Đ´ĐģŅ ҃ĐŧĐĩĐŊҌ҈ĐĩĐŊĐ¸Ņ ĐžĐąŅŠŅ‘Đŧа даĐŊĐŊҋ҅ (ĐēаĐē ҁĐĩŅ‚Đ¸, Ņ‚Đ°Đē и ĐēŅŅˆĐ° ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đ°).", "setting_image_viewer_original_title": "Đ—Đ°ĐŗŅ€ŅƒĐļĐ°Ņ‚ŅŒ Đ¸ŅŅ…ĐžĐ´ĐŊĐžĐĩ Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиĐĩ", - "setting_image_viewer_preview_subtitle": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚Đĩ Đ´ĐģŅ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēи Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ ҁҀĐĩĐ´ĐŊĐĩĐŗĐž Ņ€Đ°ĐˇŅ€Đĩ҈ĐĩĐŊĐ¸Ņ.\nĐžŅ‚ĐēĐģŅŽŅ‡Đ¸Ņ‚Đĩ, Ņ‡Ņ‚ĐžĐąŅ‹ ĐˇĐ°ĐŗŅ€ŅƒĐļĐ°Ņ‚ŅŒ Ņ‚ĐžĐģҌĐēĐž ĐžŅ€Đ¸ĐŗĐ¸ĐŊаĐģ иĐģи ĐŧиĐŊĐ¸Đ°Ņ‚ŅŽŅ€Ņƒ.", + "setting_image_viewer_preview_subtitle": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚Đĩ Đ´ĐģŅ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēи Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ ҁҀĐĩĐ´ĐŊĐĩĐŗĐž Ņ€Đ°ĐˇŅ€Đĩ҈ĐĩĐŊĐ¸Ņ. ĐžŅ‚ĐēĐģŅŽŅ‡Đ¸Ņ‚Đĩ, Ņ‡Ņ‚ĐžĐąŅ‹ ĐˇĐ°ĐŗŅ€ŅƒĐļĐ°Ņ‚ŅŒ Ņ‚ĐžĐģҌĐēĐž ĐžŅ€Đ¸ĐŗĐ¸ĐŊаĐģ иĐģи ĐŧиĐŊĐ¸Đ°Ņ‚ŅŽŅ€Ņƒ.", "setting_image_viewer_preview_title": "Đ—Đ°ĐŗŅ€ŅƒĐļĐ°Ņ‚ŅŒ ҃ĐŧĐĩĐŊҌ҈ĐĩĐŊĐŊĐžĐĩ Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиĐĩ", "setting_image_viewer_title": "Đ˜ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ", "setting_languages_apply": "ĐŸŅ€Đ¸ĐŧĐĩĐŊĐ¸Ņ‚ŅŒ", @@ -1602,7 +1608,7 @@ "setting_notifications_total_progress_subtitle": "ĐžĐąŅ‰Đ¸Đš ĐŋŅ€ĐžĐŗŅ€Đĩҁҁ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēи (Đ˛Ņ‹ĐŋĐžĐģĐŊĐĩĐŊĐž/Đ˛ŅĐĩĐŗĐž ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛)", "setting_notifications_total_progress_title": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ ĐžĐąŅ‰Đ¸Đš ĐŋŅ€ĐžĐŗŅ€Đĩҁҁ Ņ„ĐžĐŊĐžĐ˛ĐžĐŗĐž Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ", "setting_video_viewer_looping_title": "ĐĻиĐēĐģĐ¸Ņ‡ĐĩҁĐēĐžĐĩ Đ˛ĐžŅĐŋŅ€ĐžĐ¸ĐˇĐ˛ĐĩĐ´ĐĩĐŊиĐĩ", - "setting_video_viewer_original_video_subtitle": "ĐŸŅ€Đ¸ Đ˛ĐžŅĐŋŅ€ĐžĐ¸ĐˇĐ˛ĐĩĐ´ĐĩĐŊии видĐĩĐž ҁ ҁĐĩŅ€Đ˛ĐĩŅ€Đ° ĐˇĐ°ĐŗŅ€ŅƒĐļĐ°Ņ‚ŅŒ ĐžŅ€Đ¸ĐŗĐ¸ĐŊаĐģ, даĐļĐĩ ĐĩҁĐģи Đ´ĐžŅŅ‚ŅƒĐŋĐŊа Ņ‚Ņ€Đ°ĐŊҁĐēĐžĐ´Đ¸Ņ€ĐžĐ˛Đ°ĐŊĐŊĐ°Ņ вĐĩŅ€ŅĐ¸Ņ. МоĐļĐĩŅ‚ ĐŋŅ€Đ¸Đ˛ĐĩŅŅ‚Đ¸ Đē ĐąŅƒŅ„ĐĩŅ€Đ¸ĐˇĐ°Ņ†Đ¸Đ¸. НĐĩ вĐģĐ¸ŅĐĩŅ‚ ĐŊа ĐģĐžĐēаĐģҌĐŊŅ‹Đĩ видĐĩĐž", + "setting_video_viewer_original_video_subtitle": "ĐŸŅ€Đ¸ Đ˛ĐžŅĐŋŅ€ĐžĐ¸ĐˇĐ˛ĐĩĐ´ĐĩĐŊии видĐĩĐž ҁ ҁĐĩŅ€Đ˛ĐĩŅ€Đ° ĐˇĐ°ĐŗŅ€ŅƒĐļĐ°Ņ‚ŅŒ ĐžŅ€Đ¸ĐŗĐ¸ĐŊаĐģ, даĐļĐĩ ĐĩҁĐģи Đ´ĐžŅŅ‚ŅƒĐŋĐŊа Ņ‚Ņ€Đ°ĐŊҁĐēĐžĐ´Đ¸Ņ€ĐžĐ˛Đ°ĐŊĐŊĐ°Ņ вĐĩŅ€ŅĐ¸Ņ. МоĐļĐĩŅ‚ ĐŋŅ€Đ¸Đ˛ĐĩŅŅ‚Đ¸ Đē ĐąŅƒŅ„ĐĩŅ€Đ¸ĐˇĐ°Ņ†Đ¸Đ¸. ВидĐĩĐž, Đ´ĐžŅŅ‚ŅƒĐŋĐŊŅ‹Đĩ ĐģĐžĐēаĐģҌĐŊĐž, Đ˛ŅĐĩĐŗĐ´Đ° Đ˛ĐžŅĐŋŅ€ĐžĐ¸ĐˇĐ˛ĐžĐ´ŅŅ‚ŅŅ в Đ¸ŅŅ…ĐžĐ´ĐŊĐžĐŧ ĐēĐ°Ņ‡ĐĩŅŅ‚Đ˛Đĩ.", "setting_video_viewer_original_video_title": "ĐĸĐžĐģҌĐēĐž ĐžŅ€Đ¸ĐŗĐ¸ĐŊаĐģҌĐŊĐžĐĩ видĐĩĐž", "settings": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи", "settings_require_restart": "ПоĐļаĐģŅƒĐšŅŅ‚Đ°, ĐŋĐĩŅ€ĐĩСаĐŋŅƒŅŅ‚Đ¸Ņ‚Đĩ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ, Ņ‡Ņ‚ĐžĐąŅ‹ иСĐŧĐĩĐŊĐĩĐŊĐ¸Ņ Đ˛ŅŅ‚ŅƒĐŋиĐģи в ŅĐ¸Đģ҃", @@ -1750,7 +1756,7 @@ "theme_selection_description": "ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐĩҁĐēи ŅƒŅŅ‚Đ°ĐŊавĐģĐ¸Đ˛Đ°Ņ‚ŅŒ Ņ‚ĐĩĐŧ҃ в ĐˇĐ°Đ˛Đ¸ŅĐ¸ĐŧĐžŅŅ‚Đ¸ ĐžŅ‚ ŅĐ¸ŅŅ‚ĐĩĐŧĐŊҋ҅ ĐŊĐ°ŅŅ‚Ņ€ĐžĐĩĐē Đ˛Đ°ŅˆĐĩĐŗĐž ĐąŅ€Đ°ŅƒĐˇĐĩŅ€Đ°", "theme_setting_asset_list_storage_indicator_title": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ иĐŊдиĐēĐ°Ņ‚ĐžŅ€ Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đ° ĐŊа ĐŋĐģĐ¸Ņ‚ĐēĐ°Ņ… ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛", "theme_setting_asset_list_tiles_per_row_title": "КоĐģĐ¸Ņ‡ĐĩŅŅ‚Đ˛Đž ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛ в ŅŅ‚Ņ€ĐžĐēĐĩ ({})", - "theme_setting_colorful_interface_subtitle": "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ ĐžŅ‚Ņ‚ĐĩĐŊĐžĐē Đē Ņ„ĐžĐŊ҃", + "theme_setting_colorful_interface_subtitle": "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ ĐžŅ‚Ņ‚ĐĩĐŊĐžĐē Đē Ņ„ĐžĐŊ҃.", "theme_setting_colorful_interface_title": "ĐĻвĐĩŅ‚ Ņ„ĐžĐŊа", "theme_setting_image_viewer_quality_subtitle": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēа ĐēĐ°Ņ‡ĐĩŅŅ‚Đ˛Đ° ĐŋŅ€ĐžŅĐŧĐžŅ‚Ņ€Đ° Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ", "theme_setting_image_viewer_quality_title": "ĐšĐ°Ņ‡ĐĩŅŅ‚Đ˛Đž ĐŋŅ€ĐžŅĐŧĐžŅ‚Ņ€Đ° Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиК", @@ -1783,8 +1789,8 @@ "trash_emptied": "ĐšĐžŅ€ĐˇĐ¸ĐŊа ĐžŅ‡Đ¸Ņ‰ĐĩĐŊа", "trash_no_results_message": "ЗдĐĩҁҌ ĐąŅƒĐ´ŅƒŅ‚ ĐžŅ‚ĐžĐąŅ€Đ°ĐļĐ°Ņ‚ŅŒŅŅ ŅƒĐ´Đ°ĐģŅ‘ĐŊĐŊŅ‹Đĩ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đ¸ и видĐĩĐž.", "trash_page_delete_all": "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ Đ˛ŅĐĩ", - "trash_page_empty_trash_dialog_content": "ĐžŅ‡Đ¸ŅŅ‚Đ¸Ņ‚ŅŒ ĐēĐžŅ€ĐˇĐ¸ĐŊ҃? Đ­Ņ‚Đ¸ Ņ„Đ°ĐšĐģŅ‹ ĐąŅƒĐ´ŅƒŅ‚ ĐŊĐ°Đ˛ŅĐĩĐŗĐ´Đ° ŅƒĐ´Đ°ĐģĐĩĐŊŅ‹ иС Immich.", - "trash_page_info": "Đ­ĐģĐĩĐŧĐĩĐŊ҂ҋ в ĐēĐžŅ€ĐˇĐ¸ĐŊĐĩ ĐąŅƒĐ´ŅƒŅ‚ ĐžĐēĐžĐŊŅ‡Đ°Ņ‚ĐĩĐģҌĐŊĐž ŅƒĐ´Đ°ĐģĐĩĐŊŅ‹ ҇ĐĩŅ€ĐĩС {} Đ´ĐŊĐĩĐš", + "trash_page_empty_trash_dialog_content": "ĐžŅ‡Đ¸ŅŅ‚Đ¸Ņ‚ŅŒ ĐēĐžŅ€ĐˇĐ¸ĐŊ҃? ĐžĐąŅŠĐĩĐē҂ҋ в ĐŊĐĩĐš ĐąŅƒĐ´ŅƒŅ‚ ĐŊĐ°Đ˛ŅĐĩĐŗĐ´Đ° ŅƒĐ´Đ°ĐģĐĩĐŊŅ‹ иС Immich.", + "trash_page_info": "ĐžĐąŅŠĐĩĐē҂ҋ в ĐēĐžŅ€ĐˇĐ¸ĐŊĐĩ ĐąŅƒĐ´ŅƒŅ‚ ĐžĐēĐžĐŊŅ‡Đ°Ņ‚ĐĩĐģҌĐŊĐž ŅƒĐ´Đ°ĐģĐĩĐŊŅ‹ ҇ĐĩŅ€ĐĩС {} Đ´ĐŊĐĩĐš", "trash_page_no_assets": "ĐšĐžŅ€ĐˇĐ¸ĐŊа ĐŋŅƒŅŅ‚Đ°", "trash_page_restore_all": "Đ’ĐžŅŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ Đ˛ŅĐĩ", "trash_page_select_assets_btn": "Đ’Ņ‹ĐąŅ€Đ°ĐŊĐŊŅ‹Đĩ ĐžĐąŅŠĐĩĐē҂ҋ", @@ -1817,7 +1823,7 @@ "updated_password": "ĐŸĐ°Ņ€ĐžĐģҌ ОйĐŊОвĐģŅ‘ĐŊ", "upload": "Đ—Đ°ĐŗŅ€ŅƒĐˇĐ¸Ņ‚ŅŒ", "upload_concurrency": "ĐŸĐ°Ņ€Đ°ĐģĐģĐĩĐģҌĐŊĐžŅŅ‚ŅŒ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēи", - "upload_dialog_info": "ĐĨĐžŅ‚Đ¸Ņ‚Đĩ ŅĐžĐˇĐ´Đ°Ņ‚ŅŒ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊŅƒŅŽ ĐēĐžĐŋĐ¸ŅŽ Đ˛Ņ‹ĐąŅ€Đ°ĐŊĐŊҋ҅ ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛ ĐŊа ҁĐĩŅ€Đ˛ĐĩŅ€Đĩ?", + "upload_dialog_info": "ĐĨĐžŅ‚Đ¸Ņ‚Đĩ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐ¸Ņ‚ŅŒ Đ˛Ņ‹ĐąŅ€Đ°ĐŊĐŊŅ‹Đĩ ĐžĐąŅŠĐĩĐē҂ҋ ĐŊа ҁĐĩŅ€Đ˛ĐĩŅ€?", "upload_dialog_title": "Đ—Đ°ĐŗŅ€ŅƒĐˇĐ¸Ņ‚ŅŒ ĐžĐąŅŠĐĩĐēŅ‚", "upload_errors": "Đ—Đ°ĐŗŅ€ŅƒĐˇĐēа СавĐĩŅ€ŅˆĐĩĐŊа ҁ {count, plural, one {# ĐžŅˆĐ¸ĐąĐēОК} other {# ĐžŅˆĐ¸ĐąĐēаĐŧи}}, ОйĐŊĐžĐ˛Đ¸Ņ‚Đĩ ŅŅ‚Ņ€Đ°ĐŊĐ¸Ņ†Ņƒ, Ņ‡Ņ‚ĐžĐąŅ‹ ŅƒĐ˛Đ¸Đ´ĐĩŅ‚ŅŒ ĐŊĐžĐ˛Ņ‹Đĩ ĐˇĐ°ĐŗŅ€ŅƒĐļĐĩĐŊĐŊŅ‹Đĩ Ņ€ĐĩŅŅƒŅ€ŅŅ‹.", "upload_progress": "ĐžŅŅ‚Đ°ĐģĐžŅŅŒ {remaining, number} - ĐžĐąŅ€Đ°ĐąĐžŅ‚Đ°ĐŊĐž {processed, number}/{total, number}", @@ -1849,11 +1855,11 @@ "variables": "ПĐĩŅ€ĐĩĐŧĐĩĐŊĐŊŅ‹Đĩ", "version": "ВĐĩŅ€ŅĐ¸Ņ", "version_announcement_closing": "ĐĸвОК Đ´Ņ€ŅƒĐŗ АĐģĐĩĐēҁ", - "version_announcement_message": "Đ—Đ´Ņ€Đ°Đ˛ŅŅ‚Đ˛ŅƒĐšŅ‚Đĩ! Đ”ĐžŅŅ‚ŅƒĐŋĐŊа ĐŊĐžĐ˛Đ°Ņ вĐĩŅ€ŅĐ¸Ņ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸Ņ. ПоĐļаĐģŅƒĐšŅŅ‚Đ°, ĐŋŅ€ĐžŅ‡Ņ‚Đ¸Ņ‚Đĩ СаĐŧĐĩŅ‚Đēи Đē Đ˛Ņ‹Đŋ҃ҁĐē҃ и ŅƒĐąĐĩĐ´Đ¸Ņ‚ĐĩҁҌ, Ņ‡Ņ‚Đž Đ˛Đ°ŅˆĐ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁҋ docker-compose.yml и .env аĐēŅ‚ŅƒĐ°ĐģҌĐŊŅ‹, Ņ‡Ņ‚ĐžĐąŅ‹ иСйĐĩĐļĐ°Ņ‚ŅŒ ĐžŅˆĐ¸ĐąĐžĐē в ĐēĐžĐŊŅ„Đ¸ĐŗŅƒŅ€Đ°Ņ†Đ¸Đ¸, ĐžŅĐžĐąĐĩĐŊĐŊĐž ĐĩҁĐģи Đ˛Ņ‹ Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐĩŅ‚Đĩ WatchTower иĐģи Đ´Ņ€ŅƒĐŗĐžĐš ĐŧĐĩŅ…Đ°ĐŊиСĐŧ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐĩҁĐēĐžĐŗĐž ОйĐŊОвĐģĐĩĐŊĐ¸Ņ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸Ņ.", + "version_announcement_message": "Đ—Đ´Ņ€Đ°Đ˛ŅŅ‚Đ˛ŅƒĐšŅ‚Đĩ! Đ”ĐžŅŅ‚ŅƒĐŋĐŊа ĐŊĐžĐ˛Đ°Ņ вĐĩŅ€ŅĐ¸Ņ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸Ņ. ПоĐļаĐģŅƒĐšŅŅ‚Đ°, ĐŋŅ€ĐžŅ‡Ņ‚Đ¸Ņ‚Đĩ СаĐŧĐĩŅ‚Đēи Đē Đ˛Ņ‹Đŋ҃ҁĐē҃ и ŅƒĐąĐĩĐ´Đ¸Ņ‚ĐĩҁҌ, Ņ‡Ņ‚Đž ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁҋ ĐēĐžĐŊŅ„Đ¸ĐŗŅƒŅ€Đ°Ņ†Đ¸Đ¸ аĐēŅ‚ŅƒĐ°ĐģҌĐŊŅ‹, Đ´Đ°ĐąŅ‹ иСйĐĩĐļĐ°Ņ‚ŅŒ ĐžŅˆĐ¸ĐąĐžĐē, ĐžŅĐžĐąĐĩĐŊĐŊĐž ĐĩҁĐģи Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐĩŅ‚ŅŅ WatchTower иĐģи Đ´Ņ€ŅƒĐŗĐžĐš ĐŧĐĩŅ…Đ°ĐŊиСĐŧ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐĩҁĐēĐžĐŗĐž ОйĐŊОвĐģĐĩĐŊĐ¸Ņ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸Ņ.", "version_announcement_overlay_release_notes": "ĐŋŅ€Đ¸ĐŧĐĩŅ‡Đ°ĐŊĐ¸Ņ Đē Đ˛Ņ‹Đŋ҃ҁĐē҃", "version_announcement_overlay_text_1": "ĐŸŅ€Đ¸Đ˛ĐĩŅ‚, Đ´Ņ€ŅƒĐŗ! Đ’Ņ‹ŅˆĐģа ĐŊĐžĐ˛Đ°Ņ вĐĩŅ€ŅĐ¸Ņ", - "version_announcement_overlay_text_2": "ĐŋĐžĐļаĐģŅƒĐšŅŅ‚Đ°, ĐŋĐžŅĐĩŅ‚Đ¸Ņ‚Đĩ", - "version_announcement_overlay_text_3": " и ŅƒĐąĐĩĐ´Đ¸Ņ‚ĐĩҁҌ, Ņ‡Ņ‚Đž Đ˛Đ°ŅˆĐ¸ ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēи docker-compose и .env ОйĐŊОвĐģĐĩĐŊŅ‹, ĐžŅĐžĐąĐĩĐŊĐŊĐž ĐĩҁĐģи Đ˛Ņ‹ Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐĩŅ‚Đĩ WatchTower иĐģи ĐģŅŽĐąĐžĐš Đ´Ņ€ŅƒĐŗĐžĐš ĐŧĐĩŅ…Đ°ĐŊиСĐŧ, ĐēĐžŅ‚ĐžŅ€Ņ‹Đš Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐĩҁĐēи ОйĐŊОвĐģŅĐĩŅ‚ ҁĐĩŅ€Đ˛ĐĩŅ€.", + "version_announcement_overlay_text_2": "ĐŋĐžĐļаĐģŅƒĐšŅŅ‚Đ°, ĐŋĐžŅĐĩŅ‚Đ¸Ņ‚Đĩ ", + "version_announcement_overlay_text_3": " и ŅƒĐąĐĩĐ´Đ¸Ņ‚ĐĩҁҌ, Ņ‡Ņ‚Đž ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁҋ в docker-compose и .env Ņ„Đ°ĐšĐģĐ°Ņ… аĐēŅ‚ŅƒĐ°ĐģҌĐŊŅ‹, ĐžŅĐžĐąĐĩĐŊĐŊĐž ĐĩҁĐģи Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐĩŅ‚ŅŅ WatchTower иĐģи ĐģŅŽĐąĐžĐš Đ´Ņ€ŅƒĐŗĐžĐš ĐŧĐĩŅ…Đ°ĐŊиСĐŧ Đ´ĐģŅ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐĩҁĐēĐžĐŗĐž ОйĐŊОвĐģĐĩĐŊĐ¸Ņ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиК.", "version_announcement_overlay_title": "Đ”ĐžŅŅ‚ŅƒĐŋĐŊа ĐŊĐžĐ˛Đ°Ņ вĐĩŅ€ŅĐ¸Ņ ҁĐĩŅ€Đ˛ĐĩŅ€Đ° 🎉", "version_history": "Đ˜ŅŅ‚ĐžŅ€Đ¸Ņ вĐĩŅ€ŅĐ¸Đš", "version_history_item": "ВĐĩŅ€ŅĐ¸Ņ {version} ŅƒŅŅ‚Đ°ĐŊОвĐģĐĩĐŊа {date}", diff --git a/i18n/sl.json b/i18n/sl.json index 1839212037..01f62d204e 100644 --- a/i18n/sl.json +++ b/i18n/sl.json @@ -25,7 +25,7 @@ "add_to": "Dodaj vâ€Ļ", "add_to_album": "Dodaj v album", "add_to_album_bottom_sheet_added": "Dodano v {album}", - "add_to_album_bottom_sheet_already_exists": "ÅŊe v {albumu}", + "add_to_album_bottom_sheet_already_exists": "ÅŊe v {album}", "add_to_shared_album": "Dodaj k deljenemu albumu", "add_url": "Dodaj URL", "added_to_archive": "Dodano v arhiv", @@ -39,17 +39,17 @@ "authentication_settings_disable_all": "Ali zares Åželite onemogočiti vse prijavne metode? Prijava bo popolnoma onemogočena.", "authentication_settings_reenable": "Ponovno omogoči z uporabo streÅžniÅĄkega ukaza.", "background_task_job": "Opravila v ozadju", - "backup_database": "Varnostna kopija baze", - "backup_database_enable_description": "Omogoči varnostno kopiranje baze", - "backup_keep_last_amount": "Å tevilo prejÅĄnjih obdrÅžanih varnostnih kopij", - "backup_settings": "Nastavitve varnostnega kopiranja", - "backup_settings_description": "Upravljanje nastavitev varnostnih kopij", + "backup_database": "Ustvari izpis baze podatkov", + "backup_database_enable_description": "Omogoči izpise baze podatkov", + "backup_keep_last_amount": "Å tevilo prejÅĄnjih odlagaliÅĄÄ, ki jih je treba obdrÅžati", + "backup_settings": "Nastavitve izpisa baze podatkov", + "backup_settings_description": "Upravljanje nastavitev izpisa baze podatkov. Opomba: Ta opravila se ne spremljajo in o neuspehu ne boste obveÅĄÄeni.", "check_all": "Označi vse", "cleanup": "ČiÅĄÄenje", "cleared_jobs": "RazčiÅĄÄeno opravilo za: {job}", "config_set_by_file": "Konfiguracija je trenutno nastavljena s konfiguracijsko datoteko", "confirm_delete_library": "Ali ste prepričani, da Åželite izbrisati knjiÅžnico {library}?", - "confirm_delete_library_assets": "Ali ste prepričani, da Åželite izbrisati to knjiÅžnico? To bo iz Immicha izbrisalo {count, plural, one {# contained asset} other {all # vsebovanih virov}} in tega ni moÅžno razveljaviti. Datoteke bodo ostale na disku.", + "confirm_delete_library_assets": "Ali ste prepričani, da Åželite izbrisati to knjiÅžnico? To bo iz Immicha izbrisalo {count, plural, one {# vsebovani vir} two {# vsebovana vira} few {# vsebovane vire} other {vseh # vsebovanih virov}} in tega ni moÅžno razveljaviti. Datoteke bodo ostale na disku.", "confirm_email_below": "Za potrditev vnesite \"{email}\" spodaj", "confirm_reprocess_all_faces": "Ali ste prepričani, da Åželite znova obdelati vse obraze? S tem boste počistili tudi Åže imenovane osebe.", "confirm_user_password_reset": "Ali ste prepričani, da Åželite ponastaviti geslo uporabnika {user}?", @@ -347,7 +347,7 @@ "untracked_files": "Nesledene datoteke", "untracked_files_description": "Tem datotekam aplikacija ne sledi. Lahko so posledica neuspelih premikov, prekinjenih nalaganj ali zaostalih zaradi hroÅĄÄa", "user_cleanup_job": "ČiÅĄÄenje uporabnika", - "user_delete_delay": "Račun in sredstva {user} bodo načrtovani za trajno brisanje čez {delay, plural, one {# day} other {# days}}.", + "user_delete_delay": "Račun in sredstva {user} bodo načrtovani za trajno brisanje čez {delay, plural, one {# dan} other {# dni}}.", "user_delete_delay_settings": "Zamakni izbris", "user_delete_delay_settings_description": "Å tevilo dni po odstranitvi za trajno brisanje uporabnikovega računa in sredstev. Opravilo za brisanje uporabnikov se izvaja ob polnoči, da se preveri, ali so uporabniki pripravljeni na izbris. Spremembe te nastavitve bodo ovrednotene pri naslednji izvedbi.", "user_delete_immediately": "Račun in sredstva uporabnika {user} bodo v čakalni vrsti za trajno brisanje takoj.", @@ -371,6 +371,8 @@ "admin_password": "SkrbniÅĄko geslo", "administration": "Administracija", "advanced": "Napredno", + "advanced_settings_enable_alternate_media_filter_subtitle": "Uporabite to moÅžnost za filtriranje medijev med sinhronizacijo na podlagi alternativnih meril. To poskusite le, če imate teÅžave z aplikacijo, ki zaznava vse albume.", + "advanced_settings_enable_alternate_media_filter_title": "[EKSPERIMENTALNO] Uporabite alternativni filter za sinhronizacijo albuma v napravi", "advanced_settings_log_level_title": "Nivo dnevnika: {}", "advanced_settings_prefer_remote_subtitle": "Nekatere naprave zelo počasi nalagajo sličice iz sredstev v napravi. Aktivirajte to nastavitev, če Åželite namesto tega naloÅžiti oddaljene slike.", "advanced_settings_prefer_remote_title": "Uporabi raje oddaljene slike", @@ -378,12 +380,14 @@ "advanced_settings_proxy_headers_title": "Proxy glave", "advanced_settings_self_signed_ssl_subtitle": "Preskoči preverjanje potrdila SSL za končno točko streÅžnika. Zahtevano za samopodpisana potrdila.", "advanced_settings_self_signed_ssl_title": "Dovoli samopodpisana SSL potrdila", + "advanced_settings_sync_remote_deletions_subtitle": "Samodejno izbriÅĄi ali obnovi sredstvo v tej napravi, ko je to dejanje izvedeno v spletu", + "advanced_settings_sync_remote_deletions_title": "Sinhroniziraj oddaljene izbrise [EKSPERIMENTALNO]", "advanced_settings_tile_subtitle": "Napredne uporabniÅĄke nastavitve", "advanced_settings_troubleshooting_subtitle": "Omogočite dodatne funkcije za odpravljanje teÅžav", "advanced_settings_troubleshooting_title": "Odpravljanje teÅžav", - "age_months": "Starost {months, plural, one {# month} other {# months}}", - "age_year_months": "Starost 1 leto, {months, plural, one {# month} other {# months}}", - "age_years": "{years, plural, other {starost #}}", + "age_months": "Starost {months, plural, one {# mesec} two {# meseca} few {# mesece} other {# mesecev}}", + "age_year_months": "Starost 1 leto, {months, plural, one {# mesec} two {# meseca} few {# mesece} other {# mesecev}}", + "age_years": "{years, plural, one {# leto} two {# leti} few {# leta} other {# let}}", "album_added": "Album dodan", "album_added_notification_setting_description": "Prejmite e-poÅĄtno obvestilo, ko ste dodani v album v skupni rabi", "album_cover_updated": "Naslovnica albuma posodobljena", @@ -400,9 +404,9 @@ "album_remove_user_confirmation": "Ali ste prepričani, da Åželite odstraniti {user}?", "album_share_no_users": "Videti je, da ste ta album dali v skupno rabo z vsemi uporabniki ali pa nimate nobenega uporabnika, s katerim bi ga lahko delili.", "album_thumbnail_card_item": "1 element", - "album_thumbnail_card_items": "{} elementov", - "album_thumbnail_card_shared": "¡ V skupni rabi", - "album_thumbnail_shared_by": "Delil {}", + "album_thumbnail_card_items": "{count, plural, one {# element} two {# elementa} few {# elementi} other {# elementov}}", + "album_thumbnail_card_shared": " ¡ V skupni rabi", + "album_thumbnail_shared_by": "Delil {user}", "album_updated": "Album posodobljen", "album_updated_setting_description": "Prejmite e-poÅĄtno obvestilo, ko ima album v skupni rabi nova sredstva", "album_user_left": "Zapustil {album}", @@ -413,11 +417,11 @@ "album_viewer_appbar_share_err_remove": "Pri odstranjevanju sredstev iz albuma so teÅžave", "album_viewer_appbar_share_err_title": "Naslova albuma ni bilo mogoče spremeniti", "album_viewer_appbar_share_leave": "Zapusti album", - "album_viewer_appbar_share_to": "Deli z", + "album_viewer_appbar_share_to": "Deli s/z", "album_viewer_page_share_add_users": "Dodaj uporabnike", "album_with_link_access": "Omogočite vsem s povezavo ogled fotografij in ljudi v tem albumu.", "albums": "Albumi", - "albums_count": "{count, plural, one {{count, number} Album} other {{count, number} Albumi}}", + "albums_count": "{count, plural, one {{count, number} album} two {{count, number} albuma} few {{count, number} albumi} other {{count, number} albumov}}", "all": "Vse", "all_albums": "Vsi albumi", "all_people": "Vsi ljudje", @@ -427,7 +431,7 @@ "allow_public_user_to_download": "Dovoli javnemu uporabniku prenos", "allow_public_user_to_upload": "Dovolite javnemu uporabniku nalaganje", "alt_text_qr_code": "Slika QR kode", - "anti_clockwise": "V nasprotni smeri urnega kazalca", + "anti_clockwise": "V nasprotni smeri urinega kazalca", "api_key": "API ključ", "api_key_description": "Ta vrednost bo prikazana samo enkrat. Ne pozabite jo kopirati, preden zaprete okno.", "api_key_empty": "Ime ključa API ne sme biti prazno", @@ -440,14 +444,14 @@ "archive": "Arhiv", "archive_or_unarchive_photo": "Arhivirajte ali odstranite fotografijo iz arhiva", "archive_page_no_archived_assets": "Ni arhiviranih sredstev", - "archive_page_title": "Arhiv ({})\n", + "archive_page_title": "Arhiv ({number})", "archive_size": "Velikost arhiva", "archive_size_description": "Konfigurirajte velikost arhiva za prenose (v GiB)", "archived": "Arhivirano", - "archived_count": "{count, plural, other {arhivirano #}}", + "archived_count": "{count, plural, one {# arhiviran} two {# arhivirana} few {# arhivirani} other {# arhiviranih}}", "are_these_the_same_person": "Ali je to ista oseba?", "are_you_sure_to_do_this": "Ste prepričani, da Åželite to narediti?", - "asset_action_delete_err_read_only": "Sredstev samo za branje ni mogoče izbrisati, preskočim\n", + "asset_action_delete_err_read_only": "Sredstev samo za branje ni mogoče izbrisati, preskočim", "asset_action_share_err_offline": "Ni mogoče pridobiti sredstev brez povezave, preskočim", "asset_added_to_album": "Dodano v album", "asset_adding_to_album": "Dodajanje v albumâ€Ļ", @@ -473,23 +477,23 @@ "asset_viewer_settings_subtitle": "Upravljaj nastavitve pregledovalnika galerije", "asset_viewer_settings_title": "Pregledovalnik sredstev", "assets": "Sredstva", - "assets_added_count": "Dodano{count, plural, one {# sredstvo} other {# sredstev}}", - "assets_added_to_album_count": "Dodano{count, plural, one {# sredstvo} other {# sredstev}} v album", - "assets_added_to_name_count": "Dodano {count, plural, one {# sredstvo} other {# sredstev}} v {hasName, select, true {{name}} other {new album}}", - "assets_count": "{count, plural, one {# sredstvo} other {# sredstev}}", - "assets_deleted_permanently": "Å t. za vedno izbrisanih sredstev: {}", - "assets_deleted_permanently_from_server": "Å t. za vedno izbrisanih sredstev iz sreÅžnika Immich: {}", - "assets_moved_to_trash_count": "Premaknjeno {count, plural, one {# sredstev} other {# sredstev}} v smetnjak", - "assets_permanently_deleted_count": "Trajno izbrisano {count, plural, one {# sredstvo} other {# sredstev}}", - "assets_removed_count": "Odstranjeno {count, plural, one {# sredstvo} other {# sredstev}}", - "assets_removed_permanently_from_device": "Å t. za vedno izbrisanih sredstev iz vaÅĄe naprave: {}", + "assets_added_count": "Dodano{count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}}", + "assets_added_to_album_count": "Dodano {count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}} v album", + "assets_added_to_name_count": "Dodano {count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}} v {hasName, select, true {{name}} other {new album}}", + "assets_count": "{count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}}", + "assets_deleted_permanently": "{count, plural, one {# sredstvo trajno izbrisano} two {# sredstvi trajno izbrisani} few {# sredstva trajno izbrisana} other {# sredstev trajno izbrisanih}}", + "assets_deleted_permanently_from_server": "{count, plural, one {# sredstvo trajno izbrisano iz streÅžnika Immich} two {# sredstvi trajno izbrisani iz streÅžnika Immich} few {# sredstva trajno izbrisana iz streÅžnika Immich} other {# sredstev trajno izbrisanih iz streÅžnika Immich}}", + "assets_moved_to_trash_count": "Premaknjeno {count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}} v smetnjak", + "assets_permanently_deleted_count": "Trajno izbrisano {count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}}", + "assets_removed_count": "Odstranjeno {count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}}", + "assets_removed_permanently_from_device": "{count, plural, one {# sredstvo trajno izbrisano iz naprave} two {# sredstvi strajno izbrisani iz naprave} few {# sredstva trajno izbrisana iz naprave} other {# sredstve trajno izbrisanih iz naprave}}", "assets_restore_confirmation": "Ali ste prepričani, da Åželite obnoviti vsa sredstva, ki ste jih odstranili? Tega dejanja ne morete razveljaviti! UpoÅĄtevajte, da sredstev brez povezave ni mogoče obnoviti na ta način.", - "assets_restored_count": "Obnovljeno {count, plural, one {# sredstvo} other {# sredstev}}", - "assets_restored_successfully": "Å t. uspeÅĄno obnovljenih sredstev: {}", - "assets_trashed": "Å t. sredstev premaknjenih v smetnjak: {}", - "assets_trashed_count": "V smetnjak {count, plural, one {# sredstvo} other {# sredstev}}", - "assets_trashed_from_server": "Å t sredstev izbrisanih iz streÅžnika Immich: {}", - "assets_were_part_of_album_count": "{count, plural, one {sredstvo je} other {sredstev je}} Åže del albuma", + "assets_restored_count": "Obnovljeno {count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}}", + "assets_restored_successfully": "{count, plural, one {# sredstvo uspeÅĄno obnovljeno} two {# sredstvi uspeÅĄno obnovljeni} few {# sredstva uspeÅĄno obnovljena} other {# sredstev uspeÅĄno obnovljenih}}", + "assets_trashed": "{count, plural, one {# sredstvo premaknjeno v smetnjak} two {# sredstvi premaknjeni v smetnjak} few {# sredstva premaknjena v smetnjak} other {# sredstev premaknjenih v smetnjak}}", + "assets_trashed_count": "V smetnjak {count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}}", + "assets_trashed_from_server": "{count, plural, one {# sredstvo iz Immich streÅžnika v smetnjak} two {# sredstvi iz Immich streÅžnika v smetnjak} few {# sredstva iz Immich streÅžnika v smetnjak} other {# sredstev iz Immich streÅžnika v smetnjak}}", + "assets_were_part_of_album_count": "{count, plural, one {sredstvo je} two {sredstvi sta} few {sredstva so} other {sredstev je}} Åže del albuma", "authorized_devices": "PooblaÅĄÄene naprave", "automatic_endpoint_switching_subtitle": "PoveÅžite se lokalno prek določenega omreÅžja Wi-Fi, ko je na voljo, in uporabite druge povezave drugje", "automatic_endpoint_switching_title": "Samodejno preklapljanje URL-jev", @@ -497,7 +501,7 @@ "back_close_deselect": "Nazaj, zaprite ali prekličite izbiro", "background_location_permission": "Dovoljenje za iskanje lokacije v ozadju", "background_location_permission_content": "Ko deluje v ozadju mora imeti Immich za zamenjavo omreÅžij, *vedno* dostop do natančne lokacije, da lahko aplikacija prebere ime omreÅžja Wi-Fi", - "backup_album_selection_page_albums_device": "Albumi v napravi ({})", + "backup_album_selection_page_albums_device": "Albumi v napravi ({number})", "backup_album_selection_page_albums_tap": "Tapnite za vključitev, dvakrat tapnite za izključitev", "backup_album_selection_page_assets_scatter": "Sredstva so lahko razprÅĄena po več albumih. Tako je mogoče med postopkom varnostnega kopiranja albume vključiti ali izključiti.", "backup_album_selection_page_select_albums": "Izberi albume", @@ -509,7 +513,7 @@ "backup_background_service_current_upload_notification": "Nalagam {}", "backup_background_service_default_notification": "Preverjam za novimi sredstviâ€Ļ", "backup_background_service_error_title": "Napaka varnostnega kopiranja", - "backup_background_service_in_progress_notification": "Varnostno kopiranje vaÅĄih sredstev ...", + "backup_background_service_in_progress_notification": "Varnostno kopiranje vaÅĄih sredstevâ€Ļ", "backup_background_service_upload_failure_notification": "Nalaganje {} ni uspelo", "backup_controller_page_albums": "Varnostno kopiranje albumov", "backup_controller_page_background_app_refresh_disabled_content": "Omogočite osveÅževanje aplikacij v ozadju v Nastavitve > SploÅĄno > OsveÅžitev aplikacij v ozadju, če Åželite uporabiti varnostno kopiranje v ozadju.", @@ -529,11 +533,11 @@ "backup_controller_page_background_turn_on": "Vklopi storitev v ozadju", "backup_controller_page_background_wifi": "Samo na WiFi", "backup_controller_page_backup": "Varnostna kopija", - "backup_controller_page_backup_selected": "Izbrano", + "backup_controller_page_backup_selected": "Izbrano: ", "backup_controller_page_backup_sub": "Varnostno kopirane fotografije in videoposnetki", - "backup_controller_page_created": "Ustvarjeno: {}", + "backup_controller_page_created": "Ustvarjeno: {date}", "backup_controller_page_desc_backup": "Vklopite varnostno kopiranje v ospredju za samodejno nalaganje novih sredstev na streÅžnik, ko odprete aplikacijo.", - "backup_controller_page_excluded": "Izključeno:", + "backup_controller_page_excluded": "Izključeno: ", "backup_controller_page_failed": "NeuspeÅĄno ({})", "backup_controller_page_filename": "Ime datoteke: {} [{}]", "backup_controller_page_id": "ID: {}", @@ -545,7 +549,7 @@ "backup_controller_page_start_backup": "ZaÅženi varnostno kopiranje", "backup_controller_page_status_off": "Samodejno varnostno kopiranje v ospredju je izklopljeno", "backup_controller_page_status_on": "Samodejno varnostno kopiranje v ospredju je vklopljeno", - "backup_controller_page_storage_format": "Uporabljeno {} od {}", + "backup_controller_page_storage_format": "{used} od {available} uporabljeno", "backup_controller_page_to_backup": "Albumi, ki bodo varnostno kopirani", "backup_controller_page_total_sub": "Vse edinstvene fotografije in videi iz izbranih albumov", "backup_controller_page_turn_off": "Izklopite varnostno kopiranje v ospredju", @@ -566,25 +570,25 @@ "bugs_and_feature_requests": "Napake in zahteve po funkcijah", "build": "Različica", "build_image": "Različica slike", - "bulk_delete_duplicates_confirmation": "Ali ste prepričani, da Åželite mnoÅžično izbrisati {count, plural, one {# dvojnik} other {# dvojnikov}}? S tem boste ohranili največje sredstvo vsake skupine in trajno izbrisali vse druge dvojnike. Tega dejanja ne morete razveljaviti!", - "bulk_keep_duplicates_confirmation": "Ali ste prepričani, da Åželite obdrÅžati {count, plural, one {# dvojnik} other {# dvojnikov}}? S tem boste razreÅĄili vse podvojene skupine, ne da bi karkoli izbrisali.", - "bulk_trash_duplicates_confirmation": "Ali ste prepričani, da Åželite mnoÅžično vreči v smetnjak {count, plural, one {# dvojnik} other {# dvojnikov}}? S tem boste obdrÅžali največje sredstvo vsake skupine in odstranili vse druge dvojnike.", + "bulk_delete_duplicates_confirmation": "Ali ste prepričani, da Åželite mnoÅžično izbrisati {count, plural, one {# dvojnik} two {# dvojnika} few {# dvojnike} other {# dvojnikov}}? S tem boste ohranili največje sredstvo vsake skupine in trajno izbrisali vse druge dvojnike. Tega dejanja ne morete razveljaviti!", + "bulk_keep_duplicates_confirmation": "Ali ste prepričani, da Åželite obdrÅžati {count, plural, one {# dvojnik} two {# dvojnika} few {# dvojnike} other {# dvojnikov}}? S tem boste razreÅĄili vse podvojene skupine, ne da bi karkoli izbrisali.", + "bulk_trash_duplicates_confirmation": "Ali ste prepričani, da Åželite mnoÅžično vreči v smetnjak {count, plural, one {# dvojnik} two {# dvojnika} few {# dvojnike} other {# dvojnikov}}? S tem boste obdrÅžali največje sredstvo vsake skupine in odstranili vse druge dvojnike.", "buy": "Kupi Immich", - "cache_settings_album_thumbnails": "Sličice strani knjiÅžnice ({} sredstev)", + "cache_settings_album_thumbnails": "Sličice strani knjiÅžnice ({count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}})", "cache_settings_clear_cache_button": "Počisti predpomnilnik", "cache_settings_clear_cache_button_title": "Počisti predpomnilnik aplikacije. To bo znatno vplivalo na delovanje aplikacije, dokler se predpomnilnik ne obnovi.", "cache_settings_duplicated_assets_clear_button": "POČISTI", "cache_settings_duplicated_assets_subtitle": "Fotografije in videoposnetki, ki jih je aplikacija uvrstila na črni seznam", - "cache_settings_duplicated_assets_title": "Podvojena sredstva ({})", - "cache_settings_image_cache_size": "Velikost predpomnilnika slik ({} sredstev)", + "cache_settings_duplicated_assets_title": "{count, plural, one {# podvojeno sredstvo} two {# podvojeni sredstvi} few {# podvojena sredstva} other {# podvojenih sredstev}}", + "cache_settings_image_cache_size": "Velikost predpomnilnika slik ({count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}})", "cache_settings_statistics_album": "Sličice knjiÅžnice", "cache_settings_statistics_assets": "{} sredstva ({})", - "cache_settings_statistics_full": "Polne slike", + "cache_settings_statistics_full": "Izvirne slike", "cache_settings_statistics_shared": "Sličice albuma v skupni rabi", "cache_settings_statistics_thumbnail": "Sličice", "cache_settings_statistics_title": "Uporaba predpomnilnika", "cache_settings_subtitle": "Nadzirajte delovanje predpomnjenja mobilne aplikacije Immich", - "cache_settings_thumbnail_size": "Velikost predpomnilnika sličic ({} sredstev)", + "cache_settings_thumbnail_size": "Velikost predpomnilnika sličic ({count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}})", "cache_settings_tile_subtitle": "Nadzoruj vedenje lokalnega shranjevanja", "cache_settings_tile_title": "Lokalna shramba", "cache_settings_title": "Nastavitve predpomnjenja", @@ -654,15 +658,15 @@ "contain": "Vsebuje", "context": "Kontekst", "continue": "Nadaljuj", - "control_bottom_app_bar_album_info_shared": "{} elementov ¡ V skupni rabi", + "control_bottom_app_bar_album_info_shared": "{count, plural, one {# element v skupni rabi} two {# elementa v skupni rabi} few {# elementi v skupni rabi} other {# elementov v skupni rabi}}", "control_bottom_app_bar_create_new_album": "Ustvari nov album", "control_bottom_app_bar_delete_from_immich": "IzbriÅĄi iz Immicha", "control_bottom_app_bar_delete_from_local": "IzbriÅĄi iz naprave", "control_bottom_app_bar_edit_location": "Uredi lokacijo", "control_bottom_app_bar_edit_time": "Uredi datum in uro", "control_bottom_app_bar_share_link": "Deli povezavo", - "control_bottom_app_bar_share_to": "Deli z", - "control_bottom_app_bar_trash_from_immich": "Prestavi v smeti", + "control_bottom_app_bar_share_to": "Deli s/z", + "control_bottom_app_bar_trash_from_immich": "Prestavi v smetnjak", "copied_image_to_clipboard": "Slika kopirana v odloÅžiÅĄÄe.", "copied_to_clipboard": "Kopirano v odloÅžiÅĄÄe!", "copy_error": "Napaka pri kopiranju", @@ -686,7 +690,7 @@ "create_new_person": "Ustvari novo osebo", "create_new_person_hint": "Dodeli izbrana sredstva novi osebi", "create_new_user": "Ustvari novega uporabnika", - "create_shared_album_page_share_add_assets": "DODAJ SREDSTVO", + "create_shared_album_page_share_add_assets": "DODAJ SREDSTVA", "create_shared_album_page_share_select_photos": "Izberi fotografije", "create_tag": "Ustvari oznako", "create_tag_description": "Ustvarite novo oznako. Za ugnezdene oznake vnesite celotno pot oznake, vključno s poÅĄevnicami.", @@ -711,7 +715,7 @@ "deduplicate_all": "Odstrani vse podvojene", "deduplication_criteria_1": "Velikost slike v bajtih", "deduplication_criteria_2": "Å tevilo podatkov EXIF", - "deduplication_info": "Informacije o deduplikaciji", + "deduplication_info": "Informacije o zaznavanju dvojnikov", "deduplication_info_description": "Za samodejno vnaprejÅĄnjo izbiro sredstev in mnoÅžično odstranjevanje dvojnikov si ogledamo:", "default_locale": "Privzeti jezik", "default_locale_description": "Oblikujte datume in ÅĄtevilke glede na lokalne nastavitve brskalnika", @@ -742,7 +746,7 @@ "description": "Opis", "description_input_hint_text": "Dodaj opis ...", "description_input_submit_error": "Napaka pri posodabljanju opisa, preverite dnevnik za več podrobnosti", - "details": "PODROBNOSTI", + "details": "Podrobnosti", "direction": "Usmeritev", "disabled": "Onemogočeno", "disallow_edits": "Onemogoči urejanje", @@ -808,7 +812,7 @@ "editor_crop_tool_h2_rotation": "Vrtenje", "email": "E-poÅĄta", "empty_folder": "Ta mapa je prazna", - "empty_trash": "Izprazni smeti", + "empty_trash": "Izprazni smetnjak", "empty_trash_confirmation": "Ste prepričani, da Åželite izprazniti smetnjak? S tem boste iz Immicha trajno odstranili vsa sredstva v smetnjaku.\nTega dejanja ne morete razveljaviti!", "enable": "Omogoči", "enabled": "Omogočeno", @@ -855,7 +859,7 @@ "failed_to_unstack_assets": "Sredstev ni bilo mogoče razloÅžiti", "import_path_already_exists": "Ta uvozna pot Åže obstaja.", "incorrect_email_or_password": "Napačen e-poÅĄtni naslov ali geslo", - "paths_validation_failed": "{paths, plural, one {# pot} other {# poti}} ni bilo uspeÅĄno preverjeno", + "paths_validation_failed": "{paths, plural, one {# pot ni bila uspeÅĄno preverjena} two {# poti nista bili uspeÅĄno preverjeni} few {# poti niso bile uspeÅĄno preverjene} other {# poti ni bilo uspeÅĄno preverjenih}}", "profile_picture_transparent_pixels": "Profilne slike ne smejo imeti prosojnih slikovnih pik. Povečajte in/ali premaknite sliko.", "quota_higher_than_disk_size": "Nastavili ste kvoto, ki je viÅĄja od velikosti diska", "repair_unable_to_check_items": "Ni mogoče preveriti {count, select, one {predmeta} other {predmetov}}", @@ -873,7 +877,7 @@ "unable_to_change_favorite": "Ni mogoče spremeniti priljubljenega za sredstvo", "unable_to_change_location": "Lokacije ni mogoče spremeniti", "unable_to_change_password": "Gesla ni mogoče spremeniti", - "unable_to_change_visibility": "Ni mogoče spremeniti vidnosti za {count, plural, one {# osebo} other {# oseb}}", + "unable_to_change_visibility": "Ni mogoče spremeniti vidnosti za {count, plural, one {# osebo} two {# osebi} few {# osebe} other {# oseb}}", "unable_to_complete_oauth_login": "Prijave OAuth ni mogoče dokončati", "unable_to_connect": "Ni mogoče vzpostaviti povezave", "unable_to_connect_to_server": "Ni mogoče vzpostaviti povezave s streÅžnikom", @@ -953,10 +957,10 @@ "exif_bottom_sheet_location": "LOKACIJA", "exif_bottom_sheet_people": "OSEBE", "exif_bottom_sheet_person_add_person": "Dodaj ime", - "exif_bottom_sheet_person_age": "Starost {}", - "exif_bottom_sheet_person_age_months": "Starost {} mesecev", - "exif_bottom_sheet_person_age_year_months": "Starost 1 leto, {} mesecev", - "exif_bottom_sheet_person_age_years": "Starost {}", + "exif_bottom_sheet_person_age": "Starost {count, plural, one {# leto} two {# leti} few {# leta} other {# let}}", + "exif_bottom_sheet_person_age_months": "Starost {months, plural, one {# mesec} two {# meseca} few {# mesece} other {# mesecev}}", + "exif_bottom_sheet_person_age_year_months": "Starost 1 leto, {months, plural, one {# mesec} two {# meseca} few {# mesece} other {# mesecev}}", + "exif_bottom_sheet_person_age_years": "Starost {years, plural, one {# leto} two {# leti} few {# leta} other {# let}}", "exit_slideshow": "Zapustite diaprojekcijo", "expand_all": "RazÅĄiri vse", "experimental_settings_new_asset_list_subtitle": "Delo v teku", @@ -974,7 +978,7 @@ "external": "Zunanji", "external_libraries": "Zunanje knjiÅžnice", "external_network": "Zunanje omreÅžje", - "external_network_sheet_info": "Ko aplikacija ni v Åželenem omreÅžju WiFi, se bo povezala s streÅžnikom prek prvega od spodnjih URL-jev, ki jih lahko doseÅže, začenÅĄi od zgoraj navzdol", + "external_network_sheet_info": "Ko aplikacija ni v Åželenem omreÅžju Wi-Fi, se bo povezala s streÅžnikom prek prvega od spodnjih URL-jev, ki jih lahko doseÅže, začenÅĄi od zgoraj navzdol", "face_unassigned": "Nedodeljen", "failed": "Ni uspelo", "failed_to_load_assets": "Sredstev ni bilo mogoče naloÅžiti", @@ -992,6 +996,7 @@ "filetype": "Vrsta datoteke", "filter": "Filter", "filter_people": "Filtriraj ljudi", + "filter_places": "Filtriraj kraje", "find_them_fast": "Z iskanjem jih hitro poiÅĄÄite po imenu", "fix_incorrect_match": "Popravi napačno ujemanje", "folder": "Mapa", @@ -1040,7 +1045,7 @@ "home_page_delete_remote_err_local": "Lokalna sredstva pri brisanju oddaljenega izbora, preskakujem", "home_page_favorite_err_local": "Lokalnih sredstev ÅĄe ni mogoče dodati med priljubljene, preskakujem", "home_page_favorite_err_partner": "Sredstev partnerja ÅĄe ni mogoče dodati med priljubljene, preskakujem", - "home_page_first_time_notice": "Če aplikacijo uporabljate prvič, se prepričajte, da ste izbrali rezervne albume, tako da lahko časovna premica zapolni fotografije in videoposnetke v albumih.", + "home_page_first_time_notice": "Če aplikacijo uporabljate prvič, se prepričajte, da ste izbrali rezervne albume, tako da lahko časovna premica zapolni fotografije in videoposnetke v albumih", "home_page_share_err_local": "Lokalnih sredstev ni mogoče deliti prek povezave, preskakujem", "home_page_upload_err_limit": "Hkrati lahko naloÅžite največ 30 sredstev, preskakujem", "host": "Gostitelj", @@ -1066,7 +1071,7 @@ "immich_web_interface": "Immich spletni vmesnik", "import_from_json": "Uvoz iz JSON", "import_path": "Pot uvoza", - "in_albums": "V {count, plural, one {# album} other {# albumov}}", + "in_albums": "V {count, plural, one {# album} two {# albuma} few {# albume} other {# albumov}}", "in_archive": "V arhiv", "include_archived": "Vključi arhivirane", "include_shared_albums": "Vključite skupne albume", @@ -1076,7 +1081,7 @@ "info": "Info", "interval": { "day_at_onepm": "Vsak dan ob 13h", - "hours": "Vsakih {hours, plural, one {uro} other {{hours, number} ur/e}}", + "hours": "Vsakih {hours, plural, one {uro} two {uri} few {ure} other {{hours, number} ur}}", "night_at_midnight": "Vsak večer ob polnoči", "night_at_twoam": "Vsako noč ob 2h" }, @@ -1084,12 +1089,12 @@ "invalid_date_format": "Neveljavna oblika datuma", "invite_people": "Povabi ljudi", "invite_to_album": "Povabi v album", - "items_count": "{count, plural, one {# predmet} other {# predmetov}}", + "items_count": "{count, plural, one {# predmet} two {# predmeta} few {# predmeti} other {# predmetov}}", "jobs": "Opravila", "keep": "ObdrÅži", "keep_all": "ObdrÅži vse", "keep_this_delete_others": "ObdrÅži to, izbriÅĄi ostalo", - "kept_this_deleted_others": "ObdrÅži to sredstvo in izbriÅĄi {count, plural, one {# sredstvo} other {# sredstev}}", + "kept_this_deleted_others": "ObdrÅži to sredstvo in izbriÅĄi {count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}}", "keyboard_shortcuts": "BliÅžnjice na tipkovnici", "language": "Jezik", "language_setting_description": "Izberite Åželeni jezik", @@ -1120,7 +1125,7 @@ "local_network": "Lokalno omreÅžje", "local_network_sheet_info": "Aplikacija se bo povezala s streÅžnikom prek tega URL-ja, ko bo uporabljala navedeno omreÅžje Wi-Fi", "location_permission": "Dovoljenje za lokacijo", - "location_permission_content": "Za uporabo funkcije samodejnega preklapljanja potrebuje Immich dovoljenje za natančno lokacijo, da lahko prebere ime trenutnega omreÅžja WiFi", + "location_permission_content": "Za uporabo funkcije samodejnega preklapljanja potrebuje Immich dovoljenje za natančno lokacijo, da lahko prebere ime trenutnega omreÅžja Wi-Fi", "location_picker_choose_on_map": "Izberi na zemljevidu", "location_picker_latitude_error": "Vnesi veljavno zemljepisno ÅĄirino", "location_picker_latitude_hint": "Tukaj vnesi svojo zemljepisno ÅĄirino", @@ -1170,8 +1175,8 @@ "manage_your_devices": "Upravljajte svoje prijavljene naprave", "manage_your_oauth_connection": "Upravljajte svojo OAuth povezavo", "map": "Zemljevid", - "map_assets_in_bound": "{} slika", - "map_assets_in_bounds": "{} slik", + "map_assets_in_bound": "{count, plural, one {# slika}}", + "map_assets_in_bounds": "{count, plural, two {# sliki} few {# slike} other {# slik}}", "map_cannot_get_user_location": "Lokacije uporabnika ni mogoče dobiti", "map_location_dialog_yes": "Da", "map_location_picker_page_use_location": "Uporabi to lokacijo", @@ -1185,9 +1190,9 @@ "map_settings": "Nastavitve zemljevida", "map_settings_dark_mode": "Temni način", "map_settings_date_range_option_day": "Zadnjih 24 ur", - "map_settings_date_range_option_days": "Zadnjih {} dni", + "map_settings_date_range_option_days": "{count, plural, one {Zadnji # dan} two {Zadnja # dneva} few {Zadnje # dni} other {Zadnjih # dni}}", "map_settings_date_range_option_year": "Zadnje leto", - "map_settings_date_range_option_years": "Zadnjih {} let", + "map_settings_date_range_option_years": "{count, plural, two {Zadnje # leti} few {# Zadnja # leta} other {Zadnjih # let}}", "map_settings_dialog_title": "Nastavitve zemljevida", "map_settings_include_show_archived": "Vključi arhivirane", "map_settings_include_show_partners": "Vključi partnerjeve", @@ -1203,7 +1208,7 @@ "memories_start_over": "Začni od začetka", "memories_swipe_to_close": "Podrsaj gor za zapiranje", "memories_year_ago": "Leto dni nazaj", - "memories_years_ago": "{} let nazaj", + "memories_years_ago": "{years, plural, two {# leti} few {# leta} other {# let}} nazaj", "memory": "Spomin", "memory_lane_title": "Spominski trak {title}", "menu": "Meni", @@ -1282,6 +1287,7 @@ "onboarding_welcome_user": "Pozdravljen/a, {user}", "online": "Povezano", "only_favorites": "Samo priljubljene", + "open": "Odpri", "open_in_map_view": "Odpri v pogledu zemljevida", "open_in_openstreetmap": "Odpri v OpenStreetMap", "open_the_search_filters": "Odpri iskalne filtre", @@ -1298,14 +1304,14 @@ "partner_can_access": "{partner} ima dostop", "partner_can_access_assets": "Vse vaÅĄe fotografije in videoposnetki, razen tistih v arhivu in izbrisanih", "partner_can_access_location": "Lokacija, kjer so bile vaÅĄe fotografije posnete", - "partner_list_user_photos": "{user}ovih fotografij", + "partner_list_user_photos": "fotografije od {user}", "partner_list_view_all": "Poglej vse", "partner_page_empty_message": "VaÅĄe fotografije ÅĄe niso v skupni rabi z nobenim partnerjem.", "partner_page_no_more_users": "Ni več uporabnikov za dodajanje", "partner_page_partner_add_failed": "Partnerja ni bilo mogoče dodati", "partner_page_select_partner": "Izberi partnerja", "partner_page_shared_to_title": "V skupni rabi z", - "partner_page_stop_sharing_content": "{} ne bo imel več dostopa do vaÅĄih fotografij.", + "partner_page_stop_sharing_content": "{user} ne bo imel več dostopa do vaÅĄih fotografij.", "partner_sharing": "Skupna raba s partnerjem", "partners": "Partnerji", "password": "Geslo", @@ -1313,9 +1319,9 @@ "password_required": "Zahtevano je geslo", "password_reset_success": "Ponastavitev gesla je uspela", "past_durations": { - "days": "Pretek-el/-lih {days, plural, one {dan} other {# dni}}", - "hours": "Pretek-lo/-lih {hours, plural, one {uro} other {# ur}}", - "years": "Pretek-lo/-lih {years, plural, one {leto} other {# let}}" + "days": "{days, plural, one {Pretekel dan} two {Pretekla # dni} few {Pretekle # dni} other {Preteklih # dni}}", + "hours": "{hours, plural, one {Preteklo uro} two {Pretekli # uri} few {Pretekle # ure} other {Preteklih # ur}}", + "years": "{years, plural, one {Preteklo leto} two {Pretekli # leti} few {Pretekla # leta} other {Preteklih # let}}" }, "path": "Pot", "pattern": "Vzorec", @@ -1324,13 +1330,13 @@ "paused": "Zaustavljeno", "pending": "V teku", "people": "Osebe", - "people_edits_count": "Urejen-a/-ih {count, plural, one {# oseba} other {# oseb}}", + "people_edits_count": "{count, plural, one {Urejena # oseba} two {Urejeni # osebi} few {Urejene # osebe} other {Urejenih # oseb}}", "people_feature_description": "Brskanje po fotografijah in videoposnetkih, razvrÅĄÄenih po osebah", "people_sidebar_description": "PrikaÅžite povezavo do Ljudje v stranski vrstici", "permanent_deletion_warning": "Opozorilo o trajnem izbrisu", "permanent_deletion_warning_setting_description": "PokaÅži opozorilo pri trajnem brisanju sredstev", "permanently_delete": "Trajno izbriÅĄi", - "permanently_delete_assets_count": "Trajno izbriÅĄi {count, plural, one {sredstvo} other {sredstev}}", + "permanently_delete_assets_count": "Trajno izbriÅĄi {count, plural, one {sredstvo} two {sredstvi} few {sredstva} other {sredstev}}", "permanently_delete_assets_prompt": "Ali ste prepričani, da Åželite trajno izbrisati {count, plural, one {to sredstvo?} other {ta # sredstva?}} S tem boste odstranili tudi {count, plural, one {tega od teh} other {telih iz telih}} album- /-ov.", "permanently_deleted_asset": "Trajno izbrisano sredstvo", "permanently_deleted_assets_count": "Trajno izbrisano {count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}}", @@ -1348,12 +1354,12 @@ "photo_shared_all_users": "Videti je, da ste svoje fotografije delili z vsemi uporabniki ali pa nimate nobenega uporabnika, s katerim bi jih delili.", "photos": "Slike", "photos_and_videos": "Fotografije & videi", - "photos_count": "{count, plural, one {{count, number} slika} other {{count, number} slik}}", + "photos_count": "{count, plural, one {{count, number} slika} two {{count, number} sliki} few {{count, number} slike} other {{count, number} slik}}", "photos_from_previous_years": "Fotografije iz prejÅĄnjih let", "pick_a_location": "Izberi lokacijo", "place": "Lokacija", "places": "Lokacije", - "places_count": "{count, plural, one {{count, number} kraj} other {{count, number} krajev}}", + "places_count": "{count, plural, one {{count, number} kraj} two {{count, number} kraja} few {{count, number} kraji} other {{count, number} krajev}}", "play": "Predvajaj", "play_memories": "Predvajaj spomine", "play_motion_photo": "Predvajaj premikajočo fotografijo", @@ -1418,7 +1424,7 @@ "reaction_options": "MoÅžnosti reakcije", "read_changelog": "Preberi dnevnik sprememb", "reassign": "Prerazporedi", - "reassigned_assets_to_existing_person": "Ponovno dodeljeno {count, plural, one {# sredstvo} other {# sredstev}} za {name, select, null {an existing person} other {{name}}}", + "reassigned_assets_to_existing_person": "Ponovno dodeljeno {count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}} za {name, select, null {an existing person} other {{name}}}", "reassigned_assets_to_new_person": "Ponovno dodeljeno {count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}} za novo osebo", "reassing_hint": "Dodeli izbrana sredstva obstoječi osebi", "recent": "Nedavno", @@ -1426,6 +1432,8 @@ "recent_searches": "Nedavna iskanja", "recently_added": "Nedavno dodano", "recently_added_page_title": "Nedavno dodano", + "recently_taken": "Nedavno uporabljen", + "recently_taken_page_title": "Nedavno Uporabljen", "refresh": "OsveÅži", "refresh_encoded_videos": "OsveÅži kodirane videoposnetke", "refresh_faces": "OsveÅži obraze", @@ -1540,7 +1548,7 @@ "search_result_page_new_search_hint": "Novo iskanje", "search_settings": "Nastavitve iskanja", "search_state": "Iskanje deÅžele...", - "search_suggestion_list_smart_search_hint_1": "Pametno iskanje je privzeto omogočeno, za iskanje metapodatkov uporabite sintakso", + "search_suggestion_list_smart_search_hint_1": "Pametno iskanje je privzeto omogočeno, za iskanje metapodatkov uporabite sintakso ", "search_suggestion_list_smart_search_hint_2": "m:vaÅĄ-iskani-pojem", "search_tags": "Iskanje oznak...", "search_timezone": "Iskanje časovnega pasu...", @@ -1590,12 +1598,12 @@ "setting_languages_apply": "Uporabi", "setting_languages_subtitle": "Spremeni jezik aplikacije", "setting_languages_title": "Jeziki", - "setting_notifications_notify_failures_grace_period": "Obvesti o napakah varnostnega kopiranja v ozadju: {}", - "setting_notifications_notify_hours": "{} ur", + "setting_notifications_notify_failures_grace_period": "Obvesti o napakah varnostnega kopiranja v ozadju: {user}", + "setting_notifications_notify_hours": "{count, plural, one {# ura} two {# uri} few {# ure} other {# ur}}", "setting_notifications_notify_immediately": "takoj", - "setting_notifications_notify_minutes": "{} minut", + "setting_notifications_notify_minutes": "{count, plural, one {# minuta} two {# minuti} few {# minute} other {# minut}}", "setting_notifications_notify_never": "nikoli", - "setting_notifications_notify_seconds": "{} sekund", + "setting_notifications_notify_seconds": "{count, plural, one {# sekunda} two {# sekundi} few {# sekunde} other {# sekund}}", "setting_notifications_single_progress_subtitle": "Podrobne informacije o napredku nalaganja po sredstvih", "setting_notifications_single_progress_title": "PokaÅži napredek varnostnega kopiranja v ozadju", "setting_notifications_subtitle": "Prilagodite svoje nastavitve obvestil", @@ -1609,7 +1617,7 @@ "settings_saved": "Nastavitve shranjene", "share": "Deli", "share_add_photos": "Dodaj fotografije", - "share_assets_selected": "{} izbrano", + "share_assets_selected": "{count, plural, one {# izbrana} two {# izbrani} few {# izbrane} other {# izbranih}}", "share_dialog_preparing": "Priprava...", "shared": "V skupni rabi", "shared_album_activities_input_disable": "Komentiranje je onemogočeno", @@ -1618,7 +1626,7 @@ "shared_album_section_people_action_error": "Napaka pri zapuÅĄÄanju/odstranjevanju iz albuma", "shared_album_section_people_action_leave": "Odstrani uporabnika iz albuma", "shared_album_section_people_action_remove_user": "Odstrani uporabnika iz albuma", - "shared_album_section_people_title": "LJUDJE", + "shared_album_section_people_title": "OSEBE", "shared_by": "Skupna raba s/z", "shared_by_user": "Skupna raba s/z {user}", "shared_by_you": "DeliÅĄ", @@ -1630,25 +1638,25 @@ "shared_link_create_error": "Napaka pri ustvarjanju povezave skupne rabe", "shared_link_edit_description_hint": "Vnesi opis skupne rabe", "shared_link_edit_expire_after_option_day": "1 dan", - "shared_link_edit_expire_after_option_days": "{} dni", + "shared_link_edit_expire_after_option_days": "{count, plural, other {# dni}}", "shared_link_edit_expire_after_option_hour": "1 ura", - "shared_link_edit_expire_after_option_hours": "{} ur", + "shared_link_edit_expire_after_option_hours": "{count, plural, two {# uri} few {# ure} other {# ur}}", "shared_link_edit_expire_after_option_minute": "1 minuta", - "shared_link_edit_expire_after_option_minutes": "{} minut", - "shared_link_edit_expire_after_option_months": "{} mesecev", - "shared_link_edit_expire_after_option_year": "{} let", + "shared_link_edit_expire_after_option_minutes": "{count, plural, two {# minuti} few {# minute} other {# minut}}", + "shared_link_edit_expire_after_option_months": "{count, plural, one {# mesec} two {# meseca} few {# mesece} other {# mesecev}}", + "shared_link_edit_expire_after_option_year": "{count, plural, one {# leto} two {# leti} few {# leta} other {# let}}", "shared_link_edit_password_hint": "Vnesi geslo za skupno rabo", "shared_link_edit_submit_button": "Posodobi povezavo", "shared_link_error_server_url_fetch": "URL-ja streÅžnika ni mogoče pridobiti", - "shared_link_expires_day": "Poteče čez {} dan", - "shared_link_expires_days": "Poteče čez {} dni", - "shared_link_expires_hour": "Poteče čez {} uro", - "shared_link_expires_hours": "Poteče čez {} ur", - "shared_link_expires_minute": "Poteče čez {} minuto\n", - "shared_link_expires_minutes": "Poteče čez {} minut", + "shared_link_expires_day": "Poteče čez {count, plural, one {# dan}}", + "shared_link_expires_days": "Poteče čez {count, plural, other {# dni}}", + "shared_link_expires_hour": "Poteče čez {count, plural, one {# uro}}", + "shared_link_expires_hours": "Poteče čez {count, plural, two {# uri} few {# ure} other {# ur}}", + "shared_link_expires_minute": "Poteče čez {count, plural, one {# minuto}}", + "shared_link_expires_minutes": "Poteče čez {count, plural, two {# minuti} few {# minute} other {# minut}}", "shared_link_expires_never": "Poteče ∞", - "shared_link_expires_second": "Poteče čez {} sekundo", - "shared_link_expires_seconds": "Poteče čez {} sekund", + "shared_link_expires_second": "Poteče čez {count,plural, one {# sekundo}}", + "shared_link_expires_seconds": "Poteče čez {count, plural, two {# sekundi} few {# sekunde} other {# sekund}}", "shared_link_individual_shared": "Individualno deljeno", "shared_link_info_chip_metadata": "EXIF", "shared_link_manage_links": "Upravljanje povezav v skupni rabi", @@ -1784,11 +1792,11 @@ "trash_no_results_message": "Fotografije in videoposnetki, ki so v smetnjaku, bodo prikazani tukaj.", "trash_page_delete_all": "IzbriÅĄi vse", "trash_page_empty_trash_dialog_content": "Ali Åželite izprazniti svoja sredstva v smeti? Ti elementi bodo trajno odstranjeni iz Immicha", - "trash_page_info": "Elementi v smeteh bodo trajno izbrisani po {} dneh", + "trash_page_info": "Elementi v smeteh bodo trajno izbrisani po {number} dneh", "trash_page_no_assets": "Ni sredstev v smeteh", "trash_page_restore_all": "Obnovi vse", "trash_page_select_assets_btn": "Izberite sredstva", - "trash_page_title": "Smetnjak ({})", + "trash_page_title": "Smetnjak ({count, number})", "trashed_items_will_be_permanently_deleted_after": "Elementi v smetnjaku bodo trajno izbrisani po {days, plural, one {# dnevu} two {# dnevih} few {# dnevih} other {# dneh}}.", "type": "Vrsta", "unarchive": "Odstrani iz arhiva", @@ -1852,8 +1860,8 @@ "version_announcement_message": "Pozdravljeni! Na voljo je nova različica Immich. Vzemite si nekaj časa in preberite opombe ob izdaji, da zagotovite, da so vaÅĄe nastavitve posodobljene, da preprečite morebitne napačne konfiguracije, zlasti če uporabljate WatchTower ali kateri koli mehanizem, ki samodejno posodablja vaÅĄ primerek Immich.", "version_announcement_overlay_release_notes": "opombe ob izdaji", "version_announcement_overlay_text_1": "ÅŊivjo prijatelj, na voljo je nova izdaja", - "version_announcement_overlay_text_2": "vzemi si čas in obiÅĄÄi", - "version_announcement_overlay_text_3": "in zagotovite, da sta vaÅĄa nastavitev docker-compose in .env posodobljena, da preprečite morebitne napačne konfiguracije, zlasti če uporabljate WatchTower ali kateri koli mehanizem, ki samodejno posodablja vaÅĄo streÅžniÅĄko aplikacijo.", + "version_announcement_overlay_text_2": "vzemi si čas in obiÅĄÄi ", + "version_announcement_overlay_text_3": " in zagotovite, da sta vaÅĄa nastavitev docker-compose in .env posodobljena, da preprečite morebitne napačne konfiguracije, zlasti če uporabljate WatchTower ali kateri koli mehanizem, ki samodejno posodablja vaÅĄo streÅžniÅĄko aplikacijo.", "version_announcement_overlay_title": "Na voljo je nova različica streÅžnika 🎉", "version_history": "Zgodovina različic", "version_history_item": "{version} nameÅĄÄena {date}", diff --git a/i18n/sr_Cyrl.json b/i18n/sr_Cyrl.json index c8aa6a9f27..97fe461afd 100644 --- a/i18n/sr_Cyrl.json +++ b/i18n/sr_Cyrl.json @@ -1,5 +1,5 @@ { - "about": "О АĐŋĐģиĐēĐ°Ņ†Đ¸Ņ˜Đ¸", + "about": "О аĐŋĐģиĐēĐ°Ņ†Đ¸Ņ˜Đ¸", "account": "ĐŸŅ€ĐžŅ„Đ¸Đģ", "account_settings": "ПодĐĩŅˆĐ°Đ˛Đ°ŅšĐ° Са ĐŸŅ€ĐžŅ„Đ¸Đģ", "acknowledge": "ĐŸĐžŅ‚Đ˛Ņ€Đ´Đ¸", @@ -14,8 +14,8 @@ "add_a_location": "Đ”ĐžĐ´Đ°Ņ˜ ЛоĐēĐ°Ņ†Đ¸Ņ˜Ņƒ", "add_a_name": "Đ”ĐžĐ´Đ°Ņ˜ иĐŧĐĩ", "add_a_title": "Đ”ĐžĐ´Đ°Ņ˜ ĐŊĐ°ŅĐģОв", - "add_endpoint": "Add endpoint", - "add_exclusion_pattern": "Đ”ĐžĐ´Đ°Ņ˜ ĐžĐąŅ€Đ°ĐˇĐ°Ņ† Đ¸ĐˇŅƒĐˇĐ¸ĐŧĐ°ŅšĐ°", + "add_endpoint": "Đ”ĐžĐ´Đ°Ņ˜Ņ‚Đĩ ĐēŅ€Đ°Ņ˜ŅšŅƒ Ņ‚Đ°Ņ‡Đē҃", + "add_exclusion_pattern": "Đ”ĐžĐ´Đ°Ņ˜Ņ‚Đĩ ĐžĐąŅ€Đ°ĐˇĐ°Ņ† Đ¸ĐˇŅƒĐˇĐ¸ĐŧĐ°ŅšĐ°", "add_import_path": "Đ”ĐžĐ´Đ°Ņ˜ ĐŋŅƒŅ‚Đ°ŅšŅƒ Са ĐŋŅ€ĐĩŅƒĐˇĐ¸ĐŧĐ°ŅšĐĩ", "add_location": "Đ”ĐžĐ´Đ°Ņ˜ ĐģĐžĐēĐ°Ņ†Đ¸Ņ˜Ņƒ", "add_more_users": "Đ”ĐžĐ´Đ°Ņ˜ ĐēĐžŅ€Đ¸ŅĐŊиĐēĐĩ", @@ -24,8 +24,8 @@ "add_photos": "Đ”ĐžĐ´Đ°Ņ˜ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Ņ˜Đĩ", "add_to": "Đ”ĐžĐ´Đ°Ņ˜ ҃â€Ļ", "add_to_album": "Đ”ĐžĐ´Đ°Ņ˜ ҃ аĐģĐąŅƒĐŧ", - "add_to_album_bottom_sheet_added": "Added to {album}", - "add_to_album_bottom_sheet_already_exists": "Already in {album}", + "add_to_album_bottom_sheet_added": "Đ”ĐžĐ´Đ°Ņ‚Đž ҃ {album}", + "add_to_album_bottom_sheet_already_exists": "ВĐĩŅ› ҃ {album}", "add_to_shared_album": "Đ”ĐžĐ´Đ°Ņ˜ ҃ Đ´ĐĩŅ™ĐĩĐŊ аĐģĐąŅƒĐŧ", "add_url": "Đ”ĐžĐ´Đ°Ņ˜ URL", "added_to_archive": "Đ”ĐžĐ´Đ°Ņ‚Đž ҃ Đ°Ņ€Ņ…Đ¸Đ˛Ņƒ", @@ -106,7 +106,7 @@ "library_scanning_enable_description": "ОĐŧĐžĐŗŅƒŅ›Đ¸Ņ‚Đĩ ĐŋĐĩŅ€Đ¸ĐžĐ´Đ¸Ņ‡ĐŊĐž ҁĐēĐĩĐŊĐ¸Ņ€Đ°ŅšĐĩ йийĐģĐ¸ĐžŅ‚ĐĩĐēĐĩ", "library_settings": "ĐĄĐŋĐžŅ™ĐŊа йийĐģĐ¸ĐžŅ‚ĐĩĐēа", "library_settings_description": "ĐŖĐŋŅ€Đ°Đ˛Ņ™Đ°Ņ˜Ņ‚Đĩ ĐŋОдĐĩŅˆĐ°Đ˛Đ°ŅšĐ¸Đŧа ҁĐŋĐžŅ™ĐŊĐĩ йийĐģĐ¸ĐžŅ‚ĐĩĐēĐĩ", - "library_tasks_description": "ĐĄĐēĐĩĐŊĐ¸Ņ€Đ°Ņ˜Ņ‚Đĩ ҁĐŋĐžŅ™ĐŊĐĩ йийĐģĐ¸ĐžŅ‚ĐĩĐēĐĩ ҃ ĐŋĐžŅ‚Ņ€Đ°ĐˇĐ¸ Са ĐŊОвиĐŧ и/иĐģи ĐŋŅ€ĐžĐŧĐĩҚĐĩĐŊиĐŧ ҁҀĐĩĐ´ŅŅ‚Đ˛Đ¸Đŧа", + "library_tasks_description": "ĐžĐąĐ°Đ˛Ņ™Đ°Ņ˜ ĐˇĐ°Đ´Đ°Ņ‚ĐēĐĩ йийĐģĐ¸ĐžŅ‚ĐĩĐēĐĩ", "library_watching_enable_description": "ĐŸŅ€Đ°Ņ‚Đ¸Ņ‚Đĩ ҁĐŋĐžŅ™ĐŊĐĩ йийĐģĐ¸ĐžŅ‚ĐĩĐēĐĩ Са ĐŋŅ€ĐžĐŧĐĩĐŊĐĩ Đ´Đ°Ņ‚ĐžŅ‚ĐĩĐēа", "library_watching_settings": "ĐĐ°Đ´ĐŗĐģĐĩĐ´Đ°ŅšĐĩ йийĐģĐ¸ĐžŅ‚ĐĩĐēĐĩ (ЕКСПЕРИМЕНĐĸАЛНО)", "library_watching_settings_description": "ĐŅƒŅ‚ĐžĐŧĐ°Ņ‚ŅĐēи ĐŋŅ€Đ°Ņ‚Đ¸Ņ‚Đĩ ĐŋŅ€ĐžĐŧĐĩҚĐĩĐŊĐĩ Đ´Đ°Ņ‚ĐžŅ‚ĐĩĐēĐĩ", @@ -141,7 +141,7 @@ "machine_learning_smart_search_description": "ĐŸĐžŅ‚Ņ€Đ°ĐļĐ¸Ņ‚Đĩ ҁĐģиĐēĐĩ ҁĐĩĐŧаĐŊŅ‚Đ¸Ņ‡Đēи ĐēĐžŅ€Đ¸ŅŅ‚ĐĩŅ›Đ¸ ŅƒĐŗŅ€Đ°Ņ’ĐĩĐŊи ĐĻЛИП", "machine_learning_smart_search_enabled": "ОĐŧĐžĐŗŅƒŅ›Đ¸Ņ‚Đĩ ĐŋаĐŧĐĩŅ‚ĐŊ҃ ĐŋŅ€ĐĩŅ‚Ņ€Đ°ĐŗŅƒ", "machine_learning_smart_search_enabled_description": "АĐēĐž ҘĐĩ oneĐŧĐžĐŗŅƒŅ›ĐĩĐŊĐž, ҁĐģиĐēĐĩ ĐŊĐĩŅ›Đĩ ĐąĐ¸Ņ‚Đ¸ ĐēĐžĐ´Đ¸Ņ€Đ°ĐŊĐĩ Са ĐŋаĐŧĐĩŅ‚ĐŊ҃ ĐŋŅ€ĐĩŅ‚Ņ€Đ°ĐŗŅƒ.", - "machine_learning_url_description": "URL ҁĐĩŅ€Đ˛ĐĩŅ€Đ° Са ĐŧĐ°ŅˆĐ¸ĐŊҁĐēĐž ŅƒŅ‡ĐĩҚĐĩ. АĐēĐž ҘĐĩ ĐŊавĐĩĐ´ĐĩĐŊĐž Đ˛Đ¸ŅˆĐĩ Од ҘĐĩĐ´ĐŊĐĩ URL Đ°Đ´Ņ€ĐĩҁĐĩ, ŅĐ˛Đ°Đēи ҁĐĩŅ€Đ˛ĐĩŅ€ Ņ›Đĩ ҁĐĩ ĐŋĐžĐēŅƒŅˆĐ°Đ˛Đ°Ņ‚Đ¸ ҘĐĩдаĐŊ ĐŋĐž ҘĐĩдаĐŊ Đ´ĐžĐē ҘĐĩдаĐŊ ĐŊĐĩ ĐžĐ´ĐŗĐžĐ˛ĐžŅ€Đ¸ ҃ҁĐŋĐĩ҈ĐŊĐž, Ņ€ĐĩĐ´ĐžĐŧ Од ĐŋŅ€Đ˛ĐžĐŗ Đ´Đž ĐŋĐžŅĐģĐĩĐ´ŅšĐĩĐŗ. ĐĄĐĩŅ€Đ˛ĐĩŅ€Đ¸ ĐēĐžŅ˜Đ¸ ĐŊĐĩ Ņ€ĐĩĐ°ĐŗŅƒŅ˜Ņƒ ĐąĐ¸Ņ›Đĩ ĐŋŅ€Đ¸Đ˛Ņ€ĐĩĐŧĐĩĐŊĐž СаĐŊĐĩĐŧĐ°Ņ€ĐĩĐŊи Đ´ĐžĐē ҁĐĩ ĐŊĐĩ Đ˛Ņ€Đ°Ņ‚Đĩ ĐŊа ĐŧŅ€ĐĩĐļ҃.", + "machine_learning_url_description": "ĐŖĐ Đ› ҁĐĩŅ€Đ˛ĐĩŅ€Đ° Са ĐŧĐ°ŅˆĐ¸ĐŊҁĐēĐž ŅƒŅ‡ĐĩҚĐĩ. АĐēĐž ҘĐĩ ĐŊавĐĩĐ´ĐĩĐŊĐž Đ˛Đ¸ŅˆĐĩ Од ҘĐĩĐ´ĐŊĐĩ ĐŖĐ Đ› Đ°Đ´Ņ€ĐĩҁĐĩ, ŅĐ˛Đ°Đēи ҁĐĩŅ€Đ˛ĐĩŅ€ Ņ›Đĩ ҁĐĩ ĐŋĐžĐēŅƒŅˆĐ°Đ˛Đ°Ņ‚Đ¸ ҘĐĩдаĐŊ ĐŋĐž ҘĐĩдаĐŊ Đ´ĐžĐē ҘĐĩдаĐŊ ĐŊĐĩ ĐžĐ´ĐŗĐžĐ˛ĐžŅ€Đ¸ ҃ҁĐŋĐĩ҈ĐŊĐž, Ņ€ĐĩĐ´ĐžĐŧ Од ĐŋŅ€Đ˛ĐžĐŗ Đ´Đž ĐŋĐžŅĐģĐĩĐ´ŅšĐĩĐŗ. ĐĄĐĩŅ€Đ˛ĐĩŅ€Đ¸ ĐēĐžŅ˜Đ¸ ĐŊĐĩ Ņ€ĐĩĐ°ĐŗŅƒŅ˜Ņƒ ĐąĐ¸Ņ›Đĩ ĐŋŅ€Đ¸Đ˛Ņ€ĐĩĐŧĐĩĐŊĐž СаĐŊĐĩĐŧĐ°Ņ€ĐĩĐŊи Đ´ĐžĐē ҁĐĩ ĐŊĐĩ Đ˛Ņ€Đ°Ņ‚Đĩ ĐŊа ĐŧŅ€ĐĩĐļ҃.", "manage_concurrency": "ĐŖĐŋŅ€Đ°Đ˛Ņ™Đ°ŅšĐĩ ĐŋĐ°Ņ€Đ°ĐģĐĩĐģĐŊĐžŅˆŅ›Ņƒ", "manage_log_settings": "ĐŖĐŋŅ€Đ°Đ˛Ņ™Đ°Ņ˜Ņ‚Đĩ ĐŋОдĐĩŅˆĐ°Đ˛Đ°ŅšĐ¸Đŧа ĐĩвидĐĩĐŊŅ†Đ¸Ņ˜Đĩ", "map_dark_style": "ĐĸаĐŧĐŊи ŅŅ‚Đ¸Đģ", @@ -251,7 +251,7 @@ "storage_template_hash_verification_enabled_description": "ОĐŧĐžĐŗŅƒŅ›Đ°Đ˛Đ° Ņ…Đĩ҈ вĐĩŅ€Đ¸Ņ„Đ¸ĐēĐ°Ņ†Đ¸Ņ˜Ņƒ, ĐŊĐĩ oneĐŧĐžĐŗŅƒŅ›Đ°Đ˛Đ°Ņ˜Ņ‚Đĩ ОвО ĐžŅĐ¸Đŧ аĐēĐž ĐŊĐ¸ŅŅ‚Đĩ ŅĐ¸ĐŗŅƒŅ€ĐŊи ҃ ĐŋĐžŅĐģĐĩĐ´Đ¸Ņ†Đĩ", "storage_template_migration": "ĐœĐ¸ĐŗŅ€Đ°Ņ†Đ¸Ņ˜Đ° ŅˆĐ°ĐąĐģĐžĐŊа Са ҁĐēĐģĐ°Đ´Đ¸ŅˆŅ‚ĐĩҚĐĩ", "storage_template_migration_description": "ĐŸŅ€Đ¸ĐŧĐĩĐŊĐ¸Ņ‚Đĩ ҂ҀĐĩĐŊŅƒŅ‚ĐŊи {template} ĐŊа ĐŋŅ€ĐĩŅ‚Ņ…ĐžĐ´ĐŊĐž ĐžŅ‚ĐŋŅ€ĐĩĐŧŅ™ĐĩĐŊĐĩ ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đĩ", - "storage_template_migration_info": "ШайĐģĐžĐŊ Са ҁĐēĐģĐ°Đ´Đ¸ŅˆŅ‚ĐĩҚĐĩ Ņ›Đĩ ĐŋŅ€ĐĩŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ŅĐ˛Đĩ ĐĩĐēҁ҂ĐĩĐŊĐˇĐ¸Ņ˜Đĩ ҃ ĐŧаĐģа ҁĐģОва. ĐŸŅ€ĐžĐŧĐĩĐŊĐĩ ŅˆĐ°ĐąĐģĐžĐŊа Ņ›Đĩ ҁĐĩ ĐŋŅ€Đ¸ĐŧĐĩĐŊĐ¸Ņ‚Đ¸ ŅĐ°ĐŧĐž ĐŊа ĐŊОвĐĩ Đ´Đ°Ņ‚ĐžŅ‚ĐĩĐēĐĩ. Да ĐąĐ¸ŅŅ‚Đĩ Ņ€ĐĩŅ‚Ņ€ĐžĐ°ĐēŅ‚Đ¸Đ˛ĐŊĐž ĐŋŅ€Đ¸ĐŧĐĩĐŊиĐģи ŅˆĐ°ĐąĐģĐžĐŊ ĐŊа ĐŋŅ€ĐĩŅ‚Ņ…ĐžĐ´ĐŊĐž ĐžŅ‚ĐŋŅ€ĐĩĐŧŅ™ĐĩĐŊĐĩ Đ´Đ°Ņ‚ĐžŅ‚ĐĩĐēĐĩ, ĐŋĐžĐēŅ€ĐĩĐŊĐ¸Ņ‚Đĩ {job}.", + "storage_template_migration_info": "ĐŸŅ€ĐžĐŧĐĩĐŊĐĩ ŅˆĐ°ĐąĐģĐžĐŊа Ņ›Đĩ ҁĐĩ ĐŋŅ€Đ¸ĐŧĐĩĐŊĐ¸Ņ‚Đ¸ ŅĐ°ĐŧĐž ĐŊа ĐŊОвĐĩ Đ´Đ°Ņ‚ĐžŅ‚ĐĩĐēĐĩ. Да ĐąĐ¸ŅŅ‚Đĩ Ņ€ĐĩŅ‚Ņ€ĐžĐ°ĐēŅ‚Đ¸Đ˛ĐŊĐž ĐŋŅ€Đ¸ĐŧĐĩĐŊиĐģи ŅˆĐ°ĐąĐģĐžĐŊ ĐŊа ĐŋŅ€ĐĩŅ‚Ņ…ĐžĐ´ĐŊĐž ĐžŅ‚ĐŋŅ€ĐĩĐŧŅ™ĐĩĐŊĐĩ Đ´Đ°Ņ‚ĐžŅ‚ĐĩĐēĐĩ, ĐŋĐžĐēŅ€ĐĩĐŊĐ¸Ņ‚Đĩ {job}.", "storage_template_migration_job": "ĐŸĐžŅĐ°Đž ĐŧĐ¸ĐŗŅ€Đ°Ņ†Đ¸Ņ˜Đĩ ҁĐēĐģĐ°Đ´Đ¸ŅˆŅ‚Đ°", "storage_template_more_details": "За Đ˛Đ¸ŅˆĐĩ Đ´ĐĩŅ‚Đ°Ņ™Đ° Đž ĐžĐ˛ĐžŅ˜ Ņ„ŅƒĐŊĐēŅ†Đ¸Ņ˜Đ¸ ĐŋĐžĐŗĐģĐĩĐ´Đ°Ņ˜Ņ‚Đĩ ШайĐģĐžĐŊ Са ҁĐēĐģĐ°Đ´Đ¸ŅˆŅ‚Đĩ и ҚĐĩĐŗĐžĐ˛Đĩ иĐŧĐŋĐģиĐēĐ°Ņ†Đ¸Ņ˜Đĩ", "storage_template_onboarding_description": "Када ҘĐĩ ĐžĐŧĐžĐŗŅƒŅ›ĐĩĐŊа, Ова Ņ„ŅƒĐŊĐēŅ†Đ¸Ņ˜Đ° Ņ›Đĩ Đ°ŅƒŅ‚ĐžĐŧĐ°Ņ‚ŅĐēи ĐžŅ€ĐŗĐ°ĐŊĐ¸ĐˇĐžĐ˛Đ°Ņ‚Đ¸ Đ´Đ°Ņ‚ĐžŅ‚ĐĩĐēĐĩ ĐŊа ĐžŅĐŊĐžĐ˛Ņƒ ŅˆĐ°ĐąĐģĐžĐŊа ĐēĐžŅ˜Đ¸ Đ´ĐĩŅ„Đ¸ĐŊĐ¸ŅˆĐĩ ĐēĐžŅ€Đ¸ŅĐŊиĐē. Đ—ĐąĐžĐŗ ĐŋŅ€ĐžĐąĐģĐĩĐŧа ŅĐ° ŅŅ‚Đ°ĐąĐ¸ĐģĐŊĐžŅˆŅ›Ņƒ Ова Ņ„ŅƒĐŊĐēŅ†Đ¸Ņ˜Đ° ҘĐĩ ĐŋĐžĐ´Ņ€Đ°ĐˇŅƒĐŧĐĩваĐŊĐž Đ¸ŅĐēŅ™ŅƒŅ‡ĐĩĐŊа. За Đ˛Đ¸ŅˆĐĩ иĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Ņ˜Đ° ĐŋĐžĐŗĐģĐĩĐ´Đ°Ņ˜Ņ‚Đĩ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸Ņ˜Ņƒ.", @@ -310,7 +310,7 @@ "transcoding_max_b_frames": "МаĐēŅĐ¸ĐŧаĐģĐŊи Б-ĐēĐ°Đ´Ņ€Đ¸", "transcoding_max_b_frames_description": "Đ’Đ¸ŅˆĐĩ Đ˛Ņ€ĐĩĐ´ĐŊĐžŅŅ‚Đ¸ ĐŋĐžĐąĐžŅ™ŅˆĐ°Đ˛Đ°Ņ˜Ņƒ ĐĩŅ„Đ¸ĐēĐ°ŅĐŊĐžŅŅ‚ ĐēĐžĐŧĐŋŅ€ĐĩŅĐ¸Ņ˜Đĩ, аĐģи ҃ҁĐŋĐžŅ€Đ°Đ˛Đ°Ņ˜Ņƒ ĐēĐžĐ´Đ¸Ņ€Đ°ŅšĐĩ. МоĐļда ĐŊĐ¸Ņ˜Đĩ ĐēĐžĐŧĐŋĐ°Ņ‚Đ¸ĐąĐ¸ĐģĐŊĐž ŅĐ° Ņ…Đ°Ņ€Đ´Đ˛ĐĩҀҁĐēиĐŧ ŅƒĐąŅ€ĐˇĐ°ŅšĐĩĐŧ ĐŊа ŅŅ‚Đ°Ņ€Đ¸Ņ˜Đ¸Đŧ ŅƒŅ€ĐĩŅ’Đ°Ņ˜Đ¸Đŧа. 0 oneĐŧĐžĐŗŅƒŅ›Đ°Đ˛Đ° Б-ĐēĐ°Đ´Ņ€Đĩ, Đ´ĐžĐē -1 Đ°ŅƒŅ‚ĐžĐŧĐ°Ņ‚ŅĐēи ĐŋĐžŅŅ‚Đ°Đ˛Ņ™Đ° ĐžĐ˛Ņƒ Đ˛Ņ€ĐĩĐ´ĐŊĐžŅŅ‚.", "transcoding_max_bitrate": "МаĐēŅĐ¸ĐŧаĐģĐŊи ĐąĐ¸Ņ‚Ņ€Đ°Ņ‚Đĩ", - "transcoding_max_bitrate_description": "ПодĐĩŅˆĐ°Đ˛Đ°ŅšĐĩ ĐŧаĐēŅĐ¸ĐŧаĐģĐŊĐžĐŗ ĐąĐ¸Ņ‚Ņ€Đ°Ņ‚Đĩ-а ĐŧĐžĐļĐĩ ŅƒŅ‡Đ¸ĐŊĐ¸Ņ‚Đ¸ вĐĩĐģĐ¸Ņ‡Đ¸ĐŊĐĩ Đ´Đ°Ņ‚ĐžŅ‚ĐĩĐēа ĐŋŅ€ĐĩĐ´Đ˛Đ¸Đ´Ņ™Đ¸Đ˛Đ¸Ņ˜Đ¸Đŧ ŅƒĐˇ ĐŧĐ°ŅšŅƒ ҆ĐĩĐŊ҃ ĐēваĐģĐ¸Ņ‚ĐĩŅ‚Đ°. ĐŸŅ€Đ¸ 720Đŋ, Ņ‚Đ¸ĐŋĐ¸Ņ‡ĐŊĐĩ Đ˛Ņ€ĐĩĐ´ĐŊĐžŅŅ‚Đ¸ ҁ҃ 2600kbit/s Са ВП9 иĐģи ĐĨЕВĐĻ, иĐģи 4500kbit/s Са ĐĨ.264. oneĐŧĐžĐŗŅƒŅ›ĐĩĐŊĐž аĐēĐž ҘĐĩ ĐŋĐžŅŅ‚Đ°Đ˛Ņ™ĐĩĐŊĐž ĐŊа 0.", + "transcoding_max_bitrate_description": "ПодĐĩŅˆĐ°Đ˛Đ°ŅšĐĩ ĐŧаĐēŅĐ¸ĐŧаĐģĐŊĐžĐŗ ĐąĐ¸Ņ‚Ņ€Đ°Ņ‚Đĩ-а ĐŧĐžĐļĐĩ ŅƒŅ‡Đ¸ĐŊĐ¸Ņ‚Đ¸ вĐĩĐģĐ¸Ņ‡Đ¸ĐŊĐĩ Đ´Đ°Ņ‚ĐžŅ‚ĐĩĐēа ĐŋŅ€ĐĩĐ´Đ˛Đ¸Đ´Ņ™Đ¸Đ˛Đ¸Ņ˜Đ¸Đŧ ŅƒĐˇ ĐŧĐ°ŅšŅƒ ҆ĐĩĐŊ҃ ĐēваĐģĐ¸Ņ‚ĐĩŅ‚Đ°. ĐŸŅ€Đ¸ 720Đŋ, Ņ‚Đ¸ĐŋĐ¸Ņ‡ĐŊĐĩ Đ˛Ņ€ĐĩĐ´ĐŊĐžŅŅ‚Đ¸ ҁ҃ 2600Đē Са ВП9 иĐģи ĐĨЕВĐĻ, иĐģи 4500Đē Са ĐĨ.264. oneĐŧĐžĐŗŅƒŅ›ĐĩĐŊĐž аĐēĐž ҘĐĩ ĐŋĐžŅŅ‚Đ°Đ˛Ņ™ĐĩĐŊĐž ĐŊа 0.", "transcoding_max_keyframe_interval": "МаĐēŅĐ¸ĐŧаĐģĐŊи иĐŊŅ‚ĐĩŅ€Đ˛Đ°Đģ keyframe-a", "transcoding_max_keyframe_interval_description": "ĐŸĐžŅŅ‚Đ°Đ˛Ņ™Đ° ĐŧаĐēŅĐ¸ĐŧаĐģĐŊ҃ ŅƒĐ´Đ°Ņ™ĐĩĐŊĐžŅŅ‚ ĐēĐ°Đ´Ņ€ĐžĐ˛Đ° иСĐŧĐĩŅ’Ņƒ ĐēŅ™ŅƒŅ‡ĐŊĐ¸Ņ… ĐēĐ°Đ´Ņ€ĐžĐ˛Đ°. НиĐļĐĩ Đ˛Ņ€ĐĩĐ´ĐŊĐžŅŅ‚Đ¸ ĐŋĐžĐŗĐžŅ€ŅˆĐ°Đ˛Đ°Ņ˜Ņƒ ĐĩŅ„Đ¸ĐēĐ°ŅĐŊĐžŅŅ‚ ĐēĐžĐŧĐŋŅ€ĐĩŅĐ¸Ņ˜Đĩ, аĐģи ĐŋĐžĐąĐžŅ™ŅˆĐ°Đ˛Đ°Ņ˜Ņƒ Đ˛Ņ€ĐĩĐŧĐĩ Ņ‚Ņ€Đ°ĐļĐĩŅšĐ° и ĐŧĐžĐŗŅƒ ĐŋĐžĐąĐžŅ™ŅˆĐ°Ņ‚Đ¸ ĐēваĐģĐ¸Ņ‚ĐĩŅ‚ ҁ҆ĐĩĐŊа ŅĐ° ĐąŅ€ĐˇĐ¸Đŧ ĐēŅ€ĐĩŅ‚Đ°ŅšĐĩĐŧ. 0 Đ°ŅƒŅ‚ĐžĐŧĐ°Ņ‚ŅĐēи ĐŋĐžŅŅ‚Đ°Đ˛Ņ™Đ° ĐžĐ˛Ņƒ Đ˛Ņ€ĐĩĐ´ĐŊĐžŅŅ‚.", "transcoding_optimal_description": "ВидĐĩĐž ҁĐŊиĐŧŅ†Đ¸ вĐĩŅ›Đ¸ Од Ņ†Đ¸Ņ™ĐŊĐĩ Ņ€ĐĩСОĐģŅƒŅ†Đ¸Ņ˜Đĩ иĐģи ĐŊĐ¸ŅŅƒ ҃ ĐŋŅ€Đ¸Ņ…Đ˛Đ°Ņ›ĐĩĐŊĐžĐŧ Ņ„ĐžŅ€ĐŧĐ°Ņ‚Ņƒ", @@ -324,7 +324,7 @@ "transcoding_reference_frames_description": "Đ‘Ņ€ĐžŅ˜ ĐžĐēĐ˛Đ¸Ņ€Đ° (Ņ„Ņ€Đ°ĐŧĐĩҁ) Са Ņ€ĐĩŅ„ĐĩŅ€ĐĩĐŊŅ†Ņƒ ĐŋŅ€Đ¸ĐģиĐēĐžĐŧ ĐēĐžĐŧĐŋŅ€ĐĩŅĐ¸Ņ˜Đĩ Đ´Đ°Ņ‚ĐžĐŗ ĐžĐēĐ˛Đ¸Ņ€Đ°. Đ’Đ¸ŅˆĐĩ Đ˛Ņ€ĐĩĐ´ĐŊĐžŅŅ‚Đ¸ ĐŋĐžĐąĐžŅ™ŅˆĐ°Đ˛Đ°Ņ˜Ņƒ ĐĩŅ„Đ¸ĐēĐ°ŅĐŊĐžŅŅ‚ ĐēĐžĐŧĐŋŅ€ĐĩŅĐ¸Ņ˜Đĩ, аĐģи ҃ҁĐŋĐžŅ€Đ°Đ˛Đ°Ņ˜Ņƒ ĐēĐžĐ´Đ¸Ņ€Đ°ŅšĐĩ. 0 Đ°ŅƒŅ‚ĐžĐŧĐ°Ņ‚ŅĐēи ĐŋĐžŅŅ‚Đ°Đ˛Ņ™Đ° ĐžĐ˛Ņƒ Đ˛Ņ€ĐĩĐ´ĐŊĐžŅŅ‚.", "transcoding_required_description": "ХаĐŧĐž видĐĩĐž ҁĐŊиĐŧŅ†Đ¸ ĐēĐžŅ˜Đ¸ ĐŊĐ¸ŅŅƒ ҃ ĐŋŅ€Đ¸Ņ…Đ˛Đ°Ņ›ĐĩĐŊĐžĐŧ Ņ„ĐžŅ€ĐŧĐ°Ņ‚Ņƒ", "transcoding_settings": "ПодĐĩŅˆĐ°Đ˛Đ°ŅšĐ° видĐĩĐž Ņ‚Ņ€Đ°ĐŊҁĐēĐžĐ´Đ¸Ņ€Đ°ŅšĐ°", - "transcoding_settings_description": "ĐŖĐŋŅ€Đ°Đ˛Ņ™Đ°Ņ˜Ņ‚Đĩ ĐēĐžŅ˜Đĩ видĐĩĐž ҁĐŊиĐŧĐēĐĩ ĐļĐĩĐģĐ¸Ņ‚Đĩ да Ņ‚Ņ€Đ°ĐŊҁĐēĐžĐ´ŅƒŅ˜ĐĩŅ‚Đĩ и ĐēаĐēĐž Đ¸Ņ… ĐžĐąŅ€Đ°Đ´Đ¸Ņ‚Đ¸", + "transcoding_settings_description": "ĐŖĐŋŅ€Đ°Đ˛Ņ™Đ°Ņ˜Ņ‚Đĩ Ņ€ĐĩСОĐģŅƒŅ†Đ¸Ņ˜ĐžĐŧ и иĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Ņ˜Đ°Đŧа Đž ĐēĐžĐ´Đ¸Ņ€Đ°ŅšŅƒ видĐĩĐž Đ´Đ°Ņ‚ĐžŅ‚ĐĩĐēа", "transcoding_target_resolution": "ĐĻĐ¸Ņ™Đ°ĐŊа Ņ€ĐĩСОĐģŅƒŅ†Đ¸Ņ˜Đ°", "transcoding_target_resolution_description": "ВĐĩŅ›Đĩ Ņ€ĐĩСОĐģŅƒŅ†Đ¸Ņ˜Đĩ ĐŧĐžĐŗŅƒ да ŅĐ°Ņ‡ŅƒĐ˛Đ°Ņ˜Ņƒ Đ˛Đ¸ŅˆĐĩ Đ´ĐĩŅ‚Đ°Ņ™Đ°, аĐģи иĐŧ ҘĐĩ ĐŋĐžŅ‚Ņ€ĐĩĐąĐŊĐž Đ˛Đ¸ŅˆĐĩ Đ˛Ņ€ĐĩĐŧĐĩĐŊа Са ĐēĐžĐ´Đ¸Ņ€Đ°ŅšĐĩ, иĐŧĐ°Ņ˜Ņƒ вĐĩŅ›Đĩ вĐĩĐģĐ¸Ņ‡Đ¸ĐŊĐĩ Đ´Đ°Ņ‚ĐžŅ‚ĐĩĐēа и ĐŧĐžĐŗŅƒ да ҁĐŧĐ°ŅšĐĩ ĐąŅ€ĐˇĐ¸ĐŊ҃ аĐŋĐģиĐēĐ°Ņ†Đ¸Ņ˜Đĩ.", "transcoding_temporal_aq": "Đ’Ņ€ĐĩĐŧĐĩĐŊҁĐēи (ĐĸĐĩĐŧĐŋĐžŅ€Đ°Đģ) AQ", @@ -371,13 +371,17 @@ "admin_password": "АдĐŧиĐŊĐ¸ŅŅ‚Ņ€Đ°Ņ‚ĐžŅ€ŅĐēа ЛозиĐŊĐēа", "administration": "АдĐŧиĐŊĐ¸ŅŅ‚Ņ€Đ°Ņ†Đ¸Ņ˜Đ°", "advanced": "НаĐŋŅ€ĐĩĐ´ĐŊĐž", - "advanced_settings_log_level_title": "Log level: {}", - "advanced_settings_prefer_remote_subtitle": "Some devices are painfully slow to load thumbnails from assets on the device. Activate this setting to load remote images instead.", - "advanced_settings_prefer_remote_title": "Prefer remote images", - "advanced_settings_proxy_headers_subtitle": "Define proxy headers Immich should send with each network request", - "advanced_settings_proxy_headers_title": "Proxy Headers", - "advanced_settings_self_signed_ssl_subtitle": "Skips SSL certificate verification for the server endpoint. Required for self-signed certificates.", - "advanced_settings_self_signed_ssl_title": "Allow self-signed SSL certificates", + "advanced_settings_enable_alternate_media_filter_subtitle": "ĐšĐžŅ€Đ¸ŅŅ‚Đ¸Ņ‚Đĩ ĐžĐ˛Ņƒ ĐžĐŋŅ†Đ¸Ņ˜Ņƒ Са Ņ„Đ¸ĐģŅ‚Ņ€Đ¸Ņ€Đ°ŅšĐĩ ĐŧĐĩĐ´Đ¸Ņ˜Đ° Ņ‚ĐžĐēĐžĐŧ ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Ņ˜Đĩ ĐŊа ĐžŅĐŊĐžĐ˛Ņƒ аĐģŅ‚ĐĩŅ€ĐŊĐ°Ņ‚Đ¸Đ˛ĐŊĐ¸Ņ… ĐēŅ€Đ¸Ņ‚ĐĩŅ€Đ¸Ņ˜ŅƒĐŧа. ПоĐēŅƒŅˆĐ°Ņ˜Ņ‚Đĩ ОвО ŅĐ°ĐŧĐž аĐēĐž иĐŧĐ°Ņ‚Đĩ ĐŋŅ€ĐžĐąĐģĐĩĐŧа ŅĐ° аĐŋĐģиĐēĐ°Ņ†Đ¸Ņ˜ĐžĐŧ да ĐžŅ‚ĐēŅ€Đ¸Ņ˜Đĩ ŅĐ˛Đĩ аĐģĐąŅƒĐŧĐĩ.", + "advanced_settings_enable_alternate_media_filter_title": "[ЕКСПЕРИМЕНĐĸАЛНО] ĐšĐžŅ€Đ¸ŅŅ‚Đ¸Ņ‚Đĩ Ņ„Đ¸ĐģŅ‚ĐĩŅ€ Са ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Ņ˜Ņƒ аĐģĐąŅƒĐŧа ĐŊа аĐģŅ‚ĐĩŅ€ĐŊĐ°Ņ‚Đ¸Đ˛ĐŊĐžĐŧ ŅƒŅ€ĐĩŅ’Đ°Ņ˜Ņƒ", + "advanced_settings_log_level_title": "Ниво ĐĩвидĐĩĐŊŅ†Đ¸Ņ˜Đĩ(log): {}", + "advanced_settings_prefer_remote_subtitle": "НĐĩĐēи ŅƒŅ€ĐĩŅ’Đ°Ņ˜Đ¸ вĐĩĐžĐŧа ҁĐŋĐžŅ€Đž ŅƒŅ‡Đ¸Ņ‚Đ°Đ˛Đ°Ņ˜Ņƒ ҁĐģĐ¸Ņ‡Đ¸Ņ†Đĩ ŅĐ° ҁҀĐĩĐ´ŅŅ‚Đ°Đ˛Đ° ĐŊа ŅƒŅ€ĐĩŅ’Đ°Ņ˜Ņƒ. АĐēŅ‚Đ¸Đ˛Đ¸Ņ€Đ°Ņ˜Ņ‚Đĩ ОвО ĐŋОдĐĩŅˆĐ°Đ˛Đ°ŅšĐĩ да ĐąĐ¸ŅŅ‚Đĩ ҃ĐŧĐĩŅŅ‚Đž Ņ‚ĐžĐŗĐ° ŅƒŅ‡Đ¸Ņ‚Đ°Đģи ŅƒĐ´Đ°Ņ™ĐĩĐŊĐĩ ҁĐģиĐēĐĩ.", + "advanced_settings_prefer_remote_title": "ĐŸŅ€ĐĩŅ„ĐĩŅ€Đ¸Ņ€Đ°Ņ˜Ņ‚Đĩ ŅƒĐ´Đ°Ņ™ĐĩĐŊĐĩ ҁĐģиĐēĐĩ", + "advanced_settings_proxy_headers_subtitle": "ДĐĩŅ„Đ¸ĐŊĐ¸ŅˆĐ¸Ņ‚Đĩ ĐŋŅ€ĐžĐēŅĐ¸ ĐˇĐ°ĐŗĐģĐ°Đ˛Ņ™Đ° ĐēĐžŅ˜Đĩ ИĐŧĐ¸Ņ‡ ҂ҀĐĩйа да ĐŋĐžŅˆĐ°Ņ™Đĩ ŅĐ° ŅĐ˛Đ°ĐēиĐŧ ĐŧŅ€ĐĩĐļĐŊиĐŧ ĐˇĐ°Ņ…Ņ‚ĐĩвОĐŧ", + "advanced_settings_proxy_headers_title": "ĐŸŅ€ĐžĐēŅĐ¸ ĐĨĐĩадĐĩŅ€Đ¸ (headers)", + "advanced_settings_self_signed_ssl_subtitle": "ĐŸŅ€ĐĩҁĐēĐ°Ņ‡Đĩ вĐĩŅ€Đ¸Ņ„Đ¸ĐēĐ°Ņ†Đ¸Ņ˜Ņƒ SSL ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚Đ° Са ĐēŅ€Đ°Ņ˜ŅšŅƒ Ņ‚Đ°Ņ‡Đē҃ ҁĐĩŅ€Đ˛ĐĩŅ€Đ°. ОбавĐĩСĐŊĐž Са ŅĐ°ĐŧĐžĐŋĐžŅ‚ĐŋĐ¸ŅĐ°ĐŊĐĩ ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚Đĩ.", + "advanced_settings_self_signed_ssl_title": "ДозвоĐģĐ¸Ņ‚Đĩ ŅĐ°ĐŧĐžĐŋĐžŅ‚ĐŋĐ¸ŅĐ°ĐŊĐĩ SSL ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚Đĩ", + "advanced_settings_sync_remote_deletions_subtitle": "ĐŅƒŅ‚ĐžĐŧĐ°Ņ‚ŅĐēи Đ¸ĐˇĐąŅ€Đ¸ŅˆĐ¸Ņ‚Đĩ иĐģи Đ˛Ņ€Đ°Ņ‚Đ¸Ņ‚Đĩ ҁҀĐĩĐ´ŅŅ‚Đ˛Đž ĐŊа ОвОĐŧ ŅƒŅ€ĐĩŅ’Đ°Ņ˜Ņƒ Đēада ҁĐĩ Ņ‚Đ° Ņ€Đ°Đ´ŅšĐ° ĐŋŅ€ĐĩĐ´ŅƒĐˇĐŧĐĩ ĐŊа вĐĩĐąŅƒ", + "advanced_settings_sync_remote_deletions_title": "ХиĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇŅƒŅ˜Ņ‚Đĩ ŅƒĐ´Đ°Ņ™ĐĩĐŊа ĐąŅ€Đ¸ŅĐ°ŅšĐ° [ЕКСПЕРИМЕНĐĸАЛНО]", "advanced_settings_tile_subtitle": "Advanced user's settings", "advanced_settings_troubleshooting_subtitle": "Enable additional features for troubleshooting", "advanced_settings_troubleshooting_title": "Troubleshooting", @@ -400,9 +404,9 @@ "album_remove_user_confirmation": "Да Đģи ҁ҂Đĩ ŅĐ¸ĐŗŅƒŅ€ĐŊи да ĐļĐĩĐģĐ¸Ņ‚Đĩ да ҃ĐēĐģĐžĐŊĐ¸Ņ‚Đĩ {user}?", "album_share_no_users": "Đ˜ĐˇĐŗĐģĐĩда да ҁ҂Đĩ ĐŋОдĐĩĐģиĐģи ĐžĐ˛Đ°Ņ˜ аĐģĐąŅƒĐŧ ŅĐ° ŅĐ˛Đ¸Đŧ ĐēĐžŅ€Đ¸ŅĐŊĐ¸Ņ†Đ¸Đŧа иĐģи да ĐŊĐĩĐŧĐ°Ņ‚Đĩ ĐŊĐ¸Ņ˜ĐĩĐ´ĐŊĐžĐŗ ĐēĐžŅ€Đ¸ŅĐŊиĐēа ŅĐ° ĐēĐžŅ˜Đ¸Đŧ ĐąĐ¸ŅŅ‚Đĩ Đ´ĐĩĐģиĐģи.", "album_thumbnail_card_item": "1 item", - "album_thumbnail_card_items": "{} items", + "album_thumbnail_card_items": "{} ŅŅ‚Đ°Đ˛ĐēĐĩ", "album_thumbnail_card_shared": " ¡ Shared", - "album_thumbnail_shared_by": "Shared by {}", + "album_thumbnail_shared_by": "ДĐĩĐģи {}", "album_updated": "АĐģĐąŅƒĐŧ аĐļŅƒŅ€Đ¸Ņ€Đ°ĐŊ", "album_updated_setting_description": "ĐŸŅ€Đ¸ĐŧĐ¸Ņ‚Đĩ ОйавĐĩŅˆŅ‚ĐĩҚĐĩ Đĩ-ĐŋĐžŅˆŅ‚ĐžĐŧ Đēада Đ´ĐĩŅ™ĐĩĐŊи аĐģĐąŅƒĐŧ иĐŧа ĐŊОва ŅĐ˛ĐžŅ˜ŅŅ‚Đ˛Đ°", "album_user_left": "НаĐŋŅƒŅŅ‚Đ¸Đž/Đģа {album}", @@ -443,7 +447,7 @@ "archive_page_title": "Archive ({})", "archive_size": "ВĐĩĐģĐ¸Ņ‡Đ¸ĐŊа Đ°Ņ€Ņ…Đ¸Đ˛Đĩ", "archive_size_description": "ПодĐĩŅĐ¸ вĐĩĐģĐ¸Ņ‡Đ¸ĐŊ҃ Đ°Ņ€Ņ…Đ¸Đ˛Đĩ Са ĐŋŅ€ĐĩŅƒĐˇĐ¸ĐŧĐ°ŅšĐĩ (҃ ГиБ)", - "archived": "Archived", + "archived": "Arhivirano", "archived_count": "{count, plural, other {ĐŅ€Ņ…Đ¸Đ˛Đ¸Ņ€Đ°ĐŊĐž #}}", "are_these_the_same_person": "Да Đģи ҁ҃ ОвО Đ¸ŅŅ‚Đ° ĐžŅĐžĐąĐ°?", "are_you_sure_to_do_this": "ЈĐĩҁ҂Đĩ Đģи ŅĐ¸ĐŗŅƒŅ€ĐŊи да ĐļĐĩĐģĐ¸Ņ‚Đĩ ОвО да ŅƒŅ€Đ°Đ´Đ¸Ņ‚Đĩ?", @@ -992,6 +996,7 @@ "filetype": "Đ’Ņ€ŅŅ‚Đ° Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°", "filter": "Filter", "filter_people": "ФиĐģŅ‚Ņ€Đ¸Ņ€Đ°ŅšĐĩ ĐžŅĐžĐąĐ°", + "filter_places": "ФиĐģŅ‚Ņ€Đ¸Ņ€Đ°Ņ˜Ņ‚Đĩ ĐŧĐĩŅŅ‚Đ°", "find_them_fast": "Đ‘Ņ€ĐˇĐž Đ¸Ņ… ĐŋŅ€ĐžĐŊĐ°Ņ’Đ¸Ņ‚Đĩ ĐŋĐž иĐŧĐĩĐŊ҃ ĐŋĐžĐŧĐžŅ›Ņƒ ĐŋŅ€ĐĩŅ‚Ņ€Đ°ĐŗĐĩ", "fix_incorrect_match": "Đ˜ŅĐŋŅ€Đ°Đ˛Đ¸Ņ‚Đĩ ĐŊĐĩŅ‚Đ°Ņ‡ĐŊĐž ĐŋĐžĐ´ŅƒĐ´Đ°Ņ€Đ°ŅšĐĩ", "folder": "Folder", @@ -1282,6 +1287,7 @@ "onboarding_welcome_user": "Đ”ĐžĐąŅ€ĐžĐ´ĐžŅˆĐģи, {user}", "online": "Đ”ĐžŅŅ‚ŅƒĐŋаĐŊ (ОĐŊĐģиĐŊĐĩ)", "only_favorites": "ХаĐŧĐž Ņ„Đ°Đ˛ĐžŅ€Đ¸Ņ‚Đ¸", + "open": "ĐžŅ‚Đ˛ĐžŅ€Đ¸", "open_in_map_view": "ĐžŅ‚Đ˛ĐžŅ€Đ¸ ҃ ĐŋŅ€Đ¸ĐēĐ°ĐˇŅƒ ĐŧаĐŋĐĩ", "open_in_openstreetmap": "ĐžŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đĩ ҃ ОĐŋĐĩĐŊĐĄŅ‚Ņ€ĐĩĐĩŅ‚ĐœĐ°Đŋ-҃", "open_the_search_filters": "ĐžŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đĩ Ņ„Đ¸ĐģŅ‚ĐĩŅ€Đĩ Са ĐŋŅ€ĐĩŅ‚Ņ€Đ°ĐŗŅƒ", @@ -1849,7 +1855,7 @@ "variables": "ĐŸŅ€ĐžĐŧĐĩĐŊŅ™Đ¸Đ˛Đĩ (Đ˛Đ°Ņ€Đ¸Đ°ĐąĐģĐĩҁ)", "version": "ВĐĩŅ€ĐˇĐ¸Ņ˜Đ°", "version_announcement_closing": "ĐĸĐ˛ĐžŅ˜ ĐŋŅ€Đ¸Ņ˜Đ°Ņ‚ĐĩŅ™, АĐģĐĩĐēҁ", - "version_announcement_message": "Đ—Đ´Ņ€Đ°Đ˛Đž ĐŋŅ€Đ¸Ņ˜Đ°Ņ‚ĐĩŅ™Ņƒ, ĐŋĐžŅŅ‚ĐžŅ˜Đ¸ ĐŊОва вĐĩŅ€ĐˇĐ¸Ņ˜Đ° аĐŋĐģиĐēĐ°Ņ†Đ¸Ņ˜Đĩ, ĐŧĐžĐģиĐŧĐž Đ˛Đ°Ņ да ĐžĐ´Đ˛ĐžŅ˜Đ¸Ņ‚Đĩ Đ˛Ņ€ĐĩĐŧĐĩ да ĐŋĐžŅĐĩŅ‚Đ¸Ņ‚Đĩ ĐŊаĐŋĐžĐŧĐĩĐŊĐĩ Đž Đ¸ĐˇĐ´Đ°ŅšŅƒ и ŅƒĐ˛ĐĩŅ€Đ¸Ņ‚Đĩ ҁĐĩ да ҘĐĩ ҁĐĩŅ€Đ˛ĐĩŅ€ аĐļŅƒŅ€Đ¸Ņ€Đ°ĐŊ ĐēаĐēĐž йи ҁĐĩ ҁĐŋŅ€ĐĩŅ‡Đ¸ĐģĐĩ йиĐģĐž ĐēаĐēвĐĩ ĐŋĐžĐŗŅ€Đĩ҈ĐŊĐĩ ĐēĐžĐŊŅ„Đ¸ĐŗŅƒŅ€Đ°Ņ†Đ¸Ņ˜Đĩ, ĐŋĐžŅĐĩĐąĐŊĐž аĐēĐž ĐēĐžŅ€Đ¸ŅŅ‚Đ¸Ņ‚Đĩ WatchTower иĐģи йиĐģĐž ĐēĐžŅ˜Đ¸ ĐŧĐĩŅ…Đ°ĐŊиСаĐŧ ĐēĐžŅ˜Đ¸ Đ°ŅƒŅ‚ĐžĐŧĐ°Ņ‚ŅĐēи ҃ĐŋŅ€Đ°Đ˛Ņ™Đ° аĐļŅƒŅ€Đ¸Ņ€Đ°ŅšĐĩĐŧ Đ˛Đ°ŅˆĐĩ аĐŋĐģиĐēĐ°Ņ†Đ¸Ņ˜Đĩ.", + "version_announcement_message": "Đ—Đ´Ņ€Đ°Đ˛Đž ĐŋŅ€Đ¸Ņ˜Đ°Ņ‚ĐĩŅ™Ņƒ, ĐŋĐžŅŅ‚ĐžŅ˜Đ¸ ĐŊОва вĐĩŅ€ĐˇĐ¸Ņ˜Đ° аĐŋĐģиĐēĐ°Ņ†Đ¸Ņ˜Đĩ, ĐŧĐžĐģиĐŧĐž Đ˛Đ°Ņ да ĐžĐ´Đ˛ĐžŅ˜Đ¸Ņ‚Đĩ Đ˛Ņ€ĐĩĐŧĐĩ да ĐŋĐžŅĐĩŅ‚Đ¸Ņ‚Đĩ ĐŊаĐŋĐžĐŧĐĩĐŊĐĩ Đž Đ¸ĐˇĐ´Đ°ŅšŅƒ и ŅƒĐ˛ĐĩŅ€Đ¸Ņ‚Đĩ ҁĐĩ ҃ ŅĐ˛ĐžŅ˜Đĩ docker-compose.yml, и .env ĐŋОдĐĩŅˆĐ°Đ˛Đ°ŅšĐĩ ҘĐĩ аĐļŅƒŅ€Đ¸Ņ€Đ°ĐŊĐž ĐēаĐēĐž йи ҁĐĩ ҁĐŋŅ€ĐĩŅ‡Đ¸ĐģĐĩ йиĐģĐž ĐēаĐēвĐĩ ĐŋĐžĐŗŅ€Đĩ҈ĐŊĐĩ ĐēĐžĐŊŅ„Đ¸ĐŗŅƒŅ€Đ°Ņ†Đ¸Ņ˜Đĩ, ĐŋĐžŅĐĩĐąĐŊĐž аĐēĐž ĐēĐžŅ€Đ¸ŅŅ‚Đ¸Ņ‚Đĩ WatchTower иĐģи йиĐģĐž ĐēĐžŅ˜Đ¸ ĐŧĐĩŅ…Đ°ĐŊиСаĐŧ ĐēĐžŅ˜Đ¸ Đ°ŅƒŅ‚ĐžĐŧĐ°Ņ‚ŅĐēи ҃ĐŋŅ€Đ°Đ˛Ņ™Đ° аĐļŅƒŅ€Đ¸Ņ€Đ°ŅšĐĩĐŧ Đ˛Đ°ŅˆĐĩ аĐŋĐģиĐēĐ°Ņ†Đ¸Ņ˜Đĩ.", "version_announcement_overlay_release_notes": "release notes", "version_announcement_overlay_text_1": "Hi friend, there is a new release of", "version_announcement_overlay_text_2": "please take your time to visit the ", diff --git a/i18n/sr_Latn.json b/i18n/sr_Latn.json index c3280ee4fb..093bf06df7 100644 --- a/i18n/sr_Latn.json +++ b/i18n/sr_Latn.json @@ -14,7 +14,7 @@ "add_a_location": "Dodaj Lokaciju", "add_a_name": "Dodaj ime", "add_a_title": "Dodaj naslov", - "add_endpoint": "Add endpoint", + "add_endpoint": "Dodajte krajnju tačku", "add_exclusion_pattern": "Dodaj obrazac izuzimanja", "add_import_path": "Dodaj putanju za preuzimanje", "add_location": "Dodaj lokaciju", @@ -371,13 +371,17 @@ "admin_password": "Administratorska Lozinka", "administration": "Administracija", "advanced": "Napredno", - "advanced_settings_log_level_title": "Log level: {}", - "advanced_settings_prefer_remote_subtitle": "Some devices are painfully slow to load thumbnails from assets on the device. Activate this setting to load remote images instead.", - "advanced_settings_prefer_remote_title": "Prefer remote images", - "advanced_settings_proxy_headers_subtitle": "Define proxy headers Immich should send with each network request", - "advanced_settings_proxy_headers_title": "Proxy Headers", - "advanced_settings_self_signed_ssl_subtitle": "Skips SSL certificate verification for the server endpoint. Required for self-signed certificates.", + "advanced_settings_enable_alternate_media_filter_subtitle": "Koristite ovu opciju za filtriranje medija tokom sinhronizacije na osnovu alternativnih kriterijuma. PokuÅĄajte ovo samo ako imate problema sa aplikacijom da otkrije sve albume.", + "advanced_settings_enable_alternate_media_filter_title": "[EKSPERIMENTALNO] Koristite filter za sinhronizaciju albuma na alternativnom uređaju", + "advanced_settings_log_level_title": "Nivo evidencije (log): {}", + "advanced_settings_prefer_remote_subtitle": "Neki uređaji veoma sporo učitavaju sličice sa sredstava na uređaju. Aktivirajte ovo podeÅĄavanje da biste umesto toga učitali udaljene slike.", + "advanced_settings_prefer_remote_title": "Preferirajte udaljene slike", + "advanced_settings_proxy_headers_subtitle": "DefiniÅĄite proksi zaglavlja koje Immich treba da poÅĄalje sa svakim mreÅžnim zahtevom", + "advanced_settings_proxy_headers_title": "Proksi Headeri (headers)", + "advanced_settings_self_signed_ssl_subtitle": "Preskače verifikaciju SSL sertifikata za krajnju tačku servera. Obavezno za samopotpisane sertifikate.", "advanced_settings_self_signed_ssl_title": "Allow self-signed SSL certificates", + "advanced_settings_sync_remote_deletions_subtitle": "Automatski izbriÅĄite ili vratite sredstvo na ovom uređaju kada se ta radnja preduzme na vebu", + "advanced_settings_sync_remote_deletions_title": "Sinhronizujte udaljena brisanja [EKSPERIMENTALNO]", "advanced_settings_tile_subtitle": "Advanced user's settings", "advanced_settings_troubleshooting_subtitle": "Enable additional features for troubleshooting", "advanced_settings_troubleshooting_title": "Troubleshooting", @@ -402,7 +406,7 @@ "album_thumbnail_card_item": "1 stavka", "album_thumbnail_card_items": "{} stavki", "album_thumbnail_card_shared": "Deljeno", - "album_thumbnail_shared_by": "Shared by {}", + "album_thumbnail_shared_by": "Deli {}", "album_updated": "Album aÅžuriran", "album_updated_setting_description": "Primite obaveÅĄtenje e-poÅĄtom kada deljeni album ima nova svojstva", "album_user_left": "Napustio/la {album}", @@ -529,11 +533,11 @@ "backup_controller_page_background_turn_on": "Uključi pozadinski servis", "backup_controller_page_background_wifi": "Samo na WiFi", "backup_controller_page_backup": "Napravi rezervnu kopiju", - "backup_controller_page_backup_selected": "Odabrano:", + "backup_controller_page_backup_selected": "Odabrano: ", "backup_controller_page_backup_sub": "ZavrÅĄeno pravljenje rezervne kopije fotografija i videa", "backup_controller_page_created": "Napravljeno:{}", "backup_controller_page_desc_backup": "Uključi pravljenje rezervnih kopija u prvom planu da automatski napravite rezervne kopije kada otvorite aplikaciju.", - "backup_controller_page_excluded": "Isključeno:", + "backup_controller_page_excluded": "Isključeno: ", "backup_controller_page_failed": "NeuspeÅĄno ({})", "backup_controller_page_filename": "Ime fajla:{} [{}]", "backup_controller_page_id": "ID:{}", @@ -992,6 +996,7 @@ "filetype": "Vrsta dokumenta", "filter": "Filter", "filter_people": "Filtriranje osoba", + "filter_places": "Filtrirajte mesta", "find_them_fast": "Brzo ih pronađite po imenu pomocˁu pretrage", "fix_incorrect_match": "Ispravite netačno podudaranje", "folder": "Folder", @@ -1282,6 +1287,7 @@ "onboarding_welcome_user": "DobrodoÅĄli, {user}", "online": "Dostupan (Online)", "only_favorites": "Samo favoriti", + "open": "Otvori", "open_in_map_view": "Otvorite u prikaz karte", "open_in_openstreetmap": "Otvorite u OpenStreetMap-u", "open_the_search_filters": "Otvorite filtere za pretragu", diff --git a/i18n/sv.json b/i18n/sv.json index a727aa68e2..fff282f99f 100644 --- a/i18n/sv.json +++ b/i18n/sv.json @@ -39,11 +39,11 @@ "authentication_settings_disable_all": "Är du säker pÃĨ att du vill inaktivera alla inloggningsmetoder? Inloggning kommer att helt inaktiveras.", "authentication_settings_reenable": "FÃļr att ÃĨteraktivera, använd Server Command.", "background_task_job": "Bakgrundsaktiviteter", - "backup_database": "Databassäkerhetskopia", - "backup_database_enable_description": "Aktivera säkerhetskopiering av databas", - "backup_keep_last_amount": "Antal säkerhetskopior att behÃĨlla", - "backup_settings": "Säkerhetskopieringsinställningar", - "backup_settings_description": "Hantera inställningar fÃļr säkerhetskopiering av databas", + "backup_database": "Skapa Databasdump", + "backup_database_enable_description": "Aktivera dumpning av databas", + "backup_keep_last_amount": "Antal databasdumpar att behÃĨlla", + "backup_settings": "Inställningar databasdump", + "backup_settings_description": "Hantera inställningar fÃļr databasdumpning. Observera: Dessa jobb Ãļvervakas inte och du blir inte notifierad om misslyckanden.", "check_all": "Välj alla", "cleanup": "Uppstädning", "cleared_jobs": "Rensade jobben fÃļr:{job}", @@ -378,6 +378,7 @@ "advanced_settings_proxy_headers_title": "Proxy-headers", "advanced_settings_self_signed_ssl_subtitle": "Hoppar Ãļver SSL-certifikatverifiering fÃļr serverändpunkten. Krävs fÃļr självsignerade certifikat.", "advanced_settings_self_signed_ssl_title": "TillÃĨt självsignerade SSL-certifikat", + "advanced_settings_sync_remote_deletions_title": "Synkonisera fjärradering [EXPERIMENTELL]", "advanced_settings_tile_subtitle": "Avancerade användarinställningar", "advanced_settings_troubleshooting_subtitle": "Aktivera funktioner fÃļr felsÃļkning", "advanced_settings_troubleshooting_title": "FelsÃļkning", @@ -992,6 +993,7 @@ "filetype": "Filtyp", "filter": "Filter", "filter_people": "Filtrera personer", + "filter_places": "Filtrera platser", "find_them_fast": "Hitta dem snabbt efter namn med sÃļk", "fix_incorrect_match": "Fixa inkorrekt matchning", "folder": "Mapp", diff --git a/i18n/th.json b/i18n/th.json index d797dab583..939ab431a9 100644 --- a/i18n/th.json +++ b/i18n/th.json @@ -524,11 +524,11 @@ "backup_controller_page_background_turn_on": "āš€ā¸›ā¸´ā¸”ā¸šā¸Ŗā¸´ā¸ā¸˛ā¸Ŗāš€ā¸šā¸ˇāš‰ā¸­ā¸‡ā¸Ģā¸Ĩā¸ąā¸‡", "backup_controller_page_background_wifi": "ā¸šā¸™ WiFi āš€ā¸—āšˆā¸˛ā¸™ā¸ąāš‰ā¸™", "backup_controller_page_backup": "ā¸Ēā¸ŗā¸Ŗā¸­ā¸‡ā¸‚āš‰ā¸­ā¸Ąā¸šā¸Ĩ", - "backup_controller_page_backup_selected": "⏗ā¸ĩāšˆāš€ā¸Ĩ⏎⏭⏁:", + "backup_controller_page_backup_selected": "⏗ā¸ĩāšˆāš€ā¸Ĩ⏎⏭⏁: ", "backup_controller_page_backup_sub": "ā¸Ŗā¸šā¸›ā¸ ā¸˛ā¸žāšā¸Ĩ⏰⏧⏴⏔ā¸ĩāš‚ā¸­ā¸—ā¸ĩāšˆā¸Ēā¸ŗā¸Ŗā¸­ā¸‡āšā¸Ĩāš‰ā¸§", "backup_controller_page_created": "ā¸Ēā¸Ŗāš‰ā¸˛ā¸‡āš€ā¸Ąā¸ˇāšˆā¸­: {}", "backup_controller_page_desc_backup": "āš€ā¸›ā¸´ā¸”ā¸ā¸˛ā¸Ŗā¸Ēā¸ŗā¸Ŗā¸­ā¸‡ā¸‚āš‰ā¸­ā¸Ąā¸šā¸Ĩāšƒā¸™ā¸‰ā¸˛ā¸ā¸Ģā¸™āš‰ā¸˛āš€ā¸žā¸ˇāšˆā¸­ā¸—ā¸ĩāšˆā¸ˆā¸°ā¸­ā¸ąā¸žāš‚ā¸Ģā¸Ĩā¸”ā¸—ā¸Ŗā¸ąā¸žā¸ĸā¸˛ā¸ā¸Ŗāšƒā¸Ģā¸Ąāšˆāš„ā¸›ā¸ĸā¸ąā¸‡āš€ā¸‹ā¸´ā¸ŖāšŒā¸Ÿāš€ā¸§ā¸­ā¸ŖāšŒāš€ā¸Ąā¸ˇāšˆā¸­āš€ā¸›ā¸´ā¸”āšā¸­ā¸ž", - "backup_controller_page_excluded": "ā¸–ā¸šā¸ā¸ĸā¸āš€ā¸§āš‰ā¸™:", + "backup_controller_page_excluded": "ā¸–ā¸šā¸ā¸ĸā¸āš€ā¸§āš‰ā¸™: ", "backup_controller_page_failed": "ā¸Ĩāš‰ā¸Ąāš€ā¸Ģā¸Ĩ⏧ ({})", "backup_controller_page_filename": "ā¸Šā¸ˇāšˆā¸­āš„ā¸Ÿā¸ĨāšŒ: {} [{}]", "backup_controller_page_id": "ID: {}", diff --git a/i18n/tr.json b/i18n/tr.json index 35c90b7f90..db9088f5e7 100644 --- a/i18n/tr.json +++ b/i18n/tr.json @@ -524,11 +524,11 @@ "backup_controller_page_background_turn_on": "Arka plan hizmetini aç", "backup_controller_page_background_wifi": "Sadece Wi-Fi", "backup_controller_page_backup": "Yedekle", - "backup_controller_page_backup_selected": "Seçili:", + "backup_controller_page_backup_selected": "Seçili: ", "backup_controller_page_backup_sub": "Yedeklenen Ãļğeler", "backup_controller_page_created": "Oluşturma tarihi: {}", "backup_controller_page_desc_backup": "UygulamayÄą açtığınÄązda yeni Ãļğelerin sunucuya otomatik olarak yÃŧklenmesi için Ãļn planda yedeklemeyi aÃ§Äąn.", - "backup_controller_page_excluded": "Hariç tutuldu:", + "backup_controller_page_excluded": "Hariç tutuldu: ", "backup_controller_page_failed": "BaşarÄąsÄąz ({})", "backup_controller_page_filename": "Dosya adÄą: {} [{}]", "backup_controller_page_id": "ID: {}", @@ -1842,7 +1842,7 @@ "version_announcement_message": "Merhaba! Immich'in yeni bir sÃŧrÃŧmÃŧ mevcut. LÃŧtfen yapÄąlandÄąrmanÄązÄąn gÃŧncel olduğundan emin olmak için sÃŧrÃŧm notlarÄąnÄą okumak için biraz zaman ayÄąrÄąn, Ãļzellikle WatchTower veya Immich kurulumunuzu otomatik olarak gÃŧncelleyen bir mekanizma kullanÄąyorsanÄąz yanlÄąÅŸ yapÄąlandÄąrmalarÄąn ÃļnÃŧne geçmek adÄąna bu Ãļnemlidir.", "version_announcement_overlay_release_notes": "sÃŧrÃŧm notlarÄą", "version_announcement_overlay_text_1": "Merhaba arkadaÅŸÄąm, yeni bir sÃŧrÃŧm mevcut", - "version_announcement_overlay_text_2": "lÃŧtfen biraz zaman ayÄąrÄąn ve inceleyin:", + "version_announcement_overlay_text_2": "lÃŧtfen biraz zaman ayÄąrÄąn ve inceleyin: ", "version_announcement_overlay_text_3": "ve Ãļzellikle WatchTower veya sunucu uygulamanÄązÄą otomatik olarak gÃŧncelleyen herhangi bir mekanizma kullanÄąyorsanÄąz, herhangi bir yanlÄąÅŸ yapÄąlandÄąrmayÄą Ãļnlemek için docker-compose ve .env kurulumunuzun gÃŧncel olduğundan emin olun.", "version_announcement_overlay_title": "Yeni Sunucu SÃŧrÃŧmÃŧ Mevcut 🎉", "version_history": "Versiyon geçmişi", diff --git a/i18n/uk.json b/i18n/uk.json index 5c6a809f26..061d9bd78f 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -39,11 +39,11 @@ "authentication_settings_disable_all": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ виĐŧĐēĐŊŅƒŅ‚Đ¸ Đ˛ŅŅ– ĐŧĐĩŅ‚ĐžĐ´Đ¸ Đ˛Ņ…ĐžĐ´Ņƒ? Đ’Ņ…Ņ–Đ´ ĐąŅƒĐ´Đĩ ĐŋОвĐŊŅ–ŅŅ‚ŅŽ виĐŧĐēĐŊĐĩĐŊиК.", "authentication_settings_reenable": "ДĐģŅ ĐŋĐžĐ˛Ņ‚ĐžŅ€ĐŊĐžĐŗĐž Đ˛Đ˛Ņ–ĐŧĐēĐŊĐĩĐŊĐŊŅ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ КоĐŧаĐŊĐ´Ņƒ ҁĐĩŅ€Đ˛ĐĩŅ€Đ°.", "background_task_job": "ФОĐŊĐžĐ˛Ņ– ЗавдаĐŊĐŊŅ", - "backup_database": "Đ ĐĩСĐĩŅ€Đ˛ĐŊа ĐēĐžĐŋŅ–Ņ йаСи даĐŊĐ¸Ņ…", - "backup_database_enable_description": "ĐŖĐ˛Ņ–ĐŧĐēĐŊŅƒŅ‚Đ¸ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐĩ ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ йаСи даĐŊĐ¸Ņ…", - "backup_keep_last_amount": "ĐšŅ–ĐģҌĐēŅ–ŅŅ‚ŅŒ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐ¸Ņ… ĐēĐžĐŋŅ–Đš Đ´ĐģŅ СйĐĩŅ€Ņ–ĐŗĐ°ĐŊĐŊŅ", - "backup_settings": "НаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ", - "backup_settings_description": "КĐĩŅ€ŅƒĐ˛Đ°ĐŊĐŊŅ ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅĐŧи Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ йаСи даĐŊĐ¸Ņ…", + "backup_database": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ даĐŧĐŋ йаСи даĐŊĐ¸Ņ…", + "backup_database_enable_description": "ĐŖĐ˛Ņ–ĐŧĐēĐŊŅƒŅ‚Đ¸ даĐŧĐŋи йаСи даĐŊĐ¸Ņ…", + "backup_keep_last_amount": "ĐšŅ–ĐģҌĐēŅ–ŅŅ‚ŅŒ ĐŋĐžĐŋĐĩŅ€ĐĩĐ´ĐŊŅ–Ņ… даĐŧĐŋŅ–Đ˛, ŅĐēŅ– СйĐĩŅ€Ņ–ĐŗĐ°Ņ‚Đ¸", + "backup_settings": "НаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ даĐŧĐŋа йаСи даĐŊĐ¸Ņ…", + "backup_settings_description": "КĐĩŅ€ŅƒĐ˛Đ°Ņ‚Đ¸ ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅĐŧи даĐŧĐŋа йаСи даĐŊĐ¸Ņ…. ĐŸŅ€Đ¸ĐŧŅ–Ņ‚Đēа: ҆Җ СавдаĐŊĐŊŅ ĐŊĐĩ ĐēĐžĐŊŅ‚Ņ€ĐžĐģŅŽŅŽŅ‚ŅŒŅŅ, Ņ– ви ĐŊĐĩ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ”Ņ‚Đĩ ҁĐŋĐžĐ˛Ņ–Ņ‰ĐĩĐŊĐŊŅ ĐŋŅ€Đž ĐŋĐžĐŧиĐģĐēи.", "check_all": "ПĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đ¸Ņ‚Đ¸ Đ˛ŅĐĩ", "cleanup": "ĐžŅ‡Đ¸Ņ‰ĐĩĐŊĐŊŅ", "cleared_jobs": "ĐžŅ‡Đ¸Ņ‰ĐĩĐŊŅ– СавдаĐŊĐŊŅ Đ´ĐģŅ: {job}", @@ -371,13 +371,17 @@ "admin_password": "ĐŸĐ°Ņ€ĐžĐģҌ адĐŧŅ–ĐŊŅ–ŅŅ‚Ņ€Đ°Ņ‚ĐžŅ€Đ°", "administration": "АдĐŧŅ–ĐŊŅ–ŅŅ‚Ņ€ŅƒĐ˛Đ°ĐŊĐŊŅ", "advanced": "Đ ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊŅ–", + "advanced_settings_enable_alternate_media_filter_subtitle": "ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ ҆ĐĩĐš Đ˛Đ°Ņ€Ņ–Đ°ĐŊŅ‚ Đ´ĐģŅ ҄ҖĐģŅŒŅ‚Ņ€Đ°Ņ†Ņ–Ņ— ĐŧĐĩĐ´Ņ–Đ°Ņ„Đ°ĐšĐģŅ–Đ˛ ĐŋŅ–Đ´ Ņ‡Đ°Ņ ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊŅ–ĐˇĐ°Ņ†Ņ–Ņ— Са аĐģŅŒŅ‚ĐĩŅ€ĐŊĐ°Ņ‚Đ¸Đ˛ĐŊиĐŧи ĐēŅ€Đ¸Ņ‚ĐĩŅ€Ņ–ŅĐŧи. ĐĄĐŋŅ€ĐžĐąŅƒĐšŅ‚Đĩ ҆Đĩ, ŅĐēŅ‰Đž ҃ Đ˛Đ°Ņ виĐŊиĐēĐ°ŅŽŅ‚ŅŒ ĐŋŅ€ĐžĐąĐģĐĩĐŧи С Ņ‚Đ¸Đŧ, Ņ‰Đž Đ´ĐžĐ´Đ°Ņ‚ĐžĐē ĐŊĐĩ Đ˛Đ¸ŅĐ˛ĐģŅŅ” Đ˛ŅŅ– аĐģŅŒĐąĐžĐŧи.", + "advanced_settings_enable_alternate_media_filter_title": "[ЕКСПЕРИМЕНĐĸАЛĐŦНИЙ] ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ аĐģŅŒŅ‚ĐĩŅ€ĐŊĐ°Ņ‚Đ¸Đ˛ĐŊиК ҄ҖĐģŅŒŅ‚Ņ€ ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊŅ–ĐˇĐ°Ņ†Ņ–Ņ— аĐģŅŒĐąĐžĐŧŅ–Đ˛ ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅŽ", "advanced_settings_log_level_title": "Đ Ņ–Đ˛ĐĩĐŊҌ ĐģĐžĐŗŅƒĐ˛Đ°ĐŊĐŊŅ: {}", "advanced_settings_prefer_remote_subtitle": "ДĐĩŅĐēŅ– ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅ— вĐĩĐģҌĐŧи ĐŋĐžĐ˛Ņ–ĐģҌĐŊĐž СаваĐŊŅ‚Đ°ĐļŅƒŅŽŅ‚ŅŒ ĐŧŅ–ĐŊŅ–Đ°Ņ‚ŅŽŅ€Đ¸ Ņ–Đˇ ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛ ĐŊа ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅ—. АĐēŅ‚Đ¸Đ˛ŅƒĐšŅ‚Đĩ Đ´ĐģŅ СаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ Đ˛Ņ–Đ´Đ´Đ°ĐģĐĩĐŊĐ¸Ņ… ĐŧŅ–ĐŊŅ–Đ°Ņ‚ŅŽŅ€ ĐŊĐ°Ņ‚ĐžĐŧŅ–ŅŅ‚ŅŒ.", "advanced_settings_prefer_remote_title": "ПĐĩŅ€ĐĩĐ˛Đ°ĐŗĐ° Đ˛Ņ–Đ´Đ´Đ°ĐģĐĩĐŊиĐŧ ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅĐŧ", - "advanced_settings_proxy_headers_subtitle": "ВизĐŊĐ°Ņ‡Ņ‚Đĩ ĐˇĐ°ĐŗĐžĐģОвĐēи ĐŋŅ€ĐžĐēҁҖ-ҁĐĩŅ€Đ˛ĐĩŅ€Đ°, ŅĐēŅ– Immich ĐŧĐ°Ņ” ĐŊĐ°Đ´ŅĐ¸ĐģĐ°Ņ‚Đ¸ С ĐēĐžĐļĐŊиĐŧ ĐŧĐĩŅ€ĐĩĐļĐĩвиĐŧ СаĐŋĐ¸Ņ‚ĐžĐŧ.", + "advanced_settings_proxy_headers_subtitle": "ВизĐŊĐ°Ņ‡Ņ‚Đĩ ĐˇĐ°ĐŗĐžĐģОвĐēи ĐŋŅ€ĐžĐēҁҖ-ҁĐĩŅ€Đ˛ĐĩŅ€Đ°, ŅĐēŅ– Immich ĐŧĐ°Ņ” ĐŊĐ°Đ´ŅĐ¸ĐģĐ°Ņ‚Đ¸ С ĐēĐžĐļĐŊиĐŧ ĐŧĐĩŅ€ĐĩĐļĐĩвиĐŧ СаĐŋĐ¸Ņ‚ĐžĐŧ", "advanced_settings_proxy_headers_title": "ĐŸŅ€ĐžĐēҁҖ-ĐˇĐ°ĐŗĐžĐģОвĐēи", "advanced_settings_self_signed_ssl_subtitle": "ĐŸŅ€ĐžĐŋ҃ҁĐēĐ°Ņ” ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đē҃ SSL-ҁĐĩŅ€Ņ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ‚Đ° ҁĐĩŅ€Đ˛ĐĩŅ€Đ°. ĐŸĐžŅ‚Ņ€Ņ–ĐąĐŊĐĩ Đ´ĐģŅ ŅĐ°ĐŧĐžĐŋŅ–Đ´ĐŋĐ¸ŅĐ°ĐŊĐ¸Ņ… ҁĐĩŅ€Ņ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ‚Ņ–Đ˛.", "advanced_settings_self_signed_ssl_title": "ДозвоĐģĐ¸Ņ‚Đ¸ ŅĐ°ĐŧĐžĐŋŅ–Đ´ĐŋĐ¸ŅĐ°ĐŊŅ– SSL-ҁĐĩŅ€Ņ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ‚Đ¸", + "advanced_settings_sync_remote_deletions_subtitle": "ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž видаĐģŅŅ‚Đ¸ айО Đ˛Ņ–Đ´ĐŊОвĐģŅŽĐ˛Đ°Ņ‚Đ¸ Ņ€ĐĩŅŅƒŅ€Ņ ĐŊа Ņ†ŅŒĐžĐŧ҃ ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅ—, ĐēĐžĐģи Ņ†Ņ Đ´Ņ–Ņ виĐēĐžĐŊŅƒŅ”Ņ‚ŅŒŅŅ в вĐĩĐą-Ņ–ĐŊŅ‚ĐĩҀ҄ĐĩĐšŅŅ–", + "advanced_settings_sync_remote_deletions_title": "ХиĐŊŅ…Ņ€ĐžĐŊŅ–ĐˇĐ°Ņ†Ņ–Ņ видаĐģĐĩĐŊĐ¸Ņ… видаĐģĐĩĐŊҌ [ЕКСПЕРИМЕНĐĸАЛĐŦНО]", "advanced_settings_tile_subtitle": "Đ ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊŅ– ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ†ŅŒĐēŅ– ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ", "advanced_settings_troubleshooting_subtitle": "ĐŖĐ˛Ņ–ĐŧĐēĐŊŅ–Ņ‚ŅŒ Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– Ņ„ŅƒĐŊĐē҆Җҗ Đ´ĐģŅ ҃ҁ҃ĐŊĐĩĐŊĐŊŅ ĐŊĐĩҁĐŋŅ€Đ°Đ˛ĐŊĐžŅŅ‚ĐĩĐš", "advanced_settings_troubleshooting_title": "ĐŖŅŅƒĐŊĐĩĐŊĐŊŅ ĐŊĐĩҁĐŋŅ€Đ°Đ˛ĐŊĐžŅŅ‚ĐĩĐš", @@ -498,18 +502,18 @@ "background_location_permission": "Đ”ĐžĐˇĐ˛Ņ–Đģ Đ´Đž ĐŧҖҁ҆ĐĩСĐŊĐ°Ņ…ĐžĐ´ĐļĐĩĐŊĐŊŅ ҃ Ņ„ĐžĐŊŅ–", "background_location_permission_content": "ЊОй ĐŋĐĩŅ€ĐĩĐŧиĐēĐ°Ņ‚Đ¸ ĐŧĐĩŅ€ĐĩĐļŅ– ҃ Ņ„ĐžĐŊОвОĐŧ҃ Ņ€ĐĩĐļиĐŧŅ–, Immich ĐŧĐ°Ņ” *СавĐļди* ĐŧĐ°Ņ‚Đ¸ Đ´ĐžŅŅ‚ŅƒĐŋ Đ´Đž Ņ‚ĐžŅ‡ĐŊĐžŅ— ĐŗĐĩĐžĐģĐžĐēĐ°Ņ†Ņ–Ņ—, Ņ‰ĐžĐą ĐˇŅ‡Đ¸Ņ‚ŅƒĐ˛Đ°Ņ‚Đ¸ ĐŊĐ°ĐˇĐ˛Ņƒ Wi-Fi ĐŧĐĩŅ€ĐĩĐļŅ–", "backup_album_selection_page_albums_device": "АĐģŅŒĐąĐžĐŧи ĐŊа ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅ— ({})", - "backup_album_selection_page_albums_tap": "ĐĸĐžŅ€ĐēĐŊŅ–Ņ‚ŅŒŅŅ, Ņ‰ĐžĐą вĐēĐģŅŽŅ‡Đ¸Ņ‚Đ¸,\nŅ‚ĐžŅ€ĐēĐŊŅ–Ņ‚ŅŒŅŅ Đ´Đ˛Ņ–Ņ‡Ņ–, Ņ‰ĐžĐą виĐēĐģŅŽŅ‡Đ¸Ņ‚Đ¸", + "backup_album_selection_page_albums_tap": "ĐĸĐžŅ€ĐēĐŊŅ–Ņ‚ŅŒŅŅ, Ņ‰ĐžĐą вĐēĐģŅŽŅ‡Đ¸Ņ‚Đ¸, Đ´Đ˛Ņ–Ņ‡Ņ–, Ņ‰ĐžĐą виĐēĐģŅŽŅ‡Đ¸Ņ‚Đ¸", "backup_album_selection_page_assets_scatter": "ЕĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ ĐŧĐžĐļŅƒŅ‚ŅŒ ĐŊаĐģĐĩĐļĐ°Ņ‚Đ¸ Đ´Đž ĐēŅ–ĐģҌĐēĐžŅ… аĐģŅŒĐąĐžĐŧŅ–Đ˛ вОдĐŊĐžŅ‡Đ°Ņ. ĐĸаĐēиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ, аĐģŅŒĐąĐžĐŧи ĐŧĐžĐļŅƒŅ‚ŅŒ ĐąŅƒŅ‚Đ¸ вĐēĐģŅŽŅ‡ĐĩĐŊŅ– айО виĐģŅƒŅ‡ĐĩĐŊŅ– ĐŋŅ–Đ´ Ņ‡Đ°Ņ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ.", "backup_album_selection_page_select_albums": "ОбĐĩŅ€Ņ–Ņ‚ŅŒ аĐģŅŒĐąĐžĐŧи", "backup_album_selection_page_selection_info": "ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ ĐŋŅ€Đž ĐžĐąŅ€Đ°ĐŊĐĩ", "backup_album_selection_page_total_assets": "Đ—Đ°ĐŗĐ°ĐģҌĐŊа ĐēŅ–ĐģҌĐēŅ–ŅŅ‚ŅŒ ҃ĐŊŅ–ĐēаĐģҌĐŊĐ¸Ņ… ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛", "backup_all": "ĐŖŅŅ–", - "backup_background_service_backup_failed_message": "НĐĩ вдаĐģĐžŅŅ ĐˇŅ€ĐžĐąĐ¸Ņ‚Đ¸ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊ҃ ĐēĐžĐŋŅ–ŅŽ ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛. ĐŸĐžĐ˛Ņ‚ĐžŅ€ŅŽŅŽ...", - "backup_background_service_connection_failed_message": "НĐĩ вдаĐģĐžŅŅ Св'ŅĐˇĐ°Ņ‚Đ¸ŅŅ Ņ–Đˇ ҁĐĩŅ€Đ˛ĐĩŅ€ĐžĐŧ. ĐŸĐžĐ˛Ņ‚ĐžŅ€ŅŽŅŽ...", + "backup_background_service_backup_failed_message": "НĐĩ вдаĐģĐžŅŅ ĐˇŅ€ĐžĐąĐ¸Ņ‚Đ¸ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊ҃ ĐēĐžĐŋŅ–ŅŽ ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛. ĐŸĐžĐ˛Ņ‚ĐžŅ€ŅŽŅŽâ€Ļ", + "backup_background_service_connection_failed_message": "НĐĩ вдаĐģĐžŅŅ Св'ŅĐˇĐ°Ņ‚Đ¸ŅŅ Ņ–Đˇ ҁĐĩŅ€Đ˛ĐĩŅ€ĐžĐŧ. ĐŸĐžĐ˛Ņ‚ĐžŅ€ŅŽŅŽâ€Ļ", "backup_background_service_current_upload_notification": "ЗаваĐŊŅ‚Đ°ĐļŅƒŅ”Ņ‚ŅŒŅŅ {}", "backup_background_service_default_notification": "ПĐĩŅ€ĐĩĐ˛Ņ–Ņ€ŅŅŽ ĐŊĐ°ŅĐ˛ĐŊŅ–ŅŅ‚ŅŒ ĐŊĐžĐ˛Đ¸Ņ… ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛â€Ļ", "backup_background_service_error_title": "ПоĐŧиĐģĐēа Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ", - "backup_background_service_in_progress_notification": "Đ ĐĩСĐĩŅ€Đ˛ĐŊĐĩ ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ Đ˛Đ°ŅˆĐ¸Ņ… ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛...", + "backup_background_service_in_progress_notification": "Đ ĐĩСĐĩŅ€Đ˛ĐŊĐĩ ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ Đ˛Đ°ŅˆĐ¸Ņ… ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛â€Ļ", "backup_background_service_upload_failure_notification": "НĐĩ вдаĐģĐžŅŅ СаваĐŊŅ‚Đ°ĐļĐ¸Ņ‚Đ¸ {}", "backup_controller_page_albums": "Đ ĐĩСĐĩŅ€Đ˛ĐŊĐĩ ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ аĐģŅŒĐąĐžĐŧŅ–Đ˛", "backup_controller_page_background_app_refresh_disabled_content": "ДĐģŅ Ņ„ĐžĐŊĐžĐ˛ĐžĐŗĐž Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ ŅƒĐ˛Ņ–ĐŧĐēĐŊŅ–Ņ‚ŅŒ Ņ„ĐžĐŊОвĐĩ ĐžĐŊОвĐģĐĩĐŊĐŊŅ в ĐŧĐĩĐŊŅŽ \"НаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ > Đ—Đ°ĐŗĐ°ĐģҌĐŊŅ– > ФОĐŊОвĐĩ ĐžĐŊОвĐģĐĩĐŊĐŊŅ ĐŋŅ€ĐžĐŗŅ€Đ°Đŧи\".", @@ -521,7 +525,7 @@ "backup_controller_page_background_battery_info_title": "ОĐŋŅ‚Đ¸ĐŧŅ–ĐˇĐ°Ņ†Ņ–Ņ ĐąĐ°Ņ‚Đ°Ņ€ĐĩŅ—", "backup_controller_page_background_charging": "Đ›Đ¸ŅˆĐĩ ĐŋŅ–Đ´ Ņ‡Đ°Ņ ĐˇĐ°Ņ€ŅĐ´ĐļаĐŊĐŊŅ", "backup_controller_page_background_configure_error": "НĐĩ вдаĐģĐžŅŅ ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ Ņ„ĐžĐŊОвиК ҁĐĩŅ€Đ˛Ņ–Ņ", - "backup_controller_page_background_delay": "Đ—Đ°Ņ‚Ņ€Đ¸ĐŧĐēа ĐŋĐĩŅ€ĐĩĐ´ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊиĐŧ ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅĐŧ ĐŊĐžĐ˛Đ¸Ņ… ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛: {}", + "backup_controller_page_background_delay": "Đ—Đ°Ņ‚Ņ€Đ¸ĐŧĐēа Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ ĐŊĐžĐ˛Đ¸Ņ… ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛: {}", "backup_controller_page_background_description": "ĐŖĐ˛Ņ–ĐŧĐēĐŊŅ–Ņ‚ŅŒ Ņ„ĐžĐŊĐžĐ˛Ņƒ ҁĐģ҃ĐļĐąŅƒ, Ņ‰ĐžĐą Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ŅŅ‚Đ˛ĐžŅ€ŅŽĐ˛Đ°Ņ‚Đ¸ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊŅ– ĐēĐžĐŋŅ–Ņ— ĐąŅƒĐ´ŅŒ-ŅĐēĐ¸Ņ… ĐŊĐžĐ˛Đ¸Ņ… ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛ ĐąĐĩС ĐŊĐĩĐžĐąŅ…Ņ–Đ´ĐŊĐžŅŅ‚Ņ– Đ˛Ņ–Đ´ĐēŅ€Đ¸Đ˛Đ°Ņ‚Đ¸ ĐŋŅ€ĐžĐŗŅ€Đ°Đŧ҃", "backup_controller_page_background_is_off": "ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐĩ Ņ„ĐžĐŊОвĐĩ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐĩ ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ виĐŧĐēĐŊĐĩĐŊĐž", "backup_controller_page_background_is_on": "ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐĩ Ņ„ĐžĐŊОвĐĩ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐĩ ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ Đ˛Đ˛Ņ–ĐŧĐēĐŊĐĩĐŊĐž", @@ -529,11 +533,11 @@ "backup_controller_page_background_turn_on": "ĐŖĐ˛Ņ–ĐŧĐēĐŊŅƒŅ‚Đ¸ Ņ„ĐžĐŊОвиК ҁĐĩŅ€Đ˛Ņ–Ņ", "backup_controller_page_background_wifi": "Đ›Đ¸ŅˆĐĩ ĐŊа WiFi", "backup_controller_page_backup": "Đ ĐĩСĐĩŅ€Đ˛ĐŊĐĩ ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ", - "backup_controller_page_backup_selected": "ĐžĐąŅ€Đ°ĐŊĐž:", + "backup_controller_page_backup_selected": "ĐžĐąŅ€Đ°ĐŊĐž: ", "backup_controller_page_backup_sub": "Đ ĐĩСĐĩŅ€Đ˛ĐŊŅ– ĐēĐžĐŋŅ–Ņ— СĐŊŅ–ĐŧĐēŅ–Đ˛ Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž", "backup_controller_page_created": "ĐĄŅ‚Đ˛ĐžŅ€ĐĩĐŊĐž: {}", "backup_controller_page_desc_backup": "ĐŖĐ˛Ņ–ĐŧĐēĐŊŅ–Ņ‚ŅŒ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐĩ ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ ĐŊа ĐŋĐĩŅ€ĐĩĐ´ĐŊŅŒĐžĐŧ҃ ĐŋĐģаĐŊŅ–, Ņ‰ĐžĐą Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž СаваĐŊŅ‚Đ°ĐļŅƒĐ˛Đ°Ņ‚Đ¸ ĐŊĐžĐ˛Ņ– ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ ĐŊа ҁĐĩŅ€Đ˛ĐĩŅ€ ĐŋŅ–Đ´ Ņ‡Đ°Ņ Đ˛Ņ–Đ´ĐēŅ€Đ¸Ņ‚Ņ‚Ņ ĐŋŅ€ĐžĐŗŅ€Đ°Đŧи.", - "backup_controller_page_excluded": "ВиĐģŅƒŅ‡ĐĩĐŊĐž:", + "backup_controller_page_excluded": "ВиĐģŅƒŅ‡ĐĩĐŊĐž: ", "backup_controller_page_failed": "НĐĩвдаĐģŅ– ({})", "backup_controller_page_filename": "Назва Ņ„Đ°ĐšĐģ҃: {} [{}]", "backup_controller_page_id": "ID: {}", @@ -545,7 +549,7 @@ "backup_controller_page_start_backup": "ĐŸĐžŅ‡Đ°Ņ‚Đ¸ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐĩ ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ", "backup_controller_page_status_off": "ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐĩ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐĩ ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ в аĐēŅ‚Đ¸Đ˛ĐŊĐžĐŧ҃ Ņ€ĐĩĐļиĐŧŅ– виĐŧĐēĐŊĐĩĐŊĐž", "backup_controller_page_status_on": "ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐĩ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐĩ ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ в аĐēŅ‚Đ¸Đ˛ĐŊĐžĐŧ҃ Ņ€ĐĩĐļиĐŧŅ– Đ˛Đ˛Ņ–ĐŧĐēĐŊĐĩĐŊĐž", - "backup_controller_page_storage_format": "{} Ņ–Đˇ {} ҁĐŋĐžĐļĐ¸Ņ‚Đž", + "backup_controller_page_storage_format": "ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐž: {} С {}", "backup_controller_page_to_backup": "АĐģŅŒĐąĐžĐŧи Đ´Đž Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ", "backup_controller_page_total_sub": "ĐŖŅŅ– ҃ĐŊŅ–ĐēаĐģҌĐŊŅ– СĐŊŅ–ĐŧĐēи Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž С Đ˛Đ¸ĐąŅ€Đ°ĐŊĐ¸Ņ… аĐģŅŒĐąĐžĐŧŅ–Đ˛", "backup_controller_page_turn_off": "ВиĐŧĐēĐŊŅƒŅ‚Đ¸ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐĩ ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ в аĐēŅ‚Đ¸Đ˛ĐŊĐžĐŧ҃ Ņ€ĐĩĐļиĐŧŅ–", @@ -606,7 +610,7 @@ "change_password": "ЗĐŧŅ–ĐŊĐ¸Ņ‚Đ¸ ĐŋĐ°Ņ€ĐžĐģҌ", "change_password_description": "ĐĻĐĩ айО ĐŋĐĩŅ€ŅˆĐ¸Đš Ņ€Đ°Đˇ, ĐēĐžĐģи ви ŅƒĐ˛Ņ–ĐšŅˆĐģи в ŅĐ¸ŅŅ‚ĐĩĐŧ҃, айО ĐąŅƒĐģĐž ĐˇŅ€ĐžĐąĐģĐĩĐŊĐž СаĐŋĐ¸Ņ‚ ĐŊа СĐŧŅ–ĐŊ҃ Đ˛Đ°ŅˆĐžĐŗĐž ĐŋĐ°Ņ€ĐžĐģŅ. Đ‘ŅƒĐ´ŅŒ ĐģĐ°ŅĐēа, ввĐĩĐ´Ņ–Ņ‚ŅŒ ĐŊОвиК ĐŋĐ°Ņ€ĐžĐģҌ ĐŊиĐļ҇Đĩ.", "change_password_form_confirm_password": "ĐŸŅ–Đ´Ņ‚Đ˛ĐĩŅ€Đ´Đ¸Ņ‚Đ¸ ĐŋĐ°Ņ€ĐžĐģҌ", - "change_password_form_description": "ĐŸŅ€Đ¸Đ˛Ņ–Ņ‚ {name},\n\nВи айО айО вĐŋĐĩŅ€ŅˆĐĩ Đ˛Ņ…ĐžĐ´Đ¸Ņ‚Đĩ ҃ ŅĐ¸ŅŅ‚ĐĩĐŧ҃, айО ĐąŅƒĐģĐž ĐˇŅ€ĐžĐąĐģĐĩĐŊĐž СаĐŋĐ¸Ņ‚ ĐŊа СĐŧŅ–ĐŊ҃ Đ˛Đ°ŅˆĐžĐŗĐž ĐŋĐ°Ņ€ĐžĐģŅ. \nВвĐĩĐ´Ņ–Ņ‚ŅŒ Đ˛Đ°Ņˆ ĐŊОвиК ĐŋĐ°Ņ€ĐžĐģҌ.", + "change_password_form_description": "ĐŸŅ€Đ¸Đ˛Ņ–Ņ‚, {name},\n\nĐĻĐĩ айО Đ˛Đ°Ņˆ ĐŋĐĩŅ€ŅˆĐ¸Đš Đ˛Ņ…Ņ–Đ´ ҃ ŅĐ¸ŅŅ‚ĐĩĐŧ҃, айО ĐąŅƒĐģĐž ĐŊĐ°Đ´Ņ–ŅĐģаĐŊĐž СаĐŋĐ¸Ņ‚ ĐŊа СĐŧŅ–ĐŊ҃ ĐŋĐ°Ņ€ĐžĐģŅ. Đ‘ŅƒĐ´ŅŒ ĐģĐ°ŅĐēа, ввĐĩĐ´Ņ–Ņ‚ŅŒ ĐŊОвиК ĐŋĐ°Ņ€ĐžĐģҌ ĐŊиĐļ҇Đĩ.", "change_password_form_new_password": "Новий ĐŋĐ°Ņ€ĐžĐģҌ", "change_password_form_password_mismatch": "ĐŸĐ°Ņ€ĐžĐģŅ– ĐŊĐĩ ҁĐŋŅ–Đ˛ĐŋĐ°Đ´Đ°ŅŽŅ‚ŅŒ", "change_password_form_reenter_new_password": "ĐŸĐžĐ˛Ņ‚ĐžŅ€Ņ–Ņ‚ŅŒ ĐŊОвиК ĐŋĐ°Ņ€ĐžĐģҌ", @@ -630,7 +634,7 @@ "client_cert_import_success_msg": "КĐģŅ–Ņ”ĐŊŅ‚ŅŅŒĐēиК ҁĐĩŅ€Ņ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ‚ Ņ–ĐŧĐŋĐžŅ€Ņ‚ĐžĐ˛Đ°ĐŊĐž", "client_cert_invalid_msg": "НĐĩĐ´Ņ–ĐšŅĐŊиК Ņ„Đ°ĐšĐģ ҁĐĩŅ€Ņ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ‚Đ° айО ĐŊĐĩĐŋŅ€Đ°Đ˛Đ¸ĐģҌĐŊиК ĐŋĐ°Ņ€ĐžĐģҌ", "client_cert_remove_msg": "КĐģŅ–Ņ”ĐŊŅ‚ŅŅŒĐēиК ҁĐĩŅ€Ņ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ‚ видаĐģĐĩĐŊĐž", - "client_cert_subtitle": "ĐŸŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚ŅŒŅŅ ĐģĐ¸ŅˆĐĩ Ņ„ĐžŅ€ĐŧĐ°Ņ‚ PKCS12 (.p12, .pfx). ІĐŧĐŋĐžŅ€Ņ‚/видаĐģĐĩĐŊĐŊŅ ҁĐĩŅ€Ņ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ‚Đ° Đ´ĐžŅŅ‚ŅƒĐŋĐŊĐĩ ĐģĐ¸ŅˆĐĩ ĐŋĐĩŅ€ĐĩĐ´ Đ˛Ņ…ĐžĐ´ĐžĐŧ ҃ ŅĐ¸ŅŅ‚ĐĩĐŧ҃.", + "client_cert_subtitle": "ĐŸŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚ŅŒŅŅ ĐģĐ¸ŅˆĐĩ Ņ„ĐžŅ€ĐŧĐ°Ņ‚ PKCS12 (.p12, .pfx). ІĐŧĐŋĐžŅ€Ņ‚/видаĐģĐĩĐŊĐŊŅ ҁĐĩŅ€Ņ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ‚Đ° Đ´ĐžŅŅ‚ŅƒĐŋĐŊŅ– ĐģĐ¸ŅˆĐĩ Đ´Đž Đ˛Ņ…ĐžĐ´Ņƒ в ŅĐ¸ŅŅ‚ĐĩĐŧ҃", "client_cert_title": "КĐģŅ–Ņ”ĐŊŅ‚ŅŅŒĐēиК SSL-ҁĐĩŅ€Ņ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ‚", "clockwise": "По ĐŗĐžĐ´Đ¸ĐŊĐŊиĐēĐžĐ˛Ņ–Đš ҁ҂ҀҖĐģ҆Җ", "close": "ЗаĐēŅ€Đ¸Ņ‚Đ¸", @@ -719,8 +723,8 @@ "delete_album": "ВидаĐģĐ¸Ņ‚Đ¸ аĐģŅŒĐąĐžĐŧ", "delete_api_key_prompt": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ ҆ĐĩĐš ĐēĐģŅŽŅ‡ API?", "delete_dialog_alert": "ĐĻŅ– ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ ĐąŅƒĐ´ŅƒŅ‚ŅŒ ĐžŅŅ‚Đ°Ņ‚ĐžŅ‡ĐŊĐž видаĐģĐĩĐŊŅ– С ҁĐĩŅ€Đ˛ĐĩŅ€Ņƒ Immich Ņ‚Đ° Đ˛Đ°ŅˆĐžĐŗĐž ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅŽ", - "delete_dialog_alert_local": "ĐĻŅ– ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ ĐąŅƒĐ´ŅƒŅ‚ŅŒ видаĐģĐĩĐŊŅ– видаĐģĐĩĐŊŅ– С Đ’Đ°ŅˆĐžĐŗĐž ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅŽ, аĐģĐĩ СаĐģĐ¸ŅˆĐ°Ņ‚ŅŒŅŅ Đ´ĐžŅŅ‚ŅƒĐŋĐŊиĐŧи ĐŊа ҁĐĩŅ€Đ˛ĐĩҀҖ Immich", - "delete_dialog_alert_local_non_backed_up": "Đ ĐĩСĐĩŅ€Đ˛ĐŊŅ– ĐēĐžĐŋŅ–Ņ— Đ´ĐĩŅĐēĐ¸Ņ… ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛ ĐŊĐĩ ĐąŅƒĐģи СаваĐŊŅ‚Đ°ĐļĐĩĐŊŅ– в Immich Ņ– ĐąŅƒĐ´ŅƒŅ‚ŅŒ видаĐģĐĩĐŊŅ– видаĐģĐĩĐŊŅ– С Đ’Đ°ŅˆĐžĐŗĐž ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅŽ", + "delete_dialog_alert_local": "ĐĻŅ– ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ ĐąŅƒĐ´ŅƒŅ‚ŅŒ ĐžŅŅ‚Đ°Ņ‚ĐžŅ‡ĐŊĐž видаĐģĐĩĐŊŅ– С Đ˛Đ°ŅˆĐžĐŗĐž ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅŽ, аĐģĐĩ СаĐģĐ¸ŅˆĐ°Ņ‚ŅŒŅŅ Đ´ĐžŅŅ‚ŅƒĐŋĐŊиĐŧи ĐŊа ҁĐĩŅ€Đ˛ĐĩҀҖ Immich", + "delete_dialog_alert_local_non_backed_up": "ДĐĩŅĐēŅ– ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ ĐŊĐĩ ĐąŅƒĐģи СйĐĩŅ€ĐĩĐļĐĩĐŊŅ– ĐŊа ҁĐĩŅ€Đ˛ĐĩҀҖ Immich Ņ– ĐąŅƒĐ´ŅƒŅ‚ŅŒ ĐžŅŅ‚Đ°Ņ‚ĐžŅ‡ĐŊĐž видаĐģĐĩĐŊŅ– С Đ˛Đ°ŅˆĐžĐŗĐž ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅŽ", "delete_dialog_alert_remote": "ĐĻŅ– ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ ĐąŅƒĐ´ŅƒŅ‚ŅŒ ĐŊаСавĐļди видаĐģĐĩĐŊŅ– С ҁĐĩŅ€Đ˛ĐĩŅ€Ņƒ Immich", "delete_dialog_ok_force": "Đ’ŅĐĩ ОдĐŊĐž видаĐģĐ¸Ņ‚Đ¸", "delete_dialog_title": "ВидаĐģĐ¸Ņ‚Đ¸ ĐžŅŅ‚Đ°Ņ‚ĐžŅ‡ĐŊĐž", @@ -992,6 +996,7 @@ "filetype": "ĐĸиĐŋ Ņ„Đ°ĐšĐģ҃", "filter": "Đ¤Ņ–ĐģŅŒŅ‚Ņ€", "filter_people": "Đ¤Ņ–ĐģŅŒŅ‚Ņ€ ĐŋĐž ĐģŅŽĐ´ŅŅ…", + "filter_places": "Đ¤Ņ–ĐģŅŒŅ‚Ņ€ ĐŋĐž ĐŧŅ–ŅŅ†ŅŅ…", "find_them_fast": "ШвидĐēĐž СĐŊĐ°Ņ…ĐžĐ´ŅŒŅ‚Đĩ Ņ—Ņ… Са ĐŊĐ°ĐˇĐ˛ĐžŅŽ Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ ĐŋĐžŅˆŅƒĐē҃", "fix_incorrect_match": "ВиĐŋŅ€Đ°Đ˛Đ¸Ņ‚Đ¸ ĐŊĐĩĐŋŅ€Đ°Đ˛Đ¸ĐģҌĐŊиК ĐˇĐąŅ–Đŗ", "folder": "ПаĐŋĐēа", @@ -1020,7 +1025,7 @@ "header_settings_field_validator_msg": "ЗĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐŊĐĩ ĐŧĐžĐļĐĩ ĐąŅƒŅ‚Đ¸ ĐŋĐžŅ€ĐžĐļĐŊŅ–Đŧ", "header_settings_header_name_input": "ІĐŧ'Ņ ĐˇĐ°ĐŗĐžĐģОвĐē҃", "header_settings_header_value_input": "ЗĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐˇĐ°ĐŗĐžĐģОвĐē҃", - "headers_settings_tile_subtitle": "ВизĐŊĐ°Ņ‡Ņ‚Đĩ ĐˇĐ°ĐŗĐžĐģОвĐēи ĐŋŅ€ĐžĐēҁҖ, ŅĐēŅ– ĐŋŅ€ĐžĐŗŅ€Đ°Đŧа ĐŧĐ°Ņ” ĐŊĐ°Đ´ŅĐ¸ĐģĐ°Ņ‚Đ¸ С ĐēĐžĐļĐŊиĐŧ ĐŧĐĩŅ€ĐĩĐļĐĩвиĐŧ СаĐŋĐ¸Ņ‚ĐžĐŧ.", + "headers_settings_tile_subtitle": "ВизĐŊĐ°Ņ‡Ņ‚Đĩ ĐˇĐ°ĐŗĐžĐģОвĐēи ĐŋŅ€ĐžĐēҁҖ, ŅĐēŅ– ĐŋŅ€ĐžĐŗŅ€Đ°Đŧа ĐŧĐ°Ņ” ĐŊĐ°Đ´ŅĐ¸ĐģĐ°Ņ‚Đ¸ С ĐēĐžĐļĐŊиĐŧ ĐŧĐĩŅ€ĐĩĐļĐĩвиĐŧ СаĐŋĐ¸Ņ‚ĐžĐŧ", "headers_settings_tile_title": "ĐšĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°ĐģҌĐŊĐ¸Ņ†ŅŒĐēŅ– ĐˇĐ°ĐŗĐžĐģОвĐēи ĐŋŅ€ĐžĐēҁҖ", "hi_user": "ĐŸŅ€Đ¸Đ˛Ņ–Ņ‚ {name} ({email})", "hide_all_people": "ĐĄŅ…ĐžĐ˛Đ°Ņ‚Đ¸ Đ˛ŅŅ–Ņ…", @@ -1040,7 +1045,7 @@ "home_page_delete_remote_err_local": "ЛоĐēаĐģҌĐŊŅ– ĐĩĐģĐĩĐŧĐĩĐŊŅ‚(и) вĐļĐĩ в ĐŋŅ€ĐžŅ†ĐĩҁҖ видаĐģĐĩĐŊĐŊŅ С ҁĐĩŅ€Đ˛ĐĩŅ€Đ°, ĐŋŅ€ĐžĐŋŅƒŅ‰ĐĩĐŊĐž", "home_page_favorite_err_local": "ПоĐēи Ņ‰Đž ĐŊĐĩ ĐŧĐžĐļĐŊа Đ´ĐžĐ´Đ°Ņ‚Đ¸ Đ´Đž ҃ĐģŅŽĐąĐģĐĩĐŊĐ¸Ņ… ĐģĐžĐēаĐģҌĐŊŅ– ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸, ĐŋŅ€ĐžĐŋŅƒŅ‰ĐĩĐŊĐž", "home_page_favorite_err_partner": "ПоĐēи Ņ‰Đž ĐŊĐĩ ĐŧĐžĐļĐŊа Đ´ĐžĐ´Đ°Ņ‚Đ¸ Đ´Đž ҃ĐģŅŽĐąĐģĐĩĐŊĐ¸Ņ… ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ ĐŋĐ°Ņ€Ņ‚ĐŊĐĩŅ€Đ°, ĐŋŅ€ĐžĐŋŅƒŅ‰ĐĩĐŊĐž", - "home_page_first_time_notice": "Đ¯ĐēŅ‰Đž ви вĐŋĐĩŅ€ŅˆĐĩ ĐēĐžŅ€Đ¸ŅŅ‚ŅƒŅ”Ņ‚ĐĩŅŅ ĐŋŅ€ĐžĐŗŅ€Đ°ĐŧĐžŅŽ, ĐŋĐĩŅ€ĐĩĐēĐžĐŊĐ°ĐšŅ‚ĐĩŅŅ, Ņ‰Đž ви Đ˛Đ¸ĐąŅ€Đ°Đģи аĐģŅŒĐąĐžĐŧи Đ´ĐģŅ Ņ€ĐĩСĐĩŅ€Đ˛ŅƒĐ˛Đ°ĐŊĐŊŅ, Ņ‰ĐžĐą ĐŧĐžĐŗŅ‚Đ¸ СаĐŋОвĐŊŅŽĐ˛Đ°Ņ‚Đ¸ Ņ…Ņ€ĐžĐŊĐžĐģĐžĐŗŅ–ŅŽ СĐŊŅ–ĐŧĐēŅ–Đ˛ Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž в аĐģŅŒĐąĐžĐŧĐ°Ņ….", + "home_page_first_time_notice": "Đ¯ĐēŅ‰Đž ви ĐēĐžŅ€Đ¸ŅŅ‚ŅƒŅ”Ņ‚ĐĩŅŅ Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐŧ вĐŋĐĩŅ€ŅˆĐĩ, ĐąŅƒĐ´ŅŒ ĐģĐ°ŅĐēа, ОйĐĩŅ€Ņ–Ņ‚ŅŒ аĐģŅŒĐąĐžĐŧ Đ´ĐģŅ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ, Ņ‰ĐžĐą ĐŊа ҈ĐēаĐģŅ– Ņ‡Đ°ŅŅƒ Đˇâ€™ŅĐ˛Đ¸ĐģĐ¸ŅŅ Ņ„ĐžŅ‚Đž Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž", "home_page_share_err_local": "НĐĩĐŧĐžĐļĐģивО ĐŋĐžĐ´Ņ–ĐģĐ¸Ņ‚Đ¸ŅŅ ĐģĐžĐēаĐģҌĐŊиĐŧи ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ°Đŧи ҇ĐĩŅ€ĐĩС ĐŋĐžŅĐ¸ĐģаĐŊĐŊŅ, ĐŋŅ€ĐžĐŋŅƒŅ‰ĐĩĐŊĐž", "home_page_upload_err_limit": "МоĐļĐŊа ваĐŊŅ‚Đ°ĐļĐ¸Ņ‚Đ¸ ĐŊĐĩ ĐąŅ–ĐģҌ҈Đĩ 30 ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛ вОдĐŊĐžŅ‡Đ°Ņ, ĐŋŅ€ĐžĐŋŅƒŅ‰ĐĩĐŊĐž", "host": "ĐĨĐžŅŅ‚", @@ -1132,7 +1137,7 @@ "logged_out_device": "Đ’Đ¸Ņ…Ņ–Đ´ С ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅŽ", "login": "Đ’Ņ…Ņ–Đ´", "login_disabled": "ĐĐ˛Ņ‚ĐžŅ€Đ¸ĐˇĐ°Ņ†Ņ–Ņ ĐąŅƒĐģа Đ˛Ņ–Đ´ĐēĐģŅŽŅ‡ĐĩĐŊа", - "login_form_api_exception": "ПоĐŧиĐģĐēа API. ПĐĩŅ€ĐĩĐ˛Ņ–Ņ€Ņ‚Đĩ Đ°Đ´Ņ€Đĩҁ҃ ҁĐĩŅ€Đ˛ĐĩŅ€Đ° Ņ– ҁĐŋŅ€ĐžĐąŅƒĐšŅ‚Đĩ СĐŊĐžĐ˛Ņƒ", + "login_form_api_exception": "ПоĐŧиĐģĐēа API. ПĐĩŅ€ĐĩĐ˛Ņ–Ņ€Ņ‚Đĩ Đ°Đ´Ņ€Đĩҁ҃ ҁĐĩŅ€Đ˛ĐĩŅ€Đ° Ņ– ҁĐŋŅ€ĐžĐąŅƒĐšŅ‚Đĩ СĐŊĐžĐ˛Ņƒ.", "login_form_back_button_text": "Назад", "login_form_email_hint": "youremail@email.com", "login_form_endpoint_hint": "http://your-server-ip:port", @@ -1149,7 +1154,7 @@ "login_form_password_hint": "ĐŋĐ°Ņ€ĐžĐģҌ", "login_form_save_login": "ЗаĐŋаĐŧ'ŅŅ‚Đ°Ņ‚Đ¸ Đ˛Ņ…Ņ–Đ´", "login_form_server_empty": "ВвĐĩĐ´Ņ–Ņ‚ŅŒ URL-Đ°Đ´Ņ€Đĩҁ҃ ҁĐĩŅ€Đ˛ĐĩŅ€Đ°.", - "login_form_server_error": "НĐĩĐŧĐžĐļĐģивО С'Ņ”Đ´ĐŊĐ°Ņ‚Đ¸ŅŅ Ņ–Đˇ ҁĐĩŅ€Đ˛ĐĩŅ€ĐžĐŧ", + "login_form_server_error": "НĐĩ вдаĐģĐžŅŅ ĐŋŅ–Đ´ĐēĐģŅŽŅ‡Đ¸Ņ‚Đ¸ŅŅ Đ´Đž ҁĐĩŅ€Đ˛ĐĩŅ€Đ°.", "login_has_been_disabled": "Đ’Ņ…Ņ–Đ´ ĐąŅƒĐģĐž виĐŧĐēĐŊĐĩĐŊĐž.", "login_password_changed_error": "ПоĐŧиĐģĐēа ҃ ĐžĐŊОвĐģĐĩĐŊŅ– Đ˛Đ°ŅˆĐžĐŗĐž ĐŋĐ°Ņ€ĐžĐģŅ", "login_password_changed_success": "ĐŸĐ°Ņ€ĐžĐģҌ ĐžĐŊОвĐģĐĩĐŊĐž ҃ҁĐŋŅ–ŅˆĐŊĐž", @@ -1282,6 +1287,7 @@ "onboarding_welcome_user": "Đ›Đ°ŅĐēавО ĐŋŅ€ĐžŅĐ¸ĐŧĐž, {user}", "online": "Đ”ĐžŅŅ‚ŅƒĐŋĐŊиК", "only_favorites": "Đ›Đ¸ŅˆĐĩ ĐžĐąŅ€Đ°ĐŊŅ–", + "open": "Đ’Ņ–Đ´ĐēŅ€Đ¸Ņ‚Đ¸", "open_in_map_view": "Đ’Ņ–Đ´ĐēŅ€Đ¸Ņ‚Đ¸ ҃ ĐŋĐĩŅ€ĐĩĐŗĐģŅĐ´Ņ– ĐŧаĐŋи", "open_in_openstreetmap": "Đ’Ņ–Đ´ĐēŅ€Đ¸Ņ‚Đ¸ в OpenStreetMap", "open_the_search_filters": "Đ’Ņ–Đ´ĐēŅ€Đ¸ĐšŅ‚Đĩ ҄ҖĐģŅŒŅ‚Ņ€Đ¸ ĐŋĐžŅˆŅƒĐē҃", @@ -1304,7 +1310,7 @@ "partner_page_no_more_users": "Đ‘Ņ–ĐģҌ҈Đĩ ĐŊĐĩĐŧĐ°Ņ” ĐēĐžĐŗĐž Đ´ĐžĐ´Đ°Ņ‚Đ¸", "partner_page_partner_add_failed": "НĐĩ вдаĐģĐžŅŅ Đ´ĐžĐ´Đ°Ņ‚Đ¸ ĐŋĐ°Ņ€Ņ‚ĐŊĐĩŅ€Đ°", "partner_page_select_partner": "ĐžĐąŅ€Đ°Ņ‚Đ¸ ĐŋĐ°Ņ€Ņ‚ĐŊĐĩŅ€Đ°", - "partner_page_shared_to_title": "ĐĄĐŋŅ–ĐģҌĐŊĐĩ Ņ–Đˇ ", + "partner_page_shared_to_title": "ĐĄĐŋŅ–ĐģҌĐŊĐĩ Ņ–Đˇ", "partner_page_stop_sharing_content": "{} Đ˛Ņ‚Ņ€Đ°Ņ‚Đ¸Ņ‚ŅŒ Đ´ĐžŅŅ‚ŅƒĐŋ Đ´Đž Đ˛Đ°ŅˆĐ¸Ņ… СĐŊŅ–ĐŧĐēŅ–Đ˛.", "partner_sharing": "ĐĄĐŋŅ–ĐģҌĐŊĐĩ виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ", "partners": "ĐŸĐ°Ņ€Ņ‚ĐŊĐĩŅ€Đ¸", @@ -1338,9 +1344,9 @@ "permission_onboarding_continue_anyway": "Đ’ŅĐĩ ОдĐŊĐž ĐŋŅ€ĐžĐ´ĐžĐ˛ĐļĐ¸Ņ‚Đ¸", "permission_onboarding_get_started": "РОСĐŋĐžŅ‡Đ°Ņ‚Đ¸", "permission_onboarding_go_to_settings": "ПĐĩŅ€ĐĩĐšŅ‚Đ¸ Đ´Đž ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊҌ", - "permission_onboarding_permission_denied": "Đ”ĐžŅŅ‚ŅƒĐŋ ĐˇĐ°ĐąĐžŅ€ĐžĐŊĐĩĐŊĐž. Айи ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ŅŅ Immich, ĐŊĐ°Đ´Đ°ĐšŅ‚Đĩ Đ´ĐžŅŅ‚ŅƒĐŋ Đ´Đž СĐŊŅ–ĐŧĐēŅ–Đ˛ Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž ҃ НаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅŅ….", + "permission_onboarding_permission_denied": "Đ”ĐžŅŅ‚ŅƒĐŋ ĐˇĐ°ĐąĐžŅ€ĐžĐŊĐĩĐŊĐž. ДĐģŅ виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ Immich ĐŊĐ°Đ´Đ°ĐšŅ‚Đĩ дОСвОĐģи Đ´Đž \"Đ¤ĐžŅ‚Đž Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž\" в ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅŅ….", "permission_onboarding_permission_granted": "Đ”ĐžŅŅ‚ŅƒĐŋ ĐŊадаĐŊĐž! Đ’ŅĐĩ ĐŗĐžŅ‚ĐžĐ˛Đž.", - "permission_onboarding_permission_limited": "ОбĐŧĐĩĐļĐĩĐŊиК Đ´ĐžŅŅ‚ŅƒĐŋ. Айи дОСвОĐģĐ¸Ņ‚Đ¸ Immich Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐĩ ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ Ņ‚Đ° ĐēĐĩŅ€ŅƒĐ˛Đ°ĐŊĐŊŅ Đ˛Đ°ŅˆĐžŅŽ ĐŗĐ°ĐģĐĩŅ€ĐĩŅ”ŅŽ, ĐŊĐ°Đ´Đ°ĐšŅ‚Đĩ Đ´ĐžŅŅ‚ŅƒĐŋ Đ´Đž СĐŊŅ–ĐŧĐēŅ–Đ˛ Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž ҃ НаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅŅ…", + "permission_onboarding_permission_limited": "ОбĐŧĐĩĐļĐĩĐŊиК Đ´ĐžŅŅ‚ŅƒĐŋ. Айи дОСвОĐģĐ¸Ņ‚Đ¸ Immich Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐĩ ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ Ņ‚Đ° ĐēĐĩŅ€ŅƒĐ˛Đ°ĐŊĐŊŅ Đ˛Đ°ŅˆĐžŅŽ ĐŗĐ°ĐģĐĩŅ€ĐĩŅ”ŅŽ, ĐŊĐ°Đ´Đ°ĐšŅ‚Đĩ Đ´ĐžŅŅ‚ŅƒĐŋ Đ´Đž СĐŊŅ–ĐŧĐēŅ–Đ˛ Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž ҃ НаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅŅ….", "permission_onboarding_request": "Immich ĐŋĐžŅ‚Ņ€ĐĩĐąŅƒŅ” Đ´ĐžŅŅ‚ŅƒĐŋ҃ Đ´Đž Đ˛Đ°ŅˆĐ¸Ņ… СĐŊŅ–ĐŧĐēŅ–Đ˛ Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž.", "person": "Đ›ŅŽĐ´Đ¸ĐŊа", "person_birthdate": "ĐĐ°Ņ€ĐžĐ´Đ¸Đ˛ŅŅ {date}", @@ -1540,7 +1546,7 @@ "search_result_page_new_search_hint": "Новий ĐŋĐžŅˆŅƒĐē", "search_settings": "НаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ ĐŋĐžŅˆŅƒĐē҃", "search_state": "ĐŸĐžŅˆŅƒĐē Ņ€ĐĩĐŗŅ–ĐžĐŊ҃...", - "search_suggestion_list_smart_search_hint_1": "ІĐŊŅ‚ĐĩĐģĐĩĐēŅ‚ŅƒĐ°ĐģҌĐŊиК ĐŋĐžŅˆŅƒĐē ŅƒĐ˛Ņ–ĐŧĐēĐŊĐĩĐŊĐž Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ, Đ´ĐģŅ ĐŋĐžŅˆŅƒĐē҃ ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐ¸Ņ… виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ ŅĐ¸ĐŊŅ‚Đ°ĐēŅĐ¸Ņ", + "search_suggestion_list_smart_search_hint_1": "Đ ĐžĐˇŅƒĐŧĐŊиК ĐŋĐžŅˆŅƒĐē ŅƒĐ˛Ņ–ĐŧĐēĐŊĐĩĐŊĐž Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ, Đ´ĐģŅ ĐŋĐžŅˆŅƒĐē҃ Са ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊиĐŧи виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ ŅĐ¸ĐŊŅ‚Đ°ĐēŅĐ¸Ņ. ", "search_suggestion_list_smart_search_hint_2": "m:Đ˛Đ°Ņˆ-ĐŋĐžŅˆŅƒĐēОвиК-Ņ‚ĐĩŅ€ĐŧŅ–ĐŊ", "search_tags": "ĐŸĐžŅˆŅƒĐē Ņ‚ĐĩĐŗŅ–Đ˛...", "search_timezone": "ĐŸĐžŅˆŅƒĐē Ņ‡Đ°ŅĐžĐ˛ĐžĐŗĐž ĐŋĐžŅŅŅƒ...", @@ -1582,9 +1588,9 @@ "set_profile_picture": "Đ’ŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ ĐŋŅ€ĐžŅ„Ņ–ĐģŅŽ", "set_slideshow_to_fullscreen": "Đ’ŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ ҁĐģаКд-ŅˆĐžŅƒ ĐŊа вĐĩҁҌ ĐĩĐēŅ€Đ°ĐŊ", "setting_image_viewer_help": "ПовĐŊĐžĐĩĐēŅ€Đ°ĐŊĐŊиК ĐŋĐĩŅ€ĐĩĐŗĐģŅĐ´Đ°Ņ‡ ҁĐŋĐžŅ‡Đ°Ņ‚Đē҃ СаваĐŊŅ‚Đ°ĐļŅƒŅ” ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ Đ´ĐģŅ ĐŋĐžĐŋĐĩŅ€ĐĩĐ´ĐŊŅŒĐžĐŗĐž ĐŋĐĩŅ€ĐĩĐŗĐģŅĐ´Ņƒ в ĐŊĐ¸ĐˇŅŒĐēŅ–Đš Ņ€ĐžĐˇĐ´Ņ–ĐģҌĐŊŅ–Đš ĐˇĐ´Đ°Ņ‚ĐŊĐžŅŅ‚Ņ–, ĐŋĐžŅ‚Ņ–Đŧ СаваĐŊŅ‚Đ°ĐļŅƒŅ” ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ в СĐŧĐĩĐŊ҈ĐĩĐŊŅ–Đš Ņ€ĐžĐˇĐ´Ņ–ĐģҌĐŊŅ–Đš ĐˇĐ´Đ°Ņ‚ĐŊĐžŅŅ‚Ņ– Đ˛Ņ–Đ´ĐŊĐžŅĐŊĐž ĐžŅ€Đ¸ĐŗŅ–ĐŊаĐģ҃ (ŅĐēŅ‰Đž вĐēĐģŅŽŅ‡ĐĩĐŊĐž) Ņ– ĐˇŅ€ĐĩŅˆŅ‚ĐžŅŽ СаваĐŊŅ‚Đ°ĐļŅƒŅ” ĐžŅ€Đ¸ĐŗŅ–ĐŊаĐģ (ŅĐēŅ‰Đž вĐēĐģŅŽŅ‡ĐĩĐŊĐž).", - "setting_image_viewer_original_subtitle": "ĐŖĐ˛Ņ–ĐŧĐēĐŊŅ–Ņ‚ŅŒ Đ´ĐģŅ СаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ ĐžŅ€Đ¸ĐŗŅ–ĐŊаĐģҌĐŊĐžĐŗĐž ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ С ĐŋОвĐŊĐžŅŽ Ņ€ĐžĐˇĐ´Ņ–ĐģҌĐŊĐžŅŽ ĐˇĐ´Đ°Ņ‚ĐŊŅ–ŅŅ‚ŅŽ (вĐĩĐģиĐēĐĩ!).\nВиĐŧĐēĐŊŅ–Ņ‚ŅŒ, Ņ‰ĐžĐą СĐŧĐĩĐŊŅˆĐ¸Ņ‚Đ¸ виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ даĐŊĐ¸Ņ… (ĐŧĐĩŅ€ĐĩĐļŅ– Ņ‚Đ° ĐēĐĩ҈҃ ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅŽ).", + "setting_image_viewer_original_subtitle": "ĐŖĐ˛Ņ–ĐŧĐēĐŊŅƒŅ‚Đ¸ Đ´ĐģŅ СаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ ĐžŅ€Đ¸ĐŗŅ–ĐŊаĐģҌĐŊĐžĐŗĐž ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ С ĐŋОвĐŊĐžŅŽ Ņ€ĐžĐˇĐ´Ņ–ĐģҌĐŊĐžŅŽ ĐˇĐ´Đ°Ņ‚ĐŊŅ–ŅŅ‚ŅŽ (вĐĩĐģиĐēĐĩ!). ВиĐŧĐēĐŊŅƒŅ‚Đ¸, Ņ‰ĐžĐą СĐŧĐĩĐŊŅˆĐ¸Ņ‚Đ¸ виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ даĐŊĐ¸Ņ… (ŅĐē ҇ĐĩŅ€ĐĩС ĐŧĐĩŅ€ĐĩĐļ҃, Ņ‚Đ°Đē Ņ– ĐŊа ĐēĐĩŅˆŅ– ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅŽ).", "setting_image_viewer_original_title": "ЗаваĐŊŅ‚Đ°ĐļŅƒĐ˛Đ°Ņ‚Đ¸ ĐžŅ€Đ¸ĐŗŅ–ĐŊаĐģҌĐŊĐĩ ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ", - "setting_image_viewer_preview_subtitle": "ĐŖĐ˛Ņ–ĐŧĐēĐŊŅ–Ņ‚ŅŒ Đ´ĐģŅ СаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊҌ ҁĐĩŅ€ĐĩĐ´ĐŊŅŒĐžŅ— Ņ€ĐžĐˇĐ´Ņ–ĐģҌĐŊĐžŅ— ĐˇĐ´Đ°Ņ‚ĐŊĐžŅŅ‚Ņ–.\nВиĐŧĐēĐŊŅ–Ņ‚ŅŒ Đ´ĐģŅ ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐžĐŗĐž СаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ ĐžŅ€Đ¸ĐŗŅ–ĐŊаĐģ҃ айО виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐģĐ¸ŅˆĐĩ ĐŧŅ–ĐŊŅ–Đ°Ņ‚ŅŽŅ€Ņƒ.", + "setting_image_viewer_preview_subtitle": "ĐŖĐ˛Ņ–ĐŧĐēĐŊŅƒŅ‚Đ¸ Đ´ĐģŅ СаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ ҁĐĩŅ€ĐĩĐ´ĐŊŅŒĐžŅ— Ņ€ĐžĐˇĐ´Ņ–ĐģҌĐŊĐžŅ— ĐˇĐ´Đ°Ņ‚ĐŊĐžŅŅ‚Ņ–. ВиĐŧĐēĐŊŅƒŅ‚Đ¸, Ņ‰ĐžĐą СаваĐŊŅ‚Đ°ĐļŅƒĐ˛Đ°Ņ‚Đ¸ ĐžŅ€Đ¸ĐŗŅ–ĐŊаĐģ айО виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ҂ҖĐģҌĐēи ĐĩҁĐēŅ–Đˇ.", "setting_image_viewer_preview_title": "ЗаваĐŊŅ‚Đ°ĐļŅƒĐ˛Đ°Ņ‚Đ¸ ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ ĐŋĐžĐŋĐĩŅ€ĐĩĐ´ĐŊŅŒĐžĐŗĐž ĐŋĐĩŅ€ĐĩĐŗĐģŅĐ´Ņƒ", "setting_image_viewer_title": "Đ—ĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ", "setting_languages_apply": "Đ—Đ°ŅŅ‚ĐžŅŅƒĐ˛Đ°Ņ‚Đ¸", @@ -1783,7 +1789,7 @@ "trash_emptied": "ĐšĐžŅˆĐ¸Đē ĐžŅ‡Đ¸Ņ‰ĐĩĐŊиК", "trash_no_results_message": "ĐĸŅƒŅ‚ С'ŅĐ˛ĐģŅŅ‚Đ¸ĐŧŅƒŅ‚ŅŒŅŅ видаĐģĐĩĐŊŅ– Ņ„ĐžŅ‚Đž Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž.", "trash_page_delete_all": "ВидаĐģĐ¸Ņ‚Đ¸ ŅƒŅŅ–", - "trash_page_empty_trash_dialog_content": "БаĐļĐ°Ņ”Ņ‚Đĩ ĐžŅ‡Đ¸ŅŅ‚Đ¸Ņ‚Đ¸ Đ˛Đ°ŅˆŅ– ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ в ĐēĐžŅˆĐ¸Đē҃? ĐĻŅ– ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ ĐąŅƒĐ´Đĩ ĐžŅŅ‚Đ°Ņ‚ĐžŅ‡ĐŊĐž видаĐģĐĩĐŊĐž С Immich.", + "trash_page_empty_trash_dialog_content": "Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐžŅ‡Đ¸ŅŅ‚Đ¸Ņ‚Đ¸ ĐēĐžŅˆĐ¸Đē? ĐĻŅ– ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ ĐąŅƒĐ´ŅƒŅ‚ŅŒ ĐžŅŅ‚Đ°Ņ‚ĐžŅ‡ĐŊĐž видаĐģĐĩĐŊŅ– С Immich", "trash_page_info": "ПоĐŧҖ҉ĐĩĐŊŅ– ҃ ĐēĐžŅˆĐ¸Đē ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ ĐąŅƒĐ´Đĩ ĐžŅŅ‚Đ°Ņ‚ĐžŅ‡ĐŊĐž видаĐģĐĩĐŊĐž ҇ĐĩŅ€ĐĩС {} Đ´ĐŊŅ–Đ˛", "trash_page_no_assets": "Đ’Ņ–Đ´Đ´Đ°ĐģĐĩĐŊŅ– ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ Đ˛Ņ–Đ´ŅŅƒŅ‚ĐŊŅ–", "trash_page_restore_all": "Đ’Ņ–Đ´ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ ŅƒŅŅ–", @@ -1851,9 +1857,9 @@ "version_announcement_closing": "ĐĸĐ˛Ņ–Đš Đ´Ņ€ŅƒĐŗ, АĐģĐĩĐēҁ", "version_announcement_message": "ĐŸŅ€Đ¸Đ˛Ņ–Ņ‚! Đ”ĐžŅŅ‚ŅƒĐŋĐŊа ĐŊОва вĐĩŅ€ŅŅ–Ņ Immich. Đ‘ŅƒĐ´ŅŒ ĐģĐ°ŅĐēа, ĐŋŅ€Đ¸Đ´Ņ–ĐģŅ–Ņ‚ŅŒ Ņ‚Ņ€ĐžŅ…Đ¸ Ņ‡Đ°ŅŅƒ Đ´ĐģŅ ОСĐŊаКОĐŧĐģĐĩĐŊĐŊŅ С ĐŋŅ€Đ¸ĐŧŅ–Ņ‚ĐēаĐŧи Đ´Đž виĐŋ҃ҁĐē҃, Ņ‰ĐžĐą ĐŋĐĩŅ€ĐĩĐēĐžĐŊĐ°Ņ‚Đ¸ŅŅ, Ņ‰Đž Đ˛Đ°ŅˆĐ° ŅƒŅŅ‚Đ°ĐŊОвĐēа ĐžĐŊОвĐģĐĩĐŊа Ņ– ҃ĐŊиĐēĐŊŅƒŅ‚Đ¸ ĐŧĐžĐļĐģĐ¸Đ˛Đ¸Ņ… ĐŋĐžĐŧиĐģĐžĐē ҃ ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅŅ…, ĐžŅĐžĐąĐģивО ŅĐēŅ‰Đž ви виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ WatchTower айО ĐąŅƒĐ´ŅŒ-ŅĐēиК Ņ–ĐŊŅˆĐ¸Đš ĐŧĐĩŅ…Đ°ĐŊŅ–ĐˇĐŧ, ŅĐēиК Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ĐžĐŊОвĐģŅŽŅ” Đ˛Đ°Ņˆ ĐĩĐēСĐĩĐŧĐŋĐģŅŅ€ Immich.", "version_announcement_overlay_release_notes": "ĐŋŅ€Đ¸ĐŧŅ–Ņ‚Đēи Đ´Đž виĐŋ҃ҁĐē҃", - "version_announcement_overlay_text_1": "Đ’Ņ–Ņ‚Đ°Ņ”ĐŧĐž, Ņ” ĐŊОвиК виĐŋ҃ҁĐē ", + "version_announcement_overlay_text_1": "Đ’Ņ–Ņ‚Đ°Ņ”ĐŧĐž, Ņ” ĐŊОвиК виĐŋ҃ҁĐē", "version_announcement_overlay_text_2": "СĐŊĐ°ĐšĐ´Ņ–Ņ‚ŅŒ Ņ…Đ˛Đ¸ĐģҌĐē҃ ĐŊĐ°Đ˛Ņ–Đ´Đ°Ņ‚Đ¸ŅŅ ĐŊа ", - "version_announcement_overlay_text_3": "Ņ– ĐŋĐĩŅ€ĐĩĐēĐžĐŊĐ°ĐšŅ‚ĐĩŅŅ, Ņ‰Đž Đ˛Đ°ŅˆŅ– ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ docker-compose Ņ‚Đ° .env ĐžĐŊОвĐģĐĩĐŊŅ–, айи СаĐŋĐžĐąŅ–ĐŗŅ‚Đ¸ ĐąŅƒĐ´ŅŒ-ŅĐēŅ–Đš ĐŊĐĩĐŋŅ€Đ°Đ˛Đ¸ĐģҌĐŊŅ–Đš ĐēĐžĐŊŅ„Ņ–ĐŗŅƒŅ€Đ°Ņ†Ņ–Ņ—, ĐžŅĐžĐąĐģивО, ŅĐēŅ‰Đž ви виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ WatchTower айО Ņ–ĐŊŅˆĐ¸Đš ĐŧĐĩŅ…Đ°ĐŊŅ–ĐˇĐŧ, Đ´ĐģŅ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐ¸Ņ… ĐžĐŊОвĐģĐĩĐŊҌ Đ˛Đ°ŅˆĐžŅ— ҁĐĩŅ€Đ˛ĐĩŅ€ĐŊĐžŅ— Ņ‡Đ°ŅŅ‚Đ¸ĐŊи.", + "version_announcement_overlay_text_3": " Ņ– ĐŋĐĩŅ€ĐĩĐēĐžĐŊĐ°ĐšŅ‚ĐĩŅŅ, Ņ‰Đž Đ˛Đ°ŅˆŅ– ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ docker-compose Ņ‚Đ° .env ĐžĐŊОвĐģĐĩĐŊŅ–, айи СаĐŋĐžĐąŅ–ĐŗŅ‚Đ¸ ĐąŅƒĐ´ŅŒ-ŅĐēŅ–Đš ĐŊĐĩĐŋŅ€Đ°Đ˛Đ¸ĐģҌĐŊŅ–Đš ĐēĐžĐŊŅ„Ņ–ĐŗŅƒŅ€Đ°Ņ†Ņ–Ņ—, ĐžŅĐžĐąĐģивО, ŅĐēŅ‰Đž ви виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ WatchTower айО Ņ–ĐŊŅˆĐ¸Đš ĐŧĐĩŅ…Đ°ĐŊŅ–ĐˇĐŧ, Đ´ĐģŅ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐ¸Ņ… ĐžĐŊОвĐģĐĩĐŊҌ Đ˛Đ°ŅˆĐžŅ— ҁĐĩŅ€Đ˛ĐĩŅ€ĐŊĐžŅ— Ņ‡Đ°ŅŅ‚Đ¸ĐŊи.", "version_announcement_overlay_title": "Đ”ĐžŅŅ‚ŅƒĐŋĐŊа ĐŊОва вĐĩŅ€ŅŅ–Ņ ҁĐĩŅ€Đ˛ĐĩŅ€Đ° 🎉", "version_history": "Đ†ŅŅ‚ĐžŅ€Ņ–Ņ вĐĩŅ€ŅŅ–Đš", "version_history_item": "Đ’ŅŅ‚Đ°ĐŊОвĐģĐĩĐŊĐž {version} {date}", diff --git a/i18n/vi.json b/i18n/vi.json index fdcea7772c..9262d8a6b3 100644 --- a/i18n/vi.json +++ b/i18n/vi.json @@ -525,7 +525,7 @@ "backup_controller_page_backup_sub": "áēĸnh và video Ä‘ÃŖ sao lưu", "backup_controller_page_created": "TáēĄo vào: {}", "backup_controller_page_desc_backup": "Báē­t sao lưu khi áģŠng dáģĨng hoáēĄt đáģ™ng đáģƒ táģą Ä‘áģ™ng sao lưu áēŖnh máģ›i lÃĒn mÃĄy cháģ§ khi máģŸ áģŠng dáģĨng.", - "backup_controller_page_excluded": "ÄÃŖ báģ qua:", + "backup_controller_page_excluded": "ÄÃŖ báģ qua: ", "backup_controller_page_failed": "TháēĨt báēĄi ({})", "backup_controller_page_filename": "TÃĒn táģ‡p: {} [{}]", "backup_controller_page_id": "ID: {}", @@ -537,7 +537,7 @@ "backup_controller_page_start_backup": "Báē¯t đáē§u sao lưu", "backup_controller_page_status_off": "Sao lưu táģą Ä‘áģ™ng khi áģŠng dáģĨng hoáēĄt đáģ™ng đang táē¯t", "backup_controller_page_status_on": "Sao lưu táģą Ä‘áģ™ng khi áģŠng dáģĨng hoáēĄt đáģ™ng đang báē­t", - "backup_controller_page_storage_format": "ÄÃŖ sáģ­ dáģĨng {} cáģ§a {} ", + "backup_controller_page_storage_format": "ÄÃŖ sáģ­ dáģĨng {} cáģ§a {}", "backup_controller_page_to_backup": "CÃĄc album cáē§n đưáģŖc sao lưu", "backup_controller_page_total_sub": "TáēĨt cáēŖ áēŖnh và video không trÚng láē­p táģĢ cÃĄc album đưáģŖc cháģn", "backup_controller_page_turn_off": "Táē¯t sao lưu khi áģŠng dáģĨng hoáēĄt đáģ™ng", diff --git a/i18n/zh_Hant.json b/i18n/zh_Hant.json index bb5094e352..7758052880 100644 --- a/i18n/zh_Hant.json +++ b/i18n/zh_Hant.json @@ -400,9 +400,9 @@ "album_remove_user_confirmation": "įĸē厚čρį§ģ除 {user} 嗎īŧŸ", "album_share_no_users": "įœ‹äž†æ‚¨čˆ‡æ‰€æœ‰äŊŋį”¨č€…å…ąäēĢäē†é€™æœŦᛏį°ŋīŧŒæˆ–æ˛’æœ‰å…ļäģ–äŊŋį”¨č€…å¯äž›åˆ†äēĢ。", "album_thumbnail_card_item": "1 項", - "album_thumbnail_card_items": "{} 項", + "album_thumbnail_card_items": "{} 項", "album_thumbnail_card_shared": " ¡ åˇ˛å…ąäēĢ", - "album_thumbnail_shared_by": "į”ą {} å…ąäēĢ", + "album_thumbnail_shared_by": "į”ą {} å…ąäēĢ", "album_updated": "æ›´æ–°į›¸į°ŋ時", "album_updated_setting_description": "į•ļå…ąäēĢᛏį°ŋ有新æĒ”æĄˆæ™‚īŧŒį”¨é›ģ子éƒĩäģļ通įŸĨ我", "album_user_left": "厞é›ĸ開 {album}", @@ -440,7 +440,7 @@ "archive": "封存", "archive_or_unarchive_photo": "封存或取æļˆå°å­˜į…§į‰‡", "archive_page_no_archived_assets": "æœĒ扞到歸æĒ”é …į›Ž", - "archive_page_title": "æ­¸æĒ”īŧˆ {} īŧ‰", + "archive_page_title": "封存 ({})", "archive_size": "封存量", "archive_size_description": "č¨­åŽščρ䏋čŧ‰įš„封存量īŧˆå–ŽäŊīŧšGiBīŧ‰", "archived": "厞存æĒ”", @@ -506,11 +506,11 @@ "backup_all": "全部", "backup_background_service_backup_failed_message": "備äģŊå¤ąæ•—īŧŒæ­Ŗåœ¨é‡čŠĻâ€Ļ", "backup_background_service_connection_failed_message": "逪æŽĨäŧ翜å™¨å¤ąæ•—īŧŒæ­Ŗåœ¨é‡čŠĻâ€Ļ", - "backup_background_service_current_upload_notification": "æ­Ŗåœ¨ä¸Šå‚ŗ {} ", + "backup_background_service_current_upload_notification": "æ­Ŗåœ¨ä¸Šå‚ŗ {}", "backup_background_service_default_notification": "æ­Ŗåœ¨æĒĸæŸĨæ–°é …į›Žâ€Ļ", "backup_background_service_error_title": "備äģŊå¤ąæ•—", "backup_background_service_in_progress_notification": "æ­Ŗåœ¨å‚™äģŊâ€Ļ", - "backup_background_service_upload_failure_notification": "ä¸Šå‚ŗå¤ąæ•— {} ", + "backup_background_service_upload_failure_notification": "ä¸Šå‚ŗå¤ąæ•— {}", "backup_controller_page_albums": "備äģŊᛏį°ŋ", "backup_controller_page_background_app_refresh_disabled_content": "čρäŊŋį”¨čƒŒæ™¯å‚™äģŊ功čƒŊīŧŒčĢ‹åœ¨ã€Œč¨­åŽšã€>「備äģŊ」>ã€ŒčƒŒæ™¯åĨ—į”¨æ›´æ–°ã€ä¸­å•“į”¨čƒŒæœŦፋåŧæ›´æ–°ã€‚", "backup_controller_page_background_app_refresh_disabled_title": "čƒŒæ™¯åĨ—į”¨æ›´æ–°åˇ˛įρᔍ", @@ -531,12 +531,12 @@ "backup_controller_page_backup": "備äģŊ", "backup_controller_page_backup_selected": "厞遏䏭īŧš", "backup_controller_page_backup_sub": "厞備äģŊįš„į…§į‰‡å’ŒįŸ­į‰‡", - "backup_controller_page_created": "新åĸžæ™‚é–“: {} ", + "backup_controller_page_created": "新åĸžæ™‚é–“: {}", "backup_controller_page_desc_backup": "打開前台備äģŊīŧŒäģĨæœŦፋåŧé‹čĄŒæ™‚č‡Ē動備äģŊæ–°é …į›Žã€‚", "backup_controller_page_excluded": "åˇ˛æŽ’é™¤īŧš", "backup_controller_page_failed": "å¤ąæ•—īŧˆ {} īŧ‰", "backup_controller_page_filename": "文äģļåį¨ą: {} [ {} ]", - "backup_controller_page_id": "ID: {} ", + "backup_controller_page_id": "ID: {}", "backup_controller_page_info": "備äģŊčŗ‡č¨Š", "backup_controller_page_none_selected": "æœĒ選擇", "backup_controller_page_remainder": "削餘", @@ -545,7 +545,7 @@ "backup_controller_page_start_backup": "開始備äģŊ", "backup_controller_page_status_off": "前台č‡Ē動備äģŊåˇ˛é—œé–‰", "backup_controller_page_status_on": "前台č‡Ē動備äģŊ厞開啓", - "backup_controller_page_storage_format": " {} / {} 厞äŊŋᔍ", + "backup_controller_page_storage_format": "{} / {} 厞äŊŋᔍ", "backup_controller_page_to_backup": "čρ備äģŊįš„į›¸į°ŋ", "backup_controller_page_total_sub": "遏䏭ᛏį°ŋä¸­æ‰€æœ‰ä¸é‡č¤‡įš„įŸ­į‰‡å’Œåœ–į‰‡", "backup_controller_page_turn_off": "關閉前台備äģŊ", @@ -578,7 +578,7 @@ "cache_settings_duplicated_assets_title": "é‡č¤‡é …į›Žīŧˆ {} īŧ‰", "cache_settings_image_cache_size": "åœ–į‰‡įˇŠå­˜å¤§å°īŧˆ {} 項īŧ‰", "cache_settings_statistics_album": "圖åēĢį¸Žåœ–", - "cache_settings_statistics_assets": " {} 項īŧˆ {} īŧ‰", + "cache_settings_statistics_assets": "{} 項īŧˆ {} īŧ‰", "cache_settings_statistics_full": "åŽŒæ•´åœ–į‰‡", "cache_settings_statistics_shared": "å…ąäēĢᛏį°ŋį¸Žåœ–", "cache_settings_statistics_thumbnail": "į¸Žåœ–", @@ -654,7 +654,7 @@ "contain": "包åĢ", "context": "情åĸƒ", "continue": "įšŧįēŒ", - "control_bottom_app_bar_album_info_shared": " {} 項 ¡ åˇ˛å…ąäēĢ", + "control_bottom_app_bar_album_info_shared": "{} 項 ¡ åˇ˛å…ąäēĢ", "control_bottom_app_bar_create_new_album": "新åĸžį›¸į°ŋ", "control_bottom_app_bar_delete_from_immich": "åžžImmichäŧ翜å™¨ä¸­åˆĒ除", "control_bottom_app_bar_delete_from_local": "åžžį§ģå‹•čŖįŊŽä¸­åˆĒ除", @@ -763,7 +763,7 @@ "download_enqueue": "厞加å…Ĩ下čŧ‰éšŠåˆ—", "download_error": "下čŧ‰å‡ē錯", "download_failed": "下čŧ‰å¤ąæ•—", - "download_filename": "文äģļīŧš {} ", + "download_filename": "文äģļīŧš {}", "download_finished": "下čŧ‰åŽŒæˆ", "download_include_embedded_motion_videos": "åĩŒå…ĨåŊąį‰‡", "download_include_embedded_motion_videos_description": "把åĩŒå…Ĩå‹•æ…‹į…§į‰‡įš„åŊąį‰‡äŊœį‚ēå–Žį¨įš„æĒ”æĄˆåŒ…åĢ在內", @@ -819,7 +819,7 @@ "error_change_sort_album": "Failed to change album sort order", "error_delete_face": "åžžé …į›Žä¸­åˆĒé™¤č‡‰å­”æ™‚į™ŧį”ŸéŒ¯čǤ", "error_loading_image": "čŧ‰å…Ĩåœ–į‰‡æ™‚å‡ē錯", - "error_saving_image": "錯čǤīŧš {} ", + "error_saving_image": "錯čǤīŧš {}", "error_title": "錯čǤ - å‡ēå•éĄŒäē†", "errors": { "cannot_navigate_next_asset": "į„Ąæŗ•į€čĻŊ下一個æĒ”æĄˆ", @@ -1170,8 +1170,8 @@ "manage_your_devices": "įŽĄį†åˇ˛į™ģå…Ĩįš„čŖįŊŽ", "manage_your_oauth_connection": "įŽĄį†æ‚¨įš„ OAuth 逪æŽĨ", "map": "地圖", - "map_assets_in_bound": " {} åŧĩᅧቇ", - "map_assets_in_bounds": " {} åŧĩᅧቇ", + "map_assets_in_bound": "{} åŧĩᅧቇ", + "map_assets_in_bounds": "{} åŧĩᅧቇ", "map_cannot_get_user_location": "į„Ąæŗ•į˛å–į”¨æˆļäŊįŊŽ", "map_location_dialog_yes": "įĸē厚", "map_location_picker_page_use_location": "äŊŋį”¨æ­¤äŊįŊŽ", @@ -1185,9 +1185,9 @@ "map_settings": "åœ°åœ–č¨­åŽš", "map_settings_dark_mode": "æˇąč‰˛æ¨Ąåŧ", "map_settings_date_range_option_day": "過åŽģ24小時", - "map_settings_date_range_option_days": " {} 夊前", + "map_settings_date_range_option_days": "{} 夊前", "map_settings_date_range_option_year": "1嚴前", - "map_settings_date_range_option_years": " {} 嚴前", + "map_settings_date_range_option_years": "{} 嚴前", "map_settings_dialog_title": "åœ°åœ–č¨­åŽš", "map_settings_include_show_archived": "包æ‹Ŧåˇ˛æ­¸æĒ”é …į›Ž", "map_settings_include_show_partners": "包åĢå¤Ĩäŧ´", @@ -1203,7 +1203,7 @@ "memories_start_over": "å†įœ‹ä¸€æŦĄ", "memories_swipe_to_close": "上æģ‘關閉", "memories_year_ago": "1嚴前", - "memories_years_ago": " {} 嚴前", + "memories_years_ago": "{} 嚴前", "memory": "回æ†ļ", "memory_lane_title": "回æ†ļ長åģŠ{title}", "menu": "選喎", @@ -1305,7 +1305,7 @@ "partner_page_partner_add_failed": "新åĸžåŒäŧ´å¤ąæ•—", "partner_page_select_partner": "選擇同äŧ´", "partner_page_shared_to_title": "å…ąäēĢįĩĻ", - "partner_page_stop_sharing_content": " {} å°‡į„Ąæŗ•å†å­˜å–æ‚¨įš„į…§į‰‡ã€‚", + "partner_page_stop_sharing_content": "{} å°‡į„Ąæŗ•å†å­˜å–æ‚¨įš„į…§į‰‡ã€‚", "partner_sharing": "å¤Ĩäŧ´åˆ†äēĢ", "partners": "å¤Ĩäŧ´", "password": "密įĸŧ", @@ -1590,12 +1590,12 @@ "setting_languages_apply": "åĨ—ᔍ", "setting_languages_subtitle": "Change the app's language", "setting_languages_title": "čĒžč¨€", - "setting_notifications_notify_failures_grace_period": "čƒŒæ™¯å‚™äģŊå¤ąæ•—é€šįŸĨīŧš {} ", - "setting_notifications_notify_hours": " {} 小時", + "setting_notifications_notify_failures_grace_period": "čƒŒæ™¯å‚™äģŊå¤ąæ•—é€šįŸĨīŧš {}", + "setting_notifications_notify_hours": "{} 小時", "setting_notifications_notify_immediately": "įĢ‹åŗ", - "setting_notifications_notify_minutes": " {} 分鐘", + "setting_notifications_notify_minutes": "{} 分鐘", "setting_notifications_notify_never": "垞不", - "setting_notifications_notify_seconds": " {} į§’", + "setting_notifications_notify_seconds": "{} į§’", "setting_notifications_single_progress_subtitle": "æ¯é …įš„čŠŗį´°ä¸Šå‚ŗé€˛åēĻčŗ‡č¨Š", "setting_notifications_single_progress_title": "éĄ¯į¤ēčƒŒæ™¯å‚™äģŊčŠŗį´°é€˛åēĻ", "setting_notifications_subtitle": "čĒŋ整通įŸĨ選項", @@ -1609,7 +1609,7 @@ "settings_saved": "č¨­åŽšåˇ˛å„˛å­˜", "share": "分äēĢ", "share_add_photos": "新åĸžé …į›Ž", - "share_assets_selected": " {} åˇ˛é¸æ“‡", + "share_assets_selected": "{} åˇ˛é¸æ“‡", "share_dialog_preparing": "æ­Ŗåœ¨æē–å‚™...", "shared": "å…ąäēĢ", "shared_album_activities_input_disable": "厞įĻį”¨čŠ•čĢ–", @@ -1626,28 +1626,28 @@ "shared_intent_upload_button_progress_text": "{} / {} Uploaded", "shared_link_app_bar_title": "å…ąäēĢ鏈æŽĨ", "shared_link_clipboard_copied_massage": "複čŖŊ到å‰Ēč˛ŧæŋ", - "shared_link_clipboard_text": "鏈æŽĨīŧš {} \n密įĸŧīŧš {} ", + "shared_link_clipboard_text": "鏈æŽĨīŧš {} \n密įĸŧīŧš {}", "shared_link_create_error": "新åĸžå…ąäēĢ鏈æŽĨå‡ē錯", "shared_link_edit_description_hint": "ᎍčŧ¯å…ąäēĢæčŋ°", "shared_link_edit_expire_after_option_day": "1夊", - "shared_link_edit_expire_after_option_days": " {} 夊", + "shared_link_edit_expire_after_option_days": "{} 夊", "shared_link_edit_expire_after_option_hour": "1小時", - "shared_link_edit_expire_after_option_hours": " {} 小時", + "shared_link_edit_expire_after_option_hours": "{} 小時", "shared_link_edit_expire_after_option_minute": "1分鐘", - "shared_link_edit_expire_after_option_minutes": " {} 分鐘", - "shared_link_edit_expire_after_option_months": " {} 個月", - "shared_link_edit_expire_after_option_year": " {} åš´", + "shared_link_edit_expire_after_option_minutes": "{} 分鐘", + "shared_link_edit_expire_after_option_months": "{} 個月", + "shared_link_edit_expire_after_option_year": "{} åš´", "shared_link_edit_password_hint": "čŧ¸å…Ĩå…ąäēĢ密įĸŧ", "shared_link_edit_submit_button": "更新鏈æŽĨ", "shared_link_error_server_url_fetch": "į„Ąæŗ•į˛å–äŧ翜å™¨åœ°å€", - "shared_link_expires_day": " {} 夊垌過期", - "shared_link_expires_days": " {} 夊垌過期", - "shared_link_expires_hour": " {} 小時垌過期", - "shared_link_expires_hours": " {} 小時垌過期", - "shared_link_expires_minute": " {} 分鐘垌過期", + "shared_link_expires_day": "{} 夊垌過期", + "shared_link_expires_days": "{} 夊垌過期", + "shared_link_expires_hour": "{} 小時垌過期", + "shared_link_expires_hours": "{} 小時垌過期", + "shared_link_expires_minute": "{} 分鐘垌過期", "shared_link_expires_minutes": "將在 {} 分鐘垌過期", "shared_link_expires_never": "永不過期", - "shared_link_expires_second": " {} į§’åžŒéŽæœŸ", + "shared_link_expires_second": "{} į§’åžŒéŽæœŸ", "shared_link_expires_seconds": "將在 {} į§’åžŒéŽæœŸ", "shared_link_individual_shared": "個äēēå…ąäēĢ", "shared_link_info_chip_metadata": "EXIF", diff --git a/i18n/zh_SIMPLIFIED.json b/i18n/zh_SIMPLIFIED.json index 20b906ced3..573fbb7a24 100644 --- a/i18n/zh_SIMPLIFIED.json +++ b/i18n/zh_SIMPLIFIED.json @@ -39,11 +39,11 @@ "authentication_settings_disable_all": "įĄŽåŽščρįĻį”¨æ‰€æœ‰įš„į™ģåŊ•æ–šåŧīŧŸč¯Ĩ操äŊœå°†åŽŒå…¨įρæ­ĸį™ģåŊ•。", "authentication_settings_reenable": "åĻ‚éœ€å†æŦĄå¯į”¨īŧŒäŊŋᔍ æœåŠĄå™¨æŒ‡äģ¤ã€‚", "background_task_job": "后台äģģåŠĄ", - "backup_database": "备äģŊ数捎åē“", - "backup_database_enable_description": "å¯į”¨æ•°æŽåē“备äģŊ", - "backup_keep_last_amount": "čρäŋį•™įš„åŽ†å˛å¤‡äģŊ数量", - "backup_settings": "备äģŊ莞įŊŽ", - "backup_settings_description": "įŽĄį†æ•°æŽåē“备äģŊ莞įŊŽ", + "backup_database": "创åģēæ•°æŽåē“备äģŊ", + "backup_database_enable_description": "å¯į”¨æ•°æŽåē“å¯ŧå‡ē备äģŊ", + "backup_keep_last_amount": "čρäŋį•™įš„åŽ†å˛å¯ŧå‡ē数量", + "backup_settings": "数捎åē“å¯ŧå‡ē莞įŊŽ", + "backup_settings_description": "įŽĄį†æ•°æŽåē“备äģŊ莞įŊŽã€‚æŗ¨æ„īŧščŋ™äē›äģģåŠĄä¸äŧščĸĢį›‘æŽ§īŧŒå¤ąč´Ĩ也不äŧšé€šįŸĨ您。", "check_all": "æŖ€æŸĨ全部", "cleanup": "æ¸…į†", "cleared_jobs": "åˇ˛æ¸…į†äģģåŠĄīŧš{job}", @@ -371,13 +371,17 @@ "admin_password": "įŽĄį†å‘˜å¯†į ", "administration": "įŗģįģŸįŽĄį†", "advanced": "é̘įē§", - "advanced_settings_log_level_title": "æ—Ĩåŋ—į­‰įē§īŧš{}", - "advanced_settings_prefer_remote_subtitle": "在某äē›čŽžå¤‡ä¸ŠīŧŒäģŽæœŦåœ°įš„éĄšį›ŽåŠ čŊŊįŧŠį•Ĩå›žįš„é€ŸåēĻ非常æ…ĸ。\nå¯į”¨æ­¤é€‰éĄšäģĨ加čŊŊčŋœį¨‹éĄšį›Žã€‚", + "advanced_settings_enable_alternate_media_filter_subtitle": "äŊŋį”¨æ­¤é€‰éĄšå¯åœ¨åŒæ­Ĩčŋ‡į¨‹ä¸­æ šæŽå¤‡į”¨æĄäģļį­›é€‰éĄšį›Žã€‚äģ…åŊ“您在åē”ᔍፋåēæŖ€æĩ‹æ‰€æœ‰į›¸å†Œå‡é‡åˆ°é—Žéĸ˜æ—￉å°č¯•此功čƒŊ。", + "advanced_settings_enable_alternate_media_filter_title": "[厞énj] äŊŋį”¨å¤‡į”¨įš„čŽžå¤‡į›¸å†ŒåŒæ­Ĩį­›é€‰æĄäģļ", + "advanced_settings_log_level_title": "æ—Ĩåŋ—į­‰įē§: {}", + "advanced_settings_prefer_remote_subtitle": "在某äē›čŽžå¤‡ä¸ŠīŧŒäģŽæœŦåœ°įš„éĄšį›ŽåŠ čŊŊįŧŠį•Ĩå›žįš„é€ŸåēĻ非常æ…ĸã€‚å¯į”¨æ­¤é€‰éĄšäģĨ加čŊŊčŋœį¨‹éĄšį›Žã€‚", "advanced_settings_prefer_remote_title": "äŧ˜å…ˆčŋœį¨‹éĄšį›Ž", "advanced_settings_proxy_headers_subtitle": "厚䚉äģŖį†æ ‡å¤´īŧŒåē”ᔍäēŽImmichįš„æ¯æŦĄįŊ‘įģœč¯ˇæą‚", "advanced_settings_proxy_headers_title": "äģŖį†æ ‡å¤´", "advanced_settings_self_signed_ssl_subtitle": "莺čŋ‡æœåŠĄå™¨įģˆįģ“į‚šįš„ SSL 蝁äšĻénj蝁īŧˆč¯Ĩé€‰éĄšé€‚į”¨äēŽäŊŋᔍč‡Ēį­žåč¯äšĻįš„æœåŠĄå™¨īŧ‰ã€‚", "advanced_settings_self_signed_ssl_title": "å…čŽ¸č‡Ēį­žå SSL 蝁äšĻ", + "advanced_settings_sync_remote_deletions_subtitle": "在įŊ‘éĄĩä¸Šæ‰§čĄŒæ“äŊœæ—ļīŧŒč‡Ē动删除或čŋ˜åŽŸč¯ĨčŽžå¤‡ä¸­įš„éĄšį›Ž", + "advanced_settings_sync_remote_deletions_title": "čŋœį¨‹åŒæ­Ĩ删除 [厞énj]", "advanced_settings_tile_subtitle": "é̘įē§į”¨æˆˇčŽžįŊŽ", "advanced_settings_troubleshooting_subtitle": "吝ᔍᔍäēŽæ•…éšœæŽ’é™¤įš„éĸå¤–功čƒŊ", "advanced_settings_troubleshooting_title": "故障排除", @@ -477,18 +481,18 @@ "assets_added_to_album_count": "厞æˇģ加{count, plural, one {#ä¸ĒéĄšį›Ž} other {#ä¸ĒéĄšį›Ž}}åˆ°į›¸å†Œ", "assets_added_to_name_count": "厞æˇģ加{count, plural, one {#ä¸ĒéĄšį›Ž} other {#ä¸ĒéĄšį›Ž}}到{hasName, select, true {{name}} other {æ–°į›¸å†Œ}}", "assets_count": "{count, plural, one {#ä¸ĒéĄšį›Ž} other {#ä¸ĒéĄšį›Ž}}", - "assets_deleted_permanently": "{}ä¸ĒéĄšį›Žåˇ˛čĸĢæ°¸äš…删除", - "assets_deleted_permanently_from_server": "厞äģŽæœåŠĄå™¨ä¸­æ°¸äš…į§ģ除{}ä¸ĒéĄšį›Ž", + "assets_deleted_permanently": "{} ä¸ĒéĄšį›Žåˇ˛čĸĢæ°¸äš…删除", + "assets_deleted_permanently_from_server": "åˇ˛æ°¸äš…į§ģ除 {} ä¸ĒéĄšį›Ž", "assets_moved_to_trash_count": "厞į§ģ动{count, plural, one {#ä¸ĒéĄšį›Ž} other {#ä¸ĒéĄšį›Ž}}到回æ”ļįĢ™", "assets_permanently_deleted_count": "åˇ˛æ°¸äš…åˆ é™¤{count, plural, one {#ä¸ĒéĄšį›Ž} other {#ä¸ĒéĄšį›Ž}}", "assets_removed_count": "厞į§ģ除{count, plural, one {#ä¸ĒéĄšį›Ž} other {#ä¸ĒéĄšį›Ž}}", - "assets_removed_permanently_from_device": "厞äģŽčŽžå¤‡ä¸­æ°¸äš…į§ģ除{}ä¸ĒéĄšį›Ž", + "assets_removed_permanently_from_device": "厞äģŽčŽžå¤‡ä¸­æ°¸äš…į§ģ除 {} ä¸ĒéĄšį›Ž", "assets_restore_confirmation": "įĄŽåŽščρæĸ复回æ”ļįĢ™ä¸­įš„æ‰€æœ‰éĄšį›Žå—īŧŸč¯Ĩ操äŊœæ— æŗ•æ’¤æļˆīŧč¯ˇæŗ¨æ„īŧŒč„ąæœēéĄšį›Žæ— æŗ•é€ščŋ‡čŋ™į§æ–šåŧæĸ复。", "assets_restored_count": "厞æĸ复{count, plural, one {#ä¸ĒéĄšį›Ž} other {#ä¸ĒéĄšį›Ž}}", "assets_restored_successfully": "åˇ˛æˆåŠŸæĸ复{}ä¸ĒéĄšį›Ž", - "assets_trashed": "{}ä¸Ē回æ”ļįĢ™éĄšį›Ž", + "assets_trashed": "{} ä¸ĒéĄšį›Žæ”žå…Ĩ回æ”ļįĢ™", "assets_trashed_count": "{count, plural, one {#ä¸ĒéĄšį›Ž} other {#ä¸ĒéĄšį›Ž}}åˇ˛æ”žå…Ĩ回æ”ļįĢ™", - "assets_trashed_from_server": "{}ä¸ĒéĄšį›Žåˇ˛æ”žå…Ĩ回æ”ļįĢ™", + "assets_trashed_from_server": "{} ä¸ĒéĄšį›Žåˇ˛æ”žå…Ĩ回æ”ļįĢ™", "assets_were_part_of_album_count": "{count, plural, one {éĄšį›Ž} other {éĄšį›Ž}}厞įģåœ¨į›¸å†Œä¸­", "authorized_devices": "åˇ˛æŽˆæƒčŽžå¤‡", "automatic_endpoint_switching_subtitle": "åœ¨å¯į”¨įš„æƒ…å†ĩ下īŧŒé€ščŋ‡æŒ‡åŽšįš„ Wi-Fi čŋ›čĄŒæœŦ地čŋžæŽĨīŧŒåšļ在å…ļ厃地斚äŊŋᔍæ›ŋäģŖčŋžæŽĨ", @@ -521,7 +525,7 @@ "backup_controller_page_background_battery_info_title": "į”ĩæą äŧ˜åŒ–", "backup_controller_page_background_charging": "äģ…å……į”ĩæ—ļ", "backup_controller_page_background_configure_error": "配įŊŽåŽå°æœåŠĄå¤ąč´Ĩ", - "backup_controller_page_background_delay": "åģļčŋŸ {} 后备äģŊ", + "backup_controller_page_background_delay": "åģļčŋŸå¤‡äģŊįš„æ–°éĄšį›Žīŧš{}", "backup_controller_page_background_description": "打åŧ€åŽå°æœåŠĄäģĨč‡Ē动备äģŊäģģäŊ•æ–°éĄšį›ŽīŧŒä¸”无需打åŧ€åē”ᔍ", "backup_controller_page_background_is_off": "后台č‡Ē动备äģŊ厞兺闭", "backup_controller_page_background_is_on": "后台č‡Ē动备äģŊ厞åŧ€å¯", @@ -529,14 +533,14 @@ "backup_controller_page_background_turn_on": "åŧ€å¯åŽå°æœåŠĄ", "backup_controller_page_background_wifi": "äģ… WiFi", "backup_controller_page_backup": "备äģŊ", - "backup_controller_page_backup_selected": "厞选䏭īŧš", + "backup_controller_page_backup_selected": "厞选䏭īŧš ", "backup_controller_page_backup_sub": "厞备äģŊįš„į…§į‰‡å’Œč§†éĸ‘", - "backup_controller_page_created": "创åģēæ—ļ间: {}", + "backup_controller_page_created": "创åģēæ—ļ间īŧš{}", "backup_controller_page_desc_backup": "打åŧ€å‰å°å¤‡äģŊīŧŒäģĨåœ¨į¨‹åēčŋčĄŒæ—ļč‡Ē动备äģŊæ–°éĄšį›Žã€‚", - "backup_controller_page_excluded": "åˇ˛æŽ’é™¤īŧš", + "backup_controller_page_excluded": "åˇ˛æŽ’é™¤īŧš ", "backup_controller_page_failed": "å¤ąč´Ĩīŧˆ{}īŧ‰", - "backup_controller_page_filename": "文äģļåį§°: {} [{}]", - "backup_controller_page_id": "ID: {}", + "backup_controller_page_filename": "文äģļåį§°īŧš{} [{}]", + "backup_controller_page_id": "IDīŧš{}", "backup_controller_page_info": "备äģŊäŋĄæ¯", "backup_controller_page_none_selected": "æœĒ选拊", "backup_controller_page_remainder": "削äŊ™", @@ -570,7 +574,7 @@ "bulk_keep_duplicates_confirmation": "æ‚¨įĄŽåŽščρäŋį•™{count, plural, one {#ä¸Ēé‡å¤éĄšį›Ž} other {#ä¸Ēé‡å¤éĄšį›Ž}}吗īŧŸčŋ™å°†æ¸…įŠēæ‰€æœ‰é‡å¤čŽ°åŊ•īŧŒäŊ†ä¸äŧšåˆ é™¤äģģäŊ•内厚。", "bulk_trash_duplicates_confirmation": "æ‚¨įĄŽåŽščĻæ‰šé‡åˆ é™¤{count, plural, one {#ä¸Ēé‡å¤éĄšį›Ž} other {#ä¸Ēé‡å¤éĄšį›Ž}}吗īŧŸčŋ™å°†äŋį•™æ¯įģ„ä¸­æœ€å¤§įš„éĄšį›Žåšļ删除所有å…ļåŽƒé‡å¤éĄšį›Žã€‚", "buy": "č´­äš° Immich", - "cache_settings_album_thumbnails": "回åē“įŧŠį•Ĩ回īŧˆ{} 饚īŧ‰", + "cache_settings_album_thumbnails": "回åē“éĄĩéĸįŧŠį•Ĩ回īŧˆ{} 饚īŧ‰", "cache_settings_clear_cache_button": "清除įŧ“å­˜", "cache_settings_clear_cache_button_title": "清除åē”ᔍįŧ“å­˜ã€‚åœ¨é‡æ–°į”Ÿæˆįŧ“存䚋前īŧŒå°†æ˜žč‘—åŊąå“åē”į”¨įš„æ€§čƒŊ。", "cache_settings_duplicated_assets_clear_button": "清除", @@ -606,7 +610,7 @@ "change_password": "äŋŽæ”šå¯†į ", "change_password_description": "čŋ™æ˜¯äŊ įš„įŦŦ一æŦĄį™ģåŊ•äēĻæˆ–有äēēčĻæą‚æ›´æ”šäŊ įš„å¯†į ã€‚č¯ˇåœ¨ä¸‹éĸ输å…Ĩæ–°å¯†į ã€‚", "change_password_form_confirm_password": "įĄŽčŽ¤å¯†į ", - "change_password_form_description": "{name} 您åĨŊīŧŒ\n\nčŋ™æ˜¯æ‚¨éĻ–æŦĄį™ģåŊ•įŗģįģŸīŧŒæˆ–čĸĢįŽĄį†å‘˜čĻæą‚æ›´æ”šå¯†į ã€‚\nč¯ˇåœ¨ä¸‹æ–ščž“å…Ĩæ–°å¯†į ã€‚", + "change_password_form_description": "{name} 您åĨŊīŧŒ\n\nčŋ™æ˜¯æ‚¨éĻ–æŦĄį™ģåŊ•įŗģįģŸīŧŒæˆ–čĸĢįŽĄį†å‘˜čĻæą‚æ›´æ”šå¯†į ã€‚č¯ˇåœ¨ä¸‹æ–ščž“å…Ĩæ–°å¯†į ã€‚", "change_password_form_new_password": "æ–°å¯†į ", "change_password_form_password_mismatch": "å¯†į ä¸åŒšé…", "change_password_form_reenter_new_password": "再æŦĄčž“å…Ĩæ–°å¯†į ", @@ -654,13 +658,13 @@ "contain": "包åĢ", "context": "äģĨ文搜回", "continue": "įģ§įģ­", - "control_bottom_app_bar_album_info_shared": "{} 饚 ¡ åˇ˛å…ąäēĢ", + "control_bottom_app_bar_album_info_shared": "åˇ˛å…ąäēĢ {} 饚", "control_bottom_app_bar_create_new_album": "新åģēį›¸å†Œ", "control_bottom_app_bar_delete_from_immich": "äģŽImmichæœåŠĄå™¨ä¸­åˆ é™¤", "control_bottom_app_bar_delete_from_local": "äģŽį§ģåŠ¨čŽžå¤‡ä¸­åˆ é™¤", "control_bottom_app_bar_edit_location": "įŧ–čž‘äŊįŊŽäŋĄæ¯", "control_bottom_app_bar_edit_time": "įŧ–čž‘æ—Ĩ期和æ—ļ间", - "control_bottom_app_bar_share_link": "Share Link", + "control_bottom_app_bar_share_link": "分äēĢ链æŽĨ", "control_bottom_app_bar_share_to": "发送įģ™", "control_bottom_app_bar_trash_from_immich": "攞å…Ĩ回æ”ļįĢ™", "copied_image_to_clipboard": "åˇ˛å¤åˆļå›žį‰‡č‡ŗå‰Ē切æŋ。", @@ -953,10 +957,10 @@ "exif_bottom_sheet_location": "äŊįŊŽ", "exif_bottom_sheet_people": "äēēį‰Š", "exif_bottom_sheet_person_add_person": "æˇģ加姓名", - "exif_bottom_sheet_person_age": "åš´éž„ {}", - "exif_bottom_sheet_person_age_months": "Age {} months", - "exif_bottom_sheet_person_age_year_months": "Age 1 year, {} months", - "exif_bottom_sheet_person_age_years": "Age {}", + "exif_bottom_sheet_person_age": "{} 垁", + "exif_bottom_sheet_person_age_months": "{} 月鞄", + "exif_bottom_sheet_person_age_year_months": "1垁 {} ä¸Ē月", + "exif_bottom_sheet_person_age_years": "{} 垁", "exit_slideshow": "退å‡ēåšģį¯į‰‡æ”žæ˜ ", "expand_all": "å…¨éƒ¨åą•åŧ€", "experimental_settings_new_asset_list_subtitle": "æ­Ŗåœ¨å¤„į†", @@ -992,6 +996,7 @@ "filetype": "文äģļįąģ型", "filter": "᭛选", "filter_people": "čŋ‡æģ¤äēēį‰Š", + "filter_places": "į­›é€‰åœ°į‚š", "find_them_fast": "æŒ‰åį§°åŋĢ速搜į´ĸ", "fix_incorrect_match": "äŋŽå¤ä¸æ­ŖįĄŽįš„匚配", "folder": "文äģļ多", @@ -1029,9 +1034,9 @@ "hide_password": "éšč—å¯†į ", "hide_person": "隐藏äēēį‰Š", "hide_unnamed_people": "隐藏æœĒå‘Ŋåįš„äēēį‰Š", - "home_page_add_to_album_conflicts": "åˇ˛å‘į›¸å†Œ {album} 中æˇģ加 {added} éĄšã€‚\nå…ļ中 {failed} éĄšåœ¨į›¸å†Œä¸­åˇ˛å­˜åœ¨ã€‚", + "home_page_add_to_album_conflicts": "åˇ˛å‘į›¸å†Œ {album} 中æˇģ加 {added} éĄšã€‚å…ļ中 {failed} éĄšåœ¨į›¸å†Œä¸­åˇ˛å­˜åœ¨ã€‚", "home_page_add_to_album_err_local": "暂不čƒŊ将æœŦåœ°éĄšį›ŽæˇģåŠ åˆ°į›¸å†Œä¸­īŧŒčˇŗčŋ‡", - "home_page_add_to_album_success": "åˇ˛å‘į›¸å†Œ {album} 中æˇģ加 {added} éĄšã€‚", + "home_page_add_to_album_success": "åˇ˛å‘į›¸å†Œ {album} 中æˇģ加 {added} éĄšã€‚", "home_page_album_err_partner": "æš‚æ— æŗ•å°†åŒäŧ´įš„éĄšį›ŽæˇģåŠ åˆ°į›¸å†ŒīŧŒčˇŗčŋ‡", "home_page_archive_err_local": "æš‚æ— æŗ•åŊ’æĄŖæœŦåœ°éĄšį›ŽīŧŒčˇŗčŋ‡", "home_page_archive_err_partner": "æ— æŗ•å­˜æĄŖåŒäŧ´įš„éĄšį›ŽīŧŒčˇŗčŋ‡", @@ -1151,7 +1156,7 @@ "login_form_server_empty": "输å…ĨæœåŠĄå™¨åœ°å€", "login_form_server_error": "æ— æŗ•čŋžæŽĨåˆ°æœåŠĄå™¨ã€‚", "login_has_been_disabled": "į™ģåŊ•厞įĻį”¨ã€‚", - "login_password_changed_error": "æ›´æ–°å¯†į æ—ļå‡ē错\n", + "login_password_changed_error": "æ›´æ–°å¯†į æ—ļå‡ē错", "login_password_changed_success": "å¯†į æ›´æ–°æˆåŠŸ", "logout_all_device_confirmation": "įĄŽåŽščρäģŽæ‰€æœ‰čŽžå¤‡æŗ¨é”€īŧŸ", "logout_this_device_confirmation": "įĄŽåŽščρäģŽæœŦčŽžå¤‡æŗ¨é”€īŧŸ", @@ -1170,8 +1175,8 @@ "manage_your_devices": "įŽĄį†åˇ˛į™ģåŊ•čŽžå¤‡", "manage_your_oauth_connection": "įŽĄį†äŊ įš„ OAuth įģ‘åޚ", "map": "地回", - "map_assets_in_bound": "{}åŧ į…§į‰‡", - "map_assets_in_bounds": "{}åŧ į…§į‰‡", + "map_assets_in_bound": "{} åŧ į…§į‰‡", + "map_assets_in_bounds": "{} åŧ į…§į‰‡", "map_cannot_get_user_location": "æ— æŗ•čŽˇå–į”¨æˆˇäŊįŊŽ", "map_location_dialog_yes": "是", "map_location_picker_page_use_location": "äŊŋį”¨æ­¤äŊįŊŽ", @@ -1185,9 +1190,9 @@ "map_settings": "åœ°å›žčŽžįŊŽ", "map_settings_dark_mode": "æˇąč‰˛æ¨Ąåŧ", "map_settings_date_range_option_day": "čŋ‡åŽģ24小æ—ļ", - "map_settings_date_range_option_days": "{}夊前", + "map_settings_date_range_option_days": "{} 夊前", "map_settings_date_range_option_year": "1嚴前", - "map_settings_date_range_option_years": "{}嚴前", + "map_settings_date_range_option_years": "{} 嚴前", "map_settings_dialog_title": "åœ°å›žčŽžįŊŽ", "map_settings_include_show_archived": "包æ‹Ŧ厞åŊ’æĄŖéĄšį›Ž", "map_settings_include_show_partners": "包åĢäŧ™äŧ´", @@ -1203,7 +1208,7 @@ "memories_start_over": "å†įœ‹ä¸€æŦĄ", "memories_swipe_to_close": "ä¸Šåˆ’å…ŗé—­", "memories_year_ago": "1嚴前", - "memories_years_ago": "{}嚴前", + "memories_years_ago": "{} 嚴前", "memory": "回åŋ†", "memory_lane_title": "莰åŋ†įēŋ{title}", "menu": "čœå•", @@ -1282,6 +1287,7 @@ "onboarding_welcome_user": "æŦĸčŋŽäŊ īŧŒ{user}", "online": "在įēŋ", "only_favorites": "äģ…æ˜žį¤ē厞æ”ļ藏", + "open": "打åŧ€", "open_in_map_view": "åœ¨åœ°å›žč§†å›žä¸­æ‰“åŧ€", "open_in_openstreetmap": "在 OpenStreetMap 中打åŧ€", "open_the_search_filters": "打åŧ€æœį´ĸčŋ‡æģ¤å™¨", @@ -1540,7 +1546,7 @@ "search_result_page_new_search_hint": "搜į´ĸæ–°įš„", "search_settings": "搜į´ĸ莞įŊŽ", "search_state": "æŒ‰įœäģŊæŸĨ扞...", - "search_suggestion_list_smart_search_hint_1": "éģ˜čŽ¤æƒ…å†ĩ䏋吝ᔍæ™ēčƒŊ搜į´ĸīŧŒčĻæœį´ĸ元数捎īŧŒč¯ˇäŊŋį”¨į›¸å…ŗč¯­æŗ•", + "search_suggestion_list_smart_search_hint_1": "éģ˜čŽ¤æƒ…å†ĩ䏋吝ᔍæ™ēčƒŊ搜į´ĸīŧŒčĻæœį´ĸ元数捎īŧŒč¯ˇäŊŋį”¨į›¸å…ŗč¯­æŗ• ", "search_suggestion_list_smart_search_hint_2": "m:æ‚¨įš„æœį´ĸå…ŗé”Žč¯", "search_tags": "æŒ‰æ ‡į­žæŸĨ扞â€Ļ", "search_timezone": "按æ—ļåŒēæŸĨ扞...", @@ -1630,25 +1636,25 @@ "shared_link_create_error": "创åģēå…ąäēĢ链æŽĨå‡ē错", "shared_link_edit_description_hint": "įŧ–čž‘å…ąäēĢæčŋ°", "shared_link_edit_expire_after_option_day": "1夊", - "shared_link_edit_expire_after_option_days": "{}夊", + "shared_link_edit_expire_after_option_days": "{} 夊", "shared_link_edit_expire_after_option_hour": "1小æ—ļ", - "shared_link_edit_expire_after_option_hours": "{}小æ—ļ", + "shared_link_edit_expire_after_option_hours": "{} 小æ—ļ", "shared_link_edit_expire_after_option_minute": "1分钟", - "shared_link_edit_expire_after_option_minutes": "{}分钟", + "shared_link_edit_expire_after_option_minutes": "{} 分钟", "shared_link_edit_expire_after_option_months": "{} ä¸Ē月", "shared_link_edit_expire_after_option_year": "{} åš´", "shared_link_edit_password_hint": "输å…Ĩå…ąäēĢ坆᠁", "shared_link_edit_submit_button": "更新铞æŽĨ", "shared_link_error_server_url_fetch": "æ— æŗ•čŽˇå–æœåŠĄå™¨åœ°å€", - "shared_link_expires_day": "{}夊后čŋ‡æœŸ", - "shared_link_expires_days": "{}夊后čŋ‡æœŸ", - "shared_link_expires_hour": "{}小æ—ļ后čŋ‡æœŸ", - "shared_link_expires_hours": "{}小æ—ļ后čŋ‡æœŸ", - "shared_link_expires_minute": "{}分钟后čŋ‡æœŸ", - "shared_link_expires_minutes": "将在{}分钟后čŋ‡æœŸ", + "shared_link_expires_day": "{} 夊后čŋ‡æœŸ", + "shared_link_expires_days": "{} 夊后čŋ‡æœŸ", + "shared_link_expires_hour": "{} 小æ—ļ后čŋ‡æœŸ", + "shared_link_expires_hours": "{} 小æ—ļ后čŋ‡æœŸ", + "shared_link_expires_minute": "{} 分钟后čŋ‡æœŸ", + "shared_link_expires_minutes": "{} 分钟后čŋ‡æœŸ", "shared_link_expires_never": "čŋ‡æœŸæ—ļ间 ∞", - "shared_link_expires_second": "{}į§’åŽčŋ‡æœŸ", - "shared_link_expires_seconds": "将在{}į§’åŽčŋ‡æœŸ", + "shared_link_expires_second": "{} į§’åŽčŋ‡æœŸ", + "shared_link_expires_seconds": "{} į§’åŽčŋ‡æœŸ", "shared_link_individual_shared": "ä¸Ēäēēå…ąäēĢ", "shared_link_info_chip_metadata": "EXIF", "shared_link_manage_links": "įŽĄį†å…ąäēĢ链æŽĨ", @@ -1784,7 +1790,7 @@ "trash_no_results_message": "åˆ é™¤įš„į…§į‰‡å’Œč§†éĸ‘å°†åœ¨æ­¤å¤„åą•į¤ē。", "trash_page_delete_all": "删除全部", "trash_page_empty_trash_dialog_content": "是åĻ清įŠē回æ”ļįĢ™īŧŸčŋ™äē›éĄšį›Žå°†čĸĢäģŽImmich中永䚅删除", - "trash_page_info": "回æ”ļįĢ™ä¸­éĄšį›Žå°†åœ¨{}夊后永䚅删除", + "trash_page_info": "回æ”ļįĢ™ä¸­éĄšį›Žå°†åœ¨ {} 夊后永䚅删除", "trash_page_no_assets": "æš‚æ— åˇ˛åˆ é™¤éĄšį›Ž", "trash_page_restore_all": "æĸ复全部", "trash_page_select_assets_btn": "é€‰æ‹ŠéĄšį›Ž", @@ -1826,7 +1832,7 @@ "upload_status_errors": "错蝝", "upload_status_uploaded": "厞䏊äŧ ", "upload_success": "上äŧ æˆåŠŸīŧŒåˆˇæ–°éĄĩéĸæŸĨįœ‹æ–°ä¸Šäŧ įš„éĄšį›Žã€‚", - "upload_to_immich": "上äŧ č‡ŗImmich ({})", + "upload_to_immich": "上äŧ č‡ŗImmichīŧˆ{}īŧ‰", "uploading": "æ­Ŗåœ¨ä¸Šäŧ ", "url": "URL", "usage": "į”¨é‡", @@ -1852,8 +1858,8 @@ "version_announcement_message": "äŊ åĨŊīŧåˇ˛įģæŖ€æĩ‹åˆ°Immichæœ‰æ–°į‰ˆæœŦã€‚č¯ˇæŠŊįŠē阅č¯ģä¸€ä¸‹å‘čĄŒč¯´æ˜ŽīŧŒäģĨįĄŽäŋæ‚¨įš„配įŊŽæ–‡äģ￘¯æœ€æ–°įš„īŧŒéŋ免存在配įŊŽé”™č¯¯īŧŒį‰šåˆĢ是åŊ“äŊ æ˜¯äŊŋᔍWatchTower或å…ļ厃įąģäŧŧįš„č‡Ē动升įē§åˇĨå…ˇæ—ļ。", "version_announcement_overlay_release_notes": "å‘čĄŒč¯´æ˜Ž", "version_announcement_overlay_text_1": "åˇå¤–åˇå¤–īŧŒæœ‰æ–°į‰ˆæœŦįš„", - "version_announcement_overlay_text_2": "č¯ˇčŠąį‚šæ—ļ间čŽŋ问", - "version_announcement_overlay_text_3": "åšļæŖ€æŸĨæ‚¨įš„ docker-compose 和 .env 是åĻä¸ēæœ€æ–°ä¸”æ­ŖįĄŽįš„é…įŊŽīŧŒį‰šåˆĢ是您在äŊŋᔍ WatchTower æˆ–č€…å…ļäģ–č‡ĒåŠ¨æ›´æ–°įš„į¨‹åēæ—ļīŧŒæ‚¨éœ€čĻæ›´åŠ įģ†č‡´įš„æŖ€æŸĨ。", + "version_announcement_overlay_text_2": "č¯ˇčŠąį‚šæ—ļ间čŽŋ问 ", + "version_announcement_overlay_text_3": " åšļæŖ€æŸĨæ‚¨įš„ docker-compose 和 .env 是åĻä¸ēæœ€æ–°ä¸”æ­ŖįĄŽįš„é…įŊŽīŧŒį‰šåˆĢ是您在äŊŋᔍ WatchTower æˆ–č€…å…ļäģ–č‡ĒåŠ¨æ›´æ–°įš„į¨‹åēæ—ļīŧŒæ‚¨éœ€čĻæ›´åŠ įģ†č‡´įš„æŖ€æŸĨ。", "version_announcement_overlay_title": "æœåŠĄįĢ¯æœ‰æ–°į‰ˆæœŦå•Ļ 🎉", "version_history": "į‰ˆæœŦæ›´æ–°åŽ†å˛čŽ°åŊ•", "version_history_item": "在 {date} åŽ‰čŖ… {version} į‰ˆæœŦ", diff --git a/machine-learning/Dockerfile b/machine-learning/Dockerfile index 25f3c44d9e..270e743291 100644 --- a/machine-learning/Dockerfile +++ b/machine-learning/Dockerfile @@ -1,6 +1,6 @@ ARG DEVICE=cpu -FROM python:3.11-bookworm@sha256:0a9d314ae6e976351bd37b702bf6b0a89bb58e6304e5df35b960059b12531419 AS builder-cpu +FROM python:3.11-bookworm@sha256:ab60e444e04215a62671149f24c59cc2893b49cb5dad26f9d139077a86be760e AS builder-cpu FROM builder-cpu AS builder-openvino @@ -54,7 +54,7 @@ ENV PYTHONDONTWRITEBYTECODE=1 \ RUN apt-get update && apt-get install -y --no-install-recommends g++ -COPY --from=ghcr.io/astral-sh/uv:latest@sha256:0b6dc79013b689f3bc0cbf12807cb1c901beaafe80f2ee10a1d76aa3842afb92 /uv /uvx /bin/ +COPY --from=ghcr.io/astral-sh/uv:latest@sha256:4a6c9444b126bd325fba904bff796bf91fb777bf6148d60109c4cb1de2ffc497 /uv /uvx /bin/ RUN --mount=type=cache,target=/root/.cache/uv \ --mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ @@ -63,11 +63,11 @@ RUN if [ "$DEVICE" = "rocm" ]; then \ uv pip install /opt/onnxruntime_rocm-*.whl; \ fi -FROM python:3.11-slim-bookworm@sha256:49d73c49616929b0a4f37c50fee0056eb4b0f15de624591e8d9bf84b4dfdd3ce AS prod-cpu +FROM python:3.11-slim-bookworm@sha256:97ef3198ec8c78690587167bb6a4905d00ffe053900687bdae93ad667e507cbb AS prod-cpu ENV LD_PRELOAD=/usr/lib/libmimalloc.so.2 -FROM python:3.11-slim-bookworm@sha256:49d73c49616929b0a4f37c50fee0056eb4b0f15de624591e8d9bf84b4dfdd3ce AS prod-openvino +FROM python:3.11-slim-bookworm@sha256:97ef3198ec8c78690587167bb6a4905d00ffe053900687bdae93ad667e507cbb AS prod-openvino RUN apt-get update && \ apt-get install --no-install-recommends -yqq ocl-icd-libopencl1 wget && \ diff --git a/machine-learning/uv.lock b/machine-learning/uv.lock index 65011f9cab..1930e80661 100644 --- a/machine-learning/uv.lock +++ b/machine-learning/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 1 +revision = 2 requires-python = ">=3.10, <4.0" resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'darwin'", @@ -23,9 +23,9 @@ resolution-markers = [ name = "aiocache" version = "0.12.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7a/64/b945b8025a9d1e6e2138845f4022165d3b337f55f50984fbc6a4c0a1e355/aiocache-0.12.3.tar.gz", hash = "sha256:f528b27bf4d436b497a1d0d1a8f59a542c153ab1e37c3621713cb376d44c4713", size = 132196 } +sdist = { url = "https://files.pythonhosted.org/packages/7a/64/b945b8025a9d1e6e2138845f4022165d3b337f55f50984fbc6a4c0a1e355/aiocache-0.12.3.tar.gz", hash = "sha256:f528b27bf4d436b497a1d0d1a8f59a542c153ab1e37c3621713cb376d44c4713", size = 132196, upload_time = "2024-09-25T13:20:23.823Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/37/d7/15d67e05b235d1ed8c3ce61688fe4d84130e72af1657acadfaac3479f4cf/aiocache-0.12.3-py2.py3-none-any.whl", hash = "sha256:889086fc24710f431937b87ad3720a289f7fc31c4fd8b68e9f918b9bacd8270d", size = 28199 }, + { url = "https://files.pythonhosted.org/packages/37/d7/15d67e05b235d1ed8c3ce61688fe4d84130e72af1657acadfaac3479f4cf/aiocache-0.12.3-py2.py3-none-any.whl", hash = "sha256:889086fc24710f431937b87ad3720a289f7fc31c4fd8b68e9f918b9bacd8270d", size = 28199, upload_time = "2024-09-25T13:20:22.688Z" }, ] [[package]] @@ -40,18 +40,18 @@ dependencies = [ { name = "scikit-image" }, { name = "scipy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/14/d6/8dd5b690d28a332a0b2c3179a345808b5d4c7ad5ddc079b7e116098dff35/albumentations-1.3.1.tar.gz", hash = "sha256:a6a38388fe546c568071e8c82f414498e86c9ed03c08b58e7a88b31cf7a244c6", size = 176371 } +sdist = { url = "https://files.pythonhosted.org/packages/14/d6/8dd5b690d28a332a0b2c3179a345808b5d4c7ad5ddc079b7e116098dff35/albumentations-1.3.1.tar.gz", hash = "sha256:a6a38388fe546c568071e8c82f414498e86c9ed03c08b58e7a88b31cf7a244c6", size = 176371, upload_time = "2023-06-10T07:44:32.36Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9b/f6/c486cedb4f75147232f32ec4c97026714cfef7c7e247a1f0427bc5489f66/albumentations-1.3.1-py3-none-any.whl", hash = "sha256:6b641d13733181d9ecdc29550e6ad580d1bfa9d25e2213a66940062f25e291bd", size = 125706 }, + { url = "https://files.pythonhosted.org/packages/9b/f6/c486cedb4f75147232f32ec4c97026714cfef7c7e247a1f0427bc5489f66/albumentations-1.3.1-py3-none-any.whl", hash = "sha256:6b641d13733181d9ecdc29550e6ad580d1bfa9d25e2213a66940062f25e291bd", size = 125706, upload_time = "2023-06-10T07:44:30.373Z" }, ] [[package]] name = "annotated-types" version = "0.7.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload_time = "2024-05-20T21:33:25.928Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 }, + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload_time = "2024-05-20T21:33:24.1Z" }, ] [[package]] @@ -64,9 +64,18 @@ dependencies = [ { name = "sniffio" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2d/b8/7333d87d5f03247215d86a86362fd3e324111788c6cdd8d2e6196a6ba833/anyio-4.2.0.tar.gz", hash = "sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f", size = 158770 } +sdist = { url = "https://files.pythonhosted.org/packages/2d/b8/7333d87d5f03247215d86a86362fd3e324111788c6cdd8d2e6196a6ba833/anyio-4.2.0.tar.gz", hash = "sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f", size = 158770, upload_time = "2023-12-16T17:06:57.709Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bf/cd/d6d9bb1dadf73e7af02d18225cbd2c93f8552e13130484f1c8dcfece292b/anyio-4.2.0-py3-none-any.whl", hash = "sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee", size = 85481 }, + { url = "https://files.pythonhosted.org/packages/bf/cd/d6d9bb1dadf73e7af02d18225cbd2c93f8552e13130484f1c8dcfece292b/anyio-4.2.0-py3-none-any.whl", hash = "sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee", size = 85481, upload_time = "2023-12-16T17:06:55.989Z" }, +] + +[[package]] +name = "bidict" +version = "0.23.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9a/6e/026678aa5a830e07cd9498a05d3e7e650a4f56a42f267a53d22bcda1bdc9/bidict-0.23.1.tar.gz", hash = "sha256:03069d763bc387bbd20e7d49914e75fc4132a41937fa3405417e1a5a2d006d71", size = 29093, upload_time = "2024-02-18T19:09:05.748Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl", hash = "sha256:5dae8d4d79b552a71cbabc7deb25dfe8ce710b17ff41711e13010ead2abfc3e5", size = 32764, upload_time = "2024-02-18T19:09:04.156Z" }, ] [[package]] @@ -82,113 +91,113 @@ dependencies = [ { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/94/49/26a7b0f3f35da4b5a65f081943b7bcd22d7002f5f0fb8098ec1ff21cb6ef/black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666", size = 649449 } +sdist = { url = "https://files.pythonhosted.org/packages/94/49/26a7b0f3f35da4b5a65f081943b7bcd22d7002f5f0fb8098ec1ff21cb6ef/black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666", size = 649449, upload_time = "2025-01-29T04:15:40.373Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/3b/4ba3f93ac8d90410423fdd31d7541ada9bcee1df32fb90d26de41ed40e1d/black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32", size = 1629419 }, - { url = "https://files.pythonhosted.org/packages/b4/02/0bde0485146a8a5e694daed47561785e8b77a0466ccc1f3e485d5ef2925e/black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da", size = 1461080 }, - { url = "https://files.pythonhosted.org/packages/52/0e/abdf75183c830eaca7589144ff96d49bce73d7ec6ad12ef62185cc0f79a2/black-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7", size = 1766886 }, - { url = "https://files.pythonhosted.org/packages/dc/a6/97d8bb65b1d8a41f8a6736222ba0a334db7b7b77b8023ab4568288f23973/black-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9", size = 1419404 }, - { url = "https://files.pythonhosted.org/packages/7e/4f/87f596aca05c3ce5b94b8663dbfe242a12843caaa82dd3f85f1ffdc3f177/black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0", size = 1614372 }, - { url = "https://files.pythonhosted.org/packages/e7/d0/2c34c36190b741c59c901e56ab7f6e54dad8df05a6272a9747ecef7c6036/black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299", size = 1442865 }, - { url = "https://files.pythonhosted.org/packages/21/d4/7518c72262468430ead45cf22bd86c883a6448b9eb43672765d69a8f1248/black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096", size = 1749699 }, - { url = "https://files.pythonhosted.org/packages/58/db/4f5beb989b547f79096e035c4981ceb36ac2b552d0ac5f2620e941501c99/black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2", size = 1428028 }, - { url = "https://files.pythonhosted.org/packages/83/71/3fe4741df7adf015ad8dfa082dd36c94ca86bb21f25608eb247b4afb15b2/black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b", size = 1650988 }, - { url = "https://files.pythonhosted.org/packages/13/f3/89aac8a83d73937ccd39bbe8fc6ac8860c11cfa0af5b1c96d081facac844/black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc", size = 1453985 }, - { url = "https://files.pythonhosted.org/packages/6f/22/b99efca33f1f3a1d2552c714b1e1b5ae92efac6c43e790ad539a163d1754/black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f", size = 1783816 }, - { url = "https://files.pythonhosted.org/packages/18/7e/a27c3ad3822b6f2e0e00d63d58ff6299a99a5b3aee69fa77cd4b0076b261/black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba", size = 1440860 }, - { url = "https://files.pythonhosted.org/packages/98/87/0edf98916640efa5d0696e1abb0a8357b52e69e82322628f25bf14d263d1/black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f", size = 1650673 }, - { url = "https://files.pythonhosted.org/packages/52/e5/f7bf17207cf87fa6e9b676576749c6b6ed0d70f179a3d812c997870291c3/black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3", size = 1453190 }, - { url = "https://files.pythonhosted.org/packages/e3/ee/adda3d46d4a9120772fae6de454c8495603c37c4c3b9c60f25b1ab6401fe/black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171", size = 1782926 }, - { url = "https://files.pythonhosted.org/packages/cc/64/94eb5f45dcb997d2082f097a3944cfc7fe87e071907f677e80788a2d7b7a/black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18", size = 1442613 }, - { url = "https://files.pythonhosted.org/packages/09/71/54e999902aed72baf26bca0d50781b01838251a462612966e9fc4891eadd/black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717", size = 207646 }, + { url = "https://files.pythonhosted.org/packages/4d/3b/4ba3f93ac8d90410423fdd31d7541ada9bcee1df32fb90d26de41ed40e1d/black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32", size = 1629419, upload_time = "2025-01-29T05:37:06.642Z" }, + { url = "https://files.pythonhosted.org/packages/b4/02/0bde0485146a8a5e694daed47561785e8b77a0466ccc1f3e485d5ef2925e/black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da", size = 1461080, upload_time = "2025-01-29T05:37:09.321Z" }, + { url = "https://files.pythonhosted.org/packages/52/0e/abdf75183c830eaca7589144ff96d49bce73d7ec6ad12ef62185cc0f79a2/black-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7", size = 1766886, upload_time = "2025-01-29T04:18:24.432Z" }, + { url = "https://files.pythonhosted.org/packages/dc/a6/97d8bb65b1d8a41f8a6736222ba0a334db7b7b77b8023ab4568288f23973/black-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9", size = 1419404, upload_time = "2025-01-29T04:19:04.296Z" }, + { url = "https://files.pythonhosted.org/packages/7e/4f/87f596aca05c3ce5b94b8663dbfe242a12843caaa82dd3f85f1ffdc3f177/black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0", size = 1614372, upload_time = "2025-01-29T05:37:11.71Z" }, + { url = "https://files.pythonhosted.org/packages/e7/d0/2c34c36190b741c59c901e56ab7f6e54dad8df05a6272a9747ecef7c6036/black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299", size = 1442865, upload_time = "2025-01-29T05:37:14.309Z" }, + { url = "https://files.pythonhosted.org/packages/21/d4/7518c72262468430ead45cf22bd86c883a6448b9eb43672765d69a8f1248/black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096", size = 1749699, upload_time = "2025-01-29T04:18:17.688Z" }, + { url = "https://files.pythonhosted.org/packages/58/db/4f5beb989b547f79096e035c4981ceb36ac2b552d0ac5f2620e941501c99/black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2", size = 1428028, upload_time = "2025-01-29T04:18:51.711Z" }, + { url = "https://files.pythonhosted.org/packages/83/71/3fe4741df7adf015ad8dfa082dd36c94ca86bb21f25608eb247b4afb15b2/black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b", size = 1650988, upload_time = "2025-01-29T05:37:16.707Z" }, + { url = "https://files.pythonhosted.org/packages/13/f3/89aac8a83d73937ccd39bbe8fc6ac8860c11cfa0af5b1c96d081facac844/black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc", size = 1453985, upload_time = "2025-01-29T05:37:18.273Z" }, + { url = "https://files.pythonhosted.org/packages/6f/22/b99efca33f1f3a1d2552c714b1e1b5ae92efac6c43e790ad539a163d1754/black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f", size = 1783816, upload_time = "2025-01-29T04:18:33.823Z" }, + { url = "https://files.pythonhosted.org/packages/18/7e/a27c3ad3822b6f2e0e00d63d58ff6299a99a5b3aee69fa77cd4b0076b261/black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba", size = 1440860, upload_time = "2025-01-29T04:19:12.944Z" }, + { url = "https://files.pythonhosted.org/packages/98/87/0edf98916640efa5d0696e1abb0a8357b52e69e82322628f25bf14d263d1/black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f", size = 1650673, upload_time = "2025-01-29T05:37:20.574Z" }, + { url = "https://files.pythonhosted.org/packages/52/e5/f7bf17207cf87fa6e9b676576749c6b6ed0d70f179a3d812c997870291c3/black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3", size = 1453190, upload_time = "2025-01-29T05:37:22.106Z" }, + { url = "https://files.pythonhosted.org/packages/e3/ee/adda3d46d4a9120772fae6de454c8495603c37c4c3b9c60f25b1ab6401fe/black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171", size = 1782926, upload_time = "2025-01-29T04:18:58.564Z" }, + { url = "https://files.pythonhosted.org/packages/cc/64/94eb5f45dcb997d2082f097a3944cfc7fe87e071907f677e80788a2d7b7a/black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18", size = 1442613, upload_time = "2025-01-29T04:19:27.63Z" }, + { url = "https://files.pythonhosted.org/packages/09/71/54e999902aed72baf26bca0d50781b01838251a462612966e9fc4891eadd/black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717", size = 207646, upload_time = "2025-01-29T04:15:38.082Z" }, ] [[package]] name = "blinker" version = "1.7.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a1/13/6df5fc090ff4e5d246baf1f45fe9e5623aa8565757dfa5bd243f6a545f9e/blinker-1.7.0.tar.gz", hash = "sha256:e6820ff6fa4e4d1d8e2747c2283749c3f547e4fee112b98555cdcdae32996182", size = 28134 } +sdist = { url = "https://files.pythonhosted.org/packages/a1/13/6df5fc090ff4e5d246baf1f45fe9e5623aa8565757dfa5bd243f6a545f9e/blinker-1.7.0.tar.gz", hash = "sha256:e6820ff6fa4e4d1d8e2747c2283749c3f547e4fee112b98555cdcdae32996182", size = 28134, upload_time = "2023-11-01T22:06:01.588Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fa/2a/7f3714cbc6356a0efec525ce7a0613d581072ed6eb53eb7b9754f33db807/blinker-1.7.0-py3-none-any.whl", hash = "sha256:c3f865d4d54db7abc53758a01601cf343fe55b84c1de4e3fa910e420b438d5b9", size = 13068 }, + { url = "https://files.pythonhosted.org/packages/fa/2a/7f3714cbc6356a0efec525ce7a0613d581072ed6eb53eb7b9754f33db807/blinker-1.7.0-py3-none-any.whl", hash = "sha256:c3f865d4d54db7abc53758a01601cf343fe55b84c1de4e3fa910e420b438d5b9", size = 13068, upload_time = "2023-11-01T22:06:00.162Z" }, ] [[package]] name = "brotli" version = "1.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2f/c2/f9e977608bdf958650638c3f1e28f85a1b075f075ebbe77db8555463787b/Brotli-1.1.0.tar.gz", hash = "sha256:81de08ac11bcb85841e440c13611c00b67d3bf82698314928d0b676362546724", size = 7372270 } +sdist = { url = "https://files.pythonhosted.org/packages/2f/c2/f9e977608bdf958650638c3f1e28f85a1b075f075ebbe77db8555463787b/Brotli-1.1.0.tar.gz", hash = "sha256:81de08ac11bcb85841e440c13611c00b67d3bf82698314928d0b676362546724", size = 7372270, upload_time = "2023-09-07T14:05:41.643Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6d/3a/dbf4fb970c1019a57b5e492e1e0eae745d32e59ba4d6161ab5422b08eefe/Brotli-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e1140c64812cb9b06c922e77f1c26a75ec5e3f0fb2bf92cc8c58720dec276752", size = 873045 }, - { url = "https://files.pythonhosted.org/packages/dd/11/afc14026ea7f44bd6eb9316d800d439d092c8d508752055ce8d03086079a/Brotli-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c8fd5270e906eef71d4a8d19b7c6a43760c6abcfcc10c9101d14eb2357418de9", size = 446218 }, - { url = "https://files.pythonhosted.org/packages/36/83/7545a6e7729db43cb36c4287ae388d6885c85a86dd251768a47015dfde32/Brotli-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ae56aca0402a0f9a3431cddda62ad71666ca9d4dc3a10a142b9dce2e3c0cda3", size = 2903872 }, - { url = "https://files.pythonhosted.org/packages/32/23/35331c4d9391fcc0f29fd9bec2c76e4b4eeab769afbc4b11dd2e1098fb13/Brotli-1.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:43ce1b9935bfa1ede40028054d7f48b5469cd02733a365eec8a329ffd342915d", size = 2941254 }, - { url = "https://files.pythonhosted.org/packages/3b/24/1671acb450c902edb64bd765d73603797c6c7280a9ada85a195f6b78c6e5/Brotli-1.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7c4855522edb2e6ae7fdb58e07c3ba9111e7621a8956f481c68d5d979c93032e", size = 2857293 }, - { url = "https://files.pythonhosted.org/packages/d5/00/40f760cc27007912b327fe15bf6bfd8eaecbe451687f72a8abc587d503b3/Brotli-1.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:38025d9f30cf4634f8309c6874ef871b841eb3c347e90b0851f63d1ded5212da", size = 3002385 }, - { url = "https://files.pythonhosted.org/packages/b8/cb/8aaa83f7a4caa131757668c0fb0c4b6384b09ffa77f2fba9570d87ab587d/Brotli-1.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e6a904cb26bfefc2f0a6f240bdf5233be78cd2488900a2f846f3c3ac8489ab80", size = 2911104 }, - { url = "https://files.pythonhosted.org/packages/bc/c4/65456561d89d3c49f46b7fbeb8fe6e449f13bdc8ea7791832c5d476b2faf/Brotli-1.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a37b8f0391212d29b3a91a799c8e4a2855e0576911cdfb2515487e30e322253d", size = 2809981 }, - { url = "https://files.pythonhosted.org/packages/05/1b/cf49528437bae28abce5f6e059f0d0be6fecdcc1d3e33e7c54b3ca498425/Brotli-1.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e84799f09591700a4154154cab9787452925578841a94321d5ee8fb9a9a328f0", size = 2935297 }, - { url = "https://files.pythonhosted.org/packages/81/ff/190d4af610680bf0c5a09eb5d1eac6e99c7c8e216440f9c7cfd42b7adab5/Brotli-1.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f66b5337fa213f1da0d9000bc8dc0cb5b896b726eefd9c6046f699b169c41b9e", size = 2930735 }, - { url = "https://files.pythonhosted.org/packages/80/7d/f1abbc0c98f6e09abd3cad63ec34af17abc4c44f308a7a539010f79aae7a/Brotli-1.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5dab0844f2cf82be357a0eb11a9087f70c5430b2c241493fc122bb6f2bb0917c", size = 2933107 }, - { url = "https://files.pythonhosted.org/packages/34/ce/5a5020ba48f2b5a4ad1c0522d095ad5847a0be508e7d7569c8630ce25062/Brotli-1.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e4fe605b917c70283db7dfe5ada75e04561479075761a0b3866c081d035b01c1", size = 2845400 }, - { url = "https://files.pythonhosted.org/packages/44/89/fa2c4355ab1eecf3994e5a0a7f5492c6ff81dfcb5f9ba7859bd534bb5c1a/Brotli-1.1.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:1e9a65b5736232e7a7f91ff3d02277f11d339bf34099a56cdab6a8b3410a02b2", size = 3031985 }, - { url = "https://files.pythonhosted.org/packages/af/a4/79196b4a1674143d19dca400866b1a4d1a089040df7b93b88ebae81f3447/Brotli-1.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:58d4b711689366d4a03ac7957ab8c28890415e267f9b6589969e74b6e42225ec", size = 2927099 }, - { url = "https://files.pythonhosted.org/packages/e9/54/1c0278556a097f9651e657b873ab08f01b9a9ae4cac128ceb66427d7cd20/Brotli-1.1.0-cp310-cp310-win32.whl", hash = "sha256:be36e3d172dc816333f33520154d708a2657ea63762ec16b62ece02ab5e4daf2", size = 333172 }, - { url = "https://files.pythonhosted.org/packages/f7/65/b785722e941193fd8b571afd9edbec2a9b838ddec4375d8af33a50b8dab9/Brotli-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:0c6244521dda65ea562d5a69b9a26120769b7a9fb3db2fe9545935ed6735b128", size = 357255 }, - { url = "https://files.pythonhosted.org/packages/96/12/ad41e7fadd5db55459c4c401842b47f7fee51068f86dd2894dd0dcfc2d2a/Brotli-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a3daabb76a78f829cafc365531c972016e4aa8d5b4bf60660ad8ecee19df7ccc", size = 873068 }, - { url = "https://files.pythonhosted.org/packages/95/4e/5afab7b2b4b61a84e9c75b17814198ce515343a44e2ed4488fac314cd0a9/Brotli-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c8146669223164fc87a7e3de9f81e9423c67a79d6b3447994dfb9c95da16e2d6", size = 446244 }, - { url = "https://files.pythonhosted.org/packages/9d/e6/f305eb61fb9a8580c525478a4a34c5ae1a9bcb12c3aee619114940bc513d/Brotli-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30924eb4c57903d5a7526b08ef4a584acc22ab1ffa085faceb521521d2de32dd", size = 2906500 }, - { url = "https://files.pythonhosted.org/packages/3e/4f/af6846cfbc1550a3024e5d3775ede1e00474c40882c7bf5b37a43ca35e91/Brotli-1.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ceb64bbc6eac5a140ca649003756940f8d6a7c444a68af170b3187623b43bebf", size = 2943950 }, - { url = "https://files.pythonhosted.org/packages/b3/e7/ca2993c7682d8629b62630ebf0d1f3bb3d579e667ce8e7ca03a0a0576a2d/Brotli-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a469274ad18dc0e4d316eefa616d1d0c2ff9da369af19fa6f3daa4f09671fd61", size = 2918527 }, - { url = "https://files.pythonhosted.org/packages/b3/96/da98e7bedc4c51104d29cc61e5f449a502dd3dbc211944546a4cc65500d3/Brotli-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:524f35912131cc2cabb00edfd8d573b07f2d9f21fa824bd3fb19725a9cf06327", size = 2845489 }, - { url = "https://files.pythonhosted.org/packages/e8/ef/ccbc16947d6ce943a7f57e1a40596c75859eeb6d279c6994eddd69615265/Brotli-1.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5b3cc074004d968722f51e550b41a27be656ec48f8afaeeb45ebf65b561481dd", size = 2914080 }, - { url = "https://files.pythonhosted.org/packages/80/d6/0bd38d758d1afa62a5524172f0b18626bb2392d717ff94806f741fcd5ee9/Brotli-1.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:19c116e796420b0cee3da1ccec3b764ed2952ccfcc298b55a10e5610ad7885f9", size = 2813051 }, - { url = "https://files.pythonhosted.org/packages/14/56/48859dd5d129d7519e001f06dcfbb6e2cf6db92b2702c0c2ce7d97e086c1/Brotli-1.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:510b5b1bfbe20e1a7b3baf5fed9e9451873559a976c1a78eebaa3b86c57b4265", size = 2938172 }, - { url = "https://files.pythonhosted.org/packages/3d/77/a236d5f8cd9e9f4348da5acc75ab032ab1ab2c03cc8f430d24eea2672888/Brotli-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a1fd8a29719ccce974d523580987b7f8229aeace506952fa9ce1d53a033873c8", size = 2933023 }, - { url = "https://files.pythonhosted.org/packages/f1/87/3b283efc0f5cb35f7f84c0c240b1e1a1003a5e47141a4881bf87c86d0ce2/Brotli-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c247dd99d39e0338a604f8c2b3bc7061d5c2e9e2ac7ba9cc1be5a69cb6cd832f", size = 2935871 }, - { url = "https://files.pythonhosted.org/packages/f3/eb/2be4cc3e2141dc1a43ad4ca1875a72088229de38c68e842746b342667b2a/Brotli-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1b2c248cd517c222d89e74669a4adfa5577e06ab68771a529060cf5a156e9757", size = 2847784 }, - { url = "https://files.pythonhosted.org/packages/66/13/b58ddebfd35edde572ccefe6890cf7c493f0c319aad2a5badee134b4d8ec/Brotli-1.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:2a24c50840d89ded6c9a8fdc7b6ed3692ed4e86f1c4a4a938e1e92def92933e0", size = 3034905 }, - { url = "https://files.pythonhosted.org/packages/84/9c/bc96b6c7db824998a49ed3b38e441a2cae9234da6fa11f6ed17e8cf4f147/Brotli-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f31859074d57b4639318523d6ffdca586ace54271a73ad23ad021acd807eb14b", size = 2929467 }, - { url = "https://files.pythonhosted.org/packages/e7/71/8f161dee223c7ff7fea9d44893fba953ce97cf2c3c33f78ba260a91bcff5/Brotli-1.1.0-cp311-cp311-win32.whl", hash = "sha256:39da8adedf6942d76dc3e46653e52df937a3c4d6d18fdc94a7c29d263b1f5b50", size = 333169 }, - { url = "https://files.pythonhosted.org/packages/02/8a/fece0ee1057643cb2a5bbf59682de13f1725f8482b2c057d4e799d7ade75/Brotli-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:aac0411d20e345dc0920bdec5548e438e999ff68d77564d5e9463a7ca9d3e7b1", size = 357253 }, - { url = "https://files.pythonhosted.org/packages/5c/d0/5373ae13b93fe00095a58efcbce837fd470ca39f703a235d2a999baadfbc/Brotli-1.1.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:32d95b80260d79926f5fab3c41701dbb818fde1c9da590e77e571eefd14abe28", size = 815693 }, - { url = "https://files.pythonhosted.org/packages/8e/48/f6e1cdf86751300c288c1459724bfa6917a80e30dbfc326f92cea5d3683a/Brotli-1.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b760c65308ff1e462f65d69c12e4ae085cff3b332d894637f6273a12a482d09f", size = 422489 }, - { url = "https://files.pythonhosted.org/packages/06/88/564958cedce636d0f1bed313381dfc4b4e3d3f6015a63dae6146e1b8c65c/Brotli-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:316cc9b17edf613ac76b1f1f305d2a748f1b976b033b049a6ecdfd5612c70409", size = 873081 }, - { url = "https://files.pythonhosted.org/packages/58/79/b7026a8bb65da9a6bb7d14329fd2bd48d2b7f86d7329d5cc8ddc6a90526f/Brotli-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:caf9ee9a5775f3111642d33b86237b05808dafcd6268faa492250e9b78046eb2", size = 446244 }, - { url = "https://files.pythonhosted.org/packages/e5/18/c18c32ecea41b6c0004e15606e274006366fe19436b6adccc1ae7b2e50c2/Brotli-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70051525001750221daa10907c77830bc889cb6d865cc0b813d9db7fefc21451", size = 2906505 }, - { url = "https://files.pythonhosted.org/packages/08/c8/69ec0496b1ada7569b62d85893d928e865df29b90736558d6c98c2031208/Brotli-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7f4bf76817c14aa98cc6697ac02f3972cb8c3da93e9ef16b9c66573a68014f91", size = 2944152 }, - { url = "https://files.pythonhosted.org/packages/ab/fb/0517cea182219d6768113a38167ef6d4eb157a033178cc938033a552ed6d/Brotli-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0c5516f0aed654134a2fc936325cc2e642f8a0e096d075209672eb321cff408", size = 2919252 }, - { url = "https://files.pythonhosted.org/packages/c7/53/73a3431662e33ae61a5c80b1b9d2d18f58dfa910ae8dd696e57d39f1a2f5/Brotli-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c3020404e0b5eefd7c9485ccf8393cfb75ec38ce75586e046573c9dc29967a0", size = 2845955 }, - { url = "https://files.pythonhosted.org/packages/55/ac/bd280708d9c5ebdbf9de01459e625a3e3803cce0784f47d633562cf40e83/Brotli-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4ed11165dd45ce798d99a136808a794a748d5dc38511303239d4e2363c0695dc", size = 2914304 }, - { url = "https://files.pythonhosted.org/packages/76/58/5c391b41ecfc4527d2cc3350719b02e87cb424ef8ba2023fb662f9bf743c/Brotli-1.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4093c631e96fdd49e0377a9c167bfd75b6d0bad2ace734c6eb20b348bc3ea180", size = 2814452 }, - { url = "https://files.pythonhosted.org/packages/c7/4e/91b8256dfe99c407f174924b65a01f5305e303f486cc7a2e8a5d43c8bec3/Brotli-1.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e4c4629ddad63006efa0ef968c8e4751c5868ff0b1c5c40f76524e894c50248", size = 2938751 }, - { url = "https://files.pythonhosted.org/packages/5a/a6/e2a39a5d3b412938362bbbeba5af904092bf3f95b867b4a3eb856104074e/Brotli-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:861bf317735688269936f755fa136a99d1ed526883859f86e41a5d43c61d8966", size = 2933757 }, - { url = "https://files.pythonhosted.org/packages/13/f0/358354786280a509482e0e77c1a5459e439766597d280f28cb097642fc26/Brotli-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:87a3044c3a35055527ac75e419dfa9f4f3667a1e887ee80360589eb8c90aabb9", size = 2936146 }, - { url = "https://files.pythonhosted.org/packages/80/f7/daf538c1060d3a88266b80ecc1d1c98b79553b3f117a485653f17070ea2a/Brotli-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c5529b34c1c9d937168297f2c1fde7ebe9ebdd5e121297ff9c043bdb2ae3d6fb", size = 2848055 }, - { url = "https://files.pythonhosted.org/packages/ad/cf/0eaa0585c4077d3c2d1edf322d8e97aabf317941d3a72d7b3ad8bce004b0/Brotli-1.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ca63e1890ede90b2e4454f9a65135a4d387a4585ff8282bb72964fab893f2111", size = 3035102 }, - { url = "https://files.pythonhosted.org/packages/d8/63/1c1585b2aa554fe6dbce30f0c18bdbc877fa9a1bf5ff17677d9cca0ac122/Brotli-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e79e6520141d792237c70bcd7a3b122d00f2613769ae0cb61c52e89fd3443839", size = 2930029 }, - { url = "https://files.pythonhosted.org/packages/5f/3b/4e3fd1893eb3bbfef8e5a80d4508bec17a57bb92d586c85c12d28666bb13/Brotli-1.1.0-cp312-cp312-win32.whl", hash = "sha256:5f4d5ea15c9382135076d2fb28dde923352fe02951e66935a9efaac8f10e81b0", size = 333276 }, - { url = "https://files.pythonhosted.org/packages/3d/d5/942051b45a9e883b5b6e98c041698b1eb2012d25e5948c58d6bf85b1bb43/Brotli-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:906bc3a79de8c4ae5b86d3d75a8b77e44404b0f4261714306e3ad248d8ab0951", size = 357255 }, - { url = "https://files.pythonhosted.org/packages/0a/9f/fb37bb8ffc52a8da37b1c03c459a8cd55df7a57bdccd8831d500e994a0ca/Brotli-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8bf32b98b75c13ec7cf774164172683d6e7891088f6316e54425fde1efc276d5", size = 815681 }, - { url = "https://files.pythonhosted.org/packages/06/b3/dbd332a988586fefb0aa49c779f59f47cae76855c2d00f450364bb574cac/Brotli-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7bc37c4d6b87fb1017ea28c9508b36bbcb0c3d18b4260fcdf08b200c74a6aee8", size = 422475 }, - { url = "https://files.pythonhosted.org/packages/bb/80/6aaddc2f63dbcf2d93c2d204e49c11a9ec93a8c7c63261e2b4bd35198283/Brotli-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c0ef38c7a7014ffac184db9e04debe495d317cc9c6fb10071f7fefd93100a4f", size = 2906173 }, - { url = "https://files.pythonhosted.org/packages/ea/1d/e6ca79c96ff5b641df6097d299347507d39a9604bde8915e76bf026d6c77/Brotli-1.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91d7cc2a76b5567591d12c01f019dd7afce6ba8cba6571187e21e2fc418ae648", size = 2943803 }, - { url = "https://files.pythonhosted.org/packages/ac/a3/d98d2472e0130b7dd3acdbb7f390d478123dbf62b7d32bda5c830a96116d/Brotli-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a93dde851926f4f2678e704fadeb39e16c35d8baebd5252c9fd94ce8ce68c4a0", size = 2918946 }, - { url = "https://files.pythonhosted.org/packages/c4/a5/c69e6d272aee3e1423ed005d8915a7eaa0384c7de503da987f2d224d0721/Brotli-1.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f0db75f47be8b8abc8d9e31bc7aad0547ca26f24a54e6fd10231d623f183d089", size = 2845707 }, - { url = "https://files.pythonhosted.org/packages/58/9f/4149d38b52725afa39067350696c09526de0125ebfbaab5acc5af28b42ea/Brotli-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6967ced6730aed543b8673008b5a391c3b1076d834ca438bbd70635c73775368", size = 2936231 }, - { url = "https://files.pythonhosted.org/packages/5a/5a/145de884285611838a16bebfdb060c231c52b8f84dfbe52b852a15780386/Brotli-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7eedaa5d036d9336c95915035fb57422054014ebdeb6f3b42eac809928e40d0c", size = 2848157 }, - { url = "https://files.pythonhosted.org/packages/50/ae/408b6bfb8525dadebd3b3dd5b19d631da4f7d46420321db44cd99dcf2f2c/Brotli-1.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d487f5432bf35b60ed625d7e1b448e2dc855422e87469e3f450aa5552b0eb284", size = 3035122 }, - { url = "https://files.pythonhosted.org/packages/af/85/a94e5cfaa0ca449d8f91c3d6f78313ebf919a0dbd55a100c711c6e9655bc/Brotli-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:832436e59afb93e1836081a20f324cb185836c617659b07b129141a8426973c7", size = 2930206 }, - { url = "https://files.pythonhosted.org/packages/c2/f0/a61d9262cd01351df22e57ad7c34f66794709acab13f34be2675f45bf89d/Brotli-1.1.0-cp313-cp313-win32.whl", hash = "sha256:43395e90523f9c23a3d5bdf004733246fba087f2948f87ab28015f12359ca6a0", size = 333804 }, - { url = "https://files.pythonhosted.org/packages/7e/c1/ec214e9c94000d1c1974ec67ced1c970c148aa6b8d8373066123fc3dbf06/Brotli-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:9011560a466d2eb3f5a6e4929cf4a09be405c64154e12df0dd72713f6500e32b", size = 358517 }, + { url = "https://files.pythonhosted.org/packages/6d/3a/dbf4fb970c1019a57b5e492e1e0eae745d32e59ba4d6161ab5422b08eefe/Brotli-1.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e1140c64812cb9b06c922e77f1c26a75ec5e3f0fb2bf92cc8c58720dec276752", size = 873045, upload_time = "2023-09-07T14:03:16.894Z" }, + { url = "https://files.pythonhosted.org/packages/dd/11/afc14026ea7f44bd6eb9316d800d439d092c8d508752055ce8d03086079a/Brotli-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c8fd5270e906eef71d4a8d19b7c6a43760c6abcfcc10c9101d14eb2357418de9", size = 446218, upload_time = "2023-09-07T14:03:18.917Z" }, + { url = "https://files.pythonhosted.org/packages/36/83/7545a6e7729db43cb36c4287ae388d6885c85a86dd251768a47015dfde32/Brotli-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ae56aca0402a0f9a3431cddda62ad71666ca9d4dc3a10a142b9dce2e3c0cda3", size = 2903872, upload_time = "2023-09-07T14:03:20.398Z" }, + { url = "https://files.pythonhosted.org/packages/32/23/35331c4d9391fcc0f29fd9bec2c76e4b4eeab769afbc4b11dd2e1098fb13/Brotli-1.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:43ce1b9935bfa1ede40028054d7f48b5469cd02733a365eec8a329ffd342915d", size = 2941254, upload_time = "2023-09-07T14:03:21.914Z" }, + { url = "https://files.pythonhosted.org/packages/3b/24/1671acb450c902edb64bd765d73603797c6c7280a9ada85a195f6b78c6e5/Brotli-1.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7c4855522edb2e6ae7fdb58e07c3ba9111e7621a8956f481c68d5d979c93032e", size = 2857293, upload_time = "2023-09-07T14:03:24Z" }, + { url = "https://files.pythonhosted.org/packages/d5/00/40f760cc27007912b327fe15bf6bfd8eaecbe451687f72a8abc587d503b3/Brotli-1.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:38025d9f30cf4634f8309c6874ef871b841eb3c347e90b0851f63d1ded5212da", size = 3002385, upload_time = "2023-09-07T14:03:26.248Z" }, + { url = "https://files.pythonhosted.org/packages/b8/cb/8aaa83f7a4caa131757668c0fb0c4b6384b09ffa77f2fba9570d87ab587d/Brotli-1.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e6a904cb26bfefc2f0a6f240bdf5233be78cd2488900a2f846f3c3ac8489ab80", size = 2911104, upload_time = "2023-09-07T14:03:27.849Z" }, + { url = "https://files.pythonhosted.org/packages/bc/c4/65456561d89d3c49f46b7fbeb8fe6e449f13bdc8ea7791832c5d476b2faf/Brotli-1.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a37b8f0391212d29b3a91a799c8e4a2855e0576911cdfb2515487e30e322253d", size = 2809981, upload_time = "2023-09-07T14:03:29.92Z" }, + { url = "https://files.pythonhosted.org/packages/05/1b/cf49528437bae28abce5f6e059f0d0be6fecdcc1d3e33e7c54b3ca498425/Brotli-1.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e84799f09591700a4154154cab9787452925578841a94321d5ee8fb9a9a328f0", size = 2935297, upload_time = "2023-09-07T14:03:32.035Z" }, + { url = "https://files.pythonhosted.org/packages/81/ff/190d4af610680bf0c5a09eb5d1eac6e99c7c8e216440f9c7cfd42b7adab5/Brotli-1.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f66b5337fa213f1da0d9000bc8dc0cb5b896b726eefd9c6046f699b169c41b9e", size = 2930735, upload_time = "2023-09-07T14:03:33.801Z" }, + { url = "https://files.pythonhosted.org/packages/80/7d/f1abbc0c98f6e09abd3cad63ec34af17abc4c44f308a7a539010f79aae7a/Brotli-1.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5dab0844f2cf82be357a0eb11a9087f70c5430b2c241493fc122bb6f2bb0917c", size = 2933107, upload_time = "2024-10-18T12:32:09.016Z" }, + { url = "https://files.pythonhosted.org/packages/34/ce/5a5020ba48f2b5a4ad1c0522d095ad5847a0be508e7d7569c8630ce25062/Brotli-1.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e4fe605b917c70283db7dfe5ada75e04561479075761a0b3866c081d035b01c1", size = 2845400, upload_time = "2024-10-18T12:32:11.134Z" }, + { url = "https://files.pythonhosted.org/packages/44/89/fa2c4355ab1eecf3994e5a0a7f5492c6ff81dfcb5f9ba7859bd534bb5c1a/Brotli-1.1.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:1e9a65b5736232e7a7f91ff3d02277f11d339bf34099a56cdab6a8b3410a02b2", size = 3031985, upload_time = "2024-10-18T12:32:12.813Z" }, + { url = "https://files.pythonhosted.org/packages/af/a4/79196b4a1674143d19dca400866b1a4d1a089040df7b93b88ebae81f3447/Brotli-1.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:58d4b711689366d4a03ac7957ab8c28890415e267f9b6589969e74b6e42225ec", size = 2927099, upload_time = "2024-10-18T12:32:14.733Z" }, + { url = "https://files.pythonhosted.org/packages/e9/54/1c0278556a097f9651e657b873ab08f01b9a9ae4cac128ceb66427d7cd20/Brotli-1.1.0-cp310-cp310-win32.whl", hash = "sha256:be36e3d172dc816333f33520154d708a2657ea63762ec16b62ece02ab5e4daf2", size = 333172, upload_time = "2023-09-07T14:03:35.212Z" }, + { url = "https://files.pythonhosted.org/packages/f7/65/b785722e941193fd8b571afd9edbec2a9b838ddec4375d8af33a50b8dab9/Brotli-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:0c6244521dda65ea562d5a69b9a26120769b7a9fb3db2fe9545935ed6735b128", size = 357255, upload_time = "2023-09-07T14:03:36.447Z" }, + { url = "https://files.pythonhosted.org/packages/96/12/ad41e7fadd5db55459c4c401842b47f7fee51068f86dd2894dd0dcfc2d2a/Brotli-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a3daabb76a78f829cafc365531c972016e4aa8d5b4bf60660ad8ecee19df7ccc", size = 873068, upload_time = "2023-09-07T14:03:37.779Z" }, + { url = "https://files.pythonhosted.org/packages/95/4e/5afab7b2b4b61a84e9c75b17814198ce515343a44e2ed4488fac314cd0a9/Brotli-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c8146669223164fc87a7e3de9f81e9423c67a79d6b3447994dfb9c95da16e2d6", size = 446244, upload_time = "2023-09-07T14:03:39.223Z" }, + { url = "https://files.pythonhosted.org/packages/9d/e6/f305eb61fb9a8580c525478a4a34c5ae1a9bcb12c3aee619114940bc513d/Brotli-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30924eb4c57903d5a7526b08ef4a584acc22ab1ffa085faceb521521d2de32dd", size = 2906500, upload_time = "2023-09-07T14:03:40.858Z" }, + { url = "https://files.pythonhosted.org/packages/3e/4f/af6846cfbc1550a3024e5d3775ede1e00474c40882c7bf5b37a43ca35e91/Brotli-1.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ceb64bbc6eac5a140ca649003756940f8d6a7c444a68af170b3187623b43bebf", size = 2943950, upload_time = "2023-09-07T14:03:42.896Z" }, + { url = "https://files.pythonhosted.org/packages/b3/e7/ca2993c7682d8629b62630ebf0d1f3bb3d579e667ce8e7ca03a0a0576a2d/Brotli-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a469274ad18dc0e4d316eefa616d1d0c2ff9da369af19fa6f3daa4f09671fd61", size = 2918527, upload_time = "2023-09-07T14:03:44.552Z" }, + { url = "https://files.pythonhosted.org/packages/b3/96/da98e7bedc4c51104d29cc61e5f449a502dd3dbc211944546a4cc65500d3/Brotli-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:524f35912131cc2cabb00edfd8d573b07f2d9f21fa824bd3fb19725a9cf06327", size = 2845489, upload_time = "2023-09-07T14:03:46.594Z" }, + { url = "https://files.pythonhosted.org/packages/e8/ef/ccbc16947d6ce943a7f57e1a40596c75859eeb6d279c6994eddd69615265/Brotli-1.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5b3cc074004d968722f51e550b41a27be656ec48f8afaeeb45ebf65b561481dd", size = 2914080, upload_time = "2023-09-07T14:03:48.204Z" }, + { url = "https://files.pythonhosted.org/packages/80/d6/0bd38d758d1afa62a5524172f0b18626bb2392d717ff94806f741fcd5ee9/Brotli-1.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:19c116e796420b0cee3da1ccec3b764ed2952ccfcc298b55a10e5610ad7885f9", size = 2813051, upload_time = "2023-09-07T14:03:50.348Z" }, + { url = "https://files.pythonhosted.org/packages/14/56/48859dd5d129d7519e001f06dcfbb6e2cf6db92b2702c0c2ce7d97e086c1/Brotli-1.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:510b5b1bfbe20e1a7b3baf5fed9e9451873559a976c1a78eebaa3b86c57b4265", size = 2938172, upload_time = "2023-09-07T14:03:52.395Z" }, + { url = "https://files.pythonhosted.org/packages/3d/77/a236d5f8cd9e9f4348da5acc75ab032ab1ab2c03cc8f430d24eea2672888/Brotli-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a1fd8a29719ccce974d523580987b7f8229aeace506952fa9ce1d53a033873c8", size = 2933023, upload_time = "2023-09-07T14:03:53.96Z" }, + { url = "https://files.pythonhosted.org/packages/f1/87/3b283efc0f5cb35f7f84c0c240b1e1a1003a5e47141a4881bf87c86d0ce2/Brotli-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c247dd99d39e0338a604f8c2b3bc7061d5c2e9e2ac7ba9cc1be5a69cb6cd832f", size = 2935871, upload_time = "2024-10-18T12:32:16.688Z" }, + { url = "https://files.pythonhosted.org/packages/f3/eb/2be4cc3e2141dc1a43ad4ca1875a72088229de38c68e842746b342667b2a/Brotli-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1b2c248cd517c222d89e74669a4adfa5577e06ab68771a529060cf5a156e9757", size = 2847784, upload_time = "2024-10-18T12:32:18.459Z" }, + { url = "https://files.pythonhosted.org/packages/66/13/b58ddebfd35edde572ccefe6890cf7c493f0c319aad2a5badee134b4d8ec/Brotli-1.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:2a24c50840d89ded6c9a8fdc7b6ed3692ed4e86f1c4a4a938e1e92def92933e0", size = 3034905, upload_time = "2024-10-18T12:32:20.192Z" }, + { url = "https://files.pythonhosted.org/packages/84/9c/bc96b6c7db824998a49ed3b38e441a2cae9234da6fa11f6ed17e8cf4f147/Brotli-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f31859074d57b4639318523d6ffdca586ace54271a73ad23ad021acd807eb14b", size = 2929467, upload_time = "2024-10-18T12:32:21.774Z" }, + { url = "https://files.pythonhosted.org/packages/e7/71/8f161dee223c7ff7fea9d44893fba953ce97cf2c3c33f78ba260a91bcff5/Brotli-1.1.0-cp311-cp311-win32.whl", hash = "sha256:39da8adedf6942d76dc3e46653e52df937a3c4d6d18fdc94a7c29d263b1f5b50", size = 333169, upload_time = "2023-09-07T14:03:55.404Z" }, + { url = "https://files.pythonhosted.org/packages/02/8a/fece0ee1057643cb2a5bbf59682de13f1725f8482b2c057d4e799d7ade75/Brotli-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:aac0411d20e345dc0920bdec5548e438e999ff68d77564d5e9463a7ca9d3e7b1", size = 357253, upload_time = "2023-09-07T14:03:56.643Z" }, + { url = "https://files.pythonhosted.org/packages/5c/d0/5373ae13b93fe00095a58efcbce837fd470ca39f703a235d2a999baadfbc/Brotli-1.1.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:32d95b80260d79926f5fab3c41701dbb818fde1c9da590e77e571eefd14abe28", size = 815693, upload_time = "2024-10-18T12:32:23.824Z" }, + { url = "https://files.pythonhosted.org/packages/8e/48/f6e1cdf86751300c288c1459724bfa6917a80e30dbfc326f92cea5d3683a/Brotli-1.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b760c65308ff1e462f65d69c12e4ae085cff3b332d894637f6273a12a482d09f", size = 422489, upload_time = "2024-10-18T12:32:25.641Z" }, + { url = "https://files.pythonhosted.org/packages/06/88/564958cedce636d0f1bed313381dfc4b4e3d3f6015a63dae6146e1b8c65c/Brotli-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:316cc9b17edf613ac76b1f1f305d2a748f1b976b033b049a6ecdfd5612c70409", size = 873081, upload_time = "2023-09-07T14:03:57.967Z" }, + { url = "https://files.pythonhosted.org/packages/58/79/b7026a8bb65da9a6bb7d14329fd2bd48d2b7f86d7329d5cc8ddc6a90526f/Brotli-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:caf9ee9a5775f3111642d33b86237b05808dafcd6268faa492250e9b78046eb2", size = 446244, upload_time = "2023-09-07T14:03:59.319Z" }, + { url = "https://files.pythonhosted.org/packages/e5/18/c18c32ecea41b6c0004e15606e274006366fe19436b6adccc1ae7b2e50c2/Brotli-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70051525001750221daa10907c77830bc889cb6d865cc0b813d9db7fefc21451", size = 2906505, upload_time = "2023-09-07T14:04:01.327Z" }, + { url = "https://files.pythonhosted.org/packages/08/c8/69ec0496b1ada7569b62d85893d928e865df29b90736558d6c98c2031208/Brotli-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7f4bf76817c14aa98cc6697ac02f3972cb8c3da93e9ef16b9c66573a68014f91", size = 2944152, upload_time = "2023-09-07T14:04:03.033Z" }, + { url = "https://files.pythonhosted.org/packages/ab/fb/0517cea182219d6768113a38167ef6d4eb157a033178cc938033a552ed6d/Brotli-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0c5516f0aed654134a2fc936325cc2e642f8a0e096d075209672eb321cff408", size = 2919252, upload_time = "2023-09-07T14:04:04.675Z" }, + { url = "https://files.pythonhosted.org/packages/c7/53/73a3431662e33ae61a5c80b1b9d2d18f58dfa910ae8dd696e57d39f1a2f5/Brotli-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c3020404e0b5eefd7c9485ccf8393cfb75ec38ce75586e046573c9dc29967a0", size = 2845955, upload_time = "2023-09-07T14:04:06.585Z" }, + { url = "https://files.pythonhosted.org/packages/55/ac/bd280708d9c5ebdbf9de01459e625a3e3803cce0784f47d633562cf40e83/Brotli-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4ed11165dd45ce798d99a136808a794a748d5dc38511303239d4e2363c0695dc", size = 2914304, upload_time = "2023-09-07T14:04:08.668Z" }, + { url = "https://files.pythonhosted.org/packages/76/58/5c391b41ecfc4527d2cc3350719b02e87cb424ef8ba2023fb662f9bf743c/Brotli-1.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4093c631e96fdd49e0377a9c167bfd75b6d0bad2ace734c6eb20b348bc3ea180", size = 2814452, upload_time = "2023-09-07T14:04:10.736Z" }, + { url = "https://files.pythonhosted.org/packages/c7/4e/91b8256dfe99c407f174924b65a01f5305e303f486cc7a2e8a5d43c8bec3/Brotli-1.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e4c4629ddad63006efa0ef968c8e4751c5868ff0b1c5c40f76524e894c50248", size = 2938751, upload_time = "2023-09-07T14:04:12.875Z" }, + { url = "https://files.pythonhosted.org/packages/5a/a6/e2a39a5d3b412938362bbbeba5af904092bf3f95b867b4a3eb856104074e/Brotli-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:861bf317735688269936f755fa136a99d1ed526883859f86e41a5d43c61d8966", size = 2933757, upload_time = "2023-09-07T14:04:14.551Z" }, + { url = "https://files.pythonhosted.org/packages/13/f0/358354786280a509482e0e77c1a5459e439766597d280f28cb097642fc26/Brotli-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:87a3044c3a35055527ac75e419dfa9f4f3667a1e887ee80360589eb8c90aabb9", size = 2936146, upload_time = "2024-10-18T12:32:27.257Z" }, + { url = "https://files.pythonhosted.org/packages/80/f7/daf538c1060d3a88266b80ecc1d1c98b79553b3f117a485653f17070ea2a/Brotli-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c5529b34c1c9d937168297f2c1fde7ebe9ebdd5e121297ff9c043bdb2ae3d6fb", size = 2848055, upload_time = "2024-10-18T12:32:29.376Z" }, + { url = "https://files.pythonhosted.org/packages/ad/cf/0eaa0585c4077d3c2d1edf322d8e97aabf317941d3a72d7b3ad8bce004b0/Brotli-1.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ca63e1890ede90b2e4454f9a65135a4d387a4585ff8282bb72964fab893f2111", size = 3035102, upload_time = "2024-10-18T12:32:31.371Z" }, + { url = "https://files.pythonhosted.org/packages/d8/63/1c1585b2aa554fe6dbce30f0c18bdbc877fa9a1bf5ff17677d9cca0ac122/Brotli-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e79e6520141d792237c70bcd7a3b122d00f2613769ae0cb61c52e89fd3443839", size = 2930029, upload_time = "2024-10-18T12:32:33.293Z" }, + { url = "https://files.pythonhosted.org/packages/5f/3b/4e3fd1893eb3bbfef8e5a80d4508bec17a57bb92d586c85c12d28666bb13/Brotli-1.1.0-cp312-cp312-win32.whl", hash = "sha256:5f4d5ea15c9382135076d2fb28dde923352fe02951e66935a9efaac8f10e81b0", size = 333276, upload_time = "2023-09-07T14:04:16.49Z" }, + { url = "https://files.pythonhosted.org/packages/3d/d5/942051b45a9e883b5b6e98c041698b1eb2012d25e5948c58d6bf85b1bb43/Brotli-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:906bc3a79de8c4ae5b86d3d75a8b77e44404b0f4261714306e3ad248d8ab0951", size = 357255, upload_time = "2023-09-07T14:04:17.83Z" }, + { url = "https://files.pythonhosted.org/packages/0a/9f/fb37bb8ffc52a8da37b1c03c459a8cd55df7a57bdccd8831d500e994a0ca/Brotli-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8bf32b98b75c13ec7cf774164172683d6e7891088f6316e54425fde1efc276d5", size = 815681, upload_time = "2024-10-18T12:32:34.942Z" }, + { url = "https://files.pythonhosted.org/packages/06/b3/dbd332a988586fefb0aa49c779f59f47cae76855c2d00f450364bb574cac/Brotli-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7bc37c4d6b87fb1017ea28c9508b36bbcb0c3d18b4260fcdf08b200c74a6aee8", size = 422475, upload_time = "2024-10-18T12:32:36.485Z" }, + { url = "https://files.pythonhosted.org/packages/bb/80/6aaddc2f63dbcf2d93c2d204e49c11a9ec93a8c7c63261e2b4bd35198283/Brotli-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c0ef38c7a7014ffac184db9e04debe495d317cc9c6fb10071f7fefd93100a4f", size = 2906173, upload_time = "2024-10-18T12:32:37.978Z" }, + { url = "https://files.pythonhosted.org/packages/ea/1d/e6ca79c96ff5b641df6097d299347507d39a9604bde8915e76bf026d6c77/Brotli-1.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91d7cc2a76b5567591d12c01f019dd7afce6ba8cba6571187e21e2fc418ae648", size = 2943803, upload_time = "2024-10-18T12:32:39.606Z" }, + { url = "https://files.pythonhosted.org/packages/ac/a3/d98d2472e0130b7dd3acdbb7f390d478123dbf62b7d32bda5c830a96116d/Brotli-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a93dde851926f4f2678e704fadeb39e16c35d8baebd5252c9fd94ce8ce68c4a0", size = 2918946, upload_time = "2024-10-18T12:32:41.679Z" }, + { url = "https://files.pythonhosted.org/packages/c4/a5/c69e6d272aee3e1423ed005d8915a7eaa0384c7de503da987f2d224d0721/Brotli-1.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f0db75f47be8b8abc8d9e31bc7aad0547ca26f24a54e6fd10231d623f183d089", size = 2845707, upload_time = "2024-10-18T12:32:43.478Z" }, + { url = "https://files.pythonhosted.org/packages/58/9f/4149d38b52725afa39067350696c09526de0125ebfbaab5acc5af28b42ea/Brotli-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6967ced6730aed543b8673008b5a391c3b1076d834ca438bbd70635c73775368", size = 2936231, upload_time = "2024-10-18T12:32:45.224Z" }, + { url = "https://files.pythonhosted.org/packages/5a/5a/145de884285611838a16bebfdb060c231c52b8f84dfbe52b852a15780386/Brotli-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7eedaa5d036d9336c95915035fb57422054014ebdeb6f3b42eac809928e40d0c", size = 2848157, upload_time = "2024-10-18T12:32:46.894Z" }, + { url = "https://files.pythonhosted.org/packages/50/ae/408b6bfb8525dadebd3b3dd5b19d631da4f7d46420321db44cd99dcf2f2c/Brotli-1.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d487f5432bf35b60ed625d7e1b448e2dc855422e87469e3f450aa5552b0eb284", size = 3035122, upload_time = "2024-10-18T12:32:48.844Z" }, + { url = "https://files.pythonhosted.org/packages/af/85/a94e5cfaa0ca449d8f91c3d6f78313ebf919a0dbd55a100c711c6e9655bc/Brotli-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:832436e59afb93e1836081a20f324cb185836c617659b07b129141a8426973c7", size = 2930206, upload_time = "2024-10-18T12:32:51.198Z" }, + { url = "https://files.pythonhosted.org/packages/c2/f0/a61d9262cd01351df22e57ad7c34f66794709acab13f34be2675f45bf89d/Brotli-1.1.0-cp313-cp313-win32.whl", hash = "sha256:43395e90523f9c23a3d5bdf004733246fba087f2948f87ab28015f12359ca6a0", size = 333804, upload_time = "2024-10-18T12:32:52.661Z" }, + { url = "https://files.pythonhosted.org/packages/7e/c1/ec214e9c94000d1c1974ec67ced1c970c148aa6b8d8373066123fc3dbf06/Brotli-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:9011560a466d2eb3f5a6e4929cf4a09be405c64154e12df0dd72713f6500e32b", size = 358517, upload_time = "2024-10-18T12:32:54.066Z" }, ] [[package]] name = "certifi" version = "2023.11.17" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d4/91/c89518dd4fe1f3a4e3f6ab7ff23cb00ef2e8c9adf99dacc618ad5e068e28/certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1", size = 163637 } +sdist = { url = "https://files.pythonhosted.org/packages/d4/91/c89518dd4fe1f3a4e3f6ab7ff23cb00ef2e8c9adf99dacc618ad5e068e28/certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1", size = 163637, upload_time = "2023-11-18T02:54:02.397Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/64/62/428ef076be88fa93716b576e4a01f919d25968913e817077a386fcbe4f42/certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474", size = 162530 }, + { url = "https://files.pythonhosted.org/packages/64/62/428ef076be88fa93716b576e4a01f919d25968913e817077a386fcbe4f42/certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474", size = 162530, upload_time = "2023-11-18T02:54:00.083Z" }, ] [[package]] @@ -198,108 +207,108 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pycparser" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621 } +sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621, upload_time = "2024-09-04T20:45:21.852Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/90/07/f44ca684db4e4f08a3fdc6eeb9a0d15dc6883efc7b8c90357fdbf74e186c/cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14", size = 182191 }, - { url = "https://files.pythonhosted.org/packages/08/fd/cc2fedbd887223f9f5d170c96e57cbf655df9831a6546c1727ae13fa977a/cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67", size = 178592 }, - { url = "https://files.pythonhosted.org/packages/de/cc/4635c320081c78d6ffc2cab0a76025b691a91204f4aa317d568ff9280a2d/cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382", size = 426024 }, - { url = "https://files.pythonhosted.org/packages/b6/7b/3b2b250f3aab91abe5f8a51ada1b717935fdaec53f790ad4100fe2ec64d1/cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702", size = 448188 }, - { url = "https://files.pythonhosted.org/packages/d3/48/1b9283ebbf0ec065148d8de05d647a986c5f22586b18120020452fff8f5d/cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3", size = 455571 }, - { url = "https://files.pythonhosted.org/packages/40/87/3b8452525437b40f39ca7ff70276679772ee7e8b394934ff60e63b7b090c/cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6", size = 436687 }, - { url = "https://files.pythonhosted.org/packages/8d/fb/4da72871d177d63649ac449aec2e8a29efe0274035880c7af59101ca2232/cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17", size = 446211 }, - { url = "https://files.pythonhosted.org/packages/ab/a0/62f00bcb411332106c02b663b26f3545a9ef136f80d5df746c05878f8c4b/cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8", size = 461325 }, - { url = "https://files.pythonhosted.org/packages/36/83/76127035ed2e7e27b0787604d99da630ac3123bfb02d8e80c633f218a11d/cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e", size = 438784 }, - { url = "https://files.pythonhosted.org/packages/21/81/a6cd025db2f08ac88b901b745c163d884641909641f9b826e8cb87645942/cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be", size = 461564 }, - { url = "https://files.pythonhosted.org/packages/f8/fe/4d41c2f200c4a457933dbd98d3cf4e911870877bd94d9656cc0fcb390681/cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c", size = 171804 }, - { url = "https://files.pythonhosted.org/packages/d1/b6/0b0f5ab93b0df4acc49cae758c81fe4e5ef26c3ae2e10cc69249dfd8b3ab/cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15", size = 181299 }, - { url = "https://files.pythonhosted.org/packages/6b/f4/927e3a8899e52a27fa57a48607ff7dc91a9ebe97399b357b85a0c7892e00/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", size = 182264 }, - { url = "https://files.pythonhosted.org/packages/6c/f5/6c3a8efe5f503175aaddcbea6ad0d2c96dad6f5abb205750d1b3df44ef29/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", size = 178651 }, - { url = "https://files.pythonhosted.org/packages/94/dd/a3f0118e688d1b1a57553da23b16bdade96d2f9bcda4d32e7d2838047ff7/cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", size = 445259 }, - { url = "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", size = 469200 }, - { url = "https://files.pythonhosted.org/packages/1c/a0/a4fa9f4f781bda074c3ddd57a572b060fa0df7655d2a4247bbe277200146/cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", size = 477235 }, - { url = "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", size = 459721 }, - { url = "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", size = 467242 }, - { url = "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", size = 477999 }, - { url = "https://files.pythonhosted.org/packages/44/74/f2a2460684a1a2d00ca799ad880d54652841a780c4c97b87754f660c7603/cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", size = 454242 }, - { url = "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b", size = 478604 }, - { url = "https://files.pythonhosted.org/packages/34/33/e1b8a1ba29025adbdcda5fb3a36f94c03d771c1b7b12f726ff7fef2ebe36/cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", size = 171727 }, - { url = "https://files.pythonhosted.org/packages/3d/97/50228be003bb2802627d28ec0627837ac0bf35c90cf769812056f235b2d1/cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", size = 181400 }, - { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178 }, - { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840 }, - { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803 }, - { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850 }, - { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729 }, - { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256 }, - { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424 }, - { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568 }, - { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736 }, - { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448 }, - { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976 }, - { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989 }, - { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802 }, - { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792 }, - { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893 }, - { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810 }, - { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200 }, - { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447 }, - { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358 }, - { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469 }, - { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475 }, - { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009 }, + { url = "https://files.pythonhosted.org/packages/90/07/f44ca684db4e4f08a3fdc6eeb9a0d15dc6883efc7b8c90357fdbf74e186c/cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14", size = 182191, upload_time = "2024-09-04T20:43:30.027Z" }, + { url = "https://files.pythonhosted.org/packages/08/fd/cc2fedbd887223f9f5d170c96e57cbf655df9831a6546c1727ae13fa977a/cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67", size = 178592, upload_time = "2024-09-04T20:43:32.108Z" }, + { url = "https://files.pythonhosted.org/packages/de/cc/4635c320081c78d6ffc2cab0a76025b691a91204f4aa317d568ff9280a2d/cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382", size = 426024, upload_time = "2024-09-04T20:43:34.186Z" }, + { url = "https://files.pythonhosted.org/packages/b6/7b/3b2b250f3aab91abe5f8a51ada1b717935fdaec53f790ad4100fe2ec64d1/cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702", size = 448188, upload_time = "2024-09-04T20:43:36.286Z" }, + { url = "https://files.pythonhosted.org/packages/d3/48/1b9283ebbf0ec065148d8de05d647a986c5f22586b18120020452fff8f5d/cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3", size = 455571, upload_time = "2024-09-04T20:43:38.586Z" }, + { url = "https://files.pythonhosted.org/packages/40/87/3b8452525437b40f39ca7ff70276679772ee7e8b394934ff60e63b7b090c/cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6", size = 436687, upload_time = "2024-09-04T20:43:40.084Z" }, + { url = "https://files.pythonhosted.org/packages/8d/fb/4da72871d177d63649ac449aec2e8a29efe0274035880c7af59101ca2232/cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17", size = 446211, upload_time = "2024-09-04T20:43:41.526Z" }, + { url = "https://files.pythonhosted.org/packages/ab/a0/62f00bcb411332106c02b663b26f3545a9ef136f80d5df746c05878f8c4b/cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8", size = 461325, upload_time = "2024-09-04T20:43:43.117Z" }, + { url = "https://files.pythonhosted.org/packages/36/83/76127035ed2e7e27b0787604d99da630ac3123bfb02d8e80c633f218a11d/cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e", size = 438784, upload_time = "2024-09-04T20:43:45.256Z" }, + { url = "https://files.pythonhosted.org/packages/21/81/a6cd025db2f08ac88b901b745c163d884641909641f9b826e8cb87645942/cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be", size = 461564, upload_time = "2024-09-04T20:43:46.779Z" }, + { url = "https://files.pythonhosted.org/packages/f8/fe/4d41c2f200c4a457933dbd98d3cf4e911870877bd94d9656cc0fcb390681/cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c", size = 171804, upload_time = "2024-09-04T20:43:48.186Z" }, + { url = "https://files.pythonhosted.org/packages/d1/b6/0b0f5ab93b0df4acc49cae758c81fe4e5ef26c3ae2e10cc69249dfd8b3ab/cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15", size = 181299, upload_time = "2024-09-04T20:43:49.812Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f4/927e3a8899e52a27fa57a48607ff7dc91a9ebe97399b357b85a0c7892e00/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", size = 182264, upload_time = "2024-09-04T20:43:51.124Z" }, + { url = "https://files.pythonhosted.org/packages/6c/f5/6c3a8efe5f503175aaddcbea6ad0d2c96dad6f5abb205750d1b3df44ef29/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", size = 178651, upload_time = "2024-09-04T20:43:52.872Z" }, + { url = "https://files.pythonhosted.org/packages/94/dd/a3f0118e688d1b1a57553da23b16bdade96d2f9bcda4d32e7d2838047ff7/cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", size = 445259, upload_time = "2024-09-04T20:43:56.123Z" }, + { url = "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", size = 469200, upload_time = "2024-09-04T20:43:57.891Z" }, + { url = "https://files.pythonhosted.org/packages/1c/a0/a4fa9f4f781bda074c3ddd57a572b060fa0df7655d2a4247bbe277200146/cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", size = 477235, upload_time = "2024-09-04T20:44:00.18Z" }, + { url = "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", size = 459721, upload_time = "2024-09-04T20:44:01.585Z" }, + { url = "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", size = 467242, upload_time = "2024-09-04T20:44:03.467Z" }, + { url = "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", size = 477999, upload_time = "2024-09-04T20:44:05.023Z" }, + { url = "https://files.pythonhosted.org/packages/44/74/f2a2460684a1a2d00ca799ad880d54652841a780c4c97b87754f660c7603/cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", size = 454242, upload_time = "2024-09-04T20:44:06.444Z" }, + { url = "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b", size = 478604, upload_time = "2024-09-04T20:44:08.206Z" }, + { url = "https://files.pythonhosted.org/packages/34/33/e1b8a1ba29025adbdcda5fb3a36f94c03d771c1b7b12f726ff7fef2ebe36/cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", size = 171727, upload_time = "2024-09-04T20:44:09.481Z" }, + { url = "https://files.pythonhosted.org/packages/3d/97/50228be003bb2802627d28ec0627837ac0bf35c90cf769812056f235b2d1/cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", size = 181400, upload_time = "2024-09-04T20:44:10.873Z" }, + { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178, upload_time = "2024-09-04T20:44:12.232Z" }, + { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840, upload_time = "2024-09-04T20:44:13.739Z" }, + { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803, upload_time = "2024-09-04T20:44:15.231Z" }, + { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850, upload_time = "2024-09-04T20:44:17.188Z" }, + { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729, upload_time = "2024-09-04T20:44:18.688Z" }, + { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256, upload_time = "2024-09-04T20:44:20.248Z" }, + { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424, upload_time = "2024-09-04T20:44:21.673Z" }, + { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568, upload_time = "2024-09-04T20:44:23.245Z" }, + { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736, upload_time = "2024-09-04T20:44:24.757Z" }, + { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448, upload_time = "2024-09-04T20:44:26.208Z" }, + { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976, upload_time = "2024-09-04T20:44:27.578Z" }, + { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989, upload_time = "2024-09-04T20:44:28.956Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802, upload_time = "2024-09-04T20:44:30.289Z" }, + { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792, upload_time = "2024-09-04T20:44:32.01Z" }, + { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893, upload_time = "2024-09-04T20:44:33.606Z" }, + { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810, upload_time = "2024-09-04T20:44:35.191Z" }, + { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200, upload_time = "2024-09-04T20:44:36.743Z" }, + { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447, upload_time = "2024-09-04T20:44:38.492Z" }, + { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358, upload_time = "2024-09-04T20:44:40.046Z" }, + { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469, upload_time = "2024-09-04T20:44:41.616Z" }, + { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475, upload_time = "2024-09-04T20:44:43.733Z" }, + { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009, upload_time = "2024-09-04T20:44:45.309Z" }, ] [[package]] name = "charset-normalizer" version = "3.3.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/63/09/c1bc53dab74b1816a00d8d030de5bf98f724c52c1635e07681d312f20be8/charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5", size = 104809 } +sdist = { url = "https://files.pythonhosted.org/packages/63/09/c1bc53dab74b1816a00d8d030de5bf98f724c52c1635e07681d312f20be8/charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5", size = 104809, upload_time = "2023-11-01T04:04:59.997Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2b/61/095a0aa1a84d1481998b534177c8566fdc50bb1233ea9a0478cd3cc075bd/charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3", size = 194219 }, - { url = "https://files.pythonhosted.org/packages/cc/94/f7cf5e5134175de79ad2059edf2adce18e0685ebdb9227ff0139975d0e93/charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027", size = 122521 }, - { url = "https://files.pythonhosted.org/packages/46/6a/d5c26c41c49b546860cc1acabdddf48b0b3fb2685f4f5617ac59261b44ae/charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03", size = 120383 }, - { url = "https://files.pythonhosted.org/packages/b8/60/e2f67915a51be59d4539ed189eb0a2b0d292bf79270410746becb32bc2c3/charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d", size = 138223 }, - { url = "https://files.pythonhosted.org/packages/05/8c/eb854996d5fef5e4f33ad56927ad053d04dc820e4a3d39023f35cad72617/charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e", size = 148101 }, - { url = "https://files.pythonhosted.org/packages/f6/93/bb6cbeec3bf9da9b2eba458c15966658d1daa8b982c642f81c93ad9b40e1/charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6", size = 140699 }, - { url = "https://files.pythonhosted.org/packages/da/f1/3702ba2a7470666a62fd81c58a4c40be00670e5006a67f4d626e57f013ae/charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5", size = 142065 }, - { url = "https://files.pythonhosted.org/packages/3f/ba/3f5e7be00b215fa10e13d64b1f6237eb6ebea66676a41b2bcdd09fe74323/charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537", size = 144505 }, - { url = "https://files.pythonhosted.org/packages/33/c3/3b96a435c5109dd5b6adc8a59ba1d678b302a97938f032e3770cc84cd354/charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c", size = 139425 }, - { url = "https://files.pythonhosted.org/packages/43/05/3bf613e719efe68fb3a77f9c536a389f35b95d75424b96b426a47a45ef1d/charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12", size = 145287 }, - { url = "https://files.pythonhosted.org/packages/58/78/a0bc646900994df12e07b4ae5c713f2b3e5998f58b9d3720cce2aa45652f/charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f", size = 149929 }, - { url = "https://files.pythonhosted.org/packages/eb/5c/97d97248af4920bc68687d9c3b3c0f47c910e21a8ff80af4565a576bd2f0/charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269", size = 141605 }, - { url = "https://files.pythonhosted.org/packages/a8/31/47d018ef89f95b8aded95c589a77c072c55e94b50a41aa99c0a2008a45a4/charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519", size = 142646 }, - { url = "https://files.pythonhosted.org/packages/ae/d5/4fecf1d58bedb1340a50f165ba1c7ddc0400252d6832ff619c4568b36cc0/charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73", size = 92846 }, - { url = "https://files.pythonhosted.org/packages/a2/a0/4af29e22cb5942488cf45630cbdd7cefd908768e69bdd90280842e4e8529/charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09", size = 100343 }, - { url = "https://files.pythonhosted.org/packages/68/77/02839016f6fbbf808e8b38601df6e0e66c17bbab76dff4613f7511413597/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db", size = 191647 }, - { url = "https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96", size = 121434 }, - { url = "https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e", size = 118979 }, - { url = "https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f", size = 136582 }, - { url = "https://files.pythonhosted.org/packages/74/f1/0d9fe69ac441467b737ba7f48c68241487df2f4522dd7246d9426e7c690e/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574", size = 146645 }, - { url = "https://files.pythonhosted.org/packages/05/31/e1f51c76db7be1d4aef220d29fbfa5dbb4a99165d9833dcbf166753b6dc0/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4", size = 139398 }, - { url = "https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8", size = 140273 }, - { url = "https://files.pythonhosted.org/packages/07/07/7e554f2bbce3295e191f7e653ff15d55309a9ca40d0362fcdab36f01063c/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc", size = 142577 }, - { url = "https://files.pythonhosted.org/packages/d8/b5/eb705c313100defa57da79277d9207dc8d8e45931035862fa64b625bfead/charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae", size = 137747 }, - { url = "https://files.pythonhosted.org/packages/19/28/573147271fd041d351b438a5665be8223f1dd92f273713cb882ddafe214c/charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887", size = 143375 }, - { url = "https://files.pythonhosted.org/packages/cf/7c/f3b682fa053cc21373c9a839e6beba7705857075686a05c72e0f8c4980ca/charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae", size = 148474 }, - { url = "https://files.pythonhosted.org/packages/1e/49/7ab74d4ac537ece3bc3334ee08645e231f39f7d6df6347b29a74b0537103/charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce", size = 140232 }, - { url = "https://files.pythonhosted.org/packages/2d/dc/9dacba68c9ac0ae781d40e1a0c0058e26302ea0660e574ddf6797a0347f7/charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f", size = 140859 }, - { url = "https://files.pythonhosted.org/packages/6c/c2/4a583f800c0708dd22096298e49f887b49d9746d0e78bfc1d7e29816614c/charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab", size = 92509 }, - { url = "https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77", size = 99870 }, - { url = "https://files.pythonhosted.org/packages/d1/b2/fcedc8255ec42afee97f9e6f0145c734bbe104aac28300214593eb326f1d/charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8", size = 192892 }, - { url = "https://files.pythonhosted.org/packages/2e/7d/2259318c202f3d17f3fe6438149b3b9e706d1070fe3fcbb28049730bb25c/charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b", size = 122213 }, - { url = "https://files.pythonhosted.org/packages/3a/52/9f9d17c3b54dc238de384c4cb5a2ef0e27985b42a0e5cc8e8a31d918d48d/charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6", size = 119404 }, - { url = "https://files.pythonhosted.org/packages/99/b0/9c365f6d79a9f0f3c379ddb40a256a67aa69c59609608fe7feb6235896e1/charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a", size = 137275 }, - { url = "https://files.pythonhosted.org/packages/91/33/749df346e93d7a30cdcb90cbfdd41a06026317bfbfb62cd68307c1a3c543/charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389", size = 147518 }, - { url = "https://files.pythonhosted.org/packages/72/1a/641d5c9f59e6af4c7b53da463d07600a695b9824e20849cb6eea8a627761/charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa", size = 140182 }, - { url = "https://files.pythonhosted.org/packages/ee/fb/14d30eb4956408ee3ae09ad34299131fb383c47df355ddb428a7331cfa1e/charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b", size = 141869 }, - { url = "https://files.pythonhosted.org/packages/df/3e/a06b18788ca2eb6695c9b22325b6fde7dde0f1d1838b1792a0076f58fe9d/charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed", size = 144042 }, - { url = "https://files.pythonhosted.org/packages/45/59/3d27019d3b447a88fe7e7d004a1e04be220227760264cc41b405e863891b/charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26", size = 138275 }, - { url = "https://files.pythonhosted.org/packages/7b/ef/5eb105530b4da8ae37d506ccfa25057961b7b63d581def6f99165ea89c7e/charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d", size = 144819 }, - { url = "https://files.pythonhosted.org/packages/a2/51/e5023f937d7f307c948ed3e5c29c4b7a3e42ed2ee0b8cdf8f3a706089bf0/charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068", size = 149415 }, - { url = "https://files.pythonhosted.org/packages/24/9d/2e3ef673dfd5be0154b20363c5cdcc5606f35666544381bee15af3778239/charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143", size = 141212 }, - { url = "https://files.pythonhosted.org/packages/5b/ae/ce2c12fcac59cb3860b2e2d76dc405253a4475436b1861d95fe75bdea520/charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4", size = 142167 }, - { url = "https://files.pythonhosted.org/packages/ed/3a/a448bf035dce5da359daf9ae8a16b8a39623cc395a2ffb1620aa1bce62b0/charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7", size = 93041 }, - { url = "https://files.pythonhosted.org/packages/b6/7c/8debebb4f90174074b827c63242c23851bdf00a532489fba57fef3416e40/charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001", size = 100397 }, - { url = "https://files.pythonhosted.org/packages/28/76/e6222113b83e3622caa4bb41032d0b1bf785250607392e1b778aca0b8a7d/charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc", size = 48543 }, + { url = "https://files.pythonhosted.org/packages/2b/61/095a0aa1a84d1481998b534177c8566fdc50bb1233ea9a0478cd3cc075bd/charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3", size = 194219, upload_time = "2023-11-01T04:02:29.048Z" }, + { url = "https://files.pythonhosted.org/packages/cc/94/f7cf5e5134175de79ad2059edf2adce18e0685ebdb9227ff0139975d0e93/charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027", size = 122521, upload_time = "2023-11-01T04:02:32.452Z" }, + { url = "https://files.pythonhosted.org/packages/46/6a/d5c26c41c49b546860cc1acabdddf48b0b3fb2685f4f5617ac59261b44ae/charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03", size = 120383, upload_time = "2023-11-01T04:02:34.11Z" }, + { url = "https://files.pythonhosted.org/packages/b8/60/e2f67915a51be59d4539ed189eb0a2b0d292bf79270410746becb32bc2c3/charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d", size = 138223, upload_time = "2023-11-01T04:02:36.213Z" }, + { url = "https://files.pythonhosted.org/packages/05/8c/eb854996d5fef5e4f33ad56927ad053d04dc820e4a3d39023f35cad72617/charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e", size = 148101, upload_time = "2023-11-01T04:02:38.067Z" }, + { url = "https://files.pythonhosted.org/packages/f6/93/bb6cbeec3bf9da9b2eba458c15966658d1daa8b982c642f81c93ad9b40e1/charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6", size = 140699, upload_time = "2023-11-01T04:02:39.436Z" }, + { url = "https://files.pythonhosted.org/packages/da/f1/3702ba2a7470666a62fd81c58a4c40be00670e5006a67f4d626e57f013ae/charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5", size = 142065, upload_time = "2023-11-01T04:02:41.357Z" }, + { url = "https://files.pythonhosted.org/packages/3f/ba/3f5e7be00b215fa10e13d64b1f6237eb6ebea66676a41b2bcdd09fe74323/charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537", size = 144505, upload_time = "2023-11-01T04:02:43.108Z" }, + { url = "https://files.pythonhosted.org/packages/33/c3/3b96a435c5109dd5b6adc8a59ba1d678b302a97938f032e3770cc84cd354/charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c", size = 139425, upload_time = "2023-11-01T04:02:45.427Z" }, + { url = "https://files.pythonhosted.org/packages/43/05/3bf613e719efe68fb3a77f9c536a389f35b95d75424b96b426a47a45ef1d/charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12", size = 145287, upload_time = "2023-11-01T04:02:46.705Z" }, + { url = "https://files.pythonhosted.org/packages/58/78/a0bc646900994df12e07b4ae5c713f2b3e5998f58b9d3720cce2aa45652f/charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f", size = 149929, upload_time = "2023-11-01T04:02:48.098Z" }, + { url = "https://files.pythonhosted.org/packages/eb/5c/97d97248af4920bc68687d9c3b3c0f47c910e21a8ff80af4565a576bd2f0/charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269", size = 141605, upload_time = "2023-11-01T04:02:49.605Z" }, + { url = "https://files.pythonhosted.org/packages/a8/31/47d018ef89f95b8aded95c589a77c072c55e94b50a41aa99c0a2008a45a4/charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519", size = 142646, upload_time = "2023-11-01T04:02:51.35Z" }, + { url = "https://files.pythonhosted.org/packages/ae/d5/4fecf1d58bedb1340a50f165ba1c7ddc0400252d6832ff619c4568b36cc0/charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73", size = 92846, upload_time = "2023-11-01T04:02:52.679Z" }, + { url = "https://files.pythonhosted.org/packages/a2/a0/4af29e22cb5942488cf45630cbdd7cefd908768e69bdd90280842e4e8529/charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09", size = 100343, upload_time = "2023-11-01T04:02:53.915Z" }, + { url = "https://files.pythonhosted.org/packages/68/77/02839016f6fbbf808e8b38601df6e0e66c17bbab76dff4613f7511413597/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db", size = 191647, upload_time = "2023-11-01T04:02:55.329Z" }, + { url = "https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96", size = 121434, upload_time = "2023-11-01T04:02:57.173Z" }, + { url = "https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e", size = 118979, upload_time = "2023-11-01T04:02:58.442Z" }, + { url = "https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f", size = 136582, upload_time = "2023-11-01T04:02:59.776Z" }, + { url = "https://files.pythonhosted.org/packages/74/f1/0d9fe69ac441467b737ba7f48c68241487df2f4522dd7246d9426e7c690e/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574", size = 146645, upload_time = "2023-11-01T04:03:02.186Z" }, + { url = "https://files.pythonhosted.org/packages/05/31/e1f51c76db7be1d4aef220d29fbfa5dbb4a99165d9833dcbf166753b6dc0/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4", size = 139398, upload_time = "2023-11-01T04:03:04.255Z" }, + { url = "https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8", size = 140273, upload_time = "2023-11-01T04:03:05.983Z" }, + { url = "https://files.pythonhosted.org/packages/07/07/7e554f2bbce3295e191f7e653ff15d55309a9ca40d0362fcdab36f01063c/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc", size = 142577, upload_time = "2023-11-01T04:03:07.567Z" }, + { url = "https://files.pythonhosted.org/packages/d8/b5/eb705c313100defa57da79277d9207dc8d8e45931035862fa64b625bfead/charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae", size = 137747, upload_time = "2023-11-01T04:03:08.886Z" }, + { url = "https://files.pythonhosted.org/packages/19/28/573147271fd041d351b438a5665be8223f1dd92f273713cb882ddafe214c/charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887", size = 143375, upload_time = "2023-11-01T04:03:10.613Z" }, + { url = "https://files.pythonhosted.org/packages/cf/7c/f3b682fa053cc21373c9a839e6beba7705857075686a05c72e0f8c4980ca/charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae", size = 148474, upload_time = "2023-11-01T04:03:11.973Z" }, + { url = "https://files.pythonhosted.org/packages/1e/49/7ab74d4ac537ece3bc3334ee08645e231f39f7d6df6347b29a74b0537103/charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce", size = 140232, upload_time = "2023-11-01T04:03:13.505Z" }, + { url = "https://files.pythonhosted.org/packages/2d/dc/9dacba68c9ac0ae781d40e1a0c0058e26302ea0660e574ddf6797a0347f7/charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f", size = 140859, upload_time = "2023-11-01T04:03:17.362Z" }, + { url = "https://files.pythonhosted.org/packages/6c/c2/4a583f800c0708dd22096298e49f887b49d9746d0e78bfc1d7e29816614c/charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab", size = 92509, upload_time = "2023-11-01T04:03:21.453Z" }, + { url = "https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77", size = 99870, upload_time = "2023-11-01T04:03:22.723Z" }, + { url = "https://files.pythonhosted.org/packages/d1/b2/fcedc8255ec42afee97f9e6f0145c734bbe104aac28300214593eb326f1d/charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8", size = 192892, upload_time = "2023-11-01T04:03:24.135Z" }, + { url = "https://files.pythonhosted.org/packages/2e/7d/2259318c202f3d17f3fe6438149b3b9e706d1070fe3fcbb28049730bb25c/charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b", size = 122213, upload_time = "2023-11-01T04:03:25.66Z" }, + { url = "https://files.pythonhosted.org/packages/3a/52/9f9d17c3b54dc238de384c4cb5a2ef0e27985b42a0e5cc8e8a31d918d48d/charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6", size = 119404, upload_time = "2023-11-01T04:03:27.04Z" }, + { url = "https://files.pythonhosted.org/packages/99/b0/9c365f6d79a9f0f3c379ddb40a256a67aa69c59609608fe7feb6235896e1/charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a", size = 137275, upload_time = "2023-11-01T04:03:28.466Z" }, + { url = "https://files.pythonhosted.org/packages/91/33/749df346e93d7a30cdcb90cbfdd41a06026317bfbfb62cd68307c1a3c543/charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389", size = 147518, upload_time = "2023-11-01T04:03:29.82Z" }, + { url = "https://files.pythonhosted.org/packages/72/1a/641d5c9f59e6af4c7b53da463d07600a695b9824e20849cb6eea8a627761/charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa", size = 140182, upload_time = "2023-11-01T04:03:31.511Z" }, + { url = "https://files.pythonhosted.org/packages/ee/fb/14d30eb4956408ee3ae09ad34299131fb383c47df355ddb428a7331cfa1e/charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b", size = 141869, upload_time = "2023-11-01T04:03:32.887Z" }, + { url = "https://files.pythonhosted.org/packages/df/3e/a06b18788ca2eb6695c9b22325b6fde7dde0f1d1838b1792a0076f58fe9d/charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed", size = 144042, upload_time = "2023-11-01T04:03:34.412Z" }, + { url = "https://files.pythonhosted.org/packages/45/59/3d27019d3b447a88fe7e7d004a1e04be220227760264cc41b405e863891b/charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26", size = 138275, upload_time = "2023-11-01T04:03:35.759Z" }, + { url = "https://files.pythonhosted.org/packages/7b/ef/5eb105530b4da8ae37d506ccfa25057961b7b63d581def6f99165ea89c7e/charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d", size = 144819, upload_time = "2023-11-01T04:03:37.216Z" }, + { url = "https://files.pythonhosted.org/packages/a2/51/e5023f937d7f307c948ed3e5c29c4b7a3e42ed2ee0b8cdf8f3a706089bf0/charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068", size = 149415, upload_time = "2023-11-01T04:03:38.694Z" }, + { url = "https://files.pythonhosted.org/packages/24/9d/2e3ef673dfd5be0154b20363c5cdcc5606f35666544381bee15af3778239/charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143", size = 141212, upload_time = "2023-11-01T04:03:40.07Z" }, + { url = "https://files.pythonhosted.org/packages/5b/ae/ce2c12fcac59cb3860b2e2d76dc405253a4475436b1861d95fe75bdea520/charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4", size = 142167, upload_time = "2023-11-01T04:03:41.491Z" }, + { url = "https://files.pythonhosted.org/packages/ed/3a/a448bf035dce5da359daf9ae8a16b8a39623cc395a2ffb1620aa1bce62b0/charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7", size = 93041, upload_time = "2023-11-01T04:03:42.836Z" }, + { url = "https://files.pythonhosted.org/packages/b6/7c/8debebb4f90174074b827c63242c23851bdf00a532489fba57fef3416e40/charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001", size = 100397, upload_time = "2023-11-01T04:03:44.467Z" }, + { url = "https://files.pythonhosted.org/packages/28/76/e6222113b83e3622caa4bb41032d0b1bf785250607392e1b778aca0b8a7d/charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc", size = 48543, upload_time = "2023-11-01T04:04:58.622Z" }, ] [[package]] @@ -309,18 +318,18 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 } +sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121, upload_time = "2023-08-17T17:29:11.868Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", size = 97941 }, + { url = "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", size = 97941, upload_time = "2023-08-17T17:29:10.08Z" }, ] [[package]] name = "colorama" version = "0.4.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload_time = "2022-10-25T02:36:22.414Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload_time = "2022-10-25T02:36:20.889Z" }, ] [[package]] @@ -330,18 +339,18 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "humanfriendly" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/cc/c7/eed8f27100517e8c0e6b923d5f0845d0cb99763da6fdee00478f91db7325/coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0", size = 278520 } +sdist = { url = "https://files.pythonhosted.org/packages/cc/c7/eed8f27100517e8c0e6b923d5f0845d0cb99763da6fdee00478f91db7325/coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0", size = 278520, upload_time = "2021-06-11T10:22:45.202Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/06/3d6badcf13db419e25b07041d9c7b4a2c331d3f4e7134445ec5df57714cd/coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934", size = 46018 }, + { url = "https://files.pythonhosted.org/packages/a7/06/3d6badcf13db419e25b07041d9c7b4a2c331d3f4e7134445ec5df57714cd/coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934", size = 46018, upload_time = "2021-06-11T10:22:42.561Z" }, ] [[package]] name = "configargparse" version = "1.7" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/70/8a/73f1008adfad01cb923255b924b1528727b8270e67cb4ef41eabdc7d783e/ConfigArgParse-1.7.tar.gz", hash = "sha256:e7067471884de5478c58a511e529f0f9bd1c66bfef1dea90935438d6c23306d1", size = 43817 } +sdist = { url = "https://files.pythonhosted.org/packages/70/8a/73f1008adfad01cb923255b924b1528727b8270e67cb4ef41eabdc7d783e/ConfigArgParse-1.7.tar.gz", hash = "sha256:e7067471884de5478c58a511e529f0f9bd1c66bfef1dea90935438d6c23306d1", size = 43817, upload_time = "2023-07-23T16:20:04.95Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6f/b3/b4ac838711fd74a2b4e6f746703cf9dd2cf5462d17dac07e349234e21b97/ConfigArgParse-1.7-py3-none-any.whl", hash = "sha256:d249da6591465c6c26df64a9f73d2536e743be2f244eb3ebe61114af2f94f86b", size = 25489 }, + { url = "https://files.pythonhosted.org/packages/6f/b3/b4ac838711fd74a2b4e6f746703cf9dd2cf5462d17dac07e349234e21b97/ConfigArgParse-1.7-py3-none-any.whl", hash = "sha256:d249da6591465c6c26df64a9f73d2536e743be2f244eb3ebe61114af2f94f86b", size = 25489, upload_time = "2023-07-23T16:20:03.27Z" }, ] [[package]] @@ -351,97 +360,97 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/11/a3/48ddc7ae832b000952cf4be64452381d150a41a2299c2eb19237168528d1/contourpy-1.2.0.tar.gz", hash = "sha256:171f311cb758de7da13fc53af221ae47a5877be5a0843a9fe150818c51ed276a", size = 13455881 } +sdist = { url = "https://files.pythonhosted.org/packages/11/a3/48ddc7ae832b000952cf4be64452381d150a41a2299c2eb19237168528d1/contourpy-1.2.0.tar.gz", hash = "sha256:171f311cb758de7da13fc53af221ae47a5877be5a0843a9fe150818c51ed276a", size = 13455881, upload_time = "2023-11-03T17:01:03.144Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e8/ea/f6e90933d82cc5aacf52f886a1c01f47f96eba99108ca2929c7b3ef45f82/contourpy-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0274c1cb63625972c0c007ab14dd9ba9e199c36ae1a231ce45d725cbcbfd10a8", size = 256873 }, - { url = "https://files.pythonhosted.org/packages/fe/26/43821d61b7ee62c1809ec852bc572aaf4c27f101ebcebbbcce29a5ee0445/contourpy-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ab459a1cbbf18e8698399c595a01f6dcc5c138220ca3ea9e7e6126232d102bb4", size = 242211 }, - { url = "https://files.pythonhosted.org/packages/9b/99/c8fb63072a7573fe7682e1786a021f29f9c5f660a3aafcdce80b9ee8348d/contourpy-1.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fdd887f17c2f4572ce548461e4f96396681212d858cae7bd52ba3310bc6f00f", size = 293195 }, - { url = "https://files.pythonhosted.org/packages/c7/a7/ae0b4bb8e0c865270d02ee619981413996dc10ddf1fd2689c938173ff62f/contourpy-1.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d16edfc3fc09968e09ddffada434b3bf989bf4911535e04eada58469873e28e", size = 332279 }, - { url = "https://files.pythonhosted.org/packages/94/7c/682228b9085ff323fb7e946fe139072e5f21b71360cf91f36ea079d4ea95/contourpy-1.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c203f617abc0dde5792beb586f827021069fb6d403d7f4d5c2b543d87edceb9", size = 305326 }, - { url = "https://files.pythonhosted.org/packages/58/56/e2c43dcfa1f9c7db4d5e3d6f5134b24ed953f4e2133a4b12f0062148db58/contourpy-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b69303ceb2e4d4f146bf82fda78891ef7bcd80c41bf16bfca3d0d7eb545448aa", size = 310732 }, - { url = "https://files.pythonhosted.org/packages/94/0b/8495c4582057abc8377f945f6e11a86f1c07ad7b32fd4fdc968478cd0324/contourpy-1.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:884c3f9d42d7218304bc74a8a7693d172685c84bd7ab2bab1ee567b769696df9", size = 803420 }, - { url = "https://files.pythonhosted.org/packages/d5/1f/40399c7da649297147d404aedaa675cc60018f48ad284630c0d1406133e3/contourpy-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4a1b1208102be6e851f20066bf0e7a96b7d48a07c9b0cfe6d0d4545c2f6cadab", size = 829204 }, - { url = "https://files.pythonhosted.org/packages/8b/01/4be433b60dce7cbce8315cbcdfc016e7d25430a8b94e272355dff79cc3a8/contourpy-1.2.0-cp310-cp310-win32.whl", hash = "sha256:34b9071c040d6fe45d9826cbbe3727d20d83f1b6110d219b83eb0e2a01d79488", size = 165434 }, - { url = "https://files.pythonhosted.org/packages/fd/7c/168f8343f33d861305e18c56901ef1bb675d3c7f977f435ec72751a71a54/contourpy-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:bd2f1ae63998da104f16a8b788f685e55d65760cd1929518fd94cd682bf03e41", size = 186652 }, - { url = "https://files.pythonhosted.org/packages/9b/54/1dafec3c84df1d29119037330f7289db84a679cb2d5283af4ef24d89f532/contourpy-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dd10c26b4eadae44783c45ad6655220426f971c61d9b239e6f7b16d5cdaaa727", size = 258243 }, - { url = "https://files.pythonhosted.org/packages/5b/ac/26fa1057f62beaa2af4c55c6ac733b114a403b746cfe0ce3dc6e4aec921a/contourpy-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5c6b28956b7b232ae801406e529ad7b350d3f09a4fde958dfdf3c0520cdde0dd", size = 243408 }, - { url = "https://files.pythonhosted.org/packages/b7/33/cd0ecc80123f499d76d2fe2807cb4d5638ef8730735c580c8a8a03e1928e/contourpy-1.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebeac59e9e1eb4b84940d076d9f9a6cec0064e241818bcb6e32124cc5c3e377a", size = 294142 }, - { url = "https://files.pythonhosted.org/packages/6d/75/1b7bf20bf6394e01df2c4b4b3d44d3dc280c16ddaff72724639100bd4314/contourpy-1.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:139d8d2e1c1dd52d78682f505e980f592ba53c9f73bd6be102233e358b401063", size = 333129 }, - { url = "https://files.pythonhosted.org/packages/22/5b/fedd961dff1877e5d3b83c5201295cfdcdc2438884c2851aa7ecf6cec045/contourpy-1.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e9dc350fb4c58adc64df3e0703ab076f60aac06e67d48b3848c23647ae4310e", size = 307461 }, - { url = "https://files.pythonhosted.org/packages/e2/83/29a63bbc72839cc6b24b5a0e3d004d4ed4e8439f26460ad9a34e39251904/contourpy-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18fc2b4ed8e4a8fe849d18dce4bd3c7ea637758c6343a1f2bae1e9bd4c9f4686", size = 313352 }, - { url = "https://files.pythonhosted.org/packages/4b/c7/4bac0fc4f1e802ab47e75076d83d2e1448e0668ba6cc9000cf4e9d5bd94a/contourpy-1.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:16a7380e943a6d52472096cb7ad5264ecee36ed60888e2a3d3814991a0107286", size = 804127 }, - { url = "https://files.pythonhosted.org/packages/e3/47/b3fd5bdc2f6ec13502d57a5bc390ffe62648605ed1689c93b0015150a784/contourpy-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8d8faf05be5ec8e02a4d86f616fc2a0322ff4a4ce26c0f09d9f7fb5330a35c95", size = 829561 }, - { url = "https://files.pythonhosted.org/packages/5c/04/be16038e754169caea4d02d82f8e5cd97dece593e5ac9e05735da0afd0c5/contourpy-1.2.0-cp311-cp311-win32.whl", hash = "sha256:67b7f17679fa62ec82b7e3e611c43a016b887bd64fb933b3ae8638583006c6d6", size = 166197 }, - { url = "https://files.pythonhosted.org/packages/ca/2a/d197a412ec474391ee878b1218cf2fe9c6e963903755887fc5654c06636a/contourpy-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:99ad97258985328b4f207a5e777c1b44a83bfe7cf1f87b99f9c11d4ee477c4de", size = 187556 }, - { url = "https://files.pythonhosted.org/packages/4f/03/839da46999173226bead08794cbd7b4d37c9e6b02686ca74c93556b43258/contourpy-1.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:575bcaf957a25d1194903a10bc9f316c136c19f24e0985a2b9b5608bdf5dbfe0", size = 259253 }, - { url = "https://files.pythonhosted.org/packages/f3/9e/8fb3f53144269d3fecdd8786d3a4686eeff55b9b35a3c0772a3f62f71e36/contourpy-1.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9e6c93b5b2dbcedad20a2f18ec22cae47da0d705d454308063421a3b290d9ea4", size = 242555 }, - { url = "https://files.pythonhosted.org/packages/a6/85/9815ccb5a18ee8c9a46bd5ef20d02b292cd4a99c62553f38c87015f16d59/contourpy-1.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:464b423bc2a009088f19bdf1f232299e8b6917963e2b7e1d277da5041f33a779", size = 288108 }, - { url = "https://files.pythonhosted.org/packages/5a/d9/4df5c26bd0f496c8cd7940fd53db95d07deeb98518f02f805ce570590da8/contourpy-1.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:68ce4788b7d93e47f84edd3f1f95acdcd142ae60bc0e5493bfd120683d2d4316", size = 330810 }, - { url = "https://files.pythonhosted.org/packages/67/d4/8aae9793a0cfde72959312521ebd3aa635c260c3d580448e8db6bdcdd1aa/contourpy-1.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d7d1f8871998cdff5d2ff6a087e5e1780139abe2838e85b0b46b7ae6cc25399", size = 305290 }, - { url = "https://files.pythonhosted.org/packages/20/84/ffddcdcc579cbf7213fd92a3578ca08a931a3bf879a22deb5a83ffc5002c/contourpy-1.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e739530c662a8d6d42c37c2ed52a6f0932c2d4a3e8c1f90692ad0ce1274abe0", size = 303937 }, - { url = "https://files.pythonhosted.org/packages/d8/ad/6e570cf525f909da94559ed716189f92f529bc7b5f78645733c44619a0e2/contourpy-1.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:247b9d16535acaa766d03037d8e8fb20866d054d3c7fbf6fd1f993f11fc60ca0", size = 801977 }, - { url = "https://files.pythonhosted.org/packages/36/b4/55f23482c596eca36d16fc668b147865c56fcf90353f4c57f073d8d5e532/contourpy-1.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:461e3ae84cd90b30f8d533f07d87c00379644205b1d33a5ea03381edc4b69431", size = 827442 }, - { url = "https://files.pythonhosted.org/packages/e9/47/9c081b1f11d6053cb0aa4c46b7de2ea2849a4a8d40de81c7bc3f99773b02/contourpy-1.2.0-cp312-cp312-win32.whl", hash = "sha256:1c2559d6cffc94890b0529ea7eeecc20d6fadc1539273aa27faf503eb4656d8f", size = 165363 }, - { url = "https://files.pythonhosted.org/packages/8e/ae/a6353db548bff1a592b85ae6bb80275f0a51dc25a0410d059e5b33183e36/contourpy-1.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:491b1917afdd8638a05b611a56d46587d5a632cabead889a5440f7c638bc6ed9", size = 187731 }, + { url = "https://files.pythonhosted.org/packages/e8/ea/f6e90933d82cc5aacf52f886a1c01f47f96eba99108ca2929c7b3ef45f82/contourpy-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0274c1cb63625972c0c007ab14dd9ba9e199c36ae1a231ce45d725cbcbfd10a8", size = 256873, upload_time = "2023-11-03T16:56:34.548Z" }, + { url = "https://files.pythonhosted.org/packages/fe/26/43821d61b7ee62c1809ec852bc572aaf4c27f101ebcebbbcce29a5ee0445/contourpy-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ab459a1cbbf18e8698399c595a01f6dcc5c138220ca3ea9e7e6126232d102bb4", size = 242211, upload_time = "2023-11-03T16:56:38.028Z" }, + { url = "https://files.pythonhosted.org/packages/9b/99/c8fb63072a7573fe7682e1786a021f29f9c5f660a3aafcdce80b9ee8348d/contourpy-1.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fdd887f17c2f4572ce548461e4f96396681212d858cae7bd52ba3310bc6f00f", size = 293195, upload_time = "2023-11-03T16:56:41.598Z" }, + { url = "https://files.pythonhosted.org/packages/c7/a7/ae0b4bb8e0c865270d02ee619981413996dc10ddf1fd2689c938173ff62f/contourpy-1.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d16edfc3fc09968e09ddffada434b3bf989bf4911535e04eada58469873e28e", size = 332279, upload_time = "2023-11-03T16:56:46.08Z" }, + { url = "https://files.pythonhosted.org/packages/94/7c/682228b9085ff323fb7e946fe139072e5f21b71360cf91f36ea079d4ea95/contourpy-1.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c203f617abc0dde5792beb586f827021069fb6d403d7f4d5c2b543d87edceb9", size = 305326, upload_time = "2023-11-03T16:56:49.647Z" }, + { url = "https://files.pythonhosted.org/packages/58/56/e2c43dcfa1f9c7db4d5e3d6f5134b24ed953f4e2133a4b12f0062148db58/contourpy-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b69303ceb2e4d4f146bf82fda78891ef7bcd80c41bf16bfca3d0d7eb545448aa", size = 310732, upload_time = "2023-11-03T16:56:53.773Z" }, + { url = "https://files.pythonhosted.org/packages/94/0b/8495c4582057abc8377f945f6e11a86f1c07ad7b32fd4fdc968478cd0324/contourpy-1.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:884c3f9d42d7218304bc74a8a7693d172685c84bd7ab2bab1ee567b769696df9", size = 803420, upload_time = "2023-11-03T16:57:00.669Z" }, + { url = "https://files.pythonhosted.org/packages/d5/1f/40399c7da649297147d404aedaa675cc60018f48ad284630c0d1406133e3/contourpy-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4a1b1208102be6e851f20066bf0e7a96b7d48a07c9b0cfe6d0d4545c2f6cadab", size = 829204, upload_time = "2023-11-03T16:57:07.813Z" }, + { url = "https://files.pythonhosted.org/packages/8b/01/4be433b60dce7cbce8315cbcdfc016e7d25430a8b94e272355dff79cc3a8/contourpy-1.2.0-cp310-cp310-win32.whl", hash = "sha256:34b9071c040d6fe45d9826cbbe3727d20d83f1b6110d219b83eb0e2a01d79488", size = 165434, upload_time = "2023-11-03T16:57:10.601Z" }, + { url = "https://files.pythonhosted.org/packages/fd/7c/168f8343f33d861305e18c56901ef1bb675d3c7f977f435ec72751a71a54/contourpy-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:bd2f1ae63998da104f16a8b788f685e55d65760cd1929518fd94cd682bf03e41", size = 186652, upload_time = "2023-11-03T16:57:13.57Z" }, + { url = "https://files.pythonhosted.org/packages/9b/54/1dafec3c84df1d29119037330f7289db84a679cb2d5283af4ef24d89f532/contourpy-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dd10c26b4eadae44783c45ad6655220426f971c61d9b239e6f7b16d5cdaaa727", size = 258243, upload_time = "2023-11-03T16:57:16.604Z" }, + { url = "https://files.pythonhosted.org/packages/5b/ac/26fa1057f62beaa2af4c55c6ac733b114a403b746cfe0ce3dc6e4aec921a/contourpy-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5c6b28956b7b232ae801406e529ad7b350d3f09a4fde958dfdf3c0520cdde0dd", size = 243408, upload_time = "2023-11-03T16:57:20.021Z" }, + { url = "https://files.pythonhosted.org/packages/b7/33/cd0ecc80123f499d76d2fe2807cb4d5638ef8730735c580c8a8a03e1928e/contourpy-1.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebeac59e9e1eb4b84940d076d9f9a6cec0064e241818bcb6e32124cc5c3e377a", size = 294142, upload_time = "2023-11-03T16:57:23.48Z" }, + { url = "https://files.pythonhosted.org/packages/6d/75/1b7bf20bf6394e01df2c4b4b3d44d3dc280c16ddaff72724639100bd4314/contourpy-1.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:139d8d2e1c1dd52d78682f505e980f592ba53c9f73bd6be102233e358b401063", size = 333129, upload_time = "2023-11-03T16:57:27.141Z" }, + { url = "https://files.pythonhosted.org/packages/22/5b/fedd961dff1877e5d3b83c5201295cfdcdc2438884c2851aa7ecf6cec045/contourpy-1.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e9dc350fb4c58adc64df3e0703ab076f60aac06e67d48b3848c23647ae4310e", size = 307461, upload_time = "2023-11-03T16:57:30.537Z" }, + { url = "https://files.pythonhosted.org/packages/e2/83/29a63bbc72839cc6b24b5a0e3d004d4ed4e8439f26460ad9a34e39251904/contourpy-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18fc2b4ed8e4a8fe849d18dce4bd3c7ea637758c6343a1f2bae1e9bd4c9f4686", size = 313352, upload_time = "2023-11-03T16:57:34.937Z" }, + { url = "https://files.pythonhosted.org/packages/4b/c7/4bac0fc4f1e802ab47e75076d83d2e1448e0668ba6cc9000cf4e9d5bd94a/contourpy-1.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:16a7380e943a6d52472096cb7ad5264ecee36ed60888e2a3d3814991a0107286", size = 804127, upload_time = "2023-11-03T16:57:42.201Z" }, + { url = "https://files.pythonhosted.org/packages/e3/47/b3fd5bdc2f6ec13502d57a5bc390ffe62648605ed1689c93b0015150a784/contourpy-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8d8faf05be5ec8e02a4d86f616fc2a0322ff4a4ce26c0f09d9f7fb5330a35c95", size = 829561, upload_time = "2023-11-03T16:57:49.667Z" }, + { url = "https://files.pythonhosted.org/packages/5c/04/be16038e754169caea4d02d82f8e5cd97dece593e5ac9e05735da0afd0c5/contourpy-1.2.0-cp311-cp311-win32.whl", hash = "sha256:67b7f17679fa62ec82b7e3e611c43a016b887bd64fb933b3ae8638583006c6d6", size = 166197, upload_time = "2023-11-03T16:57:52.682Z" }, + { url = "https://files.pythonhosted.org/packages/ca/2a/d197a412ec474391ee878b1218cf2fe9c6e963903755887fc5654c06636a/contourpy-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:99ad97258985328b4f207a5e777c1b44a83bfe7cf1f87b99f9c11d4ee477c4de", size = 187556, upload_time = "2023-11-03T16:57:55.286Z" }, + { url = "https://files.pythonhosted.org/packages/4f/03/839da46999173226bead08794cbd7b4d37c9e6b02686ca74c93556b43258/contourpy-1.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:575bcaf957a25d1194903a10bc9f316c136c19f24e0985a2b9b5608bdf5dbfe0", size = 259253, upload_time = "2023-11-03T16:57:58.572Z" }, + { url = "https://files.pythonhosted.org/packages/f3/9e/8fb3f53144269d3fecdd8786d3a4686eeff55b9b35a3c0772a3f62f71e36/contourpy-1.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9e6c93b5b2dbcedad20a2f18ec22cae47da0d705d454308063421a3b290d9ea4", size = 242555, upload_time = "2023-11-03T16:58:01.48Z" }, + { url = "https://files.pythonhosted.org/packages/a6/85/9815ccb5a18ee8c9a46bd5ef20d02b292cd4a99c62553f38c87015f16d59/contourpy-1.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:464b423bc2a009088f19bdf1f232299e8b6917963e2b7e1d277da5041f33a779", size = 288108, upload_time = "2023-11-03T16:58:05.546Z" }, + { url = "https://files.pythonhosted.org/packages/5a/d9/4df5c26bd0f496c8cd7940fd53db95d07deeb98518f02f805ce570590da8/contourpy-1.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:68ce4788b7d93e47f84edd3f1f95acdcd142ae60bc0e5493bfd120683d2d4316", size = 330810, upload_time = "2023-11-03T16:58:09.568Z" }, + { url = "https://files.pythonhosted.org/packages/67/d4/8aae9793a0cfde72959312521ebd3aa635c260c3d580448e8db6bdcdd1aa/contourpy-1.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d7d1f8871998cdff5d2ff6a087e5e1780139abe2838e85b0b46b7ae6cc25399", size = 305290, upload_time = "2023-11-03T16:58:13.017Z" }, + { url = "https://files.pythonhosted.org/packages/20/84/ffddcdcc579cbf7213fd92a3578ca08a931a3bf879a22deb5a83ffc5002c/contourpy-1.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e739530c662a8d6d42c37c2ed52a6f0932c2d4a3e8c1f90692ad0ce1274abe0", size = 303937, upload_time = "2023-11-03T16:58:16.426Z" }, + { url = "https://files.pythonhosted.org/packages/d8/ad/6e570cf525f909da94559ed716189f92f529bc7b5f78645733c44619a0e2/contourpy-1.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:247b9d16535acaa766d03037d8e8fb20866d054d3c7fbf6fd1f993f11fc60ca0", size = 801977, upload_time = "2023-11-03T16:58:23.539Z" }, + { url = "https://files.pythonhosted.org/packages/36/b4/55f23482c596eca36d16fc668b147865c56fcf90353f4c57f073d8d5e532/contourpy-1.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:461e3ae84cd90b30f8d533f07d87c00379644205b1d33a5ea03381edc4b69431", size = 827442, upload_time = "2023-11-03T16:58:30.724Z" }, + { url = "https://files.pythonhosted.org/packages/e9/47/9c081b1f11d6053cb0aa4c46b7de2ea2849a4a8d40de81c7bc3f99773b02/contourpy-1.2.0-cp312-cp312-win32.whl", hash = "sha256:1c2559d6cffc94890b0529ea7eeecc20d6fadc1539273aa27faf503eb4656d8f", size = 165363, upload_time = "2023-11-03T16:58:33.54Z" }, + { url = "https://files.pythonhosted.org/packages/8e/ae/a6353db548bff1a592b85ae6bb80275f0a51dc25a0410d059e5b33183e36/contourpy-1.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:491b1917afdd8638a05b611a56d46587d5a632cabead889a5440f7c638bc6ed9", size = 187731, upload_time = "2023-11-03T16:58:36.585Z" }, ] [[package]] name = "coverage" version = "7.6.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/52/12/3669b6382792783e92046730ad3327f53b2726f0603f4c311c4da4824222/coverage-7.6.4.tar.gz", hash = "sha256:29fc0f17b1d3fea332f8001d4558f8214af7f1d87a345f3a133c901d60347c73", size = 798716 } +sdist = { url = "https://files.pythonhosted.org/packages/52/12/3669b6382792783e92046730ad3327f53b2726f0603f4c311c4da4824222/coverage-7.6.4.tar.gz", hash = "sha256:29fc0f17b1d3fea332f8001d4558f8214af7f1d87a345f3a133c901d60347c73", size = 798716, upload_time = "2024-10-20T22:57:39.682Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a5/93/4ad92f71e28ece5c0326e5f4a6630aa4928a8846654a65cfff69b49b95b9/coverage-7.6.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f8ae553cba74085db385d489c7a792ad66f7f9ba2ee85bfa508aeb84cf0ba07", size = 206713 }, - { url = "https://files.pythonhosted.org/packages/01/ae/747a580b1eda3f2e431d87de48f0604bd7bc92e52a1a95185a4aa585bc47/coverage-7.6.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8165b796df0bd42e10527a3f493c592ba494f16ef3c8b531288e3d0d72c1f6f0", size = 207149 }, - { url = "https://files.pythonhosted.org/packages/07/1a/1f573f8a6145f6d4c9130bbc120e0024daf1b24cf2a78d7393fa6eb6aba7/coverage-7.6.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7c8b95bf47db6d19096a5e052ffca0a05f335bc63cef281a6e8fe864d450a72", size = 235584 }, - { url = "https://files.pythonhosted.org/packages/40/42/c8523f2e4db34aa9389caee0d3688b6ada7a84fcc782e943a868a7f302bd/coverage-7.6.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ed9281d1b52628e81393f5eaee24a45cbd64965f41857559c2b7ff19385df51", size = 233486 }, - { url = "https://files.pythonhosted.org/packages/8d/95/565c310fffa16ede1a042e9ea1ca3962af0d8eb5543bc72df6b91dc0c3d5/coverage-7.6.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0809082ee480bb8f7416507538243c8863ac74fd8a5d2485c46f0f7499f2b491", size = 234649 }, - { url = "https://files.pythonhosted.org/packages/d5/81/3b550674d98968ec29c92e3e8650682be6c8b1fa7581a059e7e12e74c431/coverage-7.6.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d541423cdd416b78626b55f123412fcf979d22a2c39fce251b350de38c15c15b", size = 233744 }, - { url = "https://files.pythonhosted.org/packages/0d/70/d66c7f51b3e33aabc5ea9f9624c1c9d9655472962270eb5e7b0d32707224/coverage-7.6.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:58809e238a8a12a625c70450b48e8767cff9eb67c62e6154a642b21ddf79baea", size = 232204 }, - { url = "https://files.pythonhosted.org/packages/23/2d/2b3a2dbed7a5f40693404c8a09e779d7c1a5fbed089d3e7224c002129ec8/coverage-7.6.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c9b8e184898ed014884ca84c70562b4a82cbc63b044d366fedc68bc2b2f3394a", size = 233335 }, - { url = "https://files.pythonhosted.org/packages/5a/4f/92d1d2ad720d698a4e71c176eacf531bfb8e0721d5ad560556f2c484a513/coverage-7.6.4-cp310-cp310-win32.whl", hash = "sha256:6bd818b7ea14bc6e1f06e241e8234508b21edf1b242d49831831a9450e2f35fa", size = 209435 }, - { url = "https://files.pythonhosted.org/packages/c7/b9/cdf158e7991e2287bcf9082670928badb73d310047facac203ff8dcd5ff3/coverage-7.6.4-cp310-cp310-win_amd64.whl", hash = "sha256:06babbb8f4e74b063dbaeb74ad68dfce9186c595a15f11f5d5683f748fa1d172", size = 210243 }, - { url = "https://files.pythonhosted.org/packages/87/31/9c0cf84f0dfcbe4215b7eb95c31777cdc0483c13390e69584c8150c85175/coverage-7.6.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:73d2b73584446e66ee633eaad1a56aad577c077f46c35ca3283cd687b7715b0b", size = 206819 }, - { url = "https://files.pythonhosted.org/packages/53/ed/a38401079ad320ad6e054a01ec2b61d270511aeb3c201c80e99c841229d5/coverage-7.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:51b44306032045b383a7a8a2c13878de375117946d68dcb54308111f39775a25", size = 207263 }, - { url = "https://files.pythonhosted.org/packages/20/e7/c3ad33b179ab4213f0d70da25a9c214d52464efa11caeab438592eb1d837/coverage-7.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b3fb02fe73bed561fa12d279a417b432e5b50fe03e8d663d61b3d5990f29546", size = 239205 }, - { url = "https://files.pythonhosted.org/packages/36/91/fc02e8d8e694f557752120487fd982f654ba1421bbaa5560debf96ddceda/coverage-7.6.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed8fe9189d2beb6edc14d3ad19800626e1d9f2d975e436f84e19efb7fa19469b", size = 236612 }, - { url = "https://files.pythonhosted.org/packages/cc/57/cb08f0eda0389a9a8aaa4fc1f9fec7ac361c3e2d68efd5890d7042c18aa3/coverage-7.6.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b369ead6527d025a0fe7bd3864e46dbee3aa8f652d48df6174f8d0bac9e26e0e", size = 238479 }, - { url = "https://files.pythonhosted.org/packages/d5/c9/2c7681a9b3ca6e6f43d489c2e6653a53278ed857fd6e7010490c307b0a47/coverage-7.6.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ade3ca1e5f0ff46b678b66201f7ff477e8fa11fb537f3b55c3f0568fbfe6e718", size = 237405 }, - { url = "https://files.pythonhosted.org/packages/b5/4e/ebfc6944b96317df8b537ae875d2e57c27b84eb98820bc0a1055f358f056/coverage-7.6.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:27fb4a050aaf18772db513091c9c13f6cb94ed40eacdef8dad8411d92d9992db", size = 236038 }, - { url = "https://files.pythonhosted.org/packages/13/f2/3a0bf1841a97c0654905e2ef531170f02c89fad2555879db8fe41a097871/coverage-7.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4f704f0998911abf728a7783799444fcbbe8261c4a6c166f667937ae6a8aa522", size = 236812 }, - { url = "https://files.pythonhosted.org/packages/b9/9c/66bf59226b52ce6ed9541b02d33e80a6e816a832558fbdc1111a7bd3abd4/coverage-7.6.4-cp311-cp311-win32.whl", hash = "sha256:29155cd511ee058e260db648b6182c419422a0d2e9a4fa44501898cf918866cf", size = 209400 }, - { url = "https://files.pythonhosted.org/packages/2a/a0/b0790934c04dfc8d658d4a62acb8f7ca0efdf3818456fcad757b11c6479d/coverage-7.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:8902dd6a30173d4ef09954bfcb24b5d7b5190cf14a43170e386979651e09ba19", size = 210243 }, - { url = "https://files.pythonhosted.org/packages/7d/e7/9291de916d084f41adddfd4b82246e68d61d6a75747f075f7e64628998d2/coverage-7.6.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12394842a3a8affa3ba62b0d4ab7e9e210c5e366fbac3e8b2a68636fb19892c2", size = 207013 }, - { url = "https://files.pythonhosted.org/packages/27/03/932c2c5717a7fa80cd43c6a07d3177076d97b79f12f40f882f9916db0063/coverage-7.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b6b4c83d8e8ea79f27ab80778c19bc037759aea298da4b56621f4474ffeb117", size = 207251 }, - { url = "https://files.pythonhosted.org/packages/d5/3f/0af47dcb9327f65a45455fbca846fe96eb57c153af46c4754a3ba678938a/coverage-7.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d5b8007f81b88696d06f7df0cb9af0d3b835fe0c8dbf489bad70b45f0e45613", size = 240268 }, - { url = "https://files.pythonhosted.org/packages/8a/3c/37a9d81bbd4b23bc7d46ca820e16174c613579c66342faa390a271d2e18b/coverage-7.6.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b57b768feb866f44eeed9f46975f3d6406380275c5ddfe22f531a2bf187eda27", size = 237298 }, - { url = "https://files.pythonhosted.org/packages/c0/70/6b0627e5bd68204ee580126ed3513140b2298995c1233bd67404b4e44d0e/coverage-7.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5915fcdec0e54ee229926868e9b08586376cae1f5faa9bbaf8faf3561b393d52", size = 239367 }, - { url = "https://files.pythonhosted.org/packages/3c/eb/634d7dfab24ac3b790bebaf9da0f4a5352cbc125ce6a9d5c6cf4c6cae3c7/coverage-7.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b58c672d14f16ed92a48db984612f5ce3836ae7d72cdd161001cc54512571f2", size = 238853 }, - { url = "https://files.pythonhosted.org/packages/d9/0d/8e3ed00f1266ef7472a4e33458f42e39492e01a64281084fb3043553d3f1/coverage-7.6.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2fdef0d83a2d08d69b1f2210a93c416d54e14d9eb398f6ab2f0a209433db19e1", size = 237160 }, - { url = "https://files.pythonhosted.org/packages/ce/9c/4337f468ef0ab7a2e0887a9c9da0e58e2eada6fc6cbee637a4acd5dfd8a9/coverage-7.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cf717ee42012be8c0cb205dbbf18ffa9003c4cbf4ad078db47b95e10748eec5", size = 238824 }, - { url = "https://files.pythonhosted.org/packages/5e/09/3e94912b8dd37251377bb02727a33a67ee96b84bbbe092f132b401ca5dd9/coverage-7.6.4-cp312-cp312-win32.whl", hash = "sha256:7bb92c539a624cf86296dd0c68cd5cc286c9eef2d0c3b8b192b604ce9de20a17", size = 209639 }, - { url = "https://files.pythonhosted.org/packages/01/69/d4f3a4101171f32bc5b3caec8ff94c2c60f700107a6aaef7244b2c166793/coverage-7.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:1032e178b76a4e2b5b32e19d0fd0abbce4b58e77a1ca695820d10e491fa32b08", size = 210428 }, - { url = "https://files.pythonhosted.org/packages/c2/4d/2dede4f7cb5a70fb0bb40a57627fddf1dbdc6b9c1db81f7c4dcdcb19e2f4/coverage-7.6.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:023bf8ee3ec6d35af9c1c6ccc1d18fa69afa1cb29eaac57cb064dbb262a517f9", size = 207039 }, - { url = "https://files.pythonhosted.org/packages/3f/f9/d86368ae8c79e28f1fb458ebc76ae9ff3e8bd8069adc24e8f2fed03c58b7/coverage-7.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0ac3d42cb51c4b12df9c5f0dd2f13a4f24f01943627120ec4d293c9181219ba", size = 207298 }, - { url = "https://files.pythonhosted.org/packages/64/c5/b4cc3c3f64622c58fbfd4d8b9a7a8ce9d355f172f91fcabbba1f026852f6/coverage-7.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8fe4984b431f8621ca53d9380901f62bfb54ff759a1348cd140490ada7b693c", size = 239813 }, - { url = "https://files.pythonhosted.org/packages/8a/86/14c42e60b70a79b26099e4d289ccdfefbc68624d096f4481163085aa614c/coverage-7.6.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5fbd612f8a091954a0c8dd4c0b571b973487277d26476f8480bfa4b2a65b5d06", size = 236959 }, - { url = "https://files.pythonhosted.org/packages/7f/f8/4436a643631a2fbab4b44d54f515028f6099bfb1cd95b13cfbf701e7f2f2/coverage-7.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dacbc52de979f2823a819571f2e3a350a7e36b8cb7484cdb1e289bceaf35305f", size = 238950 }, - { url = "https://files.pythonhosted.org/packages/49/50/1571810ddd01f99a0a8be464a4ac8b147f322cd1e8e296a1528984fc560b/coverage-7.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dab4d16dfef34b185032580e2f2f89253d302facba093d5fa9dbe04f569c4f4b", size = 238610 }, - { url = "https://files.pythonhosted.org/packages/f3/8c/6312d241fe7cbd1f0cade34a62fea6f333d1a261255d76b9a87074d8703c/coverage-7.6.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:862264b12ebb65ad8d863d51f17758b1684560b66ab02770d4f0baf2ff75da21", size = 236697 }, - { url = "https://files.pythonhosted.org/packages/ce/5f/fef33dfd05d87ee9030f614c857deb6df6556b8f6a1c51bbbb41e24ee5ac/coverage-7.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5beb1ee382ad32afe424097de57134175fea3faf847b9af002cc7895be4e2a5a", size = 238541 }, - { url = "https://files.pythonhosted.org/packages/a9/64/6a984b6e92e1ea1353b7ffa08e27f707a5e29b044622445859200f541e8c/coverage-7.6.4-cp313-cp313-win32.whl", hash = "sha256:bf20494da9653f6410213424f5f8ad0ed885e01f7e8e59811f572bdb20b8972e", size = 209707 }, - { url = "https://files.pythonhosted.org/packages/5c/60/ce5a9e942e9543783b3db5d942e0578b391c25cdd5e7f342d854ea83d6b7/coverage-7.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:182e6cd5c040cec0a1c8d415a87b67ed01193ed9ad458ee427741c7d8513d963", size = 210439 }, - { url = "https://files.pythonhosted.org/packages/78/53/6719677e92c308207e7f10561a1b16ab8b5c00e9328efc9af7cfd6fb703e/coverage-7.6.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a181e99301a0ae128493a24cfe5cfb5b488c4e0bf2f8702091473d033494d04f", size = 207784 }, - { url = "https://files.pythonhosted.org/packages/fa/dd/7054928930671fcb39ae6a83bb71d9ab5f0afb733172543ced4b09a115ca/coverage-7.6.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:df57bdbeffe694e7842092c5e2e0bc80fff7f43379d465f932ef36f027179806", size = 208058 }, - { url = "https://files.pythonhosted.org/packages/b5/7d/fd656ddc2b38301927b9eb3aae3fe827e7aa82e691923ed43721fd9423c9/coverage-7.6.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bcd1069e710600e8e4cf27f65c90c7843fa8edfb4520fb0ccb88894cad08b11", size = 250772 }, - { url = "https://files.pythonhosted.org/packages/90/d0/eb9a3cc2100b83064bb086f18aedde3afffd7de6ead28f69736c00b7f302/coverage-7.6.4-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99b41d18e6b2a48ba949418db48159d7a2e81c5cc290fc934b7d2380515bd0e3", size = 246490 }, - { url = "https://files.pythonhosted.org/packages/45/44/3f64f38f6faab8a0cfd2c6bc6eb4c6daead246b97cf5f8fc23bf3788f841/coverage-7.6.4-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1e54712ba3474f34b7ef7a41e65bd9037ad47916ccb1cc78769bae324c01a", size = 248848 }, - { url = "https://files.pythonhosted.org/packages/5d/11/4c465a5f98656821e499f4b4619929bd5a34639c466021740ecdca42aa30/coverage-7.6.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53d202fd109416ce011578f321460795abfe10bb901b883cafd9b3ef851bacfc", size = 248340 }, - { url = "https://files.pythonhosted.org/packages/f1/96/ebecda2d016cce9da812f404f720ca5df83c6b29f65dc80d2000d0078741/coverage-7.6.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:c48167910a8f644671de9f2083a23630fbf7a1cb70ce939440cd3328e0919f70", size = 246229 }, - { url = "https://files.pythonhosted.org/packages/16/d9/3d820c00066ae55d69e6d0eae11d6149a5ca7546de469ba9d597f01bf2d7/coverage-7.6.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cc8ff50b50ce532de2fa7a7daae9dd12f0a699bfcd47f20945364e5c31799fef", size = 247510 }, - { url = "https://files.pythonhosted.org/packages/8f/c3/4fa1eb412bb288ff6bfcc163c11700ff06e02c5fad8513817186e460ed43/coverage-7.6.4-cp313-cp313t-win32.whl", hash = "sha256:b8d3a03d9bfcaf5b0141d07a88456bb6a4c3ce55c080712fec8418ef3610230e", size = 210353 }, - { url = "https://files.pythonhosted.org/packages/7e/77/03fc2979d1538884d921c2013075917fc927f41cd8526909852fe4494112/coverage-7.6.4-cp313-cp313t-win_amd64.whl", hash = "sha256:f3ddf056d3ebcf6ce47bdaf56142af51bb7fad09e4af310241e9db7a3a8022e1", size = 211502 }, - { url = "https://files.pythonhosted.org/packages/cc/56/e1d75e8981a2a92c2a777e67c26efa96c66da59d645423146eb9ff3a851b/coverage-7.6.4-pp39.pp310-none-any.whl", hash = "sha256:3c65d37f3a9ebb703e710befdc489a38683a5b152242664b973a7b7b22348a4e", size = 198954 }, + { url = "https://files.pythonhosted.org/packages/a5/93/4ad92f71e28ece5c0326e5f4a6630aa4928a8846654a65cfff69b49b95b9/coverage-7.6.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f8ae553cba74085db385d489c7a792ad66f7f9ba2ee85bfa508aeb84cf0ba07", size = 206713, upload_time = "2024-10-20T22:56:03.877Z" }, + { url = "https://files.pythonhosted.org/packages/01/ae/747a580b1eda3f2e431d87de48f0604bd7bc92e52a1a95185a4aa585bc47/coverage-7.6.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8165b796df0bd42e10527a3f493c592ba494f16ef3c8b531288e3d0d72c1f6f0", size = 207149, upload_time = "2024-10-20T22:56:06.511Z" }, + { url = "https://files.pythonhosted.org/packages/07/1a/1f573f8a6145f6d4c9130bbc120e0024daf1b24cf2a78d7393fa6eb6aba7/coverage-7.6.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7c8b95bf47db6d19096a5e052ffca0a05f335bc63cef281a6e8fe864d450a72", size = 235584, upload_time = "2024-10-20T22:56:07.678Z" }, + { url = "https://files.pythonhosted.org/packages/40/42/c8523f2e4db34aa9389caee0d3688b6ada7a84fcc782e943a868a7f302bd/coverage-7.6.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ed9281d1b52628e81393f5eaee24a45cbd64965f41857559c2b7ff19385df51", size = 233486, upload_time = "2024-10-20T22:56:09.496Z" }, + { url = "https://files.pythonhosted.org/packages/8d/95/565c310fffa16ede1a042e9ea1ca3962af0d8eb5543bc72df6b91dc0c3d5/coverage-7.6.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0809082ee480bb8f7416507538243c8863ac74fd8a5d2485c46f0f7499f2b491", size = 234649, upload_time = "2024-10-20T22:56:11.326Z" }, + { url = "https://files.pythonhosted.org/packages/d5/81/3b550674d98968ec29c92e3e8650682be6c8b1fa7581a059e7e12e74c431/coverage-7.6.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d541423cdd416b78626b55f123412fcf979d22a2c39fce251b350de38c15c15b", size = 233744, upload_time = "2024-10-20T22:56:12.481Z" }, + { url = "https://files.pythonhosted.org/packages/0d/70/d66c7f51b3e33aabc5ea9f9624c1c9d9655472962270eb5e7b0d32707224/coverage-7.6.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:58809e238a8a12a625c70450b48e8767cff9eb67c62e6154a642b21ddf79baea", size = 232204, upload_time = "2024-10-20T22:56:14.236Z" }, + { url = "https://files.pythonhosted.org/packages/23/2d/2b3a2dbed7a5f40693404c8a09e779d7c1a5fbed089d3e7224c002129ec8/coverage-7.6.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c9b8e184898ed014884ca84c70562b4a82cbc63b044d366fedc68bc2b2f3394a", size = 233335, upload_time = "2024-10-20T22:56:15.521Z" }, + { url = "https://files.pythonhosted.org/packages/5a/4f/92d1d2ad720d698a4e71c176eacf531bfb8e0721d5ad560556f2c484a513/coverage-7.6.4-cp310-cp310-win32.whl", hash = "sha256:6bd818b7ea14bc6e1f06e241e8234508b21edf1b242d49831831a9450e2f35fa", size = 209435, upload_time = "2024-10-20T22:56:17.309Z" }, + { url = "https://files.pythonhosted.org/packages/c7/b9/cdf158e7991e2287bcf9082670928badb73d310047facac203ff8dcd5ff3/coverage-7.6.4-cp310-cp310-win_amd64.whl", hash = "sha256:06babbb8f4e74b063dbaeb74ad68dfce9186c595a15f11f5d5683f748fa1d172", size = 210243, upload_time = "2024-10-20T22:56:18.366Z" }, + { url = "https://files.pythonhosted.org/packages/87/31/9c0cf84f0dfcbe4215b7eb95c31777cdc0483c13390e69584c8150c85175/coverage-7.6.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:73d2b73584446e66ee633eaad1a56aad577c077f46c35ca3283cd687b7715b0b", size = 206819, upload_time = "2024-10-20T22:56:20.132Z" }, + { url = "https://files.pythonhosted.org/packages/53/ed/a38401079ad320ad6e054a01ec2b61d270511aeb3c201c80e99c841229d5/coverage-7.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:51b44306032045b383a7a8a2c13878de375117946d68dcb54308111f39775a25", size = 207263, upload_time = "2024-10-20T22:56:21.88Z" }, + { url = "https://files.pythonhosted.org/packages/20/e7/c3ad33b179ab4213f0d70da25a9c214d52464efa11caeab438592eb1d837/coverage-7.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b3fb02fe73bed561fa12d279a417b432e5b50fe03e8d663d61b3d5990f29546", size = 239205, upload_time = "2024-10-20T22:56:23.03Z" }, + { url = "https://files.pythonhosted.org/packages/36/91/fc02e8d8e694f557752120487fd982f654ba1421bbaa5560debf96ddceda/coverage-7.6.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed8fe9189d2beb6edc14d3ad19800626e1d9f2d975e436f84e19efb7fa19469b", size = 236612, upload_time = "2024-10-20T22:56:24.882Z" }, + { url = "https://files.pythonhosted.org/packages/cc/57/cb08f0eda0389a9a8aaa4fc1f9fec7ac361c3e2d68efd5890d7042c18aa3/coverage-7.6.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b369ead6527d025a0fe7bd3864e46dbee3aa8f652d48df6174f8d0bac9e26e0e", size = 238479, upload_time = "2024-10-20T22:56:26.749Z" }, + { url = "https://files.pythonhosted.org/packages/d5/c9/2c7681a9b3ca6e6f43d489c2e6653a53278ed857fd6e7010490c307b0a47/coverage-7.6.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ade3ca1e5f0ff46b678b66201f7ff477e8fa11fb537f3b55c3f0568fbfe6e718", size = 237405, upload_time = "2024-10-20T22:56:27.958Z" }, + { url = "https://files.pythonhosted.org/packages/b5/4e/ebfc6944b96317df8b537ae875d2e57c27b84eb98820bc0a1055f358f056/coverage-7.6.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:27fb4a050aaf18772db513091c9c13f6cb94ed40eacdef8dad8411d92d9992db", size = 236038, upload_time = "2024-10-20T22:56:29.816Z" }, + { url = "https://files.pythonhosted.org/packages/13/f2/3a0bf1841a97c0654905e2ef531170f02c89fad2555879db8fe41a097871/coverage-7.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4f704f0998911abf728a7783799444fcbbe8261c4a6c166f667937ae6a8aa522", size = 236812, upload_time = "2024-10-20T22:56:31.654Z" }, + { url = "https://files.pythonhosted.org/packages/b9/9c/66bf59226b52ce6ed9541b02d33e80a6e816a832558fbdc1111a7bd3abd4/coverage-7.6.4-cp311-cp311-win32.whl", hash = "sha256:29155cd511ee058e260db648b6182c419422a0d2e9a4fa44501898cf918866cf", size = 209400, upload_time = "2024-10-20T22:56:33.569Z" }, + { url = "https://files.pythonhosted.org/packages/2a/a0/b0790934c04dfc8d658d4a62acb8f7ca0efdf3818456fcad757b11c6479d/coverage-7.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:8902dd6a30173d4ef09954bfcb24b5d7b5190cf14a43170e386979651e09ba19", size = 210243, upload_time = "2024-10-20T22:56:34.863Z" }, + { url = "https://files.pythonhosted.org/packages/7d/e7/9291de916d084f41adddfd4b82246e68d61d6a75747f075f7e64628998d2/coverage-7.6.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12394842a3a8affa3ba62b0d4ab7e9e210c5e366fbac3e8b2a68636fb19892c2", size = 207013, upload_time = "2024-10-20T22:56:36.034Z" }, + { url = "https://files.pythonhosted.org/packages/27/03/932c2c5717a7fa80cd43c6a07d3177076d97b79f12f40f882f9916db0063/coverage-7.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b6b4c83d8e8ea79f27ab80778c19bc037759aea298da4b56621f4474ffeb117", size = 207251, upload_time = "2024-10-20T22:56:38.054Z" }, + { url = "https://files.pythonhosted.org/packages/d5/3f/0af47dcb9327f65a45455fbca846fe96eb57c153af46c4754a3ba678938a/coverage-7.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d5b8007f81b88696d06f7df0cb9af0d3b835fe0c8dbf489bad70b45f0e45613", size = 240268, upload_time = "2024-10-20T22:56:40.051Z" }, + { url = "https://files.pythonhosted.org/packages/8a/3c/37a9d81bbd4b23bc7d46ca820e16174c613579c66342faa390a271d2e18b/coverage-7.6.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b57b768feb866f44eeed9f46975f3d6406380275c5ddfe22f531a2bf187eda27", size = 237298, upload_time = "2024-10-20T22:56:41.929Z" }, + { url = "https://files.pythonhosted.org/packages/c0/70/6b0627e5bd68204ee580126ed3513140b2298995c1233bd67404b4e44d0e/coverage-7.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5915fcdec0e54ee229926868e9b08586376cae1f5faa9bbaf8faf3561b393d52", size = 239367, upload_time = "2024-10-20T22:56:43.141Z" }, + { url = "https://files.pythonhosted.org/packages/3c/eb/634d7dfab24ac3b790bebaf9da0f4a5352cbc125ce6a9d5c6cf4c6cae3c7/coverage-7.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b58c672d14f16ed92a48db984612f5ce3836ae7d72cdd161001cc54512571f2", size = 238853, upload_time = "2024-10-20T22:56:44.33Z" }, + { url = "https://files.pythonhosted.org/packages/d9/0d/8e3ed00f1266ef7472a4e33458f42e39492e01a64281084fb3043553d3f1/coverage-7.6.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2fdef0d83a2d08d69b1f2210a93c416d54e14d9eb398f6ab2f0a209433db19e1", size = 237160, upload_time = "2024-10-20T22:56:46.258Z" }, + { url = "https://files.pythonhosted.org/packages/ce/9c/4337f468ef0ab7a2e0887a9c9da0e58e2eada6fc6cbee637a4acd5dfd8a9/coverage-7.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cf717ee42012be8c0cb205dbbf18ffa9003c4cbf4ad078db47b95e10748eec5", size = 238824, upload_time = "2024-10-20T22:56:48.666Z" }, + { url = "https://files.pythonhosted.org/packages/5e/09/3e94912b8dd37251377bb02727a33a67ee96b84bbbe092f132b401ca5dd9/coverage-7.6.4-cp312-cp312-win32.whl", hash = "sha256:7bb92c539a624cf86296dd0c68cd5cc286c9eef2d0c3b8b192b604ce9de20a17", size = 209639, upload_time = "2024-10-20T22:56:50.664Z" }, + { url = "https://files.pythonhosted.org/packages/01/69/d4f3a4101171f32bc5b3caec8ff94c2c60f700107a6aaef7244b2c166793/coverage-7.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:1032e178b76a4e2b5b32e19d0fd0abbce4b58e77a1ca695820d10e491fa32b08", size = 210428, upload_time = "2024-10-20T22:56:52.468Z" }, + { url = "https://files.pythonhosted.org/packages/c2/4d/2dede4f7cb5a70fb0bb40a57627fddf1dbdc6b9c1db81f7c4dcdcb19e2f4/coverage-7.6.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:023bf8ee3ec6d35af9c1c6ccc1d18fa69afa1cb29eaac57cb064dbb262a517f9", size = 207039, upload_time = "2024-10-20T22:56:53.656Z" }, + { url = "https://files.pythonhosted.org/packages/3f/f9/d86368ae8c79e28f1fb458ebc76ae9ff3e8bd8069adc24e8f2fed03c58b7/coverage-7.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0ac3d42cb51c4b12df9c5f0dd2f13a4f24f01943627120ec4d293c9181219ba", size = 207298, upload_time = "2024-10-20T22:56:54.979Z" }, + { url = "https://files.pythonhosted.org/packages/64/c5/b4cc3c3f64622c58fbfd4d8b9a7a8ce9d355f172f91fcabbba1f026852f6/coverage-7.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8fe4984b431f8621ca53d9380901f62bfb54ff759a1348cd140490ada7b693c", size = 239813, upload_time = "2024-10-20T22:56:56.209Z" }, + { url = "https://files.pythonhosted.org/packages/8a/86/14c42e60b70a79b26099e4d289ccdfefbc68624d096f4481163085aa614c/coverage-7.6.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5fbd612f8a091954a0c8dd4c0b571b973487277d26476f8480bfa4b2a65b5d06", size = 236959, upload_time = "2024-10-20T22:56:58.06Z" }, + { url = "https://files.pythonhosted.org/packages/7f/f8/4436a643631a2fbab4b44d54f515028f6099bfb1cd95b13cfbf701e7f2f2/coverage-7.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dacbc52de979f2823a819571f2e3a350a7e36b8cb7484cdb1e289bceaf35305f", size = 238950, upload_time = "2024-10-20T22:56:59.329Z" }, + { url = "https://files.pythonhosted.org/packages/49/50/1571810ddd01f99a0a8be464a4ac8b147f322cd1e8e296a1528984fc560b/coverage-7.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dab4d16dfef34b185032580e2f2f89253d302facba093d5fa9dbe04f569c4f4b", size = 238610, upload_time = "2024-10-20T22:57:00.645Z" }, + { url = "https://files.pythonhosted.org/packages/f3/8c/6312d241fe7cbd1f0cade34a62fea6f333d1a261255d76b9a87074d8703c/coverage-7.6.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:862264b12ebb65ad8d863d51f17758b1684560b66ab02770d4f0baf2ff75da21", size = 236697, upload_time = "2024-10-20T22:57:01.944Z" }, + { url = "https://files.pythonhosted.org/packages/ce/5f/fef33dfd05d87ee9030f614c857deb6df6556b8f6a1c51bbbb41e24ee5ac/coverage-7.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5beb1ee382ad32afe424097de57134175fea3faf847b9af002cc7895be4e2a5a", size = 238541, upload_time = "2024-10-20T22:57:03.848Z" }, + { url = "https://files.pythonhosted.org/packages/a9/64/6a984b6e92e1ea1353b7ffa08e27f707a5e29b044622445859200f541e8c/coverage-7.6.4-cp313-cp313-win32.whl", hash = "sha256:bf20494da9653f6410213424f5f8ad0ed885e01f7e8e59811f572bdb20b8972e", size = 209707, upload_time = "2024-10-20T22:57:05.123Z" }, + { url = "https://files.pythonhosted.org/packages/5c/60/ce5a9e942e9543783b3db5d942e0578b391c25cdd5e7f342d854ea83d6b7/coverage-7.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:182e6cd5c040cec0a1c8d415a87b67ed01193ed9ad458ee427741c7d8513d963", size = 210439, upload_time = "2024-10-20T22:57:06.35Z" }, + { url = "https://files.pythonhosted.org/packages/78/53/6719677e92c308207e7f10561a1b16ab8b5c00e9328efc9af7cfd6fb703e/coverage-7.6.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a181e99301a0ae128493a24cfe5cfb5b488c4e0bf2f8702091473d033494d04f", size = 207784, upload_time = "2024-10-20T22:57:07.857Z" }, + { url = "https://files.pythonhosted.org/packages/fa/dd/7054928930671fcb39ae6a83bb71d9ab5f0afb733172543ced4b09a115ca/coverage-7.6.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:df57bdbeffe694e7842092c5e2e0bc80fff7f43379d465f932ef36f027179806", size = 208058, upload_time = "2024-10-20T22:57:09.845Z" }, + { url = "https://files.pythonhosted.org/packages/b5/7d/fd656ddc2b38301927b9eb3aae3fe827e7aa82e691923ed43721fd9423c9/coverage-7.6.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bcd1069e710600e8e4cf27f65c90c7843fa8edfb4520fb0ccb88894cad08b11", size = 250772, upload_time = "2024-10-20T22:57:11.147Z" }, + { url = "https://files.pythonhosted.org/packages/90/d0/eb9a3cc2100b83064bb086f18aedde3afffd7de6ead28f69736c00b7f302/coverage-7.6.4-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99b41d18e6b2a48ba949418db48159d7a2e81c5cc290fc934b7d2380515bd0e3", size = 246490, upload_time = "2024-10-20T22:57:13.02Z" }, + { url = "https://files.pythonhosted.org/packages/45/44/3f64f38f6faab8a0cfd2c6bc6eb4c6daead246b97cf5f8fc23bf3788f841/coverage-7.6.4-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1e54712ba3474f34b7ef7a41e65bd9037ad47916ccb1cc78769bae324c01a", size = 248848, upload_time = "2024-10-20T22:57:14.927Z" }, + { url = "https://files.pythonhosted.org/packages/5d/11/4c465a5f98656821e499f4b4619929bd5a34639c466021740ecdca42aa30/coverage-7.6.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53d202fd109416ce011578f321460795abfe10bb901b883cafd9b3ef851bacfc", size = 248340, upload_time = "2024-10-20T22:57:16.246Z" }, + { url = "https://files.pythonhosted.org/packages/f1/96/ebecda2d016cce9da812f404f720ca5df83c6b29f65dc80d2000d0078741/coverage-7.6.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:c48167910a8f644671de9f2083a23630fbf7a1cb70ce939440cd3328e0919f70", size = 246229, upload_time = "2024-10-20T22:57:17.546Z" }, + { url = "https://files.pythonhosted.org/packages/16/d9/3d820c00066ae55d69e6d0eae11d6149a5ca7546de469ba9d597f01bf2d7/coverage-7.6.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cc8ff50b50ce532de2fa7a7daae9dd12f0a699bfcd47f20945364e5c31799fef", size = 247510, upload_time = "2024-10-20T22:57:18.925Z" }, + { url = "https://files.pythonhosted.org/packages/8f/c3/4fa1eb412bb288ff6bfcc163c11700ff06e02c5fad8513817186e460ed43/coverage-7.6.4-cp313-cp313t-win32.whl", hash = "sha256:b8d3a03d9bfcaf5b0141d07a88456bb6a4c3ce55c080712fec8418ef3610230e", size = 210353, upload_time = "2024-10-20T22:57:20.891Z" }, + { url = "https://files.pythonhosted.org/packages/7e/77/03fc2979d1538884d921c2013075917fc927f41cd8526909852fe4494112/coverage-7.6.4-cp313-cp313t-win_amd64.whl", hash = "sha256:f3ddf056d3ebcf6ce47bdaf56142af51bb7fad09e4af310241e9db7a3a8022e1", size = 211502, upload_time = "2024-10-20T22:57:22.21Z" }, + { url = "https://files.pythonhosted.org/packages/cc/56/e1d75e8981a2a92c2a777e67c26efa96c66da59d645423146eb9ff3a851b/coverage-7.6.4-pp39.pp310-none-any.whl", hash = "sha256:3c65d37f3a9ebb703e710befdc489a38683a5b152242664b973a7b7b22348a4e", size = 198954, upload_time = "2024-10-20T22:57:38.28Z" }, ] [package.optional-dependencies] @@ -453,57 +462,57 @@ toml = [ name = "cycler" version = "0.12.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615 } +sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615, upload_time = "2023-10-07T05:32:18.335Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321 }, + { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload_time = "2023-10-07T05:32:16.783Z" }, ] [[package]] name = "cython" version = "3.0.8" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/68/09/ffb61f29b8e3d207c444032b21328327d753e274ea081bc74e009827cc81/Cython-3.0.8.tar.gz", hash = "sha256:8333423d8fd5765e7cceea3a9985dd1e0a5dfeb2734629e1a2ed2d6233d39de6", size = 2744096 } +sdist = { url = "https://files.pythonhosted.org/packages/68/09/ffb61f29b8e3d207c444032b21328327d753e274ea081bc74e009827cc81/Cython-3.0.8.tar.gz", hash = "sha256:8333423d8fd5765e7cceea3a9985dd1e0a5dfeb2734629e1a2ed2d6233d39de6", size = 2744096, upload_time = "2024-01-10T11:01:02.155Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/63/f4/d2542e186fe33ec1cc542770fb17466421ed54f4ffe04d00fe9549d0a467/Cython-3.0.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a846e0a38e2b24e9a5c5dc74b0e54c6e29420d88d1dafabc99e0fc0f3e338636", size = 3100459 }, - { url = "https://files.pythonhosted.org/packages/fc/27/2652f395aa708fb3081148e0df3ab700bd7288636c65332ef7febad6a380/Cython-3.0.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45523fdc2b78d79b32834cc1cc12dc2ca8967af87e22a3ee1bff20e77c7f5520", size = 3456626 }, - { url = "https://files.pythonhosted.org/packages/f9/bd/e8a1d26d04c08a67bcc383f2ea5493a4e77f37a8770ead00a238b08ad729/Cython-3.0.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa0b7f3f841fe087410cab66778e2d3fb20ae2d2078a2be3dffe66c6574be39", size = 3621379 }, - { url = "https://files.pythonhosted.org/packages/03/ae/ead7ec03d0062d439879d41b7830e4f2480213f7beabf2f7052a191cc6f7/Cython-3.0.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e87294e33e40c289c77a135f491cd721bd089f193f956f7b8ed5aa2d0b8c558f", size = 3671873 }, - { url = "https://files.pythonhosted.org/packages/63/b0/81dad725604d7b529c492f873a7fa1b5800704a9f26e100ed25e9fd8d057/Cython-3.0.8-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a1df7a129344b1215c20096d33c00193437df1a8fcca25b71f17c23b1a44f782", size = 3463832 }, - { url = "https://files.pythonhosted.org/packages/13/cd/72b8e0af597ac1b376421847acf6d6fa252e60059a2a00dcf05ceb16d28f/Cython-3.0.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:13c2a5e57a0358da467d97667297bf820b62a1a87ae47c5f87938b9bb593acbd", size = 3618325 }, - { url = "https://files.pythonhosted.org/packages/ef/73/11a4355d8b8966504c751e5bcb25916c4140de27bb2ba1b54ff21994d7fe/Cython-3.0.8-cp310-cp310-win32.whl", hash = "sha256:96b028f044f5880e3cb18ecdcfc6c8d3ce9d0af28418d5ab464509f26d8adf12", size = 2571305 }, - { url = "https://files.pythonhosted.org/packages/18/15/fdc0c3552d20f9337b134a36d786da24e47998fc39f62cb61c1534f26123/Cython-3.0.8-cp310-cp310-win_amd64.whl", hash = "sha256:8140597a8b5cc4f119a1190f5a2228a84f5ca6d8d9ec386cfce24663f48b2539", size = 2776113 }, - { url = "https://files.pythonhosted.org/packages/db/a7/f4a0bc9a80e23b380daa2ebb4879bf434aaa0b3b91f7ad8a7f9762b4bd1b/Cython-3.0.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aae26f9663e50caf9657148403d9874eea41770ecdd6caf381d177c2b1bb82ba", size = 3113615 }, - { url = "https://files.pythonhosted.org/packages/e9/e9/e9295df74246c165b91253a473bfa179debf739c9bee961cbb3ae56c2b79/Cython-3.0.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:547eb3cdb2f8c6f48e6865d5a741d9dd051c25b3ce076fbca571727977b28ac3", size = 3436320 }, - { url = "https://files.pythonhosted.org/packages/26/2c/6a887c957aa53e44f928119dea628a5dfacc8e875424034f5fecac9daba4/Cython-3.0.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a567d4b9ba70b26db89d75b243529de9e649a2f56384287533cf91512705bee", size = 3591755 }, - { url = "https://files.pythonhosted.org/packages/ba/b8/f9c97bae6281da50b3ecb1f7fef0f7f7851eae084609b364717a2b366bf1/Cython-3.0.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:51d1426263b0e82fb22bda8ea60dc77a428581cc19e97741011b938445d383f1", size = 3636099 }, - { url = "https://files.pythonhosted.org/packages/17/ae/cd055c2c081c67a6fcad1d8d17d82bd6395b14c6741e3a938f40318c8bc5/Cython-3.0.8-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c26daaeccda072459b48d211415fd1e5507c06bcd976fa0d5b8b9f1063467d7b", size = 3458119 }, - { url = "https://files.pythonhosted.org/packages/72/ab/ac6f5548d6194f4bb2fc8c6c996aa7369f0fa1403e4d4de787d9e9309b27/Cython-3.0.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:289ce7838208211cd166e975865fd73b0649bf118170b6cebaedfbdaf4a37795", size = 3614418 }, - { url = "https://files.pythonhosted.org/packages/70/e2/3e3e448b7a94887bec3235bcb71957b6681dc42b4536459f8f54d46fa936/Cython-3.0.8-cp311-cp311-win32.whl", hash = "sha256:c8aa05f5e17f8042a3be052c24f2edc013fb8af874b0bf76907d16c51b4e7871", size = 2572819 }, - { url = "https://files.pythonhosted.org/packages/85/7d/58635941dfbb5b4e197adb88080b9cbfb230dc3b75683698a530a1989bdb/Cython-3.0.8-cp311-cp311-win_amd64.whl", hash = "sha256:000dc9e135d0eec6ecb2b40a5b02d0868a2f8d2e027a41b0fe16a908a9e6de02", size = 2784167 }, - { url = "https://files.pythonhosted.org/packages/3d/8e/28f8c6109990eef7317ab7e43644092b49a88a39f9373dcd19318946df09/Cython-3.0.8-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:90d3fe31db55685d8cb97d43b0ec39ef614fcf660f83c77ed06aa670cb0e164f", size = 3135638 }, - { url = "https://files.pythonhosted.org/packages/83/1f/4720cb682b8ed1ab9749dea35351a66dd29b6a022628cce038415660c384/Cython-3.0.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e24791ddae2324e88e3c902a765595c738f19ae34ee66bfb1a6dac54b1833419", size = 3340052 }, - { url = "https://files.pythonhosted.org/packages/8a/47/ec3fceb9e8f7d6fa130216b8740038e1df7c8e5f215bba363fcf1272a6c1/Cython-3.0.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f020fa1c0552052e0660790b8153b79e3fc9a15dbd8f1d0b841fe5d204a6ae6", size = 3510079 }, - { url = "https://files.pythonhosted.org/packages/71/31/b458127851e248effb909e2791b55870914863cde7c60b94db5ee65d7867/Cython-3.0.8-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18bfa387d7a7f77d7b2526af69a65dbd0b731b8d941aaff5becff8e21f6d7717", size = 3573972 }, - { url = "https://files.pythonhosted.org/packages/6b/d5/ca6513844d0634abd05ba12304053a454bb70441a9520afa9897d4300156/Cython-3.0.8-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:fe81b339cffd87c0069c6049b4d33e28bdd1874625ee515785bf42c9fdff3658", size = 3356158 }, - { url = "https://files.pythonhosted.org/packages/33/59/98a87b6264f4ad45c820db13c4ec657567476efde020c49443cc842a86af/Cython-3.0.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:80fd94c076e1e1b1ee40a309be03080b75f413e8997cddcf401a118879863388", size = 3522312 }, - { url = "https://files.pythonhosted.org/packages/2b/cb/132115d07a0b9d4f075e0741db70a5416b424dcd875b2bb0dd805e818222/Cython-3.0.8-cp312-cp312-win32.whl", hash = "sha256:85077915a93e359a9b920280d214dc0cf8a62773e1f3d7d30fab8ea4daed670c", size = 2602579 }, - { url = "https://files.pythonhosted.org/packages/b4/69/cb4620287cd9ef461103e122c0a2ae7f7ecf183e02510676fb5a15c95b05/Cython-3.0.8-cp312-cp312-win_amd64.whl", hash = "sha256:0cb2dcc565c7851f75d496f724a384a790fab12d1b82461b663e66605bec429a", size = 2791268 }, - { url = "https://files.pythonhosted.org/packages/e3/7f/f584f5d15323feb897d42ef0e9d910649e2150d7a30cf7e7a8cc1d236e6f/Cython-3.0.8-py2.py3-none-any.whl", hash = "sha256:171b27051253d3f9108e9759e504ba59ff06e7f7ba944457f94deaf9c21bf0b6", size = 1168213 }, + { url = "https://files.pythonhosted.org/packages/63/f4/d2542e186fe33ec1cc542770fb17466421ed54f4ffe04d00fe9549d0a467/Cython-3.0.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a846e0a38e2b24e9a5c5dc74b0e54c6e29420d88d1dafabc99e0fc0f3e338636", size = 3100459, upload_time = "2024-01-10T11:33:49.545Z" }, + { url = "https://files.pythonhosted.org/packages/fc/27/2652f395aa708fb3081148e0df3ab700bd7288636c65332ef7febad6a380/Cython-3.0.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45523fdc2b78d79b32834cc1cc12dc2ca8967af87e22a3ee1bff20e77c7f5520", size = 3456626, upload_time = "2024-01-10T11:01:44.897Z" }, + { url = "https://files.pythonhosted.org/packages/f9/bd/e8a1d26d04c08a67bcc383f2ea5493a4e77f37a8770ead00a238b08ad729/Cython-3.0.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa0b7f3f841fe087410cab66778e2d3fb20ae2d2078a2be3dffe66c6574be39", size = 3621379, upload_time = "2024-01-10T11:01:48.777Z" }, + { url = "https://files.pythonhosted.org/packages/03/ae/ead7ec03d0062d439879d41b7830e4f2480213f7beabf2f7052a191cc6f7/Cython-3.0.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e87294e33e40c289c77a135f491cd721bd089f193f956f7b8ed5aa2d0b8c558f", size = 3671873, upload_time = "2024-01-10T11:01:51.858Z" }, + { url = "https://files.pythonhosted.org/packages/63/b0/81dad725604d7b529c492f873a7fa1b5800704a9f26e100ed25e9fd8d057/Cython-3.0.8-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a1df7a129344b1215c20096d33c00193437df1a8fcca25b71f17c23b1a44f782", size = 3463832, upload_time = "2024-01-10T11:01:55.364Z" }, + { url = "https://files.pythonhosted.org/packages/13/cd/72b8e0af597ac1b376421847acf6d6fa252e60059a2a00dcf05ceb16d28f/Cython-3.0.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:13c2a5e57a0358da467d97667297bf820b62a1a87ae47c5f87938b9bb593acbd", size = 3618325, upload_time = "2024-01-10T11:01:59.03Z" }, + { url = "https://files.pythonhosted.org/packages/ef/73/11a4355d8b8966504c751e5bcb25916c4140de27bb2ba1b54ff21994d7fe/Cython-3.0.8-cp310-cp310-win32.whl", hash = "sha256:96b028f044f5880e3cb18ecdcfc6c8d3ce9d0af28418d5ab464509f26d8adf12", size = 2571305, upload_time = "2024-01-10T11:02:02.589Z" }, + { url = "https://files.pythonhosted.org/packages/18/15/fdc0c3552d20f9337b134a36d786da24e47998fc39f62cb61c1534f26123/Cython-3.0.8-cp310-cp310-win_amd64.whl", hash = "sha256:8140597a8b5cc4f119a1190f5a2228a84f5ca6d8d9ec386cfce24663f48b2539", size = 2776113, upload_time = "2024-01-10T11:02:05.581Z" }, + { url = "https://files.pythonhosted.org/packages/db/a7/f4a0bc9a80e23b380daa2ebb4879bf434aaa0b3b91f7ad8a7f9762b4bd1b/Cython-3.0.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aae26f9663e50caf9657148403d9874eea41770ecdd6caf381d177c2b1bb82ba", size = 3113615, upload_time = "2024-01-10T11:34:05.899Z" }, + { url = "https://files.pythonhosted.org/packages/e9/e9/e9295df74246c165b91253a473bfa179debf739c9bee961cbb3ae56c2b79/Cython-3.0.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:547eb3cdb2f8c6f48e6865d5a741d9dd051c25b3ce076fbca571727977b28ac3", size = 3436320, upload_time = "2024-01-10T11:02:08.689Z" }, + { url = "https://files.pythonhosted.org/packages/26/2c/6a887c957aa53e44f928119dea628a5dfacc8e875424034f5fecac9daba4/Cython-3.0.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a567d4b9ba70b26db89d75b243529de9e649a2f56384287533cf91512705bee", size = 3591755, upload_time = "2024-01-10T11:02:11.773Z" }, + { url = "https://files.pythonhosted.org/packages/ba/b8/f9c97bae6281da50b3ecb1f7fef0f7f7851eae084609b364717a2b366bf1/Cython-3.0.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:51d1426263b0e82fb22bda8ea60dc77a428581cc19e97741011b938445d383f1", size = 3636099, upload_time = "2024-01-10T11:02:15.191Z" }, + { url = "https://files.pythonhosted.org/packages/17/ae/cd055c2c081c67a6fcad1d8d17d82bd6395b14c6741e3a938f40318c8bc5/Cython-3.0.8-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c26daaeccda072459b48d211415fd1e5507c06bcd976fa0d5b8b9f1063467d7b", size = 3458119, upload_time = "2024-01-10T11:02:19.103Z" }, + { url = "https://files.pythonhosted.org/packages/72/ab/ac6f5548d6194f4bb2fc8c6c996aa7369f0fa1403e4d4de787d9e9309b27/Cython-3.0.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:289ce7838208211cd166e975865fd73b0649bf118170b6cebaedfbdaf4a37795", size = 3614418, upload_time = "2024-01-10T11:02:22.732Z" }, + { url = "https://files.pythonhosted.org/packages/70/e2/3e3e448b7a94887bec3235bcb71957b6681dc42b4536459f8f54d46fa936/Cython-3.0.8-cp311-cp311-win32.whl", hash = "sha256:c8aa05f5e17f8042a3be052c24f2edc013fb8af874b0bf76907d16c51b4e7871", size = 2572819, upload_time = "2024-01-10T11:02:25.976Z" }, + { url = "https://files.pythonhosted.org/packages/85/7d/58635941dfbb5b4e197adb88080b9cbfb230dc3b75683698a530a1989bdb/Cython-3.0.8-cp311-cp311-win_amd64.whl", hash = "sha256:000dc9e135d0eec6ecb2b40a5b02d0868a2f8d2e027a41b0fe16a908a9e6de02", size = 2784167, upload_time = "2024-01-10T11:02:28.808Z" }, + { url = "https://files.pythonhosted.org/packages/3d/8e/28f8c6109990eef7317ab7e43644092b49a88a39f9373dcd19318946df09/Cython-3.0.8-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:90d3fe31db55685d8cb97d43b0ec39ef614fcf660f83c77ed06aa670cb0e164f", size = 3135638, upload_time = "2024-01-10T11:34:22.889Z" }, + { url = "https://files.pythonhosted.org/packages/83/1f/4720cb682b8ed1ab9749dea35351a66dd29b6a022628cce038415660c384/Cython-3.0.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e24791ddae2324e88e3c902a765595c738f19ae34ee66bfb1a6dac54b1833419", size = 3340052, upload_time = "2024-01-10T11:02:32.471Z" }, + { url = "https://files.pythonhosted.org/packages/8a/47/ec3fceb9e8f7d6fa130216b8740038e1df7c8e5f215bba363fcf1272a6c1/Cython-3.0.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f020fa1c0552052e0660790b8153b79e3fc9a15dbd8f1d0b841fe5d204a6ae6", size = 3510079, upload_time = "2024-01-10T11:02:35.312Z" }, + { url = "https://files.pythonhosted.org/packages/71/31/b458127851e248effb909e2791b55870914863cde7c60b94db5ee65d7867/Cython-3.0.8-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18bfa387d7a7f77d7b2526af69a65dbd0b731b8d941aaff5becff8e21f6d7717", size = 3573972, upload_time = "2024-01-10T11:02:39.044Z" }, + { url = "https://files.pythonhosted.org/packages/6b/d5/ca6513844d0634abd05ba12304053a454bb70441a9520afa9897d4300156/Cython-3.0.8-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:fe81b339cffd87c0069c6049b4d33e28bdd1874625ee515785bf42c9fdff3658", size = 3356158, upload_time = "2024-01-10T11:02:42.125Z" }, + { url = "https://files.pythonhosted.org/packages/33/59/98a87b6264f4ad45c820db13c4ec657567476efde020c49443cc842a86af/Cython-3.0.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:80fd94c076e1e1b1ee40a309be03080b75f413e8997cddcf401a118879863388", size = 3522312, upload_time = "2024-01-10T11:02:45.056Z" }, + { url = "https://files.pythonhosted.org/packages/2b/cb/132115d07a0b9d4f075e0741db70a5416b424dcd875b2bb0dd805e818222/Cython-3.0.8-cp312-cp312-win32.whl", hash = "sha256:85077915a93e359a9b920280d214dc0cf8a62773e1f3d7d30fab8ea4daed670c", size = 2602579, upload_time = "2024-01-10T11:02:48.368Z" }, + { url = "https://files.pythonhosted.org/packages/b4/69/cb4620287cd9ef461103e122c0a2ae7f7ecf183e02510676fb5a15c95b05/Cython-3.0.8-cp312-cp312-win_amd64.whl", hash = "sha256:0cb2dcc565c7851f75d496f724a384a790fab12d1b82461b663e66605bec429a", size = 2791268, upload_time = "2024-01-10T11:02:51.483Z" }, + { url = "https://files.pythonhosted.org/packages/e3/7f/f584f5d15323feb897d42ef0e9d910649e2150d7a30cf7e7a8cc1d236e6f/Cython-3.0.8-py2.py3-none-any.whl", hash = "sha256:171b27051253d3f9108e9759e504ba59ff06e7f7ba944457f94deaf9c21bf0b6", size = 1168213, upload_time = "2024-01-10T11:00:56.857Z" }, ] [[package]] name = "easydict" version = "1.11" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0a/d2/deb3296d08097fedd622d423c0ec8b68b78c1704b3f1545326f6ce05c75c/easydict-1.11.tar.gz", hash = "sha256:dcb1d2ed28eb300c8e46cd371340373abc62f7c14d6dea74fdfc6f1069061c78", size = 6644 } +sdist = { url = "https://files.pythonhosted.org/packages/0a/d2/deb3296d08097fedd622d423c0ec8b68b78c1704b3f1545326f6ce05c75c/easydict-1.11.tar.gz", hash = "sha256:dcb1d2ed28eb300c8e46cd371340373abc62f7c14d6dea74fdfc6f1069061c78", size = 6644, upload_time = "2023-10-23T23:01:37.686Z" } [[package]] name = "exceptiongroup" version = "1.2.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8e/1c/beef724eaf5b01bb44b6338c8c3494eff7cab376fab4904cfbbc3585dc79/exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68", size = 26264 } +sdist = { url = "https://files.pythonhosted.org/packages/8e/1c/beef724eaf5b01bb44b6338c8c3494eff7cab376fab4904cfbbc3585dc79/exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68", size = 26264, upload_time = "2023-11-21T08:42:17.407Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b8/9a/5028fd52db10e600f1c4674441b968cf2ea4959085bfb5b99fb1250e5f68/exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14", size = 16210 }, + { url = "https://files.pythonhosted.org/packages/b8/9a/5028fd52db10e600f1c4674441b968cf2ea4959085bfb5b99fb1250e5f68/exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14", size = 16210, upload_time = "2023-11-21T08:42:15.525Z" }, ] [[package]] @@ -515,18 +524,18 @@ dependencies = [ { name = "starlette" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f4/55/ae499352d82338331ca1e28c7f4a63bfd09479b16395dce38cf50a39e2c2/fastapi-0.115.12.tar.gz", hash = "sha256:1e2c2a2646905f9e83d32f04a3f86aff4a286669c6c950ca95b5fd68c2602681", size = 295236 } +sdist = { url = "https://files.pythonhosted.org/packages/f4/55/ae499352d82338331ca1e28c7f4a63bfd09479b16395dce38cf50a39e2c2/fastapi-0.115.12.tar.gz", hash = "sha256:1e2c2a2646905f9e83d32f04a3f86aff4a286669c6c950ca95b5fd68c2602681", size = 295236, upload_time = "2025-03-23T22:55:43.822Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/50/b3/b51f09c2ba432a576fe63758bddc81f78f0c6309d9e5c10d194313bf021e/fastapi-0.115.12-py3-none-any.whl", hash = "sha256:e94613d6c05e27be7ffebdd6ea5f388112e5e430c8f7d6494a9d1d88d43e814d", size = 95164 }, + { url = "https://files.pythonhosted.org/packages/50/b3/b51f09c2ba432a576fe63758bddc81f78f0c6309d9e5c10d194313bf021e/fastapi-0.115.12-py3-none-any.whl", hash = "sha256:e94613d6c05e27be7ffebdd6ea5f388112e5e430c8f7d6494a9d1d88d43e814d", size = 95164, upload_time = "2025-03-23T22:55:42.101Z" }, ] [[package]] name = "filelock" version = "3.13.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/70/70/41905c80dcfe71b22fb06827b8eae65781783d4a14194bce79d16a013263/filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e", size = 14553 } +sdist = { url = "https://files.pythonhosted.org/packages/70/70/41905c80dcfe71b22fb06827b8eae65781783d4a14194bce79d16a013263/filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e", size = 14553, upload_time = "2023-10-30T18:29:39.035Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c", size = 11740 }, + { url = "https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c", size = 11740, upload_time = "2023-10-30T18:29:37.267Z" }, ] [[package]] @@ -540,9 +549,9 @@ dependencies = [ { name = "jinja2" }, { name = "werkzeug" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d8/09/c1a7354d3925a3c6c8cfdebf4245bae67d633ffda1ba415add06ffc839c5/flask-3.0.0.tar.gz", hash = "sha256:cfadcdb638b609361d29ec22360d6070a77d7463dcb3ab08d2c2f2f168845f58", size = 674171 } +sdist = { url = "https://files.pythonhosted.org/packages/d8/09/c1a7354d3925a3c6c8cfdebf4245bae67d633ffda1ba415add06ffc839c5/flask-3.0.0.tar.gz", hash = "sha256:cfadcdb638b609361d29ec22360d6070a77d7463dcb3ab08d2c2f2f168845f58", size = 674171, upload_time = "2023-09-30T14:36:12.918Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/36/42/015c23096649b908c809c69388a805a571a3bea44362fe87e33fc3afa01f/flask-3.0.0-py3-none-any.whl", hash = "sha256:21128f47e4e3b9d597a3e8521a329bf56909b690fcc3fa3e477725aa81367638", size = 99724 }, + { url = "https://files.pythonhosted.org/packages/36/42/015c23096649b908c809c69388a805a571a3bea44362fe87e33fc3afa01f/flask-3.0.0-py3-none-any.whl", hash = "sha256:21128f47e4e3b9d597a3e8521a329bf56909b690fcc3fa3e477725aa81367638", size = 99724, upload_time = "2023-09-30T14:36:10.961Z" }, ] [[package]] @@ -552,9 +561,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "flask" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/40/6a/a8d56d60bcfa1ec3e4fdad81b45aafd508c3bd5c244a16526fa29139d7d4/flask_cors-4.0.1.tar.gz", hash = "sha256:eeb69b342142fdbf4766ad99357a7f3876a2ceb77689dc10ff912aac06c389e4", size = 30306 } +sdist = { url = "https://files.pythonhosted.org/packages/40/6a/a8d56d60bcfa1ec3e4fdad81b45aafd508c3bd5c244a16526fa29139d7d4/flask_cors-4.0.1.tar.gz", hash = "sha256:eeb69b342142fdbf4766ad99357a7f3876a2ceb77689dc10ff912aac06c389e4", size = 30306, upload_time = "2024-05-04T19:49:43.538Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/52/2aa6285f104616f73ee1ad7905a16b2b35af0143034ad0cf7b64bcba715c/Flask_Cors-4.0.1-py2.py3-none-any.whl", hash = "sha256:f2a704e4458665580c074b714c4627dd5a306b333deb9074d0b1794dfa2fb677", size = 14290 }, + { url = "https://files.pythonhosted.org/packages/8b/52/2aa6285f104616f73ee1ad7905a16b2b35af0143034ad0cf7b64bcba715c/Flask_Cors-4.0.1-py2.py3-none-any.whl", hash = "sha256:f2a704e4458665580c074b714c4627dd5a306b333deb9074d0b1794dfa2fb677", size = 14290, upload_time = "2024-05-04T19:49:41.721Z" }, ] [[package]] @@ -565,60 +574,60 @@ dependencies = [ { name = "flask" }, { name = "werkzeug" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c3/6e/2f4e13e373bb49e68c02c51ceadd22d172715a06716f9299d9df01b6ddb2/Flask-Login-0.6.3.tar.gz", hash = "sha256:5e23d14a607ef12806c699590b89d0f0e0d67baeec599d75947bf9c147330333", size = 48834 } +sdist = { url = "https://files.pythonhosted.org/packages/c3/6e/2f4e13e373bb49e68c02c51ceadd22d172715a06716f9299d9df01b6ddb2/Flask-Login-0.6.3.tar.gz", hash = "sha256:5e23d14a607ef12806c699590b89d0f0e0d67baeec599d75947bf9c147330333", size = 48834, upload_time = "2023-10-30T14:53:21.151Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/59/f5/67e9cc5c2036f58115f9fe0f00d203cf6780c3ff8ae0e705e7a9d9e8ff9e/Flask_Login-0.6.3-py3-none-any.whl", hash = "sha256:849b25b82a436bf830a054e74214074af59097171562ab10bfa999e6b78aae5d", size = 17303 }, + { url = "https://files.pythonhosted.org/packages/59/f5/67e9cc5c2036f58115f9fe0f00d203cf6780c3ff8ae0e705e7a9d9e8ff9e/Flask_Login-0.6.3-py3-none-any.whl", hash = "sha256:849b25b82a436bf830a054e74214074af59097171562ab10bfa999e6b78aae5d", size = 17303, upload_time = "2023-10-30T14:53:19.636Z" }, ] [[package]] name = "flatbuffers" version = "23.5.26" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0c/6e/3e52cd294d8e7a61e010973cce076a0cb2c6c0dfd4d0b7a13648c1b98329/flatbuffers-23.5.26.tar.gz", hash = "sha256:9ea1144cac05ce5d86e2859f431c6cd5e66cd9c78c558317c7955fb8d4c78d89", size = 22114 } +sdist = { url = "https://files.pythonhosted.org/packages/0c/6e/3e52cd294d8e7a61e010973cce076a0cb2c6c0dfd4d0b7a13648c1b98329/flatbuffers-23.5.26.tar.gz", hash = "sha256:9ea1144cac05ce5d86e2859f431c6cd5e66cd9c78c558317c7955fb8d4c78d89", size = 22114, upload_time = "2023-05-26T17:35:16.034Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6f/12/d5c79ee252793ffe845d58a913197bfa02ae9a0b5c9bc3dc4b58d477b9e7/flatbuffers-23.5.26-py2.py3-none-any.whl", hash = "sha256:c0ff356da363087b915fde4b8b45bdda73432fc17cddb3c8157472eab1422ad1", size = 26744 }, + { url = "https://files.pythonhosted.org/packages/6f/12/d5c79ee252793ffe845d58a913197bfa02ae9a0b5c9bc3dc4b58d477b9e7/flatbuffers-23.5.26-py2.py3-none-any.whl", hash = "sha256:c0ff356da363087b915fde4b8b45bdda73432fc17cddb3c8157472eab1422ad1", size = 26744, upload_time = "2023-05-26T17:35:14.269Z" }, ] [[package]] name = "fonttools" version = "4.47.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e5/cd/75d24afa673edf92fd04657fad7d3b5e20c4abc3cad5bc14e5e30051c1f0/fonttools-4.47.2.tar.gz", hash = "sha256:7df26dd3650e98ca45f1e29883c96a0b9f5bb6af8d632a6a108bc744fa0bd9b3", size = 3410067 } +sdist = { url = "https://files.pythonhosted.org/packages/e5/cd/75d24afa673edf92fd04657fad7d3b5e20c4abc3cad5bc14e5e30051c1f0/fonttools-4.47.2.tar.gz", hash = "sha256:7df26dd3650e98ca45f1e29883c96a0b9f5bb6af8d632a6a108bc744fa0bd9b3", size = 3410067, upload_time = "2024-01-11T11:22:45.293Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/19/30/02de0b7f3d72f2c4fce3e512b166c1bdbe5a687408474b61eb0114be921c/fonttools-4.47.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3b629108351d25512d4ea1a8393a2dba325b7b7d7308116b605ea3f8e1be88df", size = 2779949 }, - { url = "https://files.pythonhosted.org/packages/9a/52/1a5e1373afb78a040ea0c371ab8a79da121060a8e518968bb8f41457ca90/fonttools-4.47.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c19044256c44fe299d9a73456aabee4b4d06c6b930287be93b533b4737d70aa1", size = 2281336 }, - { url = "https://files.pythonhosted.org/packages/c5/ce/9d3b5bf51aafee024566ebb374f5b040381d92660cb04647af3c5860c611/fonttools-4.47.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8be28c036b9f186e8c7eaf8a11b42373e7e4949f9e9f370202b9da4c4c3f56c", size = 4541692 }, - { url = "https://files.pythonhosted.org/packages/e8/68/af41b7cfd35c7418e17b6a43bb106be4b0f0e5feb405a88dee29b186f2a7/fonttools-4.47.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f83a4daef6d2a202acb9bf572958f91cfde5b10c8ee7fb1d09a4c81e5d851fd8", size = 4600529 }, - { url = "https://files.pythonhosted.org/packages/ab/7e/428dbb4cfc342b7a05cbc9d349e134e7fad6588f4ce2a7128e8e3e58ad3b/fonttools-4.47.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a5a5318ba5365d992666ac4fe35365f93004109d18858a3e18ae46f67907670", size = 4524215 }, - { url = "https://files.pythonhosted.org/packages/a6/61/762fad1cc1debc4626f2eb373fa999591c63c231fce53d5073574a639531/fonttools-4.47.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8f57ecd742545362a0f7186774b2d1c53423ed9ece67689c93a1055b236f638c", size = 4584778 }, - { url = "https://files.pythonhosted.org/packages/04/30/170ca22284c1d825470e8b5871d6b25d3a70e2f5b185ffb1647d5e11ee4d/fonttools-4.47.2-cp310-cp310-win32.whl", hash = "sha256:a1c154bb85dc9a4cf145250c88d112d88eb414bad81d4cb524d06258dea1bdc0", size = 2131876 }, - { url = "https://files.pythonhosted.org/packages/df/07/4a30437bed355b838b8ce31d14c5983334c31adc97e70c6ecff90c60d6d2/fonttools-4.47.2-cp310-cp310-win_amd64.whl", hash = "sha256:3e2b95dce2ead58fb12524d0ca7d63a63459dd489e7e5838c3cd53557f8933e1", size = 2177937 }, - { url = "https://files.pythonhosted.org/packages/dd/1d/670372323642eada0f7743cfcdd156de6a28d37769c916421fec2f32c814/fonttools-4.47.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:29495d6d109cdbabe73cfb6f419ce67080c3ef9ea1e08d5750240fd4b0c4763b", size = 2782908 }, - { url = "https://files.pythonhosted.org/packages/c1/36/5f0bb863a6575db4c4b67fa9be7f98e4c551dd87638ef327bc180b988998/fonttools-4.47.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0a1d313a415eaaba2b35d6cd33536560deeebd2ed758b9bfb89ab5d97dc5deac", size = 2283501 }, - { url = "https://files.pythonhosted.org/packages/bd/1e/95de682a86567426bcc40a56c9b118ffa97de6cbfcc293addf20994e329d/fonttools-4.47.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90f898cdd67f52f18049250a6474185ef6544c91f27a7bee70d87d77a8daf89c", size = 4848039 }, - { url = "https://files.pythonhosted.org/packages/ef/95/92a0b5fc844c1db734752f8a51431de519cd6b02e7e561efa9e9fd415544/fonttools-4.47.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3480eeb52770ff75140fe7d9a2ec33fb67b07efea0ab5129c7e0c6a639c40c70", size = 4893166 }, - { url = "https://files.pythonhosted.org/packages/ff/e6/ed9dd7ee1afd6cd70eb7237688118fe489dbde962e3765c91c86c095f84b/fonttools-4.47.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0255dbc128fee75fb9be364806b940ed450dd6838672a150d501ee86523ac61e", size = 4815529 }, - { url = "https://files.pythonhosted.org/packages/6b/67/cdffa0b3cd8f863b45125c335bbd3d9dc16ec42f5a8d5b64dd1244c5ce6b/fonttools-4.47.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f791446ff297fd5f1e2247c188de53c1bfb9dd7f0549eba55b73a3c2087a2703", size = 4875414 }, - { url = "https://files.pythonhosted.org/packages/b8/fb/41638e748c8f20f5483987afcf9be746d3ccb9e9600ca62128a27c791a82/fonttools-4.47.2-cp311-cp311-win32.whl", hash = "sha256:740947906590a878a4bde7dd748e85fefa4d470a268b964748403b3ab2aeed6c", size = 2130073 }, - { url = "https://files.pythonhosted.org/packages/a0/ef/93321cf55180a778b4d97919b28739874c0afab90e7b9f5b232db70f47c2/fonttools-4.47.2-cp311-cp311-win_amd64.whl", hash = "sha256:63fbed184979f09a65aa9c88b395ca539c94287ba3a364517698462e13e457c9", size = 2178744 }, - { url = "https://files.pythonhosted.org/packages/c0/bd/4dd1e8a9e632f325d9203ce543402f912f26efd213c8d9efec0180fbac64/fonttools-4.47.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4ec558c543609e71b2275c4894e93493f65d2f41c15fe1d089080c1d0bb4d635", size = 2754076 }, - { url = "https://files.pythonhosted.org/packages/e6/4d/c2ebaac81dadbc3fc3c3c2fa5fe7b16429dc713b1b8ace49e11e92904d78/fonttools-4.47.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e040f905d542362e07e72e03612a6270c33d38281fd573160e1003e43718d68d", size = 2263784 }, - { url = "https://files.pythonhosted.org/packages/d3/f6/9d484cd275845c7e503a8669a5952a7fa089c7a881babb4dce5ebe6fc5d1/fonttools-4.47.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6dd58cc03016b281bd2c74c84cdaa6bd3ce54c5a7f47478b7657b930ac3ed8eb", size = 4769142 }, - { url = "https://files.pythonhosted.org/packages/7a/bf/c6ae0768a531b38245aac0bb8d30bc05d53d499e09fccdc5d72e7c8d28b6/fonttools-4.47.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32ab2e9702dff0dd4510c7bb958f265a8d3dd5c0e2547e7b5f7a3df4979abb07", size = 4853241 }, - { url = "https://files.pythonhosted.org/packages/2b/f0/c06709666cb7722447efb70ea456c302bd6eb3b997d30076401fb32bca4b/fonttools-4.47.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3a808f3c1d1df1f5bf39be869b6e0c263570cdafb5bdb2df66087733f566ea71", size = 4730447 }, - { url = "https://files.pythonhosted.org/packages/3e/71/4c758ae5f4f8047904fc1c6bbbb828248c94cc7aa6406af3a62ede766f25/fonttools-4.47.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ac71e2e201df041a2891067dc36256755b1229ae167edbdc419b16da78732c2f", size = 4809265 }, - { url = "https://files.pythonhosted.org/packages/81/f6/a6912c11280607d48947341e2167502605a3917925c835afcd7dfcabc289/fonttools-4.47.2-cp312-cp312-win32.whl", hash = "sha256:69731e8bea0578b3c28fdb43dbf95b9386e2d49a399e9a4ad736b8e479b08085", size = 2118363 }, - { url = "https://files.pythonhosted.org/packages/81/4b/42d0488765ea5aa308b4e8197cb75366b2124240a73e86f98b6107ccf282/fonttools-4.47.2-cp312-cp312-win_amd64.whl", hash = "sha256:b3e1304e5f19ca861d86a72218ecce68f391646d85c851742d265787f55457a4", size = 2165866 }, - { url = "https://files.pythonhosted.org/packages/af/2f/c34b0f99d46766cf49566d1ee2ee3606e4c9880b5a7d734257dc61c804e9/fonttools-4.47.2-py3-none-any.whl", hash = "sha256:7eb7ad665258fba68fd22228a09f347469d95a97fb88198e133595947a20a184", size = 1063011 }, + { url = "https://files.pythonhosted.org/packages/19/30/02de0b7f3d72f2c4fce3e512b166c1bdbe5a687408474b61eb0114be921c/fonttools-4.47.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3b629108351d25512d4ea1a8393a2dba325b7b7d7308116b605ea3f8e1be88df", size = 2779949, upload_time = "2024-01-11T11:19:56.276Z" }, + { url = "https://files.pythonhosted.org/packages/9a/52/1a5e1373afb78a040ea0c371ab8a79da121060a8e518968bb8f41457ca90/fonttools-4.47.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c19044256c44fe299d9a73456aabee4b4d06c6b930287be93b533b4737d70aa1", size = 2281336, upload_time = "2024-01-11T11:20:08.835Z" }, + { url = "https://files.pythonhosted.org/packages/c5/ce/9d3b5bf51aafee024566ebb374f5b040381d92660cb04647af3c5860c611/fonttools-4.47.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8be28c036b9f186e8c7eaf8a11b42373e7e4949f9e9f370202b9da4c4c3f56c", size = 4541692, upload_time = "2024-01-11T11:20:13.378Z" }, + { url = "https://files.pythonhosted.org/packages/e8/68/af41b7cfd35c7418e17b6a43bb106be4b0f0e5feb405a88dee29b186f2a7/fonttools-4.47.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f83a4daef6d2a202acb9bf572958f91cfde5b10c8ee7fb1d09a4c81e5d851fd8", size = 4600529, upload_time = "2024-01-11T11:20:17.27Z" }, + { url = "https://files.pythonhosted.org/packages/ab/7e/428dbb4cfc342b7a05cbc9d349e134e7fad6588f4ce2a7128e8e3e58ad3b/fonttools-4.47.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a5a5318ba5365d992666ac4fe35365f93004109d18858a3e18ae46f67907670", size = 4524215, upload_time = "2024-01-11T11:20:21.061Z" }, + { url = "https://files.pythonhosted.org/packages/a6/61/762fad1cc1debc4626f2eb373fa999591c63c231fce53d5073574a639531/fonttools-4.47.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8f57ecd742545362a0f7186774b2d1c53423ed9ece67689c93a1055b236f638c", size = 4584778, upload_time = "2024-01-11T11:20:25.815Z" }, + { url = "https://files.pythonhosted.org/packages/04/30/170ca22284c1d825470e8b5871d6b25d3a70e2f5b185ffb1647d5e11ee4d/fonttools-4.47.2-cp310-cp310-win32.whl", hash = "sha256:a1c154bb85dc9a4cf145250c88d112d88eb414bad81d4cb524d06258dea1bdc0", size = 2131876, upload_time = "2024-01-11T11:20:30.261Z" }, + { url = "https://files.pythonhosted.org/packages/df/07/4a30437bed355b838b8ce31d14c5983334c31adc97e70c6ecff90c60d6d2/fonttools-4.47.2-cp310-cp310-win_amd64.whl", hash = "sha256:3e2b95dce2ead58fb12524d0ca7d63a63459dd489e7e5838c3cd53557f8933e1", size = 2177937, upload_time = "2024-01-11T11:20:33.814Z" }, + { url = "https://files.pythonhosted.org/packages/dd/1d/670372323642eada0f7743cfcdd156de6a28d37769c916421fec2f32c814/fonttools-4.47.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:29495d6d109cdbabe73cfb6f419ce67080c3ef9ea1e08d5750240fd4b0c4763b", size = 2782908, upload_time = "2024-01-11T11:20:37.495Z" }, + { url = "https://files.pythonhosted.org/packages/c1/36/5f0bb863a6575db4c4b67fa9be7f98e4c551dd87638ef327bc180b988998/fonttools-4.47.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0a1d313a415eaaba2b35d6cd33536560deeebd2ed758b9bfb89ab5d97dc5deac", size = 2283501, upload_time = "2024-01-11T11:20:42.027Z" }, + { url = "https://files.pythonhosted.org/packages/bd/1e/95de682a86567426bcc40a56c9b118ffa97de6cbfcc293addf20994e329d/fonttools-4.47.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90f898cdd67f52f18049250a6474185ef6544c91f27a7bee70d87d77a8daf89c", size = 4848039, upload_time = "2024-01-11T11:20:47.038Z" }, + { url = "https://files.pythonhosted.org/packages/ef/95/92a0b5fc844c1db734752f8a51431de519cd6b02e7e561efa9e9fd415544/fonttools-4.47.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3480eeb52770ff75140fe7d9a2ec33fb67b07efea0ab5129c7e0c6a639c40c70", size = 4893166, upload_time = "2024-01-11T11:20:50.855Z" }, + { url = "https://files.pythonhosted.org/packages/ff/e6/ed9dd7ee1afd6cd70eb7237688118fe489dbde962e3765c91c86c095f84b/fonttools-4.47.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0255dbc128fee75fb9be364806b940ed450dd6838672a150d501ee86523ac61e", size = 4815529, upload_time = "2024-01-11T11:20:54.696Z" }, + { url = "https://files.pythonhosted.org/packages/6b/67/cdffa0b3cd8f863b45125c335bbd3d9dc16ec42f5a8d5b64dd1244c5ce6b/fonttools-4.47.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f791446ff297fd5f1e2247c188de53c1bfb9dd7f0549eba55b73a3c2087a2703", size = 4875414, upload_time = "2024-01-11T11:20:58.435Z" }, + { url = "https://files.pythonhosted.org/packages/b8/fb/41638e748c8f20f5483987afcf9be746d3ccb9e9600ca62128a27c791a82/fonttools-4.47.2-cp311-cp311-win32.whl", hash = "sha256:740947906590a878a4bde7dd748e85fefa4d470a268b964748403b3ab2aeed6c", size = 2130073, upload_time = "2024-01-11T11:21:02.056Z" }, + { url = "https://files.pythonhosted.org/packages/a0/ef/93321cf55180a778b4d97919b28739874c0afab90e7b9f5b232db70f47c2/fonttools-4.47.2-cp311-cp311-win_amd64.whl", hash = "sha256:63fbed184979f09a65aa9c88b395ca539c94287ba3a364517698462e13e457c9", size = 2178744, upload_time = "2024-01-11T11:21:05.88Z" }, + { url = "https://files.pythonhosted.org/packages/c0/bd/4dd1e8a9e632f325d9203ce543402f912f26efd213c8d9efec0180fbac64/fonttools-4.47.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4ec558c543609e71b2275c4894e93493f65d2f41c15fe1d089080c1d0bb4d635", size = 2754076, upload_time = "2024-01-11T11:21:09.745Z" }, + { url = "https://files.pythonhosted.org/packages/e6/4d/c2ebaac81dadbc3fc3c3c2fa5fe7b16429dc713b1b8ace49e11e92904d78/fonttools-4.47.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e040f905d542362e07e72e03612a6270c33d38281fd573160e1003e43718d68d", size = 2263784, upload_time = "2024-01-11T11:21:13.367Z" }, + { url = "https://files.pythonhosted.org/packages/d3/f6/9d484cd275845c7e503a8669a5952a7fa089c7a881babb4dce5ebe6fc5d1/fonttools-4.47.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6dd58cc03016b281bd2c74c84cdaa6bd3ce54c5a7f47478b7657b930ac3ed8eb", size = 4769142, upload_time = "2024-01-11T11:21:17.615Z" }, + { url = "https://files.pythonhosted.org/packages/7a/bf/c6ae0768a531b38245aac0bb8d30bc05d53d499e09fccdc5d72e7c8d28b6/fonttools-4.47.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32ab2e9702dff0dd4510c7bb958f265a8d3dd5c0e2547e7b5f7a3df4979abb07", size = 4853241, upload_time = "2024-01-11T11:21:21.16Z" }, + { url = "https://files.pythonhosted.org/packages/2b/f0/c06709666cb7722447efb70ea456c302bd6eb3b997d30076401fb32bca4b/fonttools-4.47.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3a808f3c1d1df1f5bf39be869b6e0c263570cdafb5bdb2df66087733f566ea71", size = 4730447, upload_time = "2024-01-11T11:21:24.755Z" }, + { url = "https://files.pythonhosted.org/packages/3e/71/4c758ae5f4f8047904fc1c6bbbb828248c94cc7aa6406af3a62ede766f25/fonttools-4.47.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ac71e2e201df041a2891067dc36256755b1229ae167edbdc419b16da78732c2f", size = 4809265, upload_time = "2024-01-11T11:21:28.586Z" }, + { url = "https://files.pythonhosted.org/packages/81/f6/a6912c11280607d48947341e2167502605a3917925c835afcd7dfcabc289/fonttools-4.47.2-cp312-cp312-win32.whl", hash = "sha256:69731e8bea0578b3c28fdb43dbf95b9386e2d49a399e9a4ad736b8e479b08085", size = 2118363, upload_time = "2024-01-11T11:21:33.245Z" }, + { url = "https://files.pythonhosted.org/packages/81/4b/42d0488765ea5aa308b4e8197cb75366b2124240a73e86f98b6107ccf282/fonttools-4.47.2-cp312-cp312-win_amd64.whl", hash = "sha256:b3e1304e5f19ca861d86a72218ecce68f391646d85c851742d265787f55457a4", size = 2165866, upload_time = "2024-01-11T11:21:37.23Z" }, + { url = "https://files.pythonhosted.org/packages/af/2f/c34b0f99d46766cf49566d1ee2ee3606e4c9880b5a7d734257dc61c804e9/fonttools-4.47.2-py3-none-any.whl", hash = "sha256:7eb7ad665258fba68fd22228a09f347469d95a97fb88198e133595947a20a184", size = 1063011, upload_time = "2024-01-11T11:22:41.676Z" }, ] [[package]] name = "fsspec" version = "2023.12.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fa/08/cac914ff6ff46c4500fc4323a939dbe7a0f528cca04e7fd3e859611dea41/fsspec-2023.12.2.tar.gz", hash = "sha256:8548d39e8810b59c38014934f6b31e57f40c1b20f911f4cc2b85389c7e9bf0cb", size = 167507 } +sdist = { url = "https://files.pythonhosted.org/packages/fa/08/cac914ff6ff46c4500fc4323a939dbe7a0f528cca04e7fd3e859611dea41/fsspec-2023.12.2.tar.gz", hash = "sha256:8548d39e8810b59c38014934f6b31e57f40c1b20f911f4cc2b85389c7e9bf0cb", size = 167507, upload_time = "2023-12-11T21:19:54.832Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/70/25/fab23259a52ece5670dcb8452e1af34b89e6135ecc17cd4b54b4b479eac6/fsspec-2023.12.2-py3-none-any.whl", hash = "sha256:d800d87f72189a745fa3d6b033b9dc4a34ad069f60ca60b943a63599f5501960", size = 168979 }, + { url = "https://files.pythonhosted.org/packages/70/25/fab23259a52ece5670dcb8452e1af34b89e6135ecc17cd4b54b4b479eac6/fsspec-2023.12.2-py3-none-any.whl", hash = "sha256:d800d87f72189a745fa3d6b033b9dc4a34ad069f60ca60b943a63599f5501960", size = 168979, upload_time = "2023-12-11T21:19:52.446Z" }, ] [[package]] @@ -628,9 +637,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "wcwidth" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a5/d3/8650919bc3c7c6e90ee3fa7fd618bf373cbbe55dff043bd67353dbb20cd8/ftfy-6.3.1.tar.gz", hash = "sha256:9b3c3d90f84fb267fe64d375a07b7f8912d817cf86009ae134aa03e1819506ec", size = 308927 } +sdist = { url = "https://files.pythonhosted.org/packages/a5/d3/8650919bc3c7c6e90ee3fa7fd618bf373cbbe55dff043bd67353dbb20cd8/ftfy-6.3.1.tar.gz", hash = "sha256:9b3c3d90f84fb267fe64d375a07b7f8912d817cf86009ae134aa03e1819506ec", size = 308927, upload_time = "2024-10-26T00:50:35.149Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ab/6e/81d47999aebc1b155f81eca4477a616a70f238a2549848c38983f3c22a82/ftfy-6.3.1-py3-none-any.whl", hash = "sha256:7c70eb532015cd2f9adb53f101fb6c7945988d023a085d127d1573dc49dd0083", size = 44821 }, + { url = "https://files.pythonhosted.org/packages/ab/6e/81d47999aebc1b155f81eca4477a616a70f238a2549848c38983f3c22a82/ftfy-6.3.1-py3-none-any.whl", hash = "sha256:7c70eb532015cd2f9adb53f101fb6c7945988d023a085d127d1573dc49dd0083", size = 44821, upload_time = "2024-10-26T00:50:33.425Z" }, ] [[package]] @@ -643,41 +652,41 @@ dependencies = [ { name = "zope-event" }, { name = "zope-interface" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/70/f0/be10ed5d7721ed2317d7feb59e167603217156c2a6d57f128523e24e673d/gevent-24.10.3.tar.gz", hash = "sha256:aa7ee1bd5cabb2b7ef35105f863b386c8d5e332f754b60cfc354148bd70d35d1", size = 6108837 } +sdist = { url = "https://files.pythonhosted.org/packages/70/f0/be10ed5d7721ed2317d7feb59e167603217156c2a6d57f128523e24e673d/gevent-24.10.3.tar.gz", hash = "sha256:aa7ee1bd5cabb2b7ef35105f863b386c8d5e332f754b60cfc354148bd70d35d1", size = 6108837, upload_time = "2024-10-18T16:06:25.867Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6b/6f/a2100e7883c7bdfc2b45cb60b310ca748762a21596258b9dd01c5c093dbc/gevent-24.10.3-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:d7a1ad0f2da582f5bd238bca067e1c6c482c30c15a6e4d14aaa3215cbb2232f3", size = 3014382 }, - { url = "https://files.pythonhosted.org/packages/7a/b1/460e4884ed6185d9eb9c4c2e9639d2b254197e46513301c0f63dec22dc90/gevent-24.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4e526fdc279c655c1e809b0c34b45844182c2a6b219802da5e411bd2cf5a8ad", size = 4853460 }, - { url = "https://files.pythonhosted.org/packages/ca/f6/7ded98760d381229183ecce8db2edcce96f13e23807d31a90c66dae85304/gevent-24.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57a5c4e0bdac482c5f02f240d0354e61362df73501ef6ebafce8ef635cad7527", size = 4977636 }, - { url = "https://files.pythonhosted.org/packages/7d/21/7b928e6029eedb93ef94fc0aee701f497af2e601f0ec00aac0e72e3f450e/gevent-24.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d67daed8383326dc8b5e58d88e148d29b6b52274a489e383530b0969ae7b9cb9", size = 5058031 }, - { url = "https://files.pythonhosted.org/packages/00/98/12c03fd004fbeeca01276ffc589f5a368fd741d02582ab7006d1bdef57e7/gevent-24.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e24ffea72e27987979c009536fd0868e52239b44afe6cf7135ce8aafd0f108e", size = 6683694 }, - { url = "https://files.pythonhosted.org/packages/64/4c/ea14d971452d3da09e49267e052d8312f112c7835120aed78d22ef14efee/gevent-24.10.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c1d80090485da1ea3d99205fe97908b31188c1f4857f08b333ffaf2de2e89d18", size = 5286063 }, - { url = "https://files.pythonhosted.org/packages/39/3f/397efff27e637d7306caa00d1560512c44028c25c70be1e72c46b79b1b66/gevent-24.10.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f0c129f81d60cda614acb4b0c5731997ca05b031fb406fcb58ad53a7ade53b13", size = 6817462 }, - { url = "https://files.pythonhosted.org/packages/aa/5d/19939eaa7c5b7c0f37e0a0665a911ddfe1e35c25c512446fc356a065c16e/gevent-24.10.3-cp310-cp310-win_amd64.whl", hash = "sha256:26ca7a6b42d35129617025ac801135118333cad75856ffc3217b38e707383eba", size = 1566631 }, - { url = "https://files.pythonhosted.org/packages/6e/01/1be5cf013826d8baae235976d6a94f3628014fd2db7c071aeec13f82b4d1/gevent-24.10.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:68c3a0d8402755eba7f69022e42e8021192a721ca8341908acc222ea597029b6", size = 2966909 }, - { url = "https://files.pythonhosted.org/packages/fe/3e/7fa9ab023f24d8689e2c77951981f8ea1f25089e0349a0bf8b35ee9b9277/gevent-24.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d850a453d66336272be4f1d3a8126777f3efdaea62d053b4829857f91e09755", size = 4913247 }, - { url = "https://files.pythonhosted.org/packages/db/63/6e40eaaa3c2abd1561faff11dc3e6781f8c25e975354b8835762834415af/gevent-24.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8e58ee3723f1fbe07d66892f1caa7481c306f653a6829b6fd16cb23d618a5915", size = 5049036 }, - { url = "https://files.pythonhosted.org/packages/94/89/158bc32cdc898dda0481040ac18650022e73133d93460c5af56ca622fe9a/gevent-24.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b52382124eca13135a3abe4f65c6bd428656975980a48e51b17aeab68bdb14db", size = 5107299 }, - { url = "https://files.pythonhosted.org/packages/64/91/1abe62ee350fdfac186d33f615d0d3a0b3b140e7ccf23c73547aa0deec44/gevent-24.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ca2266e08f43c0e22c028801dff7d92a0b102ef20e4caeb6a46abfb95f6a328", size = 6819625 }, - { url = "https://files.pythonhosted.org/packages/92/8b/0b2fe0d36b7c4d463e46cc68eaf6c14488bd7d86cc37e995c64a0ff7d02f/gevent-24.10.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d758f0d4dbf32502ec87bb9b536ca8055090a16f8305f0ada3ce6f34e70f2fd7", size = 5474079 }, - { url = "https://files.pythonhosted.org/packages/12/7b/9f5abbf0021a50321314f850697e0f46d2e5081168223af2d8544af9d19f/gevent-24.10.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0de6eb3d55c03138fda567d9bfed28487ce5d0928c5107549767a93efdf2be26", size = 6901323 }, - { url = "https://files.pythonhosted.org/packages/8a/63/607715c621ae78ed581b7ba36d076df63feeb352993d521327f865056771/gevent-24.10.3-cp311-cp311-win_amd64.whl", hash = "sha256:385710355eadecdb70428a5ae3e7e5a45dcf888baa1426884588be9d25ac4290", size = 1549468 }, - { url = "https://files.pythonhosted.org/packages/d9/e4/4edbe17001bb3e6fade4ad2d85ca8f9e4eabcbde4aa29aa6889281616e3e/gevent-24.10.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3ad8fb70aa0ebc935729c9699ac31b210a49b689a7b27b7ac9f91676475f3f53", size = 2970952 }, - { url = "https://files.pythonhosted.org/packages/3c/a6/ce0824fe9398ba6b00028a74840f12be1165d5feaacdc028ea953db3d6c3/gevent-24.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f18689f7a70d2ed0e75bad5036ec3c89690a493d4cfac8d7cdb258ac04b132bd", size = 5172230 }, - { url = "https://files.pythonhosted.org/packages/25/d4/9002cfb585bfa52c860ed4b1349d1a6400bdf2df9f1bd21df5ff33eea33c/gevent-24.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f4f171d4d2018170454d84c934842e1b5f6ce7468ba298f6e7f7cff15000a3", size = 5338394 }, - { url = "https://files.pythonhosted.org/packages/0c/98/222f1a14f22ad2d1cbcc37edb74095264c1f9c7ab49e6423693383462b8a/gevent-24.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7021e26d70189b33c27173d4173f27bf4685d6b6f1c0ea50e5335f8491cb110c", size = 5437989 }, - { url = "https://files.pythonhosted.org/packages/bf/e8/cbb46afea3c7ecdc7289e15cb4a6f89903f4f9754a27ca320d3e465abc78/gevent-24.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:34aea15f9c79f27a8faeaa361bc1e72c773a9b54a1996a2ec4eefc8bcd59a824", size = 6838539 }, - { url = "https://files.pythonhosted.org/packages/69/c3/e43e348f23da404a6d4368a14453ed097cdfca97d5212eaceb987d04a0e1/gevent-24.10.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:8af65a4d4feaec6042c666d22c322a310fba3b47e841ad52f724b9c3ce5da48e", size = 5513842 }, - { url = "https://files.pythonhosted.org/packages/c2/76/84b7c19c072a80900118717a85236859127d630cdf8b079fe42f19649f12/gevent-24.10.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:89c4115e3f5ada55f92b61701a46043fe42f702b5af863b029e4c1a76f6cc2d4", size = 6927374 }, - { url = "https://files.pythonhosted.org/packages/5e/69/0ab1b04c363547058fb5035275c144957b80b36cb6aee715fe6181b0cee9/gevent-24.10.3-cp312-cp312-win_amd64.whl", hash = "sha256:1ce6dab94c0b0d24425ba55712de2f8c9cb21267150ca63f5bb3a0e1f165da99", size = 1546701 }, - { url = "https://files.pythonhosted.org/packages/f7/2d/c783583d7999cd2f2e7aa2d6a1c333d663003ca61255a89ff6a891be95f4/gevent-24.10.3-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:f147e38423fbe96e8731f60a63475b3d2cab2f3d10578d8ee9d10c507c58a2ff", size = 2962857 }, - { url = "https://files.pythonhosted.org/packages/f3/77/d3ce96fd49406f61976e9a3b6c742b97bb274d3b30c68ff190c5b5f81afd/gevent-24.10.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18e6984ec96fc95fd67488555c38ece3015be1f38b1bcceb27b7d6c36b343008", size = 5141676 }, - { url = "https://files.pythonhosted.org/packages/49/f4/f99f893770c316b9d2f03bd684947126cbed0321b89fe5423838974c2025/gevent-24.10.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:051b22e2758accfddb0457728bfc9abf8c3f2ce6bca43f1ff6e07b5ed9e49bf4", size = 5310248 }, - { url = "https://files.pythonhosted.org/packages/e3/0c/67257ba906f76ed82e8f0bd8c00c2a0687b360a1050b70db7e58dff749ab/gevent-24.10.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eb5edb6433764119a664bbb148d2aea9990950aa89cc3498f475c2408d523ea3", size = 5407304 }, - { url = "https://files.pythonhosted.org/packages/35/6c/3a72da7c224b0111728130c0f1abc3ee07feff91b37e0ea83db98f4a3eaf/gevent-24.10.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce417bcaaab496bc9c77f75566531e9d93816262037b8b2dbb88b0fdcd66587c", size = 6818624 }, - { url = "https://files.pythonhosted.org/packages/a3/96/cc5f6ecba032a45fc312fe0db2908a893057fd81361eea93845d6c325556/gevent-24.10.3-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:1c3a828b033fb02b7c31da4d75014a1f82e6c072fc0523456569a57f8b025861", size = 5484356 }, - { url = "https://files.pythonhosted.org/packages/7c/97/e680b2b2f0c291ae4db9813ffbf02c22c2a0f14c8f1a613971385e29ef67/gevent-24.10.3-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:f2ae3efbbd120cdf4a68b7abc27a37e61e6f443c5a06ec2c6ad94c37cd8471ec", size = 6903191 }, - { url = "https://files.pythonhosted.org/packages/1b/1c/b4181957da062d1c060974ec6cb798cc24aeeb28e8cd2ece84eb4b4991f7/gevent-24.10.3-cp313-cp313-win_amd64.whl", hash = "sha256:9e1210334a9bc9f76c3d008e0785ca62214f8a54e1325f6c2ecab3b6a572a015", size = 1545117 }, - { url = "https://files.pythonhosted.org/packages/89/2b/bf4af9950b8f9abd5b4025858f6311930de550e3498bbfeb47c914701a1d/gevent-24.10.3-pp310-pypy310_pp73-macosx_11_0_universal2.whl", hash = "sha256:e534e6a968d74463b11de6c9c67f4b4bf61775fb00f2e6e0f7fcdd412ceade18", size = 1271541 }, + { url = "https://files.pythonhosted.org/packages/6b/6f/a2100e7883c7bdfc2b45cb60b310ca748762a21596258b9dd01c5c093dbc/gevent-24.10.3-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:d7a1ad0f2da582f5bd238bca067e1c6c482c30c15a6e4d14aaa3215cbb2232f3", size = 3014382, upload_time = "2024-10-18T15:37:34.041Z" }, + { url = "https://files.pythonhosted.org/packages/7a/b1/460e4884ed6185d9eb9c4c2e9639d2b254197e46513301c0f63dec22dc90/gevent-24.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4e526fdc279c655c1e809b0c34b45844182c2a6b219802da5e411bd2cf5a8ad", size = 4853460, upload_time = "2024-10-18T16:19:39.515Z" }, + { url = "https://files.pythonhosted.org/packages/ca/f6/7ded98760d381229183ecce8db2edcce96f13e23807d31a90c66dae85304/gevent-24.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57a5c4e0bdac482c5f02f240d0354e61362df73501ef6ebafce8ef635cad7527", size = 4977636, upload_time = "2024-10-18T16:18:45.464Z" }, + { url = "https://files.pythonhosted.org/packages/7d/21/7b928e6029eedb93ef94fc0aee701f497af2e601f0ec00aac0e72e3f450e/gevent-24.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d67daed8383326dc8b5e58d88e148d29b6b52274a489e383530b0969ae7b9cb9", size = 5058031, upload_time = "2024-10-18T16:23:10.719Z" }, + { url = "https://files.pythonhosted.org/packages/00/98/12c03fd004fbeeca01276ffc589f5a368fd741d02582ab7006d1bdef57e7/gevent-24.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e24ffea72e27987979c009536fd0868e52239b44afe6cf7135ce8aafd0f108e", size = 6683694, upload_time = "2024-10-18T15:59:35.475Z" }, + { url = "https://files.pythonhosted.org/packages/64/4c/ea14d971452d3da09e49267e052d8312f112c7835120aed78d22ef14efee/gevent-24.10.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c1d80090485da1ea3d99205fe97908b31188c1f4857f08b333ffaf2de2e89d18", size = 5286063, upload_time = "2024-10-18T16:38:24.113Z" }, + { url = "https://files.pythonhosted.org/packages/39/3f/397efff27e637d7306caa00d1560512c44028c25c70be1e72c46b79b1b66/gevent-24.10.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f0c129f81d60cda614acb4b0c5731997ca05b031fb406fcb58ad53a7ade53b13", size = 6817462, upload_time = "2024-10-18T16:02:48.427Z" }, + { url = "https://files.pythonhosted.org/packages/aa/5d/19939eaa7c5b7c0f37e0a0665a911ddfe1e35c25c512446fc356a065c16e/gevent-24.10.3-cp310-cp310-win_amd64.whl", hash = "sha256:26ca7a6b42d35129617025ac801135118333cad75856ffc3217b38e707383eba", size = 1566631, upload_time = "2024-10-18T16:08:38.489Z" }, + { url = "https://files.pythonhosted.org/packages/6e/01/1be5cf013826d8baae235976d6a94f3628014fd2db7c071aeec13f82b4d1/gevent-24.10.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:68c3a0d8402755eba7f69022e42e8021192a721ca8341908acc222ea597029b6", size = 2966909, upload_time = "2024-10-18T15:37:31.43Z" }, + { url = "https://files.pythonhosted.org/packages/fe/3e/7fa9ab023f24d8689e2c77951981f8ea1f25089e0349a0bf8b35ee9b9277/gevent-24.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d850a453d66336272be4f1d3a8126777f3efdaea62d053b4829857f91e09755", size = 4913247, upload_time = "2024-10-18T16:19:41.792Z" }, + { url = "https://files.pythonhosted.org/packages/db/63/6e40eaaa3c2abd1561faff11dc3e6781f8c25e975354b8835762834415af/gevent-24.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8e58ee3723f1fbe07d66892f1caa7481c306f653a6829b6fd16cb23d618a5915", size = 5049036, upload_time = "2024-10-18T16:18:47.419Z" }, + { url = "https://files.pythonhosted.org/packages/94/89/158bc32cdc898dda0481040ac18650022e73133d93460c5af56ca622fe9a/gevent-24.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b52382124eca13135a3abe4f65c6bd428656975980a48e51b17aeab68bdb14db", size = 5107299, upload_time = "2024-10-18T16:23:12.296Z" }, + { url = "https://files.pythonhosted.org/packages/64/91/1abe62ee350fdfac186d33f615d0d3a0b3b140e7ccf23c73547aa0deec44/gevent-24.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ca2266e08f43c0e22c028801dff7d92a0b102ef20e4caeb6a46abfb95f6a328", size = 6819625, upload_time = "2024-10-18T15:59:38.226Z" }, + { url = "https://files.pythonhosted.org/packages/92/8b/0b2fe0d36b7c4d463e46cc68eaf6c14488bd7d86cc37e995c64a0ff7d02f/gevent-24.10.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d758f0d4dbf32502ec87bb9b536ca8055090a16f8305f0ada3ce6f34e70f2fd7", size = 5474079, upload_time = "2024-10-18T16:38:26.866Z" }, + { url = "https://files.pythonhosted.org/packages/12/7b/9f5abbf0021a50321314f850697e0f46d2e5081168223af2d8544af9d19f/gevent-24.10.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0de6eb3d55c03138fda567d9bfed28487ce5d0928c5107549767a93efdf2be26", size = 6901323, upload_time = "2024-10-18T16:02:50.066Z" }, + { url = "https://files.pythonhosted.org/packages/8a/63/607715c621ae78ed581b7ba36d076df63feeb352993d521327f865056771/gevent-24.10.3-cp311-cp311-win_amd64.whl", hash = "sha256:385710355eadecdb70428a5ae3e7e5a45dcf888baa1426884588be9d25ac4290", size = 1549468, upload_time = "2024-10-18T16:01:30.331Z" }, + { url = "https://files.pythonhosted.org/packages/d9/e4/4edbe17001bb3e6fade4ad2d85ca8f9e4eabcbde4aa29aa6889281616e3e/gevent-24.10.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3ad8fb70aa0ebc935729c9699ac31b210a49b689a7b27b7ac9f91676475f3f53", size = 2970952, upload_time = "2024-10-18T15:37:31.389Z" }, + { url = "https://files.pythonhosted.org/packages/3c/a6/ce0824fe9398ba6b00028a74840f12be1165d5feaacdc028ea953db3d6c3/gevent-24.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f18689f7a70d2ed0e75bad5036ec3c89690a493d4cfac8d7cdb258ac04b132bd", size = 5172230, upload_time = "2024-10-18T16:19:43.661Z" }, + { url = "https://files.pythonhosted.org/packages/25/d4/9002cfb585bfa52c860ed4b1349d1a6400bdf2df9f1bd21df5ff33eea33c/gevent-24.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f4f171d4d2018170454d84c934842e1b5f6ce7468ba298f6e7f7cff15000a3", size = 5338394, upload_time = "2024-10-18T16:18:49.371Z" }, + { url = "https://files.pythonhosted.org/packages/0c/98/222f1a14f22ad2d1cbcc37edb74095264c1f9c7ab49e6423693383462b8a/gevent-24.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7021e26d70189b33c27173d4173f27bf4685d6b6f1c0ea50e5335f8491cb110c", size = 5437989, upload_time = "2024-10-18T16:23:13.851Z" }, + { url = "https://files.pythonhosted.org/packages/bf/e8/cbb46afea3c7ecdc7289e15cb4a6f89903f4f9754a27ca320d3e465abc78/gevent-24.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:34aea15f9c79f27a8faeaa361bc1e72c773a9b54a1996a2ec4eefc8bcd59a824", size = 6838539, upload_time = "2024-10-18T15:59:40.489Z" }, + { url = "https://files.pythonhosted.org/packages/69/c3/e43e348f23da404a6d4368a14453ed097cdfca97d5212eaceb987d04a0e1/gevent-24.10.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:8af65a4d4feaec6042c666d22c322a310fba3b47e841ad52f724b9c3ce5da48e", size = 5513842, upload_time = "2024-10-18T16:38:29.538Z" }, + { url = "https://files.pythonhosted.org/packages/c2/76/84b7c19c072a80900118717a85236859127d630cdf8b079fe42f19649f12/gevent-24.10.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:89c4115e3f5ada55f92b61701a46043fe42f702b5af863b029e4c1a76f6cc2d4", size = 6927374, upload_time = "2024-10-18T16:02:51.669Z" }, + { url = "https://files.pythonhosted.org/packages/5e/69/0ab1b04c363547058fb5035275c144957b80b36cb6aee715fe6181b0cee9/gevent-24.10.3-cp312-cp312-win_amd64.whl", hash = "sha256:1ce6dab94c0b0d24425ba55712de2f8c9cb21267150ca63f5bb3a0e1f165da99", size = 1546701, upload_time = "2024-10-18T15:54:53.562Z" }, + { url = "https://files.pythonhosted.org/packages/f7/2d/c783583d7999cd2f2e7aa2d6a1c333d663003ca61255a89ff6a891be95f4/gevent-24.10.3-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:f147e38423fbe96e8731f60a63475b3d2cab2f3d10578d8ee9d10c507c58a2ff", size = 2962857, upload_time = "2024-10-18T15:37:33.098Z" }, + { url = "https://files.pythonhosted.org/packages/f3/77/d3ce96fd49406f61976e9a3b6c742b97bb274d3b30c68ff190c5b5f81afd/gevent-24.10.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18e6984ec96fc95fd67488555c38ece3015be1f38b1bcceb27b7d6c36b343008", size = 5141676, upload_time = "2024-10-18T16:19:45.484Z" }, + { url = "https://files.pythonhosted.org/packages/49/f4/f99f893770c316b9d2f03bd684947126cbed0321b89fe5423838974c2025/gevent-24.10.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:051b22e2758accfddb0457728bfc9abf8c3f2ce6bca43f1ff6e07b5ed9e49bf4", size = 5310248, upload_time = "2024-10-18T16:18:51.175Z" }, + { url = "https://files.pythonhosted.org/packages/e3/0c/67257ba906f76ed82e8f0bd8c00c2a0687b360a1050b70db7e58dff749ab/gevent-24.10.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eb5edb6433764119a664bbb148d2aea9990950aa89cc3498f475c2408d523ea3", size = 5407304, upload_time = "2024-10-18T16:23:15.348Z" }, + { url = "https://files.pythonhosted.org/packages/35/6c/3a72da7c224b0111728130c0f1abc3ee07feff91b37e0ea83db98f4a3eaf/gevent-24.10.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce417bcaaab496bc9c77f75566531e9d93816262037b8b2dbb88b0fdcd66587c", size = 6818624, upload_time = "2024-10-18T15:59:42.068Z" }, + { url = "https://files.pythonhosted.org/packages/a3/96/cc5f6ecba032a45fc312fe0db2908a893057fd81361eea93845d6c325556/gevent-24.10.3-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:1c3a828b033fb02b7c31da4d75014a1f82e6c072fc0523456569a57f8b025861", size = 5484356, upload_time = "2024-10-18T16:38:31.709Z" }, + { url = "https://files.pythonhosted.org/packages/7c/97/e680b2b2f0c291ae4db9813ffbf02c22c2a0f14c8f1a613971385e29ef67/gevent-24.10.3-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:f2ae3efbbd120cdf4a68b7abc27a37e61e6f443c5a06ec2c6ad94c37cd8471ec", size = 6903191, upload_time = "2024-10-18T16:02:53.888Z" }, + { url = "https://files.pythonhosted.org/packages/1b/1c/b4181957da062d1c060974ec6cb798cc24aeeb28e8cd2ece84eb4b4991f7/gevent-24.10.3-cp313-cp313-win_amd64.whl", hash = "sha256:9e1210334a9bc9f76c3d008e0785ca62214f8a54e1325f6c2ecab3b6a572a015", size = 1545117, upload_time = "2024-10-18T15:45:47.375Z" }, + { url = "https://files.pythonhosted.org/packages/89/2b/bf4af9950b8f9abd5b4025858f6311930de550e3498bbfeb47c914701a1d/gevent-24.10.3-pp310-pypy310_pp73-macosx_11_0_universal2.whl", hash = "sha256:e534e6a968d74463b11de6c9c67f4b4bf61775fb00f2e6e0f7fcdd412ceade18", size = 1271541, upload_time = "2024-10-18T15:37:53.146Z" }, ] [[package]] @@ -690,103 +699,103 @@ dependencies = [ { name = "gevent" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8c/14/d4eddae757de44985718a9e38d9e6f2a923d764ed97d0f1cbc1a8aa2b0ef/geventhttpclient-2.3.1.tar.gz", hash = "sha256:b40ddac8517c456818942c7812f555f84702105c82783238c9fcb8dc12675185", size = 69345 } +sdist = { url = "https://files.pythonhosted.org/packages/8c/14/d4eddae757de44985718a9e38d9e6f2a923d764ed97d0f1cbc1a8aa2b0ef/geventhttpclient-2.3.1.tar.gz", hash = "sha256:b40ddac8517c456818942c7812f555f84702105c82783238c9fcb8dc12675185", size = 69345, upload_time = "2024-04-18T21:39:50.83Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a2/a5/5e49d6a581b3f1399425e22961c6e341e90c12fa2193ed0adee9afbd864c/geventhttpclient-2.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:da22ab7bf5af4ba3d07cffee6de448b42696e53e7ac1fe97ed289037733bf1c2", size = 71729 }, - { url = "https://files.pythonhosted.org/packages/eb/23/4ff584e5f344dae64b5bc588b65c4ea81083f9d662b9f64cf5f28e5ae9cc/geventhttpclient-2.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2399e3d4e2fae8bbd91756189da6e9d84adf8f3eaace5eef0667874a705a29f8", size = 52062 }, - { url = "https://files.pythonhosted.org/packages/bb/60/6bd8badb97b31a49f4c2b79466abce208a97dad95d447893c7546063fc8a/geventhttpclient-2.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d3e33e87d0d5b9f5782c4e6d3cb7e3592fea41af52713137d04776df7646d71b", size = 51645 }, - { url = "https://files.pythonhosted.org/packages/e1/62/47d431bf05f74aa683d63163a11432bda8f576c86dec8c3bc9d6a156ee03/geventhttpclient-2.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c071db313866c3d0510feb6c0f40ec086ccf7e4a845701b6316c82c06e8b9b29", size = 117838 }, - { url = "https://files.pythonhosted.org/packages/6c/8b/e7c9ae813bb41883a96ad9afcf86465219c3bb682daa8b09448481edef8a/geventhttpclient-2.3.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f36f0c6ef88a27e60af8369d9c2189fe372c6f2943182a7568e0f2ad33bb69f1", size = 123272 }, - { url = "https://files.pythonhosted.org/packages/4d/26/71e9b2526009faadda9f588dac04f8bf837a5b97628ab44145efc3fa796e/geventhttpclient-2.3.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c4624843c03a5337282a42247d987c2531193e57255ee307b36eeb4f243a0c21", size = 114319 }, - { url = "https://files.pythonhosted.org/packages/34/8c/1da2960293c42b7a6b01dbe3204b569e4cdb55b8289cb1c7154826500f19/geventhttpclient-2.3.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d614573621ba827c417786057e1e20e9f96c4f6b3878c55b1b7b54e1026693bc", size = 112705 }, - { url = "https://files.pythonhosted.org/packages/a7/a1/4d08ecf0f213fdc63f78a217f87c07c1cb9891e68cdf74c8cbca76298bdb/geventhttpclient-2.3.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5d51330a40ac9762879d0e296c279c1beae8cfa6484bb196ac829242c416b709", size = 121236 }, - { url = "https://files.pythonhosted.org/packages/4f/f7/42ece3e1f54602c518d74364a214da3b35b6be267b335564b7e9f0d37705/geventhttpclient-2.3.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bc9f2162d4e8cb86bb5322d99bfd552088a3eacd540a841298f06bb8bc1f1f03", size = 117859 }, - { url = "https://files.pythonhosted.org/packages/1f/8e/de026b3697bffe5fa1a4938a3882107e378eea826905acf8e46c69b71ffd/geventhttpclient-2.3.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:06e59d3397e63c65ecc7a7561a5289f0cf2e2c2252e29632741e792f57f5d124", size = 127268 }, - { url = "https://files.pythonhosted.org/packages/54/bf/1ee99a322467e6825a24612d306a46ca94b51088170d1b5de0df1c82ab2a/geventhttpclient-2.3.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4436eef515b3e0c1d4a453ae32e047290e780a623c1eddb11026ae9d5fb03d42", size = 116426 }, - { url = "https://files.pythonhosted.org/packages/72/54/10c8ec745b3dcbfd52af62977fec85829749c0325e1a5429d050a4b45e75/geventhttpclient-2.3.1-cp310-cp310-win32.whl", hash = "sha256:5d1cf7d8a4f8e15cc8fd7d88ac4cdb058d6274203a42587e594cc9f0850ac862", size = 47599 }, - { url = "https://files.pythonhosted.org/packages/da/0d/36a47cdeaa83c3b4efdbd18d77720fa27dc40600998f4dedd7c4a1259862/geventhttpclient-2.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:4deaebc121036f7ea95430c2d0f80ab085b15280e6ab677a6360b70e57020e7f", size = 48302 }, - { url = "https://files.pythonhosted.org/packages/56/ad/1fcbbea0465f04d4425960e3737d4d8ae6407043cfc88688fb17b9064160/geventhttpclient-2.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f0ae055b9ce1704f2ce72c0847df28f4e14dbb3eea79256cda6c909d82688ea3", size = 71733 }, - { url = "https://files.pythonhosted.org/packages/06/1a/10e547adb675beea407ff7117ecb4e5063534569ac14bb4360279d2888dd/geventhttpclient-2.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f087af2ac439495b5388841d6f3c4de8d2573ca9870593d78f7b554aa5cfa7f5", size = 52060 }, - { url = "https://files.pythonhosted.org/packages/e0/c0/9960ac6e8818a00702743cd2a9637d6f26909ac7ac59ca231f446e367b20/geventhttpclient-2.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:76c367d175810facfe56281e516c9a5a4a191eff76641faaa30aa33882ed4b2f", size = 51649 }, - { url = "https://files.pythonhosted.org/packages/58/3a/b032cd8f885dafdfa002a8a0e4e21b633713798ec08e19010b815fbfead6/geventhttpclient-2.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a58376d0d461fe0322ff2ad362553b437daee1eeb92b4c0e3b1ffef9e77defbe", size = 117987 }, - { url = "https://files.pythonhosted.org/packages/94/36/6493a5cbc20c269a51186946947f3ca2eae687e05831289891027bd038c3/geventhttpclient-2.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f440cc704f8a9869848a109b2c401805c17c070539b2014e7b884ecfc8591e33", size = 123356 }, - { url = "https://files.pythonhosted.org/packages/2f/07/b66d9a13b97a7e59d84b4faf704113aa963aaf3a0f71c9138c8740d57d5c/geventhttpclient-2.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f10c62994f9052f23948c19de930b2d1f063240462c8bd7077c2b3290e61f4fa", size = 114460 }, - { url = "https://files.pythonhosted.org/packages/4e/72/1467b9e1ef63aecfe3b42333fb7607f66129dffaeca231f97e4be6f71803/geventhttpclient-2.3.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:52c45d9f3dd9627844c12e9ca347258c7be585bed54046336220e25ea6eac155", size = 112808 }, - { url = "https://files.pythonhosted.org/packages/ce/ef/64894efd67cb3459074c734736ecacff398cd841a5538dc70e3e77d35500/geventhttpclient-2.3.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:77c1a2c6e3854bf87cd5588b95174640c8a881716bd07fa0d131d082270a6795", size = 122049 }, - { url = "https://files.pythonhosted.org/packages/c5/c8/1b13b4ea4bb88d7c2db56d070a52daf4757b3139afd83885e81455cb422f/geventhttpclient-2.3.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ce649d4e25c2d56023471df0bf1e8e2ab67dfe4ff12ce3e8fe7e6fae30cd672a", size = 118755 }, - { url = "https://files.pythonhosted.org/packages/d1/06/95ac63fa1ee118a4d5824aa0a6b0dc3a2934a2f4ce695bf6747e1744d813/geventhttpclient-2.3.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:265d9f31b4ac8f688eebef0bd4c814ffb37a16f769ad0c8c8b8c24a84db8eab5", size = 128053 }, - { url = "https://files.pythonhosted.org/packages/8a/27/3d6dbbd128e1b965bae198bffa4b5552cd635397e3d2bbcc7d9592890ca9/geventhttpclient-2.3.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2de436a9d61dae877e4e811fb3e2594e2a1df1b18f4280878f318aef48a562b9", size = 117316 }, - { url = "https://files.pythonhosted.org/packages/ed/9a/8b65daf417ff982fa1928ebc6ebdfb081750d426f877f0056288aaa689e8/geventhttpclient-2.3.1-cp311-cp311-win32.whl", hash = "sha256:83e22178b9480b0a95edf0053d4f30b717d0b696b3c262beabe6964d9c5224b1", size = 47598 }, - { url = "https://files.pythonhosted.org/packages/ab/83/ed0d14787861cf30beddd3aadc29ad07d75555de43c629ba514ddd2978d0/geventhttpclient-2.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:97b072a282233384c1302a7dee88ad8bfedc916f06b1bc1da54f84980f1406a9", size = 48301 }, - { url = "https://files.pythonhosted.org/packages/82/ee/bf3d26170a518d2b1254f44202f2fa4490496b476ee24046ff6c34e79c08/geventhttpclient-2.3.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:e1c90abcc2735cd8dd2d2572a13da32f6625392dc04862decb5c6476a3ddee22", size = 71742 }, - { url = "https://files.pythonhosted.org/packages/77/72/bd64b2a491094a3fbf7f3c314bb3c3918afb652783a8a9db07b86072da35/geventhttpclient-2.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5deb41c2f51247b4e568c14964f59d7b8e537eff51900564c88af3200004e678", size = 52070 }, - { url = "https://files.pythonhosted.org/packages/85/96/e25becfde16c5551ba04ed2beac1f018e2efc70275ec19ae3765ff634ff2/geventhttpclient-2.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c6f1a56a66a90c4beae2f009b5e9d42db9a58ced165aa35441ace04d69cb7b37", size = 51650 }, - { url = "https://files.pythonhosted.org/packages/5d/b8/fe6e938a369b3742103d04e5771e1ec7b18c047ac30b06a8e9704e2d34fc/geventhttpclient-2.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ee6e741849c29e3129b1ec3828ac3a5e5dcb043402f852ea92c52334fb8cabf", size = 118507 }, - { url = "https://files.pythonhosted.org/packages/68/0b/381d01de049b02dc70addbcc1c8e24d15500bff6a9e89103c4aa8eb352c3/geventhttpclient-2.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0d0972096a63b1ddaa73fa3dab2c7a136e3ab8bf7999a2f85a5dee851fa77cdd", size = 124061 }, - { url = "https://files.pythonhosted.org/packages/c6/e6/7c97b5bf41cc403b2936a0887a85550b3153aa4b60c0c5062c49cd6286f2/geventhttpclient-2.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00675ba682fb7d19d659c14686fa8a52a65e3f301b56c2a4ee6333b380dd9467", size = 115060 }, - { url = "https://files.pythonhosted.org/packages/45/1f/3e02464449c74a8146f27218471578c1dfabf18731cf047520b76e1b6331/geventhttpclient-2.3.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea77b67c186df90473416f4403839728f70ef6cf1689cec97b4f6bbde392a8a8", size = 113762 }, - { url = "https://files.pythonhosted.org/packages/4f/a4/08551776f7d6b219d6f73ca25be88806007b16af51a1dbfed7192528e1c3/geventhttpclient-2.3.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ddcc3f0fdffd9a3801e1005b73026202cffed8199863fdef9315bea9a860a032", size = 122018 }, - { url = "https://files.pythonhosted.org/packages/70/14/ba91417ac7cbce8d553f72c885a19c6b9d7f9dc7de81b7814551cf020a57/geventhttpclient-2.3.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:c9f1ef4ec048563cc621a47ff01a4f10048ff8b676d7a4d75e5433ed8e703e56", size = 118884 }, - { url = "https://files.pythonhosted.org/packages/7c/78/e1f2c30e11bda8347a74b3a7254f727ff53ea260244da77d76b96779a006/geventhttpclient-2.3.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:a364b30bec7a0a00dbe256e2b6807e4dc866bead7ac84aaa51ca5e2c3d15c258", size = 128224 }, - { url = "https://files.pythonhosted.org/packages/ac/2f/b7fd96e9cfa9d9719b0c9feb50b4cbb341d1940e34fd3305006efa8c3e33/geventhttpclient-2.3.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:25d255383d3d6a6fbd643bb51ae1a7e4f6f7b0dbd5f3225b537d0bd0432eaf39", size = 117758 }, - { url = "https://files.pythonhosted.org/packages/fb/e0/1384c9a76379ab257b75df92283797861dcae592dd98e471df254f87c635/geventhttpclient-2.3.1-cp312-cp312-win32.whl", hash = "sha256:ad0b507e354d2f398186dcb12fe526d0594e7c9387b514fb843f7a14fdf1729a", size = 47595 }, - { url = "https://files.pythonhosted.org/packages/54/e3/6b8dbb24e3941e20abbe7736e59290c5d4182057ea1d984d46c853208bcd/geventhttpclient-2.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:7924e0883bc2b177cfe27aa65af6bb9dd57f3e26905c7675a2d1f3ef69df7cca", size = 48271 }, - { url = "https://files.pythonhosted.org/packages/ee/9f/251b1b7e665523137a8711f0f0029196cf18b57741135f01aea80a56f16c/geventhttpclient-2.3.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c31431e38df45b3c79bf3c9427c796adb8263d622bc6fa25e2f6ba916c2aad93", size = 49827 }, - { url = "https://files.pythonhosted.org/packages/74/c7/ad4c23de669191e1c83cfa28c51d3b50fc246d72e1ee40d4d5b330532492/geventhttpclient-2.3.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:855ab1e145575769b180b57accb0573a77cd6a7392f40a6ef7bc9a4926ebd77b", size = 54017 }, - { url = "https://files.pythonhosted.org/packages/04/7b/59fc8c8fbd10596abfc46dc103654e3d9676de64229d8eee4b0a4ac2e890/geventhttpclient-2.3.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a374aad77c01539e786d0c7829bec2eba034ccd45733c1bf9811ad18d2a8ecd", size = 58359 }, - { url = "https://files.pythonhosted.org/packages/94/b7/743552b0ecda75458c83d55d62937e29c9ee9a42598f57d4025d5de70004/geventhttpclient-2.3.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66c1e97460608304f400485ac099736fff3566d3d8db2038533d466f8cf5de5a", size = 54262 }, - { url = "https://files.pythonhosted.org/packages/18/60/10f6215b6cc76b5845a7f4b9c3d1f47d7ecd84ce8769b1e27e0482d605d7/geventhttpclient-2.3.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:4f843f81ee44ba4c553a1b3f73115e0ad8f00044023c24db29f5b1df3da08465", size = 48343 }, + { url = "https://files.pythonhosted.org/packages/a2/a5/5e49d6a581b3f1399425e22961c6e341e90c12fa2193ed0adee9afbd864c/geventhttpclient-2.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:da22ab7bf5af4ba3d07cffee6de448b42696e53e7ac1fe97ed289037733bf1c2", size = 71729, upload_time = "2024-04-18T21:38:06.866Z" }, + { url = "https://files.pythonhosted.org/packages/eb/23/4ff584e5f344dae64b5bc588b65c4ea81083f9d662b9f64cf5f28e5ae9cc/geventhttpclient-2.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2399e3d4e2fae8bbd91756189da6e9d84adf8f3eaace5eef0667874a705a29f8", size = 52062, upload_time = "2024-04-18T21:38:08.433Z" }, + { url = "https://files.pythonhosted.org/packages/bb/60/6bd8badb97b31a49f4c2b79466abce208a97dad95d447893c7546063fc8a/geventhttpclient-2.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d3e33e87d0d5b9f5782c4e6d3cb7e3592fea41af52713137d04776df7646d71b", size = 51645, upload_time = "2024-04-18T21:38:10.139Z" }, + { url = "https://files.pythonhosted.org/packages/e1/62/47d431bf05f74aa683d63163a11432bda8f576c86dec8c3bc9d6a156ee03/geventhttpclient-2.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c071db313866c3d0510feb6c0f40ec086ccf7e4a845701b6316c82c06e8b9b29", size = 117838, upload_time = "2024-04-18T21:38:12.036Z" }, + { url = "https://files.pythonhosted.org/packages/6c/8b/e7c9ae813bb41883a96ad9afcf86465219c3bb682daa8b09448481edef8a/geventhttpclient-2.3.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f36f0c6ef88a27e60af8369d9c2189fe372c6f2943182a7568e0f2ad33bb69f1", size = 123272, upload_time = "2024-04-18T21:38:13.704Z" }, + { url = "https://files.pythonhosted.org/packages/4d/26/71e9b2526009faadda9f588dac04f8bf837a5b97628ab44145efc3fa796e/geventhttpclient-2.3.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c4624843c03a5337282a42247d987c2531193e57255ee307b36eeb4f243a0c21", size = 114319, upload_time = "2024-04-18T21:38:15.097Z" }, + { url = "https://files.pythonhosted.org/packages/34/8c/1da2960293c42b7a6b01dbe3204b569e4cdb55b8289cb1c7154826500f19/geventhttpclient-2.3.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d614573621ba827c417786057e1e20e9f96c4f6b3878c55b1b7b54e1026693bc", size = 112705, upload_time = "2024-04-18T21:38:17.005Z" }, + { url = "https://files.pythonhosted.org/packages/a7/a1/4d08ecf0f213fdc63f78a217f87c07c1cb9891e68cdf74c8cbca76298bdb/geventhttpclient-2.3.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5d51330a40ac9762879d0e296c279c1beae8cfa6484bb196ac829242c416b709", size = 121236, upload_time = "2024-04-18T21:38:18.831Z" }, + { url = "https://files.pythonhosted.org/packages/4f/f7/42ece3e1f54602c518d74364a214da3b35b6be267b335564b7e9f0d37705/geventhttpclient-2.3.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bc9f2162d4e8cb86bb5322d99bfd552088a3eacd540a841298f06bb8bc1f1f03", size = 117859, upload_time = "2024-04-18T21:38:20.917Z" }, + { url = "https://files.pythonhosted.org/packages/1f/8e/de026b3697bffe5fa1a4938a3882107e378eea826905acf8e46c69b71ffd/geventhttpclient-2.3.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:06e59d3397e63c65ecc7a7561a5289f0cf2e2c2252e29632741e792f57f5d124", size = 127268, upload_time = "2024-04-18T21:38:22.676Z" }, + { url = "https://files.pythonhosted.org/packages/54/bf/1ee99a322467e6825a24612d306a46ca94b51088170d1b5de0df1c82ab2a/geventhttpclient-2.3.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4436eef515b3e0c1d4a453ae32e047290e780a623c1eddb11026ae9d5fb03d42", size = 116426, upload_time = "2024-04-18T21:38:24.228Z" }, + { url = "https://files.pythonhosted.org/packages/72/54/10c8ec745b3dcbfd52af62977fec85829749c0325e1a5429d050a4b45e75/geventhttpclient-2.3.1-cp310-cp310-win32.whl", hash = "sha256:5d1cf7d8a4f8e15cc8fd7d88ac4cdb058d6274203a42587e594cc9f0850ac862", size = 47599, upload_time = "2024-04-18T21:38:26.385Z" }, + { url = "https://files.pythonhosted.org/packages/da/0d/36a47cdeaa83c3b4efdbd18d77720fa27dc40600998f4dedd7c4a1259862/geventhttpclient-2.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:4deaebc121036f7ea95430c2d0f80ab085b15280e6ab677a6360b70e57020e7f", size = 48302, upload_time = "2024-04-18T21:38:28.297Z" }, + { url = "https://files.pythonhosted.org/packages/56/ad/1fcbbea0465f04d4425960e3737d4d8ae6407043cfc88688fb17b9064160/geventhttpclient-2.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f0ae055b9ce1704f2ce72c0847df28f4e14dbb3eea79256cda6c909d82688ea3", size = 71733, upload_time = "2024-04-18T21:38:30.357Z" }, + { url = "https://files.pythonhosted.org/packages/06/1a/10e547adb675beea407ff7117ecb4e5063534569ac14bb4360279d2888dd/geventhttpclient-2.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f087af2ac439495b5388841d6f3c4de8d2573ca9870593d78f7b554aa5cfa7f5", size = 52060, upload_time = "2024-04-18T21:38:32.561Z" }, + { url = "https://files.pythonhosted.org/packages/e0/c0/9960ac6e8818a00702743cd2a9637d6f26909ac7ac59ca231f446e367b20/geventhttpclient-2.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:76c367d175810facfe56281e516c9a5a4a191eff76641faaa30aa33882ed4b2f", size = 51649, upload_time = "2024-04-18T21:38:34.265Z" }, + { url = "https://files.pythonhosted.org/packages/58/3a/b032cd8f885dafdfa002a8a0e4e21b633713798ec08e19010b815fbfead6/geventhttpclient-2.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a58376d0d461fe0322ff2ad362553b437daee1eeb92b4c0e3b1ffef9e77defbe", size = 117987, upload_time = "2024-04-18T21:38:37.661Z" }, + { url = "https://files.pythonhosted.org/packages/94/36/6493a5cbc20c269a51186946947f3ca2eae687e05831289891027bd038c3/geventhttpclient-2.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f440cc704f8a9869848a109b2c401805c17c070539b2014e7b884ecfc8591e33", size = 123356, upload_time = "2024-04-18T21:38:39.705Z" }, + { url = "https://files.pythonhosted.org/packages/2f/07/b66d9a13b97a7e59d84b4faf704113aa963aaf3a0f71c9138c8740d57d5c/geventhttpclient-2.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f10c62994f9052f23948c19de930b2d1f063240462c8bd7077c2b3290e61f4fa", size = 114460, upload_time = "2024-04-18T21:38:40.947Z" }, + { url = "https://files.pythonhosted.org/packages/4e/72/1467b9e1ef63aecfe3b42333fb7607f66129dffaeca231f97e4be6f71803/geventhttpclient-2.3.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:52c45d9f3dd9627844c12e9ca347258c7be585bed54046336220e25ea6eac155", size = 112808, upload_time = "2024-04-18T21:38:42.684Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ef/64894efd67cb3459074c734736ecacff398cd841a5538dc70e3e77d35500/geventhttpclient-2.3.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:77c1a2c6e3854bf87cd5588b95174640c8a881716bd07fa0d131d082270a6795", size = 122049, upload_time = "2024-04-18T21:38:44.184Z" }, + { url = "https://files.pythonhosted.org/packages/c5/c8/1b13b4ea4bb88d7c2db56d070a52daf4757b3139afd83885e81455cb422f/geventhttpclient-2.3.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ce649d4e25c2d56023471df0bf1e8e2ab67dfe4ff12ce3e8fe7e6fae30cd672a", size = 118755, upload_time = "2024-04-18T21:38:45.654Z" }, + { url = "https://files.pythonhosted.org/packages/d1/06/95ac63fa1ee118a4d5824aa0a6b0dc3a2934a2f4ce695bf6747e1744d813/geventhttpclient-2.3.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:265d9f31b4ac8f688eebef0bd4c814ffb37a16f769ad0c8c8b8c24a84db8eab5", size = 128053, upload_time = "2024-04-18T21:38:47.247Z" }, + { url = "https://files.pythonhosted.org/packages/8a/27/3d6dbbd128e1b965bae198bffa4b5552cd635397e3d2bbcc7d9592890ca9/geventhttpclient-2.3.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2de436a9d61dae877e4e811fb3e2594e2a1df1b18f4280878f318aef48a562b9", size = 117316, upload_time = "2024-04-18T21:38:49.086Z" }, + { url = "https://files.pythonhosted.org/packages/ed/9a/8b65daf417ff982fa1928ebc6ebdfb081750d426f877f0056288aaa689e8/geventhttpclient-2.3.1-cp311-cp311-win32.whl", hash = "sha256:83e22178b9480b0a95edf0053d4f30b717d0b696b3c262beabe6964d9c5224b1", size = 47598, upload_time = "2024-04-18T21:38:50.919Z" }, + { url = "https://files.pythonhosted.org/packages/ab/83/ed0d14787861cf30beddd3aadc29ad07d75555de43c629ba514ddd2978d0/geventhttpclient-2.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:97b072a282233384c1302a7dee88ad8bfedc916f06b1bc1da54f84980f1406a9", size = 48301, upload_time = "2024-04-18T21:38:52.14Z" }, + { url = "https://files.pythonhosted.org/packages/82/ee/bf3d26170a518d2b1254f44202f2fa4490496b476ee24046ff6c34e79c08/geventhttpclient-2.3.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:e1c90abcc2735cd8dd2d2572a13da32f6625392dc04862decb5c6476a3ddee22", size = 71742, upload_time = "2024-04-18T21:38:54.167Z" }, + { url = "https://files.pythonhosted.org/packages/77/72/bd64b2a491094a3fbf7f3c314bb3c3918afb652783a8a9db07b86072da35/geventhttpclient-2.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5deb41c2f51247b4e568c14964f59d7b8e537eff51900564c88af3200004e678", size = 52070, upload_time = "2024-04-18T21:38:55.484Z" }, + { url = "https://files.pythonhosted.org/packages/85/96/e25becfde16c5551ba04ed2beac1f018e2efc70275ec19ae3765ff634ff2/geventhttpclient-2.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c6f1a56a66a90c4beae2f009b5e9d42db9a58ced165aa35441ace04d69cb7b37", size = 51650, upload_time = "2024-04-18T21:38:57.022Z" }, + { url = "https://files.pythonhosted.org/packages/5d/b8/fe6e938a369b3742103d04e5771e1ec7b18c047ac30b06a8e9704e2d34fc/geventhttpclient-2.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ee6e741849c29e3129b1ec3828ac3a5e5dcb043402f852ea92c52334fb8cabf", size = 118507, upload_time = "2024-04-18T21:38:58.936Z" }, + { url = "https://files.pythonhosted.org/packages/68/0b/381d01de049b02dc70addbcc1c8e24d15500bff6a9e89103c4aa8eb352c3/geventhttpclient-2.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0d0972096a63b1ddaa73fa3dab2c7a136e3ab8bf7999a2f85a5dee851fa77cdd", size = 124061, upload_time = "2024-04-18T21:39:00.473Z" }, + { url = "https://files.pythonhosted.org/packages/c6/e6/7c97b5bf41cc403b2936a0887a85550b3153aa4b60c0c5062c49cd6286f2/geventhttpclient-2.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00675ba682fb7d19d659c14686fa8a52a65e3f301b56c2a4ee6333b380dd9467", size = 115060, upload_time = "2024-04-18T21:39:02.323Z" }, + { url = "https://files.pythonhosted.org/packages/45/1f/3e02464449c74a8146f27218471578c1dfabf18731cf047520b76e1b6331/geventhttpclient-2.3.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea77b67c186df90473416f4403839728f70ef6cf1689cec97b4f6bbde392a8a8", size = 113762, upload_time = "2024-04-18T21:39:03.769Z" }, + { url = "https://files.pythonhosted.org/packages/4f/a4/08551776f7d6b219d6f73ca25be88806007b16af51a1dbfed7192528e1c3/geventhttpclient-2.3.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ddcc3f0fdffd9a3801e1005b73026202cffed8199863fdef9315bea9a860a032", size = 122018, upload_time = "2024-04-18T21:39:05.781Z" }, + { url = "https://files.pythonhosted.org/packages/70/14/ba91417ac7cbce8d553f72c885a19c6b9d7f9dc7de81b7814551cf020a57/geventhttpclient-2.3.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:c9f1ef4ec048563cc621a47ff01a4f10048ff8b676d7a4d75e5433ed8e703e56", size = 118884, upload_time = "2024-04-18T21:39:08.001Z" }, + { url = "https://files.pythonhosted.org/packages/7c/78/e1f2c30e11bda8347a74b3a7254f727ff53ea260244da77d76b96779a006/geventhttpclient-2.3.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:a364b30bec7a0a00dbe256e2b6807e4dc866bead7ac84aaa51ca5e2c3d15c258", size = 128224, upload_time = "2024-04-18T21:39:09.31Z" }, + { url = "https://files.pythonhosted.org/packages/ac/2f/b7fd96e9cfa9d9719b0c9feb50b4cbb341d1940e34fd3305006efa8c3e33/geventhttpclient-2.3.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:25d255383d3d6a6fbd643bb51ae1a7e4f6f7b0dbd5f3225b537d0bd0432eaf39", size = 117758, upload_time = "2024-04-18T21:39:11.287Z" }, + { url = "https://files.pythonhosted.org/packages/fb/e0/1384c9a76379ab257b75df92283797861dcae592dd98e471df254f87c635/geventhttpclient-2.3.1-cp312-cp312-win32.whl", hash = "sha256:ad0b507e354d2f398186dcb12fe526d0594e7c9387b514fb843f7a14fdf1729a", size = 47595, upload_time = "2024-04-18T21:39:12.535Z" }, + { url = "https://files.pythonhosted.org/packages/54/e3/6b8dbb24e3941e20abbe7736e59290c5d4182057ea1d984d46c853208bcd/geventhttpclient-2.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:7924e0883bc2b177cfe27aa65af6bb9dd57f3e26905c7675a2d1f3ef69df7cca", size = 48271, upload_time = "2024-04-18T21:39:14.479Z" }, + { url = "https://files.pythonhosted.org/packages/ee/9f/251b1b7e665523137a8711f0f0029196cf18b57741135f01aea80a56f16c/geventhttpclient-2.3.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c31431e38df45b3c79bf3c9427c796adb8263d622bc6fa25e2f6ba916c2aad93", size = 49827, upload_time = "2024-04-18T21:39:36.14Z" }, + { url = "https://files.pythonhosted.org/packages/74/c7/ad4c23de669191e1c83cfa28c51d3b50fc246d72e1ee40d4d5b330532492/geventhttpclient-2.3.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:855ab1e145575769b180b57accb0573a77cd6a7392f40a6ef7bc9a4926ebd77b", size = 54017, upload_time = "2024-04-18T21:39:37.577Z" }, + { url = "https://files.pythonhosted.org/packages/04/7b/59fc8c8fbd10596abfc46dc103654e3d9676de64229d8eee4b0a4ac2e890/geventhttpclient-2.3.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a374aad77c01539e786d0c7829bec2eba034ccd45733c1bf9811ad18d2a8ecd", size = 58359, upload_time = "2024-04-18T21:39:39.437Z" }, + { url = "https://files.pythonhosted.org/packages/94/b7/743552b0ecda75458c83d55d62937e29c9ee9a42598f57d4025d5de70004/geventhttpclient-2.3.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66c1e97460608304f400485ac099736fff3566d3d8db2038533d466f8cf5de5a", size = 54262, upload_time = "2024-04-18T21:39:40.866Z" }, + { url = "https://files.pythonhosted.org/packages/18/60/10f6215b6cc76b5845a7f4b9c3d1f47d7ecd84ce8769b1e27e0482d605d7/geventhttpclient-2.3.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:4f843f81ee44ba4c553a1b3f73115e0ad8f00044023c24db29f5b1df3da08465", size = 48343, upload_time = "2024-04-18T21:39:42.173Z" }, ] [[package]] name = "greenlet" version = "3.1.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2f/ff/df5fede753cc10f6a5be0931204ea30c35fa2f2ea7a35b25bdaf4fe40e46/greenlet-3.1.1.tar.gz", hash = "sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467", size = 186022 } +sdist = { url = "https://files.pythonhosted.org/packages/2f/ff/df5fede753cc10f6a5be0931204ea30c35fa2f2ea7a35b25bdaf4fe40e46/greenlet-3.1.1.tar.gz", hash = "sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467", size = 186022, upload_time = "2024-09-20T18:21:04.506Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/25/90/5234a78dc0ef6496a6eb97b67a42a8e96742a56f7dc808cb954a85390448/greenlet-3.1.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:0bbae94a29c9e5c7e4a2b7f0aae5c17e8e90acbfd3bf6270eeba60c39fce3563", size = 271235 }, - { url = "https://files.pythonhosted.org/packages/7c/16/cd631fa0ab7d06ef06387135b7549fdcc77d8d859ed770a0d28e47b20972/greenlet-3.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fde093fb93f35ca72a556cf72c92ea3ebfda3d79fc35bb19fbe685853869a83", size = 637168 }, - { url = "https://files.pythonhosted.org/packages/2f/b1/aed39043a6fec33c284a2c9abd63ce191f4f1a07319340ffc04d2ed3256f/greenlet-3.1.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:36b89d13c49216cadb828db8dfa6ce86bbbc476a82d3a6c397f0efae0525bdd0", size = 648826 }, - { url = "https://files.pythonhosted.org/packages/76/25/40e0112f7f3ebe54e8e8ed91b2b9f970805143efef16d043dfc15e70f44b/greenlet-3.1.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94b6150a85e1b33b40b1464a3f9988dcc5251d6ed06842abff82e42632fac120", size = 644443 }, - { url = "https://files.pythonhosted.org/packages/fb/2f/3850b867a9af519794784a7eeed1dd5bc68ffbcc5b28cef703711025fd0a/greenlet-3.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93147c513fac16385d1036b7e5b102c7fbbdb163d556b791f0f11eada7ba65dc", size = 643295 }, - { url = "https://files.pythonhosted.org/packages/cf/69/79e4d63b9387b48939096e25115b8af7cd8a90397a304f92436bcb21f5b2/greenlet-3.1.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:da7a9bff22ce038e19bf62c4dd1ec8391062878710ded0a845bcf47cc0200617", size = 599544 }, - { url = "https://files.pythonhosted.org/packages/46/1d/44dbcb0e6c323bd6f71b8c2f4233766a5faf4b8948873225d34a0b7efa71/greenlet-3.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b2795058c23988728eec1f36a4e5e4ebad22f8320c85f3587b539b9ac84128d7", size = 1125456 }, - { url = "https://files.pythonhosted.org/packages/e0/1d/a305dce121838d0278cee39d5bb268c657f10a5363ae4b726848f833f1bb/greenlet-3.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ed10eac5830befbdd0c32f83e8aa6288361597550ba669b04c48f0f9a2c843c6", size = 1149111 }, - { url = "https://files.pythonhosted.org/packages/96/28/d62835fb33fb5652f2e98d34c44ad1a0feacc8b1d3f1aecab035f51f267d/greenlet-3.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:77c386de38a60d1dfb8e55b8c1101d68c79dfdd25c7095d51fec2dd800892b80", size = 298392 }, - { url = "https://files.pythonhosted.org/packages/28/62/1c2665558618553c42922ed47a4e6d6527e2fa3516a8256c2f431c5d0441/greenlet-3.1.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:e4d333e558953648ca09d64f13e6d8f0523fa705f51cae3f03b5983489958c70", size = 272479 }, - { url = "https://files.pythonhosted.org/packages/76/9d/421e2d5f07285b6e4e3a676b016ca781f63cfe4a0cd8eaecf3fd6f7a71ae/greenlet-3.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09fc016b73c94e98e29af67ab7b9a879c307c6731a2c9da0db5a7d9b7edd1159", size = 640404 }, - { url = "https://files.pythonhosted.org/packages/e5/de/6e05f5c59262a584e502dd3d261bbdd2c97ab5416cc9c0b91ea38932a901/greenlet-3.1.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d5e975ca70269d66d17dd995dafc06f1b06e8cb1ec1e9ed54c1d1e4a7c4cf26e", size = 652813 }, - { url = "https://files.pythonhosted.org/packages/49/93/d5f93c84241acdea15a8fd329362c2c71c79e1a507c3f142a5d67ea435ae/greenlet-3.1.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b2813dc3de8c1ee3f924e4d4227999285fd335d1bcc0d2be6dc3f1f6a318ec1", size = 648517 }, - { url = "https://files.pythonhosted.org/packages/15/85/72f77fc02d00470c86a5c982b8daafdf65d38aefbbe441cebff3bf7037fc/greenlet-3.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e347b3bfcf985a05e8c0b7d462ba6f15b1ee1c909e2dcad795e49e91b152c383", size = 647831 }, - { url = "https://files.pythonhosted.org/packages/f7/4b/1c9695aa24f808e156c8f4813f685d975ca73c000c2a5056c514c64980f6/greenlet-3.1.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e8f8c9cb53cdac7ba9793c276acd90168f416b9ce36799b9b885790f8ad6c0a", size = 602413 }, - { url = "https://files.pythonhosted.org/packages/76/70/ad6e5b31ef330f03b12559d19fda2606a522d3849cde46b24f223d6d1619/greenlet-3.1.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:62ee94988d6b4722ce0028644418d93a52429e977d742ca2ccbe1c4f4a792511", size = 1129619 }, - { url = "https://files.pythonhosted.org/packages/f4/fb/201e1b932e584066e0f0658b538e73c459b34d44b4bd4034f682423bc801/greenlet-3.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1776fd7f989fc6b8d8c8cb8da1f6b82c5814957264d1f6cf818d475ec2bf6395", size = 1155198 }, - { url = "https://files.pythonhosted.org/packages/12/da/b9ed5e310bb8b89661b80cbcd4db5a067903bbcd7fc854923f5ebb4144f0/greenlet-3.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:48ca08c771c268a768087b408658e216133aecd835c0ded47ce955381105ba39", size = 298930 }, - { url = "https://files.pythonhosted.org/packages/7d/ec/bad1ac26764d26aa1353216fcbfa4670050f66d445448aafa227f8b16e80/greenlet-3.1.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:4afe7ea89de619adc868e087b4d2359282058479d7cfb94970adf4b55284574d", size = 274260 }, - { url = "https://files.pythonhosted.org/packages/66/d4/c8c04958870f482459ab5956c2942c4ec35cac7fe245527f1039837c17a9/greenlet-3.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f406b22b7c9a9b4f8aa9d2ab13d6ae0ac3e85c9a809bd590ad53fed2bf70dc79", size = 649064 }, - { url = "https://files.pythonhosted.org/packages/51/41/467b12a8c7c1303d20abcca145db2be4e6cd50a951fa30af48b6ec607581/greenlet-3.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c3a701fe5a9695b238503ce5bbe8218e03c3bcccf7e204e455e7462d770268aa", size = 663420 }, - { url = "https://files.pythonhosted.org/packages/27/8f/2a93cd9b1e7107d5c7b3b7816eeadcac2ebcaf6d6513df9abaf0334777f6/greenlet-3.1.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2846930c65b47d70b9d178e89c7e1a69c95c1f68ea5aa0a58646b7a96df12441", size = 658035 }, - { url = "https://files.pythonhosted.org/packages/57/5c/7c6f50cb12be092e1dccb2599be5a942c3416dbcfb76efcf54b3f8be4d8d/greenlet-3.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99cfaa2110534e2cf3ba31a7abcac9d328d1d9f1b95beede58294a60348fba36", size = 660105 }, - { url = "https://files.pythonhosted.org/packages/f1/66/033e58a50fd9ec9df00a8671c74f1f3a320564c6415a4ed82a1c651654ba/greenlet-3.1.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1443279c19fca463fc33e65ef2a935a5b09bb90f978beab37729e1c3c6c25fe9", size = 613077 }, - { url = "https://files.pythonhosted.org/packages/19/c5/36384a06f748044d06bdd8776e231fadf92fc896bd12cb1c9f5a1bda9578/greenlet-3.1.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b7cede291382a78f7bb5f04a529cb18e068dd29e0fb27376074b6d0317bf4dd0", size = 1135975 }, - { url = "https://files.pythonhosted.org/packages/38/f9/c0a0eb61bdf808d23266ecf1d63309f0e1471f284300ce6dac0ae1231881/greenlet-3.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:23f20bb60ae298d7d8656c6ec6db134bca379ecefadb0b19ce6f19d1f232a942", size = 1163955 }, - { url = "https://files.pythonhosted.org/packages/43/21/a5d9df1d21514883333fc86584c07c2b49ba7c602e670b174bd73cfc9c7f/greenlet-3.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:7124e16b4c55d417577c2077be379514321916d5790fa287c9ed6f23bd2ffd01", size = 299655 }, - { url = "https://files.pythonhosted.org/packages/f3/57/0db4940cd7bb461365ca8d6fd53e68254c9dbbcc2b452e69d0d41f10a85e/greenlet-3.1.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:05175c27cb459dcfc05d026c4232f9de8913ed006d42713cb8a5137bd49375f1", size = 272990 }, - { url = "https://files.pythonhosted.org/packages/1c/ec/423d113c9f74e5e402e175b157203e9102feeb7088cee844d735b28ef963/greenlet-3.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:935e943ec47c4afab8965954bf49bfa639c05d4ccf9ef6e924188f762145c0ff", size = 649175 }, - { url = "https://files.pythonhosted.org/packages/a9/46/ddbd2db9ff209186b7b7c621d1432e2f21714adc988703dbdd0e65155c77/greenlet-3.1.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:667a9706c970cb552ede35aee17339a18e8f2a87a51fba2ed39ceeeb1004798a", size = 663425 }, - { url = "https://files.pythonhosted.org/packages/bc/f9/9c82d6b2b04aa37e38e74f0c429aece5eeb02bab6e3b98e7db89b23d94c6/greenlet-3.1.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b8a678974d1f3aa55f6cc34dc480169d58f2e6d8958895d68845fa4ab566509e", size = 657736 }, - { url = "https://files.pythonhosted.org/packages/d9/42/b87bc2a81e3a62c3de2b0d550bf91a86939442b7ff85abb94eec3fc0e6aa/greenlet-3.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efc0f674aa41b92da8c49e0346318c6075d734994c3c4e4430b1c3f853e498e4", size = 660347 }, - { url = "https://files.pythonhosted.org/packages/37/fa/71599c3fd06336cdc3eac52e6871cfebab4d9d70674a9a9e7a482c318e99/greenlet-3.1.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0153404a4bb921f0ff1abeb5ce8a5131da56b953eda6e14b88dc6bbc04d2049e", size = 615583 }, - { url = "https://files.pythonhosted.org/packages/4e/96/e9ef85de031703ee7a4483489b40cf307f93c1824a02e903106f2ea315fe/greenlet-3.1.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:275f72decf9932639c1c6dd1013a1bc266438eb32710016a1c742df5da6e60a1", size = 1133039 }, - { url = "https://files.pythonhosted.org/packages/87/76/b2b6362accd69f2d1889db61a18c94bc743e961e3cab344c2effaa4b4a25/greenlet-3.1.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c4aab7f6381f38a4b42f269057aee279ab0fc7bf2e929e3d4abfae97b682a12c", size = 1160716 }, - { url = "https://files.pythonhosted.org/packages/1f/1b/54336d876186920e185066d8c3024ad55f21d7cc3683c856127ddb7b13ce/greenlet-3.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:b42703b1cf69f2aa1df7d1030b9d77d3e584a70755674d60e710f0af570f3761", size = 299490 }, - { url = "https://files.pythonhosted.org/packages/5f/17/bea55bf36990e1638a2af5ba10c1640273ef20f627962cf97107f1e5d637/greenlet-3.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1695e76146579f8c06c1509c7ce4dfe0706f49c6831a817ac04eebb2fd02011", size = 643731 }, - { url = "https://files.pythonhosted.org/packages/78/d2/aa3d2157f9ab742a08e0fd8f77d4699f37c22adfbfeb0c610a186b5f75e0/greenlet-3.1.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7876452af029456b3f3549b696bb36a06db7c90747740c5302f74a9e9fa14b13", size = 649304 }, - { url = "https://files.pythonhosted.org/packages/f1/8e/d0aeffe69e53ccff5a28fa86f07ad1d2d2d6537a9506229431a2a02e2f15/greenlet-3.1.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ead44c85f8ab905852d3de8d86f6f8baf77109f9da589cb4fa142bd3b57b475", size = 646537 }, - { url = "https://files.pythonhosted.org/packages/05/79/e15408220bbb989469c8871062c97c6c9136770657ba779711b90870d867/greenlet-3.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8320f64b777d00dd7ccdade271eaf0cad6636343293a25074cc5566160e4de7b", size = 642506 }, - { url = "https://files.pythonhosted.org/packages/18/87/470e01a940307796f1d25f8167b551a968540fbe0551c0ebb853cb527dd6/greenlet-3.1.1-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6510bf84a6b643dabba74d3049ead221257603a253d0a9873f55f6a59a65f822", size = 602753 }, - { url = "https://files.pythonhosted.org/packages/e2/72/576815ba674eddc3c25028238f74d7b8068902b3968cbe456771b166455e/greenlet-3.1.1-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:04b013dc07c96f83134b1e99888e7a79979f1a247e2a9f59697fa14b5862ed01", size = 1122731 }, - { url = "https://files.pythonhosted.org/packages/ac/38/08cc303ddddc4b3d7c628c3039a61a3aae36c241ed01393d00c2fd663473/greenlet-3.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:411f015496fec93c1c8cd4e5238da364e1da7a124bcb293f085bf2860c32c6f6", size = 1142112 }, + { url = "https://files.pythonhosted.org/packages/25/90/5234a78dc0ef6496a6eb97b67a42a8e96742a56f7dc808cb954a85390448/greenlet-3.1.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:0bbae94a29c9e5c7e4a2b7f0aae5c17e8e90acbfd3bf6270eeba60c39fce3563", size = 271235, upload_time = "2024-09-20T17:07:18.761Z" }, + { url = "https://files.pythonhosted.org/packages/7c/16/cd631fa0ab7d06ef06387135b7549fdcc77d8d859ed770a0d28e47b20972/greenlet-3.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fde093fb93f35ca72a556cf72c92ea3ebfda3d79fc35bb19fbe685853869a83", size = 637168, upload_time = "2024-09-20T17:36:43.774Z" }, + { url = "https://files.pythonhosted.org/packages/2f/b1/aed39043a6fec33c284a2c9abd63ce191f4f1a07319340ffc04d2ed3256f/greenlet-3.1.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:36b89d13c49216cadb828db8dfa6ce86bbbc476a82d3a6c397f0efae0525bdd0", size = 648826, upload_time = "2024-09-20T17:39:16.921Z" }, + { url = "https://files.pythonhosted.org/packages/76/25/40e0112f7f3ebe54e8e8ed91b2b9f970805143efef16d043dfc15e70f44b/greenlet-3.1.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94b6150a85e1b33b40b1464a3f9988dcc5251d6ed06842abff82e42632fac120", size = 644443, upload_time = "2024-09-20T17:44:21.896Z" }, + { url = "https://files.pythonhosted.org/packages/fb/2f/3850b867a9af519794784a7eeed1dd5bc68ffbcc5b28cef703711025fd0a/greenlet-3.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93147c513fac16385d1036b7e5b102c7fbbdb163d556b791f0f11eada7ba65dc", size = 643295, upload_time = "2024-09-20T17:08:37.951Z" }, + { url = "https://files.pythonhosted.org/packages/cf/69/79e4d63b9387b48939096e25115b8af7cd8a90397a304f92436bcb21f5b2/greenlet-3.1.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:da7a9bff22ce038e19bf62c4dd1ec8391062878710ded0a845bcf47cc0200617", size = 599544, upload_time = "2024-09-20T17:08:27.894Z" }, + { url = "https://files.pythonhosted.org/packages/46/1d/44dbcb0e6c323bd6f71b8c2f4233766a5faf4b8948873225d34a0b7efa71/greenlet-3.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b2795058c23988728eec1f36a4e5e4ebad22f8320c85f3587b539b9ac84128d7", size = 1125456, upload_time = "2024-09-20T17:44:11.755Z" }, + { url = "https://files.pythonhosted.org/packages/e0/1d/a305dce121838d0278cee39d5bb268c657f10a5363ae4b726848f833f1bb/greenlet-3.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ed10eac5830befbdd0c32f83e8aa6288361597550ba669b04c48f0f9a2c843c6", size = 1149111, upload_time = "2024-09-20T17:09:22.104Z" }, + { url = "https://files.pythonhosted.org/packages/96/28/d62835fb33fb5652f2e98d34c44ad1a0feacc8b1d3f1aecab035f51f267d/greenlet-3.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:77c386de38a60d1dfb8e55b8c1101d68c79dfdd25c7095d51fec2dd800892b80", size = 298392, upload_time = "2024-09-20T17:28:51.988Z" }, + { url = "https://files.pythonhosted.org/packages/28/62/1c2665558618553c42922ed47a4e6d6527e2fa3516a8256c2f431c5d0441/greenlet-3.1.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:e4d333e558953648ca09d64f13e6d8f0523fa705f51cae3f03b5983489958c70", size = 272479, upload_time = "2024-09-20T17:07:22.332Z" }, + { url = "https://files.pythonhosted.org/packages/76/9d/421e2d5f07285b6e4e3a676b016ca781f63cfe4a0cd8eaecf3fd6f7a71ae/greenlet-3.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09fc016b73c94e98e29af67ab7b9a879c307c6731a2c9da0db5a7d9b7edd1159", size = 640404, upload_time = "2024-09-20T17:36:45.588Z" }, + { url = "https://files.pythonhosted.org/packages/e5/de/6e05f5c59262a584e502dd3d261bbdd2c97ab5416cc9c0b91ea38932a901/greenlet-3.1.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d5e975ca70269d66d17dd995dafc06f1b06e8cb1ec1e9ed54c1d1e4a7c4cf26e", size = 652813, upload_time = "2024-09-20T17:39:19.052Z" }, + { url = "https://files.pythonhosted.org/packages/49/93/d5f93c84241acdea15a8fd329362c2c71c79e1a507c3f142a5d67ea435ae/greenlet-3.1.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b2813dc3de8c1ee3f924e4d4227999285fd335d1bcc0d2be6dc3f1f6a318ec1", size = 648517, upload_time = "2024-09-20T17:44:24.101Z" }, + { url = "https://files.pythonhosted.org/packages/15/85/72f77fc02d00470c86a5c982b8daafdf65d38aefbbe441cebff3bf7037fc/greenlet-3.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e347b3bfcf985a05e8c0b7d462ba6f15b1ee1c909e2dcad795e49e91b152c383", size = 647831, upload_time = "2024-09-20T17:08:40.577Z" }, + { url = "https://files.pythonhosted.org/packages/f7/4b/1c9695aa24f808e156c8f4813f685d975ca73c000c2a5056c514c64980f6/greenlet-3.1.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e8f8c9cb53cdac7ba9793c276acd90168f416b9ce36799b9b885790f8ad6c0a", size = 602413, upload_time = "2024-09-20T17:08:31.728Z" }, + { url = "https://files.pythonhosted.org/packages/76/70/ad6e5b31ef330f03b12559d19fda2606a522d3849cde46b24f223d6d1619/greenlet-3.1.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:62ee94988d6b4722ce0028644418d93a52429e977d742ca2ccbe1c4f4a792511", size = 1129619, upload_time = "2024-09-20T17:44:14.222Z" }, + { url = "https://files.pythonhosted.org/packages/f4/fb/201e1b932e584066e0f0658b538e73c459b34d44b4bd4034f682423bc801/greenlet-3.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1776fd7f989fc6b8d8c8cb8da1f6b82c5814957264d1f6cf818d475ec2bf6395", size = 1155198, upload_time = "2024-09-20T17:09:23.903Z" }, + { url = "https://files.pythonhosted.org/packages/12/da/b9ed5e310bb8b89661b80cbcd4db5a067903bbcd7fc854923f5ebb4144f0/greenlet-3.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:48ca08c771c268a768087b408658e216133aecd835c0ded47ce955381105ba39", size = 298930, upload_time = "2024-09-20T17:25:18.656Z" }, + { url = "https://files.pythonhosted.org/packages/7d/ec/bad1ac26764d26aa1353216fcbfa4670050f66d445448aafa227f8b16e80/greenlet-3.1.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:4afe7ea89de619adc868e087b4d2359282058479d7cfb94970adf4b55284574d", size = 274260, upload_time = "2024-09-20T17:08:07.301Z" }, + { url = "https://files.pythonhosted.org/packages/66/d4/c8c04958870f482459ab5956c2942c4ec35cac7fe245527f1039837c17a9/greenlet-3.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f406b22b7c9a9b4f8aa9d2ab13d6ae0ac3e85c9a809bd590ad53fed2bf70dc79", size = 649064, upload_time = "2024-09-20T17:36:47.628Z" }, + { url = "https://files.pythonhosted.org/packages/51/41/467b12a8c7c1303d20abcca145db2be4e6cd50a951fa30af48b6ec607581/greenlet-3.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c3a701fe5a9695b238503ce5bbe8218e03c3bcccf7e204e455e7462d770268aa", size = 663420, upload_time = "2024-09-20T17:39:21.258Z" }, + { url = "https://files.pythonhosted.org/packages/27/8f/2a93cd9b1e7107d5c7b3b7816eeadcac2ebcaf6d6513df9abaf0334777f6/greenlet-3.1.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2846930c65b47d70b9d178e89c7e1a69c95c1f68ea5aa0a58646b7a96df12441", size = 658035, upload_time = "2024-09-20T17:44:26.501Z" }, + { url = "https://files.pythonhosted.org/packages/57/5c/7c6f50cb12be092e1dccb2599be5a942c3416dbcfb76efcf54b3f8be4d8d/greenlet-3.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99cfaa2110534e2cf3ba31a7abcac9d328d1d9f1b95beede58294a60348fba36", size = 660105, upload_time = "2024-09-20T17:08:42.048Z" }, + { url = "https://files.pythonhosted.org/packages/f1/66/033e58a50fd9ec9df00a8671c74f1f3a320564c6415a4ed82a1c651654ba/greenlet-3.1.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1443279c19fca463fc33e65ef2a935a5b09bb90f978beab37729e1c3c6c25fe9", size = 613077, upload_time = "2024-09-20T17:08:33.707Z" }, + { url = "https://files.pythonhosted.org/packages/19/c5/36384a06f748044d06bdd8776e231fadf92fc896bd12cb1c9f5a1bda9578/greenlet-3.1.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b7cede291382a78f7bb5f04a529cb18e068dd29e0fb27376074b6d0317bf4dd0", size = 1135975, upload_time = "2024-09-20T17:44:15.989Z" }, + { url = "https://files.pythonhosted.org/packages/38/f9/c0a0eb61bdf808d23266ecf1d63309f0e1471f284300ce6dac0ae1231881/greenlet-3.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:23f20bb60ae298d7d8656c6ec6db134bca379ecefadb0b19ce6f19d1f232a942", size = 1163955, upload_time = "2024-09-20T17:09:25.539Z" }, + { url = "https://files.pythonhosted.org/packages/43/21/a5d9df1d21514883333fc86584c07c2b49ba7c602e670b174bd73cfc9c7f/greenlet-3.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:7124e16b4c55d417577c2077be379514321916d5790fa287c9ed6f23bd2ffd01", size = 299655, upload_time = "2024-09-20T17:21:22.427Z" }, + { url = "https://files.pythonhosted.org/packages/f3/57/0db4940cd7bb461365ca8d6fd53e68254c9dbbcc2b452e69d0d41f10a85e/greenlet-3.1.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:05175c27cb459dcfc05d026c4232f9de8913ed006d42713cb8a5137bd49375f1", size = 272990, upload_time = "2024-09-20T17:08:26.312Z" }, + { url = "https://files.pythonhosted.org/packages/1c/ec/423d113c9f74e5e402e175b157203e9102feeb7088cee844d735b28ef963/greenlet-3.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:935e943ec47c4afab8965954bf49bfa639c05d4ccf9ef6e924188f762145c0ff", size = 649175, upload_time = "2024-09-20T17:36:48.983Z" }, + { url = "https://files.pythonhosted.org/packages/a9/46/ddbd2db9ff209186b7b7c621d1432e2f21714adc988703dbdd0e65155c77/greenlet-3.1.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:667a9706c970cb552ede35aee17339a18e8f2a87a51fba2ed39ceeeb1004798a", size = 663425, upload_time = "2024-09-20T17:39:22.705Z" }, + { url = "https://files.pythonhosted.org/packages/bc/f9/9c82d6b2b04aa37e38e74f0c429aece5eeb02bab6e3b98e7db89b23d94c6/greenlet-3.1.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b8a678974d1f3aa55f6cc34dc480169d58f2e6d8958895d68845fa4ab566509e", size = 657736, upload_time = "2024-09-20T17:44:28.544Z" }, + { url = "https://files.pythonhosted.org/packages/d9/42/b87bc2a81e3a62c3de2b0d550bf91a86939442b7ff85abb94eec3fc0e6aa/greenlet-3.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efc0f674aa41b92da8c49e0346318c6075d734994c3c4e4430b1c3f853e498e4", size = 660347, upload_time = "2024-09-20T17:08:45.56Z" }, + { url = "https://files.pythonhosted.org/packages/37/fa/71599c3fd06336cdc3eac52e6871cfebab4d9d70674a9a9e7a482c318e99/greenlet-3.1.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0153404a4bb921f0ff1abeb5ce8a5131da56b953eda6e14b88dc6bbc04d2049e", size = 615583, upload_time = "2024-09-20T17:08:36.85Z" }, + { url = "https://files.pythonhosted.org/packages/4e/96/e9ef85de031703ee7a4483489b40cf307f93c1824a02e903106f2ea315fe/greenlet-3.1.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:275f72decf9932639c1c6dd1013a1bc266438eb32710016a1c742df5da6e60a1", size = 1133039, upload_time = "2024-09-20T17:44:18.287Z" }, + { url = "https://files.pythonhosted.org/packages/87/76/b2b6362accd69f2d1889db61a18c94bc743e961e3cab344c2effaa4b4a25/greenlet-3.1.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c4aab7f6381f38a4b42f269057aee279ab0fc7bf2e929e3d4abfae97b682a12c", size = 1160716, upload_time = "2024-09-20T17:09:27.112Z" }, + { url = "https://files.pythonhosted.org/packages/1f/1b/54336d876186920e185066d8c3024ad55f21d7cc3683c856127ddb7b13ce/greenlet-3.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:b42703b1cf69f2aa1df7d1030b9d77d3e584a70755674d60e710f0af570f3761", size = 299490, upload_time = "2024-09-20T17:17:09.501Z" }, + { url = "https://files.pythonhosted.org/packages/5f/17/bea55bf36990e1638a2af5ba10c1640273ef20f627962cf97107f1e5d637/greenlet-3.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1695e76146579f8c06c1509c7ce4dfe0706f49c6831a817ac04eebb2fd02011", size = 643731, upload_time = "2024-09-20T17:36:50.376Z" }, + { url = "https://files.pythonhosted.org/packages/78/d2/aa3d2157f9ab742a08e0fd8f77d4699f37c22adfbfeb0c610a186b5f75e0/greenlet-3.1.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7876452af029456b3f3549b696bb36a06db7c90747740c5302f74a9e9fa14b13", size = 649304, upload_time = "2024-09-20T17:39:24.55Z" }, + { url = "https://files.pythonhosted.org/packages/f1/8e/d0aeffe69e53ccff5a28fa86f07ad1d2d2d6537a9506229431a2a02e2f15/greenlet-3.1.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ead44c85f8ab905852d3de8d86f6f8baf77109f9da589cb4fa142bd3b57b475", size = 646537, upload_time = "2024-09-20T17:44:31.102Z" }, + { url = "https://files.pythonhosted.org/packages/05/79/e15408220bbb989469c8871062c97c6c9136770657ba779711b90870d867/greenlet-3.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8320f64b777d00dd7ccdade271eaf0cad6636343293a25074cc5566160e4de7b", size = 642506, upload_time = "2024-09-20T17:08:47.852Z" }, + { url = "https://files.pythonhosted.org/packages/18/87/470e01a940307796f1d25f8167b551a968540fbe0551c0ebb853cb527dd6/greenlet-3.1.1-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6510bf84a6b643dabba74d3049ead221257603a253d0a9873f55f6a59a65f822", size = 602753, upload_time = "2024-09-20T17:08:38.079Z" }, + { url = "https://files.pythonhosted.org/packages/e2/72/576815ba674eddc3c25028238f74d7b8068902b3968cbe456771b166455e/greenlet-3.1.1-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:04b013dc07c96f83134b1e99888e7a79979f1a247e2a9f59697fa14b5862ed01", size = 1122731, upload_time = "2024-09-20T17:44:20.556Z" }, + { url = "https://files.pythonhosted.org/packages/ac/38/08cc303ddddc4b3d7c628c3039a61a3aae36c241ed01393d00c2fd663473/greenlet-3.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:411f015496fec93c1c8cd4e5238da364e1da7a124bcb293f085bf2860c32c6f6", size = 1142112, upload_time = "2024-09-20T17:09:28.753Z" }, ] [[package]] @@ -796,18 +805,18 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "packaging" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/34/72/9614c465dc206155d93eff0ca20d42e1e35afc533971379482de953521a4/gunicorn-23.0.0.tar.gz", hash = "sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec", size = 375031 } +sdist = { url = "https://files.pythonhosted.org/packages/34/72/9614c465dc206155d93eff0ca20d42e1e35afc533971379482de953521a4/gunicorn-23.0.0.tar.gz", hash = "sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec", size = 375031, upload_time = "2024-08-10T20:25:27.378Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/7d/6dac2a6e1eba33ee43f318edbed4ff29151a49b5d37f080aad1e6469bca4/gunicorn-23.0.0-py3-none-any.whl", hash = "sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d", size = 85029 }, + { url = "https://files.pythonhosted.org/packages/cb/7d/6dac2a6e1eba33ee43f318edbed4ff29151a49b5d37f080aad1e6469bca4/gunicorn-23.0.0-py3-none-any.whl", hash = "sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d", size = 85029, upload_time = "2024-08-10T20:25:24.996Z" }, ] [[package]] name = "h11" version = "0.14.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418 } +sdist = { url = "https://files.pythonhosted.org/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418, upload_time = "2022-09-25T15:40:01.519Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 }, + { url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259, upload_time = "2022-09-25T15:39:59.68Z" }, ] [[package]] @@ -818,45 +827,45 @@ dependencies = [ { name = "certifi" }, { name = "h11" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/18/56/78a38490b834fa0942cbe6d39bd8a7fd76316e8940319305a98d2b320366/httpcore-1.0.2.tar.gz", hash = "sha256:9fc092e4799b26174648e54b74ed5f683132a464e95643b226e00c2ed2fa6535", size = 81036 } +sdist = { url = "https://files.pythonhosted.org/packages/18/56/78a38490b834fa0942cbe6d39bd8a7fd76316e8940319305a98d2b320366/httpcore-1.0.2.tar.gz", hash = "sha256:9fc092e4799b26174648e54b74ed5f683132a464e95643b226e00c2ed2fa6535", size = 81036, upload_time = "2023-11-10T13:37:42.496Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/56/ba/78b0a99c4da0ff8b0f59defa2f13ca4668189b134bd9840b6202a93d9a0f/httpcore-1.0.2-py3-none-any.whl", hash = "sha256:096cc05bca73b8e459a1fc3dcf585148f63e534eae4339559c9b8a8d6399acc7", size = 76943 }, + { url = "https://files.pythonhosted.org/packages/56/ba/78b0a99c4da0ff8b0f59defa2f13ca4668189b134bd9840b6202a93d9a0f/httpcore-1.0.2-py3-none-any.whl", hash = "sha256:096cc05bca73b8e459a1fc3dcf585148f63e534eae4339559c9b8a8d6399acc7", size = 76943, upload_time = "2023-11-10T13:37:40.937Z" }, ] [[package]] name = "httptools" version = "0.6.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a7/9a/ce5e1f7e131522e6d3426e8e7a490b3a01f39a6696602e1c4f33f9e94277/httptools-0.6.4.tar.gz", hash = "sha256:4e93eee4add6493b59a5c514da98c939b244fce4a0d8879cd3f466562f4b7d5c", size = 240639 } +sdist = { url = "https://files.pythonhosted.org/packages/a7/9a/ce5e1f7e131522e6d3426e8e7a490b3a01f39a6696602e1c4f33f9e94277/httptools-0.6.4.tar.gz", hash = "sha256:4e93eee4add6493b59a5c514da98c939b244fce4a0d8879cd3f466562f4b7d5c", size = 240639, upload_time = "2024-10-16T19:45:08.902Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3b/6f/972f8eb0ea7d98a1c6be436e2142d51ad2a64ee18e02b0e7ff1f62171ab1/httptools-0.6.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3c73ce323711a6ffb0d247dcd5a550b8babf0f757e86a52558fe5b86d6fefcc0", size = 198780 }, - { url = "https://files.pythonhosted.org/packages/6a/b0/17c672b4bc5c7ba7f201eada4e96c71d0a59fbc185e60e42580093a86f21/httptools-0.6.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:345c288418f0944a6fe67be8e6afa9262b18c7626c3ef3c28adc5eabc06a68da", size = 103297 }, - { url = "https://files.pythonhosted.org/packages/92/5e/b4a826fe91971a0b68e8c2bd4e7db3e7519882f5a8ccdb1194be2b3ab98f/httptools-0.6.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deee0e3343f98ee8047e9f4c5bc7cedbf69f5734454a94c38ee829fb2d5fa3c1", size = 443130 }, - { url = "https://files.pythonhosted.org/packages/b0/51/ce61e531e40289a681a463e1258fa1e05e0be54540e40d91d065a264cd8f/httptools-0.6.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca80b7485c76f768a3bc83ea58373f8db7b015551117375e4918e2aa77ea9b50", size = 442148 }, - { url = "https://files.pythonhosted.org/packages/ea/9e/270b7d767849b0c96f275c695d27ca76c30671f8eb8cc1bab6ced5c5e1d0/httptools-0.6.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:90d96a385fa941283ebd231464045187a31ad932ebfa541be8edf5b3c2328959", size = 415949 }, - { url = "https://files.pythonhosted.org/packages/81/86/ced96e3179c48c6f656354e106934e65c8963d48b69be78f355797f0e1b3/httptools-0.6.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:59e724f8b332319e2875efd360e61ac07f33b492889284a3e05e6d13746876f4", size = 417591 }, - { url = "https://files.pythonhosted.org/packages/75/73/187a3f620ed3175364ddb56847d7a608a6fc42d551e133197098c0143eca/httptools-0.6.4-cp310-cp310-win_amd64.whl", hash = "sha256:c26f313951f6e26147833fc923f78f95604bbec812a43e5ee37f26dc9e5a686c", size = 88344 }, - { url = "https://files.pythonhosted.org/packages/7b/26/bb526d4d14c2774fe07113ca1db7255737ffbb119315839af2065abfdac3/httptools-0.6.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f47f8ed67cc0ff862b84a1189831d1d33c963fb3ce1ee0c65d3b0cbe7b711069", size = 199029 }, - { url = "https://files.pythonhosted.org/packages/a6/17/3e0d3e9b901c732987a45f4f94d4e2c62b89a041d93db89eafb262afd8d5/httptools-0.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0614154d5454c21b6410fdf5262b4a3ddb0f53f1e1721cfd59d55f32138c578a", size = 103492 }, - { url = "https://files.pythonhosted.org/packages/b7/24/0fe235d7b69c42423c7698d086d4db96475f9b50b6ad26a718ef27a0bce6/httptools-0.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8787367fbdfccae38e35abf7641dafc5310310a5987b689f4c32cc8cc3ee975", size = 462891 }, - { url = "https://files.pythonhosted.org/packages/b1/2f/205d1f2a190b72da6ffb5f41a3736c26d6fa7871101212b15e9b5cd8f61d/httptools-0.6.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40b0f7fe4fd38e6a507bdb751db0379df1e99120c65fbdc8ee6c1d044897a636", size = 459788 }, - { url = "https://files.pythonhosted.org/packages/6e/4c/d09ce0eff09057a206a74575ae8f1e1e2f0364d20e2442224f9e6612c8b9/httptools-0.6.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:40a5ec98d3f49904b9fe36827dcf1aadfef3b89e2bd05b0e35e94f97c2b14721", size = 433214 }, - { url = "https://files.pythonhosted.org/packages/3e/d2/84c9e23edbccc4a4c6f96a1b8d99dfd2350289e94f00e9ccc7aadde26fb5/httptools-0.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dacdd3d10ea1b4ca9df97a0a303cbacafc04b5cd375fa98732678151643d4988", size = 434120 }, - { url = "https://files.pythonhosted.org/packages/d0/46/4d8e7ba9581416de1c425b8264e2cadd201eb709ec1584c381f3e98f51c1/httptools-0.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:288cd628406cc53f9a541cfaf06041b4c71d751856bab45e3702191f931ccd17", size = 88565 }, - { url = "https://files.pythonhosted.org/packages/bb/0e/d0b71465c66b9185f90a091ab36389a7352985fe857e352801c39d6127c8/httptools-0.6.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:df017d6c780287d5c80601dafa31f17bddb170232d85c066604d8558683711a2", size = 200683 }, - { url = "https://files.pythonhosted.org/packages/e2/b8/412a9bb28d0a8988de3296e01efa0bd62068b33856cdda47fe1b5e890954/httptools-0.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:85071a1e8c2d051b507161f6c3e26155b5c790e4e28d7f236422dbacc2a9cc44", size = 104337 }, - { url = "https://files.pythonhosted.org/packages/9b/01/6fb20be3196ffdc8eeec4e653bc2a275eca7f36634c86302242c4fbb2760/httptools-0.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69422b7f458c5af875922cdb5bd586cc1f1033295aa9ff63ee196a87519ac8e1", size = 508796 }, - { url = "https://files.pythonhosted.org/packages/f7/d8/b644c44acc1368938317d76ac991c9bba1166311880bcc0ac297cb9d6bd7/httptools-0.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16e603a3bff50db08cd578d54f07032ca1631450ceb972c2f834c2b860c28ea2", size = 510837 }, - { url = "https://files.pythonhosted.org/packages/52/d8/254d16a31d543073a0e57f1c329ca7378d8924e7e292eda72d0064987486/httptools-0.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ec4f178901fa1834d4a060320d2f3abc5c9e39766953d038f1458cb885f47e81", size = 485289 }, - { url = "https://files.pythonhosted.org/packages/5f/3c/4aee161b4b7a971660b8be71a92c24d6c64372c1ab3ae7f366b3680df20f/httptools-0.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f9eb89ecf8b290f2e293325c646a211ff1c2493222798bb80a530c5e7502494f", size = 489779 }, - { url = "https://files.pythonhosted.org/packages/12/b7/5cae71a8868e555f3f67a50ee7f673ce36eac970f029c0c5e9d584352961/httptools-0.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:db78cb9ca56b59b016e64b6031eda5653be0589dba2b1b43453f6e8b405a0970", size = 88634 }, - { url = "https://files.pythonhosted.org/packages/94/a3/9fe9ad23fd35f7de6b91eeb60848986058bd8b5a5c1e256f5860a160cc3e/httptools-0.6.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ade273d7e767d5fae13fa637f4d53b6e961fb7fd93c7797562663f0171c26660", size = 197214 }, - { url = "https://files.pythonhosted.org/packages/ea/d9/82d5e68bab783b632023f2fa31db20bebb4e89dfc4d2293945fd68484ee4/httptools-0.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:856f4bc0478ae143bad54a4242fccb1f3f86a6e1be5548fecfd4102061b3a083", size = 102431 }, - { url = "https://files.pythonhosted.org/packages/96/c1/cb499655cbdbfb57b577734fde02f6fa0bbc3fe9fb4d87b742b512908dff/httptools-0.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:322d20ea9cdd1fa98bd6a74b77e2ec5b818abdc3d36695ab402a0de8ef2865a3", size = 473121 }, - { url = "https://files.pythonhosted.org/packages/af/71/ee32fd358f8a3bb199b03261f10921716990808a675d8160b5383487a317/httptools-0.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d87b29bd4486c0093fc64dea80231f7c7f7eb4dc70ae394d70a495ab8436071", size = 473805 }, - { url = "https://files.pythonhosted.org/packages/8a/0a/0d4df132bfca1507114198b766f1737d57580c9ad1cf93c1ff673e3387be/httptools-0.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:342dd6946aa6bda4b8f18c734576106b8a31f2fe31492881a9a160ec84ff4bd5", size = 448858 }, - { url = "https://files.pythonhosted.org/packages/1e/6a/787004fdef2cabea27bad1073bf6a33f2437b4dbd3b6fb4a9d71172b1c7c/httptools-0.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b36913ba52008249223042dca46e69967985fb4051951f94357ea681e1f5dc0", size = 452042 }, - { url = "https://files.pythonhosted.org/packages/4d/dc/7decab5c404d1d2cdc1bb330b1bf70e83d6af0396fd4fc76fc60c0d522bf/httptools-0.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:28908df1b9bb8187393d5b5db91435ccc9c8e891657f9cbb42a2541b44c82fc8", size = 87682 }, + { url = "https://files.pythonhosted.org/packages/3b/6f/972f8eb0ea7d98a1c6be436e2142d51ad2a64ee18e02b0e7ff1f62171ab1/httptools-0.6.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3c73ce323711a6ffb0d247dcd5a550b8babf0f757e86a52558fe5b86d6fefcc0", size = 198780, upload_time = "2024-10-16T19:44:06.882Z" }, + { url = "https://files.pythonhosted.org/packages/6a/b0/17c672b4bc5c7ba7f201eada4e96c71d0a59fbc185e60e42580093a86f21/httptools-0.6.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:345c288418f0944a6fe67be8e6afa9262b18c7626c3ef3c28adc5eabc06a68da", size = 103297, upload_time = "2024-10-16T19:44:08.129Z" }, + { url = "https://files.pythonhosted.org/packages/92/5e/b4a826fe91971a0b68e8c2bd4e7db3e7519882f5a8ccdb1194be2b3ab98f/httptools-0.6.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deee0e3343f98ee8047e9f4c5bc7cedbf69f5734454a94c38ee829fb2d5fa3c1", size = 443130, upload_time = "2024-10-16T19:44:09.45Z" }, + { url = "https://files.pythonhosted.org/packages/b0/51/ce61e531e40289a681a463e1258fa1e05e0be54540e40d91d065a264cd8f/httptools-0.6.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca80b7485c76f768a3bc83ea58373f8db7b015551117375e4918e2aa77ea9b50", size = 442148, upload_time = "2024-10-16T19:44:11.539Z" }, + { url = "https://files.pythonhosted.org/packages/ea/9e/270b7d767849b0c96f275c695d27ca76c30671f8eb8cc1bab6ced5c5e1d0/httptools-0.6.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:90d96a385fa941283ebd231464045187a31ad932ebfa541be8edf5b3c2328959", size = 415949, upload_time = "2024-10-16T19:44:13.388Z" }, + { url = "https://files.pythonhosted.org/packages/81/86/ced96e3179c48c6f656354e106934e65c8963d48b69be78f355797f0e1b3/httptools-0.6.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:59e724f8b332319e2875efd360e61ac07f33b492889284a3e05e6d13746876f4", size = 417591, upload_time = "2024-10-16T19:44:15.258Z" }, + { url = "https://files.pythonhosted.org/packages/75/73/187a3f620ed3175364ddb56847d7a608a6fc42d551e133197098c0143eca/httptools-0.6.4-cp310-cp310-win_amd64.whl", hash = "sha256:c26f313951f6e26147833fc923f78f95604bbec812a43e5ee37f26dc9e5a686c", size = 88344, upload_time = "2024-10-16T19:44:16.54Z" }, + { url = "https://files.pythonhosted.org/packages/7b/26/bb526d4d14c2774fe07113ca1db7255737ffbb119315839af2065abfdac3/httptools-0.6.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f47f8ed67cc0ff862b84a1189831d1d33c963fb3ce1ee0c65d3b0cbe7b711069", size = 199029, upload_time = "2024-10-16T19:44:18.427Z" }, + { url = "https://files.pythonhosted.org/packages/a6/17/3e0d3e9b901c732987a45f4f94d4e2c62b89a041d93db89eafb262afd8d5/httptools-0.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0614154d5454c21b6410fdf5262b4a3ddb0f53f1e1721cfd59d55f32138c578a", size = 103492, upload_time = "2024-10-16T19:44:19.515Z" }, + { url = "https://files.pythonhosted.org/packages/b7/24/0fe235d7b69c42423c7698d086d4db96475f9b50b6ad26a718ef27a0bce6/httptools-0.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8787367fbdfccae38e35abf7641dafc5310310a5987b689f4c32cc8cc3ee975", size = 462891, upload_time = "2024-10-16T19:44:21.067Z" }, + { url = "https://files.pythonhosted.org/packages/b1/2f/205d1f2a190b72da6ffb5f41a3736c26d6fa7871101212b15e9b5cd8f61d/httptools-0.6.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40b0f7fe4fd38e6a507bdb751db0379df1e99120c65fbdc8ee6c1d044897a636", size = 459788, upload_time = "2024-10-16T19:44:22.958Z" }, + { url = "https://files.pythonhosted.org/packages/6e/4c/d09ce0eff09057a206a74575ae8f1e1e2f0364d20e2442224f9e6612c8b9/httptools-0.6.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:40a5ec98d3f49904b9fe36827dcf1aadfef3b89e2bd05b0e35e94f97c2b14721", size = 433214, upload_time = "2024-10-16T19:44:24.513Z" }, + { url = "https://files.pythonhosted.org/packages/3e/d2/84c9e23edbccc4a4c6f96a1b8d99dfd2350289e94f00e9ccc7aadde26fb5/httptools-0.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dacdd3d10ea1b4ca9df97a0a303cbacafc04b5cd375fa98732678151643d4988", size = 434120, upload_time = "2024-10-16T19:44:26.295Z" }, + { url = "https://files.pythonhosted.org/packages/d0/46/4d8e7ba9581416de1c425b8264e2cadd201eb709ec1584c381f3e98f51c1/httptools-0.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:288cd628406cc53f9a541cfaf06041b4c71d751856bab45e3702191f931ccd17", size = 88565, upload_time = "2024-10-16T19:44:29.188Z" }, + { url = "https://files.pythonhosted.org/packages/bb/0e/d0b71465c66b9185f90a091ab36389a7352985fe857e352801c39d6127c8/httptools-0.6.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:df017d6c780287d5c80601dafa31f17bddb170232d85c066604d8558683711a2", size = 200683, upload_time = "2024-10-16T19:44:30.175Z" }, + { url = "https://files.pythonhosted.org/packages/e2/b8/412a9bb28d0a8988de3296e01efa0bd62068b33856cdda47fe1b5e890954/httptools-0.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:85071a1e8c2d051b507161f6c3e26155b5c790e4e28d7f236422dbacc2a9cc44", size = 104337, upload_time = "2024-10-16T19:44:31.786Z" }, + { url = "https://files.pythonhosted.org/packages/9b/01/6fb20be3196ffdc8eeec4e653bc2a275eca7f36634c86302242c4fbb2760/httptools-0.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69422b7f458c5af875922cdb5bd586cc1f1033295aa9ff63ee196a87519ac8e1", size = 508796, upload_time = "2024-10-16T19:44:32.825Z" }, + { url = "https://files.pythonhosted.org/packages/f7/d8/b644c44acc1368938317d76ac991c9bba1166311880bcc0ac297cb9d6bd7/httptools-0.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16e603a3bff50db08cd578d54f07032ca1631450ceb972c2f834c2b860c28ea2", size = 510837, upload_time = "2024-10-16T19:44:33.974Z" }, + { url = "https://files.pythonhosted.org/packages/52/d8/254d16a31d543073a0e57f1c329ca7378d8924e7e292eda72d0064987486/httptools-0.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ec4f178901fa1834d4a060320d2f3abc5c9e39766953d038f1458cb885f47e81", size = 485289, upload_time = "2024-10-16T19:44:35.111Z" }, + { url = "https://files.pythonhosted.org/packages/5f/3c/4aee161b4b7a971660b8be71a92c24d6c64372c1ab3ae7f366b3680df20f/httptools-0.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f9eb89ecf8b290f2e293325c646a211ff1c2493222798bb80a530c5e7502494f", size = 489779, upload_time = "2024-10-16T19:44:36.253Z" }, + { url = "https://files.pythonhosted.org/packages/12/b7/5cae71a8868e555f3f67a50ee7f673ce36eac970f029c0c5e9d584352961/httptools-0.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:db78cb9ca56b59b016e64b6031eda5653be0589dba2b1b43453f6e8b405a0970", size = 88634, upload_time = "2024-10-16T19:44:37.357Z" }, + { url = "https://files.pythonhosted.org/packages/94/a3/9fe9ad23fd35f7de6b91eeb60848986058bd8b5a5c1e256f5860a160cc3e/httptools-0.6.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ade273d7e767d5fae13fa637f4d53b6e961fb7fd93c7797562663f0171c26660", size = 197214, upload_time = "2024-10-16T19:44:38.738Z" }, + { url = "https://files.pythonhosted.org/packages/ea/d9/82d5e68bab783b632023f2fa31db20bebb4e89dfc4d2293945fd68484ee4/httptools-0.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:856f4bc0478ae143bad54a4242fccb1f3f86a6e1be5548fecfd4102061b3a083", size = 102431, upload_time = "2024-10-16T19:44:39.818Z" }, + { url = "https://files.pythonhosted.org/packages/96/c1/cb499655cbdbfb57b577734fde02f6fa0bbc3fe9fb4d87b742b512908dff/httptools-0.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:322d20ea9cdd1fa98bd6a74b77e2ec5b818abdc3d36695ab402a0de8ef2865a3", size = 473121, upload_time = "2024-10-16T19:44:41.189Z" }, + { url = "https://files.pythonhosted.org/packages/af/71/ee32fd358f8a3bb199b03261f10921716990808a675d8160b5383487a317/httptools-0.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d87b29bd4486c0093fc64dea80231f7c7f7eb4dc70ae394d70a495ab8436071", size = 473805, upload_time = "2024-10-16T19:44:42.384Z" }, + { url = "https://files.pythonhosted.org/packages/8a/0a/0d4df132bfca1507114198b766f1737d57580c9ad1cf93c1ff673e3387be/httptools-0.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:342dd6946aa6bda4b8f18c734576106b8a31f2fe31492881a9a160ec84ff4bd5", size = 448858, upload_time = "2024-10-16T19:44:43.959Z" }, + { url = "https://files.pythonhosted.org/packages/1e/6a/787004fdef2cabea27bad1073bf6a33f2437b4dbd3b6fb4a9d71172b1c7c/httptools-0.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b36913ba52008249223042dca46e69967985fb4051951f94357ea681e1f5dc0", size = 452042, upload_time = "2024-10-16T19:44:45.071Z" }, + { url = "https://files.pythonhosted.org/packages/4d/dc/7decab5c404d1d2cdc1bb330b1bf70e83d6af0396fd4fc76fc60c0d522bf/httptools-0.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:28908df1b9bb8187393d5b5db91435ccc9c8e891657f9cbb42a2541b44c82fc8", size = 87682, upload_time = "2024-10-16T19:44:46.46Z" }, ] [[package]] @@ -869,9 +878,9 @@ dependencies = [ { name = "httpcore" }, { name = "idna" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406 } +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload_time = "2024-12-06T15:37:23.222Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 }, + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload_time = "2024-12-06T15:37:21.509Z" }, ] [[package]] @@ -887,9 +896,9 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/df/22/8eb91736b1dcb83d879bd49050a09df29a57cc5cd9f38e48a4b1c45ee890/huggingface_hub-0.30.2.tar.gz", hash = "sha256:9a7897c5b6fd9dad3168a794a8998d6378210f5b9688d0dfc180b1a228dc2466", size = 400868 } +sdist = { url = "https://files.pythonhosted.org/packages/df/22/8eb91736b1dcb83d879bd49050a09df29a57cc5cd9f38e48a4b1c45ee890/huggingface_hub-0.30.2.tar.gz", hash = "sha256:9a7897c5b6fd9dad3168a794a8998d6378210f5b9688d0dfc180b1a228dc2466", size = 400868, upload_time = "2025-04-08T08:32:45.26Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/93/27/1fb384a841e9661faad1c31cbfa62864f59632e876df5d795234da51c395/huggingface_hub-0.30.2-py3-none-any.whl", hash = "sha256:68ff05969927058cfa41df4f2155d4bb48f5f54f719dd0390103eefa9b191e28", size = 481433 }, + { url = "https://files.pythonhosted.org/packages/93/27/1fb384a841e9661faad1c31cbfa62864f59632e876df5d795234da51c395/huggingface_hub-0.30.2-py3-none-any.whl", hash = "sha256:68ff05969927058cfa41df4f2155d4bb48f5f54f719dd0390103eefa9b191e28", size = 481433, upload_time = "2025-04-08T08:32:43.305Z" }, ] [[package]] @@ -899,18 +908,18 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pyreadline3", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/cc/3f/2c29224acb2e2df4d2046e4c73ee2662023c58ff5b113c4c1adac0886c43/humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc", size = 360702 } +sdist = { url = "https://files.pythonhosted.org/packages/cc/3f/2c29224acb2e2df4d2046e4c73ee2662023c58ff5b113c4c1adac0886c43/humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc", size = 360702, upload_time = "2021-09-17T21:40:43.31Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f0/0f/310fb31e39e2d734ccaa2c0fb981ee41f7bd5056ce9bc29b2248bd569169/humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477", size = 86794 }, + { url = "https://files.pythonhosted.org/packages/f0/0f/310fb31e39e2d734ccaa2c0fb981ee41f7bd5056ce9bc29b2248bd569169/humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477", size = 86794, upload_time = "2021-09-17T21:40:39.897Z" }, ] [[package]] name = "idna" version = "3.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/bf/3f/ea4b9117521a1e9c50344b909be7886dd00a519552724809bb1f486986c2/idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca", size = 175426 } +sdist = { url = "https://files.pythonhosted.org/packages/bf/3f/ea4b9117521a1e9c50344b909be7886dd00a519552724809bb1f486986c2/idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca", size = 175426, upload_time = "2023-11-25T15:40:54.902Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f", size = 61567 }, + { url = "https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f", size = 61567, upload_time = "2023-11-25T15:40:52.604Z" }, ] [[package]] @@ -921,9 +930,9 @@ dependencies = [ { name = "numpy" }, { name = "pillow" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/25/38/f4c568318c656352d211eec6954460dc3af0b7583a6682308f8a66e4c19b/imageio-2.33.1.tar.gz", hash = "sha256:78722d40b137bd98f5ec7312119f8aea9ad2049f76f434748eb306b6937cc1ce", size = 387374 } +sdist = { url = "https://files.pythonhosted.org/packages/25/38/f4c568318c656352d211eec6954460dc3af0b7583a6682308f8a66e4c19b/imageio-2.33.1.tar.gz", hash = "sha256:78722d40b137bd98f5ec7312119f8aea9ad2049f76f434748eb306b6937cc1ce", size = 387374, upload_time = "2023-12-11T02:26:44.715Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c0/69/3aaa69cb0748e33e644fda114c9abd3186ce369edd4fca11107e9f39c6a7/imageio-2.33.1-py3-none-any.whl", hash = "sha256:c5094c48ccf6b2e6da8b4061cd95e1209380afafcbeae4a4e280938cce227e1d", size = 313345 }, + { url = "https://files.pythonhosted.org/packages/c0/69/3aaa69cb0748e33e644fda114c9abd3186ce369edd4fca11107e9f39c6a7/imageio-2.33.1-py3-none-any.whl", hash = "sha256:c5094c48ccf6b2e6da8b4061cd95e1209380afafcbeae4a4e280938cce227e1d", size = 313345, upload_time = "2023-12-11T02:26:42.724Z" }, ] [[package]] @@ -1080,9 +1089,9 @@ types = [ name = "iniconfig" version = "2.0.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 } +sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646, upload_time = "2023-01-07T11:08:11.254Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 }, + { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892, upload_time = "2023-01-07T11:08:09.864Z" }, ] [[package]] @@ -1104,15 +1113,15 @@ dependencies = [ { name = "scipy" }, { name = "tqdm" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0b/8d/0f4af90999ca96cf8cb846eb5ae27c5ef5b390f9c090dd19e4fa76364c13/insightface-0.7.3.tar.gz", hash = "sha256:f191f719612ebb37018f41936814500544cd0f86e6fcd676c023f354c668ddf7", size = 439490 } +sdist = { url = "https://files.pythonhosted.org/packages/0b/8d/0f4af90999ca96cf8cb846eb5ae27c5ef5b390f9c090dd19e4fa76364c13/insightface-0.7.3.tar.gz", hash = "sha256:f191f719612ebb37018f41936814500544cd0f86e6fcd676c023f354c668ddf7", size = 439490, upload_time = "2023-04-02T08:01:54.541Z" } [[package]] name = "itsdangerous" version = "2.1.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7f/a1/d3fb83e7a61fa0c0d3d08ad0a94ddbeff3731c05212617dff3a94e097f08/itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a", size = 56143 } +sdist = { url = "https://files.pythonhosted.org/packages/7f/a1/d3fb83e7a61fa0c0d3d08ad0a94ddbeff3731c05212617dff3a94e097f08/itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a", size = 56143, upload_time = "2022-03-24T15:12:15.102Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/68/5f/447e04e828f47465eeab35b5d408b7ebaaaee207f48b7136c5a7267a30ae/itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44", size = 15749 }, + { url = "https://files.pythonhosted.org/packages/68/5f/447e04e828f47465eeab35b5d408b7ebaaaee207f48b7136c5a7267a30ae/itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44", size = 15749, upload_time = "2022-03-24T15:12:13.2Z" }, ] [[package]] @@ -1122,93 +1131,94 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markupsafe" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ed/55/39036716d19cab0747a5020fc7e907f362fbf48c984b14e62127f7e68e5d/jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369", size = 240245 } +sdist = { url = "https://files.pythonhosted.org/packages/ed/55/39036716d19cab0747a5020fc7e907f362fbf48c984b14e62127f7e68e5d/jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369", size = 240245, upload_time = "2024-05-05T23:42:02.455Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/31/80/3a54838c3fb461f6fec263ebf3a3a41771bd05190238de3486aae8540c36/jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d", size = 133271 }, + { url = "https://files.pythonhosted.org/packages/31/80/3a54838c3fb461f6fec263ebf3a3a41771bd05190238de3486aae8540c36/jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d", size = 133271, upload_time = "2024-05-05T23:41:59.928Z" }, ] [[package]] name = "joblib" version = "1.3.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/15/0f/d3b33b9f106dddef461f6df1872b7881321b247f3d255b87f61a7636f7fe/joblib-1.3.2.tar.gz", hash = "sha256:92f865e621e17784e7955080b6d042489e3b8e294949cc44c6eac304f59772b1", size = 1987720 } +sdist = { url = "https://files.pythonhosted.org/packages/15/0f/d3b33b9f106dddef461f6df1872b7881321b247f3d255b87f61a7636f7fe/joblib-1.3.2.tar.gz", hash = "sha256:92f865e621e17784e7955080b6d042489e3b8e294949cc44c6eac304f59772b1", size = 1987720, upload_time = "2023-08-09T09:23:40.503Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/10/40/d551139c85db202f1f384ba8bcf96aca2f329440a844f924c8a0040b6d02/joblib-1.3.2-py3-none-any.whl", hash = "sha256:ef4331c65f239985f3f2220ecc87db222f08fd22097a3dd5698f693875f8cbb9", size = 302207 }, + { url = "https://files.pythonhosted.org/packages/10/40/d551139c85db202f1f384ba8bcf96aca2f329440a844f924c8a0040b6d02/joblib-1.3.2-py3-none-any.whl", hash = "sha256:ef4331c65f239985f3f2220ecc87db222f08fd22097a3dd5698f693875f8cbb9", size = 302207, upload_time = "2023-08-09T09:23:34.583Z" }, ] [[package]] name = "kiwisolver" version = "1.4.5" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b9/2d/226779e405724344fc678fcc025b812587617ea1a48b9442628b688e85ea/kiwisolver-1.4.5.tar.gz", hash = "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec", size = 97552 } +sdist = { url = "https://files.pythonhosted.org/packages/b9/2d/226779e405724344fc678fcc025b812587617ea1a48b9442628b688e85ea/kiwisolver-1.4.5.tar.gz", hash = "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec", size = 97552, upload_time = "2023-08-24T09:30:39.861Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f1/56/cb02dcefdaab40df636b91e703b172966b444605a0ea313549f3ffc05bd3/kiwisolver-1.4.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:05703cf211d585109fcd72207a31bb170a0f22144d68298dc5e61b3c946518af", size = 127397 }, - { url = "https://files.pythonhosted.org/packages/0e/c1/d084f8edb26533a191415d5173157080837341f9a06af9dd1a75f727abb4/kiwisolver-1.4.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:146d14bebb7f1dc4d5fbf74f8a6cb15ac42baadee8912eb84ac0b3b2a3dc6ac3", size = 68125 }, - { url = "https://files.pythonhosted.org/packages/23/11/6fb190bae4b279d712a834e7b1da89f6dcff6791132f7399aa28a57c3565/kiwisolver-1.4.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ef7afcd2d281494c0a9101d5c571970708ad911d028137cd558f02b851c08b4", size = 66211 }, - { url = "https://files.pythonhosted.org/packages/b3/13/5e9e52feb33e9e063f76b2c5eb09cb977f5bba622df3210081bfb26ec9a3/kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9eaa8b117dc8337728e834b9c6e2611f10c79e38f65157c4c38e9400286f5cb1", size = 1637145 }, - { url = "https://files.pythonhosted.org/packages/6f/40/4ab1fdb57fced80ce5903f04ae1aed7c1d5939dda4fd0c0aa526c12fe28a/kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec20916e7b4cbfb1f12380e46486ec4bcbaa91a9c448b97023fde0d5bbf9e4ff", size = 1617849 }, - { url = "https://files.pythonhosted.org/packages/49/ca/61ef43bd0832c7253b370735b0c38972c140c8774889b884372a629a8189/kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39b42c68602539407884cf70d6a480a469b93b81b7701378ba5e2328660c847a", size = 1400921 }, - { url = "https://files.pythonhosted.org/packages/68/6f/854f6a845c00b4257482468e08d8bc386f4929ee499206142378ba234419/kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa12042de0171fad672b6c59df69106d20d5596e4f87b5e8f76df757a7c399aa", size = 1513009 }, - { url = "https://files.pythonhosted.org/packages/50/65/76f303377167d12eb7a9b423d6771b39fe5c4373e4a42f075805b1f581ae/kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a40773c71d7ccdd3798f6489aaac9eee213d566850a9533f8d26332d626b82c", size = 1444819 }, - { url = "https://files.pythonhosted.org/packages/7e/ee/98cdf9dde129551467138b6e18cc1cc901e75ecc7ffb898c6f49609f33b1/kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:19df6e621f6d8b4b9c4d45f40a66839294ff2bb235e64d2178f7522d9170ac5b", size = 1817054 }, - { url = "https://files.pythonhosted.org/packages/e6/5b/ab569016ec4abc7b496f6cb8a3ab511372c99feb6a23d948cda97e0db6da/kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:83d78376d0d4fd884e2c114d0621624b73d2aba4e2788182d286309ebdeed770", size = 1918613 }, - { url = "https://files.pythonhosted.org/packages/93/ac/39b9f99d2474b1ac7af1ddfe5756ddf9b6a8f24c5f3a32cd4c010317fc6b/kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e391b1f0a8a5a10ab3b9bb6afcfd74f2175f24f8975fb87ecae700d1503cdee0", size = 1872650 }, - { url = "https://files.pythonhosted.org/packages/40/5b/be568548266516b114d1776120281ea9236c732fb6032a1f8f3b1e5e921c/kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:852542f9481f4a62dbb5dd99e8ab7aedfeb8fb6342349a181d4036877410f525", size = 1827415 }, - { url = "https://files.pythonhosted.org/packages/d4/80/c0c13d2a17a12937a19ef378bf35e94399fd171ed6ec05bcee0f038e1eaf/kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59edc41b24031bc25108e210c0def6f6c2191210492a972d585a06ff246bb79b", size = 1838094 }, - { url = "https://files.pythonhosted.org/packages/70/d1/5ab93ee00ca5af708929cc12fbe665b6f1ed4ad58088e70dc00e87e0d107/kiwisolver-1.4.5-cp310-cp310-win32.whl", hash = "sha256:a6aa6315319a052b4ee378aa171959c898a6183f15c1e541821c5c59beaa0238", size = 46585 }, - { url = "https://files.pythonhosted.org/packages/4a/a1/8a9c9be45c642fa12954855d8b3a02d9fd8551165a558835a19508fec2e6/kiwisolver-1.4.5-cp310-cp310-win_amd64.whl", hash = "sha256:d0ef46024e6a3d79c01ff13801cb19d0cad7fd859b15037aec74315540acc276", size = 56095 }, - { url = "https://files.pythonhosted.org/packages/2a/eb/9e099ad7c47c279995d2d20474e1821100a5f10f847739bd65b1c1f02442/kiwisolver-1.4.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:11863aa14a51fd6ec28688d76f1735f8f69ab1fabf388851a595d0721af042f5", size = 127403 }, - { url = "https://files.pythonhosted.org/packages/a6/94/695922e71288855fc7cace3bdb52edda9d7e50edba77abb0c9d7abb51e96/kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90", size = 68156 }, - { url = "https://files.pythonhosted.org/packages/4a/fe/23d7fa78f7c66086d196406beb1fb2eaf629dd7adc01c3453033303d17fa/kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797", size = 66166 }, - { url = "https://files.pythonhosted.org/packages/f1/68/f472bf16c9141bb1bea5c0b8c66c68fc1ccb048efdbd8f0872b92125724e/kiwisolver-1.4.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dfdd7c0b105af050eb3d64997809dc21da247cf44e63dc73ff0fd20b96be55a9", size = 1334300 }, - { url = "https://files.pythonhosted.org/packages/8d/26/b4569d1f29751fca22ee915b4ebfef5974f4ef239b3335fc072882bd62d9/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437", size = 1426579 }, - { url = "https://files.pythonhosted.org/packages/f3/a3/804fc7c8bf233806ec0321c9da35971578620f2ab4fafe67d76100b3ce52/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbea0db94288e29afcc4c28afbf3a7ccaf2d7e027489c449cf7e8f83c6346eb9", size = 1541360 }, - { url = "https://files.pythonhosted.org/packages/07/ef/286e1d26524854f6fbd6540e8364d67a8857d61038ac743e11edc42fe217/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ceec1a6bc6cab1d6ff5d06592a91a692f90ec7505d6463a88a52cc0eb58545da", size = 1470091 }, - { url = "https://files.pythonhosted.org/packages/17/ba/17a706b232308e65f57deeccae503c268292e6a091313f6ce833a23093ea/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e", size = 1426259 }, - { url = "https://files.pythonhosted.org/packages/d0/f3/a0925611c9d6c2f37c5935a39203cadec6883aa914e013b46c84c4c2e641/kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f91de7223d4c7b793867797bacd1ee53bfe7359bd70d27b7b58a04efbb9436c8", size = 1847516 }, - { url = "https://files.pythonhosted.org/packages/da/85/82d59bb8f7c4c9bb2785138b72462cb1b161668f8230c58bbb28c0403cd5/kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:faae4860798c31530dd184046a900e652c95513796ef51a12bc086710c2eec4d", size = 1946228 }, - { url = "https://files.pythonhosted.org/packages/34/3c/6a37f444c0233993881e5db3a6a1775925d4d9d2f2609bb325bb1348ed94/kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0157420efcb803e71d1b28e2c287518b8808b7cf1ab8af36718fd0a2c453eb0", size = 1901716 }, - { url = "https://files.pythonhosted.org/packages/cd/7e/180425790efc00adfd47db14e1e341cb4826516982334129012b971121a6/kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:06f54715b7737c2fecdbf140d1afb11a33d59508a47bf11bb38ecf21dc9ab79f", size = 1852871 }, - { url = "https://files.pythonhosted.org/packages/1b/9a/13c68b2edb1fa74321e60893a9a5829788e135138e68060cf44e2d92d2c3/kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fdb7adb641a0d13bdcd4ef48e062363d8a9ad4a182ac7647ec88f695e719ae9f", size = 1870265 }, - { url = "https://files.pythonhosted.org/packages/9f/0a/fa56a0fdee5da2b4c79899c0f6bd1aefb29d9438c2d66430e78793571c6b/kiwisolver-1.4.5-cp311-cp311-win32.whl", hash = "sha256:bb86433b1cfe686da83ce32a9d3a8dd308e85c76b60896d58f082136f10bffac", size = 46649 }, - { url = "https://files.pythonhosted.org/packages/1e/37/d3c2d4ba2719059a0f12730947bbe1ad5ee8bff89e8c35319dcb2c9ddb4c/kiwisolver-1.4.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355", size = 56116 }, - { url = "https://files.pythonhosted.org/packages/f3/7a/debbce859be1a2711eb8437818107137192007b88d17b5cfdb556f457b42/kiwisolver-1.4.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:32d5cf40c4f7c7b3ca500f8985eb3fb3a7dfc023215e876f207956b5ea26632a", size = 125484 }, - { url = "https://files.pythonhosted.org/packages/2d/e0/bf8df75ba93b9e035cc6757dd5dcaf63084fdc1c846ae134e818bd7e0f03/kiwisolver-1.4.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f846c260f483d1fd217fe5ed7c173fb109efa6b1fc8381c8b7552c5781756192", size = 67332 }, - { url = "https://files.pythonhosted.org/packages/26/61/58bb691f6880588be3a4801d199bd776032ece07203faf3e4a8b377f7d9b/kiwisolver-1.4.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ff5cf3571589b6d13bfbfd6bcd7a3f659e42f96b5fd1c4830c4cf21d4f5ef45", size = 64987 }, - { url = "https://files.pythonhosted.org/packages/8e/a3/96ac5413068b237c006f54dd8d70114e8756d70e3da7613c5aef20627e22/kiwisolver-1.4.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7269d9e5f1084a653d575c7ec012ff57f0c042258bf5db0954bf551c158466e7", size = 1370613 }, - { url = "https://files.pythonhosted.org/packages/4d/12/f48539e6e17068b59c7f12f4d6214b973431b8e3ac83af525cafd27cebec/kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da802a19d6e15dffe4b0c24b38b3af68e6c1a68e6e1d8f30148c83864f3881db", size = 1463183 }, - { url = "https://files.pythonhosted.org/packages/f3/70/26c99be8eb034cc8e3f62e0760af1fbdc97a842a7cbc252f7978507d41c2/kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3aba7311af82e335dd1e36ffff68aaca609ca6290c2cb6d821a39aa075d8e3ff", size = 1581248 }, - { url = "https://files.pythonhosted.org/packages/17/f6/f75f20e543639b09b2de7fc864274a5a9b96cda167a6210a1d9d19306b9d/kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763773d53f07244148ccac5b084da5adb90bfaee39c197554f01b286cf869228", size = 1508815 }, - { url = "https://files.pythonhosted.org/packages/e3/d5/bc0f22ac108743062ab703f8d6d71c9c7b077b8839fa358700bfb81770b8/kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2270953c0d8cdab5d422bee7d2007f043473f9d2999631c86a223c9db56cbd16", size = 1466042 }, - { url = "https://files.pythonhosted.org/packages/75/18/98142500f21d6838bcab49ec919414a1f0c6d049d21ddadf139124db6a70/kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d099e745a512f7e3bbe7249ca835f4d357c586d78d79ae8f1dcd4d8adeb9bda9", size = 1885159 }, - { url = "https://files.pythonhosted.org/packages/21/49/a241eff9e0ee013368c1d17957f9d345b0957493c3a43d82ebb558c90b0a/kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:74db36e14a7d1ce0986fa104f7d5637aea5c82ca6326ed0ec5694280942d1162", size = 1981694 }, - { url = "https://files.pythonhosted.org/packages/90/90/9490c3de4788123041b1d600d64434f1eed809a2ce9f688075a22166b289/kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e5bab140c309cb3a6ce373a9e71eb7e4873c70c2dda01df6820474f9889d6d4", size = 1941579 }, - { url = "https://files.pythonhosted.org/packages/b7/bb/a0cc488ef2aa92d7d304318c8549d3ec8dfe6dd3c2c67a44e3922b77bc4f/kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0f114aa76dc1b8f636d077979c0ac22e7cd8f3493abbab152f20eb8d3cda71f3", size = 1888168 }, - { url = "https://files.pythonhosted.org/packages/4f/e9/9c0de8e45fef3d63f85eed3b1757f9aa511065942866331ef8b99421f433/kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:88a2df29d4724b9237fc0c6eaf2a1adae0cdc0b3e9f4d8e7dc54b16812d2d81a", size = 1908464 }, - { url = "https://files.pythonhosted.org/packages/a3/60/4f0fd50b08f5be536ea0cef518ac7255d9dab43ca40f3b93b60e3ddf80dd/kiwisolver-1.4.5-cp312-cp312-win32.whl", hash = "sha256:72d40b33e834371fd330fb1472ca19d9b8327acb79a5821d4008391db8e29f20", size = 46473 }, - { url = "https://files.pythonhosted.org/packages/63/50/2746566bdf4a6a842d117367d05c90cfb87ac04e9e2845aa1fa21f071362/kiwisolver-1.4.5-cp312-cp312-win_amd64.whl", hash = "sha256:2c5674c4e74d939b9d91dda0fae10597ac7521768fec9e399c70a1f27e2ea2d9", size = 56004 }, + { url = "https://files.pythonhosted.org/packages/f1/56/cb02dcefdaab40df636b91e703b172966b444605a0ea313549f3ffc05bd3/kiwisolver-1.4.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:05703cf211d585109fcd72207a31bb170a0f22144d68298dc5e61b3c946518af", size = 127397, upload_time = "2023-08-24T09:28:18.105Z" }, + { url = "https://files.pythonhosted.org/packages/0e/c1/d084f8edb26533a191415d5173157080837341f9a06af9dd1a75f727abb4/kiwisolver-1.4.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:146d14bebb7f1dc4d5fbf74f8a6cb15ac42baadee8912eb84ac0b3b2a3dc6ac3", size = 68125, upload_time = "2023-08-24T09:28:19.218Z" }, + { url = "https://files.pythonhosted.org/packages/23/11/6fb190bae4b279d712a834e7b1da89f6dcff6791132f7399aa28a57c3565/kiwisolver-1.4.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ef7afcd2d281494c0a9101d5c571970708ad911d028137cd558f02b851c08b4", size = 66211, upload_time = "2023-08-24T09:28:20.241Z" }, + { url = "https://files.pythonhosted.org/packages/b3/13/5e9e52feb33e9e063f76b2c5eb09cb977f5bba622df3210081bfb26ec9a3/kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9eaa8b117dc8337728e834b9c6e2611f10c79e38f65157c4c38e9400286f5cb1", size = 1637145, upload_time = "2023-08-24T09:28:21.439Z" }, + { url = "https://files.pythonhosted.org/packages/6f/40/4ab1fdb57fced80ce5903f04ae1aed7c1d5939dda4fd0c0aa526c12fe28a/kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec20916e7b4cbfb1f12380e46486ec4bcbaa91a9c448b97023fde0d5bbf9e4ff", size = 1617849, upload_time = "2023-08-24T09:28:23.004Z" }, + { url = "https://files.pythonhosted.org/packages/49/ca/61ef43bd0832c7253b370735b0c38972c140c8774889b884372a629a8189/kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39b42c68602539407884cf70d6a480a469b93b81b7701378ba5e2328660c847a", size = 1400921, upload_time = "2023-08-24T09:28:24.331Z" }, + { url = "https://files.pythonhosted.org/packages/68/6f/854f6a845c00b4257482468e08d8bc386f4929ee499206142378ba234419/kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa12042de0171fad672b6c59df69106d20d5596e4f87b5e8f76df757a7c399aa", size = 1513009, upload_time = "2023-08-24T09:28:25.636Z" }, + { url = "https://files.pythonhosted.org/packages/50/65/76f303377167d12eb7a9b423d6771b39fe5c4373e4a42f075805b1f581ae/kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a40773c71d7ccdd3798f6489aaac9eee213d566850a9533f8d26332d626b82c", size = 1444819, upload_time = "2023-08-24T09:28:27.547Z" }, + { url = "https://files.pythonhosted.org/packages/7e/ee/98cdf9dde129551467138b6e18cc1cc901e75ecc7ffb898c6f49609f33b1/kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:19df6e621f6d8b4b9c4d45f40a66839294ff2bb235e64d2178f7522d9170ac5b", size = 1817054, upload_time = "2023-08-24T09:28:28.839Z" }, + { url = "https://files.pythonhosted.org/packages/e6/5b/ab569016ec4abc7b496f6cb8a3ab511372c99feb6a23d948cda97e0db6da/kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:83d78376d0d4fd884e2c114d0621624b73d2aba4e2788182d286309ebdeed770", size = 1918613, upload_time = "2023-08-24T09:28:30.351Z" }, + { url = "https://files.pythonhosted.org/packages/93/ac/39b9f99d2474b1ac7af1ddfe5756ddf9b6a8f24c5f3a32cd4c010317fc6b/kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e391b1f0a8a5a10ab3b9bb6afcfd74f2175f24f8975fb87ecae700d1503cdee0", size = 1872650, upload_time = "2023-08-24T09:28:32.303Z" }, + { url = "https://files.pythonhosted.org/packages/40/5b/be568548266516b114d1776120281ea9236c732fb6032a1f8f3b1e5e921c/kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:852542f9481f4a62dbb5dd99e8ab7aedfeb8fb6342349a181d4036877410f525", size = 1827415, upload_time = "2023-08-24T09:28:34.141Z" }, + { url = "https://files.pythonhosted.org/packages/d4/80/c0c13d2a17a12937a19ef378bf35e94399fd171ed6ec05bcee0f038e1eaf/kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59edc41b24031bc25108e210c0def6f6c2191210492a972d585a06ff246bb79b", size = 1838094, upload_time = "2023-08-24T09:28:35.97Z" }, + { url = "https://files.pythonhosted.org/packages/70/d1/5ab93ee00ca5af708929cc12fbe665b6f1ed4ad58088e70dc00e87e0d107/kiwisolver-1.4.5-cp310-cp310-win32.whl", hash = "sha256:a6aa6315319a052b4ee378aa171959c898a6183f15c1e541821c5c59beaa0238", size = 46585, upload_time = "2023-08-24T09:28:37.326Z" }, + { url = "https://files.pythonhosted.org/packages/4a/a1/8a9c9be45c642fa12954855d8b3a02d9fd8551165a558835a19508fec2e6/kiwisolver-1.4.5-cp310-cp310-win_amd64.whl", hash = "sha256:d0ef46024e6a3d79c01ff13801cb19d0cad7fd859b15037aec74315540acc276", size = 56095, upload_time = "2023-08-24T09:28:38.325Z" }, + { url = "https://files.pythonhosted.org/packages/2a/eb/9e099ad7c47c279995d2d20474e1821100a5f10f847739bd65b1c1f02442/kiwisolver-1.4.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:11863aa14a51fd6ec28688d76f1735f8f69ab1fabf388851a595d0721af042f5", size = 127403, upload_time = "2023-08-24T09:28:39.3Z" }, + { url = "https://files.pythonhosted.org/packages/a6/94/695922e71288855fc7cace3bdb52edda9d7e50edba77abb0c9d7abb51e96/kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90", size = 68156, upload_time = "2023-08-24T09:28:40.301Z" }, + { url = "https://files.pythonhosted.org/packages/4a/fe/23d7fa78f7c66086d196406beb1fb2eaf629dd7adc01c3453033303d17fa/kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797", size = 66166, upload_time = "2023-08-24T09:28:41.235Z" }, + { url = "https://files.pythonhosted.org/packages/f1/68/f472bf16c9141bb1bea5c0b8c66c68fc1ccb048efdbd8f0872b92125724e/kiwisolver-1.4.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dfdd7c0b105af050eb3d64997809dc21da247cf44e63dc73ff0fd20b96be55a9", size = 1334300, upload_time = "2023-08-24T09:28:42.409Z" }, + { url = "https://files.pythonhosted.org/packages/8d/26/b4569d1f29751fca22ee915b4ebfef5974f4ef239b3335fc072882bd62d9/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437", size = 1426579, upload_time = "2023-08-24T09:28:43.677Z" }, + { url = "https://files.pythonhosted.org/packages/f3/a3/804fc7c8bf233806ec0321c9da35971578620f2ab4fafe67d76100b3ce52/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbea0db94288e29afcc4c28afbf3a7ccaf2d7e027489c449cf7e8f83c6346eb9", size = 1541360, upload_time = "2023-08-24T09:28:45.939Z" }, + { url = "https://files.pythonhosted.org/packages/07/ef/286e1d26524854f6fbd6540e8364d67a8857d61038ac743e11edc42fe217/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ceec1a6bc6cab1d6ff5d06592a91a692f90ec7505d6463a88a52cc0eb58545da", size = 1470091, upload_time = "2023-08-24T09:28:47.959Z" }, + { url = "https://files.pythonhosted.org/packages/17/ba/17a706b232308e65f57deeccae503c268292e6a091313f6ce833a23093ea/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e", size = 1426259, upload_time = "2023-08-24T09:28:49.224Z" }, + { url = "https://files.pythonhosted.org/packages/d0/f3/a0925611c9d6c2f37c5935a39203cadec6883aa914e013b46c84c4c2e641/kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f91de7223d4c7b793867797bacd1ee53bfe7359bd70d27b7b58a04efbb9436c8", size = 1847516, upload_time = "2023-08-24T09:28:50.979Z" }, + { url = "https://files.pythonhosted.org/packages/da/85/82d59bb8f7c4c9bb2785138b72462cb1b161668f8230c58bbb28c0403cd5/kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:faae4860798c31530dd184046a900e652c95513796ef51a12bc086710c2eec4d", size = 1946228, upload_time = "2023-08-24T09:28:52.812Z" }, + { url = "https://files.pythonhosted.org/packages/34/3c/6a37f444c0233993881e5db3a6a1775925d4d9d2f2609bb325bb1348ed94/kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0157420efcb803e71d1b28e2c287518b8808b7cf1ab8af36718fd0a2c453eb0", size = 1901716, upload_time = "2023-08-24T09:28:54.115Z" }, + { url = "https://files.pythonhosted.org/packages/cd/7e/180425790efc00adfd47db14e1e341cb4826516982334129012b971121a6/kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:06f54715b7737c2fecdbf140d1afb11a33d59508a47bf11bb38ecf21dc9ab79f", size = 1852871, upload_time = "2023-08-24T09:28:55.433Z" }, + { url = "https://files.pythonhosted.org/packages/1b/9a/13c68b2edb1fa74321e60893a9a5829788e135138e68060cf44e2d92d2c3/kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fdb7adb641a0d13bdcd4ef48e062363d8a9ad4a182ac7647ec88f695e719ae9f", size = 1870265, upload_time = "2023-08-24T09:28:56.855Z" }, + { url = "https://files.pythonhosted.org/packages/9f/0a/fa56a0fdee5da2b4c79899c0f6bd1aefb29d9438c2d66430e78793571c6b/kiwisolver-1.4.5-cp311-cp311-win32.whl", hash = "sha256:bb86433b1cfe686da83ce32a9d3a8dd308e85c76b60896d58f082136f10bffac", size = 46649, upload_time = "2023-08-24T09:28:58.021Z" }, + { url = "https://files.pythonhosted.org/packages/1e/37/d3c2d4ba2719059a0f12730947bbe1ad5ee8bff89e8c35319dcb2c9ddb4c/kiwisolver-1.4.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355", size = 56116, upload_time = "2023-08-24T09:28:58.994Z" }, + { url = "https://files.pythonhosted.org/packages/f3/7a/debbce859be1a2711eb8437818107137192007b88d17b5cfdb556f457b42/kiwisolver-1.4.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:32d5cf40c4f7c7b3ca500f8985eb3fb3a7dfc023215e876f207956b5ea26632a", size = 125484, upload_time = "2023-08-24T09:28:59.975Z" }, + { url = "https://files.pythonhosted.org/packages/2d/e0/bf8df75ba93b9e035cc6757dd5dcaf63084fdc1c846ae134e818bd7e0f03/kiwisolver-1.4.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f846c260f483d1fd217fe5ed7c173fb109efa6b1fc8381c8b7552c5781756192", size = 67332, upload_time = "2023-08-24T09:29:01.733Z" }, + { url = "https://files.pythonhosted.org/packages/26/61/58bb691f6880588be3a4801d199bd776032ece07203faf3e4a8b377f7d9b/kiwisolver-1.4.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ff5cf3571589b6d13bfbfd6bcd7a3f659e42f96b5fd1c4830c4cf21d4f5ef45", size = 64987, upload_time = "2023-08-24T09:29:02.789Z" }, + { url = "https://files.pythonhosted.org/packages/8e/a3/96ac5413068b237c006f54dd8d70114e8756d70e3da7613c5aef20627e22/kiwisolver-1.4.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7269d9e5f1084a653d575c7ec012ff57f0c042258bf5db0954bf551c158466e7", size = 1370613, upload_time = "2023-08-24T09:29:03.912Z" }, + { url = "https://files.pythonhosted.org/packages/4d/12/f48539e6e17068b59c7f12f4d6214b973431b8e3ac83af525cafd27cebec/kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da802a19d6e15dffe4b0c24b38b3af68e6c1a68e6e1d8f30148c83864f3881db", size = 1463183, upload_time = "2023-08-24T09:29:05.244Z" }, + { url = "https://files.pythonhosted.org/packages/f3/70/26c99be8eb034cc8e3f62e0760af1fbdc97a842a7cbc252f7978507d41c2/kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3aba7311af82e335dd1e36ffff68aaca609ca6290c2cb6d821a39aa075d8e3ff", size = 1581248, upload_time = "2023-08-24T09:29:06.531Z" }, + { url = "https://files.pythonhosted.org/packages/17/f6/f75f20e543639b09b2de7fc864274a5a9b96cda167a6210a1d9d19306b9d/kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763773d53f07244148ccac5b084da5adb90bfaee39c197554f01b286cf869228", size = 1508815, upload_time = "2023-08-24T09:29:07.867Z" }, + { url = "https://files.pythonhosted.org/packages/e3/d5/bc0f22ac108743062ab703f8d6d71c9c7b077b8839fa358700bfb81770b8/kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2270953c0d8cdab5d422bee7d2007f043473f9d2999631c86a223c9db56cbd16", size = 1466042, upload_time = "2023-08-24T09:29:09.403Z" }, + { url = "https://files.pythonhosted.org/packages/75/18/98142500f21d6838bcab49ec919414a1f0c6d049d21ddadf139124db6a70/kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d099e745a512f7e3bbe7249ca835f4d357c586d78d79ae8f1dcd4d8adeb9bda9", size = 1885159, upload_time = "2023-08-24T09:29:10.66Z" }, + { url = "https://files.pythonhosted.org/packages/21/49/a241eff9e0ee013368c1d17957f9d345b0957493c3a43d82ebb558c90b0a/kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:74db36e14a7d1ce0986fa104f7d5637aea5c82ca6326ed0ec5694280942d1162", size = 1981694, upload_time = "2023-08-24T09:29:12.469Z" }, + { url = "https://files.pythonhosted.org/packages/90/90/9490c3de4788123041b1d600d64434f1eed809a2ce9f688075a22166b289/kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e5bab140c309cb3a6ce373a9e71eb7e4873c70c2dda01df6820474f9889d6d4", size = 1941579, upload_time = "2023-08-24T09:29:13.743Z" }, + { url = "https://files.pythonhosted.org/packages/b7/bb/a0cc488ef2aa92d7d304318c8549d3ec8dfe6dd3c2c67a44e3922b77bc4f/kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0f114aa76dc1b8f636d077979c0ac22e7cd8f3493abbab152f20eb8d3cda71f3", size = 1888168, upload_time = "2023-08-24T09:29:15.097Z" }, + { url = "https://files.pythonhosted.org/packages/4f/e9/9c0de8e45fef3d63f85eed3b1757f9aa511065942866331ef8b99421f433/kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:88a2df29d4724b9237fc0c6eaf2a1adae0cdc0b3e9f4d8e7dc54b16812d2d81a", size = 1908464, upload_time = "2023-08-24T09:29:16.539Z" }, + { url = "https://files.pythonhosted.org/packages/a3/60/4f0fd50b08f5be536ea0cef518ac7255d9dab43ca40f3b93b60e3ddf80dd/kiwisolver-1.4.5-cp312-cp312-win32.whl", hash = "sha256:72d40b33e834371fd330fb1472ca19d9b8327acb79a5821d4008391db8e29f20", size = 46473, upload_time = "2023-08-24T09:29:17.956Z" }, + { url = "https://files.pythonhosted.org/packages/63/50/2746566bdf4a6a842d117367d05c90cfb87ac04e9e2845aa1fa21f071362/kiwisolver-1.4.5-cp312-cp312-win_amd64.whl", hash = "sha256:2c5674c4e74d939b9d91dda0fae10597ac7521768fec9e399c70a1f27e2ea2d9", size = 56004, upload_time = "2023-08-24T09:29:19.329Z" }, ] [[package]] name = "lazy-loader" version = "0.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0e/3a/1630a735bfdf9eb857a3b9a53317a1e1658ea97a1b4b39dcb0f71dae81f8/lazy_loader-0.3.tar.gz", hash = "sha256:3b68898e34f5b2a29daaaac172c6555512d0f32074f147e2254e4a6d9d838f37", size = 12268 } +sdist = { url = "https://files.pythonhosted.org/packages/0e/3a/1630a735bfdf9eb857a3b9a53317a1e1658ea97a1b4b39dcb0f71dae81f8/lazy_loader-0.3.tar.gz", hash = "sha256:3b68898e34f5b2a29daaaac172c6555512d0f32074f147e2254e4a6d9d838f37", size = 12268, upload_time = "2023-06-30T21:12:55.362Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a1/c3/65b3814e155836acacf720e5be3b5757130346670ac454fee29d3eda1381/lazy_loader-0.3-py3-none-any.whl", hash = "sha256:1e9e76ee8631e264c62ce10006718e80b2cfc74340d17d1031e0f84af7478554", size = 9087 }, + { url = "https://files.pythonhosted.org/packages/a1/c3/65b3814e155836acacf720e5be3b5757130346670ac454fee29d3eda1381/lazy_loader-0.3-py3-none-any.whl", hash = "sha256:1e9e76ee8631e264c62ce10006718e80b2cfc74340d17d1031e0f84af7478554", size = 9087, upload_time = "2023-06-30T21:12:51.09Z" }, ] [[package]] name = "locust" -version = "2.34.1" +version = "2.36.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "configargparse" }, { name = "flask" }, { name = "flask-cors" }, { name = "flask-login" }, - { name = "gevent", marker = "python_full_version != '3.13.*'" }, + { name = "gevent" }, { name = "geventhttpclient" }, + { name = "locust-cloud" }, { name = "msgpack" }, { name = "psutil" }, { name = "pywin32", marker = "sys_platform == 'win32'" }, @@ -1219,9 +1229,25 @@ dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.11'" }, { name = "werkzeug" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/56/21/c2bfe4f9482f8754e9a1ff2b1840a1abe63640576fc918a67a02fff7d961/locust-2.34.1.tar.gz", hash = "sha256:184a6ffcb0d6c543bbeae4de65cbb198c7e0739d569d48a2b8bf5db962077733", size = 2240533 } +sdist = { url = "https://files.pythonhosted.org/packages/6d/90/55d4fbc8911e5e6ec4072caaca9e8b7b2b11279435c0d1330c9966b0c898/locust-2.36.2.tar.gz", hash = "sha256:604aff7535f5a83b7f666d32373b2dc74ad260c7c3d1dc274f4c82844be72eb6", size = 2251110, upload_time = "2025-04-25T14:03:35.919Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e2/e4/0944fbfb1ce0bf09cb400ed9349d4cbaed1230114e4018ac28805097f1c6/locust-2.34.1-py3-none-any.whl", hash = "sha256:487bfadd584e3320f9862adf5aa1cfa1023e030a6af414f4e0a92e62617ce451", size = 2257910 }, + { url = "https://files.pythonhosted.org/packages/ab/f5/99dab104be69122eee3513dcdc6e0b32d59ca1f4cfd8715470c5f3aa7643/locust-2.36.2-py3-none-any.whl", hash = "sha256:74239f493f44035b25a87a0665deadf41d213b3dcd45774398e511dec15e26eb", size = 2267937, upload_time = "2025-04-25T14:03:33.671Z" }, +] + +[[package]] +name = "locust-cloud" +version = "1.20.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "configargparse" }, + { name = "gevent" }, + { name = "platformdirs" }, + { name = "python-socketio", extra = ["client"] }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/94/47/1ec2478f3d4e526fb8d667b01a75b22093b2e66aea665b5369dd656ceec9/locust_cloud-1.20.7.tar.gz", hash = "sha256:24c16b767adffab51b97f489bcf142e16e2439354fb4296ecbb3e87ad20e220a", size = 448622, upload_time = "2025-04-28T11:01:49.381Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8c/07/62b5b174c77d4281235405f1ffd439f12a877e434e007a24a5299c461e39/locust_cloud-1.20.7-py3-none-any.whl", hash = "sha256:f38214e77993d0ee87114dafa857e1689789ed4bfe4ae57c2b9dc754674f08bc", size = 406619, upload_time = "2025-04-28T11:01:43.135Z" }, ] [[package]] @@ -1231,47 +1257,47 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mdurl" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 } +sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596, upload_time = "2023-06-03T06:41:14.443Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 }, + { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528, upload_time = "2023-06-03T06:41:11.019Z" }, ] [[package]] name = "markupsafe" version = "2.1.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6d/7c/59a3248f411813f8ccba92a55feaac4bf360d29e2ff05ee7d8e1ef2d7dbf/MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad", size = 19132 } +sdist = { url = "https://files.pythonhosted.org/packages/6d/7c/59a3248f411813f8ccba92a55feaac4bf360d29e2ff05ee7d8e1ef2d7dbf/MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad", size = 19132, upload_time = "2023-06-02T21:43:45.578Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/1d/713d443799d935f4d26a4f1510c9e61b1d288592fb869845e5cc92a1e055/MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa", size = 17846 }, - { url = "https://files.pythonhosted.org/packages/f7/9c/86cbd8e0e1d81f0ba420f20539dd459c50537c7751e28102dbfee2b6f28c/MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57", size = 13720 }, - { url = "https://files.pythonhosted.org/packages/a6/56/f1d4ee39e898a9e63470cbb7fae1c58cce6874f25f54220b89213a47f273/MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f", size = 26498 }, - { url = "https://files.pythonhosted.org/packages/12/b3/d9ed2c0971e1435b8a62354b18d3060b66c8cb1d368399ec0b9baa7c0ee5/MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52", size = 25691 }, - { url = "https://files.pythonhosted.org/packages/bf/b7/c5ba9b7ad9ad21fc4a60df226615cf43ead185d328b77b0327d603d00cc5/MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00", size = 25366 }, - { url = "https://files.pythonhosted.org/packages/71/61/f5673d7aac2cf7f203859008bb3fc2b25187aa330067c5e9955e5c5ebbab/MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6", size = 30505 }, - { url = "https://files.pythonhosted.org/packages/47/26/932140621773bfd4df3223fbdd9e78de3477f424f0d2987c313b1cb655ff/MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779", size = 29616 }, - { url = "https://files.pythonhosted.org/packages/3c/c8/74d13c999cbb49e3460bf769025659a37ef4a8e884de629720ab4e42dcdb/MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7", size = 29891 }, - { url = "https://files.pythonhosted.org/packages/96/e4/4db3b1abc5a1fe7295aa0683eafd13832084509c3b8236f3faf8dd4eff75/MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431", size = 16525 }, - { url = "https://files.pythonhosted.org/packages/84/a8/c4aebb8a14a1d39d5135eb8233a0b95831cdc42c4088358449c3ed657044/MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559", size = 17083 }, - { url = "https://files.pythonhosted.org/packages/fe/09/c31503cb8150cf688c1534a7135cc39bb9092f8e0e6369ec73494d16ee0e/MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c", size = 17862 }, - { url = "https://files.pythonhosted.org/packages/c0/c7/171f5ac6b065e1425e8fabf4a4dfbeca76fd8070072c6a41bd5c07d90d8b/MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575", size = 13738 }, - { url = "https://files.pythonhosted.org/packages/a2/f7/9175ad1b8152092f7c3b78c513c1bdfe9287e0564447d1c2d3d1a2471540/MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee", size = 28891 }, - { url = "https://files.pythonhosted.org/packages/fe/21/2eff1de472ca6c99ec3993eab11308787b9879af9ca8bbceb4868cf4f2ca/MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2", size = 28096 }, - { url = "https://files.pythonhosted.org/packages/f4/a0/103f94793c3bf829a18d2415117334ece115aeca56f2df1c47fa02c6dbd6/MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9", size = 27631 }, - { url = "https://files.pythonhosted.org/packages/43/70/f24470f33b2035b035ef0c0ffebf57006beb2272cf3df068fc5154e04ead/MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc", size = 33863 }, - { url = "https://files.pythonhosted.org/packages/32/d4/ce98c4ca713d91c4a17c1a184785cc00b9e9c25699d618956c2b9999500a/MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9", size = 32591 }, - { url = "https://files.pythonhosted.org/packages/bb/82/f88ccb3ca6204a4536cf7af5abdad7c3657adac06ab33699aa67279e0744/MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac", size = 33186 }, - { url = "https://files.pythonhosted.org/packages/44/53/93405d37bb04a10c43b1bdd6f548097478d494d7eadb4b364e3e1337f0cc/MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb", size = 16537 }, - { url = "https://files.pythonhosted.org/packages/be/bb/08b85bc194034efbf572e70c3951549c8eca0ada25363afc154386b5390a/MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686", size = 17089 }, - { url = "https://files.pythonhosted.org/packages/89/5a/ee546f2aa73a1d6fcfa24272f356fe06d29acca81e76b8d32ca53e429a2e/MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc", size = 17849 }, - { url = "https://files.pythonhosted.org/packages/3a/72/9f683a059bde096776e8acf9aa34cbbba21ddc399861fe3953790d4f2cde/MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823", size = 13700 }, - { url = "https://files.pythonhosted.org/packages/9d/78/92f15eb9b1e8f1668a9787ba103cf6f8d19a9efed8150245404836145c24/MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11", size = 29319 }, - { url = "https://files.pythonhosted.org/packages/51/94/9a04085114ff2c24f7424dbc890a281d73c5a74ea935dc2e69c66a3bd558/MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd", size = 28314 }, - { url = "https://files.pythonhosted.org/packages/ec/53/fcb3214bd370185e223b209ce6bb010fb887ea57173ca4f75bd211b24e10/MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939", size = 27696 }, - { url = "https://files.pythonhosted.org/packages/e7/33/54d29854716725d7826079b8984dd235fac76dab1c32321e555d493e61f5/MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c", size = 33746 }, - { url = "https://files.pythonhosted.org/packages/11/40/ea7f85e2681d29bc9301c757257de561923924f24de1802d9c3baa396bb4/MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c", size = 32131 }, - { url = "https://files.pythonhosted.org/packages/41/f1/bc770c37ecd58638c18f8ec85df205dacb818ccf933692082fd93010a4bc/MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1", size = 32878 }, - { url = "https://files.pythonhosted.org/packages/49/74/bf95630aab0a9ed6a67556cd4e54f6aeb0e74f4cb0fd2f229154873a4be4/MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007", size = 16426 }, - { url = "https://files.pythonhosted.org/packages/44/44/dbaf65876e258facd65f586dde158387ab89963e7f2235551afc9c2e24c2/MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb", size = 16979 }, + { url = "https://files.pythonhosted.org/packages/20/1d/713d443799d935f4d26a4f1510c9e61b1d288592fb869845e5cc92a1e055/MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa", size = 17846, upload_time = "2023-06-02T21:42:33.954Z" }, + { url = "https://files.pythonhosted.org/packages/f7/9c/86cbd8e0e1d81f0ba420f20539dd459c50537c7751e28102dbfee2b6f28c/MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57", size = 13720, upload_time = "2023-06-02T21:42:35.102Z" }, + { url = "https://files.pythonhosted.org/packages/a6/56/f1d4ee39e898a9e63470cbb7fae1c58cce6874f25f54220b89213a47f273/MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f", size = 26498, upload_time = "2023-06-02T21:42:36.608Z" }, + { url = "https://files.pythonhosted.org/packages/12/b3/d9ed2c0971e1435b8a62354b18d3060b66c8cb1d368399ec0b9baa7c0ee5/MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52", size = 25691, upload_time = "2023-06-02T21:42:37.778Z" }, + { url = "https://files.pythonhosted.org/packages/bf/b7/c5ba9b7ad9ad21fc4a60df226615cf43ead185d328b77b0327d603d00cc5/MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00", size = 25366, upload_time = "2023-06-02T21:42:39.441Z" }, + { url = "https://files.pythonhosted.org/packages/71/61/f5673d7aac2cf7f203859008bb3fc2b25187aa330067c5e9955e5c5ebbab/MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6", size = 30505, upload_time = "2023-06-02T21:42:41.088Z" }, + { url = "https://files.pythonhosted.org/packages/47/26/932140621773bfd4df3223fbdd9e78de3477f424f0d2987c313b1cb655ff/MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779", size = 29616, upload_time = "2023-06-02T21:42:42.273Z" }, + { url = "https://files.pythonhosted.org/packages/3c/c8/74d13c999cbb49e3460bf769025659a37ef4a8e884de629720ab4e42dcdb/MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7", size = 29891, upload_time = "2023-06-02T21:42:43.635Z" }, + { url = "https://files.pythonhosted.org/packages/96/e4/4db3b1abc5a1fe7295aa0683eafd13832084509c3b8236f3faf8dd4eff75/MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431", size = 16525, upload_time = "2023-06-02T21:42:45.271Z" }, + { url = "https://files.pythonhosted.org/packages/84/a8/c4aebb8a14a1d39d5135eb8233a0b95831cdc42c4088358449c3ed657044/MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559", size = 17083, upload_time = "2023-06-02T21:42:46.948Z" }, + { url = "https://files.pythonhosted.org/packages/fe/09/c31503cb8150cf688c1534a7135cc39bb9092f8e0e6369ec73494d16ee0e/MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c", size = 17862, upload_time = "2023-06-02T21:42:48.569Z" }, + { url = "https://files.pythonhosted.org/packages/c0/c7/171f5ac6b065e1425e8fabf4a4dfbeca76fd8070072c6a41bd5c07d90d8b/MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575", size = 13738, upload_time = "2023-06-02T21:42:49.727Z" }, + { url = "https://files.pythonhosted.org/packages/a2/f7/9175ad1b8152092f7c3b78c513c1bdfe9287e0564447d1c2d3d1a2471540/MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee", size = 28891, upload_time = "2023-06-02T21:42:51.33Z" }, + { url = "https://files.pythonhosted.org/packages/fe/21/2eff1de472ca6c99ec3993eab11308787b9879af9ca8bbceb4868cf4f2ca/MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2", size = 28096, upload_time = "2023-06-02T21:42:52.966Z" }, + { url = "https://files.pythonhosted.org/packages/f4/a0/103f94793c3bf829a18d2415117334ece115aeca56f2df1c47fa02c6dbd6/MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9", size = 27631, upload_time = "2023-06-02T21:42:54.518Z" }, + { url = "https://files.pythonhosted.org/packages/43/70/f24470f33b2035b035ef0c0ffebf57006beb2272cf3df068fc5154e04ead/MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc", size = 33863, upload_time = "2023-06-02T21:42:55.777Z" }, + { url = "https://files.pythonhosted.org/packages/32/d4/ce98c4ca713d91c4a17c1a184785cc00b9e9c25699d618956c2b9999500a/MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9", size = 32591, upload_time = "2023-06-02T21:42:57.415Z" }, + { url = "https://files.pythonhosted.org/packages/bb/82/f88ccb3ca6204a4536cf7af5abdad7c3657adac06ab33699aa67279e0744/MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac", size = 33186, upload_time = "2023-06-02T21:42:59.107Z" }, + { url = "https://files.pythonhosted.org/packages/44/53/93405d37bb04a10c43b1bdd6f548097478d494d7eadb4b364e3e1337f0cc/MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb", size = 16537, upload_time = "2023-06-02T21:43:00.927Z" }, + { url = "https://files.pythonhosted.org/packages/be/bb/08b85bc194034efbf572e70c3951549c8eca0ada25363afc154386b5390a/MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686", size = 17089, upload_time = "2023-06-02T21:43:02.355Z" }, + { url = "https://files.pythonhosted.org/packages/89/5a/ee546f2aa73a1d6fcfa24272f356fe06d29acca81e76b8d32ca53e429a2e/MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc", size = 17849, upload_time = "2023-09-07T16:00:43.795Z" }, + { url = "https://files.pythonhosted.org/packages/3a/72/9f683a059bde096776e8acf9aa34cbbba21ddc399861fe3953790d4f2cde/MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823", size = 13700, upload_time = "2023-09-07T16:00:45.384Z" }, + { url = "https://files.pythonhosted.org/packages/9d/78/92f15eb9b1e8f1668a9787ba103cf6f8d19a9efed8150245404836145c24/MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11", size = 29319, upload_time = "2023-09-07T16:00:46.48Z" }, + { url = "https://files.pythonhosted.org/packages/51/94/9a04085114ff2c24f7424dbc890a281d73c5a74ea935dc2e69c66a3bd558/MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd", size = 28314, upload_time = "2023-09-07T16:00:47.64Z" }, + { url = "https://files.pythonhosted.org/packages/ec/53/fcb3214bd370185e223b209ce6bb010fb887ea57173ca4f75bd211b24e10/MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939", size = 27696, upload_time = "2023-09-07T16:00:48.92Z" }, + { url = "https://files.pythonhosted.org/packages/e7/33/54d29854716725d7826079b8984dd235fac76dab1c32321e555d493e61f5/MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c", size = 33746, upload_time = "2023-09-07T16:00:50.081Z" }, + { url = "https://files.pythonhosted.org/packages/11/40/ea7f85e2681d29bc9301c757257de561923924f24de1802d9c3baa396bb4/MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c", size = 32131, upload_time = "2023-09-07T16:00:51.822Z" }, + { url = "https://files.pythonhosted.org/packages/41/f1/bc770c37ecd58638c18f8ec85df205dacb818ccf933692082fd93010a4bc/MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1", size = 32878, upload_time = "2023-09-07T16:00:53.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/74/bf95630aab0a9ed6a67556cd4e54f6aeb0e74f4cb0fd2f229154873a4be4/MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007", size = 16426, upload_time = "2023-09-07T16:00:55.987Z" }, + { url = "https://files.pythonhosted.org/packages/44/44/dbaf65876e258facd65f586dde158387ab89963e7f2235551afc9c2e24c2/MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb", size = 16979, upload_time = "2023-09-07T16:00:57.77Z" }, ] [[package]] @@ -1289,85 +1315,85 @@ dependencies = [ { name = "pyparsing" }, { name = "python-dateutil" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fb/ab/38a0e94cb01dacb50f06957c2bed1c83b8f9dac6618988a37b2487862944/matplotlib-3.8.2.tar.gz", hash = "sha256:01a978b871b881ee76017152f1f1a0cbf6bd5f7b8ff8c96df0df1bd57d8755a1", size = 35866957 } +sdist = { url = "https://files.pythonhosted.org/packages/fb/ab/38a0e94cb01dacb50f06957c2bed1c83b8f9dac6618988a37b2487862944/matplotlib-3.8.2.tar.gz", hash = "sha256:01a978b871b881ee76017152f1f1a0cbf6bd5f7b8ff8c96df0df1bd57d8755a1", size = 35866957, upload_time = "2023-11-17T21:16:40.15Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/92/d0/fc5f6796a1956f5b9a33555611d01a3cec038f000c3d70ecb051b1631ac4/matplotlib-3.8.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:09796f89fb71a0c0e1e2f4bdaf63fb2cefc84446bb963ecdeb40dfee7dfa98c7", size = 7590640 }, - { url = "https://files.pythonhosted.org/packages/57/44/007b592809f50883c910db9ec4b81b16dfa0136407250fb581824daabf03/matplotlib-3.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6f9c6976748a25e8b9be51ea028df49b8e561eed7809146da7a47dbecebab367", size = 7484350 }, - { url = "https://files.pythonhosted.org/packages/01/87/c7b24f3048234fe10184560263be2173311376dc3d1fa329de7f012d6ce5/matplotlib-3.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b78e4f2cedf303869b782071b55fdde5987fda3038e9d09e58c91cc261b5ad18", size = 11382388 }, - { url = "https://files.pythonhosted.org/packages/19/e5/a4ea514515f270224435c69359abb7a3d152ed31b9ee3ba5e63017461945/matplotlib-3.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e208f46cf6576a7624195aa047cb344a7f802e113bb1a06cfd4bee431de5e31", size = 11611959 }, - { url = "https://files.pythonhosted.org/packages/09/23/ab5a562c9acb81e351b084bea39f65b153918417fb434619cf5a19f44a55/matplotlib-3.8.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:46a569130ff53798ea5f50afce7406e91fdc471ca1e0e26ba976a8c734c9427a", size = 9536938 }, - { url = "https://files.pythonhosted.org/packages/46/37/b5e27ab30ecc0a3694c8a78287b5ef35dad0c3095c144fcc43081170bfd6/matplotlib-3.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:830f00640c965c5b7f6bc32f0d4ce0c36dfe0379f7dd65b07a00c801713ec40a", size = 7643836 }, - { url = "https://files.pythonhosted.org/packages/a9/0d/53afb186adafc7326d093b8333e8a79974c495095771659f4304626c4bc7/matplotlib-3.8.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d86593ccf546223eb75a39b44c32788e6f6440d13cfc4750c1c15d0fcb850b63", size = 7593458 }, - { url = "https://files.pythonhosted.org/packages/ce/25/a557ee10ac9dce1300850024707ce1850a6958f1673a9194be878b99d631/matplotlib-3.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9a5430836811b7652991939012f43d2808a2db9b64ee240387e8c43e2e5578c8", size = 7486840 }, - { url = "https://files.pythonhosted.org/packages/e7/3d/72712b3895ee180f6e342638a8591c31912fbcc09ce9084cc256da16d0a0/matplotlib-3.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9576723858a78751d5aacd2497b8aef29ffea6d1c95981505877f7ac28215c6", size = 11387332 }, - { url = "https://files.pythonhosted.org/packages/92/1a/cd3e0c90d1a763ad90073e13b189b4702f11becf4e71dbbad70a7a149811/matplotlib-3.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ba9cbd8ac6cf422f3102622b20f8552d601bf8837e49a3afed188d560152788", size = 11616911 }, - { url = "https://files.pythonhosted.org/packages/78/4a/bad239071477305a3758eb4810615e310a113399cddd7682998be9f01e97/matplotlib-3.8.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:03f9d160a29e0b65c0790bb07f4f45d6a181b1ac33eb1bb0dd225986450148f0", size = 9549260 }, - { url = "https://files.pythonhosted.org/packages/26/5a/27fd341e4510257789f19a4b4be8bb90d1113b8f176c3dab562b4f21466e/matplotlib-3.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:3773002da767f0a9323ba1a9b9b5d00d6257dbd2a93107233167cfb581f64717", size = 7645742 }, - { url = "https://files.pythonhosted.org/packages/e4/1b/864d28d5a72d586ac137f4ca54d5afc8b869720e30d508dbd9adcce4d231/matplotlib-3.8.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:4c318c1e95e2f5926fba326f68177dee364aa791d6df022ceb91b8221bd0a627", size = 7590988 }, - { url = "https://files.pythonhosted.org/packages/9a/b0/dd2b60f2dd90fbc21d1d3129c36a453c322d7995d5e3589f5b3c59ee528d/matplotlib-3.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:091275d18d942cf1ee9609c830a1bc36610607d8223b1b981c37d5c9fc3e46a4", size = 7483594 }, - { url = "https://files.pythonhosted.org/packages/33/da/9942533ad9f96753bde0e5a5d48eacd6c21de8ea1ad16570e31bda8a017f/matplotlib-3.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b0f3b8ea0e99e233a4bcc44590f01604840d833c280ebb8fe5554fd3e6cfe8d", size = 11380843 }, - { url = "https://files.pythonhosted.org/packages/fc/52/bfd36eb4745a3b21b3946c2c3a15679b620e14574fe2b98e9451b65ef578/matplotlib-3.8.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7b1704a530395aaf73912be741c04d181f82ca78084fbd80bc737be04848331", size = 11604608 }, - { url = "https://files.pythonhosted.org/packages/6d/8c/0cdfbf604d4ea3dfa77435176c51e233cc408ad8f3efbf8d2c9f57cbdafb/matplotlib-3.8.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:533b0e3b0c6768eef8cbe4b583731ce25a91ab54a22f830db2b031e83cca9213", size = 9545252 }, - { url = "https://files.pythonhosted.org/packages/2e/51/c77a14869b7eb9d6fb440e811b754fc3950d6868c38ace57d0632b674415/matplotlib-3.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:0f4fc5d72b75e2c18e55eb32292659cf731d9d5b312a6eb036506304f4675630", size = 7645067 }, + { url = "https://files.pythonhosted.org/packages/92/d0/fc5f6796a1956f5b9a33555611d01a3cec038f000c3d70ecb051b1631ac4/matplotlib-3.8.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:09796f89fb71a0c0e1e2f4bdaf63fb2cefc84446bb963ecdeb40dfee7dfa98c7", size = 7590640, upload_time = "2023-11-17T21:17:02.834Z" }, + { url = "https://files.pythonhosted.org/packages/57/44/007b592809f50883c910db9ec4b81b16dfa0136407250fb581824daabf03/matplotlib-3.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6f9c6976748a25e8b9be51ea028df49b8e561eed7809146da7a47dbecebab367", size = 7484350, upload_time = "2023-11-17T21:17:12.281Z" }, + { url = "https://files.pythonhosted.org/packages/01/87/c7b24f3048234fe10184560263be2173311376dc3d1fa329de7f012d6ce5/matplotlib-3.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b78e4f2cedf303869b782071b55fdde5987fda3038e9d09e58c91cc261b5ad18", size = 11382388, upload_time = "2023-11-17T21:17:26.461Z" }, + { url = "https://files.pythonhosted.org/packages/19/e5/a4ea514515f270224435c69359abb7a3d152ed31b9ee3ba5e63017461945/matplotlib-3.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e208f46cf6576a7624195aa047cb344a7f802e113bb1a06cfd4bee431de5e31", size = 11611959, upload_time = "2023-11-17T21:17:40.541Z" }, + { url = "https://files.pythonhosted.org/packages/09/23/ab5a562c9acb81e351b084bea39f65b153918417fb434619cf5a19f44a55/matplotlib-3.8.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:46a569130ff53798ea5f50afce7406e91fdc471ca1e0e26ba976a8c734c9427a", size = 9536938, upload_time = "2023-11-17T21:17:49.925Z" }, + { url = "https://files.pythonhosted.org/packages/46/37/b5e27ab30ecc0a3694c8a78287b5ef35dad0c3095c144fcc43081170bfd6/matplotlib-3.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:830f00640c965c5b7f6bc32f0d4ce0c36dfe0379f7dd65b07a00c801713ec40a", size = 7643836, upload_time = "2023-11-17T21:17:58.379Z" }, + { url = "https://files.pythonhosted.org/packages/a9/0d/53afb186adafc7326d093b8333e8a79974c495095771659f4304626c4bc7/matplotlib-3.8.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d86593ccf546223eb75a39b44c32788e6f6440d13cfc4750c1c15d0fcb850b63", size = 7593458, upload_time = "2023-11-17T21:18:06.141Z" }, + { url = "https://files.pythonhosted.org/packages/ce/25/a557ee10ac9dce1300850024707ce1850a6958f1673a9194be878b99d631/matplotlib-3.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9a5430836811b7652991939012f43d2808a2db9b64ee240387e8c43e2e5578c8", size = 7486840, upload_time = "2023-11-17T21:18:13.706Z" }, + { url = "https://files.pythonhosted.org/packages/e7/3d/72712b3895ee180f6e342638a8591c31912fbcc09ce9084cc256da16d0a0/matplotlib-3.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9576723858a78751d5aacd2497b8aef29ffea6d1c95981505877f7ac28215c6", size = 11387332, upload_time = "2023-11-17T21:18:23.699Z" }, + { url = "https://files.pythonhosted.org/packages/92/1a/cd3e0c90d1a763ad90073e13b189b4702f11becf4e71dbbad70a7a149811/matplotlib-3.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ba9cbd8ac6cf422f3102622b20f8552d601bf8837e49a3afed188d560152788", size = 11616911, upload_time = "2023-11-17T21:18:35.27Z" }, + { url = "https://files.pythonhosted.org/packages/78/4a/bad239071477305a3758eb4810615e310a113399cddd7682998be9f01e97/matplotlib-3.8.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:03f9d160a29e0b65c0790bb07f4f45d6a181b1ac33eb1bb0dd225986450148f0", size = 9549260, upload_time = "2023-11-17T21:18:44.836Z" }, + { url = "https://files.pythonhosted.org/packages/26/5a/27fd341e4510257789f19a4b4be8bb90d1113b8f176c3dab562b4f21466e/matplotlib-3.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:3773002da767f0a9323ba1a9b9b5d00d6257dbd2a93107233167cfb581f64717", size = 7645742, upload_time = "2023-11-17T21:18:53.448Z" }, + { url = "https://files.pythonhosted.org/packages/e4/1b/864d28d5a72d586ac137f4ca54d5afc8b869720e30d508dbd9adcce4d231/matplotlib-3.8.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:4c318c1e95e2f5926fba326f68177dee364aa791d6df022ceb91b8221bd0a627", size = 7590988, upload_time = "2023-11-17T21:19:01.119Z" }, + { url = "https://files.pythonhosted.org/packages/9a/b0/dd2b60f2dd90fbc21d1d3129c36a453c322d7995d5e3589f5b3c59ee528d/matplotlib-3.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:091275d18d942cf1ee9609c830a1bc36610607d8223b1b981c37d5c9fc3e46a4", size = 7483594, upload_time = "2023-11-17T21:19:09.865Z" }, + { url = "https://files.pythonhosted.org/packages/33/da/9942533ad9f96753bde0e5a5d48eacd6c21de8ea1ad16570e31bda8a017f/matplotlib-3.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b0f3b8ea0e99e233a4bcc44590f01604840d833c280ebb8fe5554fd3e6cfe8d", size = 11380843, upload_time = "2023-11-17T21:19:20.46Z" }, + { url = "https://files.pythonhosted.org/packages/fc/52/bfd36eb4745a3b21b3946c2c3a15679b620e14574fe2b98e9451b65ef578/matplotlib-3.8.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7b1704a530395aaf73912be741c04d181f82ca78084fbd80bc737be04848331", size = 11604608, upload_time = "2023-11-17T21:19:31.363Z" }, + { url = "https://files.pythonhosted.org/packages/6d/8c/0cdfbf604d4ea3dfa77435176c51e233cc408ad8f3efbf8d2c9f57cbdafb/matplotlib-3.8.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:533b0e3b0c6768eef8cbe4b583731ce25a91ab54a22f830db2b031e83cca9213", size = 9545252, upload_time = "2023-11-17T21:19:42.271Z" }, + { url = "https://files.pythonhosted.org/packages/2e/51/c77a14869b7eb9d6fb440e811b754fc3950d6868c38ace57d0632b674415/matplotlib-3.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:0f4fc5d72b75e2c18e55eb32292659cf731d9d5b312a6eb036506304f4675630", size = 7645067, upload_time = "2023-11-17T21:19:50.091Z" }, ] [[package]] name = "mdurl" version = "0.1.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload_time = "2022-08-14T12:40:10.846Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 }, + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload_time = "2022-08-14T12:40:09.779Z" }, ] [[package]] name = "mpmath" version = "1.3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e0/47/dd32fa426cc72114383ac549964eecb20ecfd886d1e5ccf5340b55b02f57/mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f", size = 508106 } +sdist = { url = "https://files.pythonhosted.org/packages/e0/47/dd32fa426cc72114383ac549964eecb20ecfd886d1e5ccf5340b55b02f57/mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f", size = 508106, upload_time = "2023-03-07T16:47:11.061Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c", size = 536198 }, + { url = "https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c", size = 536198, upload_time = "2023-03-07T16:47:09.197Z" }, ] [[package]] name = "msgpack" version = "1.0.7" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c2/d5/5662032db1571110b5b51647aed4b56dfbd01bfae789fa566a2be1f385d1/msgpack-1.0.7.tar.gz", hash = "sha256:572efc93db7a4d27e404501975ca6d2d9775705c2d922390d878fcf768d92c87", size = 166311 } +sdist = { url = "https://files.pythonhosted.org/packages/c2/d5/5662032db1571110b5b51647aed4b56dfbd01bfae789fa566a2be1f385d1/msgpack-1.0.7.tar.gz", hash = "sha256:572efc93db7a4d27e404501975ca6d2d9775705c2d922390d878fcf768d92c87", size = 166311, upload_time = "2023-09-28T13:20:36.726Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/41/3a/2e2e902afcd751738e38d88af976fc4010b16e8e821945f4cbf32f75f9c3/msgpack-1.0.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04ad6069c86e531682f9e1e71b71c1c3937d6014a7c3e9edd2aa81ad58842862", size = 304827 }, - { url = "https://files.pythonhosted.org/packages/86/a6/490792a524a82e855bdf3885ecb73d7b3a0b17744b3cf4a40aea13ceca38/msgpack-1.0.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cca1b62fe70d761a282496b96a5e51c44c213e410a964bdffe0928e611368329", size = 234959 }, - { url = "https://files.pythonhosted.org/packages/ad/72/d39ed43bfb2ec6968d768318477adb90c474bdc59b2437170c6697ee4115/msgpack-1.0.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e50ebce52f41370707f1e21a59514e3375e3edd6e1832f5e5235237db933c98b", size = 231970 }, - { url = "https://files.pythonhosted.org/packages/a2/90/2d769e693654f036acfb462b54dacb3ae345699999897ca34f6bd9534fe9/msgpack-1.0.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a7b4f35de6a304b5533c238bee86b670b75b03d31b7797929caa7a624b5dda6", size = 522440 }, - { url = "https://files.pythonhosted.org/packages/46/95/d0440400485eab1bf50f1efe5118967b539f3191d994c3dfc220657594cd/msgpack-1.0.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28efb066cde83c479dfe5a48141a53bc7e5f13f785b92ddde336c716663039ee", size = 530797 }, - { url = "https://files.pythonhosted.org/packages/76/33/35df717bc095c6e938b3c65ed117b95048abc24d1614427685123fb2f0af/msgpack-1.0.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4cb14ce54d9b857be9591ac364cb08dc2d6a5c4318c1182cb1d02274029d590d", size = 520372 }, - { url = "https://files.pythonhosted.org/packages/af/d1/abbdd58a43827fbec5d98427a7a535c620890289b9d927154465313d6967/msgpack-1.0.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b573a43ef7c368ba4ea06050a957c2a7550f729c31f11dd616d2ac4aba99888d", size = 527287 }, - { url = "https://files.pythonhosted.org/packages/0c/ac/66625b05091b97ca2c7418eb2d2af152f033d969519f9315556a4ed800fe/msgpack-1.0.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ccf9a39706b604d884d2cb1e27fe973bc55f2890c52f38df742bc1d79ab9f5e1", size = 560715 }, - { url = "https://files.pythonhosted.org/packages/de/4e/a0e8611f94bac32d2c1c4ad05bb1c0ae61132e3398e0b44a93e6d7830968/msgpack-1.0.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cb70766519500281815dfd7a87d3a178acf7ce95390544b8c90587d76b227681", size = 532614 }, - { url = "https://files.pythonhosted.org/packages/9b/07/0b3f089684ca330602b2994248eda2898a7232e4b63882b9271164ef672e/msgpack-1.0.7-cp310-cp310-win32.whl", hash = "sha256:b610ff0f24e9f11c9ae653c67ff8cc03c075131401b3e5ef4b82570d1728f8a9", size = 216340 }, - { url = "https://files.pythonhosted.org/packages/4b/14/c62fbc8dff118f1558e43b9469d56a1f37bbb35febadc3163efaedd01500/msgpack-1.0.7-cp310-cp310-win_amd64.whl", hash = "sha256:a40821a89dc373d6427e2b44b572efc36a2778d3f543299e2f24eb1a5de65415", size = 222828 }, - { url = "https://files.pythonhosted.org/packages/f9/b3/309de40dc7406b7f3492332c5ee2b492a593c2a9bb97ea48ebf2f5279999/msgpack-1.0.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:576eb384292b139821c41995523654ad82d1916da6a60cff129c715a6223ea84", size = 305096 }, - { url = "https://files.pythonhosted.org/packages/15/56/a677cd761a2cefb2e3ffe7e684633294dccb161d78e8ea6da9277e45b4a2/msgpack-1.0.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:730076207cb816138cf1af7f7237b208340a2c5e749707457d70705715c93b93", size = 235210 }, - { url = "https://files.pythonhosted.org/packages/f5/4e/1ab4a982cbd90f988e49f849fc1212f2c04a59870c59daabf8950617e2aa/msgpack-1.0.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:85765fdf4b27eb5086f05ac0491090fc76f4f2b28e09d9350c31aac25a5aaff8", size = 231952 }, - { url = "https://files.pythonhosted.org/packages/6d/74/bd02044eb628c7361ad2bd8c1a6147af5c6c2bbceb77b3b1da20f4a8a9c5/msgpack-1.0.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3476fae43db72bd11f29a5147ae2f3cb22e2f1a91d575ef130d2bf49afd21c46", size = 549511 }, - { url = "https://files.pythonhosted.org/packages/df/09/dee50913ba5cc047f7fd7162f09453a676e7935c84b3bf3a398e12108677/msgpack-1.0.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d4c80667de2e36970ebf74f42d1088cc9ee7ef5f4e8c35eee1b40eafd33ca5b", size = 557980 }, - { url = "https://files.pythonhosted.org/packages/26/a5/78a7d87f5f8ffe4c32167afa15d4957db649bab4822f909d8d765339bbab/msgpack-1.0.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b0bf0effb196ed76b7ad883848143427a73c355ae8e569fa538365064188b8e", size = 545547 }, - { url = "https://files.pythonhosted.org/packages/d4/53/698c10913947f97f6fe7faad86a34e6aa1b66cea2df6f99105856bd346d9/msgpack-1.0.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f9a7c509542db4eceed3dcf21ee5267ab565a83555c9b88a8109dcecc4709002", size = 554669 }, - { url = "https://files.pythonhosted.org/packages/f5/3f/9730c6cb574b15d349b80cd8523a7df4b82058528339f952ea1c32ac8a10/msgpack-1.0.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:84b0daf226913133f899ea9b30618722d45feffa67e4fe867b0b5ae83a34060c", size = 583353 }, - { url = "https://files.pythonhosted.org/packages/4c/bc/dc184d943692671149848438fb3bed3a3de288ce7998cb91bc98f40f201b/msgpack-1.0.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ec79ff6159dffcc30853b2ad612ed572af86c92b5168aa3fc01a67b0fa40665e", size = 557455 }, - { url = "https://files.pythonhosted.org/packages/cf/7b/1bc69d4a56c8d2f4f2dfbe4722d40344af9a85b6fb3b09cfb350ba6a42f6/msgpack-1.0.7-cp311-cp311-win32.whl", hash = "sha256:3e7bf4442b310ff154b7bb9d81eb2c016b7d597e364f97d72b1acc3817a0fdc1", size = 216367 }, - { url = "https://files.pythonhosted.org/packages/b4/3d/c8dd23050eefa3d9b9c5b8329ed3308c2f2f80f65825e9ea4b7fa621cdab/msgpack-1.0.7-cp311-cp311-win_amd64.whl", hash = "sha256:3f0c8c6dfa6605ab8ff0611995ee30d4f9fcff89966cf562733b4008a3d60d82", size = 222860 }, - { url = "https://files.pythonhosted.org/packages/d7/47/20dff6b4512cf3575550c8801bc53fe7d540f4efef9c5c37af51760fcdcf/msgpack-1.0.7-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f0936e08e0003f66bfd97e74ee530427707297b0d0361247e9b4f59ab78ddc8b", size = 305759 }, - { url = "https://files.pythonhosted.org/packages/6f/8a/34f1726d2c9feccec3d946776e9bce8f20ae09d8b91899fc20b296c942af/msgpack-1.0.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98bbd754a422a0b123c66a4c341de0474cad4a5c10c164ceed6ea090f3563db4", size = 235330 }, - { url = "https://files.pythonhosted.org/packages/9c/f6/e64c72577d6953789c3cb051b059a4b56317056b3c65013952338ed8a34e/msgpack-1.0.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b291f0ee7961a597cbbcc77709374087fa2a9afe7bdb6a40dbbd9b127e79afee", size = 232537 }, - { url = "https://files.pythonhosted.org/packages/89/75/1ed3a96e12941873fd957e016cc40c0c178861a872bd45e75b9a188eb422/msgpack-1.0.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebbbba226f0a108a7366bf4b59bf0f30a12fd5e75100c630267d94d7f0ad20e5", size = 546561 }, - { url = "https://files.pythonhosted.org/packages/e5/0a/c6a1390f9c6a31da0fecbbfdb86b1cb39ad302d9e24f9cca3d9e14c364f0/msgpack-1.0.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e2d69948e4132813b8d1131f29f9101bc2c915f26089a6d632001a5c1349672", size = 559009 }, - { url = "https://files.pythonhosted.org/packages/a5/74/99f6077754665613ea1f37b3d91c10129f6976b7721ab4d0973023808e5a/msgpack-1.0.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bdf38ba2d393c7911ae989c3bbba510ebbcdf4ecbdbfec36272abe350c454075", size = 543882 }, - { url = "https://files.pythonhosted.org/packages/9c/7e/dc0dc8de2bf27743b31691149258f9b1bd4bf3c44c105df3df9b97081cd1/msgpack-1.0.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:993584fc821c58d5993521bfdcd31a4adf025c7d745bbd4d12ccfecf695af5ba", size = 546949 }, - { url = "https://files.pythonhosted.org/packages/78/61/91bae9474def032f6c333d62889bbeda9e1554c6b123375ceeb1767efd78/msgpack-1.0.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:52700dc63a4676669b341ba33520f4d6e43d3ca58d422e22ba66d1736b0a6e4c", size = 579836 }, - { url = "https://files.pythonhosted.org/packages/5d/4d/d98592099d4f18945f89cf3e634dc0cb128bb33b1b93f85a84173d35e181/msgpack-1.0.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e45ae4927759289c30ccba8d9fdce62bb414977ba158286b5ddaf8df2cddb5c5", size = 556587 }, - { url = "https://files.pythonhosted.org/packages/5e/44/6556ffe169bf2c0e974e2ea25fb82a7e55ebcf52a81b03a5e01820de5f84/msgpack-1.0.7-cp312-cp312-win32.whl", hash = "sha256:27dcd6f46a21c18fa5e5deed92a43d4554e3df8d8ca5a47bf0615d6a5f39dbc9", size = 216509 }, - { url = "https://files.pythonhosted.org/packages/dc/c1/63903f30d51d165e132e5221a2a4a1bbfab7508b68131c871d70bffac78a/msgpack-1.0.7-cp312-cp312-win_amd64.whl", hash = "sha256:7687e22a31e976a0e7fc99c2f4d11ca45eff652a81eb8c8085e9609298916dcf", size = 223287 }, + { url = "https://files.pythonhosted.org/packages/41/3a/2e2e902afcd751738e38d88af976fc4010b16e8e821945f4cbf32f75f9c3/msgpack-1.0.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04ad6069c86e531682f9e1e71b71c1c3937d6014a7c3e9edd2aa81ad58842862", size = 304827, upload_time = "2023-09-28T13:18:30.258Z" }, + { url = "https://files.pythonhosted.org/packages/86/a6/490792a524a82e855bdf3885ecb73d7b3a0b17744b3cf4a40aea13ceca38/msgpack-1.0.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cca1b62fe70d761a282496b96a5e51c44c213e410a964bdffe0928e611368329", size = 234959, upload_time = "2023-09-28T13:18:32.146Z" }, + { url = "https://files.pythonhosted.org/packages/ad/72/d39ed43bfb2ec6968d768318477adb90c474bdc59b2437170c6697ee4115/msgpack-1.0.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e50ebce52f41370707f1e21a59514e3375e3edd6e1832f5e5235237db933c98b", size = 231970, upload_time = "2023-09-28T13:18:34.134Z" }, + { url = "https://files.pythonhosted.org/packages/a2/90/2d769e693654f036acfb462b54dacb3ae345699999897ca34f6bd9534fe9/msgpack-1.0.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a7b4f35de6a304b5533c238bee86b670b75b03d31b7797929caa7a624b5dda6", size = 522440, upload_time = "2023-09-28T13:18:35.866Z" }, + { url = "https://files.pythonhosted.org/packages/46/95/d0440400485eab1bf50f1efe5118967b539f3191d994c3dfc220657594cd/msgpack-1.0.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28efb066cde83c479dfe5a48141a53bc7e5f13f785b92ddde336c716663039ee", size = 530797, upload_time = "2023-09-28T13:18:37.653Z" }, + { url = "https://files.pythonhosted.org/packages/76/33/35df717bc095c6e938b3c65ed117b95048abc24d1614427685123fb2f0af/msgpack-1.0.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4cb14ce54d9b857be9591ac364cb08dc2d6a5c4318c1182cb1d02274029d590d", size = 520372, upload_time = "2023-09-28T13:18:39.685Z" }, + { url = "https://files.pythonhosted.org/packages/af/d1/abbdd58a43827fbec5d98427a7a535c620890289b9d927154465313d6967/msgpack-1.0.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b573a43ef7c368ba4ea06050a957c2a7550f729c31f11dd616d2ac4aba99888d", size = 527287, upload_time = "2023-09-28T13:18:41.051Z" }, + { url = "https://files.pythonhosted.org/packages/0c/ac/66625b05091b97ca2c7418eb2d2af152f033d969519f9315556a4ed800fe/msgpack-1.0.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ccf9a39706b604d884d2cb1e27fe973bc55f2890c52f38df742bc1d79ab9f5e1", size = 560715, upload_time = "2023-09-28T13:18:42.883Z" }, + { url = "https://files.pythonhosted.org/packages/de/4e/a0e8611f94bac32d2c1c4ad05bb1c0ae61132e3398e0b44a93e6d7830968/msgpack-1.0.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cb70766519500281815dfd7a87d3a178acf7ce95390544b8c90587d76b227681", size = 532614, upload_time = "2023-09-28T13:18:44.679Z" }, + { url = "https://files.pythonhosted.org/packages/9b/07/0b3f089684ca330602b2994248eda2898a7232e4b63882b9271164ef672e/msgpack-1.0.7-cp310-cp310-win32.whl", hash = "sha256:b610ff0f24e9f11c9ae653c67ff8cc03c075131401b3e5ef4b82570d1728f8a9", size = 216340, upload_time = "2023-09-28T13:18:46.588Z" }, + { url = "https://files.pythonhosted.org/packages/4b/14/c62fbc8dff118f1558e43b9469d56a1f37bbb35febadc3163efaedd01500/msgpack-1.0.7-cp310-cp310-win_amd64.whl", hash = "sha256:a40821a89dc373d6427e2b44b572efc36a2778d3f543299e2f24eb1a5de65415", size = 222828, upload_time = "2023-09-28T13:18:47.875Z" }, + { url = "https://files.pythonhosted.org/packages/f9/b3/309de40dc7406b7f3492332c5ee2b492a593c2a9bb97ea48ebf2f5279999/msgpack-1.0.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:576eb384292b139821c41995523654ad82d1916da6a60cff129c715a6223ea84", size = 305096, upload_time = "2023-09-28T13:18:49.678Z" }, + { url = "https://files.pythonhosted.org/packages/15/56/a677cd761a2cefb2e3ffe7e684633294dccb161d78e8ea6da9277e45b4a2/msgpack-1.0.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:730076207cb816138cf1af7f7237b208340a2c5e749707457d70705715c93b93", size = 235210, upload_time = "2023-09-28T13:18:51.039Z" }, + { url = "https://files.pythonhosted.org/packages/f5/4e/1ab4a982cbd90f988e49f849fc1212f2c04a59870c59daabf8950617e2aa/msgpack-1.0.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:85765fdf4b27eb5086f05ac0491090fc76f4f2b28e09d9350c31aac25a5aaff8", size = 231952, upload_time = "2023-09-28T13:18:52.871Z" }, + { url = "https://files.pythonhosted.org/packages/6d/74/bd02044eb628c7361ad2bd8c1a6147af5c6c2bbceb77b3b1da20f4a8a9c5/msgpack-1.0.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3476fae43db72bd11f29a5147ae2f3cb22e2f1a91d575ef130d2bf49afd21c46", size = 549511, upload_time = "2023-09-28T13:18:54.422Z" }, + { url = "https://files.pythonhosted.org/packages/df/09/dee50913ba5cc047f7fd7162f09453a676e7935c84b3bf3a398e12108677/msgpack-1.0.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d4c80667de2e36970ebf74f42d1088cc9ee7ef5f4e8c35eee1b40eafd33ca5b", size = 557980, upload_time = "2023-09-28T13:18:56.058Z" }, + { url = "https://files.pythonhosted.org/packages/26/a5/78a7d87f5f8ffe4c32167afa15d4957db649bab4822f909d8d765339bbab/msgpack-1.0.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b0bf0effb196ed76b7ad883848143427a73c355ae8e569fa538365064188b8e", size = 545547, upload_time = "2023-09-28T13:18:57.396Z" }, + { url = "https://files.pythonhosted.org/packages/d4/53/698c10913947f97f6fe7faad86a34e6aa1b66cea2df6f99105856bd346d9/msgpack-1.0.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f9a7c509542db4eceed3dcf21ee5267ab565a83555c9b88a8109dcecc4709002", size = 554669, upload_time = "2023-09-28T13:18:58.957Z" }, + { url = "https://files.pythonhosted.org/packages/f5/3f/9730c6cb574b15d349b80cd8523a7df4b82058528339f952ea1c32ac8a10/msgpack-1.0.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:84b0daf226913133f899ea9b30618722d45feffa67e4fe867b0b5ae83a34060c", size = 583353, upload_time = "2023-09-28T13:19:01.186Z" }, + { url = "https://files.pythonhosted.org/packages/4c/bc/dc184d943692671149848438fb3bed3a3de288ce7998cb91bc98f40f201b/msgpack-1.0.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ec79ff6159dffcc30853b2ad612ed572af86c92b5168aa3fc01a67b0fa40665e", size = 557455, upload_time = "2023-09-28T13:19:03.201Z" }, + { url = "https://files.pythonhosted.org/packages/cf/7b/1bc69d4a56c8d2f4f2dfbe4722d40344af9a85b6fb3b09cfb350ba6a42f6/msgpack-1.0.7-cp311-cp311-win32.whl", hash = "sha256:3e7bf4442b310ff154b7bb9d81eb2c016b7d597e364f97d72b1acc3817a0fdc1", size = 216367, upload_time = "2023-09-28T13:19:04.554Z" }, + { url = "https://files.pythonhosted.org/packages/b4/3d/c8dd23050eefa3d9b9c5b8329ed3308c2f2f80f65825e9ea4b7fa621cdab/msgpack-1.0.7-cp311-cp311-win_amd64.whl", hash = "sha256:3f0c8c6dfa6605ab8ff0611995ee30d4f9fcff89966cf562733b4008a3d60d82", size = 222860, upload_time = "2023-09-28T13:19:06.397Z" }, + { url = "https://files.pythonhosted.org/packages/d7/47/20dff6b4512cf3575550c8801bc53fe7d540f4efef9c5c37af51760fcdcf/msgpack-1.0.7-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f0936e08e0003f66bfd97e74ee530427707297b0d0361247e9b4f59ab78ddc8b", size = 305759, upload_time = "2023-09-28T13:19:08.148Z" }, + { url = "https://files.pythonhosted.org/packages/6f/8a/34f1726d2c9feccec3d946776e9bce8f20ae09d8b91899fc20b296c942af/msgpack-1.0.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98bbd754a422a0b123c66a4c341de0474cad4a5c10c164ceed6ea090f3563db4", size = 235330, upload_time = "2023-09-28T13:19:09.417Z" }, + { url = "https://files.pythonhosted.org/packages/9c/f6/e64c72577d6953789c3cb051b059a4b56317056b3c65013952338ed8a34e/msgpack-1.0.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b291f0ee7961a597cbbcc77709374087fa2a9afe7bdb6a40dbbd9b127e79afee", size = 232537, upload_time = "2023-09-28T13:19:10.898Z" }, + { url = "https://files.pythonhosted.org/packages/89/75/1ed3a96e12941873fd957e016cc40c0c178861a872bd45e75b9a188eb422/msgpack-1.0.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebbbba226f0a108a7366bf4b59bf0f30a12fd5e75100c630267d94d7f0ad20e5", size = 546561, upload_time = "2023-09-28T13:19:12.779Z" }, + { url = "https://files.pythonhosted.org/packages/e5/0a/c6a1390f9c6a31da0fecbbfdb86b1cb39ad302d9e24f9cca3d9e14c364f0/msgpack-1.0.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e2d69948e4132813b8d1131f29f9101bc2c915f26089a6d632001a5c1349672", size = 559009, upload_time = "2023-09-28T13:19:14.373Z" }, + { url = "https://files.pythonhosted.org/packages/a5/74/99f6077754665613ea1f37b3d91c10129f6976b7721ab4d0973023808e5a/msgpack-1.0.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bdf38ba2d393c7911ae989c3bbba510ebbcdf4ecbdbfec36272abe350c454075", size = 543882, upload_time = "2023-09-28T13:19:16.277Z" }, + { url = "https://files.pythonhosted.org/packages/9c/7e/dc0dc8de2bf27743b31691149258f9b1bd4bf3c44c105df3df9b97081cd1/msgpack-1.0.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:993584fc821c58d5993521bfdcd31a4adf025c7d745bbd4d12ccfecf695af5ba", size = 546949, upload_time = "2023-09-28T13:19:18.114Z" }, + { url = "https://files.pythonhosted.org/packages/78/61/91bae9474def032f6c333d62889bbeda9e1554c6b123375ceeb1767efd78/msgpack-1.0.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:52700dc63a4676669b341ba33520f4d6e43d3ca58d422e22ba66d1736b0a6e4c", size = 579836, upload_time = "2023-09-28T13:19:19.729Z" }, + { url = "https://files.pythonhosted.org/packages/5d/4d/d98592099d4f18945f89cf3e634dc0cb128bb33b1b93f85a84173d35e181/msgpack-1.0.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e45ae4927759289c30ccba8d9fdce62bb414977ba158286b5ddaf8df2cddb5c5", size = 556587, upload_time = "2023-09-28T13:19:21.666Z" }, + { url = "https://files.pythonhosted.org/packages/5e/44/6556ffe169bf2c0e974e2ea25fb82a7e55ebcf52a81b03a5e01820de5f84/msgpack-1.0.7-cp312-cp312-win32.whl", hash = "sha256:27dcd6f46a21c18fa5e5deed92a43d4554e3df8d8ca5a47bf0615d6a5f39dbc9", size = 216509, upload_time = "2023-09-28T13:19:23.161Z" }, + { url = "https://files.pythonhosted.org/packages/dc/c1/63903f30d51d165e132e5221a2a4a1bbfab7508b68131c871d70bffac78a/msgpack-1.0.7-cp312-cp312-win_amd64.whl", hash = "sha256:7687e22a31e976a0e7fc99c2f4d11ca45eff652a81eb8c8085e9609298916dcf", size = 223287, upload_time = "2023-09-28T13:19:25.097Z" }, ] [[package]] @@ -1379,83 +1405,83 @@ dependencies = [ { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ce/43/d5e49a86afa64bd3839ea0d5b9c7103487007d728e1293f52525d6d5486a/mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43", size = 3239717 } +sdist = { url = "https://files.pythonhosted.org/packages/ce/43/d5e49a86afa64bd3839ea0d5b9c7103487007d728e1293f52525d6d5486a/mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43", size = 3239717, upload_time = "2025-02-05T03:50:34.655Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/68/f8/65a7ce8d0e09b6329ad0c8d40330d100ea343bd4dd04c4f8ae26462d0a17/mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13", size = 10738433 }, - { url = "https://files.pythonhosted.org/packages/b4/95/9c0ecb8eacfe048583706249439ff52105b3f552ea9c4024166c03224270/mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559", size = 9861472 }, - { url = "https://files.pythonhosted.org/packages/84/09/9ec95e982e282e20c0d5407bc65031dfd0f0f8ecc66b69538296e06fcbee/mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b", size = 11611424 }, - { url = "https://files.pythonhosted.org/packages/78/13/f7d14e55865036a1e6a0a69580c240f43bc1f37407fe9235c0d4ef25ffb0/mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3", size = 12365450 }, - { url = "https://files.pythonhosted.org/packages/48/e1/301a73852d40c241e915ac6d7bcd7fedd47d519246db2d7b86b9d7e7a0cb/mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b", size = 12551765 }, - { url = "https://files.pythonhosted.org/packages/77/ba/c37bc323ae5fe7f3f15a28e06ab012cd0b7552886118943e90b15af31195/mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828", size = 9274701 }, - { url = "https://files.pythonhosted.org/packages/03/bc/f6339726c627bd7ca1ce0fa56c9ae2d0144604a319e0e339bdadafbbb599/mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f", size = 10662338 }, - { url = "https://files.pythonhosted.org/packages/e2/90/8dcf506ca1a09b0d17555cc00cd69aee402c203911410136cd716559efe7/mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5", size = 9787540 }, - { url = "https://files.pythonhosted.org/packages/05/05/a10f9479681e5da09ef2f9426f650d7b550d4bafbef683b69aad1ba87457/mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e", size = 11538051 }, - { url = "https://files.pythonhosted.org/packages/e9/9a/1f7d18b30edd57441a6411fcbc0c6869448d1a4bacbaee60656ac0fc29c8/mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c", size = 12286751 }, - { url = "https://files.pythonhosted.org/packages/72/af/19ff499b6f1dafcaf56f9881f7a965ac2f474f69f6f618b5175b044299f5/mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f", size = 12421783 }, - { url = "https://files.pythonhosted.org/packages/96/39/11b57431a1f686c1aed54bf794870efe0f6aeca11aca281a0bd87a5ad42c/mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f", size = 9265618 }, - { url = "https://files.pythonhosted.org/packages/98/3a/03c74331c5eb8bd025734e04c9840532226775c47a2c39b56a0c8d4f128d/mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd", size = 10793981 }, - { url = "https://files.pythonhosted.org/packages/f0/1a/41759b18f2cfd568848a37c89030aeb03534411eef981df621d8fad08a1d/mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f", size = 9749175 }, - { url = "https://files.pythonhosted.org/packages/12/7e/873481abf1ef112c582db832740f4c11b2bfa510e829d6da29b0ab8c3f9c/mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464", size = 11455675 }, - { url = "https://files.pythonhosted.org/packages/b3/d0/92ae4cde706923a2d3f2d6c39629134063ff64b9dedca9c1388363da072d/mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee", size = 12410020 }, - { url = "https://files.pythonhosted.org/packages/46/8b/df49974b337cce35f828ba6fda228152d6db45fed4c86ba56ffe442434fd/mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e", size = 12498582 }, - { url = "https://files.pythonhosted.org/packages/13/50/da5203fcf6c53044a0b699939f31075c45ae8a4cadf538a9069b165c1050/mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22", size = 9366614 }, - { url = "https://files.pythonhosted.org/packages/6a/9b/fd2e05d6ffff24d912f150b87db9e364fa8282045c875654ce7e32fffa66/mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445", size = 10788592 }, - { url = "https://files.pythonhosted.org/packages/74/37/b246d711c28a03ead1fd906bbc7106659aed7c089d55fe40dd58db812628/mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d", size = 9753611 }, - { url = "https://files.pythonhosted.org/packages/a6/ac/395808a92e10cfdac8003c3de9a2ab6dc7cde6c0d2a4df3df1b815ffd067/mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5", size = 11438443 }, - { url = "https://files.pythonhosted.org/packages/d2/8b/801aa06445d2de3895f59e476f38f3f8d610ef5d6908245f07d002676cbf/mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036", size = 12402541 }, - { url = "https://files.pythonhosted.org/packages/c7/67/5a4268782eb77344cc613a4cf23540928e41f018a9a1ec4c6882baf20ab8/mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357", size = 12494348 }, - { url = "https://files.pythonhosted.org/packages/83/3e/57bb447f7bbbfaabf1712d96f9df142624a386d98fb026a761532526057e/mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf", size = 9373648 }, - { url = "https://files.pythonhosted.org/packages/09/4e/a7d65c7322c510de2c409ff3828b03354a7c43f5a8ed458a7a131b41c7b9/mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e", size = 2221777 }, + { url = "https://files.pythonhosted.org/packages/68/f8/65a7ce8d0e09b6329ad0c8d40330d100ea343bd4dd04c4f8ae26462d0a17/mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13", size = 10738433, upload_time = "2025-02-05T03:49:29.145Z" }, + { url = "https://files.pythonhosted.org/packages/b4/95/9c0ecb8eacfe048583706249439ff52105b3f552ea9c4024166c03224270/mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559", size = 9861472, upload_time = "2025-02-05T03:49:16.986Z" }, + { url = "https://files.pythonhosted.org/packages/84/09/9ec95e982e282e20c0d5407bc65031dfd0f0f8ecc66b69538296e06fcbee/mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b", size = 11611424, upload_time = "2025-02-05T03:49:46.908Z" }, + { url = "https://files.pythonhosted.org/packages/78/13/f7d14e55865036a1e6a0a69580c240f43bc1f37407fe9235c0d4ef25ffb0/mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3", size = 12365450, upload_time = "2025-02-05T03:50:05.89Z" }, + { url = "https://files.pythonhosted.org/packages/48/e1/301a73852d40c241e915ac6d7bcd7fedd47d519246db2d7b86b9d7e7a0cb/mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b", size = 12551765, upload_time = "2025-02-05T03:49:33.56Z" }, + { url = "https://files.pythonhosted.org/packages/77/ba/c37bc323ae5fe7f3f15a28e06ab012cd0b7552886118943e90b15af31195/mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828", size = 9274701, upload_time = "2025-02-05T03:49:38.981Z" }, + { url = "https://files.pythonhosted.org/packages/03/bc/f6339726c627bd7ca1ce0fa56c9ae2d0144604a319e0e339bdadafbbb599/mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f", size = 10662338, upload_time = "2025-02-05T03:50:17.287Z" }, + { url = "https://files.pythonhosted.org/packages/e2/90/8dcf506ca1a09b0d17555cc00cd69aee402c203911410136cd716559efe7/mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5", size = 9787540, upload_time = "2025-02-05T03:49:51.21Z" }, + { url = "https://files.pythonhosted.org/packages/05/05/a10f9479681e5da09ef2f9426f650d7b550d4bafbef683b69aad1ba87457/mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e", size = 11538051, upload_time = "2025-02-05T03:50:20.885Z" }, + { url = "https://files.pythonhosted.org/packages/e9/9a/1f7d18b30edd57441a6411fcbc0c6869448d1a4bacbaee60656ac0fc29c8/mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c", size = 12286751, upload_time = "2025-02-05T03:49:42.408Z" }, + { url = "https://files.pythonhosted.org/packages/72/af/19ff499b6f1dafcaf56f9881f7a965ac2f474f69f6f618b5175b044299f5/mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f", size = 12421783, upload_time = "2025-02-05T03:49:07.707Z" }, + { url = "https://files.pythonhosted.org/packages/96/39/11b57431a1f686c1aed54bf794870efe0f6aeca11aca281a0bd87a5ad42c/mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f", size = 9265618, upload_time = "2025-02-05T03:49:54.581Z" }, + { url = "https://files.pythonhosted.org/packages/98/3a/03c74331c5eb8bd025734e04c9840532226775c47a2c39b56a0c8d4f128d/mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd", size = 10793981, upload_time = "2025-02-05T03:50:28.25Z" }, + { url = "https://files.pythonhosted.org/packages/f0/1a/41759b18f2cfd568848a37c89030aeb03534411eef981df621d8fad08a1d/mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f", size = 9749175, upload_time = "2025-02-05T03:50:13.411Z" }, + { url = "https://files.pythonhosted.org/packages/12/7e/873481abf1ef112c582db832740f4c11b2bfa510e829d6da29b0ab8c3f9c/mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464", size = 11455675, upload_time = "2025-02-05T03:50:31.421Z" }, + { url = "https://files.pythonhosted.org/packages/b3/d0/92ae4cde706923a2d3f2d6c39629134063ff64b9dedca9c1388363da072d/mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee", size = 12410020, upload_time = "2025-02-05T03:48:48.705Z" }, + { url = "https://files.pythonhosted.org/packages/46/8b/df49974b337cce35f828ba6fda228152d6db45fed4c86ba56ffe442434fd/mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e", size = 12498582, upload_time = "2025-02-05T03:49:03.628Z" }, + { url = "https://files.pythonhosted.org/packages/13/50/da5203fcf6c53044a0b699939f31075c45ae8a4cadf538a9069b165c1050/mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22", size = 9366614, upload_time = "2025-02-05T03:50:00.313Z" }, + { url = "https://files.pythonhosted.org/packages/6a/9b/fd2e05d6ffff24d912f150b87db9e364fa8282045c875654ce7e32fffa66/mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445", size = 10788592, upload_time = "2025-02-05T03:48:55.789Z" }, + { url = "https://files.pythonhosted.org/packages/74/37/b246d711c28a03ead1fd906bbc7106659aed7c089d55fe40dd58db812628/mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d", size = 9753611, upload_time = "2025-02-05T03:48:44.581Z" }, + { url = "https://files.pythonhosted.org/packages/a6/ac/395808a92e10cfdac8003c3de9a2ab6dc7cde6c0d2a4df3df1b815ffd067/mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5", size = 11438443, upload_time = "2025-02-05T03:49:25.514Z" }, + { url = "https://files.pythonhosted.org/packages/d2/8b/801aa06445d2de3895f59e476f38f3f8d610ef5d6908245f07d002676cbf/mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036", size = 12402541, upload_time = "2025-02-05T03:49:57.623Z" }, + { url = "https://files.pythonhosted.org/packages/c7/67/5a4268782eb77344cc613a4cf23540928e41f018a9a1ec4c6882baf20ab8/mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357", size = 12494348, upload_time = "2025-02-05T03:48:52.361Z" }, + { url = "https://files.pythonhosted.org/packages/83/3e/57bb447f7bbbfaabf1712d96f9df142624a386d98fb026a761532526057e/mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf", size = 9373648, upload_time = "2025-02-05T03:49:11.395Z" }, + { url = "https://files.pythonhosted.org/packages/09/4e/a7d65c7322c510de2c409ff3828b03354a7c43f5a8ed458a7a131b41c7b9/mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e", size = 2221777, upload_time = "2025-02-05T03:50:08.348Z" }, ] [[package]] name = "mypy-extensions" version = "1.0.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/98/a4/1ab47638b92648243faf97a5aeb6ea83059cc3624972ab6b8d2316078d3f/mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782", size = 4433 } +sdist = { url = "https://files.pythonhosted.org/packages/98/a4/1ab47638b92648243faf97a5aeb6ea83059cc3624972ab6b8d2316078d3f/mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782", size = 4433, upload_time = "2023-02-04T12:11:27.157Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695 }, + { url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695, upload_time = "2023-02-04T12:11:25.002Z" }, ] [[package]] name = "networkx" version = "3.2.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c4/80/a84676339aaae2f1cfdf9f418701dd634aef9cc76f708ef55c36ff39c3ca/networkx-3.2.1.tar.gz", hash = "sha256:9f1bb5cf3409bf324e0a722c20bdb4c20ee39bf1c30ce8ae499c8502b0b5e0c6", size = 2073928 } +sdist = { url = "https://files.pythonhosted.org/packages/c4/80/a84676339aaae2f1cfdf9f418701dd634aef9cc76f708ef55c36ff39c3ca/networkx-3.2.1.tar.gz", hash = "sha256:9f1bb5cf3409bf324e0a722c20bdb4c20ee39bf1c30ce8ae499c8502b0b5e0c6", size = 2073928, upload_time = "2023-10-28T08:41:39.364Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d5/f0/8fbc882ca80cf077f1b246c0e3c3465f7f415439bdea6b899f6b19f61f70/networkx-3.2.1-py3-none-any.whl", hash = "sha256:f18c69adc97877c42332c170849c96cefa91881c99a7cb3e95b7c659ebdc1ec2", size = 1647772 }, + { url = "https://files.pythonhosted.org/packages/d5/f0/8fbc882ca80cf077f1b246c0e3c3465f7f415439bdea6b899f6b19f61f70/networkx-3.2.1-py3-none-any.whl", hash = "sha256:f18c69adc97877c42332c170849c96cefa91881c99a7cb3e95b7c659ebdc1ec2", size = 1647772, upload_time = "2023-10-28T08:41:36.945Z" }, ] [[package]] name = "numpy" version = "1.26.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/65/6e/09db70a523a96d25e115e71cc56a6f9031e7b8cd166c1ac8438307c14058/numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010", size = 15786129 } +sdist = { url = "https://files.pythonhosted.org/packages/65/6e/09db70a523a96d25e115e71cc56a6f9031e7b8cd166c1ac8438307c14058/numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010", size = 15786129, upload_time = "2024-02-06T00:26:44.495Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/94/ace0fdea5241a27d13543ee117cbc65868e82213fb31a8eb7fe9ff23f313/numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0", size = 20631468 }, - { url = "https://files.pythonhosted.org/packages/20/f7/b24208eba89f9d1b58c1668bc6c8c4fd472b20c45573cb767f59d49fb0f6/numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a", size = 13966411 }, - { url = "https://files.pythonhosted.org/packages/fc/a5/4beee6488160798683eed5bdb7eead455892c3b4e1f78d79d8d3f3b084ac/numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4", size = 14219016 }, - { url = "https://files.pythonhosted.org/packages/4b/d7/ecf66c1cd12dc28b4040b15ab4d17b773b87fa9d29ca16125de01adb36cd/numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f", size = 18240889 }, - { url = "https://files.pythonhosted.org/packages/24/03/6f229fe3187546435c4f6f89f6d26c129d4f5bed40552899fcf1f0bf9e50/numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a", size = 13876746 }, - { url = "https://files.pythonhosted.org/packages/39/fe/39ada9b094f01f5a35486577c848fe274e374bbf8d8f472e1423a0bbd26d/numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2", size = 18078620 }, - { url = "https://files.pythonhosted.org/packages/d5/ef/6ad11d51197aad206a9ad2286dc1aac6a378059e06e8cf22cd08ed4f20dc/numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07", size = 5972659 }, - { url = "https://files.pythonhosted.org/packages/19/77/538f202862b9183f54108557bfda67e17603fc560c384559e769321c9d92/numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5", size = 15808905 }, - { url = "https://files.pythonhosted.org/packages/11/57/baae43d14fe163fa0e4c47f307b6b2511ab8d7d30177c491960504252053/numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71", size = 20630554 }, - { url = "https://files.pythonhosted.org/packages/1a/2e/151484f49fd03944c4a3ad9c418ed193cfd02724e138ac8a9505d056c582/numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef", size = 13997127 }, - { url = "https://files.pythonhosted.org/packages/79/ae/7e5b85136806f9dadf4878bf73cf223fe5c2636818ba3ab1c585d0403164/numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e", size = 14222994 }, - { url = "https://files.pythonhosted.org/packages/3a/d0/edc009c27b406c4f9cbc79274d6e46d634d139075492ad055e3d68445925/numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5", size = 18252005 }, - { url = "https://files.pythonhosted.org/packages/09/bf/2b1aaf8f525f2923ff6cfcf134ae5e750e279ac65ebf386c75a0cf6da06a/numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a", size = 13885297 }, - { url = "https://files.pythonhosted.org/packages/df/a0/4e0f14d847cfc2a633a1c8621d00724f3206cfeddeb66d35698c4e2cf3d2/numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a", size = 18093567 }, - { url = "https://files.pythonhosted.org/packages/d2/b7/a734c733286e10a7f1a8ad1ae8c90f2d33bf604a96548e0a4a3a6739b468/numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20", size = 5968812 }, - { url = "https://files.pythonhosted.org/packages/3f/6b/5610004206cf7f8e7ad91c5a85a8c71b2f2f8051a0c0c4d5916b76d6cbb2/numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2", size = 15811913 }, - { url = "https://files.pythonhosted.org/packages/95/12/8f2020a8e8b8383ac0177dc9570aad031a3beb12e38847f7129bacd96228/numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218", size = 20335901 }, - { url = "https://files.pythonhosted.org/packages/75/5b/ca6c8bd14007e5ca171c7c03102d17b4f4e0ceb53957e8c44343a9546dcc/numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b", size = 13685868 }, - { url = "https://files.pythonhosted.org/packages/79/f8/97f10e6755e2a7d027ca783f63044d5b1bc1ae7acb12afe6a9b4286eac17/numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b", size = 13925109 }, - { url = "https://files.pythonhosted.org/packages/0f/50/de23fde84e45f5c4fda2488c759b69990fd4512387a8632860f3ac9cd225/numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed", size = 17950613 }, - { url = "https://files.pythonhosted.org/packages/4c/0c/9c603826b6465e82591e05ca230dfc13376da512b25ccd0894709b054ed0/numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a", size = 13572172 }, - { url = "https://files.pythonhosted.org/packages/76/8c/2ba3902e1a0fc1c74962ea9bb33a534bb05984ad7ff9515bf8d07527cadd/numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0", size = 17786643 }, - { url = "https://files.pythonhosted.org/packages/28/4a/46d9e65106879492374999e76eb85f87b15328e06bd1550668f79f7b18c6/numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110", size = 5677803 }, - { url = "https://files.pythonhosted.org/packages/16/2e/86f24451c2d530c88daf997cb8d6ac622c1d40d19f5a031ed68a4b73a374/numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818", size = 15517754 }, + { url = "https://files.pythonhosted.org/packages/a7/94/ace0fdea5241a27d13543ee117cbc65868e82213fb31a8eb7fe9ff23f313/numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0", size = 20631468, upload_time = "2024-02-05T23:48:01.194Z" }, + { url = "https://files.pythonhosted.org/packages/20/f7/b24208eba89f9d1b58c1668bc6c8c4fd472b20c45573cb767f59d49fb0f6/numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a", size = 13966411, upload_time = "2024-02-05T23:48:29.038Z" }, + { url = "https://files.pythonhosted.org/packages/fc/a5/4beee6488160798683eed5bdb7eead455892c3b4e1f78d79d8d3f3b084ac/numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4", size = 14219016, upload_time = "2024-02-05T23:48:54.098Z" }, + { url = "https://files.pythonhosted.org/packages/4b/d7/ecf66c1cd12dc28b4040b15ab4d17b773b87fa9d29ca16125de01adb36cd/numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f", size = 18240889, upload_time = "2024-02-05T23:49:25.361Z" }, + { url = "https://files.pythonhosted.org/packages/24/03/6f229fe3187546435c4f6f89f6d26c129d4f5bed40552899fcf1f0bf9e50/numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a", size = 13876746, upload_time = "2024-02-05T23:49:51.983Z" }, + { url = "https://files.pythonhosted.org/packages/39/fe/39ada9b094f01f5a35486577c848fe274e374bbf8d8f472e1423a0bbd26d/numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2", size = 18078620, upload_time = "2024-02-05T23:50:22.515Z" }, + { url = "https://files.pythonhosted.org/packages/d5/ef/6ad11d51197aad206a9ad2286dc1aac6a378059e06e8cf22cd08ed4f20dc/numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07", size = 5972659, upload_time = "2024-02-05T23:50:35.834Z" }, + { url = "https://files.pythonhosted.org/packages/19/77/538f202862b9183f54108557bfda67e17603fc560c384559e769321c9d92/numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5", size = 15808905, upload_time = "2024-02-05T23:51:03.701Z" }, + { url = "https://files.pythonhosted.org/packages/11/57/baae43d14fe163fa0e4c47f307b6b2511ab8d7d30177c491960504252053/numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71", size = 20630554, upload_time = "2024-02-05T23:51:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/1a/2e/151484f49fd03944c4a3ad9c418ed193cfd02724e138ac8a9505d056c582/numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef", size = 13997127, upload_time = "2024-02-05T23:52:15.314Z" }, + { url = "https://files.pythonhosted.org/packages/79/ae/7e5b85136806f9dadf4878bf73cf223fe5c2636818ba3ab1c585d0403164/numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e", size = 14222994, upload_time = "2024-02-05T23:52:47.569Z" }, + { url = "https://files.pythonhosted.org/packages/3a/d0/edc009c27b406c4f9cbc79274d6e46d634d139075492ad055e3d68445925/numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5", size = 18252005, upload_time = "2024-02-05T23:53:15.637Z" }, + { url = "https://files.pythonhosted.org/packages/09/bf/2b1aaf8f525f2923ff6cfcf134ae5e750e279ac65ebf386c75a0cf6da06a/numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a", size = 13885297, upload_time = "2024-02-05T23:53:42.16Z" }, + { url = "https://files.pythonhosted.org/packages/df/a0/4e0f14d847cfc2a633a1c8621d00724f3206cfeddeb66d35698c4e2cf3d2/numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a", size = 18093567, upload_time = "2024-02-05T23:54:11.696Z" }, + { url = "https://files.pythonhosted.org/packages/d2/b7/a734c733286e10a7f1a8ad1ae8c90f2d33bf604a96548e0a4a3a6739b468/numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20", size = 5968812, upload_time = "2024-02-05T23:54:26.453Z" }, + { url = "https://files.pythonhosted.org/packages/3f/6b/5610004206cf7f8e7ad91c5a85a8c71b2f2f8051a0c0c4d5916b76d6cbb2/numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2", size = 15811913, upload_time = "2024-02-05T23:54:53.933Z" }, + { url = "https://files.pythonhosted.org/packages/95/12/8f2020a8e8b8383ac0177dc9570aad031a3beb12e38847f7129bacd96228/numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218", size = 20335901, upload_time = "2024-02-05T23:55:32.801Z" }, + { url = "https://files.pythonhosted.org/packages/75/5b/ca6c8bd14007e5ca171c7c03102d17b4f4e0ceb53957e8c44343a9546dcc/numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b", size = 13685868, upload_time = "2024-02-05T23:55:56.28Z" }, + { url = "https://files.pythonhosted.org/packages/79/f8/97f10e6755e2a7d027ca783f63044d5b1bc1ae7acb12afe6a9b4286eac17/numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b", size = 13925109, upload_time = "2024-02-05T23:56:20.368Z" }, + { url = "https://files.pythonhosted.org/packages/0f/50/de23fde84e45f5c4fda2488c759b69990fd4512387a8632860f3ac9cd225/numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed", size = 17950613, upload_time = "2024-02-05T23:56:56.054Z" }, + { url = "https://files.pythonhosted.org/packages/4c/0c/9c603826b6465e82591e05ca230dfc13376da512b25ccd0894709b054ed0/numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a", size = 13572172, upload_time = "2024-02-05T23:57:21.56Z" }, + { url = "https://files.pythonhosted.org/packages/76/8c/2ba3902e1a0fc1c74962ea9bb33a534bb05984ad7ff9515bf8d07527cadd/numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0", size = 17786643, upload_time = "2024-02-05T23:57:56.585Z" }, + { url = "https://files.pythonhosted.org/packages/28/4a/46d9e65106879492374999e76eb85f87b15328e06bd1550668f79f7b18c6/numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110", size = 5677803, upload_time = "2024-02-05T23:58:08.963Z" }, + { url = "https://files.pythonhosted.org/packages/16/2e/86f24451c2d530c88daf997cb8d6ac622c1d40d19f5a031ed68a4b73a374/numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818", size = 15517754, upload_time = "2024-02-05T23:58:36.364Z" }, ] [[package]] @@ -1466,26 +1492,26 @@ dependencies = [ { name = "numpy" }, { name = "protobuf" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b3/fe/0978403c8d710ece2f34006367e78de80410743fe0e7680c8f33f2dab20d/onnx-1.16.0.tar.gz", hash = "sha256:237c6987c6c59d9f44b6136f5819af79574f8d96a760a1fa843bede11f3822f7", size = 12303017 } +sdist = { url = "https://files.pythonhosted.org/packages/b3/fe/0978403c8d710ece2f34006367e78de80410743fe0e7680c8f33f2dab20d/onnx-1.16.0.tar.gz", hash = "sha256:237c6987c6c59d9f44b6136f5819af79574f8d96a760a1fa843bede11f3822f7", size = 12303017, upload_time = "2024-03-25T15:33:46.091Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c8/0b/f4705e4a3fa6fd0de971302fdae17ad176b024eca8c24360f0e37c00f9df/onnx-1.16.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:9eadbdce25b19d6216f426d6d99b8bc877a65ed92cbef9707751c6669190ba4f", size = 16514483 }, - { url = "https://files.pythonhosted.org/packages/b8/1c/50310a559857951fc6e069cf5d89deebe34287997d1c5928bca435456f62/onnx-1.16.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:034ae21a2aaa2e9c14119a840d2926d213c27aad29e5e3edaa30145a745048e1", size = 15012939 }, - { url = "https://files.pythonhosted.org/packages/ef/6e/96be6692ebcd8da568084d753f386ce08efa1f99b216f346ee281edd6cc3/onnx-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec22a43d74eb1f2303373e2fbe7fbcaa45fb225f4eb146edfed1356ada7a9aea", size = 15791856 }, - { url = "https://files.pythonhosted.org/packages/49/5f/d8e1a24247f506a77cbe22341c72ca91bea3b468c5d6bca2047d885ea3c6/onnx-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:298f28a2b5ac09145fa958513d3d1e6b349ccf86a877dbdcccad57713fe360b3", size = 15922279 }, - { url = "https://files.pythonhosted.org/packages/cb/14/562e4ac22cdf41f4465e3b114ef1a9467d513eeff0b9c2285c2da5db6ed1/onnx-1.16.0-cp310-cp310-win32.whl", hash = "sha256:66300197b52beca08bc6262d43c103289c5d45fde43fb51922ed1eb83658cf0c", size = 14335703 }, - { url = "https://files.pythonhosted.org/packages/3b/e2/471ff83b3862967791d67f630000afce038756afbdf0665a3d767677c851/onnx-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:ae0029f5e47bf70a1a62e7f88c80bca4ef39b844a89910039184221775df5e43", size = 14435099 }, - { url = "https://files.pythonhosted.org/packages/a4/b8/7accf3f93eee498711f0b7f07f6e93906e031622473e85ce9cd3578f6a92/onnx-1.16.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:f51179d4af3372b4f3800c558d204b592c61e4b4a18b8f61e0eea7f46211221a", size = 16514376 }, - { url = "https://files.pythonhosted.org/packages/cc/24/a328236b594d5fea23f70a3a8139e730cb43334f0b24693831c47c9064f0/onnx-1.16.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:5202559070afec5144332db216c20f2fff8323cf7f6512b0ca11b215eacc5bf3", size = 15012839 }, - { url = "https://files.pythonhosted.org/packages/80/12/57187bab3f830a47fa65eafe4fbaef01dfdf5042cf82a41fa440fab68766/onnx-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77579e7c15b4df39d29465b216639a5f9b74026bdd9e4b6306cd19a32dcfe67c", size = 15791944 }, - { url = "https://files.pythonhosted.org/packages/df/48/63f68b65d041aedffab41eea930563ca52aab70dbaa7d4820501618c1a70/onnx-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e60ca76ac24b65c25860d0f2d2cdd96d6320d062a01dd8ce87c5743603789b8", size = 15922450 }, - { url = "https://files.pythonhosted.org/packages/08/1b/4bdf4534f5ff08973725ba5409f95bbf64e2789cd20be615880dae689973/onnx-1.16.0-cp311-cp311-win32.whl", hash = "sha256:81b4ee01bc554e8a2b11ac6439882508a5377a1c6b452acd69a1eebb83571117", size = 14335808 }, - { url = "https://files.pythonhosted.org/packages/aa/d0/0514d02d2e84e7bb48a105877eae4065e54d7dabb60d0b60214fe2677346/onnx-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:7449241e70b847b9c3eb8dae622df8c1b456d11032a9d7e26e0ee8a698d5bf86", size = 14434905 }, - { url = "https://files.pythonhosted.org/packages/42/87/577adadda30ee08041e81ef02a331ca9d1a8df93a2e4c4c53ec56fbbc2ac/onnx-1.16.0-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:03a627488b1a9975d95d6a55582af3e14c7f3bb87444725b999935ddd271d352", size = 16516304 }, - { url = "https://files.pythonhosted.org/packages/e3/1b/6e1ea37e081cc49a28f0e4d3830b4c8525081354cf9f5529c6c92268fc77/onnx-1.16.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:c392faeabd9283ee344ccb4b067d1fea9dfc614fa1f0de7c47589efd79e15e78", size = 15016538 }, - { url = "https://files.pythonhosted.org/packages/6d/07/f8fefd5eb0984be42ef677f0b7db7527edc4529224a34a3c31f7b12ec80d/onnx-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0efeb46985de08f0efe758cb54ad3457e821a05c2eaf5ba2ccb8cd1602c08084", size = 15790415 }, - { url = "https://files.pythonhosted.org/packages/11/71/c219ce6d4b5205c77405af7f2de2511ad4eeffbfeb77a422151e893de0ea/onnx-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddf14a3d32234f23e44abb73a755cb96a423fac7f004e8f046f36b10214151ee", size = 15922224 }, - { url = "https://files.pythonhosted.org/packages/8e/a4/554a6e5741b42406c5b1970d04685d7f2012019d4178408ed4b3ec953033/onnx-1.16.0-cp312-cp312-win32.whl", hash = "sha256:62a2e27ae8ba5fc9b4a2620301446a517b5ffaaf8566611de7a7c2160f5bcf4c", size = 14336234 }, - { url = "https://files.pythonhosted.org/packages/e9/a1/8aecec497010ad34e7656408df1868d94483c5c56bc991f4088c06150896/onnx-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:3e0860fea94efde777e81a6f68f65761ed5e5f3adea2e050d7fbe373a9ae05b3", size = 14436591 }, + { url = "https://files.pythonhosted.org/packages/c8/0b/f4705e4a3fa6fd0de971302fdae17ad176b024eca8c24360f0e37c00f9df/onnx-1.16.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:9eadbdce25b19d6216f426d6d99b8bc877a65ed92cbef9707751c6669190ba4f", size = 16514483, upload_time = "2024-03-25T15:25:07.947Z" }, + { url = "https://files.pythonhosted.org/packages/b8/1c/50310a559857951fc6e069cf5d89deebe34287997d1c5928bca435456f62/onnx-1.16.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:034ae21a2aaa2e9c14119a840d2926d213c27aad29e5e3edaa30145a745048e1", size = 15012939, upload_time = "2024-03-25T15:25:11.632Z" }, + { url = "https://files.pythonhosted.org/packages/ef/6e/96be6692ebcd8da568084d753f386ce08efa1f99b216f346ee281edd6cc3/onnx-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec22a43d74eb1f2303373e2fbe7fbcaa45fb225f4eb146edfed1356ada7a9aea", size = 15791856, upload_time = "2024-03-25T15:25:15.36Z" }, + { url = "https://files.pythonhosted.org/packages/49/5f/d8e1a24247f506a77cbe22341c72ca91bea3b468c5d6bca2047d885ea3c6/onnx-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:298f28a2b5ac09145fa958513d3d1e6b349ccf86a877dbdcccad57713fe360b3", size = 15922279, upload_time = "2024-03-25T15:25:18.939Z" }, + { url = "https://files.pythonhosted.org/packages/cb/14/562e4ac22cdf41f4465e3b114ef1a9467d513eeff0b9c2285c2da5db6ed1/onnx-1.16.0-cp310-cp310-win32.whl", hash = "sha256:66300197b52beca08bc6262d43c103289c5d45fde43fb51922ed1eb83658cf0c", size = 14335703, upload_time = "2024-03-25T15:25:22.611Z" }, + { url = "https://files.pythonhosted.org/packages/3b/e2/471ff83b3862967791d67f630000afce038756afbdf0665a3d767677c851/onnx-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:ae0029f5e47bf70a1a62e7f88c80bca4ef39b844a89910039184221775df5e43", size = 14435099, upload_time = "2024-03-25T15:25:25.05Z" }, + { url = "https://files.pythonhosted.org/packages/a4/b8/7accf3f93eee498711f0b7f07f6e93906e031622473e85ce9cd3578f6a92/onnx-1.16.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:f51179d4af3372b4f3800c558d204b592c61e4b4a18b8f61e0eea7f46211221a", size = 16514376, upload_time = "2024-03-25T15:25:27.899Z" }, + { url = "https://files.pythonhosted.org/packages/cc/24/a328236b594d5fea23f70a3a8139e730cb43334f0b24693831c47c9064f0/onnx-1.16.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:5202559070afec5144332db216c20f2fff8323cf7f6512b0ca11b215eacc5bf3", size = 15012839, upload_time = "2024-03-25T15:25:31.16Z" }, + { url = "https://files.pythonhosted.org/packages/80/12/57187bab3f830a47fa65eafe4fbaef01dfdf5042cf82a41fa440fab68766/onnx-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77579e7c15b4df39d29465b216639a5f9b74026bdd9e4b6306cd19a32dcfe67c", size = 15791944, upload_time = "2024-03-25T15:25:34.778Z" }, + { url = "https://files.pythonhosted.org/packages/df/48/63f68b65d041aedffab41eea930563ca52aab70dbaa7d4820501618c1a70/onnx-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e60ca76ac24b65c25860d0f2d2cdd96d6320d062a01dd8ce87c5743603789b8", size = 15922450, upload_time = "2024-03-25T15:25:37.983Z" }, + { url = "https://files.pythonhosted.org/packages/08/1b/4bdf4534f5ff08973725ba5409f95bbf64e2789cd20be615880dae689973/onnx-1.16.0-cp311-cp311-win32.whl", hash = "sha256:81b4ee01bc554e8a2b11ac6439882508a5377a1c6b452acd69a1eebb83571117", size = 14335808, upload_time = "2024-03-25T15:25:40.523Z" }, + { url = "https://files.pythonhosted.org/packages/aa/d0/0514d02d2e84e7bb48a105877eae4065e54d7dabb60d0b60214fe2677346/onnx-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:7449241e70b847b9c3eb8dae622df8c1b456d11032a9d7e26e0ee8a698d5bf86", size = 14434905, upload_time = "2024-03-25T15:25:42.905Z" }, + { url = "https://files.pythonhosted.org/packages/42/87/577adadda30ee08041e81ef02a331ca9d1a8df93a2e4c4c53ec56fbbc2ac/onnx-1.16.0-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:03a627488b1a9975d95d6a55582af3e14c7f3bb87444725b999935ddd271d352", size = 16516304, upload_time = "2024-03-25T15:25:45.875Z" }, + { url = "https://files.pythonhosted.org/packages/e3/1b/6e1ea37e081cc49a28f0e4d3830b4c8525081354cf9f5529c6c92268fc77/onnx-1.16.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:c392faeabd9283ee344ccb4b067d1fea9dfc614fa1f0de7c47589efd79e15e78", size = 15016538, upload_time = "2024-03-25T15:25:49.396Z" }, + { url = "https://files.pythonhosted.org/packages/6d/07/f8fefd5eb0984be42ef677f0b7db7527edc4529224a34a3c31f7b12ec80d/onnx-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0efeb46985de08f0efe758cb54ad3457e821a05c2eaf5ba2ccb8cd1602c08084", size = 15790415, upload_time = "2024-03-25T15:25:51.929Z" }, + { url = "https://files.pythonhosted.org/packages/11/71/c219ce6d4b5205c77405af7f2de2511ad4eeffbfeb77a422151e893de0ea/onnx-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddf14a3d32234f23e44abb73a755cb96a423fac7f004e8f046f36b10214151ee", size = 15922224, upload_time = "2024-03-25T15:25:55.049Z" }, + { url = "https://files.pythonhosted.org/packages/8e/a4/554a6e5741b42406c5b1970d04685d7f2012019d4178408ed4b3ec953033/onnx-1.16.0-cp312-cp312-win32.whl", hash = "sha256:62a2e27ae8ba5fc9b4a2620301446a517b5ffaaf8566611de7a7c2160f5bcf4c", size = 14336234, upload_time = "2024-03-25T15:25:57.998Z" }, + { url = "https://files.pythonhosted.org/packages/e9/a1/8aecec497010ad34e7656408df1868d94483c5c56bc991f4088c06150896/onnx-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:3e0860fea94efde777e81a6f68f65761ed5e5f3adea2e050d7fbe373a9ae05b3", size = 14436591, upload_time = "2024-03-25T15:26:01.252Z" }, ] [[package]] @@ -1501,27 +1527,27 @@ dependencies = [ { name = "sympy" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/4e/28/99f903b0eb1cd6f3faa0e343217d9fb9f47b84bca98bd9859884631336ee/onnxruntime-1.20.1-cp310-cp310-macosx_13_0_universal2.whl", hash = "sha256:e50ba5ff7fed4f7d9253a6baf801ca2883cc08491f9d32d78a80da57256a5439", size = 30996314 }, - { url = "https://files.pythonhosted.org/packages/6d/c6/c4c0860bee2fde6037bdd9dcd12d323f6e38cf00fcc9a5065b394337fc55/onnxruntime-1.20.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7b2908b50101a19e99c4d4e97ebb9905561daf61829403061c1adc1b588bc0de", size = 11954010 }, - { url = "https://files.pythonhosted.org/packages/63/47/3dc0b075ab539f16b3d8b09df6b504f51836086ee709690a6278d791737d/onnxruntime-1.20.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d82daaec24045a2e87598b8ac2b417b1cce623244e80e663882e9fe1aae86410", size = 13330452 }, - { url = "https://files.pythonhosted.org/packages/27/ef/80fab86289ecc01a734b7ddf115dfb93d8b2e004bd1e1977e12881c72b12/onnxruntime-1.20.1-cp310-cp310-win32.whl", hash = "sha256:4c4b251a725a3b8cf2aab284f7d940c26094ecd9d442f07dd81ab5470e99b83f", size = 9813849 }, - { url = "https://files.pythonhosted.org/packages/a9/e6/33ab10066c9875a29d55e66ae97c3bf91b9b9b987179455d67c32261a49c/onnxruntime-1.20.1-cp310-cp310-win_amd64.whl", hash = "sha256:d3b616bb53a77a9463707bb313637223380fc327f5064c9a782e8ec69c22e6a2", size = 11329702 }, - { url = "https://files.pythonhosted.org/packages/95/8d/2634e2959b34aa8a0037989f4229e9abcfa484e9c228f99633b3241768a6/onnxruntime-1.20.1-cp311-cp311-macosx_13_0_universal2.whl", hash = "sha256:06bfbf02ca9ab5f28946e0f912a562a5f005301d0c419283dc57b3ed7969bb7b", size = 30998725 }, - { url = "https://files.pythonhosted.org/packages/a5/da/c44bf9bd66cd6d9018a921f053f28d819445c4d84b4dd4777271b0fe52a2/onnxruntime-1.20.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f6243e34d74423bdd1edf0ae9596dd61023b260f546ee17d701723915f06a9f7", size = 11955227 }, - { url = "https://files.pythonhosted.org/packages/11/ac/4120dfb74c8e45cce1c664fc7f7ce010edd587ba67ac41489f7432eb9381/onnxruntime-1.20.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5eec64c0269dcdb8d9a9a53dc4d64f87b9e0c19801d9321246a53b7eb5a7d1bc", size = 13331703 }, - { url = "https://files.pythonhosted.org/packages/12/f1/cefacac137f7bb7bfba57c50c478150fcd3c54aca72762ac2c05ce0532c1/onnxruntime-1.20.1-cp311-cp311-win32.whl", hash = "sha256:a19bc6e8c70e2485a1725b3d517a2319603acc14c1f1a017dda0afe6d4665b41", size = 9813977 }, - { url = "https://files.pythonhosted.org/packages/2c/2d/2d4d202c0bcfb3a4cc2b171abb9328672d7f91d7af9ea52572722c6d8d96/onnxruntime-1.20.1-cp311-cp311-win_amd64.whl", hash = "sha256:8508887eb1c5f9537a4071768723ec7c30c28eb2518a00d0adcd32c89dea3221", size = 11329895 }, - { url = "https://files.pythonhosted.org/packages/e5/39/9335e0874f68f7d27103cbffc0e235e32e26759202df6085716375c078bb/onnxruntime-1.20.1-cp312-cp312-macosx_13_0_universal2.whl", hash = "sha256:22b0655e2bf4f2161d52706e31f517a0e54939dc393e92577df51808a7edc8c9", size = 31007580 }, - { url = "https://files.pythonhosted.org/packages/c5/9d/a42a84e10f1744dd27c6f2f9280cc3fb98f869dd19b7cd042e391ee2ab61/onnxruntime-1.20.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f1f56e898815963d6dc4ee1c35fc6c36506466eff6d16f3cb9848cea4e8c8172", size = 11952833 }, - { url = "https://files.pythonhosted.org/packages/47/42/2f71f5680834688a9c81becbe5c5bb996fd33eaed5c66ae0606c3b1d6a02/onnxruntime-1.20.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bb71a814f66517a65628c9e4a2bb530a6edd2cd5d87ffa0af0f6f773a027d99e", size = 13333903 }, - { url = "https://files.pythonhosted.org/packages/c8/f1/aabfdf91d013320aa2fc46cf43c88ca0182860ff15df872b4552254a9680/onnxruntime-1.20.1-cp312-cp312-win32.whl", hash = "sha256:bd386cc9ee5f686ee8a75ba74037750aca55183085bf1941da8efcfe12d5b120", size = 9814562 }, - { url = "https://files.pythonhosted.org/packages/dd/80/76979e0b744307d488c79e41051117634b956612cc731f1028eb17ee7294/onnxruntime-1.20.1-cp312-cp312-win_amd64.whl", hash = "sha256:19c2d843eb074f385e8bbb753a40df780511061a63f9def1b216bf53860223fb", size = 11331482 }, - { url = "https://files.pythonhosted.org/packages/f7/71/c5d980ac4189589267a06f758bd6c5667d07e55656bed6c6c0580733ad07/onnxruntime-1.20.1-cp313-cp313-macosx_13_0_universal2.whl", hash = "sha256:cc01437a32d0042b606f462245c8bbae269e5442797f6213e36ce61d5abdd8cc", size = 31007574 }, - { url = "https://files.pythonhosted.org/packages/81/0d/13bbd9489be2a6944f4a940084bfe388f1100472f38c07080a46fbd4ab96/onnxruntime-1.20.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb44b08e017a648924dbe91b82d89b0c105b1adcfe31e90d1dc06b8677ad37be", size = 11951459 }, - { url = "https://files.pythonhosted.org/packages/c0/ea/4454ae122874fd52bbb8a961262de81c5f932edeb1b72217f594c700d6ef/onnxruntime-1.20.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bda6aebdf7917c1d811f21d41633df00c58aff2bef2f598f69289c1f1dabc4b3", size = 13331620 }, - { url = "https://files.pythonhosted.org/packages/d8/e0/50db43188ca1c945decaa8fc2a024c33446d31afed40149897d4f9de505f/onnxruntime-1.20.1-cp313-cp313-win_amd64.whl", hash = "sha256:d30367df7e70f1d9fc5a6a68106f5961686d39b54d3221f760085524e8d38e16", size = 11331758 }, - { url = "https://files.pythonhosted.org/packages/d8/55/3821c5fd60b52a6c82a00bba18531793c93c4addfe64fbf061e235c5617a/onnxruntime-1.20.1-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c9158465745423b2b5d97ed25aa7740c7d38d2993ee2e5c3bfacb0c4145c49d8", size = 11950342 }, - { url = "https://files.pythonhosted.org/packages/14/56/fd990ca222cef4f9f4a9400567b9a15b220dee2eafffb16b2adbc55c8281/onnxruntime-1.20.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0df6f2df83d61f46e842dbcde610ede27218947c33e994545a22333491e72a3b", size = 13337040 }, + { url = "https://files.pythonhosted.org/packages/4e/28/99f903b0eb1cd6f3faa0e343217d9fb9f47b84bca98bd9859884631336ee/onnxruntime-1.20.1-cp310-cp310-macosx_13_0_universal2.whl", hash = "sha256:e50ba5ff7fed4f7d9253a6baf801ca2883cc08491f9d32d78a80da57256a5439", size = 30996314, upload_time = "2024-11-21T00:48:31.43Z" }, + { url = "https://files.pythonhosted.org/packages/6d/c6/c4c0860bee2fde6037bdd9dcd12d323f6e38cf00fcc9a5065b394337fc55/onnxruntime-1.20.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7b2908b50101a19e99c4d4e97ebb9905561daf61829403061c1adc1b588bc0de", size = 11954010, upload_time = "2024-11-21T00:48:35.254Z" }, + { url = "https://files.pythonhosted.org/packages/63/47/3dc0b075ab539f16b3d8b09df6b504f51836086ee709690a6278d791737d/onnxruntime-1.20.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d82daaec24045a2e87598b8ac2b417b1cce623244e80e663882e9fe1aae86410", size = 13330452, upload_time = "2024-11-21T00:48:40.02Z" }, + { url = "https://files.pythonhosted.org/packages/27/ef/80fab86289ecc01a734b7ddf115dfb93d8b2e004bd1e1977e12881c72b12/onnxruntime-1.20.1-cp310-cp310-win32.whl", hash = "sha256:4c4b251a725a3b8cf2aab284f7d940c26094ecd9d442f07dd81ab5470e99b83f", size = 9813849, upload_time = "2024-11-21T00:48:43.569Z" }, + { url = "https://files.pythonhosted.org/packages/a9/e6/33ab10066c9875a29d55e66ae97c3bf91b9b9b987179455d67c32261a49c/onnxruntime-1.20.1-cp310-cp310-win_amd64.whl", hash = "sha256:d3b616bb53a77a9463707bb313637223380fc327f5064c9a782e8ec69c22e6a2", size = 11329702, upload_time = "2024-11-21T00:48:46.599Z" }, + { url = "https://files.pythonhosted.org/packages/95/8d/2634e2959b34aa8a0037989f4229e9abcfa484e9c228f99633b3241768a6/onnxruntime-1.20.1-cp311-cp311-macosx_13_0_universal2.whl", hash = "sha256:06bfbf02ca9ab5f28946e0f912a562a5f005301d0c419283dc57b3ed7969bb7b", size = 30998725, upload_time = "2024-11-21T00:48:51.013Z" }, + { url = "https://files.pythonhosted.org/packages/a5/da/c44bf9bd66cd6d9018a921f053f28d819445c4d84b4dd4777271b0fe52a2/onnxruntime-1.20.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f6243e34d74423bdd1edf0ae9596dd61023b260f546ee17d701723915f06a9f7", size = 11955227, upload_time = "2024-11-21T00:48:54.556Z" }, + { url = "https://files.pythonhosted.org/packages/11/ac/4120dfb74c8e45cce1c664fc7f7ce010edd587ba67ac41489f7432eb9381/onnxruntime-1.20.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5eec64c0269dcdb8d9a9a53dc4d64f87b9e0c19801d9321246a53b7eb5a7d1bc", size = 13331703, upload_time = "2024-11-21T00:48:57.97Z" }, + { url = "https://files.pythonhosted.org/packages/12/f1/cefacac137f7bb7bfba57c50c478150fcd3c54aca72762ac2c05ce0532c1/onnxruntime-1.20.1-cp311-cp311-win32.whl", hash = "sha256:a19bc6e8c70e2485a1725b3d517a2319603acc14c1f1a017dda0afe6d4665b41", size = 9813977, upload_time = "2024-11-21T00:49:00.519Z" }, + { url = "https://files.pythonhosted.org/packages/2c/2d/2d4d202c0bcfb3a4cc2b171abb9328672d7f91d7af9ea52572722c6d8d96/onnxruntime-1.20.1-cp311-cp311-win_amd64.whl", hash = "sha256:8508887eb1c5f9537a4071768723ec7c30c28eb2518a00d0adcd32c89dea3221", size = 11329895, upload_time = "2024-11-21T00:49:03.845Z" }, + { url = "https://files.pythonhosted.org/packages/e5/39/9335e0874f68f7d27103cbffc0e235e32e26759202df6085716375c078bb/onnxruntime-1.20.1-cp312-cp312-macosx_13_0_universal2.whl", hash = "sha256:22b0655e2bf4f2161d52706e31f517a0e54939dc393e92577df51808a7edc8c9", size = 31007580, upload_time = "2024-11-21T00:49:07.029Z" }, + { url = "https://files.pythonhosted.org/packages/c5/9d/a42a84e10f1744dd27c6f2f9280cc3fb98f869dd19b7cd042e391ee2ab61/onnxruntime-1.20.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f1f56e898815963d6dc4ee1c35fc6c36506466eff6d16f3cb9848cea4e8c8172", size = 11952833, upload_time = "2024-11-21T00:49:10.563Z" }, + { url = "https://files.pythonhosted.org/packages/47/42/2f71f5680834688a9c81becbe5c5bb996fd33eaed5c66ae0606c3b1d6a02/onnxruntime-1.20.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bb71a814f66517a65628c9e4a2bb530a6edd2cd5d87ffa0af0f6f773a027d99e", size = 13333903, upload_time = "2024-11-21T00:49:12.984Z" }, + { url = "https://files.pythonhosted.org/packages/c8/f1/aabfdf91d013320aa2fc46cf43c88ca0182860ff15df872b4552254a9680/onnxruntime-1.20.1-cp312-cp312-win32.whl", hash = "sha256:bd386cc9ee5f686ee8a75ba74037750aca55183085bf1941da8efcfe12d5b120", size = 9814562, upload_time = "2024-11-21T00:49:15.453Z" }, + { url = "https://files.pythonhosted.org/packages/dd/80/76979e0b744307d488c79e41051117634b956612cc731f1028eb17ee7294/onnxruntime-1.20.1-cp312-cp312-win_amd64.whl", hash = "sha256:19c2d843eb074f385e8bbb753a40df780511061a63f9def1b216bf53860223fb", size = 11331482, upload_time = "2024-11-21T00:49:19.412Z" }, + { url = "https://files.pythonhosted.org/packages/f7/71/c5d980ac4189589267a06f758bd6c5667d07e55656bed6c6c0580733ad07/onnxruntime-1.20.1-cp313-cp313-macosx_13_0_universal2.whl", hash = "sha256:cc01437a32d0042b606f462245c8bbae269e5442797f6213e36ce61d5abdd8cc", size = 31007574, upload_time = "2024-11-21T00:49:23.225Z" }, + { url = "https://files.pythonhosted.org/packages/81/0d/13bbd9489be2a6944f4a940084bfe388f1100472f38c07080a46fbd4ab96/onnxruntime-1.20.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb44b08e017a648924dbe91b82d89b0c105b1adcfe31e90d1dc06b8677ad37be", size = 11951459, upload_time = "2024-11-21T00:49:26.269Z" }, + { url = "https://files.pythonhosted.org/packages/c0/ea/4454ae122874fd52bbb8a961262de81c5f932edeb1b72217f594c700d6ef/onnxruntime-1.20.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bda6aebdf7917c1d811f21d41633df00c58aff2bef2f598f69289c1f1dabc4b3", size = 13331620, upload_time = "2024-11-21T00:49:28.875Z" }, + { url = "https://files.pythonhosted.org/packages/d8/e0/50db43188ca1c945decaa8fc2a024c33446d31afed40149897d4f9de505f/onnxruntime-1.20.1-cp313-cp313-win_amd64.whl", hash = "sha256:d30367df7e70f1d9fc5a6a68106f5961686d39b54d3221f760085524e8d38e16", size = 11331758, upload_time = "2024-11-21T00:49:31.417Z" }, + { url = "https://files.pythonhosted.org/packages/d8/55/3821c5fd60b52a6c82a00bba18531793c93c4addfe64fbf061e235c5617a/onnxruntime-1.20.1-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c9158465745423b2b5d97ed25aa7740c7d38d2993ee2e5c3bfacb0c4145c49d8", size = 11950342, upload_time = "2024-11-21T00:49:34.164Z" }, + { url = "https://files.pythonhosted.org/packages/14/56/fd990ca222cef4f9f4a9400567b9a15b220dee2eafffb16b2adbc55c8281/onnxruntime-1.20.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0df6f2df83d61f46e842dbcde610ede27218947c33e994545a22333491e72a3b", size = 13337040, upload_time = "2024-11-21T00:49:37.271Z" }, ] [[package]] @@ -1558,10 +1584,10 @@ dependencies = [ { name = "sympy" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/57/e9a080f2477b2a4c16925f766e4615fc545098b0f4e20cf8ad803e7a9672/onnxruntime_openvino-1.18.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:565b874d21bcd48126da7d62f57db019f5ec0e1f82ae9b0740afa2ad91f8d331", size = 41971800 }, - { url = "https://files.pythonhosted.org/packages/34/7d/b75913bce58f4ee9bf6a02d1b513b9fc82303a496ec698e6fb1f9d597cb4/onnxruntime_openvino-1.18.0-cp310-cp310-win_amd64.whl", hash = "sha256:7f1931060f710a6c8e32121bb73044c4772ef5925802fc8776d3fe1e87ab3f75", size = 5963263 }, - { url = "https://files.pythonhosted.org/packages/7e/d3/8299b7285dc8fa7bd986b6f0d7c50b7f0fd13db50dd3b88b93ec269b1e08/onnxruntime_openvino-1.18.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:eb1723d386f70a8e26398d983ebe35d2c25ba56e9cdb382670ebbf1f5139f8ba", size = 41971927 }, - { url = "https://files.pythonhosted.org/packages/88/d9/ca0bfd7ed37153d9664ccdcfb4d0e5b1963563553b05cb4338b46968feb2/onnxruntime_openvino-1.18.0-cp311-cp311-win_amd64.whl", hash = "sha256:874a1e263dd86674593e5a879257650b06a8609c4d5768c3d8ed8dc4ae874b9c", size = 5963464 }, + { url = "https://files.pythonhosted.org/packages/b3/57/e9a080f2477b2a4c16925f766e4615fc545098b0f4e20cf8ad803e7a9672/onnxruntime_openvino-1.18.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:565b874d21bcd48126da7d62f57db019f5ec0e1f82ae9b0740afa2ad91f8d331", size = 41971800, upload_time = "2024-06-25T06:30:37.042Z" }, + { url = "https://files.pythonhosted.org/packages/34/7d/b75913bce58f4ee9bf6a02d1b513b9fc82303a496ec698e6fb1f9d597cb4/onnxruntime_openvino-1.18.0-cp310-cp310-win_amd64.whl", hash = "sha256:7f1931060f710a6c8e32121bb73044c4772ef5925802fc8776d3fe1e87ab3f75", size = 5963263, upload_time = "2024-06-24T13:38:15.906Z" }, + { url = "https://files.pythonhosted.org/packages/7e/d3/8299b7285dc8fa7bd986b6f0d7c50b7f0fd13db50dd3b88b93ec269b1e08/onnxruntime_openvino-1.18.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:eb1723d386f70a8e26398d983ebe35d2c25ba56e9cdb382670ebbf1f5139f8ba", size = 41971927, upload_time = "2024-06-25T06:30:43.765Z" }, + { url = "https://files.pythonhosted.org/packages/88/d9/ca0bfd7ed37153d9664ccdcfb4d0e5b1963563553b05cb4338b46968feb2/onnxruntime_openvino-1.18.0-cp311-cp311-win_amd64.whl", hash = "sha256:874a1e263dd86674593e5a879257650b06a8609c4d5768c3d8ed8dc4ae874b9c", size = 5963464, upload_time = "2024-06-24T13:38:18.437Z" }, ] [[package]] @@ -1571,171 +1597,171 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/36/2f/5b2b3ba52c864848885ba988f24b7f105052f68da9ab0e693cc7c25b0b30/opencv-python-headless-4.11.0.86.tar.gz", hash = "sha256:996eb282ca4b43ec6a3972414de0e2331f5d9cda2b41091a49739c19fb843798", size = 95177929 } +sdist = { url = "https://files.pythonhosted.org/packages/36/2f/5b2b3ba52c864848885ba988f24b7f105052f68da9ab0e693cc7c25b0b30/opencv-python-headless-4.11.0.86.tar.gz", hash = "sha256:996eb282ca4b43ec6a3972414de0e2331f5d9cda2b41091a49739c19fb843798", size = 95177929, upload_time = "2025-01-16T13:53:40.22Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/dc/53/2c50afa0b1e05ecdb4603818e85f7d174e683d874ef63a6abe3ac92220c8/opencv_python_headless-4.11.0.86-cp37-abi3-macosx_13_0_arm64.whl", hash = "sha256:48128188ade4a7e517237c8e1e11a9cdf5c282761473383e77beb875bb1e61ca", size = 37326460 }, - { url = "https://files.pythonhosted.org/packages/3b/43/68555327df94bb9b59a1fd645f63fafb0762515344d2046698762fc19d58/opencv_python_headless-4.11.0.86-cp37-abi3-macosx_13_0_x86_64.whl", hash = "sha256:a66c1b286a9de872c343ee7c3553b084244299714ebb50fbdcd76f07ebbe6c81", size = 56723330 }, - { url = "https://files.pythonhosted.org/packages/45/be/1438ce43ebe65317344a87e4b150865c5585f4c0db880a34cdae5ac46881/opencv_python_headless-4.11.0.86-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6efabcaa9df731f29e5ea9051776715b1bdd1845d7c9530065c7951d2a2899eb", size = 29487060 }, - { url = "https://files.pythonhosted.org/packages/dd/5c/c139a7876099916879609372bfa513b7f1257f7f1a908b0bdc1c2328241b/opencv_python_headless-4.11.0.86-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e0a27c19dd1f40ddff94976cfe43066fbbe9dfbb2ec1907d66c19caef42a57b", size = 49969856 }, - { url = "https://files.pythonhosted.org/packages/95/dd/ed1191c9dc91abcc9f752b499b7928aacabf10567bb2c2535944d848af18/opencv_python_headless-4.11.0.86-cp37-abi3-win32.whl", hash = "sha256:f447d8acbb0b6f2808da71fddd29c1cdd448d2bc98f72d9bb78a7a898fc9621b", size = 29324425 }, - { url = "https://files.pythonhosted.org/packages/86/8a/69176a64335aed183529207ba8bc3d329c2999d852b4f3818027203f50e6/opencv_python_headless-4.11.0.86-cp37-abi3-win_amd64.whl", hash = "sha256:6c304df9caa7a6a5710b91709dd4786bf20a74d57672b3c31f7033cc638174ca", size = 39402386 }, + { url = "https://files.pythonhosted.org/packages/dc/53/2c50afa0b1e05ecdb4603818e85f7d174e683d874ef63a6abe3ac92220c8/opencv_python_headless-4.11.0.86-cp37-abi3-macosx_13_0_arm64.whl", hash = "sha256:48128188ade4a7e517237c8e1e11a9cdf5c282761473383e77beb875bb1e61ca", size = 37326460, upload_time = "2025-01-16T13:52:57.015Z" }, + { url = "https://files.pythonhosted.org/packages/3b/43/68555327df94bb9b59a1fd645f63fafb0762515344d2046698762fc19d58/opencv_python_headless-4.11.0.86-cp37-abi3-macosx_13_0_x86_64.whl", hash = "sha256:a66c1b286a9de872c343ee7c3553b084244299714ebb50fbdcd76f07ebbe6c81", size = 56723330, upload_time = "2025-01-16T13:55:45.731Z" }, + { url = "https://files.pythonhosted.org/packages/45/be/1438ce43ebe65317344a87e4b150865c5585f4c0db880a34cdae5ac46881/opencv_python_headless-4.11.0.86-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6efabcaa9df731f29e5ea9051776715b1bdd1845d7c9530065c7951d2a2899eb", size = 29487060, upload_time = "2025-01-16T13:51:59.625Z" }, + { url = "https://files.pythonhosted.org/packages/dd/5c/c139a7876099916879609372bfa513b7f1257f7f1a908b0bdc1c2328241b/opencv_python_headless-4.11.0.86-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e0a27c19dd1f40ddff94976cfe43066fbbe9dfbb2ec1907d66c19caef42a57b", size = 49969856, upload_time = "2025-01-16T13:53:29.654Z" }, + { url = "https://files.pythonhosted.org/packages/95/dd/ed1191c9dc91abcc9f752b499b7928aacabf10567bb2c2535944d848af18/opencv_python_headless-4.11.0.86-cp37-abi3-win32.whl", hash = "sha256:f447d8acbb0b6f2808da71fddd29c1cdd448d2bc98f72d9bb78a7a898fc9621b", size = 29324425, upload_time = "2025-01-16T13:52:49.048Z" }, + { url = "https://files.pythonhosted.org/packages/86/8a/69176a64335aed183529207ba8bc3d329c2999d852b4f3818027203f50e6/opencv_python_headless-4.11.0.86-cp37-abi3-win_amd64.whl", hash = "sha256:6c304df9caa7a6a5710b91709dd4786bf20a74d57672b3c31f7033cc638174ca", size = 39402386, upload_time = "2025-01-16T13:52:56.418Z" }, ] [[package]] name = "orjson" version = "3.10.16" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/98/c7/03913cc4332174071950acf5b0735463e3f63760c80585ef369270c2b372/orjson-3.10.16.tar.gz", hash = "sha256:d2aaa5c495e11d17b9b93205f5fa196737ee3202f000aaebf028dc9a73750f10", size = 5410415 } +sdist = { url = "https://files.pythonhosted.org/packages/98/c7/03913cc4332174071950acf5b0735463e3f63760c80585ef369270c2b372/orjson-3.10.16.tar.gz", hash = "sha256:d2aaa5c495e11d17b9b93205f5fa196737ee3202f000aaebf028dc9a73750f10", size = 5410415, upload_time = "2025-03-24T17:00:23.312Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9d/a6/22cb9b03baf167bc2d659c9e74d7580147f36e6a155e633801badfd5a74d/orjson-3.10.16-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:4cb473b8e79154fa778fb56d2d73763d977be3dcc140587e07dbc545bbfc38f8", size = 249179 }, - { url = "https://files.pythonhosted.org/packages/d7/ce/3e68cc33020a6ebd8f359b8628b69d2132cd84fea68155c33057e502ee51/orjson-3.10.16-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:622a8e85eeec1948690409a19ca1c7d9fd8ff116f4861d261e6ae2094fe59a00", size = 138510 }, - { url = "https://files.pythonhosted.org/packages/dc/12/63bee7764ce12052f7c1a1393ce7f26dc392c93081eb8754dd3dce9b7c6b/orjson-3.10.16-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c682d852d0ce77613993dc967e90e151899fe2d8e71c20e9be164080f468e370", size = 132373 }, - { url = "https://files.pythonhosted.org/packages/b3/d5/2998c2f319adcd572f2b03ba2083e8176863d1055d8d713683ddcf927b71/orjson-3.10.16-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c520ae736acd2e32df193bcff73491e64c936f3e44a2916b548da048a48b46b", size = 136774 }, - { url = "https://files.pythonhosted.org/packages/00/03/88c236ae307bd0604623204d4a835e15fbf9c75b8535c8f13ef45abd413f/orjson-3.10.16-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:134f87c76bfae00f2094d85cfab261b289b76d78c6da8a7a3b3c09d362fd1e06", size = 138030 }, - { url = "https://files.pythonhosted.org/packages/66/ba/3e256ddfeb364f98fd6ac65774844090d356158b2d1de8998db2bf984503/orjson-3.10.16-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b59afde79563e2cf37cfe62ee3b71c063fd5546c8e662d7fcfc2a3d5031a5c4c", size = 142677 }, - { url = "https://files.pythonhosted.org/packages/2c/71/73a1214bd27baa2ea5184fff4aa6193a114dfb0aa5663dad48fe63e8cd29/orjson-3.10.16-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:113602f8241daaff05d6fad25bd481d54c42d8d72ef4c831bb3ab682a54d9e15", size = 132798 }, - { url = "https://files.pythonhosted.org/packages/53/ac/0b2f41c0a1e8c095439d0fab3b33103cf41a39be8e6aa2c56298a6034259/orjson-3.10.16-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4fc0077d101f8fab4031e6554fc17b4c2ad8fdbc56ee64a727f3c95b379e31da", size = 135450 }, - { url = "https://files.pythonhosted.org/packages/d9/ca/7524c7b0bc815d426ca134dab54cad519802287b808a3846b047a5b2b7a3/orjson-3.10.16-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:9c6bf6ff180cd69e93f3f50380224218cfab79953a868ea3908430bcfaf9cb5e", size = 412356 }, - { url = "https://files.pythonhosted.org/packages/05/1d/3ae2367c255276bf16ff7e1b210dd0af18bc8da20c4e4295755fc7de1268/orjson-3.10.16-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5673eadfa952f95a7cd76418ff189df11b0a9c34b1995dff43a6fdbce5d63bf4", size = 152769 }, - { url = "https://files.pythonhosted.org/packages/d3/2d/8eb10b6b1d30bb69c35feb15e5ba5ac82466cf743d562e3e8047540efd2f/orjson-3.10.16-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5fe638a423d852b0ae1e1a79895851696cb0d9fa0946fdbfd5da5072d9bb9551", size = 137223 }, - { url = "https://files.pythonhosted.org/packages/47/42/f043717930cb2de5fbebe47f308f101bed9ec2b3580b1f99c8284b2f5fe8/orjson-3.10.16-cp310-cp310-win32.whl", hash = "sha256:33af58f479b3c6435ab8f8b57999874b4b40c804c7a36b5cc6b54d8f28e1d3dd", size = 141734 }, - { url = "https://files.pythonhosted.org/packages/67/99/795ad7282b425b9fddcfb8a31bded5dcf84dba78ecb1e7ae716e84e794da/orjson-3.10.16-cp310-cp310-win_amd64.whl", hash = "sha256:0338356b3f56d71293c583350af26f053017071836b07e064e92819ecf1aa055", size = 133779 }, - { url = "https://files.pythonhosted.org/packages/97/29/43f91a5512b5d2535594438eb41c5357865fd5e64dec745d90a588820c75/orjson-3.10.16-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:44fcbe1a1884f8bc9e2e863168b0f84230c3d634afe41c678637d2728ea8e739", size = 249180 }, - { url = "https://files.pythonhosted.org/packages/0c/36/2a72d55e266473c19a86d97b7363bb8bf558ab450f75205689a287d5ce61/orjson-3.10.16-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78177bf0a9d0192e0b34c3d78bcff7fe21d1b5d84aeb5ebdfe0dbe637b885225", size = 138510 }, - { url = "https://files.pythonhosted.org/packages/bb/ad/f86d6f55c1a68b57ff6ea7966bce5f4e5163f2e526ddb7db9fc3c2c8d1c4/orjson-3.10.16-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:12824073a010a754bb27330cad21d6e9b98374f497f391b8707752b96f72e741", size = 132373 }, - { url = "https://files.pythonhosted.org/packages/5e/8b/d18f2711493a809f3082a88fda89342bc8e16767743b909cd3c34989fba3/orjson-3.10.16-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddd41007e56284e9867864aa2f29f3136bb1dd19a49ca43c0b4eda22a579cf53", size = 136773 }, - { url = "https://files.pythonhosted.org/packages/a1/dc/ce025f002f8e0749e3f057c4d773a4d4de32b7b4c1fc5a50b429e7532586/orjson-3.10.16-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0877c4d35de639645de83666458ca1f12560d9fa7aa9b25d8bb8f52f61627d14", size = 138029 }, - { url = "https://files.pythonhosted.org/packages/0e/1b/cf9df85852b91160029d9f26014230366a2b4deb8cc51fabe68e250a8c1a/orjson-3.10.16-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9a09a539e9cc3beead3e7107093b4ac176d015bec64f811afb5965fce077a03c", size = 142677 }, - { url = "https://files.pythonhosted.org/packages/92/18/5b1e1e995bffad49dc4311a0bdfd874bc6f135fd20f0e1f671adc2c9910e/orjson-3.10.16-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31b98bc9b40610fec971d9a4d67bb2ed02eec0a8ae35f8ccd2086320c28526ca", size = 132800 }, - { url = "https://files.pythonhosted.org/packages/d6/eb/467f25b580e942fcca1344adef40633b7f05ac44a65a63fc913f9a805d58/orjson-3.10.16-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0ce243f5a8739f3a18830bc62dc2e05b69a7545bafd3e3249f86668b2bcd8e50", size = 135451 }, - { url = "https://files.pythonhosted.org/packages/8d/4b/9d10888038975cb375982e9339d9495bac382d5c976c500b8d6f2c8e2e4e/orjson-3.10.16-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:64792c0025bae049b3074c6abe0cf06f23c8e9f5a445f4bab31dc5ca23dbf9e1", size = 412358 }, - { url = "https://files.pythonhosted.org/packages/3b/e2/cfbcfcc4fbe619e0ca9bdbbfccb2d62b540bbfe41e0ee77d44a628594f59/orjson-3.10.16-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ea53f7e68eec718b8e17e942f7ca56c6bd43562eb19db3f22d90d75e13f0431d", size = 152772 }, - { url = "https://files.pythonhosted.org/packages/b9/d6/627a1b00569be46173007c11dde3da4618c9bfe18409325b0e3e2a82fe29/orjson-3.10.16-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a741ba1a9488c92227711bde8c8c2b63d7d3816883268c808fbeada00400c164", size = 137225 }, - { url = "https://files.pythonhosted.org/packages/0a/7b/a73c67b505021af845b9f05c7c848793258ea141fa2058b52dd9b067c2b4/orjson-3.10.16-cp311-cp311-win32.whl", hash = "sha256:c7ed2c61bb8226384c3fdf1fb01c51b47b03e3f4536c985078cccc2fd19f1619", size = 141733 }, - { url = "https://files.pythonhosted.org/packages/f4/22/5e8217c48d68c0adbfb181e749d6a733761074e598b083c69a1383d18147/orjson-3.10.16-cp311-cp311-win_amd64.whl", hash = "sha256:cd67d8b3e0e56222a2e7b7f7da9031e30ecd1fe251c023340b9f12caca85ab60", size = 133784 }, - { url = "https://files.pythonhosted.org/packages/5d/15/67ce9d4c959c83f112542222ea3b9209c1d424231d71d74c4890ea0acd2b/orjson-3.10.16-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:6d3444abbfa71ba21bb042caa4b062535b122248259fdb9deea567969140abca", size = 249325 }, - { url = "https://files.pythonhosted.org/packages/da/2c/1426b06f30a1b9ada74b6f512c1ddf9d2760f53f61cdb59efeb9ad342133/orjson-3.10.16-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:30245c08d818fdcaa48b7d5b81499b8cae09acabb216fe61ca619876b128e184", size = 133621 }, - { url = "https://files.pythonhosted.org/packages/9e/88/18d26130954bc73bee3be10f95371ea1dfb8679e0e2c46b0f6d8c6289402/orjson-3.10.16-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0ba1d0baa71bf7579a4ccdcf503e6f3098ef9542106a0eca82395898c8a500a", size = 138270 }, - { url = "https://files.pythonhosted.org/packages/4f/f9/6d8b64fcd58fae072e80ee7981be8ba0d7c26ace954e5cd1d027fc80518f/orjson-3.10.16-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb0beefa5ef3af8845f3a69ff2a4aa62529b5acec1cfe5f8a6b4141033fd46ef", size = 132346 }, - { url = "https://files.pythonhosted.org/packages/16/3f/2513fd5bc786f40cd12af569c23cae6381aeddbefeed2a98f0a666eb5d0d/orjson-3.10.16-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6daa0e1c9bf2e030e93c98394de94506f2a4d12e1e9dadd7c53d5e44d0f9628e", size = 136845 }, - { url = "https://files.pythonhosted.org/packages/6d/42/b0e7b36720f5ab722b48e8ccf06514d4f769358dd73c51abd8728ef58d0b/orjson-3.10.16-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9da9019afb21e02410ef600e56666652b73eb3e4d213a0ec919ff391a7dd52aa", size = 138078 }, - { url = "https://files.pythonhosted.org/packages/a3/a8/d220afb8a439604be74fc755dbc740bded5ed14745ca536b304ed32eb18a/orjson-3.10.16-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:daeb3a1ee17b69981d3aae30c3b4e786b0f8c9e6c71f2b48f1aef934f63f38f4", size = 142712 }, - { url = "https://files.pythonhosted.org/packages/8c/88/7e41e9883c00f84f92fe357a8371edae816d9d7ef39c67b5106960c20389/orjson-3.10.16-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80fed80eaf0e20a31942ae5d0728849862446512769692474be5e6b73123a23b", size = 133136 }, - { url = "https://files.pythonhosted.org/packages/e9/ca/61116095307ad0be828ea26093febaf59e38596d84a9c8d765c3c5e4934f/orjson-3.10.16-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73390ed838f03764540a7bdc4071fe0123914c2cc02fb6abf35182d5fd1b7a42", size = 135258 }, - { url = "https://files.pythonhosted.org/packages/dc/1b/09493cf7d801505f094c9295f79c98c1e0af2ac01c7ed8d25b30fcb19ada/orjson-3.10.16-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a22bba012a0c94ec02a7768953020ab0d3e2b884760f859176343a36c01adf87", size = 412326 }, - { url = "https://files.pythonhosted.org/packages/ea/02/125d7bbd7f7a500190ddc8ae5d2d3c39d87ed3ed28f5b37cfe76962c678d/orjson-3.10.16-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5385bbfdbc90ff5b2635b7e6bebf259652db00a92b5e3c45b616df75b9058e88", size = 152800 }, - { url = "https://files.pythonhosted.org/packages/f9/09/7658a9e3e793d5b3b00598023e0fb6935d0e7bbb8ff72311c5415a8ce677/orjson-3.10.16-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:02c6279016346e774dd92625d46c6c40db687b8a0d685aadb91e26e46cc33e1e", size = 137516 }, - { url = "https://files.pythonhosted.org/packages/29/87/32b7a4831e909d347278101a48d4cf9f3f25901b2295e7709df1651f65a1/orjson-3.10.16-cp312-cp312-win32.whl", hash = "sha256:7ca55097a11426db80f79378e873a8c51f4dde9ffc22de44850f9696b7eb0e8c", size = 141759 }, - { url = "https://files.pythonhosted.org/packages/35/ce/81a27e7b439b807bd393585271364cdddf50dc281fc57c4feef7ccb186a6/orjson-3.10.16-cp312-cp312-win_amd64.whl", hash = "sha256:86d127efdd3f9bf5f04809b70faca1e6836556ea3cc46e662b44dab3fe71f3d6", size = 133944 }, - { url = "https://files.pythonhosted.org/packages/87/b9/ff6aa28b8c86af9526160905593a2fe8d004ac7a5e592ee0b0ff71017511/orjson-3.10.16-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:148a97f7de811ba14bc6dbc4a433e0341ffd2cc285065199fb5f6a98013744bd", size = 249289 }, - { url = "https://files.pythonhosted.org/packages/6c/81/6d92a586149b52684ab8fd70f3623c91d0e6a692f30fd8c728916ab2263c/orjson-3.10.16-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:1d960c1bf0e734ea36d0adc880076de3846aaec45ffad29b78c7f1b7962516b8", size = 133640 }, - { url = "https://files.pythonhosted.org/packages/c2/88/b72443f4793d2e16039ab85d0026677932b15ab968595fb7149750d74134/orjson-3.10.16-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a318cd184d1269f68634464b12871386808dc8b7c27de8565234d25975a7a137", size = 138286 }, - { url = "https://files.pythonhosted.org/packages/c3/3c/72a22d4b28c076c4016d5a52bd644a8e4d849d3bb0373d9e377f9e3b2250/orjson-3.10.16-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:df23f8df3ef9223d1d6748bea63fca55aae7da30a875700809c500a05975522b", size = 132307 }, - { url = "https://files.pythonhosted.org/packages/8a/a2/f1259561bdb6ad7061ff1b95dab082fe32758c4bc143ba8d3d70831f0a06/orjson-3.10.16-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b94dda8dd6d1378f1037d7f3f6b21db769ef911c4567cbaa962bb6dc5021cf90", size = 136739 }, - { url = "https://files.pythonhosted.org/packages/3d/af/c7583c4b34f33d8b8b90cfaab010ff18dd64e7074cc1e117a5f1eff20dcf/orjson-3.10.16-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f12970a26666a8775346003fd94347d03ccb98ab8aa063036818381acf5f523e", size = 138076 }, - { url = "https://files.pythonhosted.org/packages/d7/59/d7fc7fbdd3d4a64c2eae4fc7341a5aa39cf9549bd5e2d7f6d3c07f8b715b/orjson-3.10.16-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15a1431a245d856bd56e4d29ea0023eb4d2c8f71efe914beb3dee8ab3f0cd7fb", size = 142643 }, - { url = "https://files.pythonhosted.org/packages/92/0e/3bd8f2197d27601f16b4464ae948826da2bcf128af31230a9dbbad7ceb57/orjson-3.10.16-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c83655cfc247f399a222567d146524674a7b217af7ef8289c0ff53cfe8db09f0", size = 133168 }, - { url = "https://files.pythonhosted.org/packages/af/a8/351fd87b664b02f899f9144d2c3dc848b33ac04a5df05234cbfb9e2a7540/orjson-3.10.16-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:fa59ae64cb6ddde8f09bdbf7baf933c4cd05734ad84dcf4e43b887eb24e37652", size = 135271 }, - { url = "https://files.pythonhosted.org/packages/ba/b0/a6d42a7d412d867c60c0337d95123517dd5a9370deea705ea1be0f89389e/orjson-3.10.16-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ca5426e5aacc2e9507d341bc169d8af9c3cbe88f4cd4c1cf2f87e8564730eb56", size = 412444 }, - { url = "https://files.pythonhosted.org/packages/79/ec/7572cd4e20863f60996f3f10bc0a6da64a6fd9c35954189a914cec0b7377/orjson-3.10.16-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6fd5da4edf98a400946cd3a195680de56f1e7575109b9acb9493331047157430", size = 152737 }, - { url = "https://files.pythonhosted.org/packages/a9/19/ceb9e8fed5403b2e76a8ac15f581b9d25780a3be3c9b3aa54b7777a210d5/orjson-3.10.16-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:980ecc7a53e567169282a5e0ff078393bac78320d44238da4e246d71a4e0e8f5", size = 137482 }, - { url = "https://files.pythonhosted.org/packages/1b/78/a78bb810f3786579dbbbd94768284cbe8f2fd65167cd7020260679665c17/orjson-3.10.16-cp313-cp313-win32.whl", hash = "sha256:28f79944dd006ac540a6465ebd5f8f45dfdf0948ff998eac7a908275b4c1add6", size = 141714 }, - { url = "https://files.pythonhosted.org/packages/81/9c/b66ce9245ff319df2c3278acd351a3f6145ef34b4a2d7f4b0f739368370f/orjson-3.10.16-cp313-cp313-win_amd64.whl", hash = "sha256:fe0a145e96d51971407cb8ba947e63ead2aa915db59d6631a355f5f2150b56b7", size = 133954 }, + { url = "https://files.pythonhosted.org/packages/9d/a6/22cb9b03baf167bc2d659c9e74d7580147f36e6a155e633801badfd5a74d/orjson-3.10.16-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:4cb473b8e79154fa778fb56d2d73763d977be3dcc140587e07dbc545bbfc38f8", size = 249179, upload_time = "2025-03-24T16:58:41.294Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/3e68cc33020a6ebd8f359b8628b69d2132cd84fea68155c33057e502ee51/orjson-3.10.16-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:622a8e85eeec1948690409a19ca1c7d9fd8ff116f4861d261e6ae2094fe59a00", size = 138510, upload_time = "2025-03-24T16:58:43.732Z" }, + { url = "https://files.pythonhosted.org/packages/dc/12/63bee7764ce12052f7c1a1393ce7f26dc392c93081eb8754dd3dce9b7c6b/orjson-3.10.16-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c682d852d0ce77613993dc967e90e151899fe2d8e71c20e9be164080f468e370", size = 132373, upload_time = "2025-03-24T16:58:45.094Z" }, + { url = "https://files.pythonhosted.org/packages/b3/d5/2998c2f319adcd572f2b03ba2083e8176863d1055d8d713683ddcf927b71/orjson-3.10.16-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c520ae736acd2e32df193bcff73491e64c936f3e44a2916b548da048a48b46b", size = 136774, upload_time = "2025-03-24T16:58:46.273Z" }, + { url = "https://files.pythonhosted.org/packages/00/03/88c236ae307bd0604623204d4a835e15fbf9c75b8535c8f13ef45abd413f/orjson-3.10.16-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:134f87c76bfae00f2094d85cfab261b289b76d78c6da8a7a3b3c09d362fd1e06", size = 138030, upload_time = "2025-03-24T16:58:47.921Z" }, + { url = "https://files.pythonhosted.org/packages/66/ba/3e256ddfeb364f98fd6ac65774844090d356158b2d1de8998db2bf984503/orjson-3.10.16-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b59afde79563e2cf37cfe62ee3b71c063fd5546c8e662d7fcfc2a3d5031a5c4c", size = 142677, upload_time = "2025-03-24T16:58:49.191Z" }, + { url = "https://files.pythonhosted.org/packages/2c/71/73a1214bd27baa2ea5184fff4aa6193a114dfb0aa5663dad48fe63e8cd29/orjson-3.10.16-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:113602f8241daaff05d6fad25bd481d54c42d8d72ef4c831bb3ab682a54d9e15", size = 132798, upload_time = "2025-03-24T16:58:50.746Z" }, + { url = "https://files.pythonhosted.org/packages/53/ac/0b2f41c0a1e8c095439d0fab3b33103cf41a39be8e6aa2c56298a6034259/orjson-3.10.16-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4fc0077d101f8fab4031e6554fc17b4c2ad8fdbc56ee64a727f3c95b379e31da", size = 135450, upload_time = "2025-03-24T16:58:52.481Z" }, + { url = "https://files.pythonhosted.org/packages/d9/ca/7524c7b0bc815d426ca134dab54cad519802287b808a3846b047a5b2b7a3/orjson-3.10.16-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:9c6bf6ff180cd69e93f3f50380224218cfab79953a868ea3908430bcfaf9cb5e", size = 412356, upload_time = "2025-03-24T16:58:54.17Z" }, + { url = "https://files.pythonhosted.org/packages/05/1d/3ae2367c255276bf16ff7e1b210dd0af18bc8da20c4e4295755fc7de1268/orjson-3.10.16-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5673eadfa952f95a7cd76418ff189df11b0a9c34b1995dff43a6fdbce5d63bf4", size = 152769, upload_time = "2025-03-24T16:58:55.821Z" }, + { url = "https://files.pythonhosted.org/packages/d3/2d/8eb10b6b1d30bb69c35feb15e5ba5ac82466cf743d562e3e8047540efd2f/orjson-3.10.16-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5fe638a423d852b0ae1e1a79895851696cb0d9fa0946fdbfd5da5072d9bb9551", size = 137223, upload_time = "2025-03-24T16:58:57.136Z" }, + { url = "https://files.pythonhosted.org/packages/47/42/f043717930cb2de5fbebe47f308f101bed9ec2b3580b1f99c8284b2f5fe8/orjson-3.10.16-cp310-cp310-win32.whl", hash = "sha256:33af58f479b3c6435ab8f8b57999874b4b40c804c7a36b5cc6b54d8f28e1d3dd", size = 141734, upload_time = "2025-03-24T16:58:58.516Z" }, + { url = "https://files.pythonhosted.org/packages/67/99/795ad7282b425b9fddcfb8a31bded5dcf84dba78ecb1e7ae716e84e794da/orjson-3.10.16-cp310-cp310-win_amd64.whl", hash = "sha256:0338356b3f56d71293c583350af26f053017071836b07e064e92819ecf1aa055", size = 133779, upload_time = "2025-03-24T16:59:00.254Z" }, + { url = "https://files.pythonhosted.org/packages/97/29/43f91a5512b5d2535594438eb41c5357865fd5e64dec745d90a588820c75/orjson-3.10.16-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:44fcbe1a1884f8bc9e2e863168b0f84230c3d634afe41c678637d2728ea8e739", size = 249180, upload_time = "2025-03-24T16:59:01.507Z" }, + { url = "https://files.pythonhosted.org/packages/0c/36/2a72d55e266473c19a86d97b7363bb8bf558ab450f75205689a287d5ce61/orjson-3.10.16-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78177bf0a9d0192e0b34c3d78bcff7fe21d1b5d84aeb5ebdfe0dbe637b885225", size = 138510, upload_time = "2025-03-24T16:59:02.876Z" }, + { url = "https://files.pythonhosted.org/packages/bb/ad/f86d6f55c1a68b57ff6ea7966bce5f4e5163f2e526ddb7db9fc3c2c8d1c4/orjson-3.10.16-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:12824073a010a754bb27330cad21d6e9b98374f497f391b8707752b96f72e741", size = 132373, upload_time = "2025-03-24T16:59:04.103Z" }, + { url = "https://files.pythonhosted.org/packages/5e/8b/d18f2711493a809f3082a88fda89342bc8e16767743b909cd3c34989fba3/orjson-3.10.16-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddd41007e56284e9867864aa2f29f3136bb1dd19a49ca43c0b4eda22a579cf53", size = 136773, upload_time = "2025-03-24T16:59:05.636Z" }, + { url = "https://files.pythonhosted.org/packages/a1/dc/ce025f002f8e0749e3f057c4d773a4d4de32b7b4c1fc5a50b429e7532586/orjson-3.10.16-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0877c4d35de639645de83666458ca1f12560d9fa7aa9b25d8bb8f52f61627d14", size = 138029, upload_time = "2025-03-24T16:59:06.99Z" }, + { url = "https://files.pythonhosted.org/packages/0e/1b/cf9df85852b91160029d9f26014230366a2b4deb8cc51fabe68e250a8c1a/orjson-3.10.16-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9a09a539e9cc3beead3e7107093b4ac176d015bec64f811afb5965fce077a03c", size = 142677, upload_time = "2025-03-24T16:59:08.22Z" }, + { url = "https://files.pythonhosted.org/packages/92/18/5b1e1e995bffad49dc4311a0bdfd874bc6f135fd20f0e1f671adc2c9910e/orjson-3.10.16-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31b98bc9b40610fec971d9a4d67bb2ed02eec0a8ae35f8ccd2086320c28526ca", size = 132800, upload_time = "2025-03-24T16:59:09.529Z" }, + { url = "https://files.pythonhosted.org/packages/d6/eb/467f25b580e942fcca1344adef40633b7f05ac44a65a63fc913f9a805d58/orjson-3.10.16-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0ce243f5a8739f3a18830bc62dc2e05b69a7545bafd3e3249f86668b2bcd8e50", size = 135451, upload_time = "2025-03-24T16:59:10.823Z" }, + { url = "https://files.pythonhosted.org/packages/8d/4b/9d10888038975cb375982e9339d9495bac382d5c976c500b8d6f2c8e2e4e/orjson-3.10.16-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:64792c0025bae049b3074c6abe0cf06f23c8e9f5a445f4bab31dc5ca23dbf9e1", size = 412358, upload_time = "2025-03-24T16:59:12.113Z" }, + { url = "https://files.pythonhosted.org/packages/3b/e2/cfbcfcc4fbe619e0ca9bdbbfccb2d62b540bbfe41e0ee77d44a628594f59/orjson-3.10.16-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ea53f7e68eec718b8e17e942f7ca56c6bd43562eb19db3f22d90d75e13f0431d", size = 152772, upload_time = "2025-03-24T16:59:13.919Z" }, + { url = "https://files.pythonhosted.org/packages/b9/d6/627a1b00569be46173007c11dde3da4618c9bfe18409325b0e3e2a82fe29/orjson-3.10.16-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a741ba1a9488c92227711bde8c8c2b63d7d3816883268c808fbeada00400c164", size = 137225, upload_time = "2025-03-24T16:59:15.355Z" }, + { url = "https://files.pythonhosted.org/packages/0a/7b/a73c67b505021af845b9f05c7c848793258ea141fa2058b52dd9b067c2b4/orjson-3.10.16-cp311-cp311-win32.whl", hash = "sha256:c7ed2c61bb8226384c3fdf1fb01c51b47b03e3f4536c985078cccc2fd19f1619", size = 141733, upload_time = "2025-03-24T16:59:16.791Z" }, + { url = "https://files.pythonhosted.org/packages/f4/22/5e8217c48d68c0adbfb181e749d6a733761074e598b083c69a1383d18147/orjson-3.10.16-cp311-cp311-win_amd64.whl", hash = "sha256:cd67d8b3e0e56222a2e7b7f7da9031e30ecd1fe251c023340b9f12caca85ab60", size = 133784, upload_time = "2025-03-24T16:59:18.106Z" }, + { url = "https://files.pythonhosted.org/packages/5d/15/67ce9d4c959c83f112542222ea3b9209c1d424231d71d74c4890ea0acd2b/orjson-3.10.16-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:6d3444abbfa71ba21bb042caa4b062535b122248259fdb9deea567969140abca", size = 249325, upload_time = "2025-03-24T16:59:19.784Z" }, + { url = "https://files.pythonhosted.org/packages/da/2c/1426b06f30a1b9ada74b6f512c1ddf9d2760f53f61cdb59efeb9ad342133/orjson-3.10.16-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:30245c08d818fdcaa48b7d5b81499b8cae09acabb216fe61ca619876b128e184", size = 133621, upload_time = "2025-03-24T16:59:21.207Z" }, + { url = "https://files.pythonhosted.org/packages/9e/88/18d26130954bc73bee3be10f95371ea1dfb8679e0e2c46b0f6d8c6289402/orjson-3.10.16-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0ba1d0baa71bf7579a4ccdcf503e6f3098ef9542106a0eca82395898c8a500a", size = 138270, upload_time = "2025-03-24T16:59:22.514Z" }, + { url = "https://files.pythonhosted.org/packages/4f/f9/6d8b64fcd58fae072e80ee7981be8ba0d7c26ace954e5cd1d027fc80518f/orjson-3.10.16-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb0beefa5ef3af8845f3a69ff2a4aa62529b5acec1cfe5f8a6b4141033fd46ef", size = 132346, upload_time = "2025-03-24T16:59:24.277Z" }, + { url = "https://files.pythonhosted.org/packages/16/3f/2513fd5bc786f40cd12af569c23cae6381aeddbefeed2a98f0a666eb5d0d/orjson-3.10.16-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6daa0e1c9bf2e030e93c98394de94506f2a4d12e1e9dadd7c53d5e44d0f9628e", size = 136845, upload_time = "2025-03-24T16:59:25.588Z" }, + { url = "https://files.pythonhosted.org/packages/6d/42/b0e7b36720f5ab722b48e8ccf06514d4f769358dd73c51abd8728ef58d0b/orjson-3.10.16-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9da9019afb21e02410ef600e56666652b73eb3e4d213a0ec919ff391a7dd52aa", size = 138078, upload_time = "2025-03-24T16:59:27.288Z" }, + { url = "https://files.pythonhosted.org/packages/a3/a8/d220afb8a439604be74fc755dbc740bded5ed14745ca536b304ed32eb18a/orjson-3.10.16-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:daeb3a1ee17b69981d3aae30c3b4e786b0f8c9e6c71f2b48f1aef934f63f38f4", size = 142712, upload_time = "2025-03-24T16:59:28.613Z" }, + { url = "https://files.pythonhosted.org/packages/8c/88/7e41e9883c00f84f92fe357a8371edae816d9d7ef39c67b5106960c20389/orjson-3.10.16-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80fed80eaf0e20a31942ae5d0728849862446512769692474be5e6b73123a23b", size = 133136, upload_time = "2025-03-24T16:59:29.987Z" }, + { url = "https://files.pythonhosted.org/packages/e9/ca/61116095307ad0be828ea26093febaf59e38596d84a9c8d765c3c5e4934f/orjson-3.10.16-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73390ed838f03764540a7bdc4071fe0123914c2cc02fb6abf35182d5fd1b7a42", size = 135258, upload_time = "2025-03-24T16:59:31.339Z" }, + { url = "https://files.pythonhosted.org/packages/dc/1b/09493cf7d801505f094c9295f79c98c1e0af2ac01c7ed8d25b30fcb19ada/orjson-3.10.16-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a22bba012a0c94ec02a7768953020ab0d3e2b884760f859176343a36c01adf87", size = 412326, upload_time = "2025-03-24T16:59:32.709Z" }, + { url = "https://files.pythonhosted.org/packages/ea/02/125d7bbd7f7a500190ddc8ae5d2d3c39d87ed3ed28f5b37cfe76962c678d/orjson-3.10.16-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5385bbfdbc90ff5b2635b7e6bebf259652db00a92b5e3c45b616df75b9058e88", size = 152800, upload_time = "2025-03-24T16:59:34.134Z" }, + { url = "https://files.pythonhosted.org/packages/f9/09/7658a9e3e793d5b3b00598023e0fb6935d0e7bbb8ff72311c5415a8ce677/orjson-3.10.16-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:02c6279016346e774dd92625d46c6c40db687b8a0d685aadb91e26e46cc33e1e", size = 137516, upload_time = "2025-03-24T16:59:35.446Z" }, + { url = "https://files.pythonhosted.org/packages/29/87/32b7a4831e909d347278101a48d4cf9f3f25901b2295e7709df1651f65a1/orjson-3.10.16-cp312-cp312-win32.whl", hash = "sha256:7ca55097a11426db80f79378e873a8c51f4dde9ffc22de44850f9696b7eb0e8c", size = 141759, upload_time = "2025-03-24T16:59:37.509Z" }, + { url = "https://files.pythonhosted.org/packages/35/ce/81a27e7b439b807bd393585271364cdddf50dc281fc57c4feef7ccb186a6/orjson-3.10.16-cp312-cp312-win_amd64.whl", hash = "sha256:86d127efdd3f9bf5f04809b70faca1e6836556ea3cc46e662b44dab3fe71f3d6", size = 133944, upload_time = "2025-03-24T16:59:38.814Z" }, + { url = "https://files.pythonhosted.org/packages/87/b9/ff6aa28b8c86af9526160905593a2fe8d004ac7a5e592ee0b0ff71017511/orjson-3.10.16-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:148a97f7de811ba14bc6dbc4a433e0341ffd2cc285065199fb5f6a98013744bd", size = 249289, upload_time = "2025-03-24T16:59:40.117Z" }, + { url = "https://files.pythonhosted.org/packages/6c/81/6d92a586149b52684ab8fd70f3623c91d0e6a692f30fd8c728916ab2263c/orjson-3.10.16-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:1d960c1bf0e734ea36d0adc880076de3846aaec45ffad29b78c7f1b7962516b8", size = 133640, upload_time = "2025-03-24T16:59:41.469Z" }, + { url = "https://files.pythonhosted.org/packages/c2/88/b72443f4793d2e16039ab85d0026677932b15ab968595fb7149750d74134/orjson-3.10.16-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a318cd184d1269f68634464b12871386808dc8b7c27de8565234d25975a7a137", size = 138286, upload_time = "2025-03-24T16:59:42.769Z" }, + { url = "https://files.pythonhosted.org/packages/c3/3c/72a22d4b28c076c4016d5a52bd644a8e4d849d3bb0373d9e377f9e3b2250/orjson-3.10.16-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:df23f8df3ef9223d1d6748bea63fca55aae7da30a875700809c500a05975522b", size = 132307, upload_time = "2025-03-24T16:59:44.143Z" }, + { url = "https://files.pythonhosted.org/packages/8a/a2/f1259561bdb6ad7061ff1b95dab082fe32758c4bc143ba8d3d70831f0a06/orjson-3.10.16-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b94dda8dd6d1378f1037d7f3f6b21db769ef911c4567cbaa962bb6dc5021cf90", size = 136739, upload_time = "2025-03-24T16:59:45.995Z" }, + { url = "https://files.pythonhosted.org/packages/3d/af/c7583c4b34f33d8b8b90cfaab010ff18dd64e7074cc1e117a5f1eff20dcf/orjson-3.10.16-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f12970a26666a8775346003fd94347d03ccb98ab8aa063036818381acf5f523e", size = 138076, upload_time = "2025-03-24T16:59:47.776Z" }, + { url = "https://files.pythonhosted.org/packages/d7/59/d7fc7fbdd3d4a64c2eae4fc7341a5aa39cf9549bd5e2d7f6d3c07f8b715b/orjson-3.10.16-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15a1431a245d856bd56e4d29ea0023eb4d2c8f71efe914beb3dee8ab3f0cd7fb", size = 142643, upload_time = "2025-03-24T16:59:49.258Z" }, + { url = "https://files.pythonhosted.org/packages/92/0e/3bd8f2197d27601f16b4464ae948826da2bcf128af31230a9dbbad7ceb57/orjson-3.10.16-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c83655cfc247f399a222567d146524674a7b217af7ef8289c0ff53cfe8db09f0", size = 133168, upload_time = "2025-03-24T16:59:51.027Z" }, + { url = "https://files.pythonhosted.org/packages/af/a8/351fd87b664b02f899f9144d2c3dc848b33ac04a5df05234cbfb9e2a7540/orjson-3.10.16-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:fa59ae64cb6ddde8f09bdbf7baf933c4cd05734ad84dcf4e43b887eb24e37652", size = 135271, upload_time = "2025-03-24T16:59:52.449Z" }, + { url = "https://files.pythonhosted.org/packages/ba/b0/a6d42a7d412d867c60c0337d95123517dd5a9370deea705ea1be0f89389e/orjson-3.10.16-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ca5426e5aacc2e9507d341bc169d8af9c3cbe88f4cd4c1cf2f87e8564730eb56", size = 412444, upload_time = "2025-03-24T16:59:53.825Z" }, + { url = "https://files.pythonhosted.org/packages/79/ec/7572cd4e20863f60996f3f10bc0a6da64a6fd9c35954189a914cec0b7377/orjson-3.10.16-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6fd5da4edf98a400946cd3a195680de56f1e7575109b9acb9493331047157430", size = 152737, upload_time = "2025-03-24T16:59:55.599Z" }, + { url = "https://files.pythonhosted.org/packages/a9/19/ceb9e8fed5403b2e76a8ac15f581b9d25780a3be3c9b3aa54b7777a210d5/orjson-3.10.16-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:980ecc7a53e567169282a5e0ff078393bac78320d44238da4e246d71a4e0e8f5", size = 137482, upload_time = "2025-03-24T16:59:57.045Z" }, + { url = "https://files.pythonhosted.org/packages/1b/78/a78bb810f3786579dbbbd94768284cbe8f2fd65167cd7020260679665c17/orjson-3.10.16-cp313-cp313-win32.whl", hash = "sha256:28f79944dd006ac540a6465ebd5f8f45dfdf0948ff998eac7a908275b4c1add6", size = 141714, upload_time = "2025-03-24T16:59:58.666Z" }, + { url = "https://files.pythonhosted.org/packages/81/9c/b66ce9245ff319df2c3278acd351a3f6145ef34b4a2d7f4b0f739368370f/orjson-3.10.16-cp313-cp313-win_amd64.whl", hash = "sha256:fe0a145e96d51971407cb8ba947e63ead2aa915db59d6631a355f5f2150b56b7", size = 133954, upload_time = "2025-03-24T17:00:00.101Z" }, ] [[package]] name = "packaging" version = "23.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fb/2b/9b9c33ffed44ee921d0967086d653047286054117d584f1b1a7c22ceaf7b/packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", size = 146714 } +sdist = { url = "https://files.pythonhosted.org/packages/fb/2b/9b9c33ffed44ee921d0967086d653047286054117d584f1b1a7c22ceaf7b/packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", size = 146714, upload_time = "2023-10-01T13:50:05.279Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/1a/610693ac4ee14fcdf2d9bf3c493370e4f2ef7ae2e19217d7a237ff42367d/packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7", size = 53011 }, + { url = "https://files.pythonhosted.org/packages/ec/1a/610693ac4ee14fcdf2d9bf3c493370e4f2ef7ae2e19217d7a237ff42367d/packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7", size = 53011, upload_time = "2023-10-01T13:50:03.745Z" }, ] [[package]] name = "pathspec" version = "0.12.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043 } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload_time = "2023-12-10T22:30:45Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 }, + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload_time = "2023-12-10T22:30:43.14Z" }, ] [[package]] name = "pillow" version = "10.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cd/74/ad3d526f3bf7b6d3f408b73fde271ec69dfac8b81341a318ce825f2b3812/pillow-10.4.0.tar.gz", hash = "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06", size = 46555059 } +sdist = { url = "https://files.pythonhosted.org/packages/cd/74/ad3d526f3bf7b6d3f408b73fde271ec69dfac8b81341a318ce825f2b3812/pillow-10.4.0.tar.gz", hash = "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06", size = 46555059, upload_time = "2024-07-01T09:48:43.583Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0e/69/a31cccd538ca0b5272be2a38347f8839b97a14be104ea08b0db92f749c74/pillow-10.4.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:4d9667937cfa347525b319ae34375c37b9ee6b525440f3ef48542fcf66f2731e", size = 3509271 }, - { url = "https://files.pythonhosted.org/packages/9a/9e/4143b907be8ea0bce215f2ae4f7480027473f8b61fcedfda9d851082a5d2/pillow-10.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:543f3dc61c18dafb755773efc89aae60d06b6596a63914107f75459cf984164d", size = 3375658 }, - { url = "https://files.pythonhosted.org/packages/8a/25/1fc45761955f9359b1169aa75e241551e74ac01a09f487adaaf4c3472d11/pillow-10.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7928ecbf1ece13956b95d9cbcfc77137652b02763ba384d9ab508099a2eca856", size = 4332075 }, - { url = "https://files.pythonhosted.org/packages/5e/dd/425b95d0151e1d6c951f45051112394f130df3da67363b6bc75dc4c27aba/pillow-10.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4d49b85c4348ea0b31ea63bc75a9f3857869174e2bf17e7aba02945cd218e6f", size = 4444808 }, - { url = "https://files.pythonhosted.org/packages/b1/84/9a15cc5726cbbfe7f9f90bfb11f5d028586595907cd093815ca6644932e3/pillow-10.4.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:6c762a5b0997f5659a5ef2266abc1d8851ad7749ad9a6a5506eb23d314e4f46b", size = 4356290 }, - { url = "https://files.pythonhosted.org/packages/b5/5b/6651c288b08df3b8c1e2f8c1152201e0b25d240e22ddade0f1e242fc9fa0/pillow-10.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a985e028fc183bf12a77a8bbf36318db4238a3ded7fa9df1b9a133f1cb79f8fc", size = 4525163 }, - { url = "https://files.pythonhosted.org/packages/07/8b/34854bf11a83c248505c8cb0fcf8d3d0b459a2246c8809b967963b6b12ae/pillow-10.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:812f7342b0eee081eaec84d91423d1b4650bb9828eb53d8511bcef8ce5aecf1e", size = 4463100 }, - { url = "https://files.pythonhosted.org/packages/78/63/0632aee4e82476d9cbe5200c0cdf9ba41ee04ed77887432845264d81116d/pillow-10.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ac1452d2fbe4978c2eec89fb5a23b8387aba707ac72810d9490118817d9c0b46", size = 4592880 }, - { url = "https://files.pythonhosted.org/packages/df/56/b8663d7520671b4398b9d97e1ed9f583d4afcbefbda3c6188325e8c297bd/pillow-10.4.0-cp310-cp310-win32.whl", hash = "sha256:bcd5e41a859bf2e84fdc42f4edb7d9aba0a13d29a2abadccafad99de3feff984", size = 2235218 }, - { url = "https://files.pythonhosted.org/packages/f4/72/0203e94a91ddb4a9d5238434ae6c1ca10e610e8487036132ea9bf806ca2a/pillow-10.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:ecd85a8d3e79cd7158dec1c9e5808e821feea088e2f69a974db5edf84dc53141", size = 2554487 }, - { url = "https://files.pythonhosted.org/packages/bd/52/7e7e93d7a6e4290543f17dc6f7d3af4bd0b3dd9926e2e8a35ac2282bc5f4/pillow-10.4.0-cp310-cp310-win_arm64.whl", hash = "sha256:ff337c552345e95702c5fde3158acb0625111017d0e5f24bf3acdb9cc16b90d1", size = 2243219 }, - { url = "https://files.pythonhosted.org/packages/a7/62/c9449f9c3043c37f73e7487ec4ef0c03eb9c9afc91a92b977a67b3c0bbc5/pillow-10.4.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c", size = 3509265 }, - { url = "https://files.pythonhosted.org/packages/f4/5f/491dafc7bbf5a3cc1845dc0430872e8096eb9e2b6f8161509d124594ec2d/pillow-10.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be", size = 3375655 }, - { url = "https://files.pythonhosted.org/packages/73/d5/c4011a76f4207a3c151134cd22a1415741e42fa5ddecec7c0182887deb3d/pillow-10.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3", size = 4340304 }, - { url = "https://files.pythonhosted.org/packages/ac/10/c67e20445a707f7a610699bba4fe050583b688d8cd2d202572b257f46600/pillow-10.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6", size = 4452804 }, - { url = "https://files.pythonhosted.org/packages/a9/83/6523837906d1da2b269dee787e31df3b0acb12e3d08f024965a3e7f64665/pillow-10.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe", size = 4365126 }, - { url = "https://files.pythonhosted.org/packages/ba/e5/8c68ff608a4203085158cff5cc2a3c534ec384536d9438c405ed6370d080/pillow-10.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319", size = 4533541 }, - { url = "https://files.pythonhosted.org/packages/f4/7c/01b8dbdca5bc6785573f4cee96e2358b0918b7b2c7b60d8b6f3abf87a070/pillow-10.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d", size = 4471616 }, - { url = "https://files.pythonhosted.org/packages/c8/57/2899b82394a35a0fbfd352e290945440e3b3785655a03365c0ca8279f351/pillow-10.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696", size = 4600802 }, - { url = "https://files.pythonhosted.org/packages/4d/d7/a44f193d4c26e58ee5d2d9db3d4854b2cfb5b5e08d360a5e03fe987c0086/pillow-10.4.0-cp311-cp311-win32.whl", hash = "sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496", size = 2235213 }, - { url = "https://files.pythonhosted.org/packages/c1/d0/5866318eec2b801cdb8c82abf190c8343d8a1cd8bf5a0c17444a6f268291/pillow-10.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91", size = 2554498 }, - { url = "https://files.pythonhosted.org/packages/d4/c8/310ac16ac2b97e902d9eb438688de0d961660a87703ad1561fd3dfbd2aa0/pillow-10.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22", size = 2243219 }, - { url = "https://files.pythonhosted.org/packages/05/cb/0353013dc30c02a8be34eb91d25e4e4cf594b59e5a55ea1128fde1e5f8ea/pillow-10.4.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94", size = 3509350 }, - { url = "https://files.pythonhosted.org/packages/e7/cf/5c558a0f247e0bf9cec92bff9b46ae6474dd736f6d906315e60e4075f737/pillow-10.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597", size = 3374980 }, - { url = "https://files.pythonhosted.org/packages/84/48/6e394b86369a4eb68b8a1382c78dc092245af517385c086c5094e3b34428/pillow-10.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80", size = 4343799 }, - { url = "https://files.pythonhosted.org/packages/3b/f3/a8c6c11fa84b59b9df0cd5694492da8c039a24cd159f0f6918690105c3be/pillow-10.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca", size = 4459973 }, - { url = "https://files.pythonhosted.org/packages/7d/1b/c14b4197b80150fb64453585247e6fb2e1d93761fa0fa9cf63b102fde822/pillow-10.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef", size = 4370054 }, - { url = "https://files.pythonhosted.org/packages/55/77/40daddf677897a923d5d33329acd52a2144d54a9644f2a5422c028c6bf2d/pillow-10.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a", size = 4539484 }, - { url = "https://files.pythonhosted.org/packages/40/54/90de3e4256b1207300fb2b1d7168dd912a2fb4b2401e439ba23c2b2cabde/pillow-10.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b", size = 4477375 }, - { url = "https://files.pythonhosted.org/packages/13/24/1bfba52f44193860918ff7c93d03d95e3f8748ca1de3ceaf11157a14cf16/pillow-10.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9", size = 4608773 }, - { url = "https://files.pythonhosted.org/packages/55/04/5e6de6e6120451ec0c24516c41dbaf80cce1b6451f96561235ef2429da2e/pillow-10.4.0-cp312-cp312-win32.whl", hash = "sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42", size = 2235690 }, - { url = "https://files.pythonhosted.org/packages/74/0a/d4ce3c44bca8635bd29a2eab5aa181b654a734a29b263ca8efe013beea98/pillow-10.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a", size = 2554951 }, - { url = "https://files.pythonhosted.org/packages/b5/ca/184349ee40f2e92439be9b3502ae6cfc43ac4b50bc4fc6b3de7957563894/pillow-10.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9", size = 2243427 }, - { url = "https://files.pythonhosted.org/packages/c3/00/706cebe7c2c12a6318aabe5d354836f54adff7156fd9e1bd6c89f4ba0e98/pillow-10.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3", size = 3525685 }, - { url = "https://files.pythonhosted.org/packages/cf/76/f658cbfa49405e5ecbfb9ba42d07074ad9792031267e782d409fd8fe7c69/pillow-10.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb", size = 3374883 }, - { url = "https://files.pythonhosted.org/packages/46/2b/99c28c4379a85e65378211971c0b430d9c7234b1ec4d59b2668f6299e011/pillow-10.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70", size = 4339837 }, - { url = "https://files.pythonhosted.org/packages/f1/74/b1ec314f624c0c43711fdf0d8076f82d9d802afd58f1d62c2a86878e8615/pillow-10.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be", size = 4455562 }, - { url = "https://files.pythonhosted.org/packages/4a/2a/4b04157cb7b9c74372fa867096a1607e6fedad93a44deeff553ccd307868/pillow-10.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0", size = 4366761 }, - { url = "https://files.pythonhosted.org/packages/ac/7b/8f1d815c1a6a268fe90481232c98dd0e5fa8c75e341a75f060037bd5ceae/pillow-10.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc", size = 4536767 }, - { url = "https://files.pythonhosted.org/packages/e5/77/05fa64d1f45d12c22c314e7b97398ffb28ef2813a485465017b7978b3ce7/pillow-10.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a", size = 4477989 }, - { url = "https://files.pythonhosted.org/packages/12/63/b0397cfc2caae05c3fb2f4ed1b4fc4fc878f0243510a7a6034ca59726494/pillow-10.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309", size = 4610255 }, - { url = "https://files.pythonhosted.org/packages/7b/f9/cfaa5082ca9bc4a6de66ffe1c12c2d90bf09c309a5f52b27759a596900e7/pillow-10.4.0-cp313-cp313-win32.whl", hash = "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060", size = 2235603 }, - { url = "https://files.pythonhosted.org/packages/01/6a/30ff0eef6e0c0e71e55ded56a38d4859bf9d3634a94a88743897b5f96936/pillow-10.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea", size = 2554972 }, - { url = "https://files.pythonhosted.org/packages/48/2c/2e0a52890f269435eee38b21c8218e102c621fe8d8df8b9dd06fabf879ba/pillow-10.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d", size = 2243375 }, - { url = "https://files.pythonhosted.org/packages/38/30/095d4f55f3a053392f75e2eae45eba3228452783bab3d9a920b951ac495c/pillow-10.4.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5b4815f2e65b30f5fbae9dfffa8636d992d49705723fe86a3661806e069352d4", size = 3493889 }, - { url = "https://files.pythonhosted.org/packages/f3/e8/4ff79788803a5fcd5dc35efdc9386af153569853767bff74540725b45863/pillow-10.4.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8f0aef4ef59694b12cadee839e2ba6afeab89c0f39a3adc02ed51d109117b8da", size = 3346160 }, - { url = "https://files.pythonhosted.org/packages/d7/ac/4184edd511b14f760c73f5bb8a5d6fd85c591c8aff7c2229677a355c4179/pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f4727572e2918acaa9077c919cbbeb73bd2b3ebcfe033b72f858fc9fbef0026", size = 3435020 }, - { url = "https://files.pythonhosted.org/packages/da/21/1749cd09160149c0a246a81d646e05f35041619ce76f6493d6a96e8d1103/pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff25afb18123cea58a591ea0244b92eb1e61a1fd497bf6d6384f09bc3262ec3e", size = 3490539 }, - { url = "https://files.pythonhosted.org/packages/b6/f5/f71fe1888b96083b3f6dfa0709101f61fc9e972c0c8d04e9d93ccef2a045/pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dc3e2db6ba09ffd7d02ae9141cfa0ae23393ee7687248d46a7507b75d610f4f5", size = 3476125 }, - { url = "https://files.pythonhosted.org/packages/96/b9/c0362c54290a31866c3526848583a2f45a535aa9d725fd31e25d318c805f/pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:02a2be69f9c9b8c1e97cf2713e789d4e398c751ecfd9967c18d0ce304efbf885", size = 3579373 }, - { url = "https://files.pythonhosted.org/packages/52/3b/ce7a01026a7cf46e5452afa86f97a5e88ca97f562cafa76570178ab56d8d/pillow-10.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5", size = 2554661 }, + { url = "https://files.pythonhosted.org/packages/0e/69/a31cccd538ca0b5272be2a38347f8839b97a14be104ea08b0db92f749c74/pillow-10.4.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:4d9667937cfa347525b319ae34375c37b9ee6b525440f3ef48542fcf66f2731e", size = 3509271, upload_time = "2024-07-01T09:45:22.07Z" }, + { url = "https://files.pythonhosted.org/packages/9a/9e/4143b907be8ea0bce215f2ae4f7480027473f8b61fcedfda9d851082a5d2/pillow-10.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:543f3dc61c18dafb755773efc89aae60d06b6596a63914107f75459cf984164d", size = 3375658, upload_time = "2024-07-01T09:45:25.292Z" }, + { url = "https://files.pythonhosted.org/packages/8a/25/1fc45761955f9359b1169aa75e241551e74ac01a09f487adaaf4c3472d11/pillow-10.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7928ecbf1ece13956b95d9cbcfc77137652b02763ba384d9ab508099a2eca856", size = 4332075, upload_time = "2024-07-01T09:45:27.94Z" }, + { url = "https://files.pythonhosted.org/packages/5e/dd/425b95d0151e1d6c951f45051112394f130df3da67363b6bc75dc4c27aba/pillow-10.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4d49b85c4348ea0b31ea63bc75a9f3857869174e2bf17e7aba02945cd218e6f", size = 4444808, upload_time = "2024-07-01T09:45:30.305Z" }, + { url = "https://files.pythonhosted.org/packages/b1/84/9a15cc5726cbbfe7f9f90bfb11f5d028586595907cd093815ca6644932e3/pillow-10.4.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:6c762a5b0997f5659a5ef2266abc1d8851ad7749ad9a6a5506eb23d314e4f46b", size = 4356290, upload_time = "2024-07-01T09:45:32.868Z" }, + { url = "https://files.pythonhosted.org/packages/b5/5b/6651c288b08df3b8c1e2f8c1152201e0b25d240e22ddade0f1e242fc9fa0/pillow-10.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a985e028fc183bf12a77a8bbf36318db4238a3ded7fa9df1b9a133f1cb79f8fc", size = 4525163, upload_time = "2024-07-01T09:45:35.279Z" }, + { url = "https://files.pythonhosted.org/packages/07/8b/34854bf11a83c248505c8cb0fcf8d3d0b459a2246c8809b967963b6b12ae/pillow-10.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:812f7342b0eee081eaec84d91423d1b4650bb9828eb53d8511bcef8ce5aecf1e", size = 4463100, upload_time = "2024-07-01T09:45:37.74Z" }, + { url = "https://files.pythonhosted.org/packages/78/63/0632aee4e82476d9cbe5200c0cdf9ba41ee04ed77887432845264d81116d/pillow-10.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ac1452d2fbe4978c2eec89fb5a23b8387aba707ac72810d9490118817d9c0b46", size = 4592880, upload_time = "2024-07-01T09:45:39.89Z" }, + { url = "https://files.pythonhosted.org/packages/df/56/b8663d7520671b4398b9d97e1ed9f583d4afcbefbda3c6188325e8c297bd/pillow-10.4.0-cp310-cp310-win32.whl", hash = "sha256:bcd5e41a859bf2e84fdc42f4edb7d9aba0a13d29a2abadccafad99de3feff984", size = 2235218, upload_time = "2024-07-01T09:45:42.771Z" }, + { url = "https://files.pythonhosted.org/packages/f4/72/0203e94a91ddb4a9d5238434ae6c1ca10e610e8487036132ea9bf806ca2a/pillow-10.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:ecd85a8d3e79cd7158dec1c9e5808e821feea088e2f69a974db5edf84dc53141", size = 2554487, upload_time = "2024-07-01T09:45:45.176Z" }, + { url = "https://files.pythonhosted.org/packages/bd/52/7e7e93d7a6e4290543f17dc6f7d3af4bd0b3dd9926e2e8a35ac2282bc5f4/pillow-10.4.0-cp310-cp310-win_arm64.whl", hash = "sha256:ff337c552345e95702c5fde3158acb0625111017d0e5f24bf3acdb9cc16b90d1", size = 2243219, upload_time = "2024-07-01T09:45:47.274Z" }, + { url = "https://files.pythonhosted.org/packages/a7/62/c9449f9c3043c37f73e7487ec4ef0c03eb9c9afc91a92b977a67b3c0bbc5/pillow-10.4.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c", size = 3509265, upload_time = "2024-07-01T09:45:49.812Z" }, + { url = "https://files.pythonhosted.org/packages/f4/5f/491dafc7bbf5a3cc1845dc0430872e8096eb9e2b6f8161509d124594ec2d/pillow-10.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be", size = 3375655, upload_time = "2024-07-01T09:45:52.462Z" }, + { url = "https://files.pythonhosted.org/packages/73/d5/c4011a76f4207a3c151134cd22a1415741e42fa5ddecec7c0182887deb3d/pillow-10.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3", size = 4340304, upload_time = "2024-07-01T09:45:55.006Z" }, + { url = "https://files.pythonhosted.org/packages/ac/10/c67e20445a707f7a610699bba4fe050583b688d8cd2d202572b257f46600/pillow-10.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6", size = 4452804, upload_time = "2024-07-01T09:45:58.437Z" }, + { url = "https://files.pythonhosted.org/packages/a9/83/6523837906d1da2b269dee787e31df3b0acb12e3d08f024965a3e7f64665/pillow-10.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe", size = 4365126, upload_time = "2024-07-01T09:46:00.713Z" }, + { url = "https://files.pythonhosted.org/packages/ba/e5/8c68ff608a4203085158cff5cc2a3c534ec384536d9438c405ed6370d080/pillow-10.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319", size = 4533541, upload_time = "2024-07-01T09:46:03.235Z" }, + { url = "https://files.pythonhosted.org/packages/f4/7c/01b8dbdca5bc6785573f4cee96e2358b0918b7b2c7b60d8b6f3abf87a070/pillow-10.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d", size = 4471616, upload_time = "2024-07-01T09:46:05.356Z" }, + { url = "https://files.pythonhosted.org/packages/c8/57/2899b82394a35a0fbfd352e290945440e3b3785655a03365c0ca8279f351/pillow-10.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696", size = 4600802, upload_time = "2024-07-01T09:46:08.145Z" }, + { url = "https://files.pythonhosted.org/packages/4d/d7/a44f193d4c26e58ee5d2d9db3d4854b2cfb5b5e08d360a5e03fe987c0086/pillow-10.4.0-cp311-cp311-win32.whl", hash = "sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496", size = 2235213, upload_time = "2024-07-01T09:46:10.211Z" }, + { url = "https://files.pythonhosted.org/packages/c1/d0/5866318eec2b801cdb8c82abf190c8343d8a1cd8bf5a0c17444a6f268291/pillow-10.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91", size = 2554498, upload_time = "2024-07-01T09:46:12.685Z" }, + { url = "https://files.pythonhosted.org/packages/d4/c8/310ac16ac2b97e902d9eb438688de0d961660a87703ad1561fd3dfbd2aa0/pillow-10.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22", size = 2243219, upload_time = "2024-07-01T09:46:14.83Z" }, + { url = "https://files.pythonhosted.org/packages/05/cb/0353013dc30c02a8be34eb91d25e4e4cf594b59e5a55ea1128fde1e5f8ea/pillow-10.4.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94", size = 3509350, upload_time = "2024-07-01T09:46:17.177Z" }, + { url = "https://files.pythonhosted.org/packages/e7/cf/5c558a0f247e0bf9cec92bff9b46ae6474dd736f6d906315e60e4075f737/pillow-10.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597", size = 3374980, upload_time = "2024-07-01T09:46:19.169Z" }, + { url = "https://files.pythonhosted.org/packages/84/48/6e394b86369a4eb68b8a1382c78dc092245af517385c086c5094e3b34428/pillow-10.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80", size = 4343799, upload_time = "2024-07-01T09:46:21.883Z" }, + { url = "https://files.pythonhosted.org/packages/3b/f3/a8c6c11fa84b59b9df0cd5694492da8c039a24cd159f0f6918690105c3be/pillow-10.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca", size = 4459973, upload_time = "2024-07-01T09:46:24.321Z" }, + { url = "https://files.pythonhosted.org/packages/7d/1b/c14b4197b80150fb64453585247e6fb2e1d93761fa0fa9cf63b102fde822/pillow-10.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef", size = 4370054, upload_time = "2024-07-01T09:46:26.825Z" }, + { url = "https://files.pythonhosted.org/packages/55/77/40daddf677897a923d5d33329acd52a2144d54a9644f2a5422c028c6bf2d/pillow-10.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a", size = 4539484, upload_time = "2024-07-01T09:46:29.355Z" }, + { url = "https://files.pythonhosted.org/packages/40/54/90de3e4256b1207300fb2b1d7168dd912a2fb4b2401e439ba23c2b2cabde/pillow-10.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b", size = 4477375, upload_time = "2024-07-01T09:46:31.756Z" }, + { url = "https://files.pythonhosted.org/packages/13/24/1bfba52f44193860918ff7c93d03d95e3f8748ca1de3ceaf11157a14cf16/pillow-10.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9", size = 4608773, upload_time = "2024-07-01T09:46:33.73Z" }, + { url = "https://files.pythonhosted.org/packages/55/04/5e6de6e6120451ec0c24516c41dbaf80cce1b6451f96561235ef2429da2e/pillow-10.4.0-cp312-cp312-win32.whl", hash = "sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42", size = 2235690, upload_time = "2024-07-01T09:46:36.587Z" }, + { url = "https://files.pythonhosted.org/packages/74/0a/d4ce3c44bca8635bd29a2eab5aa181b654a734a29b263ca8efe013beea98/pillow-10.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a", size = 2554951, upload_time = "2024-07-01T09:46:38.777Z" }, + { url = "https://files.pythonhosted.org/packages/b5/ca/184349ee40f2e92439be9b3502ae6cfc43ac4b50bc4fc6b3de7957563894/pillow-10.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9", size = 2243427, upload_time = "2024-07-01T09:46:43.15Z" }, + { url = "https://files.pythonhosted.org/packages/c3/00/706cebe7c2c12a6318aabe5d354836f54adff7156fd9e1bd6c89f4ba0e98/pillow-10.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3", size = 3525685, upload_time = "2024-07-01T09:46:45.194Z" }, + { url = "https://files.pythonhosted.org/packages/cf/76/f658cbfa49405e5ecbfb9ba42d07074ad9792031267e782d409fd8fe7c69/pillow-10.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb", size = 3374883, upload_time = "2024-07-01T09:46:47.331Z" }, + { url = "https://files.pythonhosted.org/packages/46/2b/99c28c4379a85e65378211971c0b430d9c7234b1ec4d59b2668f6299e011/pillow-10.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70", size = 4339837, upload_time = "2024-07-01T09:46:49.647Z" }, + { url = "https://files.pythonhosted.org/packages/f1/74/b1ec314f624c0c43711fdf0d8076f82d9d802afd58f1d62c2a86878e8615/pillow-10.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be", size = 4455562, upload_time = "2024-07-01T09:46:51.811Z" }, + { url = "https://files.pythonhosted.org/packages/4a/2a/4b04157cb7b9c74372fa867096a1607e6fedad93a44deeff553ccd307868/pillow-10.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0", size = 4366761, upload_time = "2024-07-01T09:46:53.961Z" }, + { url = "https://files.pythonhosted.org/packages/ac/7b/8f1d815c1a6a268fe90481232c98dd0e5fa8c75e341a75f060037bd5ceae/pillow-10.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc", size = 4536767, upload_time = "2024-07-01T09:46:56.664Z" }, + { url = "https://files.pythonhosted.org/packages/e5/77/05fa64d1f45d12c22c314e7b97398ffb28ef2813a485465017b7978b3ce7/pillow-10.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a", size = 4477989, upload_time = "2024-07-01T09:46:58.977Z" }, + { url = "https://files.pythonhosted.org/packages/12/63/b0397cfc2caae05c3fb2f4ed1b4fc4fc878f0243510a7a6034ca59726494/pillow-10.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309", size = 4610255, upload_time = "2024-07-01T09:47:01.189Z" }, + { url = "https://files.pythonhosted.org/packages/7b/f9/cfaa5082ca9bc4a6de66ffe1c12c2d90bf09c309a5f52b27759a596900e7/pillow-10.4.0-cp313-cp313-win32.whl", hash = "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060", size = 2235603, upload_time = "2024-07-01T09:47:03.918Z" }, + { url = "https://files.pythonhosted.org/packages/01/6a/30ff0eef6e0c0e71e55ded56a38d4859bf9d3634a94a88743897b5f96936/pillow-10.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea", size = 2554972, upload_time = "2024-07-01T09:47:06.152Z" }, + { url = "https://files.pythonhosted.org/packages/48/2c/2e0a52890f269435eee38b21c8218e102c621fe8d8df8b9dd06fabf879ba/pillow-10.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d", size = 2243375, upload_time = "2024-07-01T09:47:09.065Z" }, + { url = "https://files.pythonhosted.org/packages/38/30/095d4f55f3a053392f75e2eae45eba3228452783bab3d9a920b951ac495c/pillow-10.4.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5b4815f2e65b30f5fbae9dfffa8636d992d49705723fe86a3661806e069352d4", size = 3493889, upload_time = "2024-07-01T09:48:04.815Z" }, + { url = "https://files.pythonhosted.org/packages/f3/e8/4ff79788803a5fcd5dc35efdc9386af153569853767bff74540725b45863/pillow-10.4.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8f0aef4ef59694b12cadee839e2ba6afeab89c0f39a3adc02ed51d109117b8da", size = 3346160, upload_time = "2024-07-01T09:48:07.206Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ac/4184edd511b14f760c73f5bb8a5d6fd85c591c8aff7c2229677a355c4179/pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f4727572e2918acaa9077c919cbbeb73bd2b3ebcfe033b72f858fc9fbef0026", size = 3435020, upload_time = "2024-07-01T09:48:09.66Z" }, + { url = "https://files.pythonhosted.org/packages/da/21/1749cd09160149c0a246a81d646e05f35041619ce76f6493d6a96e8d1103/pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff25afb18123cea58a591ea0244b92eb1e61a1fd497bf6d6384f09bc3262ec3e", size = 3490539, upload_time = "2024-07-01T09:48:12.529Z" }, + { url = "https://files.pythonhosted.org/packages/b6/f5/f71fe1888b96083b3f6dfa0709101f61fc9e972c0c8d04e9d93ccef2a045/pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dc3e2db6ba09ffd7d02ae9141cfa0ae23393ee7687248d46a7507b75d610f4f5", size = 3476125, upload_time = "2024-07-01T09:48:14.891Z" }, + { url = "https://files.pythonhosted.org/packages/96/b9/c0362c54290a31866c3526848583a2f45a535aa9d725fd31e25d318c805f/pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:02a2be69f9c9b8c1e97cf2713e789d4e398c751ecfd9967c18d0ce304efbf885", size = 3579373, upload_time = "2024-07-01T09:48:17.601Z" }, + { url = "https://files.pythonhosted.org/packages/52/3b/ce7a01026a7cf46e5452afa86f97a5e88ca97f562cafa76570178ab56d8d/pillow-10.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5", size = 2554661, upload_time = "2024-07-01T09:48:20.293Z" }, ] [[package]] name = "platformdirs" -version = "4.1.0" +version = "4.3.7" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/62/d1/7feaaacb1a3faeba96c06e6c5091f90695cc0f94b7e8e1a3a3fe2b33ff9a/platformdirs-4.1.0.tar.gz", hash = "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420", size = 19760 } +sdist = { url = "https://files.pythonhosted.org/packages/b6/2d/7d512a3913d60623e7eb945c6d1b4f0bddf1d0b7ada5225274c87e5b53d1/platformdirs-4.3.7.tar.gz", hash = "sha256:eb437d586b6a0986388f0d6f74aa0cde27b48d0e3d66843640bfb6bdcdb6e351", size = 21291, upload_time = "2025-03-19T20:36:10.989Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/be/53/42fe5eab4a09d251a76d0043e018172db324a23fcdac70f77a551c11f618/platformdirs-4.1.0-py3-none-any.whl", hash = "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380", size = 17420 }, + { url = "https://files.pythonhosted.org/packages/6d/45/59578566b3275b8fd9157885918fcd0c4d74162928a5310926887b856a51/platformdirs-4.3.7-py3-none-any.whl", hash = "sha256:a03875334331946f13c549dbd8f4bac7a13a50a895a0eb1e8c6a8ace80d40a94", size = 18499, upload_time = "2025-03-19T20:36:09.038Z" }, ] [[package]] name = "pluggy" version = "1.5.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 } +sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955, upload_time = "2024-04-20T21:34:42.531Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 }, + { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556, upload_time = "2024-04-20T21:34:40.434Z" }, ] [[package]] @@ -1745,46 +1771,46 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "wcwidth" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e1/c0/5e9c4d2a643a00a6f67578ef35485173de273a4567279e4f0c200c01386b/prettytable-3.9.0.tar.gz", hash = "sha256:f4ed94803c23073a90620b201965e5dc0bccf1760b7a7eaf3158cab8aaffdf34", size = 47874 } +sdist = { url = "https://files.pythonhosted.org/packages/e1/c0/5e9c4d2a643a00a6f67578ef35485173de273a4567279e4f0c200c01386b/prettytable-3.9.0.tar.gz", hash = "sha256:f4ed94803c23073a90620b201965e5dc0bccf1760b7a7eaf3158cab8aaffdf34", size = 47874, upload_time = "2023-09-11T14:04:14.548Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/81/316b6a55a0d1f327d04cc7b0ba9d04058cb62de6c3a4d4b0df280cbe3b0b/prettytable-3.9.0-py3-none-any.whl", hash = "sha256:a71292ab7769a5de274b146b276ce938786f56c31cf7cea88b6f3775d82fe8c8", size = 27772 }, + { url = "https://files.pythonhosted.org/packages/4d/81/316b6a55a0d1f327d04cc7b0ba9d04058cb62de6c3a4d4b0df280cbe3b0b/prettytable-3.9.0-py3-none-any.whl", hash = "sha256:a71292ab7769a5de274b146b276ce938786f56c31cf7cea88b6f3775d82fe8c8", size = 27772, upload_time = "2023-09-11T14:03:45.582Z" }, ] [[package]] name = "protobuf" version = "4.25.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/db/a5/05ea470f4e793c9408bc975ce1c6957447e3134ce7f7a58c13be8b2c216f/protobuf-4.25.2.tar.gz", hash = "sha256:fe599e175cb347efc8ee524bcd4b902d11f7262c0e569ececcb89995c15f0a5e", size = 380282 } +sdist = { url = "https://files.pythonhosted.org/packages/db/a5/05ea470f4e793c9408bc975ce1c6957447e3134ce7f7a58c13be8b2c216f/protobuf-4.25.2.tar.gz", hash = "sha256:fe599e175cb347efc8ee524bcd4b902d11f7262c0e569ececcb89995c15f0a5e", size = 380282, upload_time = "2024-01-10T19:37:42.958Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/36/2f/01f63896ddf22cbb0173ab51f54fde70b0208ca6c2f5e8416950977930e1/protobuf-4.25.2-cp310-abi3-win32.whl", hash = "sha256:b50c949608682b12efb0b2717f53256f03636af5f60ac0c1d900df6213910fd6", size = 392408 }, - { url = "https://files.pythonhosted.org/packages/c1/00/c3ae19cabb36cfabc94ff0b102aac21b471c9f91a1357f8aafffb9efe8e0/protobuf-4.25.2-cp310-abi3-win_amd64.whl", hash = "sha256:8f62574857ee1de9f770baf04dde4165e30b15ad97ba03ceac65f760ff018ac9", size = 413397 }, - { url = "https://files.pythonhosted.org/packages/b3/81/0017aefacf23273d4efd1154ef958a27eed9c177c4cc09d2d4ba398fb47f/protobuf-4.25.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:2db9f8fa64fbdcdc93767d3cf81e0f2aef176284071507e3ede160811502fd3d", size = 394159 }, - { url = "https://files.pythonhosted.org/packages/23/17/405ba44f60a693dfe96c7a18e843707cffa0fcfad80bd8fc4f227f499ea5/protobuf-4.25.2-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:10894a2885b7175d3984f2be8d9850712c57d5e7587a2410720af8be56cdaf62", size = 293698 }, - { url = "https://files.pythonhosted.org/packages/81/9e/63501b8d5b4e40c7260049836bd15ec3270c936e83bc57b85e4603cc212c/protobuf-4.25.2-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:fc381d1dd0516343f1440019cedf08a7405f791cd49eef4ae1ea06520bc1c020", size = 294609 }, - { url = "https://files.pythonhosted.org/packages/ff/52/5d23df1fe3b368133ec3e2436fb3dd4ccedf44c8d5ac7f4a88087c75180b/protobuf-4.25.2-py3-none-any.whl", hash = "sha256:a8b7a98d4ce823303145bf3c1a8bdb0f2f4642a414b196f04ad9853ed0c8f830", size = 156463 }, + { url = "https://files.pythonhosted.org/packages/36/2f/01f63896ddf22cbb0173ab51f54fde70b0208ca6c2f5e8416950977930e1/protobuf-4.25.2-cp310-abi3-win32.whl", hash = "sha256:b50c949608682b12efb0b2717f53256f03636af5f60ac0c1d900df6213910fd6", size = 392408, upload_time = "2024-01-10T19:37:23.466Z" }, + { url = "https://files.pythonhosted.org/packages/c1/00/c3ae19cabb36cfabc94ff0b102aac21b471c9f91a1357f8aafffb9efe8e0/protobuf-4.25.2-cp310-abi3-win_amd64.whl", hash = "sha256:8f62574857ee1de9f770baf04dde4165e30b15ad97ba03ceac65f760ff018ac9", size = 413397, upload_time = "2024-01-10T19:37:26.321Z" }, + { url = "https://files.pythonhosted.org/packages/b3/81/0017aefacf23273d4efd1154ef958a27eed9c177c4cc09d2d4ba398fb47f/protobuf-4.25.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:2db9f8fa64fbdcdc93767d3cf81e0f2aef176284071507e3ede160811502fd3d", size = 394159, upload_time = "2024-01-10T19:37:28.932Z" }, + { url = "https://files.pythonhosted.org/packages/23/17/405ba44f60a693dfe96c7a18e843707cffa0fcfad80bd8fc4f227f499ea5/protobuf-4.25.2-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:10894a2885b7175d3984f2be8d9850712c57d5e7587a2410720af8be56cdaf62", size = 293698, upload_time = "2024-01-10T19:37:30.666Z" }, + { url = "https://files.pythonhosted.org/packages/81/9e/63501b8d5b4e40c7260049836bd15ec3270c936e83bc57b85e4603cc212c/protobuf-4.25.2-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:fc381d1dd0516343f1440019cedf08a7405f791cd49eef4ae1ea06520bc1c020", size = 294609, upload_time = "2024-01-10T19:37:32.777Z" }, + { url = "https://files.pythonhosted.org/packages/ff/52/5d23df1fe3b368133ec3e2436fb3dd4ccedf44c8d5ac7f4a88087c75180b/protobuf-4.25.2-py3-none-any.whl", hash = "sha256:a8b7a98d4ce823303145bf3c1a8bdb0f2f4642a414b196f04ad9853ed0c8f830", size = 156463, upload_time = "2024-01-10T19:37:41.24Z" }, ] [[package]] name = "psutil" version = "5.9.7" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a0/d0/c9ae661a302931735237791f04cb7086ac244377f78692ba3b3eae3a9619/psutil-5.9.7.tar.gz", hash = "sha256:3f02134e82cfb5d089fddf20bb2e03fd5cd52395321d1c8458a9e58500ff417c", size = 498429 } +sdist = { url = "https://files.pythonhosted.org/packages/a0/d0/c9ae661a302931735237791f04cb7086ac244377f78692ba3b3eae3a9619/psutil-5.9.7.tar.gz", hash = "sha256:3f02134e82cfb5d089fddf20bb2e03fd5cd52395321d1c8458a9e58500ff417c", size = 498429, upload_time = "2023-12-17T11:25:21.22Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6c/63/86a4ccc640b4ee1193800f57bbd20b766853c0cdbdbb248a27cdfafe6cbf/psutil-5.9.7-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ea36cc62e69a13ec52b2f625c27527f6e4479bca2b340b7a452af55b34fcbe2e", size = 245972 }, - { url = "https://files.pythonhosted.org/packages/58/80/cc6666b3968646f2d94de66bbc63d701d501f4aa04de43dd7d1f5dc477dd/psutil-5.9.7-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1132704b876e58d277168cd729d64750633d5ff0183acf5b3c986b8466cd0284", size = 282514 }, - { url = "https://files.pythonhosted.org/packages/be/fa/f1f626620e3b47e6237dcc64cb8cc1472f139e99422e5b9fa5bbcf457f48/psutil-5.9.7-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe8b7f07948f1304497ce4f4684881250cd859b16d06a1dc4d7941eeb6233bfe", size = 285469 }, - { url = "https://files.pythonhosted.org/packages/7c/b8/dc6ebfc030b47cccc5f5229eeb15e64142b4782796c3ce169ccd60b4d511/psutil-5.9.7-cp37-abi3-win32.whl", hash = "sha256:c727ca5a9b2dd5193b8644b9f0c883d54f1248310023b5ad3e92036c5e2ada68", size = 248406 }, - { url = "https://files.pythonhosted.org/packages/50/28/92b74d95dd991c837813ffac0c79a581a3d129eb0fa7c1dd616d9901e0f3/psutil-5.9.7-cp37-abi3-win_amd64.whl", hash = "sha256:f37f87e4d73b79e6c5e749440c3113b81d1ee7d26f21c19c47371ddea834f414", size = 252245 }, - { url = "https://files.pythonhosted.org/packages/ba/8a/000d0e80156f0b96c55bda6c60f5ed6543d7b5e893ccab83117e50de1400/psutil-5.9.7-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:032f4f2c909818c86cea4fe2cc407f1c0f0cde8e6c6d702b28b8ce0c0d143340", size = 246739 }, + { url = "https://files.pythonhosted.org/packages/6c/63/86a4ccc640b4ee1193800f57bbd20b766853c0cdbdbb248a27cdfafe6cbf/psutil-5.9.7-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ea36cc62e69a13ec52b2f625c27527f6e4479bca2b340b7a452af55b34fcbe2e", size = 245972, upload_time = "2023-12-17T11:25:48.202Z" }, + { url = "https://files.pythonhosted.org/packages/58/80/cc6666b3968646f2d94de66bbc63d701d501f4aa04de43dd7d1f5dc477dd/psutil-5.9.7-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1132704b876e58d277168cd729d64750633d5ff0183acf5b3c986b8466cd0284", size = 282514, upload_time = "2023-12-17T11:25:51.371Z" }, + { url = "https://files.pythonhosted.org/packages/be/fa/f1f626620e3b47e6237dcc64cb8cc1472f139e99422e5b9fa5bbcf457f48/psutil-5.9.7-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe8b7f07948f1304497ce4f4684881250cd859b16d06a1dc4d7941eeb6233bfe", size = 285469, upload_time = "2023-12-17T11:25:54.25Z" }, + { url = "https://files.pythonhosted.org/packages/7c/b8/dc6ebfc030b47cccc5f5229eeb15e64142b4782796c3ce169ccd60b4d511/psutil-5.9.7-cp37-abi3-win32.whl", hash = "sha256:c727ca5a9b2dd5193b8644b9f0c883d54f1248310023b5ad3e92036c5e2ada68", size = 248406, upload_time = "2023-12-17T12:38:50.326Z" }, + { url = "https://files.pythonhosted.org/packages/50/28/92b74d95dd991c837813ffac0c79a581a3d129eb0fa7c1dd616d9901e0f3/psutil-5.9.7-cp37-abi3-win_amd64.whl", hash = "sha256:f37f87e4d73b79e6c5e749440c3113b81d1ee7d26f21c19c47371ddea834f414", size = 252245, upload_time = "2023-12-17T12:39:00.686Z" }, + { url = "https://files.pythonhosted.org/packages/ba/8a/000d0e80156f0b96c55bda6c60f5ed6543d7b5e893ccab83117e50de1400/psutil-5.9.7-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:032f4f2c909818c86cea4fe2cc407f1c0f0cde8e6c6d702b28b8ce0c0d143340", size = 246739, upload_time = "2023-12-17T11:25:57.305Z" }, ] [[package]] name = "pycparser" version = "2.21" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5e/0b/95d387f5f4433cb0f53ff7ad859bd2c6051051cebbb564f139a999ab46de/pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206", size = 170877 } +sdist = { url = "https://files.pythonhosted.org/packages/5e/0b/95d387f5f4433cb0f53ff7ad859bd2c6051051cebbb564f139a999ab46de/pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206", size = 170877, upload_time = "2021-11-06T12:48:46.095Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/62/d5/5f610ebe421e85889f2e55e33b7f9a6795bd982198517d912eb1c76e1a53/pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", size = 118697 }, + { url = "https://files.pythonhosted.org/packages/62/d5/5f610ebe421e85889f2e55e33b7f9a6795bd982198517d912eb1c76e1a53/pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", size = 118697, upload_time = "2021-11-06T12:50:13.61Z" }, ] [[package]] @@ -1797,9 +1823,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/10/2e/ca897f093ee6c5f3b0bee123ee4465c50e75431c3d5b6a3b44a47134e891/pydantic-2.11.3.tar.gz", hash = "sha256:7471657138c16adad9322fe3070c0116dd6c3ad8d649300e3cbdfe91f4db4ec3", size = 785513 } +sdist = { url = "https://files.pythonhosted.org/packages/10/2e/ca897f093ee6c5f3b0bee123ee4465c50e75431c3d5b6a3b44a47134e891/pydantic-2.11.3.tar.gz", hash = "sha256:7471657138c16adad9322fe3070c0116dd6c3ad8d649300e3cbdfe91f4db4ec3", size = 785513, upload_time = "2025-04-08T13:27:06.399Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b0/1d/407b29780a289868ed696d1616f4aad49d6388e5a77f567dcd2629dcd7b8/pydantic-2.11.3-py3-none-any.whl", hash = "sha256:a082753436a07f9ba1289c6ffa01cd93db3548776088aa917cc43b63f68fa60f", size = 443591 }, + { url = "https://files.pythonhosted.org/packages/b0/1d/407b29780a289868ed696d1616f4aad49d6388e5a77f567dcd2629dcd7b8/pydantic-2.11.3-py3-none-any.whl", hash = "sha256:a082753436a07f9ba1289c6ffa01cd93db3548776088aa917cc43b63f68fa60f", size = 443591, upload_time = "2025-04-08T13:27:03.789Z" }, ] [[package]] @@ -1809,124 +1835,125 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/17/19/ed6a078a5287aea7922de6841ef4c06157931622c89c2a47940837b5eecd/pydantic_core-2.33.1.tar.gz", hash = "sha256:bcc9c6fdb0ced789245b02b7d6603e17d1563064ddcfc36f046b61c0c05dd9df", size = 434395 } +sdist = { url = "https://files.pythonhosted.org/packages/17/19/ed6a078a5287aea7922de6841ef4c06157931622c89c2a47940837b5eecd/pydantic_core-2.33.1.tar.gz", hash = "sha256:bcc9c6fdb0ced789245b02b7d6603e17d1563064ddcfc36f046b61c0c05dd9df", size = 434395, upload_time = "2025-04-02T09:49:41.8Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/38/ea/5f572806ab4d4223d11551af814d243b0e3e02cc6913def4d1fe4a5ca41c/pydantic_core-2.33.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3077cfdb6125cc8dab61b155fdd714663e401f0e6883f9632118ec12cf42df26", size = 2044021 }, - { url = "https://files.pythonhosted.org/packages/8c/d1/f86cc96d2aa80e3881140d16d12ef2b491223f90b28b9a911346c04ac359/pydantic_core-2.33.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8ffab8b2908d152e74862d276cf5017c81a2f3719f14e8e3e8d6b83fda863927", size = 1861742 }, - { url = "https://files.pythonhosted.org/packages/37/08/fbd2cd1e9fc735a0df0142fac41c114ad9602d1c004aea340169ae90973b/pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5183e4f6a2d468787243ebcd70cf4098c247e60d73fb7d68d5bc1e1beaa0c4db", size = 1910414 }, - { url = "https://files.pythonhosted.org/packages/7f/73/3ac217751decbf8d6cb9443cec9b9eb0130eeada6ae56403e11b486e277e/pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:398a38d323f37714023be1e0285765f0a27243a8b1506b7b7de87b647b517e48", size = 1996848 }, - { url = "https://files.pythonhosted.org/packages/9a/f5/5c26b265cdcff2661e2520d2d1e9db72d117ea00eb41e00a76efe68cb009/pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87d3776f0001b43acebfa86f8c64019c043b55cc5a6a2e313d728b5c95b46969", size = 2141055 }, - { url = "https://files.pythonhosted.org/packages/5d/14/a9c3cee817ef2f8347c5ce0713e91867a0dceceefcb2973942855c917379/pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c566dd9c5f63d22226409553531f89de0cac55397f2ab8d97d6f06cfce6d947e", size = 2753806 }, - { url = "https://files.pythonhosted.org/packages/f2/68/866ce83a51dd37e7c604ce0050ff6ad26de65a7799df89f4db87dd93d1d6/pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0d5f3acc81452c56895e90643a625302bd6be351e7010664151cc55b7b97f89", size = 2007777 }, - { url = "https://files.pythonhosted.org/packages/b6/a8/36771f4404bb3e49bd6d4344da4dede0bf89cc1e01f3b723c47248a3761c/pydantic_core-2.33.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d3a07fadec2a13274a8d861d3d37c61e97a816beae717efccaa4b36dfcaadcde", size = 2122803 }, - { url = "https://files.pythonhosted.org/packages/18/9c/730a09b2694aa89360d20756369822d98dc2f31b717c21df33b64ffd1f50/pydantic_core-2.33.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f99aeda58dce827f76963ee87a0ebe75e648c72ff9ba1174a253f6744f518f65", size = 2086755 }, - { url = "https://files.pythonhosted.org/packages/54/8e/2dccd89602b5ec31d1c58138d02340ecb2ebb8c2cac3cc66b65ce3edb6ce/pydantic_core-2.33.1-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:902dbc832141aa0ec374f4310f1e4e7febeebc3256f00dc359a9ac3f264a45dc", size = 2257358 }, - { url = "https://files.pythonhosted.org/packages/d1/9c/126e4ac1bfad8a95a9837acdd0963695d69264179ba4ede8b8c40d741702/pydantic_core-2.33.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fe44d56aa0b00d66640aa84a3cbe80b7a3ccdc6f0b1ca71090696a6d4777c091", size = 2257916 }, - { url = "https://files.pythonhosted.org/packages/7d/ba/91eea2047e681a6853c81c20aeca9dcdaa5402ccb7404a2097c2adf9d038/pydantic_core-2.33.1-cp310-cp310-win32.whl", hash = "sha256:ed3eb16d51257c763539bde21e011092f127a2202692afaeaccb50db55a31383", size = 1923823 }, - { url = "https://files.pythonhosted.org/packages/94/c0/fcdf739bf60d836a38811476f6ecd50374880b01e3014318b6e809ddfd52/pydantic_core-2.33.1-cp310-cp310-win_amd64.whl", hash = "sha256:694ad99a7f6718c1a498dc170ca430687a39894a60327f548e02a9c7ee4b6504", size = 1952494 }, - { url = "https://files.pythonhosted.org/packages/d6/7f/c6298830cb780c46b4f46bb24298d01019ffa4d21769f39b908cd14bbd50/pydantic_core-2.33.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6e966fc3caaf9f1d96b349b0341c70c8d6573bf1bac7261f7b0ba88f96c56c24", size = 2044224 }, - { url = "https://files.pythonhosted.org/packages/a8/65/6ab3a536776cad5343f625245bd38165d6663256ad43f3a200e5936afd6c/pydantic_core-2.33.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bfd0adeee563d59c598ceabddf2c92eec77abcb3f4a391b19aa7366170bd9e30", size = 1858845 }, - { url = "https://files.pythonhosted.org/packages/e9/15/9a22fd26ba5ee8c669d4b8c9c244238e940cd5d818649603ca81d1c69861/pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91815221101ad3c6b507804178a7bb5cb7b2ead9ecd600041669c8d805ebd595", size = 1910029 }, - { url = "https://files.pythonhosted.org/packages/d5/33/8cb1a62818974045086f55f604044bf35b9342900318f9a2a029a1bec460/pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9fea9c1869bb4742d174a57b4700c6dadea951df8b06de40c2fedb4f02931c2e", size = 1997784 }, - { url = "https://files.pythonhosted.org/packages/c0/ca/49958e4df7715c71773e1ea5be1c74544923d10319173264e6db122543f9/pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d20eb4861329bb2484c021b9d9a977566ab16d84000a57e28061151c62b349a", size = 2141075 }, - { url = "https://files.pythonhosted.org/packages/7b/a6/0b3a167a9773c79ba834b959b4e18c3ae9216b8319bd8422792abc8a41b1/pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb935c5591573ae3201640579f30128ccc10739b45663f93c06796854405505", size = 2745849 }, - { url = "https://files.pythonhosted.org/packages/0b/60/516484135173aa9e5861d7a0663dce82e4746d2e7f803627d8c25dfa5578/pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c964fd24e6166420d18fb53996d8c9fd6eac9bf5ae3ec3d03015be4414ce497f", size = 2005794 }, - { url = "https://files.pythonhosted.org/packages/86/70/05b1eb77459ad47de00cf78ee003016da0cedf8b9170260488d7c21e9181/pydantic_core-2.33.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:681d65e9011f7392db5aa002b7423cc442d6a673c635668c227c6c8d0e5a4f77", size = 2123237 }, - { url = "https://files.pythonhosted.org/packages/c7/57/12667a1409c04ae7dc95d3b43158948eb0368e9c790be8b095cb60611459/pydantic_core-2.33.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e100c52f7355a48413e2999bfb4e139d2977a904495441b374f3d4fb4a170961", size = 2086351 }, - { url = "https://files.pythonhosted.org/packages/57/61/cc6d1d1c1664b58fdd6ecc64c84366c34ec9b606aeb66cafab6f4088974c/pydantic_core-2.33.1-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:048831bd363490be79acdd3232f74a0e9951b11b2b4cc058aeb72b22fdc3abe1", size = 2258914 }, - { url = "https://files.pythonhosted.org/packages/d1/0a/edb137176a1f5419b2ddee8bde6a0a548cfa3c74f657f63e56232df8de88/pydantic_core-2.33.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bdc84017d28459c00db6f918a7272a5190bec3090058334e43a76afb279eac7c", size = 2257385 }, - { url = "https://files.pythonhosted.org/packages/26/3c/48ca982d50e4b0e1d9954919c887bdc1c2b462801bf408613ccc641b3daa/pydantic_core-2.33.1-cp311-cp311-win32.whl", hash = "sha256:32cd11c5914d1179df70406427097c7dcde19fddf1418c787540f4b730289896", size = 1923765 }, - { url = "https://files.pythonhosted.org/packages/33/cd/7ab70b99e5e21559f5de38a0928ea84e6f23fdef2b0d16a6feaf942b003c/pydantic_core-2.33.1-cp311-cp311-win_amd64.whl", hash = "sha256:2ea62419ba8c397e7da28a9170a16219d310d2cf4970dbc65c32faf20d828c83", size = 1950688 }, - { url = "https://files.pythonhosted.org/packages/4b/ae/db1fc237b82e2cacd379f63e3335748ab88b5adde98bf7544a1b1bd10a84/pydantic_core-2.33.1-cp311-cp311-win_arm64.whl", hash = "sha256:fc903512177361e868bc1f5b80ac8c8a6e05fcdd574a5fb5ffeac5a9982b9e89", size = 1908185 }, - { url = "https://files.pythonhosted.org/packages/c8/ce/3cb22b07c29938f97ff5f5bb27521f95e2ebec399b882392deb68d6c440e/pydantic_core-2.33.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:1293d7febb995e9d3ec3ea09caf1a26214eec45b0f29f6074abb004723fc1de8", size = 2026640 }, - { url = "https://files.pythonhosted.org/packages/19/78/f381d643b12378fee782a72126ec5d793081ef03791c28a0fd542a5bee64/pydantic_core-2.33.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:99b56acd433386c8f20be5c4000786d1e7ca0523c8eefc995d14d79c7a081498", size = 1852649 }, - { url = "https://files.pythonhosted.org/packages/9d/2b/98a37b80b15aac9eb2c6cfc6dbd35e5058a352891c5cce3a8472d77665a6/pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35a5ec3fa8c2fe6c53e1b2ccc2454398f95d5393ab398478f53e1afbbeb4d939", size = 1892472 }, - { url = "https://files.pythonhosted.org/packages/4e/d4/3c59514e0f55a161004792b9ff3039da52448f43f5834f905abef9db6e4a/pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b172f7b9d2f3abc0efd12e3386f7e48b576ef309544ac3a63e5e9cdd2e24585d", size = 1977509 }, - { url = "https://files.pythonhosted.org/packages/a9/b6/c2c7946ef70576f79a25db59a576bce088bdc5952d1b93c9789b091df716/pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9097b9f17f91eea659b9ec58148c0747ec354a42f7389b9d50701610d86f812e", size = 2128702 }, - { url = "https://files.pythonhosted.org/packages/88/fe/65a880f81e3f2a974312b61f82a03d85528f89a010ce21ad92f109d94deb/pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cc77ec5b7e2118b152b0d886c7514a4653bcb58c6b1d760134a9fab915f777b3", size = 2679428 }, - { url = "https://files.pythonhosted.org/packages/6f/ff/4459e4146afd0462fb483bb98aa2436d69c484737feaceba1341615fb0ac/pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3d15245b08fa4a84cefc6c9222e6f37c98111c8679fbd94aa145f9a0ae23d", size = 2008753 }, - { url = "https://files.pythonhosted.org/packages/7c/76/1c42e384e8d78452ededac8b583fe2550c84abfef83a0552e0e7478ccbc3/pydantic_core-2.33.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ef99779001d7ac2e2461d8ab55d3373fe7315caefdbecd8ced75304ae5a6fc6b", size = 2114849 }, - { url = "https://files.pythonhosted.org/packages/00/72/7d0cf05095c15f7ffe0eb78914b166d591c0eed72f294da68378da205101/pydantic_core-2.33.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:fc6bf8869e193855e8d91d91f6bf59699a5cdfaa47a404e278e776dd7f168b39", size = 2069541 }, - { url = "https://files.pythonhosted.org/packages/b3/69/94a514066bb7d8be499aa764926937409d2389c09be0b5107a970286ef81/pydantic_core-2.33.1-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:b1caa0bc2741b043db7823843e1bde8aaa58a55a58fda06083b0569f8b45693a", size = 2239225 }, - { url = "https://files.pythonhosted.org/packages/84/b0/e390071eadb44b41f4f54c3cef64d8bf5f9612c92686c9299eaa09e267e2/pydantic_core-2.33.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ec259f62538e8bf364903a7d0d0239447059f9434b284f5536e8402b7dd198db", size = 2248373 }, - { url = "https://files.pythonhosted.org/packages/d6/b2/288b3579ffc07e92af66e2f1a11be3b056fe1214aab314748461f21a31c3/pydantic_core-2.33.1-cp312-cp312-win32.whl", hash = "sha256:e14f369c98a7c15772b9da98987f58e2b509a93235582838bd0d1d8c08b68fda", size = 1907034 }, - { url = "https://files.pythonhosted.org/packages/02/28/58442ad1c22b5b6742b992ba9518420235adced665513868f99a1c2638a5/pydantic_core-2.33.1-cp312-cp312-win_amd64.whl", hash = "sha256:1c607801d85e2e123357b3893f82c97a42856192997b95b4d8325deb1cd0c5f4", size = 1956848 }, - { url = "https://files.pythonhosted.org/packages/a1/eb/f54809b51c7e2a1d9f439f158b8dd94359321abcc98767e16fc48ae5a77e/pydantic_core-2.33.1-cp312-cp312-win_arm64.whl", hash = "sha256:8d13f0276806ee722e70a1c93da19748594f19ac4299c7e41237fc791d1861ea", size = 1903986 }, - { url = "https://files.pythonhosted.org/packages/7a/24/eed3466a4308d79155f1cdd5c7432c80ddcc4530ba8623b79d5ced021641/pydantic_core-2.33.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:70af6a21237b53d1fe7b9325b20e65cbf2f0a848cf77bed492b029139701e66a", size = 2033551 }, - { url = "https://files.pythonhosted.org/packages/ab/14/df54b1a0bc9b6ded9b758b73139d2c11b4e8eb43e8ab9c5847c0a2913ada/pydantic_core-2.33.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:282b3fe1bbbe5ae35224a0dbd05aed9ccabccd241e8e6b60370484234b456266", size = 1852785 }, - { url = "https://files.pythonhosted.org/packages/fa/96/e275f15ff3d34bb04b0125d9bc8848bf69f25d784d92a63676112451bfb9/pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b315e596282bbb5822d0c7ee9d255595bd7506d1cb20c2911a4da0b970187d3", size = 1897758 }, - { url = "https://files.pythonhosted.org/packages/b7/d8/96bc536e975b69e3a924b507d2a19aedbf50b24e08c80fb00e35f9baaed8/pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1dfae24cf9921875ca0ca6a8ecb4bb2f13c855794ed0d468d6abbec6e6dcd44a", size = 1986109 }, - { url = "https://files.pythonhosted.org/packages/90/72/ab58e43ce7e900b88cb571ed057b2fcd0e95b708a2e0bed475b10130393e/pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6dd8ecfde08d8bfadaea669e83c63939af76f4cf5538a72597016edfa3fad516", size = 2129159 }, - { url = "https://files.pythonhosted.org/packages/dc/3f/52d85781406886c6870ac995ec0ba7ccc028b530b0798c9080531b409fdb/pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f593494876eae852dc98c43c6f260f45abdbfeec9e4324e31a481d948214764", size = 2680222 }, - { url = "https://files.pythonhosted.org/packages/f4/56/6e2ef42f363a0eec0fd92f74a91e0ac48cd2e49b695aac1509ad81eee86a/pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:948b73114f47fd7016088e5186d13faf5e1b2fe83f5e320e371f035557fd264d", size = 2006980 }, - { url = "https://files.pythonhosted.org/packages/4c/c0/604536c4379cc78359f9ee0aa319f4aedf6b652ec2854953f5a14fc38c5a/pydantic_core-2.33.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e11f3864eb516af21b01e25fac915a82e9ddad3bb0fb9e95a246067398b435a4", size = 2120840 }, - { url = "https://files.pythonhosted.org/packages/1f/46/9eb764814f508f0edfb291a0f75d10854d78113fa13900ce13729aaec3ae/pydantic_core-2.33.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:549150be302428b56fdad0c23c2741dcdb5572413776826c965619a25d9c6bde", size = 2072518 }, - { url = "https://files.pythonhosted.org/packages/42/e3/fb6b2a732b82d1666fa6bf53e3627867ea3131c5f39f98ce92141e3e3dc1/pydantic_core-2.33.1-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:495bc156026efafd9ef2d82372bd38afce78ddd82bf28ef5276c469e57c0c83e", size = 2248025 }, - { url = "https://files.pythonhosted.org/packages/5c/9d/fbe8fe9d1aa4dac88723f10a921bc7418bd3378a567cb5e21193a3c48b43/pydantic_core-2.33.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ec79de2a8680b1a67a07490bddf9636d5c2fab609ba8c57597e855fa5fa4dacd", size = 2254991 }, - { url = "https://files.pythonhosted.org/packages/aa/99/07e2237b8a66438d9b26482332cda99a9acccb58d284af7bc7c946a42fd3/pydantic_core-2.33.1-cp313-cp313-win32.whl", hash = "sha256:ee12a7be1742f81b8a65b36c6921022301d466b82d80315d215c4c691724986f", size = 1915262 }, - { url = "https://files.pythonhosted.org/packages/8a/f4/e457a7849beeed1e5defbcf5051c6f7b3c91a0624dd31543a64fc9adcf52/pydantic_core-2.33.1-cp313-cp313-win_amd64.whl", hash = "sha256:ede9b407e39949d2afc46385ce6bd6e11588660c26f80576c11c958e6647bc40", size = 1956626 }, - { url = "https://files.pythonhosted.org/packages/20/d0/e8d567a7cff7b04e017ae164d98011f1e1894269fe8e90ea187a3cbfb562/pydantic_core-2.33.1-cp313-cp313-win_arm64.whl", hash = "sha256:aa687a23d4b7871a00e03ca96a09cad0f28f443690d300500603bd0adba4b523", size = 1909590 }, - { url = "https://files.pythonhosted.org/packages/ef/fd/24ea4302d7a527d672c5be06e17df16aabfb4e9fdc6e0b345c21580f3d2a/pydantic_core-2.33.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:401d7b76e1000d0dd5538e6381d28febdcacb097c8d340dde7d7fc6e13e9f95d", size = 1812963 }, - { url = "https://files.pythonhosted.org/packages/5f/95/4fbc2ecdeb5c1c53f1175a32d870250194eb2fdf6291b795ab08c8646d5d/pydantic_core-2.33.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7aeb055a42d734c0255c9e489ac67e75397d59c6fbe60d155851e9782f276a9c", size = 1986896 }, - { url = "https://files.pythonhosted.org/packages/71/ae/fe31e7f4a62431222d8f65a3bd02e3fa7e6026d154a00818e6d30520ea77/pydantic_core-2.33.1-cp313-cp313t-win_amd64.whl", hash = "sha256:338ea9b73e6e109f15ab439e62cb3b78aa752c7fd9536794112e14bee02c8d18", size = 1931810 }, - { url = "https://files.pythonhosted.org/packages/9c/c7/8b311d5adb0fe00a93ee9b4e92a02b0ec08510e9838885ef781ccbb20604/pydantic_core-2.33.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c834f54f8f4640fd7e4b193f80eb25a0602bba9e19b3cd2fc7ffe8199f5ae02", size = 2041659 }, - { url = "https://files.pythonhosted.org/packages/8a/d6/4f58d32066a9e26530daaf9adc6664b01875ae0691570094968aaa7b8fcc/pydantic_core-2.33.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:049e0de24cf23766f12cc5cc71d8abc07d4a9deb9061b334b62093dedc7cb068", size = 1873294 }, - { url = "https://files.pythonhosted.org/packages/f7/3f/53cc9c45d9229da427909c751f8ed2bf422414f7664ea4dde2d004f596ba/pydantic_core-2.33.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a28239037b3d6f16916a4c831a5a0eadf856bdd6d2e92c10a0da3a59eadcf3e", size = 1903771 }, - { url = "https://files.pythonhosted.org/packages/f0/49/bf0783279ce674eb9903fb9ae43f6c614cb2f1c4951370258823f795368b/pydantic_core-2.33.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d3da303ab5f378a268fa7d45f37d7d85c3ec19769f28d2cc0c61826a8de21fe", size = 2083558 }, - { url = "https://files.pythonhosted.org/packages/9c/5b/0d998367687f986c7d8484a2c476d30f07bf5b8b1477649a6092bd4c540e/pydantic_core-2.33.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:25626fb37b3c543818c14821afe0fd3830bc327a43953bc88db924b68c5723f1", size = 2118038 }, - { url = "https://files.pythonhosted.org/packages/b3/33/039287d410230ee125daee57373ac01940d3030d18dba1c29cd3089dc3ca/pydantic_core-2.33.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3ab2d36e20fbfcce8f02d73c33a8a7362980cff717926bbae030b93ae46b56c7", size = 2079315 }, - { url = "https://files.pythonhosted.org/packages/1f/85/6d8b2646d99c062d7da2d0ab2faeb0d6ca9cca4c02da6076376042a20da3/pydantic_core-2.33.1-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:2f9284e11c751b003fd4215ad92d325d92c9cb19ee6729ebd87e3250072cdcde", size = 2249063 }, - { url = "https://files.pythonhosted.org/packages/17/d7/c37d208d5738f7b9ad8f22ae8a727d88ebf9c16c04ed2475122cc3f7224a/pydantic_core-2.33.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:048c01eee07d37cbd066fc512b9d8b5ea88ceeb4e629ab94b3e56965ad655add", size = 2254631 }, - { url = "https://files.pythonhosted.org/packages/13/e0/bafa46476d328e4553b85ab9b2f7409e7aaef0ce4c937c894821c542d347/pydantic_core-2.33.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5ccd429694cf26af7997595d627dd2637e7932214486f55b8a357edaac9dae8c", size = 2080877 }, - { url = "https://files.pythonhosted.org/packages/0b/76/1794e440c1801ed35415238d2c728f26cd12695df9057154ad768b7b991c/pydantic_core-2.33.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3a371dc00282c4b84246509a5ddc808e61b9864aa1eae9ecc92bb1268b82db4a", size = 2042858 }, - { url = "https://files.pythonhosted.org/packages/73/b4/9cd7b081fb0b1b4f8150507cd59d27b275c3e22ad60b35cb19ea0977d9b9/pydantic_core-2.33.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:f59295ecc75a1788af8ba92f2e8c6eeaa5a94c22fc4d151e8d9638814f85c8fc", size = 1873745 }, - { url = "https://files.pythonhosted.org/packages/e1/d7/9ddb7575d4321e40d0363903c2576c8c0c3280ebea137777e5ab58d723e3/pydantic_core-2.33.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08530b8ac922003033f399128505f513e30ca770527cc8bbacf75a84fcc2c74b", size = 1904188 }, - { url = "https://files.pythonhosted.org/packages/d1/a8/3194ccfe461bb08da19377ebec8cb4f13c9bd82e13baebc53c5c7c39a029/pydantic_core-2.33.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bae370459da6a5466978c0eacf90690cb57ec9d533f8e63e564ef3822bfa04fe", size = 2083479 }, - { url = "https://files.pythonhosted.org/packages/42/c7/84cb569555d7179ca0b3f838cef08f66f7089b54432f5b8599aac6e9533e/pydantic_core-2.33.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e3de2777e3b9f4d603112f78006f4ae0acb936e95f06da6cb1a45fbad6bdb4b5", size = 2118415 }, - { url = "https://files.pythonhosted.org/packages/3b/67/72abb8c73e0837716afbb58a59cc9e3ae43d1aa8677f3b4bc72c16142716/pydantic_core-2.33.1-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3a64e81e8cba118e108d7126362ea30e021291b7805d47e4896e52c791be2761", size = 2079623 }, - { url = "https://files.pythonhosted.org/packages/0b/cd/c59707e35a47ba4cbbf153c3f7c56420c58653b5801b055dc52cccc8e2dc/pydantic_core-2.33.1-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:52928d8c1b6bda03cc6d811e8923dffc87a2d3c8b3bfd2ce16471c7147a24850", size = 2250175 }, - { url = "https://files.pythonhosted.org/packages/84/32/e4325a6676b0bed32d5b084566ec86ed7fd1e9bcbfc49c578b1755bde920/pydantic_core-2.33.1-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:1b30d92c9412beb5ac6b10a3eb7ef92ccb14e3f2a8d7732e2d739f58b3aa7544", size = 2254674 }, - { url = "https://files.pythonhosted.org/packages/12/6f/5596dc418f2e292ffc661d21931ab34591952e2843e7168ea5a52591f6ff/pydantic_core-2.33.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:f995719707e0e29f0f41a8aa3bcea6e761a36c9136104d3189eafb83f5cec5e5", size = 2080951 }, + { url = "https://files.pythonhosted.org/packages/38/ea/5f572806ab4d4223d11551af814d243b0e3e02cc6913def4d1fe4a5ca41c/pydantic_core-2.33.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3077cfdb6125cc8dab61b155fdd714663e401f0e6883f9632118ec12cf42df26", size = 2044021, upload_time = "2025-04-02T09:46:45.065Z" }, + { url = "https://files.pythonhosted.org/packages/8c/d1/f86cc96d2aa80e3881140d16d12ef2b491223f90b28b9a911346c04ac359/pydantic_core-2.33.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8ffab8b2908d152e74862d276cf5017c81a2f3719f14e8e3e8d6b83fda863927", size = 1861742, upload_time = "2025-04-02T09:46:46.684Z" }, + { url = "https://files.pythonhosted.org/packages/37/08/fbd2cd1e9fc735a0df0142fac41c114ad9602d1c004aea340169ae90973b/pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5183e4f6a2d468787243ebcd70cf4098c247e60d73fb7d68d5bc1e1beaa0c4db", size = 1910414, upload_time = "2025-04-02T09:46:48.263Z" }, + { url = "https://files.pythonhosted.org/packages/7f/73/3ac217751decbf8d6cb9443cec9b9eb0130eeada6ae56403e11b486e277e/pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:398a38d323f37714023be1e0285765f0a27243a8b1506b7b7de87b647b517e48", size = 1996848, upload_time = "2025-04-02T09:46:49.441Z" }, + { url = "https://files.pythonhosted.org/packages/9a/f5/5c26b265cdcff2661e2520d2d1e9db72d117ea00eb41e00a76efe68cb009/pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87d3776f0001b43acebfa86f8c64019c043b55cc5a6a2e313d728b5c95b46969", size = 2141055, upload_time = "2025-04-02T09:46:50.602Z" }, + { url = "https://files.pythonhosted.org/packages/5d/14/a9c3cee817ef2f8347c5ce0713e91867a0dceceefcb2973942855c917379/pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c566dd9c5f63d22226409553531f89de0cac55397f2ab8d97d6f06cfce6d947e", size = 2753806, upload_time = "2025-04-02T09:46:52.116Z" }, + { url = "https://files.pythonhosted.org/packages/f2/68/866ce83a51dd37e7c604ce0050ff6ad26de65a7799df89f4db87dd93d1d6/pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0d5f3acc81452c56895e90643a625302bd6be351e7010664151cc55b7b97f89", size = 2007777, upload_time = "2025-04-02T09:46:53.675Z" }, + { url = "https://files.pythonhosted.org/packages/b6/a8/36771f4404bb3e49bd6d4344da4dede0bf89cc1e01f3b723c47248a3761c/pydantic_core-2.33.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d3a07fadec2a13274a8d861d3d37c61e97a816beae717efccaa4b36dfcaadcde", size = 2122803, upload_time = "2025-04-02T09:46:55.789Z" }, + { url = "https://files.pythonhosted.org/packages/18/9c/730a09b2694aa89360d20756369822d98dc2f31b717c21df33b64ffd1f50/pydantic_core-2.33.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f99aeda58dce827f76963ee87a0ebe75e648c72ff9ba1174a253f6744f518f65", size = 2086755, upload_time = "2025-04-02T09:46:56.956Z" }, + { url = "https://files.pythonhosted.org/packages/54/8e/2dccd89602b5ec31d1c58138d02340ecb2ebb8c2cac3cc66b65ce3edb6ce/pydantic_core-2.33.1-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:902dbc832141aa0ec374f4310f1e4e7febeebc3256f00dc359a9ac3f264a45dc", size = 2257358, upload_time = "2025-04-02T09:46:58.445Z" }, + { url = "https://files.pythonhosted.org/packages/d1/9c/126e4ac1bfad8a95a9837acdd0963695d69264179ba4ede8b8c40d741702/pydantic_core-2.33.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fe44d56aa0b00d66640aa84a3cbe80b7a3ccdc6f0b1ca71090696a6d4777c091", size = 2257916, upload_time = "2025-04-02T09:46:59.726Z" }, + { url = "https://files.pythonhosted.org/packages/7d/ba/91eea2047e681a6853c81c20aeca9dcdaa5402ccb7404a2097c2adf9d038/pydantic_core-2.33.1-cp310-cp310-win32.whl", hash = "sha256:ed3eb16d51257c763539bde21e011092f127a2202692afaeaccb50db55a31383", size = 1923823, upload_time = "2025-04-02T09:47:01.278Z" }, + { url = "https://files.pythonhosted.org/packages/94/c0/fcdf739bf60d836a38811476f6ecd50374880b01e3014318b6e809ddfd52/pydantic_core-2.33.1-cp310-cp310-win_amd64.whl", hash = "sha256:694ad99a7f6718c1a498dc170ca430687a39894a60327f548e02a9c7ee4b6504", size = 1952494, upload_time = "2025-04-02T09:47:02.976Z" }, + { url = "https://files.pythonhosted.org/packages/d6/7f/c6298830cb780c46b4f46bb24298d01019ffa4d21769f39b908cd14bbd50/pydantic_core-2.33.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6e966fc3caaf9f1d96b349b0341c70c8d6573bf1bac7261f7b0ba88f96c56c24", size = 2044224, upload_time = "2025-04-02T09:47:04.199Z" }, + { url = "https://files.pythonhosted.org/packages/a8/65/6ab3a536776cad5343f625245bd38165d6663256ad43f3a200e5936afd6c/pydantic_core-2.33.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bfd0adeee563d59c598ceabddf2c92eec77abcb3f4a391b19aa7366170bd9e30", size = 1858845, upload_time = "2025-04-02T09:47:05.686Z" }, + { url = "https://files.pythonhosted.org/packages/e9/15/9a22fd26ba5ee8c669d4b8c9c244238e940cd5d818649603ca81d1c69861/pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91815221101ad3c6b507804178a7bb5cb7b2ead9ecd600041669c8d805ebd595", size = 1910029, upload_time = "2025-04-02T09:47:07.042Z" }, + { url = "https://files.pythonhosted.org/packages/d5/33/8cb1a62818974045086f55f604044bf35b9342900318f9a2a029a1bec460/pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9fea9c1869bb4742d174a57b4700c6dadea951df8b06de40c2fedb4f02931c2e", size = 1997784, upload_time = "2025-04-02T09:47:08.63Z" }, + { url = "https://files.pythonhosted.org/packages/c0/ca/49958e4df7715c71773e1ea5be1c74544923d10319173264e6db122543f9/pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d20eb4861329bb2484c021b9d9a977566ab16d84000a57e28061151c62b349a", size = 2141075, upload_time = "2025-04-02T09:47:10.267Z" }, + { url = "https://files.pythonhosted.org/packages/7b/a6/0b3a167a9773c79ba834b959b4e18c3ae9216b8319bd8422792abc8a41b1/pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb935c5591573ae3201640579f30128ccc10739b45663f93c06796854405505", size = 2745849, upload_time = "2025-04-02T09:47:11.724Z" }, + { url = "https://files.pythonhosted.org/packages/0b/60/516484135173aa9e5861d7a0663dce82e4746d2e7f803627d8c25dfa5578/pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c964fd24e6166420d18fb53996d8c9fd6eac9bf5ae3ec3d03015be4414ce497f", size = 2005794, upload_time = "2025-04-02T09:47:13.099Z" }, + { url = "https://files.pythonhosted.org/packages/86/70/05b1eb77459ad47de00cf78ee003016da0cedf8b9170260488d7c21e9181/pydantic_core-2.33.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:681d65e9011f7392db5aa002b7423cc442d6a673c635668c227c6c8d0e5a4f77", size = 2123237, upload_time = "2025-04-02T09:47:14.355Z" }, + { url = "https://files.pythonhosted.org/packages/c7/57/12667a1409c04ae7dc95d3b43158948eb0368e9c790be8b095cb60611459/pydantic_core-2.33.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e100c52f7355a48413e2999bfb4e139d2977a904495441b374f3d4fb4a170961", size = 2086351, upload_time = "2025-04-02T09:47:15.676Z" }, + { url = "https://files.pythonhosted.org/packages/57/61/cc6d1d1c1664b58fdd6ecc64c84366c34ec9b606aeb66cafab6f4088974c/pydantic_core-2.33.1-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:048831bd363490be79acdd3232f74a0e9951b11b2b4cc058aeb72b22fdc3abe1", size = 2258914, upload_time = "2025-04-02T09:47:17Z" }, + { url = "https://files.pythonhosted.org/packages/d1/0a/edb137176a1f5419b2ddee8bde6a0a548cfa3c74f657f63e56232df8de88/pydantic_core-2.33.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bdc84017d28459c00db6f918a7272a5190bec3090058334e43a76afb279eac7c", size = 2257385, upload_time = "2025-04-02T09:47:18.631Z" }, + { url = "https://files.pythonhosted.org/packages/26/3c/48ca982d50e4b0e1d9954919c887bdc1c2b462801bf408613ccc641b3daa/pydantic_core-2.33.1-cp311-cp311-win32.whl", hash = "sha256:32cd11c5914d1179df70406427097c7dcde19fddf1418c787540f4b730289896", size = 1923765, upload_time = "2025-04-02T09:47:20.34Z" }, + { url = "https://files.pythonhosted.org/packages/33/cd/7ab70b99e5e21559f5de38a0928ea84e6f23fdef2b0d16a6feaf942b003c/pydantic_core-2.33.1-cp311-cp311-win_amd64.whl", hash = "sha256:2ea62419ba8c397e7da28a9170a16219d310d2cf4970dbc65c32faf20d828c83", size = 1950688, upload_time = "2025-04-02T09:47:22.029Z" }, + { url = "https://files.pythonhosted.org/packages/4b/ae/db1fc237b82e2cacd379f63e3335748ab88b5adde98bf7544a1b1bd10a84/pydantic_core-2.33.1-cp311-cp311-win_arm64.whl", hash = "sha256:fc903512177361e868bc1f5b80ac8c8a6e05fcdd574a5fb5ffeac5a9982b9e89", size = 1908185, upload_time = "2025-04-02T09:47:23.385Z" }, + { url = "https://files.pythonhosted.org/packages/c8/ce/3cb22b07c29938f97ff5f5bb27521f95e2ebec399b882392deb68d6c440e/pydantic_core-2.33.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:1293d7febb995e9d3ec3ea09caf1a26214eec45b0f29f6074abb004723fc1de8", size = 2026640, upload_time = "2025-04-02T09:47:25.394Z" }, + { url = "https://files.pythonhosted.org/packages/19/78/f381d643b12378fee782a72126ec5d793081ef03791c28a0fd542a5bee64/pydantic_core-2.33.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:99b56acd433386c8f20be5c4000786d1e7ca0523c8eefc995d14d79c7a081498", size = 1852649, upload_time = "2025-04-02T09:47:27.417Z" }, + { url = "https://files.pythonhosted.org/packages/9d/2b/98a37b80b15aac9eb2c6cfc6dbd35e5058a352891c5cce3a8472d77665a6/pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35a5ec3fa8c2fe6c53e1b2ccc2454398f95d5393ab398478f53e1afbbeb4d939", size = 1892472, upload_time = "2025-04-02T09:47:29.006Z" }, + { url = "https://files.pythonhosted.org/packages/4e/d4/3c59514e0f55a161004792b9ff3039da52448f43f5834f905abef9db6e4a/pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b172f7b9d2f3abc0efd12e3386f7e48b576ef309544ac3a63e5e9cdd2e24585d", size = 1977509, upload_time = "2025-04-02T09:47:33.464Z" }, + { url = "https://files.pythonhosted.org/packages/a9/b6/c2c7946ef70576f79a25db59a576bce088bdc5952d1b93c9789b091df716/pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9097b9f17f91eea659b9ec58148c0747ec354a42f7389b9d50701610d86f812e", size = 2128702, upload_time = "2025-04-02T09:47:34.812Z" }, + { url = "https://files.pythonhosted.org/packages/88/fe/65a880f81e3f2a974312b61f82a03d85528f89a010ce21ad92f109d94deb/pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cc77ec5b7e2118b152b0d886c7514a4653bcb58c6b1d760134a9fab915f777b3", size = 2679428, upload_time = "2025-04-02T09:47:37.315Z" }, + { url = "https://files.pythonhosted.org/packages/6f/ff/4459e4146afd0462fb483bb98aa2436d69c484737feaceba1341615fb0ac/pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3d15245b08fa4a84cefc6c9222e6f37c98111c8679fbd94aa145f9a0ae23d", size = 2008753, upload_time = "2025-04-02T09:47:39.013Z" }, + { url = "https://files.pythonhosted.org/packages/7c/76/1c42e384e8d78452ededac8b583fe2550c84abfef83a0552e0e7478ccbc3/pydantic_core-2.33.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ef99779001d7ac2e2461d8ab55d3373fe7315caefdbecd8ced75304ae5a6fc6b", size = 2114849, upload_time = "2025-04-02T09:47:40.427Z" }, + { url = "https://files.pythonhosted.org/packages/00/72/7d0cf05095c15f7ffe0eb78914b166d591c0eed72f294da68378da205101/pydantic_core-2.33.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:fc6bf8869e193855e8d91d91f6bf59699a5cdfaa47a404e278e776dd7f168b39", size = 2069541, upload_time = "2025-04-02T09:47:42.01Z" }, + { url = "https://files.pythonhosted.org/packages/b3/69/94a514066bb7d8be499aa764926937409d2389c09be0b5107a970286ef81/pydantic_core-2.33.1-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:b1caa0bc2741b043db7823843e1bde8aaa58a55a58fda06083b0569f8b45693a", size = 2239225, upload_time = "2025-04-02T09:47:43.425Z" }, + { url = "https://files.pythonhosted.org/packages/84/b0/e390071eadb44b41f4f54c3cef64d8bf5f9612c92686c9299eaa09e267e2/pydantic_core-2.33.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ec259f62538e8bf364903a7d0d0239447059f9434b284f5536e8402b7dd198db", size = 2248373, upload_time = "2025-04-02T09:47:44.979Z" }, + { url = "https://files.pythonhosted.org/packages/d6/b2/288b3579ffc07e92af66e2f1a11be3b056fe1214aab314748461f21a31c3/pydantic_core-2.33.1-cp312-cp312-win32.whl", hash = "sha256:e14f369c98a7c15772b9da98987f58e2b509a93235582838bd0d1d8c08b68fda", size = 1907034, upload_time = "2025-04-02T09:47:46.843Z" }, + { url = "https://files.pythonhosted.org/packages/02/28/58442ad1c22b5b6742b992ba9518420235adced665513868f99a1c2638a5/pydantic_core-2.33.1-cp312-cp312-win_amd64.whl", hash = "sha256:1c607801d85e2e123357b3893f82c97a42856192997b95b4d8325deb1cd0c5f4", size = 1956848, upload_time = "2025-04-02T09:47:48.404Z" }, + { url = "https://files.pythonhosted.org/packages/a1/eb/f54809b51c7e2a1d9f439f158b8dd94359321abcc98767e16fc48ae5a77e/pydantic_core-2.33.1-cp312-cp312-win_arm64.whl", hash = "sha256:8d13f0276806ee722e70a1c93da19748594f19ac4299c7e41237fc791d1861ea", size = 1903986, upload_time = "2025-04-02T09:47:49.839Z" }, + { url = "https://files.pythonhosted.org/packages/7a/24/eed3466a4308d79155f1cdd5c7432c80ddcc4530ba8623b79d5ced021641/pydantic_core-2.33.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:70af6a21237b53d1fe7b9325b20e65cbf2f0a848cf77bed492b029139701e66a", size = 2033551, upload_time = "2025-04-02T09:47:51.648Z" }, + { url = "https://files.pythonhosted.org/packages/ab/14/df54b1a0bc9b6ded9b758b73139d2c11b4e8eb43e8ab9c5847c0a2913ada/pydantic_core-2.33.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:282b3fe1bbbe5ae35224a0dbd05aed9ccabccd241e8e6b60370484234b456266", size = 1852785, upload_time = "2025-04-02T09:47:53.149Z" }, + { url = "https://files.pythonhosted.org/packages/fa/96/e275f15ff3d34bb04b0125d9bc8848bf69f25d784d92a63676112451bfb9/pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b315e596282bbb5822d0c7ee9d255595bd7506d1cb20c2911a4da0b970187d3", size = 1897758, upload_time = "2025-04-02T09:47:55.006Z" }, + { url = "https://files.pythonhosted.org/packages/b7/d8/96bc536e975b69e3a924b507d2a19aedbf50b24e08c80fb00e35f9baaed8/pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1dfae24cf9921875ca0ca6a8ecb4bb2f13c855794ed0d468d6abbec6e6dcd44a", size = 1986109, upload_time = "2025-04-02T09:47:56.532Z" }, + { url = "https://files.pythonhosted.org/packages/90/72/ab58e43ce7e900b88cb571ed057b2fcd0e95b708a2e0bed475b10130393e/pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6dd8ecfde08d8bfadaea669e83c63939af76f4cf5538a72597016edfa3fad516", size = 2129159, upload_time = "2025-04-02T09:47:58.088Z" }, + { url = "https://files.pythonhosted.org/packages/dc/3f/52d85781406886c6870ac995ec0ba7ccc028b530b0798c9080531b409fdb/pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f593494876eae852dc98c43c6f260f45abdbfeec9e4324e31a481d948214764", size = 2680222, upload_time = "2025-04-02T09:47:59.591Z" }, + { url = "https://files.pythonhosted.org/packages/f4/56/6e2ef42f363a0eec0fd92f74a91e0ac48cd2e49b695aac1509ad81eee86a/pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:948b73114f47fd7016088e5186d13faf5e1b2fe83f5e320e371f035557fd264d", size = 2006980, upload_time = "2025-04-02T09:48:01.397Z" }, + { url = "https://files.pythonhosted.org/packages/4c/c0/604536c4379cc78359f9ee0aa319f4aedf6b652ec2854953f5a14fc38c5a/pydantic_core-2.33.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e11f3864eb516af21b01e25fac915a82e9ddad3bb0fb9e95a246067398b435a4", size = 2120840, upload_time = "2025-04-02T09:48:03.056Z" }, + { url = "https://files.pythonhosted.org/packages/1f/46/9eb764814f508f0edfb291a0f75d10854d78113fa13900ce13729aaec3ae/pydantic_core-2.33.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:549150be302428b56fdad0c23c2741dcdb5572413776826c965619a25d9c6bde", size = 2072518, upload_time = "2025-04-02T09:48:04.662Z" }, + { url = "https://files.pythonhosted.org/packages/42/e3/fb6b2a732b82d1666fa6bf53e3627867ea3131c5f39f98ce92141e3e3dc1/pydantic_core-2.33.1-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:495bc156026efafd9ef2d82372bd38afce78ddd82bf28ef5276c469e57c0c83e", size = 2248025, upload_time = "2025-04-02T09:48:06.226Z" }, + { url = "https://files.pythonhosted.org/packages/5c/9d/fbe8fe9d1aa4dac88723f10a921bc7418bd3378a567cb5e21193a3c48b43/pydantic_core-2.33.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ec79de2a8680b1a67a07490bddf9636d5c2fab609ba8c57597e855fa5fa4dacd", size = 2254991, upload_time = "2025-04-02T09:48:08.114Z" }, + { url = "https://files.pythonhosted.org/packages/aa/99/07e2237b8a66438d9b26482332cda99a9acccb58d284af7bc7c946a42fd3/pydantic_core-2.33.1-cp313-cp313-win32.whl", hash = "sha256:ee12a7be1742f81b8a65b36c6921022301d466b82d80315d215c4c691724986f", size = 1915262, upload_time = "2025-04-02T09:48:09.708Z" }, + { url = "https://files.pythonhosted.org/packages/8a/f4/e457a7849beeed1e5defbcf5051c6f7b3c91a0624dd31543a64fc9adcf52/pydantic_core-2.33.1-cp313-cp313-win_amd64.whl", hash = "sha256:ede9b407e39949d2afc46385ce6bd6e11588660c26f80576c11c958e6647bc40", size = 1956626, upload_time = "2025-04-02T09:48:11.288Z" }, + { url = "https://files.pythonhosted.org/packages/20/d0/e8d567a7cff7b04e017ae164d98011f1e1894269fe8e90ea187a3cbfb562/pydantic_core-2.33.1-cp313-cp313-win_arm64.whl", hash = "sha256:aa687a23d4b7871a00e03ca96a09cad0f28f443690d300500603bd0adba4b523", size = 1909590, upload_time = "2025-04-02T09:48:12.861Z" }, + { url = "https://files.pythonhosted.org/packages/ef/fd/24ea4302d7a527d672c5be06e17df16aabfb4e9fdc6e0b345c21580f3d2a/pydantic_core-2.33.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:401d7b76e1000d0dd5538e6381d28febdcacb097c8d340dde7d7fc6e13e9f95d", size = 1812963, upload_time = "2025-04-02T09:48:14.553Z" }, + { url = "https://files.pythonhosted.org/packages/5f/95/4fbc2ecdeb5c1c53f1175a32d870250194eb2fdf6291b795ab08c8646d5d/pydantic_core-2.33.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7aeb055a42d734c0255c9e489ac67e75397d59c6fbe60d155851e9782f276a9c", size = 1986896, upload_time = "2025-04-02T09:48:16.222Z" }, + { url = "https://files.pythonhosted.org/packages/71/ae/fe31e7f4a62431222d8f65a3bd02e3fa7e6026d154a00818e6d30520ea77/pydantic_core-2.33.1-cp313-cp313t-win_amd64.whl", hash = "sha256:338ea9b73e6e109f15ab439e62cb3b78aa752c7fd9536794112e14bee02c8d18", size = 1931810, upload_time = "2025-04-02T09:48:17.97Z" }, + { url = "https://files.pythonhosted.org/packages/9c/c7/8b311d5adb0fe00a93ee9b4e92a02b0ec08510e9838885ef781ccbb20604/pydantic_core-2.33.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c834f54f8f4640fd7e4b193f80eb25a0602bba9e19b3cd2fc7ffe8199f5ae02", size = 2041659, upload_time = "2025-04-02T09:48:45.342Z" }, + { url = "https://files.pythonhosted.org/packages/8a/d6/4f58d32066a9e26530daaf9adc6664b01875ae0691570094968aaa7b8fcc/pydantic_core-2.33.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:049e0de24cf23766f12cc5cc71d8abc07d4a9deb9061b334b62093dedc7cb068", size = 1873294, upload_time = "2025-04-02T09:48:47.548Z" }, + { url = "https://files.pythonhosted.org/packages/f7/3f/53cc9c45d9229da427909c751f8ed2bf422414f7664ea4dde2d004f596ba/pydantic_core-2.33.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a28239037b3d6f16916a4c831a5a0eadf856bdd6d2e92c10a0da3a59eadcf3e", size = 1903771, upload_time = "2025-04-02T09:48:49.468Z" }, + { url = "https://files.pythonhosted.org/packages/f0/49/bf0783279ce674eb9903fb9ae43f6c614cb2f1c4951370258823f795368b/pydantic_core-2.33.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d3da303ab5f378a268fa7d45f37d7d85c3ec19769f28d2cc0c61826a8de21fe", size = 2083558, upload_time = "2025-04-02T09:48:51.409Z" }, + { url = "https://files.pythonhosted.org/packages/9c/5b/0d998367687f986c7d8484a2c476d30f07bf5b8b1477649a6092bd4c540e/pydantic_core-2.33.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:25626fb37b3c543818c14821afe0fd3830bc327a43953bc88db924b68c5723f1", size = 2118038, upload_time = "2025-04-02T09:48:53.702Z" }, + { url = "https://files.pythonhosted.org/packages/b3/33/039287d410230ee125daee57373ac01940d3030d18dba1c29cd3089dc3ca/pydantic_core-2.33.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3ab2d36e20fbfcce8f02d73c33a8a7362980cff717926bbae030b93ae46b56c7", size = 2079315, upload_time = "2025-04-02T09:48:55.555Z" }, + { url = "https://files.pythonhosted.org/packages/1f/85/6d8b2646d99c062d7da2d0ab2faeb0d6ca9cca4c02da6076376042a20da3/pydantic_core-2.33.1-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:2f9284e11c751b003fd4215ad92d325d92c9cb19ee6729ebd87e3250072cdcde", size = 2249063, upload_time = "2025-04-02T09:48:57.479Z" }, + { url = "https://files.pythonhosted.org/packages/17/d7/c37d208d5738f7b9ad8f22ae8a727d88ebf9c16c04ed2475122cc3f7224a/pydantic_core-2.33.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:048c01eee07d37cbd066fc512b9d8b5ea88ceeb4e629ab94b3e56965ad655add", size = 2254631, upload_time = "2025-04-02T09:48:59.581Z" }, + { url = "https://files.pythonhosted.org/packages/13/e0/bafa46476d328e4553b85ab9b2f7409e7aaef0ce4c937c894821c542d347/pydantic_core-2.33.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5ccd429694cf26af7997595d627dd2637e7932214486f55b8a357edaac9dae8c", size = 2080877, upload_time = "2025-04-02T09:49:01.52Z" }, + { url = "https://files.pythonhosted.org/packages/0b/76/1794e440c1801ed35415238d2c728f26cd12695df9057154ad768b7b991c/pydantic_core-2.33.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3a371dc00282c4b84246509a5ddc808e61b9864aa1eae9ecc92bb1268b82db4a", size = 2042858, upload_time = "2025-04-02T09:49:03.419Z" }, + { url = "https://files.pythonhosted.org/packages/73/b4/9cd7b081fb0b1b4f8150507cd59d27b275c3e22ad60b35cb19ea0977d9b9/pydantic_core-2.33.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:f59295ecc75a1788af8ba92f2e8c6eeaa5a94c22fc4d151e8d9638814f85c8fc", size = 1873745, upload_time = "2025-04-02T09:49:05.391Z" }, + { url = "https://files.pythonhosted.org/packages/e1/d7/9ddb7575d4321e40d0363903c2576c8c0c3280ebea137777e5ab58d723e3/pydantic_core-2.33.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08530b8ac922003033f399128505f513e30ca770527cc8bbacf75a84fcc2c74b", size = 1904188, upload_time = "2025-04-02T09:49:07.352Z" }, + { url = "https://files.pythonhosted.org/packages/d1/a8/3194ccfe461bb08da19377ebec8cb4f13c9bd82e13baebc53c5c7c39a029/pydantic_core-2.33.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bae370459da6a5466978c0eacf90690cb57ec9d533f8e63e564ef3822bfa04fe", size = 2083479, upload_time = "2025-04-02T09:49:09.304Z" }, + { url = "https://files.pythonhosted.org/packages/42/c7/84cb569555d7179ca0b3f838cef08f66f7089b54432f5b8599aac6e9533e/pydantic_core-2.33.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e3de2777e3b9f4d603112f78006f4ae0acb936e95f06da6cb1a45fbad6bdb4b5", size = 2118415, upload_time = "2025-04-02T09:49:11.25Z" }, + { url = "https://files.pythonhosted.org/packages/3b/67/72abb8c73e0837716afbb58a59cc9e3ae43d1aa8677f3b4bc72c16142716/pydantic_core-2.33.1-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3a64e81e8cba118e108d7126362ea30e021291b7805d47e4896e52c791be2761", size = 2079623, upload_time = "2025-04-02T09:49:13.292Z" }, + { url = "https://files.pythonhosted.org/packages/0b/cd/c59707e35a47ba4cbbf153c3f7c56420c58653b5801b055dc52cccc8e2dc/pydantic_core-2.33.1-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:52928d8c1b6bda03cc6d811e8923dffc87a2d3c8b3bfd2ce16471c7147a24850", size = 2250175, upload_time = "2025-04-02T09:49:15.597Z" }, + { url = "https://files.pythonhosted.org/packages/84/32/e4325a6676b0bed32d5b084566ec86ed7fd1e9bcbfc49c578b1755bde920/pydantic_core-2.33.1-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:1b30d92c9412beb5ac6b10a3eb7ef92ccb14e3f2a8d7732e2d739f58b3aa7544", size = 2254674, upload_time = "2025-04-02T09:49:17.61Z" }, + { url = "https://files.pythonhosted.org/packages/12/6f/5596dc418f2e292ffc661d21931ab34591952e2843e7168ea5a52591f6ff/pydantic_core-2.33.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:f995719707e0e29f0f41a8aa3bcea6e761a36c9136104d3189eafb83f5cec5e5", size = 2080951, upload_time = "2025-04-02T09:49:19.559Z" }, ] [[package]] name = "pydantic-settings" -version = "2.8.1" +version = "2.9.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic" }, { name = "python-dotenv" }, + { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/88/82/c79424d7d8c29b994fb01d277da57b0a9b09cc03c3ff875f9bd8a86b2145/pydantic_settings-2.8.1.tar.gz", hash = "sha256:d5c663dfbe9db9d5e1c646b2e161da12f0d734d422ee56f567d0ea2cee4e8585", size = 83550 } +sdist = { url = "https://files.pythonhosted.org/packages/67/1d/42628a2c33e93f8e9acbde0d5d735fa0850f3e6a2f8cb1eb6c40b9a732ac/pydantic_settings-2.9.1.tar.gz", hash = "sha256:c509bf79d27563add44e8446233359004ed85066cd096d8b510f715e6ef5d268", size = 163234, upload_time = "2025-04-18T16:44:48.265Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0b/53/a64f03044927dc47aafe029c42a5b7aabc38dfb813475e0e1bf71c4a59d0/pydantic_settings-2.8.1-py3-none-any.whl", hash = "sha256:81942d5ac3d905f7f3ee1a70df5dfb62d5569c12f51a5a647defc1c3d9ee2e9c", size = 30839 }, + { url = "https://files.pythonhosted.org/packages/b6/5f/d6d641b490fd3ec2c4c13b4244d68deea3a1b970a97be64f34fb5504ff72/pydantic_settings-2.9.1-py3-none-any.whl", hash = "sha256:59b4f431b1defb26fe620c71a7d3968a710d719f5f4cdbbdb7926edeb770f6ef", size = 44356, upload_time = "2025-04-18T16:44:46.617Z" }, ] [[package]] name = "pygments" version = "2.17.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/55/59/8bccf4157baf25e4aa5a0bb7fa3ba8600907de105ebc22b0c78cfbf6f565/pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367", size = 4827772 } +sdist = { url = "https://files.pythonhosted.org/packages/55/59/8bccf4157baf25e4aa5a0bb7fa3ba8600907de105ebc22b0c78cfbf6f565/pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367", size = 4827772, upload_time = "2023-11-21T20:43:53.875Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c", size = 1179756 }, + { url = "https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c", size = 1179756, upload_time = "2023-11-21T20:43:49.423Z" }, ] [[package]] name = "pyparsing" version = "3.1.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/37/fe/65c989f70bd630b589adfbbcd6ed238af22319e90f059946c26b4835e44b/pyparsing-3.1.1.tar.gz", hash = "sha256:ede28a1a32462f5a9705e07aea48001a08f7cf81a021585011deba701581a0db", size = 884814 } +sdist = { url = "https://files.pythonhosted.org/packages/37/fe/65c989f70bd630b589adfbbcd6ed238af22319e90f059946c26b4835e44b/pyparsing-3.1.1.tar.gz", hash = "sha256:ede28a1a32462f5a9705e07aea48001a08f7cf81a021585011deba701581a0db", size = 884814, upload_time = "2023-07-30T15:07:02.617Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/39/92/8486ede85fcc088f1b3dba4ce92dd29d126fd96b0008ea213167940a2475/pyparsing-3.1.1-py3-none-any.whl", hash = "sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb", size = 103139 }, + { url = "https://files.pythonhosted.org/packages/39/92/8486ede85fcc088f1b3dba4ce92dd29d126fd96b0008ea213167940a2475/pyparsing-3.1.1-py3-none-any.whl", hash = "sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb", size = 103139, upload_time = "2023-07-30T15:06:59.829Z" }, ] [[package]] name = "pyreadline3" version = "3.4.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d7/86/3d61a61f36a0067874a00cb4dceb9028d34b6060e47828f7fc86fb9f7ee9/pyreadline3-3.4.1.tar.gz", hash = "sha256:6f3d1f7b8a31ba32b73917cefc1f28cc660562f39aea8646d30bd6eff21f7bae", size = 86465 } +sdist = { url = "https://files.pythonhosted.org/packages/d7/86/3d61a61f36a0067874a00cb4dceb9028d34b6060e47828f7fc86fb9f7ee9/pyreadline3-3.4.1.tar.gz", hash = "sha256:6f3d1f7b8a31ba32b73917cefc1f28cc660562f39aea8646d30bd6eff21f7bae", size = 86465, upload_time = "2022-01-24T20:05:11.66Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/56/fc/a3c13ded7b3057680c8ae95a9b6cc83e63657c38e0005c400a5d018a33a7/pyreadline3-3.4.1-py3-none-any.whl", hash = "sha256:b0efb6516fd4fb07b45949053826a62fa4cb353db5be2bbb4a7aa1fdd1e345fb", size = 95203 }, + { url = "https://files.pythonhosted.org/packages/56/fc/a3c13ded7b3057680c8ae95a9b6cc83e63657c38e0005c400a5d018a33a7/pyreadline3-3.4.1-py3-none-any.whl", hash = "sha256:b0efb6516fd4fb07b45949053826a62fa4cb353db5be2bbb4a7aa1fdd1e345fb", size = 95203, upload_time = "2022-01-24T20:05:10.442Z" }, ] [[package]] @@ -1941,9 +1968,9 @@ dependencies = [ { name = "pluggy" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891 } +sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891, upload_time = "2025-03-02T12:54:54.503Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634 }, + { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634, upload_time = "2025-03-02T12:54:52.069Z" }, ] [[package]] @@ -1953,9 +1980,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8e/c4/453c52c659521066969523e87d85d54139bbd17b78f09532fb8eb8cdb58e/pytest_asyncio-0.26.0.tar.gz", hash = "sha256:c4df2a697648241ff39e7f0e4a73050b03f123f760673956cf0d72a4990e312f", size = 54156 } +sdist = { url = "https://files.pythonhosted.org/packages/8e/c4/453c52c659521066969523e87d85d54139bbd17b78f09532fb8eb8cdb58e/pytest_asyncio-0.26.0.tar.gz", hash = "sha256:c4df2a697648241ff39e7f0e4a73050b03f123f760673956cf0d72a4990e312f", size = 54156, upload_time = "2025-03-25T06:22:28.883Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/7f/338843f449ace853647ace35870874f69a764d251872ed1b4de9f234822c/pytest_asyncio-0.26.0-py3-none-any.whl", hash = "sha256:7b51ed894f4fbea1340262bdae5135797ebbe21d8638978e35d31c6d19f72fb0", size = 19694 }, + { url = "https://files.pythonhosted.org/packages/20/7f/338843f449ace853647ace35870874f69a764d251872ed1b4de9f234822c/pytest_asyncio-0.26.0-py3-none-any.whl", hash = "sha256:7b51ed894f4fbea1340262bdae5135797ebbe21d8638978e35d31c6d19f72fb0", size = 19694, upload_time = "2025-03-25T06:22:27.807Z" }, ] [[package]] @@ -1966,9 +1993,9 @@ dependencies = [ { name = "coverage", extra = ["toml"] }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/25/69/5f1e57f6c5a39f81411b550027bf72842c4567ff5fd572bed1edc9e4b5d9/pytest_cov-6.1.1.tar.gz", hash = "sha256:46935f7aaefba760e716c2ebfbe1c216240b9592966e7da99ea8292d4d3e2a0a", size = 66857 } +sdist = { url = "https://files.pythonhosted.org/packages/25/69/5f1e57f6c5a39f81411b550027bf72842c4567ff5fd572bed1edc9e4b5d9/pytest_cov-6.1.1.tar.gz", hash = "sha256:46935f7aaefba760e716c2ebfbe1c216240b9592966e7da99ea8292d4d3e2a0a", size = 66857, upload_time = "2025-04-05T14:07:51.592Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/28/d0/def53b4a790cfb21483016430ed828f64830dd981ebe1089971cd10cab25/pytest_cov-6.1.1-py3-none-any.whl", hash = "sha256:bddf29ed2d0ab6f4df17b4c55b0a657287db8684af9c42ea546b21b1041b3dde", size = 23841 }, + { url = "https://files.pythonhosted.org/packages/28/d0/def53b4a790cfb21483016430ed828f64830dd981ebe1089971cd10cab25/pytest_cov-6.1.1-py3-none-any.whl", hash = "sha256:bddf29ed2d0ab6f4df17b4c55b0a657287db8684af9c42ea546b21b1041b3dde", size = 23841, upload_time = "2025-04-05T14:07:49.641Z" }, ] [[package]] @@ -1978,9 +2005,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c6/90/a955c3ab35ccd41ad4de556596fa86685bf4fc5ffcc62d22d856cfd4e29a/pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0", size = 32814 } +sdist = { url = "https://files.pythonhosted.org/packages/c6/90/a955c3ab35ccd41ad4de556596fa86685bf4fc5ffcc62d22d856cfd4e29a/pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0", size = 32814, upload_time = "2024-03-21T22:14:04.964Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f2/3b/b26f90f74e2986a82df6e7ac7e319b8ea7ccece1caec9f8ab6104dc70603/pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f", size = 9863 }, + { url = "https://files.pythonhosted.org/packages/f2/3b/b26f90f74e2986a82df6e7ac7e319b8ea7ccece1caec9f8ab6104dc70603/pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f", size = 9863, upload_time = "2024-03-21T22:14:02.694Z" }, ] [[package]] @@ -1990,27 +2017,58 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "six" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4c/c4/13b4776ea2d76c115c1d1b84579f3764ee6d57204f6be27119f13a61d0a9/python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", size = 357324 } +sdist = { url = "https://files.pythonhosted.org/packages/4c/c4/13b4776ea2d76c115c1d1b84579f3764ee6d57204f6be27119f13a61d0a9/python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", size = 357324, upload_time = "2021-07-14T08:19:19.783Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/36/7a/87837f39d0296e723bb9b62bbb257d0355c7f6128853c78955f57342a56d/python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9", size = 247702 }, + { url = "https://files.pythonhosted.org/packages/36/7a/87837f39d0296e723bb9b62bbb257d0355c7f6128853c78955f57342a56d/python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9", size = 247702, upload_time = "2021-07-14T08:19:18.161Z" }, ] [[package]] name = "python-dotenv" version = "1.0.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/31/06/1ef763af20d0572c032fa22882cfbfb005fba6e7300715a37840858c919e/python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba", size = 37399 } +sdist = { url = "https://files.pythonhosted.org/packages/31/06/1ef763af20d0572c032fa22882cfbfb005fba6e7300715a37840858c919e/python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba", size = 37399, upload_time = "2023-02-24T06:46:37.282Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/44/2f/62ea1c8b593f4e093cc1a7768f0d46112107e790c3e478532329e434f00b/python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a", size = 19482 }, + { url = "https://files.pythonhosted.org/packages/44/2f/62ea1c8b593f4e093cc1a7768f0d46112107e790c3e478532329e434f00b/python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a", size = 19482, upload_time = "2023-02-24T06:46:36.009Z" }, +] + +[[package]] +name = "python-engineio" +version = "4.12.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "simple-websocket" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f7/e1/eee1129544b7f78fa2afa9fa0fce153cdcb21015b9b331d1b8adf90f45cb/python_engineio-4.12.0.tar.gz", hash = "sha256:f42a36a868d7063aa10ddccf6bd6117a169b6bd00d7ca53999772093b62014f9", size = 91503, upload_time = "2025-04-12T15:30:23.905Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2b/f7/0aeea75424c47633c1d98557a2323be23bed31fa950f00161b34a5150d06/python_engineio-4.12.0-py3-none-any.whl", hash = "sha256:a0c47c129c39777e8ebc6d18011efd50db2144e4e8f08983acae8a3614626535", size = 59319, upload_time = "2025-04-12T15:30:22.325Z" }, ] [[package]] name = "python-multipart" version = "0.0.20" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f3/87/f44d7c9f274c7ee665a29b885ec97089ec5dc034c7f3fafa03da9e39a09e/python_multipart-0.0.20.tar.gz", hash = "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13", size = 37158 } +sdist = { url = "https://files.pythonhosted.org/packages/f3/87/f44d7c9f274c7ee665a29b885ec97089ec5dc034c7f3fafa03da9e39a09e/python_multipart-0.0.20.tar.gz", hash = "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13", size = 37158, upload_time = "2024-12-16T19:45:46.972Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/45/58/38b5afbc1a800eeea951b9285d3912613f2603bdf897a4ab0f4bd7f405fc/python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104", size = 24546 }, + { url = "https://files.pythonhosted.org/packages/45/58/38b5afbc1a800eeea951b9285d3912613f2603bdf897a4ab0f4bd7f405fc/python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104", size = 24546, upload_time = "2024-12-16T19:45:44.423Z" }, +] + +[[package]] +name = "python-socketio" +version = "5.13.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "bidict" }, + { name = "python-engineio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/21/1a/396d50ccf06ee539fa758ce5623b59a9cb27637fc4b2dc07ed08bf495e77/python_socketio-5.13.0.tar.gz", hash = "sha256:ac4e19a0302ae812e23b712ec8b6427ca0521f7c582d6abb096e36e24a263029", size = 121125, upload_time = "2025-04-12T15:46:59.933Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/32/b4fb8585d1be0f68bde7e110dffbcf354915f77ad8c778563f0ad9655c02/python_socketio-5.13.0-py3-none-any.whl", hash = "sha256:51f68d6499f2df8524668c24bcec13ba1414117cfb3a90115c559b601ab10caf", size = 77800, upload_time = "2025-04-12T15:46:58.412Z" }, +] + +[package.optional-dependencies] +client = [ + { name = "requests" }, + { name = "websocket-client" }, ] [[package]] @@ -2018,45 +2076,45 @@ name = "pywin32" version = "306" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/08/dc/28c668097edfaf4eac4617ef7adf081b9cf50d254672fcf399a70f5efc41/pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d", size = 8506422 }, - { url = "https://files.pythonhosted.org/packages/d3/d6/891894edec688e72c2e308b3243fad98b4066e1839fd2fe78f04129a9d31/pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8", size = 9226392 }, - { url = "https://files.pythonhosted.org/packages/8b/1e/fc18ad83ca553e01b97aa8393ff10e33c1fb57801db05488b83282ee9913/pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407", size = 8507689 }, - { url = "https://files.pythonhosted.org/packages/7e/9e/ad6b1ae2a5ad1066dc509350e0fbf74d8d50251a51e420a2a8feaa0cecbd/pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e", size = 9227547 }, - { url = "https://files.pythonhosted.org/packages/91/20/f744bff1da8f43388498503634378dbbefbe493e65675f2cc52f7185c2c2/pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a", size = 10388324 }, - { url = "https://files.pythonhosted.org/packages/14/91/17e016d5923e178346aabda3dfec6629d1a26efe587d19667542105cf0a6/pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b", size = 8507705 }, - { url = "https://files.pythonhosted.org/packages/83/1c/25b79fc3ec99b19b0a0730cc47356f7e2959863bf9f3cd314332bddb4f68/pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e", size = 9227429 }, - { url = "https://files.pythonhosted.org/packages/1c/43/e3444dc9a12f8365d9603c2145d16bf0a2f8180f343cf87be47f5579e547/pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040", size = 10388145 }, + { url = "https://files.pythonhosted.org/packages/08/dc/28c668097edfaf4eac4617ef7adf081b9cf50d254672fcf399a70f5efc41/pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d", size = 8506422, upload_time = "2023-03-26T03:27:46.303Z" }, + { url = "https://files.pythonhosted.org/packages/d3/d6/891894edec688e72c2e308b3243fad98b4066e1839fd2fe78f04129a9d31/pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8", size = 9226392, upload_time = "2023-03-26T03:27:53.591Z" }, + { url = "https://files.pythonhosted.org/packages/8b/1e/fc18ad83ca553e01b97aa8393ff10e33c1fb57801db05488b83282ee9913/pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407", size = 8507689, upload_time = "2023-03-25T23:50:08.499Z" }, + { url = "https://files.pythonhosted.org/packages/7e/9e/ad6b1ae2a5ad1066dc509350e0fbf74d8d50251a51e420a2a8feaa0cecbd/pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e", size = 9227547, upload_time = "2023-03-25T23:50:20.331Z" }, + { url = "https://files.pythonhosted.org/packages/91/20/f744bff1da8f43388498503634378dbbefbe493e65675f2cc52f7185c2c2/pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a", size = 10388324, upload_time = "2023-03-25T23:50:30.904Z" }, + { url = "https://files.pythonhosted.org/packages/14/91/17e016d5923e178346aabda3dfec6629d1a26efe587d19667542105cf0a6/pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b", size = 8507705, upload_time = "2023-03-25T23:50:40.279Z" }, + { url = "https://files.pythonhosted.org/packages/83/1c/25b79fc3ec99b19b0a0730cc47356f7e2959863bf9f3cd314332bddb4f68/pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e", size = 9227429, upload_time = "2023-03-25T23:50:50.222Z" }, + { url = "https://files.pythonhosted.org/packages/1c/43/e3444dc9a12f8365d9603c2145d16bf0a2f8180f343cf87be47f5579e547/pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040", size = 10388145, upload_time = "2023-03-25T23:51:01.401Z" }, ] [[package]] name = "pyyaml" version = "6.0.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cd/e5/af35f7ea75cf72f2cd079c95ee16797de7cd71f29ea7c68ae5ce7be1eda0/PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43", size = 125201 } +sdist = { url = "https://files.pythonhosted.org/packages/cd/e5/af35f7ea75cf72f2cd079c95ee16797de7cd71f29ea7c68ae5ce7be1eda0/PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43", size = 125201, upload_time = "2023-07-18T00:00:23.308Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/96/06/4beb652c0fe16834032e54f0956443d4cc797fe645527acee59e7deaa0a2/PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a", size = 189447 }, - { url = "https://files.pythonhosted.org/packages/5b/07/10033a403b23405a8fc48975444463d3d10a5c2736b7eb2550b07b367429/PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f", size = 169264 }, - { url = "https://files.pythonhosted.org/packages/f1/26/55e4f21db1f72eaef092015d9017c11510e7e6301c62a6cfee91295d13c6/PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938", size = 677003 }, - { url = "https://files.pythonhosted.org/packages/ba/91/090818dfa62e85181f3ae23dd1e8b7ea7f09684864a900cab72d29c57346/PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d", size = 699070 }, - { url = "https://files.pythonhosted.org/packages/29/61/bf33c6c85c55bc45a29eee3195848ff2d518d84735eb0e2d8cb42e0d285e/PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515", size = 705525 }, - { url = "https://files.pythonhosted.org/packages/07/91/45dfd0ef821a7f41d9d0136ea3608bb5b1653e42fd56a7970532cb5c003f/PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290", size = 707514 }, - { url = "https://files.pythonhosted.org/packages/b6/a0/b6700da5d49e9fed49dc3243d3771b598dad07abb37cc32e524607f96adc/PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924", size = 130488 }, - { url = "https://files.pythonhosted.org/packages/24/97/9b59b43431f98d01806b288532da38099cc6f2fea0f3d712e21e269c0279/PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d", size = 145338 }, - { url = "https://files.pythonhosted.org/packages/ec/0d/26fb23e8863e0aeaac0c64e03fd27367ad2ae3f3cccf3798ee98ce160368/PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007", size = 187867 }, - { url = "https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab", size = 167530 }, - { url = "https://files.pythonhosted.org/packages/5e/94/7d5ee059dfb92ca9e62f4057dcdec9ac08a9e42679644854dc01177f8145/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d", size = 732244 }, - { url = "https://files.pythonhosted.org/packages/06/92/e0224aa6ebf9dc54a06a4609da37da40bb08d126f5535d81bff6b417b2ae/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc", size = 752871 }, - { url = "https://files.pythonhosted.org/packages/7b/5e/efd033ab7199a0b2044dab3b9f7a4f6670e6a52c089de572e928d2873b06/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673", size = 757729 }, - { url = "https://files.pythonhosted.org/packages/03/5c/c4671451b2f1d76ebe352c0945d4cd13500adb5d05f5a51ee296d80152f7/PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b", size = 748528 }, - { url = "https://files.pythonhosted.org/packages/73/9c/766e78d1efc0d1fca637a6b62cea1b4510a7fb93617eb805223294fef681/PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741", size = 130286 }, - { url = "https://files.pythonhosted.org/packages/b3/34/65bb4b2d7908044963ebf614fe0fdb080773fc7030d7e39c8d3eddcd4257/PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34", size = 144699 }, - { url = "https://files.pythonhosted.org/packages/bc/06/1b305bf6aa704343be85444c9d011f626c763abb40c0edc1cad13bfd7f86/PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28", size = 178692 }, - { url = "https://files.pythonhosted.org/packages/84/02/404de95ced348b73dd84f70e15a41843d817ff8c1744516bf78358f2ffd2/PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9", size = 165622 }, - { url = "https://files.pythonhosted.org/packages/c7/4c/4a2908632fc980da6d918b9de9c1d9d7d7e70b2672b1ad5166ed27841ef7/PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef", size = 696937 }, - { url = "https://files.pythonhosted.org/packages/b4/33/720548182ffa8344418126017aa1d4ab4aeec9a2275f04ce3f3573d8ace8/PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0", size = 724969 }, - { url = "https://files.pythonhosted.org/packages/4f/78/77b40157b6cb5f2d3d31a3d9b2efd1ba3505371f76730d267e8b32cf4b7f/PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4", size = 712604 }, - { url = "https://files.pythonhosted.org/packages/2e/97/3e0e089ee85e840f4b15bfa00e4e63d84a3691ababbfea92d6f820ea6f21/PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54", size = 126098 }, - { url = "https://files.pythonhosted.org/packages/2b/9f/fbade56564ad486809c27b322d0f7e6a89c01f6b4fe208402e90d4443a99/PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df", size = 138675 }, + { url = "https://files.pythonhosted.org/packages/96/06/4beb652c0fe16834032e54f0956443d4cc797fe645527acee59e7deaa0a2/PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a", size = 189447, upload_time = "2023-07-17T23:57:04.325Z" }, + { url = "https://files.pythonhosted.org/packages/5b/07/10033a403b23405a8fc48975444463d3d10a5c2736b7eb2550b07b367429/PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f", size = 169264, upload_time = "2023-07-17T23:57:07.787Z" }, + { url = "https://files.pythonhosted.org/packages/f1/26/55e4f21db1f72eaef092015d9017c11510e7e6301c62a6cfee91295d13c6/PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938", size = 677003, upload_time = "2023-07-17T23:57:13.144Z" }, + { url = "https://files.pythonhosted.org/packages/ba/91/090818dfa62e85181f3ae23dd1e8b7ea7f09684864a900cab72d29c57346/PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d", size = 699070, upload_time = "2023-07-17T23:57:19.402Z" }, + { url = "https://files.pythonhosted.org/packages/29/61/bf33c6c85c55bc45a29eee3195848ff2d518d84735eb0e2d8cb42e0d285e/PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515", size = 705525, upload_time = "2023-07-17T23:57:25.272Z" }, + { url = "https://files.pythonhosted.org/packages/07/91/45dfd0ef821a7f41d9d0136ea3608bb5b1653e42fd56a7970532cb5c003f/PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290", size = 707514, upload_time = "2023-08-28T18:43:20.945Z" }, + { url = "https://files.pythonhosted.org/packages/b6/a0/b6700da5d49e9fed49dc3243d3771b598dad07abb37cc32e524607f96adc/PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924", size = 130488, upload_time = "2023-07-17T23:57:28.144Z" }, + { url = "https://files.pythonhosted.org/packages/24/97/9b59b43431f98d01806b288532da38099cc6f2fea0f3d712e21e269c0279/PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d", size = 145338, upload_time = "2023-07-17T23:57:31.118Z" }, + { url = "https://files.pythonhosted.org/packages/ec/0d/26fb23e8863e0aeaac0c64e03fd27367ad2ae3f3cccf3798ee98ce160368/PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007", size = 187867, upload_time = "2023-07-17T23:57:34.35Z" }, + { url = "https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab", size = 167530, upload_time = "2023-07-17T23:57:36.975Z" }, + { url = "https://files.pythonhosted.org/packages/5e/94/7d5ee059dfb92ca9e62f4057dcdec9ac08a9e42679644854dc01177f8145/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d", size = 732244, upload_time = "2023-07-17T23:57:43.774Z" }, + { url = "https://files.pythonhosted.org/packages/06/92/e0224aa6ebf9dc54a06a4609da37da40bb08d126f5535d81bff6b417b2ae/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc", size = 752871, upload_time = "2023-07-17T23:57:51.921Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5e/efd033ab7199a0b2044dab3b9f7a4f6670e6a52c089de572e928d2873b06/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673", size = 757729, upload_time = "2023-07-17T23:57:59.865Z" }, + { url = "https://files.pythonhosted.org/packages/03/5c/c4671451b2f1d76ebe352c0945d4cd13500adb5d05f5a51ee296d80152f7/PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b", size = 748528, upload_time = "2023-08-28T18:43:23.207Z" }, + { url = "https://files.pythonhosted.org/packages/73/9c/766e78d1efc0d1fca637a6b62cea1b4510a7fb93617eb805223294fef681/PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741", size = 130286, upload_time = "2023-07-17T23:58:02.964Z" }, + { url = "https://files.pythonhosted.org/packages/b3/34/65bb4b2d7908044963ebf614fe0fdb080773fc7030d7e39c8d3eddcd4257/PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34", size = 144699, upload_time = "2023-07-17T23:58:05.586Z" }, + { url = "https://files.pythonhosted.org/packages/bc/06/1b305bf6aa704343be85444c9d011f626c763abb40c0edc1cad13bfd7f86/PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28", size = 178692, upload_time = "2023-08-28T18:43:24.924Z" }, + { url = "https://files.pythonhosted.org/packages/84/02/404de95ced348b73dd84f70e15a41843d817ff8c1744516bf78358f2ffd2/PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9", size = 165622, upload_time = "2023-08-28T18:43:26.54Z" }, + { url = "https://files.pythonhosted.org/packages/c7/4c/4a2908632fc980da6d918b9de9c1d9d7d7e70b2672b1ad5166ed27841ef7/PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef", size = 696937, upload_time = "2024-01-18T20:40:22.92Z" }, + { url = "https://files.pythonhosted.org/packages/b4/33/720548182ffa8344418126017aa1d4ab4aeec9a2275f04ce3f3573d8ace8/PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0", size = 724969, upload_time = "2023-08-28T18:43:28.56Z" }, + { url = "https://files.pythonhosted.org/packages/4f/78/77b40157b6cb5f2d3d31a3d9b2efd1ba3505371f76730d267e8b32cf4b7f/PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4", size = 712604, upload_time = "2023-08-28T18:43:30.206Z" }, + { url = "https://files.pythonhosted.org/packages/2e/97/3e0e089ee85e840f4b15bfa00e4e63d84a3691ababbfea92d6f820ea6f21/PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54", size = 126098, upload_time = "2023-08-28T18:43:31.835Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9f/fbade56564ad486809c27b322d0f7e6a89c01f6b4fe208402e90d4443a99/PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df", size = 138675, upload_time = "2023-08-28T18:43:33.613Z" }, ] [[package]] @@ -2066,46 +2124,46 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "implementation_name == 'pypy'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3a/33/1a3683fc9a4bd64d8ccc0290da75c8f042184a1a49c146d28398414d3341/pyzmq-25.1.2.tar.gz", hash = "sha256:93f1aa311e8bb912e34f004cf186407a4e90eec4f0ecc0efd26056bf7eda0226", size = 1402339 } +sdist = { url = "https://files.pythonhosted.org/packages/3a/33/1a3683fc9a4bd64d8ccc0290da75c8f042184a1a49c146d28398414d3341/pyzmq-25.1.2.tar.gz", hash = "sha256:93f1aa311e8bb912e34f004cf186407a4e90eec4f0ecc0efd26056bf7eda0226", size = 1402339, upload_time = "2023-12-05T07:34:47.976Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5e/f4/901edb48b2b2c00ad73de0db2ee76e24ce5903ef815ad0ad10e14555d989/pyzmq-25.1.2-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:e624c789359f1a16f83f35e2c705d07663ff2b4d4479bad35621178d8f0f6ea4", size = 1872310 }, - { url = "https://files.pythonhosted.org/packages/5e/46/2de69c7c79fd78bf4c22a9e8165fa6312f5d49410f1be6ddab51a6fe7236/pyzmq-25.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:49151b0efece79f6a79d41a461d78535356136ee70084a1c22532fc6383f4ad0", size = 1249619 }, - { url = "https://files.pythonhosted.org/packages/d1/f5/d6b9755713843bf9701ae86bf6fd97ec294a52cf2af719cd14fdf9392f65/pyzmq-25.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9a5f194cf730f2b24d6af1f833c14c10f41023da46a7f736f48b6d35061e76e", size = 897360 }, - { url = "https://files.pythonhosted.org/packages/7c/88/c1aef8820f12e710d136024d231e70e24684a01314aa1814f0758960ba01/pyzmq-25.1.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:faf79a302f834d9e8304fafdc11d0d042266667ac45209afa57e5efc998e3872", size = 1156959 }, - { url = "https://files.pythonhosted.org/packages/82/1b/b25d2c4ac3b4dae238c98e63395dbb88daf11968b168948d3c6289c3e95c/pyzmq-25.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f51a7b4ead28d3fca8dda53216314a553b0f7a91ee8fc46a72b402a78c3e43d", size = 1100585 }, - { url = "https://files.pythonhosted.org/packages/67/bf/6bc0977acd934b66eacab79cec303ecf08ae4a6150d57c628aa919615488/pyzmq-25.1.2-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:0ddd6d71d4ef17ba5a87becf7ddf01b371eaba553c603477679ae817a8d84d75", size = 1109267 }, - { url = "https://files.pythonhosted.org/packages/64/fb/4f07424e56c6a5fb47306d9ba744c3c250250c2e7272f9c81efbf8daaccf/pyzmq-25.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:246747b88917e4867e2367b005fc8eefbb4a54b7db363d6c92f89d69abfff4b6", size = 1431853 }, - { url = "https://files.pythonhosted.org/packages/a2/10/2b88c1d4beb59a1d45c13983c4b7c5dcd6ef7988db3c03d23b0cabc5adca/pyzmq-25.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:00c48ae2fd81e2a50c3485de1b9d5c7c57cd85dc8ec55683eac16846e57ac979", size = 1766212 }, - { url = "https://files.pythonhosted.org/packages/bc/ab/c9a22eacfd5bd82620501ae426a3dd6ffa374ac335b21e54209d7a93d3fb/pyzmq-25.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5a68d491fc20762b630e5db2191dd07ff89834086740f70e978bb2ef2668be08", size = 1653737 }, - { url = "https://files.pythonhosted.org/packages/d6/e5/71bd89e47eedb7ebec31ef9a49dcdb0517dbbb063bd5de363980a6911eb1/pyzmq-25.1.2-cp310-cp310-win32.whl", hash = "sha256:09dfe949e83087da88c4a76767df04b22304a682d6154de2c572625c62ad6886", size = 906288 }, - { url = "https://files.pythonhosted.org/packages/9d/5f/2defc8a579e8b5679d92720ab3a4cb93e3a77d923070bf4c1a103d3ae478/pyzmq-25.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:fa99973d2ed20417744fca0073390ad65ce225b546febb0580358e36aa90dba6", size = 1170923 }, - { url = "https://files.pythonhosted.org/packages/35/de/7579518bc58cebf92568b48e354a702fb52525d0fab166dc544f2a0615dc/pyzmq-25.1.2-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:82544e0e2d0c1811482d37eef297020a040c32e0687c1f6fc23a75b75db8062c", size = 1870360 }, - { url = "https://files.pythonhosted.org/packages/ce/f9/58b6cc9a110b1832f666fa6b5a67dc4d520fabfc680ca87a8167b2061d5d/pyzmq-25.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:01171fc48542348cd1a360a4b6c3e7d8f46cdcf53a8d40f84db6707a6768acc1", size = 1249008 }, - { url = "https://files.pythonhosted.org/packages/bc/4a/ac6469c01813cb3652ab4e30ec4a37815cc9949afc18af33f64e2ec704aa/pyzmq-25.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc69c96735ab501419c432110016329bf0dea8898ce16fab97c6d9106dc0b348", size = 904394 }, - { url = "https://files.pythonhosted.org/packages/77/b7/8cee519b11bdd3f76c1a6eb537ab13c1bfef2964d725717705c86f524e4c/pyzmq-25.1.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3e124e6b1dd3dfbeb695435dff0e383256655bb18082e094a8dd1f6293114642", size = 1161453 }, - { url = "https://files.pythonhosted.org/packages/b6/1d/c35a956a44b333b064ae1b1c588c2dfa0e01b7ec90884c1972bfcef119c3/pyzmq-25.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7598d2ba821caa37a0f9d54c25164a4fa351ce019d64d0b44b45540950458840", size = 1105501 }, - { url = "https://files.pythonhosted.org/packages/18/d1/b3d1e985318ed7287737ea9e6b6e21748cc7c89accc2443347cd2c8d5f0f/pyzmq-25.1.2-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d1299d7e964c13607efd148ca1f07dcbf27c3ab9e125d1d0ae1d580a1682399d", size = 1109513 }, - { url = "https://files.pythonhosted.org/packages/14/9b/341cdfb47440069010101403298dc24d449150370c6cb322e73bfa1949bd/pyzmq-25.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4e6f689880d5ad87918430957297c975203a082d9a036cc426648fcbedae769b", size = 1433541 }, - { url = "https://files.pythonhosted.org/packages/fa/52/c6d4e76e020c554e965459d41a98201b4d45277a288648f53a4e5a2429cc/pyzmq-25.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cc69949484171cc961e6ecd4a8911b9ce7a0d1f738fcae717177c231bf77437b", size = 1766133 }, - { url = "https://files.pythonhosted.org/packages/1d/6d/0cbd8dd5b8979fd6b9cf1852ed067b9d2cd6fa0c09c3bafe6874d2d2e03c/pyzmq-25.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9880078f683466b7f567b8624bfc16cad65077be046b6e8abb53bed4eeb82dd3", size = 1653636 }, - { url = "https://files.pythonhosted.org/packages/f5/af/d90eed9cf3840685d54d4a35d5f9e242a8a48b5410d41146f14c1e098302/pyzmq-25.1.2-cp311-cp311-win32.whl", hash = "sha256:4e5837af3e5aaa99a091302df5ee001149baff06ad22b722d34e30df5f0d9097", size = 904865 }, - { url = "https://files.pythonhosted.org/packages/20/d2/09443dc73053ad01c846d7fb77e09fe9d93c09d4e900215f3c8b7b56bfec/pyzmq-25.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:25c2dbb97d38b5ac9fd15586e048ec5eb1e38f3d47fe7d92167b0c77bb3584e9", size = 1171332 }, - { url = "https://files.pythonhosted.org/packages/6e/f0/d71cf69dc039c9adc8b625efc3bad3684f3660a570e47f0f0c64df787b41/pyzmq-25.1.2-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:11e70516688190e9c2db14fcf93c04192b02d457b582a1f6190b154691b4c93a", size = 1871111 }, - { url = "https://files.pythonhosted.org/packages/68/62/d365773edf56ad71993579ee574105f02f83530caf600ebf28bea15d88d0/pyzmq-25.1.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:313c3794d650d1fccaaab2df942af9f2c01d6217c846177cfcbc693c7410839e", size = 1248844 }, - { url = "https://files.pythonhosted.org/packages/72/55/cc3163e20f40615a49245fa7041badec6103e8ee7e482dbb0feea00a7b84/pyzmq-25.1.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b3cbba2f47062b85fe0ef9de5b987612140a9ba3a9c6d2543c6dec9f7c2ab27", size = 899373 }, - { url = "https://files.pythonhosted.org/packages/40/aa/ae292bd85deda637230970bbc53c1dc53696a99e82fc7cd6d373ec173853/pyzmq-25.1.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fc31baa0c32a2ca660784d5af3b9487e13b61b3032cb01a115fce6588e1bed30", size = 1160901 }, - { url = "https://files.pythonhosted.org/packages/93/b7/6e291eafbbbc66d0e87658dd21383ec2b4ab35edcfb283902c580a6db76f/pyzmq-25.1.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02c9087b109070c5ab0b383079fa1b5f797f8d43e9a66c07a4b8b8bdecfd88ee", size = 1101147 }, - { url = "https://files.pythonhosted.org/packages/3a/f1/e296d5a507eac519d1fe1382851b1a4575f690bc2b2d2c8eca2ed7e4bd1f/pyzmq-25.1.2-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:f8429b17cbb746c3e043cb986328da023657e79d5ed258b711c06a70c2ea7537", size = 1105315 }, - { url = "https://files.pythonhosted.org/packages/56/63/5c2abb556ab4cf013d98e01782d5bd642238a0ed9b019e965a7d7e957f56/pyzmq-25.1.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5074adeacede5f810b7ef39607ee59d94e948b4fd954495bdb072f8c54558181", size = 1427747 }, - { url = "https://files.pythonhosted.org/packages/b1/71/5dba5f6b12ef54fb977c9b9279075e151c04fc0dd6851e9663d9e66b593f/pyzmq-25.1.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:7ae8f354b895cbd85212da245f1a5ad8159e7840e37d78b476bb4f4c3f32a9fe", size = 1762221 }, - { url = "https://files.pythonhosted.org/packages/cf/49/54d7e8bb3df82a3509325b11491d33450dc91580d4826b62fa5e554bb9cf/pyzmq-25.1.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b264bf2cc96b5bc43ce0e852be995e400376bd87ceb363822e2cb1964fcdc737", size = 1649505 }, - { url = "https://files.pythonhosted.org/packages/34/14/58e5037229bc37963e2ce804c2c075a3a541e3f84bf1c231e7c9779d36f1/pyzmq-25.1.2-cp312-cp312-win32.whl", hash = "sha256:02bbc1a87b76e04fd780b45e7f695471ae6de747769e540da909173d50ff8e2d", size = 954891 }, - { url = "https://files.pythonhosted.org/packages/2c/2d/04fab685ef3a8e6e955220fd2a54dc99efaee960a88675bf5c92cd277164/pyzmq-25.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:ced111c2e81506abd1dc142e6cd7b68dd53747b3b7ae5edbea4578c5eeff96b7", size = 1252773 }, - { url = "https://files.pythonhosted.org/packages/6b/fe/ed38fe12c540bafc1cae32c3ff638e9df32528f5cf91b5e400e6a8f5b3ec/pyzmq-25.1.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a8c1d566344aee826b74e472e16edae0a02e2a044f14f7c24e123002dcff1c05", size = 963654 }, - { url = "https://files.pythonhosted.org/packages/44/97/a760a2dff0672c408f22f726f2ea10a7a516ffa5001ca5a3641e355a45f9/pyzmq-25.1.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:759cfd391a0996345ba94b6a5110fca9c557ad4166d86a6e81ea526c376a01e8", size = 609436 }, - { url = "https://files.pythonhosted.org/packages/41/81/ace39daa19c78b2f4fc12ef217d9d5f1ac658d5828d692bbbb68240cd55b/pyzmq-25.1.2-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c61e346ac34b74028ede1c6b4bcecf649d69b707b3ff9dc0fab453821b04d1e", size = 843396 }, - { url = "https://files.pythonhosted.org/packages/4c/43/150b0b203f5461a9aeadaa925c55167e2b4215c9322b6911a64360d2243e/pyzmq-25.1.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cb8fc1f8d69b411b8ec0b5f1ffbcaf14c1db95b6bccea21d83610987435f1a4", size = 800856 }, - { url = "https://files.pythonhosted.org/packages/5f/91/a618b56aaabe40dddcd25db85624d7408768fd32f5bfcf81bc0af5b1ce75/pyzmq-25.1.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:3c00c9b7d1ca8165c610437ca0c92e7b5607b2f9076f4eb4b095c85d6e680a1d", size = 413836 }, + { url = "https://files.pythonhosted.org/packages/5e/f4/901edb48b2b2c00ad73de0db2ee76e24ce5903ef815ad0ad10e14555d989/pyzmq-25.1.2-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:e624c789359f1a16f83f35e2c705d07663ff2b4d4479bad35621178d8f0f6ea4", size = 1872310, upload_time = "2023-12-05T07:48:13.713Z" }, + { url = "https://files.pythonhosted.org/packages/5e/46/2de69c7c79fd78bf4c22a9e8165fa6312f5d49410f1be6ddab51a6fe7236/pyzmq-25.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:49151b0efece79f6a79d41a461d78535356136ee70084a1c22532fc6383f4ad0", size = 1249619, upload_time = "2023-12-05T07:50:38.691Z" }, + { url = "https://files.pythonhosted.org/packages/d1/f5/d6b9755713843bf9701ae86bf6fd97ec294a52cf2af719cd14fdf9392f65/pyzmq-25.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9a5f194cf730f2b24d6af1f833c14c10f41023da46a7f736f48b6d35061e76e", size = 897360, upload_time = "2023-12-05T07:42:26.268Z" }, + { url = "https://files.pythonhosted.org/packages/7c/88/c1aef8820f12e710d136024d231e70e24684a01314aa1814f0758960ba01/pyzmq-25.1.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:faf79a302f834d9e8304fafdc11d0d042266667ac45209afa57e5efc998e3872", size = 1156959, upload_time = "2023-12-05T07:44:29.904Z" }, + { url = "https://files.pythonhosted.org/packages/82/1b/b25d2c4ac3b4dae238c98e63395dbb88daf11968b168948d3c6289c3e95c/pyzmq-25.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f51a7b4ead28d3fca8dda53216314a553b0f7a91ee8fc46a72b402a78c3e43d", size = 1100585, upload_time = "2023-12-05T07:45:05.518Z" }, + { url = "https://files.pythonhosted.org/packages/67/bf/6bc0977acd934b66eacab79cec303ecf08ae4a6150d57c628aa919615488/pyzmq-25.1.2-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:0ddd6d71d4ef17ba5a87becf7ddf01b371eaba553c603477679ae817a8d84d75", size = 1109267, upload_time = "2023-12-05T07:39:51.21Z" }, + { url = "https://files.pythonhosted.org/packages/64/fb/4f07424e56c6a5fb47306d9ba744c3c250250c2e7272f9c81efbf8daaccf/pyzmq-25.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:246747b88917e4867e2367b005fc8eefbb4a54b7db363d6c92f89d69abfff4b6", size = 1431853, upload_time = "2023-12-05T07:41:09.261Z" }, + { url = "https://files.pythonhosted.org/packages/a2/10/2b88c1d4beb59a1d45c13983c4b7c5dcd6ef7988db3c03d23b0cabc5adca/pyzmq-25.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:00c48ae2fd81e2a50c3485de1b9d5c7c57cd85dc8ec55683eac16846e57ac979", size = 1766212, upload_time = "2023-12-05T07:49:05.926Z" }, + { url = "https://files.pythonhosted.org/packages/bc/ab/c9a22eacfd5bd82620501ae426a3dd6ffa374ac335b21e54209d7a93d3fb/pyzmq-25.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5a68d491fc20762b630e5db2191dd07ff89834086740f70e978bb2ef2668be08", size = 1653737, upload_time = "2023-12-05T07:49:09.096Z" }, + { url = "https://files.pythonhosted.org/packages/d6/e5/71bd89e47eedb7ebec31ef9a49dcdb0517dbbb063bd5de363980a6911eb1/pyzmq-25.1.2-cp310-cp310-win32.whl", hash = "sha256:09dfe949e83087da88c4a76767df04b22304a682d6154de2c572625c62ad6886", size = 906288, upload_time = "2023-12-05T07:42:05.509Z" }, + { url = "https://files.pythonhosted.org/packages/9d/5f/2defc8a579e8b5679d92720ab3a4cb93e3a77d923070bf4c1a103d3ae478/pyzmq-25.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:fa99973d2ed20417744fca0073390ad65ce225b546febb0580358e36aa90dba6", size = 1170923, upload_time = "2023-12-05T07:44:54.296Z" }, + { url = "https://files.pythonhosted.org/packages/35/de/7579518bc58cebf92568b48e354a702fb52525d0fab166dc544f2a0615dc/pyzmq-25.1.2-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:82544e0e2d0c1811482d37eef297020a040c32e0687c1f6fc23a75b75db8062c", size = 1870360, upload_time = "2023-12-05T07:48:16.153Z" }, + { url = "https://files.pythonhosted.org/packages/ce/f9/58b6cc9a110b1832f666fa6b5a67dc4d520fabfc680ca87a8167b2061d5d/pyzmq-25.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:01171fc48542348cd1a360a4b6c3e7d8f46cdcf53a8d40f84db6707a6768acc1", size = 1249008, upload_time = "2023-12-05T07:50:40.442Z" }, + { url = "https://files.pythonhosted.org/packages/bc/4a/ac6469c01813cb3652ab4e30ec4a37815cc9949afc18af33f64e2ec704aa/pyzmq-25.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc69c96735ab501419c432110016329bf0dea8898ce16fab97c6d9106dc0b348", size = 904394, upload_time = "2023-12-05T07:42:27.815Z" }, + { url = "https://files.pythonhosted.org/packages/77/b7/8cee519b11bdd3f76c1a6eb537ab13c1bfef2964d725717705c86f524e4c/pyzmq-25.1.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3e124e6b1dd3dfbeb695435dff0e383256655bb18082e094a8dd1f6293114642", size = 1161453, upload_time = "2023-12-05T07:44:32.003Z" }, + { url = "https://files.pythonhosted.org/packages/b6/1d/c35a956a44b333b064ae1b1c588c2dfa0e01b7ec90884c1972bfcef119c3/pyzmq-25.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7598d2ba821caa37a0f9d54c25164a4fa351ce019d64d0b44b45540950458840", size = 1105501, upload_time = "2023-12-05T07:45:07.18Z" }, + { url = "https://files.pythonhosted.org/packages/18/d1/b3d1e985318ed7287737ea9e6b6e21748cc7c89accc2443347cd2c8d5f0f/pyzmq-25.1.2-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d1299d7e964c13607efd148ca1f07dcbf27c3ab9e125d1d0ae1d580a1682399d", size = 1109513, upload_time = "2023-12-05T07:39:53.338Z" }, + { url = "https://files.pythonhosted.org/packages/14/9b/341cdfb47440069010101403298dc24d449150370c6cb322e73bfa1949bd/pyzmq-25.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4e6f689880d5ad87918430957297c975203a082d9a036cc426648fcbedae769b", size = 1433541, upload_time = "2023-12-05T07:41:10.786Z" }, + { url = "https://files.pythonhosted.org/packages/fa/52/c6d4e76e020c554e965459d41a98201b4d45277a288648f53a4e5a2429cc/pyzmq-25.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cc69949484171cc961e6ecd4a8911b9ce7a0d1f738fcae717177c231bf77437b", size = 1766133, upload_time = "2023-12-05T07:49:11.204Z" }, + { url = "https://files.pythonhosted.org/packages/1d/6d/0cbd8dd5b8979fd6b9cf1852ed067b9d2cd6fa0c09c3bafe6874d2d2e03c/pyzmq-25.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9880078f683466b7f567b8624bfc16cad65077be046b6e8abb53bed4eeb82dd3", size = 1653636, upload_time = "2023-12-05T07:49:13.787Z" }, + { url = "https://files.pythonhosted.org/packages/f5/af/d90eed9cf3840685d54d4a35d5f9e242a8a48b5410d41146f14c1e098302/pyzmq-25.1.2-cp311-cp311-win32.whl", hash = "sha256:4e5837af3e5aaa99a091302df5ee001149baff06ad22b722d34e30df5f0d9097", size = 904865, upload_time = "2023-12-05T07:42:07.189Z" }, + { url = "https://files.pythonhosted.org/packages/20/d2/09443dc73053ad01c846d7fb77e09fe9d93c09d4e900215f3c8b7b56bfec/pyzmq-25.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:25c2dbb97d38b5ac9fd15586e048ec5eb1e38f3d47fe7d92167b0c77bb3584e9", size = 1171332, upload_time = "2023-12-05T07:44:56.111Z" }, + { url = "https://files.pythonhosted.org/packages/6e/f0/d71cf69dc039c9adc8b625efc3bad3684f3660a570e47f0f0c64df787b41/pyzmq-25.1.2-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:11e70516688190e9c2db14fcf93c04192b02d457b582a1f6190b154691b4c93a", size = 1871111, upload_time = "2023-12-05T07:48:17.868Z" }, + { url = "https://files.pythonhosted.org/packages/68/62/d365773edf56ad71993579ee574105f02f83530caf600ebf28bea15d88d0/pyzmq-25.1.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:313c3794d650d1fccaaab2df942af9f2c01d6217c846177cfcbc693c7410839e", size = 1248844, upload_time = "2023-12-05T07:50:42.922Z" }, + { url = "https://files.pythonhosted.org/packages/72/55/cc3163e20f40615a49245fa7041badec6103e8ee7e482dbb0feea00a7b84/pyzmq-25.1.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b3cbba2f47062b85fe0ef9de5b987612140a9ba3a9c6d2543c6dec9f7c2ab27", size = 899373, upload_time = "2023-12-05T07:42:29.595Z" }, + { url = "https://files.pythonhosted.org/packages/40/aa/ae292bd85deda637230970bbc53c1dc53696a99e82fc7cd6d373ec173853/pyzmq-25.1.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fc31baa0c32a2ca660784d5af3b9487e13b61b3032cb01a115fce6588e1bed30", size = 1160901, upload_time = "2023-12-05T07:44:33.819Z" }, + { url = "https://files.pythonhosted.org/packages/93/b7/6e291eafbbbc66d0e87658dd21383ec2b4ab35edcfb283902c580a6db76f/pyzmq-25.1.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02c9087b109070c5ab0b383079fa1b5f797f8d43e9a66c07a4b8b8bdecfd88ee", size = 1101147, upload_time = "2023-12-05T07:45:10.058Z" }, + { url = "https://files.pythonhosted.org/packages/3a/f1/e296d5a507eac519d1fe1382851b1a4575f690bc2b2d2c8eca2ed7e4bd1f/pyzmq-25.1.2-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:f8429b17cbb746c3e043cb986328da023657e79d5ed258b711c06a70c2ea7537", size = 1105315, upload_time = "2023-12-05T07:39:55.851Z" }, + { url = "https://files.pythonhosted.org/packages/56/63/5c2abb556ab4cf013d98e01782d5bd642238a0ed9b019e965a7d7e957f56/pyzmq-25.1.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5074adeacede5f810b7ef39607ee59d94e948b4fd954495bdb072f8c54558181", size = 1427747, upload_time = "2023-12-05T07:41:13.219Z" }, + { url = "https://files.pythonhosted.org/packages/b1/71/5dba5f6b12ef54fb977c9b9279075e151c04fc0dd6851e9663d9e66b593f/pyzmq-25.1.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:7ae8f354b895cbd85212da245f1a5ad8159e7840e37d78b476bb4f4c3f32a9fe", size = 1762221, upload_time = "2023-12-05T07:49:16.352Z" }, + { url = "https://files.pythonhosted.org/packages/cf/49/54d7e8bb3df82a3509325b11491d33450dc91580d4826b62fa5e554bb9cf/pyzmq-25.1.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b264bf2cc96b5bc43ce0e852be995e400376bd87ceb363822e2cb1964fcdc737", size = 1649505, upload_time = "2023-12-05T07:49:18.952Z" }, + { url = "https://files.pythonhosted.org/packages/34/14/58e5037229bc37963e2ce804c2c075a3a541e3f84bf1c231e7c9779d36f1/pyzmq-25.1.2-cp312-cp312-win32.whl", hash = "sha256:02bbc1a87b76e04fd780b45e7f695471ae6de747769e540da909173d50ff8e2d", size = 954891, upload_time = "2023-12-05T07:42:09.208Z" }, + { url = "https://files.pythonhosted.org/packages/2c/2d/04fab685ef3a8e6e955220fd2a54dc99efaee960a88675bf5c92cd277164/pyzmq-25.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:ced111c2e81506abd1dc142e6cd7b68dd53747b3b7ae5edbea4578c5eeff96b7", size = 1252773, upload_time = "2023-12-05T07:44:58.16Z" }, + { url = "https://files.pythonhosted.org/packages/6b/fe/ed38fe12c540bafc1cae32c3ff638e9df32528f5cf91b5e400e6a8f5b3ec/pyzmq-25.1.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a8c1d566344aee826b74e472e16edae0a02e2a044f14f7c24e123002dcff1c05", size = 963654, upload_time = "2023-12-05T07:47:03.874Z" }, + { url = "https://files.pythonhosted.org/packages/44/97/a760a2dff0672c408f22f726f2ea10a7a516ffa5001ca5a3641e355a45f9/pyzmq-25.1.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:759cfd391a0996345ba94b6a5110fca9c557ad4166d86a6e81ea526c376a01e8", size = 609436, upload_time = "2023-12-05T07:42:37.762Z" }, + { url = "https://files.pythonhosted.org/packages/41/81/ace39daa19c78b2f4fc12ef217d9d5f1ac658d5828d692bbbb68240cd55b/pyzmq-25.1.2-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c61e346ac34b74028ede1c6b4bcecf649d69b707b3ff9dc0fab453821b04d1e", size = 843396, upload_time = "2023-12-05T07:44:43.727Z" }, + { url = "https://files.pythonhosted.org/packages/4c/43/150b0b203f5461a9aeadaa925c55167e2b4215c9322b6911a64360d2243e/pyzmq-25.1.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cb8fc1f8d69b411b8ec0b5f1ffbcaf14c1db95b6bccea21d83610987435f1a4", size = 800856, upload_time = "2023-12-05T07:45:21.117Z" }, + { url = "https://files.pythonhosted.org/packages/5f/91/a618b56aaabe40dddcd25db85624d7408768fd32f5bfcf81bc0af5b1ce75/pyzmq-25.1.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:3c00c9b7d1ca8165c610437ca0c92e7b5607b2f9076f4eb4b095c85d6e680a1d", size = 413836, upload_time = "2023-12-05T07:53:22.583Z" }, ] [[package]] @@ -2118,9 +2176,9 @@ dependencies = [ { name = "scikit-learn" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3e/2d/bab8babd9dc9a9e4df6eb115540cee4322c1a74078fb6f3b3ebc452a22b3/qudida-0.0.4.tar.gz", hash = "sha256:db198e2887ab0c9aa0023e565afbff41dfb76b361f85fd5e13f780d75ba18cc8", size = 3100 } +sdist = { url = "https://files.pythonhosted.org/packages/3e/2d/bab8babd9dc9a9e4df6eb115540cee4322c1a74078fb6f3b3ebc452a22b3/qudida-0.0.4.tar.gz", hash = "sha256:db198e2887ab0c9aa0023e565afbff41dfb76b361f85fd5e13f780d75ba18cc8", size = 3100, upload_time = "2021-08-09T16:47:55.807Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f0/a1/a5f4bebaa31d109003909809d88aeb0d4b201463a9ea29308d9e4f9e7655/qudida-0.0.4-py3-none-any.whl", hash = "sha256:4519714c40cd0f2e6c51e1735edae8f8b19f4efe1f33be13e9d644ca5f736dd6", size = 3478 }, + { url = "https://files.pythonhosted.org/packages/f0/a1/a5f4bebaa31d109003909809d88aeb0d4b201463a9ea29308d9e4f9e7655/qudida-0.0.4-py3-none-any.whl", hash = "sha256:4519714c40cd0f2e6c51e1735edae8f8b19f4efe1f33be13e9d644ca5f736dd6", size = 3478, upload_time = "2021-08-09T16:47:54.637Z" }, ] [[package]] @@ -2133,9 +2191,9 @@ dependencies = [ { name = "idna" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218 } +sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218, upload_time = "2024-05-29T15:37:49.536Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 }, + { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928, upload_time = "2024-05-29T15:37:47.027Z" }, ] [[package]] @@ -2147,9 +2205,9 @@ dependencies = [ { name = "pygments" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 } +sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149, upload_time = "2024-11-01T16:43:57.873Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 }, + { url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424, upload_time = "2024-11-01T16:43:55.817Z" }, ] [[package]] @@ -2162,9 +2220,9 @@ dependencies = [ { name = "ruamel-yaml" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/77/6af374a4a8cd2aee762a1fb8a3050dcf3f129134bbdc4bb6bed755c4325b/rknn_toolkit_lite2-2.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b6733689bd09a262bcb6ba4744e690dd4b37ebeac4ed427cf45242c4b4ce9a4", size = 559372 }, - { url = "https://files.pythonhosted.org/packages/9b/0c/76ff1eb09d09ce4394a6959d2343a321d28dd9e604348ffdafceafdc344c/rknn_toolkit_lite2-2.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3e4fefe355dc34a155680e4bcb9e4abb37ebc271f045ec9e0a4a3a018bc5beb", size = 569149 }, - { url = "https://files.pythonhosted.org/packages/0d/6e/8679562028051b02312212defc6e8c07248953f10dd7ad506e941b575bf3/rknn_toolkit_lite2-2.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37394371d1561f470c553f39869d7c35ff93405dffe3d0d72babf297a2b0aee9", size = 527457 }, + { url = "https://files.pythonhosted.org/packages/ed/77/6af374a4a8cd2aee762a1fb8a3050dcf3f129134bbdc4bb6bed755c4325b/rknn_toolkit_lite2-2.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b6733689bd09a262bcb6ba4744e690dd4b37ebeac4ed427cf45242c4b4ce9a4", size = 559372, upload_time = "2024-11-11T03:51:20.599Z" }, + { url = "https://files.pythonhosted.org/packages/9b/0c/76ff1eb09d09ce4394a6959d2343a321d28dd9e604348ffdafceafdc344c/rknn_toolkit_lite2-2.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3e4fefe355dc34a155680e4bcb9e4abb37ebc271f045ec9e0a4a3a018bc5beb", size = 569149, upload_time = "2024-11-11T03:51:22.838Z" }, + { url = "https://files.pythonhosted.org/packages/0d/6e/8679562028051b02312212defc6e8c07248953f10dd7ad506e941b575bf3/rknn_toolkit_lite2-2.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37394371d1561f470c553f39869d7c35ff93405dffe3d0d72babf297a2b0aee9", size = 527457, upload_time = "2024-11-11T03:51:25.456Z" }, ] [[package]] @@ -2174,78 +2232,78 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "ruamel-yaml-clib", marker = "python_full_version < '3.13' and platform_python_implementation == 'CPython'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ea/46/f44d8be06b85bc7c4d8c95d658be2b68f27711f279bf9dd0612a5e4794f5/ruamel.yaml-0.18.10.tar.gz", hash = "sha256:20c86ab29ac2153f80a428e1254a8adf686d3383df04490514ca3b79a362db58", size = 143447 } +sdist = { url = "https://files.pythonhosted.org/packages/ea/46/f44d8be06b85bc7c4d8c95d658be2b68f27711f279bf9dd0612a5e4794f5/ruamel.yaml-0.18.10.tar.gz", hash = "sha256:20c86ab29ac2153f80a428e1254a8adf686d3383df04490514ca3b79a362db58", size = 143447, upload_time = "2025-01-06T14:08:51.334Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c2/36/dfc1ebc0081e6d39924a2cc53654497f967a084a436bb64402dfce4254d9/ruamel.yaml-0.18.10-py3-none-any.whl", hash = "sha256:30f22513ab2301b3d2b577adc121c6471f28734d3d9728581245f1e76468b4f1", size = 117729 }, + { url = "https://files.pythonhosted.org/packages/c2/36/dfc1ebc0081e6d39924a2cc53654497f967a084a436bb64402dfce4254d9/ruamel.yaml-0.18.10-py3-none-any.whl", hash = "sha256:30f22513ab2301b3d2b577adc121c6471f28734d3d9728581245f1e76468b4f1", size = 117729, upload_time = "2025-01-06T14:08:47.471Z" }, ] [[package]] name = "ruamel-yaml-clib" version = "0.2.12" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/20/84/80203abff8ea4993a87d823a5f632e4d92831ef75d404c9fc78d0176d2b5/ruamel.yaml.clib-0.2.12.tar.gz", hash = "sha256:6c8fbb13ec503f99a91901ab46e0b07ae7941cd527393187039aec586fdfd36f", size = 225315 } +sdist = { url = "https://files.pythonhosted.org/packages/20/84/80203abff8ea4993a87d823a5f632e4d92831ef75d404c9fc78d0176d2b5/ruamel.yaml.clib-0.2.12.tar.gz", hash = "sha256:6c8fbb13ec503f99a91901ab46e0b07ae7941cd527393187039aec586fdfd36f", size = 225315, upload_time = "2024-10-20T10:10:56.22Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/70/57/40a958e863e299f0c74ef32a3bde9f2d1ea8d69669368c0c502a0997f57f/ruamel.yaml.clib-0.2.12-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:11f891336688faf5156a36293a9c362bdc7c88f03a8a027c2c1d8e0bcde998e5", size = 131301 }, - { url = "https://files.pythonhosted.org/packages/98/a8/29a3eb437b12b95f50a6bcc3d7d7214301c6c529d8fdc227247fa84162b5/ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:a606ef75a60ecf3d924613892cc603b154178ee25abb3055db5062da811fd969", size = 633728 }, - { url = "https://files.pythonhosted.org/packages/35/6d/ae05a87a3ad540259c3ad88d71275cbd1c0f2d30ae04c65dcbfb6dcd4b9f/ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd5415dded15c3822597455bc02bcd66e81ef8b7a48cb71a33628fc9fdde39df", size = 722230 }, - { url = "https://files.pythonhosted.org/packages/7f/b7/20c6f3c0b656fe609675d69bc135c03aac9e3865912444be6339207b6648/ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f66efbc1caa63c088dead1c4170d148eabc9b80d95fb75b6c92ac0aad2437d76", size = 686712 }, - { url = "https://files.pythonhosted.org/packages/cd/11/d12dbf683471f888d354dac59593873c2b45feb193c5e3e0f2ebf85e68b9/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:22353049ba4181685023b25b5b51a574bce33e7f51c759371a7422dcae5402a6", size = 663936 }, - { url = "https://files.pythonhosted.org/packages/72/14/4c268f5077db5c83f743ee1daeb236269fa8577133a5cfa49f8b382baf13/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:932205970b9f9991b34f55136be327501903f7c66830e9760a8ffb15b07f05cd", size = 696580 }, - { url = "https://files.pythonhosted.org/packages/30/fc/8cd12f189c6405a4c1cf37bd633aa740a9538c8e40497c231072d0fef5cf/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a52d48f4e7bf9005e8f0a89209bf9a73f7190ddf0489eee5eb51377385f59f2a", size = 663393 }, - { url = "https://files.pythonhosted.org/packages/80/29/c0a017b704aaf3cbf704989785cd9c5d5b8ccec2dae6ac0c53833c84e677/ruamel.yaml.clib-0.2.12-cp310-cp310-win32.whl", hash = "sha256:3eac5a91891ceb88138c113f9db04f3cebdae277f5d44eaa3651a4f573e6a5da", size = 100326 }, - { url = "https://files.pythonhosted.org/packages/3a/65/fa39d74db4e2d0cd252355732d966a460a41cd01c6353b820a0952432839/ruamel.yaml.clib-0.2.12-cp310-cp310-win_amd64.whl", hash = "sha256:ab007f2f5a87bd08ab1499bdf96f3d5c6ad4dcfa364884cb4549aa0154b13a28", size = 118079 }, - { url = "https://files.pythonhosted.org/packages/fb/8f/683c6ad562f558cbc4f7c029abcd9599148c51c54b5ef0f24f2638da9fbb/ruamel.yaml.clib-0.2.12-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:4a6679521a58256a90b0d89e03992c15144c5f3858f40d7c18886023d7943db6", size = 132224 }, - { url = "https://files.pythonhosted.org/packages/3c/d2/b79b7d695e2f21da020bd44c782490578f300dd44f0a4c57a92575758a76/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:d84318609196d6bd6da0edfa25cedfbabd8dbde5140a0a23af29ad4b8f91fb1e", size = 641480 }, - { url = "https://files.pythonhosted.org/packages/68/6e/264c50ce2a31473a9fdbf4fa66ca9b2b17c7455b31ef585462343818bd6c/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb43a269eb827806502c7c8efb7ae7e9e9d0573257a46e8e952f4d4caba4f31e", size = 739068 }, - { url = "https://files.pythonhosted.org/packages/86/29/88c2567bc893c84d88b4c48027367c3562ae69121d568e8a3f3a8d363f4d/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:811ea1594b8a0fb466172c384267a4e5e367298af6b228931f273b111f17ef52", size = 703012 }, - { url = "https://files.pythonhosted.org/packages/11/46/879763c619b5470820f0cd6ca97d134771e502776bc2b844d2adb6e37753/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cf12567a7b565cbf65d438dec6cfbe2917d3c1bdddfce84a9930b7d35ea59642", size = 704352 }, - { url = "https://files.pythonhosted.org/packages/02/80/ece7e6034256a4186bbe50dee28cd032d816974941a6abf6a9d65e4228a7/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7dd5adc8b930b12c8fc5b99e2d535a09889941aa0d0bd06f4749e9a9397c71d2", size = 737344 }, - { url = "https://files.pythonhosted.org/packages/f0/ca/e4106ac7e80efbabdf4bf91d3d32fc424e41418458251712f5672eada9ce/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1492a6051dab8d912fc2adeef0e8c72216b24d57bd896ea607cb90bb0c4981d3", size = 714498 }, - { url = "https://files.pythonhosted.org/packages/67/58/b1f60a1d591b771298ffa0428237afb092c7f29ae23bad93420b1eb10703/ruamel.yaml.clib-0.2.12-cp311-cp311-win32.whl", hash = "sha256:bd0a08f0bab19093c54e18a14a10b4322e1eacc5217056f3c063bd2f59853ce4", size = 100205 }, - { url = "https://files.pythonhosted.org/packages/b4/4f/b52f634c9548a9291a70dfce26ca7ebce388235c93588a1068028ea23fcc/ruamel.yaml.clib-0.2.12-cp311-cp311-win_amd64.whl", hash = "sha256:a274fb2cb086c7a3dea4322ec27f4cb5cc4b6298adb583ab0e211a4682f241eb", size = 118185 }, - { url = "https://files.pythonhosted.org/packages/48/41/e7a405afbdc26af961678474a55373e1b323605a4f5e2ddd4a80ea80f628/ruamel.yaml.clib-0.2.12-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:20b0f8dc160ba83b6dcc0e256846e1a02d044e13f7ea74a3d1d56ede4e48c632", size = 133433 }, - { url = "https://files.pythonhosted.org/packages/ec/b0/b850385604334c2ce90e3ee1013bd911aedf058a934905863a6ea95e9eb4/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:943f32bc9dedb3abff9879edc134901df92cfce2c3d5c9348f172f62eb2d771d", size = 647362 }, - { url = "https://files.pythonhosted.org/packages/44/d0/3f68a86e006448fb6c005aee66565b9eb89014a70c491d70c08de597f8e4/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95c3829bb364fdb8e0332c9931ecf57d9be3519241323c5274bd82f709cebc0c", size = 754118 }, - { url = "https://files.pythonhosted.org/packages/52/a9/d39f3c5ada0a3bb2870d7db41901125dbe2434fa4f12ca8c5b83a42d7c53/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:749c16fcc4a2b09f28843cda5a193e0283e47454b63ec4b81eaa2242f50e4ccd", size = 706497 }, - { url = "https://files.pythonhosted.org/packages/b0/fa/097e38135dadd9ac25aecf2a54be17ddf6e4c23e43d538492a90ab3d71c6/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bf165fef1f223beae7333275156ab2022cffe255dcc51c27f066b4370da81e31", size = 698042 }, - { url = "https://files.pythonhosted.org/packages/ec/d5/a659ca6f503b9379b930f13bc6b130c9f176469b73b9834296822a83a132/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:32621c177bbf782ca5a18ba4d7af0f1082a3f6e517ac2a18b3974d4edf349680", size = 745831 }, - { url = "https://files.pythonhosted.org/packages/db/5d/36619b61ffa2429eeaefaab4f3374666adf36ad8ac6330d855848d7d36fd/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b82a7c94a498853aa0b272fd5bc67f29008da798d4f93a2f9f289feb8426a58d", size = 715692 }, - { url = "https://files.pythonhosted.org/packages/b1/82/85cb92f15a4231c89b95dfe08b09eb6adca929ef7df7e17ab59902b6f589/ruamel.yaml.clib-0.2.12-cp312-cp312-win32.whl", hash = "sha256:e8c4ebfcfd57177b572e2040777b8abc537cdef58a2120e830124946aa9b42c5", size = 98777 }, - { url = "https://files.pythonhosted.org/packages/d7/8f/c3654f6f1ddb75daf3922c3d8fc6005b1ab56671ad56ffb874d908bfa668/ruamel.yaml.clib-0.2.12-cp312-cp312-win_amd64.whl", hash = "sha256:0467c5965282c62203273b838ae77c0d29d7638c8a4e3a1c8bdd3602c10904e4", size = 115523 }, - { url = "https://files.pythonhosted.org/packages/29/00/4864119668d71a5fa45678f380b5923ff410701565821925c69780356ffa/ruamel.yaml.clib-0.2.12-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4c8c5d82f50bb53986a5e02d1b3092b03622c02c2eb78e29bec33fd9593bae1a", size = 132011 }, - { url = "https://files.pythonhosted.org/packages/7f/5e/212f473a93ae78c669ffa0cb051e3fee1139cb2d385d2ae1653d64281507/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux2014_aarch64.whl", hash = "sha256:e7e3736715fbf53e9be2a79eb4db68e4ed857017344d697e8b9749444ae57475", size = 642488 }, - { url = "https://files.pythonhosted.org/packages/1f/8f/ecfbe2123ade605c49ef769788f79c38ddb1c8fa81e01f4dbf5cf1a44b16/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b7e75b4965e1d4690e93021adfcecccbca7d61c7bddd8e22406ef2ff20d74ef", size = 745066 }, - { url = "https://files.pythonhosted.org/packages/e2/a9/28f60726d29dfc01b8decdb385de4ced2ced9faeb37a847bd5cf26836815/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96777d473c05ee3e5e3c3e999f5d23c6f4ec5b0c38c098b3a5229085f74236c6", size = 701785 }, - { url = "https://files.pythonhosted.org/packages/84/7e/8e7ec45920daa7f76046578e4f677a3215fe8f18ee30a9cb7627a19d9b4c/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:3bc2a80e6420ca8b7d3590791e2dfc709c88ab9152c00eeb511c9875ce5778bf", size = 693017 }, - { url = "https://files.pythonhosted.org/packages/c5/b3/d650eaade4ca225f02a648321e1ab835b9d361c60d51150bac49063b83fa/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e188d2699864c11c36cdfdada94d781fd5d6b0071cd9c427bceb08ad3d7c70e1", size = 741270 }, - { url = "https://files.pythonhosted.org/packages/87/b8/01c29b924dcbbed75cc45b30c30d565d763b9c4d540545a0eeecffb8f09c/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f6f3eac23941b32afccc23081e1f50612bdbe4e982012ef4f5797986828cd01", size = 709059 }, - { url = "https://files.pythonhosted.org/packages/30/8c/ed73f047a73638257aa9377ad356bea4d96125b305c34a28766f4445cc0f/ruamel.yaml.clib-0.2.12-cp313-cp313-win32.whl", hash = "sha256:6442cb36270b3afb1b4951f060eccca1ce49f3d087ca1ca4563a6eb479cb3de6", size = 98583 }, - { url = "https://files.pythonhosted.org/packages/b0/85/e8e751d8791564dd333d5d9a4eab0a7a115f7e349595417fd50ecae3395c/ruamel.yaml.clib-0.2.12-cp313-cp313-win_amd64.whl", hash = "sha256:e5b8daf27af0b90da7bb903a876477a9e6d7270be6146906b276605997c7e9a3", size = 115190 }, + { url = "https://files.pythonhosted.org/packages/70/57/40a958e863e299f0c74ef32a3bde9f2d1ea8d69669368c0c502a0997f57f/ruamel.yaml.clib-0.2.12-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:11f891336688faf5156a36293a9c362bdc7c88f03a8a027c2c1d8e0bcde998e5", size = 131301, upload_time = "2024-10-20T10:12:35.876Z" }, + { url = "https://files.pythonhosted.org/packages/98/a8/29a3eb437b12b95f50a6bcc3d7d7214301c6c529d8fdc227247fa84162b5/ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:a606ef75a60ecf3d924613892cc603b154178ee25abb3055db5062da811fd969", size = 633728, upload_time = "2024-10-20T10:12:37.858Z" }, + { url = "https://files.pythonhosted.org/packages/35/6d/ae05a87a3ad540259c3ad88d71275cbd1c0f2d30ae04c65dcbfb6dcd4b9f/ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd5415dded15c3822597455bc02bcd66e81ef8b7a48cb71a33628fc9fdde39df", size = 722230, upload_time = "2024-10-20T10:12:39.457Z" }, + { url = "https://files.pythonhosted.org/packages/7f/b7/20c6f3c0b656fe609675d69bc135c03aac9e3865912444be6339207b6648/ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f66efbc1caa63c088dead1c4170d148eabc9b80d95fb75b6c92ac0aad2437d76", size = 686712, upload_time = "2024-10-20T10:12:41.119Z" }, + { url = "https://files.pythonhosted.org/packages/cd/11/d12dbf683471f888d354dac59593873c2b45feb193c5e3e0f2ebf85e68b9/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:22353049ba4181685023b25b5b51a574bce33e7f51c759371a7422dcae5402a6", size = 663936, upload_time = "2024-10-21T11:26:37.419Z" }, + { url = "https://files.pythonhosted.org/packages/72/14/4c268f5077db5c83f743ee1daeb236269fa8577133a5cfa49f8b382baf13/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:932205970b9f9991b34f55136be327501903f7c66830e9760a8ffb15b07f05cd", size = 696580, upload_time = "2024-10-21T11:26:39.503Z" }, + { url = "https://files.pythonhosted.org/packages/30/fc/8cd12f189c6405a4c1cf37bd633aa740a9538c8e40497c231072d0fef5cf/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a52d48f4e7bf9005e8f0a89209bf9a73f7190ddf0489eee5eb51377385f59f2a", size = 663393, upload_time = "2024-12-11T19:58:13.873Z" }, + { url = "https://files.pythonhosted.org/packages/80/29/c0a017b704aaf3cbf704989785cd9c5d5b8ccec2dae6ac0c53833c84e677/ruamel.yaml.clib-0.2.12-cp310-cp310-win32.whl", hash = "sha256:3eac5a91891ceb88138c113f9db04f3cebdae277f5d44eaa3651a4f573e6a5da", size = 100326, upload_time = "2024-10-20T10:12:42.967Z" }, + { url = "https://files.pythonhosted.org/packages/3a/65/fa39d74db4e2d0cd252355732d966a460a41cd01c6353b820a0952432839/ruamel.yaml.clib-0.2.12-cp310-cp310-win_amd64.whl", hash = "sha256:ab007f2f5a87bd08ab1499bdf96f3d5c6ad4dcfa364884cb4549aa0154b13a28", size = 118079, upload_time = "2024-10-20T10:12:44.117Z" }, + { url = "https://files.pythonhosted.org/packages/fb/8f/683c6ad562f558cbc4f7c029abcd9599148c51c54b5ef0f24f2638da9fbb/ruamel.yaml.clib-0.2.12-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:4a6679521a58256a90b0d89e03992c15144c5f3858f40d7c18886023d7943db6", size = 132224, upload_time = "2024-10-20T10:12:45.162Z" }, + { url = "https://files.pythonhosted.org/packages/3c/d2/b79b7d695e2f21da020bd44c782490578f300dd44f0a4c57a92575758a76/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:d84318609196d6bd6da0edfa25cedfbabd8dbde5140a0a23af29ad4b8f91fb1e", size = 641480, upload_time = "2024-10-20T10:12:46.758Z" }, + { url = "https://files.pythonhosted.org/packages/68/6e/264c50ce2a31473a9fdbf4fa66ca9b2b17c7455b31ef585462343818bd6c/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb43a269eb827806502c7c8efb7ae7e9e9d0573257a46e8e952f4d4caba4f31e", size = 739068, upload_time = "2024-10-20T10:12:48.605Z" }, + { url = "https://files.pythonhosted.org/packages/86/29/88c2567bc893c84d88b4c48027367c3562ae69121d568e8a3f3a8d363f4d/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:811ea1594b8a0fb466172c384267a4e5e367298af6b228931f273b111f17ef52", size = 703012, upload_time = "2024-10-20T10:12:51.124Z" }, + { url = "https://files.pythonhosted.org/packages/11/46/879763c619b5470820f0cd6ca97d134771e502776bc2b844d2adb6e37753/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cf12567a7b565cbf65d438dec6cfbe2917d3c1bdddfce84a9930b7d35ea59642", size = 704352, upload_time = "2024-10-21T11:26:41.438Z" }, + { url = "https://files.pythonhosted.org/packages/02/80/ece7e6034256a4186bbe50dee28cd032d816974941a6abf6a9d65e4228a7/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7dd5adc8b930b12c8fc5b99e2d535a09889941aa0d0bd06f4749e9a9397c71d2", size = 737344, upload_time = "2024-10-21T11:26:43.62Z" }, + { url = "https://files.pythonhosted.org/packages/f0/ca/e4106ac7e80efbabdf4bf91d3d32fc424e41418458251712f5672eada9ce/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1492a6051dab8d912fc2adeef0e8c72216b24d57bd896ea607cb90bb0c4981d3", size = 714498, upload_time = "2024-12-11T19:58:15.592Z" }, + { url = "https://files.pythonhosted.org/packages/67/58/b1f60a1d591b771298ffa0428237afb092c7f29ae23bad93420b1eb10703/ruamel.yaml.clib-0.2.12-cp311-cp311-win32.whl", hash = "sha256:bd0a08f0bab19093c54e18a14a10b4322e1eacc5217056f3c063bd2f59853ce4", size = 100205, upload_time = "2024-10-20T10:12:52.865Z" }, + { url = "https://files.pythonhosted.org/packages/b4/4f/b52f634c9548a9291a70dfce26ca7ebce388235c93588a1068028ea23fcc/ruamel.yaml.clib-0.2.12-cp311-cp311-win_amd64.whl", hash = "sha256:a274fb2cb086c7a3dea4322ec27f4cb5cc4b6298adb583ab0e211a4682f241eb", size = 118185, upload_time = "2024-10-20T10:12:54.652Z" }, + { url = "https://files.pythonhosted.org/packages/48/41/e7a405afbdc26af961678474a55373e1b323605a4f5e2ddd4a80ea80f628/ruamel.yaml.clib-0.2.12-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:20b0f8dc160ba83b6dcc0e256846e1a02d044e13f7ea74a3d1d56ede4e48c632", size = 133433, upload_time = "2024-10-20T10:12:55.657Z" }, + { url = "https://files.pythonhosted.org/packages/ec/b0/b850385604334c2ce90e3ee1013bd911aedf058a934905863a6ea95e9eb4/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:943f32bc9dedb3abff9879edc134901df92cfce2c3d5c9348f172f62eb2d771d", size = 647362, upload_time = "2024-10-20T10:12:57.155Z" }, + { url = "https://files.pythonhosted.org/packages/44/d0/3f68a86e006448fb6c005aee66565b9eb89014a70c491d70c08de597f8e4/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95c3829bb364fdb8e0332c9931ecf57d9be3519241323c5274bd82f709cebc0c", size = 754118, upload_time = "2024-10-20T10:12:58.501Z" }, + { url = "https://files.pythonhosted.org/packages/52/a9/d39f3c5ada0a3bb2870d7db41901125dbe2434fa4f12ca8c5b83a42d7c53/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:749c16fcc4a2b09f28843cda5a193e0283e47454b63ec4b81eaa2242f50e4ccd", size = 706497, upload_time = "2024-10-20T10:13:00.211Z" }, + { url = "https://files.pythonhosted.org/packages/b0/fa/097e38135dadd9ac25aecf2a54be17ddf6e4c23e43d538492a90ab3d71c6/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bf165fef1f223beae7333275156ab2022cffe255dcc51c27f066b4370da81e31", size = 698042, upload_time = "2024-10-21T11:26:46.038Z" }, + { url = "https://files.pythonhosted.org/packages/ec/d5/a659ca6f503b9379b930f13bc6b130c9f176469b73b9834296822a83a132/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:32621c177bbf782ca5a18ba4d7af0f1082a3f6e517ac2a18b3974d4edf349680", size = 745831, upload_time = "2024-10-21T11:26:47.487Z" }, + { url = "https://files.pythonhosted.org/packages/db/5d/36619b61ffa2429eeaefaab4f3374666adf36ad8ac6330d855848d7d36fd/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b82a7c94a498853aa0b272fd5bc67f29008da798d4f93a2f9f289feb8426a58d", size = 715692, upload_time = "2024-12-11T19:58:17.252Z" }, + { url = "https://files.pythonhosted.org/packages/b1/82/85cb92f15a4231c89b95dfe08b09eb6adca929ef7df7e17ab59902b6f589/ruamel.yaml.clib-0.2.12-cp312-cp312-win32.whl", hash = "sha256:e8c4ebfcfd57177b572e2040777b8abc537cdef58a2120e830124946aa9b42c5", size = 98777, upload_time = "2024-10-20T10:13:01.395Z" }, + { url = "https://files.pythonhosted.org/packages/d7/8f/c3654f6f1ddb75daf3922c3d8fc6005b1ab56671ad56ffb874d908bfa668/ruamel.yaml.clib-0.2.12-cp312-cp312-win_amd64.whl", hash = "sha256:0467c5965282c62203273b838ae77c0d29d7638c8a4e3a1c8bdd3602c10904e4", size = 115523, upload_time = "2024-10-20T10:13:02.768Z" }, + { url = "https://files.pythonhosted.org/packages/29/00/4864119668d71a5fa45678f380b5923ff410701565821925c69780356ffa/ruamel.yaml.clib-0.2.12-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4c8c5d82f50bb53986a5e02d1b3092b03622c02c2eb78e29bec33fd9593bae1a", size = 132011, upload_time = "2024-10-20T10:13:04.377Z" }, + { url = "https://files.pythonhosted.org/packages/7f/5e/212f473a93ae78c669ffa0cb051e3fee1139cb2d385d2ae1653d64281507/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux2014_aarch64.whl", hash = "sha256:e7e3736715fbf53e9be2a79eb4db68e4ed857017344d697e8b9749444ae57475", size = 642488, upload_time = "2024-10-20T10:13:05.906Z" }, + { url = "https://files.pythonhosted.org/packages/1f/8f/ecfbe2123ade605c49ef769788f79c38ddb1c8fa81e01f4dbf5cf1a44b16/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b7e75b4965e1d4690e93021adfcecccbca7d61c7bddd8e22406ef2ff20d74ef", size = 745066, upload_time = "2024-10-20T10:13:07.26Z" }, + { url = "https://files.pythonhosted.org/packages/e2/a9/28f60726d29dfc01b8decdb385de4ced2ced9faeb37a847bd5cf26836815/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96777d473c05ee3e5e3c3e999f5d23c6f4ec5b0c38c098b3a5229085f74236c6", size = 701785, upload_time = "2024-10-20T10:13:08.504Z" }, + { url = "https://files.pythonhosted.org/packages/84/7e/8e7ec45920daa7f76046578e4f677a3215fe8f18ee30a9cb7627a19d9b4c/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:3bc2a80e6420ca8b7d3590791e2dfc709c88ab9152c00eeb511c9875ce5778bf", size = 693017, upload_time = "2024-10-21T11:26:48.866Z" }, + { url = "https://files.pythonhosted.org/packages/c5/b3/d650eaade4ca225f02a648321e1ab835b9d361c60d51150bac49063b83fa/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e188d2699864c11c36cdfdada94d781fd5d6b0071cd9c427bceb08ad3d7c70e1", size = 741270, upload_time = "2024-10-21T11:26:50.213Z" }, + { url = "https://files.pythonhosted.org/packages/87/b8/01c29b924dcbbed75cc45b30c30d565d763b9c4d540545a0eeecffb8f09c/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f6f3eac23941b32afccc23081e1f50612bdbe4e982012ef4f5797986828cd01", size = 709059, upload_time = "2024-12-11T19:58:18.846Z" }, + { url = "https://files.pythonhosted.org/packages/30/8c/ed73f047a73638257aa9377ad356bea4d96125b305c34a28766f4445cc0f/ruamel.yaml.clib-0.2.12-cp313-cp313-win32.whl", hash = "sha256:6442cb36270b3afb1b4951f060eccca1ce49f3d087ca1ca4563a6eb479cb3de6", size = 98583, upload_time = "2024-10-20T10:13:09.658Z" }, + { url = "https://files.pythonhosted.org/packages/b0/85/e8e751d8791564dd333d5d9a4eab0a7a115f7e349595417fd50ecae3395c/ruamel.yaml.clib-0.2.12-cp313-cp313-win_amd64.whl", hash = "sha256:e5b8daf27af0b90da7bb903a876477a9e6d7270be6146906b276605997c7e9a3", size = 115190, upload_time = "2024-10-20T10:13:10.66Z" }, ] [[package]] name = "ruff" -version = "0.11.5" +version = "0.11.7" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/45/71/5759b2a6b2279bb77fe15b1435b89473631c2cd6374d45ccdb6b785810be/ruff-0.11.5.tar.gz", hash = "sha256:cae2e2439cb88853e421901ec040a758960b576126dab520fa08e9de431d1bef", size = 3976488 } +sdist = { url = "https://files.pythonhosted.org/packages/5b/89/6f9c9674818ac2e9cc2f2b35b704b7768656e6b7c139064fc7ba8fbc99f1/ruff-0.11.7.tar.gz", hash = "sha256:655089ad3224070736dc32844fde783454f8558e71f501cb207485fe4eee23d4", size = 4054861, upload_time = "2025-04-24T18:49:37.007Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/23/db/6efda6381778eec7f35875b5cbefd194904832a1153d68d36d6b269d81a8/ruff-0.11.5-py3-none-linux_armv6l.whl", hash = "sha256:2561294e108eb648e50f210671cc56aee590fb6167b594144401532138c66c7b", size = 10103150 }, - { url = "https://files.pythonhosted.org/packages/44/f2/06cd9006077a8db61956768bc200a8e52515bf33a8f9b671ee527bb10d77/ruff-0.11.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ac12884b9e005c12d0bd121f56ccf8033e1614f736f766c118ad60780882a077", size = 10898637 }, - { url = "https://files.pythonhosted.org/packages/18/f5/af390a013c56022fe6f72b95c86eb7b2585c89cc25d63882d3bfe411ecf1/ruff-0.11.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:4bfd80a6ec559a5eeb96c33f832418bf0fb96752de0539905cf7b0cc1d31d779", size = 10236012 }, - { url = "https://files.pythonhosted.org/packages/b8/ca/b9bf954cfed165e1a0c24b86305d5c8ea75def256707f2448439ac5e0d8b/ruff-0.11.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0947c0a1afa75dcb5db4b34b070ec2bccee869d40e6cc8ab25aca11a7d527794", size = 10415338 }, - { url = "https://files.pythonhosted.org/packages/d9/4d/2522dde4e790f1b59885283f8786ab0046958dfd39959c81acc75d347467/ruff-0.11.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ad871ff74b5ec9caa66cb725b85d4ef89b53f8170f47c3406e32ef040400b038", size = 9965277 }, - { url = "https://files.pythonhosted.org/packages/e5/7a/749f56f150eef71ce2f626a2f6988446c620af2f9ba2a7804295ca450397/ruff-0.11.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e6cf918390cfe46d240732d4d72fa6e18e528ca1f60e318a10835cf2fa3dc19f", size = 11541614 }, - { url = "https://files.pythonhosted.org/packages/89/b2/7d9b8435222485b6aac627d9c29793ba89be40b5de11584ca604b829e960/ruff-0.11.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:56145ee1478582f61c08f21076dc59153310d606ad663acc00ea3ab5b2125f82", size = 12198873 }, - { url = "https://files.pythonhosted.org/packages/00/e0/a1a69ef5ffb5c5f9c31554b27e030a9c468fc6f57055886d27d316dfbabd/ruff-0.11.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e5f66f8f1e8c9fc594cbd66fbc5f246a8d91f916cb9667e80208663ec3728304", size = 11670190 }, - { url = "https://files.pythonhosted.org/packages/05/61/c1c16df6e92975072c07f8b20dad35cd858e8462b8865bc856fe5d6ccb63/ruff-0.11.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80b4df4d335a80315ab9afc81ed1cff62be112bd165e162b5eed8ac55bfc8470", size = 13902301 }, - { url = "https://files.pythonhosted.org/packages/79/89/0af10c8af4363304fd8cb833bd407a2850c760b71edf742c18d5a87bb3ad/ruff-0.11.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3068befab73620b8a0cc2431bd46b3cd619bc17d6f7695a3e1bb166b652c382a", size = 11350132 }, - { url = "https://files.pythonhosted.org/packages/b9/e1/ecb4c687cbf15164dd00e38cf62cbab238cad05dd8b6b0fc68b0c2785e15/ruff-0.11.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f5da2e710a9641828e09aa98b92c9ebbc60518fdf3921241326ca3e8f8e55b8b", size = 10312937 }, - { url = "https://files.pythonhosted.org/packages/cf/4f/0e53fe5e500b65934500949361e3cd290c5ba60f0324ed59d15f46479c06/ruff-0.11.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ef39f19cb8ec98cbc762344921e216f3857a06c47412030374fffd413fb8fd3a", size = 9936683 }, - { url = "https://files.pythonhosted.org/packages/04/a8/8183c4da6d35794ae7f76f96261ef5960853cd3f899c2671961f97a27d8e/ruff-0.11.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:b2a7cedf47244f431fd11aa5a7e2806dda2e0c365873bda7834e8f7d785ae159", size = 10950217 }, - { url = "https://files.pythonhosted.org/packages/26/88/9b85a5a8af21e46a0639b107fcf9bfc31da4f1d263f2fc7fbe7199b47f0a/ruff-0.11.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:81be52e7519f3d1a0beadcf8e974715b2dfc808ae8ec729ecfc79bddf8dbb783", size = 11404521 }, - { url = "https://files.pythonhosted.org/packages/fc/52/047f35d3b20fd1ae9ccfe28791ef0f3ca0ef0b3e6c1a58badd97d450131b/ruff-0.11.5-py3-none-win32.whl", hash = "sha256:e268da7b40f56e3eca571508a7e567e794f9bfcc0f412c4b607931d3af9c4afe", size = 10320697 }, - { url = "https://files.pythonhosted.org/packages/b9/fe/00c78010e3332a6e92762424cf4c1919065707e962232797d0b57fd8267e/ruff-0.11.5-py3-none-win_amd64.whl", hash = "sha256:6c6dc38af3cfe2863213ea25b6dc616d679205732dc0fb673356c2d69608f800", size = 11378665 }, - { url = "https://files.pythonhosted.org/packages/43/7c/c83fe5cbb70ff017612ff36654edfebec4b1ef79b558b8e5fd933bab836b/ruff-0.11.5-py3-none-win_arm64.whl", hash = "sha256:67e241b4314f4eacf14a601d586026a962f4002a475aa702c69980a38087aa4e", size = 10460287 }, + { url = "https://files.pythonhosted.org/packages/b4/ec/21927cb906c5614b786d1621dba405e3d44f6e473872e6df5d1a6bca0455/ruff-0.11.7-py3-none-linux_armv6l.whl", hash = "sha256:d29e909d9a8d02f928d72ab7837b5cbc450a5bdf578ab9ebee3263d0a525091c", size = 10245403, upload_time = "2025-04-24T18:48:40.459Z" }, + { url = "https://files.pythonhosted.org/packages/e2/af/fec85b6c2c725bcb062a354dd7cbc1eed53c33ff3aa665165871c9c16ddf/ruff-0.11.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:dd1fb86b168ae349fb01dd497d83537b2c5541fe0626e70c786427dd8363aaee", size = 11007166, upload_time = "2025-04-24T18:48:44.742Z" }, + { url = "https://files.pythonhosted.org/packages/31/9a/2d0d260a58e81f388800343a45898fd8df73c608b8261c370058b675319a/ruff-0.11.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d3d7d2e140a6fbbc09033bce65bd7ea29d6a0adeb90b8430262fbacd58c38ada", size = 10378076, upload_time = "2025-04-24T18:48:47.918Z" }, + { url = "https://files.pythonhosted.org/packages/c2/c4/9b09b45051404d2e7dd6d9dbcbabaa5ab0093f9febcae664876a77b9ad53/ruff-0.11.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4809df77de390a1c2077d9b7945d82f44b95d19ceccf0c287c56e4dc9b91ca64", size = 10557138, upload_time = "2025-04-24T18:48:51.707Z" }, + { url = "https://files.pythonhosted.org/packages/5e/5e/f62a1b6669870a591ed7db771c332fabb30f83c967f376b05e7c91bccd14/ruff-0.11.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f3a0c2e169e6b545f8e2dba185eabbd9db4f08880032e75aa0e285a6d3f48201", size = 10095726, upload_time = "2025-04-24T18:48:54.243Z" }, + { url = "https://files.pythonhosted.org/packages/45/59/a7aa8e716f4cbe07c3500a391e58c52caf665bb242bf8be42c62adef649c/ruff-0.11.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49b888200a320dd96a68e86736cf531d6afba03e4f6cf098401406a257fcf3d6", size = 11672265, upload_time = "2025-04-24T18:48:57.639Z" }, + { url = "https://files.pythonhosted.org/packages/dd/e3/101a8b707481f37aca5f0fcc3e42932fa38b51add87bfbd8e41ab14adb24/ruff-0.11.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:2b19cdb9cf7dae00d5ee2e7c013540cdc3b31c4f281f1dacb5a799d610e90db4", size = 12331418, upload_time = "2025-04-24T18:49:00.697Z" }, + { url = "https://files.pythonhosted.org/packages/dd/71/037f76cbe712f5cbc7b852e4916cd3cf32301a30351818d32ab71580d1c0/ruff-0.11.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64e0ee994c9e326b43539d133a36a455dbaab477bc84fe7bfbd528abe2f05c1e", size = 11794506, upload_time = "2025-04-24T18:49:03.545Z" }, + { url = "https://files.pythonhosted.org/packages/ca/de/e450b6bab1fc60ef263ef8fcda077fb4977601184877dce1c59109356084/ruff-0.11.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bad82052311479a5865f52c76ecee5d468a58ba44fb23ee15079f17dd4c8fd63", size = 13939084, upload_time = "2025-04-24T18:49:07.159Z" }, + { url = "https://files.pythonhosted.org/packages/0e/2c/1e364cc92970075d7d04c69c928430b23e43a433f044474f57e425cbed37/ruff-0.11.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7940665e74e7b65d427b82bffc1e46710ec7f30d58b4b2d5016e3f0321436502", size = 11450441, upload_time = "2025-04-24T18:49:11.41Z" }, + { url = "https://files.pythonhosted.org/packages/9d/7d/1b048eb460517ff9accd78bca0fa6ae61df2b276010538e586f834f5e402/ruff-0.11.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:169027e31c52c0e36c44ae9a9c7db35e505fee0b39f8d9fca7274a6305295a92", size = 10441060, upload_time = "2025-04-24T18:49:14.184Z" }, + { url = "https://files.pythonhosted.org/packages/3a/57/8dc6ccfd8380e5ca3d13ff7591e8ba46a3b330323515a4996b991b10bd5d/ruff-0.11.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:305b93f9798aee582e91e34437810439acb28b5fc1fee6b8205c78c806845a94", size = 10058689, upload_time = "2025-04-24T18:49:17.559Z" }, + { url = "https://files.pythonhosted.org/packages/23/bf/20487561ed72654147817885559ba2aa705272d8b5dee7654d3ef2dbf912/ruff-0.11.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a681db041ef55550c371f9cd52a3cf17a0da4c75d6bd691092dfc38170ebc4b6", size = 11073703, upload_time = "2025-04-24T18:49:20.247Z" }, + { url = "https://files.pythonhosted.org/packages/9d/27/04f2db95f4ef73dccedd0c21daf9991cc3b7f29901a4362057b132075aa4/ruff-0.11.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:07f1496ad00a4a139f4de220b0c97da6d4c85e0e4aa9b2624167b7d4d44fd6b6", size = 11532822, upload_time = "2025-04-24T18:49:23.765Z" }, + { url = "https://files.pythonhosted.org/packages/e1/72/43b123e4db52144c8add336581de52185097545981ff6e9e58a21861c250/ruff-0.11.7-py3-none-win32.whl", hash = "sha256:f25dfb853ad217e6e5f1924ae8a5b3f6709051a13e9dad18690de6c8ff299e26", size = 10362436, upload_time = "2025-04-24T18:49:27.377Z" }, + { url = "https://files.pythonhosted.org/packages/c5/a0/3e58cd76fdee53d5c8ce7a56d84540833f924ccdf2c7d657cb009e604d82/ruff-0.11.7-py3-none-win_amd64.whl", hash = "sha256:0a931d85959ceb77e92aea4bbedfded0a31534ce191252721128f77e5ae1f98a", size = 11566676, upload_time = "2025-04-24T18:49:30.938Z" }, + { url = "https://files.pythonhosted.org/packages/68/ca/69d7c7752bce162d1516e5592b1cc6b6668e9328c0d270609ddbeeadd7cf/ruff-0.11.7-py3-none-win_arm64.whl", hash = "sha256:778c1e5d6f9e91034142dfd06110534ca13220bfaad5c3735f6cb844654f6177", size = 10677936, upload_time = "2025-04-24T18:49:34.392Z" }, ] [[package]] @@ -2262,23 +2320,23 @@ dependencies = [ { name = "scipy" }, { name = "tifffile" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/65/c1/a49da20845f0f0e1afbb1c2586d406dc0acb84c26ae293bad6d7e7f718bc/scikit_image-0.22.0.tar.gz", hash = "sha256:018d734df1d2da2719087d15f679d19285fce97cd37695103deadfaef2873236", size = 22685018 } +sdist = { url = "https://files.pythonhosted.org/packages/65/c1/a49da20845f0f0e1afbb1c2586d406dc0acb84c26ae293bad6d7e7f718bc/scikit_image-0.22.0.tar.gz", hash = "sha256:018d734df1d2da2719087d15f679d19285fce97cd37695103deadfaef2873236", size = 22685018, upload_time = "2023-10-03T21:36:34.274Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9c/8c/381ae42b37cf3e9e99a1deb3ffe76ca5ff5dd18ffa368293476164507fad/scikit_image-0.22.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:74ec5c1d4693506842cc7c9487c89d8fc32aed064e9363def7af08b8f8cbb31d", size = 13905039 }, - { url = "https://files.pythonhosted.org/packages/16/06/4bfba08f5cce26d5070bb2cf4e3f9f479480978806355d1c5bea6f26a17c/scikit_image-0.22.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:a05ae4fe03d802587ed8974e900b943275548cde6a6807b785039d63e9a7a5ff", size = 13279212 }, - { url = "https://files.pythonhosted.org/packages/74/57/dbf744ca00eea2a09b1848c9dec28a43978c16dc049b1fba949cb050bedf/scikit_image-0.22.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a92dca3d95b1301442af055e196a54b5a5128c6768b79fc0a4098f1d662dee6", size = 14091779 }, - { url = "https://files.pythonhosted.org/packages/f1/6c/49f5a0ce8ddcdbdac5ac69c129654938cc6de0a936303caa6cad495ceb2a/scikit_image-0.22.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3663d063d8bf2fb9bdfb0ca967b9ee3b6593139c860c7abc2d2351a8a8863938", size = 14682042 }, - { url = "https://files.pythonhosted.org/packages/86/f0/18895318109f9b508f2310f136922e455a453550826a8240b412063c2528/scikit_image-0.22.0-cp310-cp310-win_amd64.whl", hash = "sha256:ebdbdc901bae14dab637f8d5c99f6d5cc7aaf4a3b6f4003194e003e9f688a6fc", size = 24492345 }, - { url = "https://files.pythonhosted.org/packages/9f/d9/dc99e527d1a0050f0353d2fff3548273b4df6151884806e324f26572fd6b/scikit_image-0.22.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:95d6da2d8a44a36ae04437c76d32deb4e3c993ffc846b394b9949fd8ded73cb2", size = 13883619 }, - { url = "https://files.pythonhosted.org/packages/80/37/7670020b112ff9a47e49b1e36f438d000db5b632aab8a8fd7e6be545d065/scikit_image-0.22.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:2c6ef454a85f569659b813ac2a93948022b0298516b757c9c6c904132be327e2", size = 13264761 }, - { url = "https://files.pythonhosted.org/packages/ad/85/dadf1194793ac1c895370f3ed048bb91dda083775b42e11d9672a50494d5/scikit_image-0.22.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e87872f067444ee90a00dd49ca897208308645382e8a24bd3e76f301af2352cd", size = 14070710 }, - { url = "https://files.pythonhosted.org/packages/d4/34/e27bf2bfe7b52b884b49bd71ea91ff81e4737246735ee5ea383314c31876/scikit_image-0.22.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5c378db54e61b491b9edeefff87e49fcf7fdf729bb93c777d7a5f15d36f743e", size = 14664172 }, - { url = "https://files.pythonhosted.org/packages/ce/d0/a3f60c9f57ed295b3076e4acdb29a37bbd8823452562ab2ad51b03d6f377/scikit_image-0.22.0-cp311-cp311-win_amd64.whl", hash = "sha256:2bcb74adb0634258a67f66c2bb29978c9a3e222463e003b67ba12056c003971b", size = 24491321 }, - { url = "https://files.pythonhosted.org/packages/da/a4/b0b69bde4d6360e801d647691591dc9967a25a18a4c63ecf7f87d94e3fac/scikit_image-0.22.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:003ca2274ac0fac252280e7179ff986ff783407001459ddea443fe7916e38cff", size = 13968808 }, - { url = "https://files.pythonhosted.org/packages/e4/65/3c0f77e7a9bae100a8f7f5cebde410fca1a3cf64e1ecdd343666e27b11d4/scikit_image-0.22.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:cf3c0c15b60ae3e557a0c7575fbd352f0c3ce0afca562febfe3ab80efbeec0e9", size = 13323763 }, - { url = "https://files.pythonhosted.org/packages/4a/ed/7faf9f7a55d5b3095d33990a85603b66866cce2a608b27f0e1487d70a451/scikit_image-0.22.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5b23908dd4d120e6aecb1ed0277563e8cbc8d6c0565bdc4c4c6475d53608452", size = 13877233 }, - { url = "https://files.pythonhosted.org/packages/ae/9d/09d06f36ce71fa276e1d9453fb4b04250a7038292b13b8c273a5a1a8f7c0/scikit_image-0.22.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be79d7493f320a964f8fcf603121595ba82f84720de999db0fcca002266a549a", size = 14954814 }, - { url = "https://files.pythonhosted.org/packages/dc/35/e6327ae498c6f557cb0a7c3fc284effe7958d2d1c43fb61cd77804fc2c4f/scikit_image-0.22.0-cp312-cp312-win_amd64.whl", hash = "sha256:722b970aa5da725dca55252c373b18bbea7858c1cdb406e19f9b01a4a73b30b2", size = 25004857 }, + { url = "https://files.pythonhosted.org/packages/9c/8c/381ae42b37cf3e9e99a1deb3ffe76ca5ff5dd18ffa368293476164507fad/scikit_image-0.22.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:74ec5c1d4693506842cc7c9487c89d8fc32aed064e9363def7af08b8f8cbb31d", size = 13905039, upload_time = "2023-10-03T21:35:27.279Z" }, + { url = "https://files.pythonhosted.org/packages/16/06/4bfba08f5cce26d5070bb2cf4e3f9f479480978806355d1c5bea6f26a17c/scikit_image-0.22.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:a05ae4fe03d802587ed8974e900b943275548cde6a6807b785039d63e9a7a5ff", size = 13279212, upload_time = "2023-10-03T21:35:30.864Z" }, + { url = "https://files.pythonhosted.org/packages/74/57/dbf744ca00eea2a09b1848c9dec28a43978c16dc049b1fba949cb050bedf/scikit_image-0.22.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a92dca3d95b1301442af055e196a54b5a5128c6768b79fc0a4098f1d662dee6", size = 14091779, upload_time = "2023-10-03T21:35:34.273Z" }, + { url = "https://files.pythonhosted.org/packages/f1/6c/49f5a0ce8ddcdbdac5ac69c129654938cc6de0a936303caa6cad495ceb2a/scikit_image-0.22.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3663d063d8bf2fb9bdfb0ca967b9ee3b6593139c860c7abc2d2351a8a8863938", size = 14682042, upload_time = "2023-10-03T21:35:37.787Z" }, + { url = "https://files.pythonhosted.org/packages/86/f0/18895318109f9b508f2310f136922e455a453550826a8240b412063c2528/scikit_image-0.22.0-cp310-cp310-win_amd64.whl", hash = "sha256:ebdbdc901bae14dab637f8d5c99f6d5cc7aaf4a3b6f4003194e003e9f688a6fc", size = 24492345, upload_time = "2023-10-03T21:35:41.122Z" }, + { url = "https://files.pythonhosted.org/packages/9f/d9/dc99e527d1a0050f0353d2fff3548273b4df6151884806e324f26572fd6b/scikit_image-0.22.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:95d6da2d8a44a36ae04437c76d32deb4e3c993ffc846b394b9949fd8ded73cb2", size = 13883619, upload_time = "2023-10-03T21:35:44.88Z" }, + { url = "https://files.pythonhosted.org/packages/80/37/7670020b112ff9a47e49b1e36f438d000db5b632aab8a8fd7e6be545d065/scikit_image-0.22.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:2c6ef454a85f569659b813ac2a93948022b0298516b757c9c6c904132be327e2", size = 13264761, upload_time = "2023-10-03T21:35:48.865Z" }, + { url = "https://files.pythonhosted.org/packages/ad/85/dadf1194793ac1c895370f3ed048bb91dda083775b42e11d9672a50494d5/scikit_image-0.22.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e87872f067444ee90a00dd49ca897208308645382e8a24bd3e76f301af2352cd", size = 14070710, upload_time = "2023-10-03T21:35:51.711Z" }, + { url = "https://files.pythonhosted.org/packages/d4/34/e27bf2bfe7b52b884b49bd71ea91ff81e4737246735ee5ea383314c31876/scikit_image-0.22.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5c378db54e61b491b9edeefff87e49fcf7fdf729bb93c777d7a5f15d36f743e", size = 14664172, upload_time = "2023-10-03T21:35:55.752Z" }, + { url = "https://files.pythonhosted.org/packages/ce/d0/a3f60c9f57ed295b3076e4acdb29a37bbd8823452562ab2ad51b03d6f377/scikit_image-0.22.0-cp311-cp311-win_amd64.whl", hash = "sha256:2bcb74adb0634258a67f66c2bb29978c9a3e222463e003b67ba12056c003971b", size = 24491321, upload_time = "2023-10-03T21:35:58.847Z" }, + { url = "https://files.pythonhosted.org/packages/da/a4/b0b69bde4d6360e801d647691591dc9967a25a18a4c63ecf7f87d94e3fac/scikit_image-0.22.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:003ca2274ac0fac252280e7179ff986ff783407001459ddea443fe7916e38cff", size = 13968808, upload_time = "2023-10-03T21:36:02.526Z" }, + { url = "https://files.pythonhosted.org/packages/e4/65/3c0f77e7a9bae100a8f7f5cebde410fca1a3cf64e1ecdd343666e27b11d4/scikit_image-0.22.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:cf3c0c15b60ae3e557a0c7575fbd352f0c3ce0afca562febfe3ab80efbeec0e9", size = 13323763, upload_time = "2023-10-03T21:36:05.504Z" }, + { url = "https://files.pythonhosted.org/packages/4a/ed/7faf9f7a55d5b3095d33990a85603b66866cce2a608b27f0e1487d70a451/scikit_image-0.22.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5b23908dd4d120e6aecb1ed0277563e8cbc8d6c0565bdc4c4c6475d53608452", size = 13877233, upload_time = "2023-10-03T21:36:08.352Z" }, + { url = "https://files.pythonhosted.org/packages/ae/9d/09d06f36ce71fa276e1d9453fb4b04250a7038292b13b8c273a5a1a8f7c0/scikit_image-0.22.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be79d7493f320a964f8fcf603121595ba82f84720de999db0fcca002266a549a", size = 14954814, upload_time = "2023-10-03T21:36:11.871Z" }, + { url = "https://files.pythonhosted.org/packages/dc/35/e6327ae498c6f557cb0a7c3fc284effe7958d2d1c43fb61cd77804fc2c4f/scikit_image-0.22.0-cp312-cp312-win_amd64.whl", hash = "sha256:722b970aa5da725dca55252c373b18bbea7858c1cdb406e19f9b01a4a73b30b2", size = 25004857, upload_time = "2023-10-03T21:36:15.457Z" }, ] [[package]] @@ -2291,23 +2349,23 @@ dependencies = [ { name = "scipy" }, { name = "threadpoolctl" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/88/00/835e3d280fdd7784e76bdef91dd9487582d7951a7254f59fc8004fc8b213/scikit-learn-1.3.2.tar.gz", hash = "sha256:a2f54c76accc15a34bfb9066e6c7a56c1e7235dda5762b990792330b52ccfb05", size = 7510251 } +sdist = { url = "https://files.pythonhosted.org/packages/88/00/835e3d280fdd7784e76bdef91dd9487582d7951a7254f59fc8004fc8b213/scikit-learn-1.3.2.tar.gz", hash = "sha256:a2f54c76accc15a34bfb9066e6c7a56c1e7235dda5762b990792330b52ccfb05", size = 7510251, upload_time = "2023-10-23T13:47:55.287Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0d/53/570b55a6e10b8694ac1e3024d2df5cd443f1b4ff6d28430845da8b9019b3/scikit_learn-1.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e326c0eb5cf4d6ba40f93776a20e9a7a69524c4db0757e7ce24ba222471ee8a1", size = 10209999 }, - { url = "https://files.pythonhosted.org/packages/70/d0/50ace22129f79830e3cf682d0a2bd4843ef91573299d43112d52790163a8/scikit_learn-1.3.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:535805c2a01ccb40ca4ab7d081d771aea67e535153e35a1fd99418fcedd1648a", size = 9479353 }, - { url = "https://files.pythonhosted.org/packages/8f/46/fcc35ed7606c50d3072eae5a107a45cfa5b7f5fa8cc48610edd8cc8e8550/scikit_learn-1.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1215e5e58e9880b554b01187b8c9390bf4dc4692eedeaf542d3273f4785e342c", size = 10304705 }, - { url = "https://files.pythonhosted.org/packages/d0/0b/26ad95cf0b747be967b15fb71a06f5ac67aba0fd2f9cd174de6edefc4674/scikit_learn-1.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ee107923a623b9f517754ea2f69ea3b62fc898a3641766cb7deb2f2ce450161", size = 10827807 }, - { url = "https://files.pythonhosted.org/packages/69/8a/cf17d6443f5f537e099be81535a56ab68a473f9393fbffda38cd19899fc8/scikit_learn-1.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:35a22e8015048c628ad099da9df5ab3004cdbf81edc75b396fd0cff8699ac58c", size = 9255427 }, - { url = "https://files.pythonhosted.org/packages/08/5d/e5acecd6e99a6b656e42e7a7b18284e2f9c9f512e8ed6979e1e75d25f05f/scikit_learn-1.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6fb6bc98f234fda43163ddbe36df8bcde1d13ee176c6dc9b92bb7d3fc842eb66", size = 10116376 }, - { url = "https://files.pythonhosted.org/packages/40/c6/2e91eefb757822e70d351e02cc38d07c137212ae7c41ac12746415b4860a/scikit_learn-1.3.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:18424efee518a1cde7b0b53a422cde2f6625197de6af36da0b57ec502f126157", size = 9383415 }, - { url = "https://files.pythonhosted.org/packages/fa/fd/b3637639e73bb72b12803c5245f2a7299e09b2acd85a0f23937c53369a1c/scikit_learn-1.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3271552a5eb16f208a6f7f617b8cc6d1f137b52c8a1ef8edf547db0259b2c9fb", size = 10279163 }, - { url = "https://files.pythonhosted.org/packages/0c/2a/d3ff6091406bc2207e0adb832ebd15e40ac685811c7e2e3b432bfd969b71/scikit_learn-1.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4144a5004a676d5022b798d9e573b05139e77f271253a4703eed295bde0433", size = 10884422 }, - { url = "https://files.pythonhosted.org/packages/4e/ba/ce9bd1cd4953336a0e213b29cb80bb11816f2a93de8c99f88ef0b446ad0c/scikit_learn-1.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:67f37d708f042a9b8d59551cf94d30431e01374e00dc2645fa186059c6c5d78b", size = 9207060 }, - { url = "https://files.pythonhosted.org/packages/26/7e/2c3b82c8c29aa384c8bf859740419278627d2cdd0050db503c8840e72477/scikit_learn-1.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8db94cd8a2e038b37a80a04df8783e09caac77cbe052146432e67800e430c028", size = 9979322 }, - { url = "https://files.pythonhosted.org/packages/cf/fc/6c52ffeb587259b6b893b7cac268f1eb1b5426bcce1aa20e53523bfe6944/scikit_learn-1.3.2-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:61a6efd384258789aa89415a410dcdb39a50e19d3d8410bd29be365bcdd512d5", size = 9270688 }, - { url = "https://files.pythonhosted.org/packages/e5/a7/6f4ae76f72ae9de162b97acbf1f53acbe404c555f968d13da21e4112a002/scikit_learn-1.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb06f8dce3f5ddc5dee1715a9b9f19f20d295bed8e3cd4fa51e1d050347de525", size = 10280398 }, - { url = "https://files.pythonhosted.org/packages/5d/b7/ee35904c07a0666784349529412fbb9814a56382b650d30fd9d6be5e5054/scikit_learn-1.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b2de18d86f630d68fe1f87af690d451388bb186480afc719e5f770590c2ef6c", size = 10796478 }, - { url = "https://files.pythonhosted.org/packages/fe/6b/db949ed5ac367987b1f250f070f340b7715d22f0c9c965bdf07de6ca75a3/scikit_learn-1.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:0402638c9a7c219ee52c94cbebc8fcb5eb9fe9c773717965c1f4185588ad3107", size = 9133979 }, + { url = "https://files.pythonhosted.org/packages/0d/53/570b55a6e10b8694ac1e3024d2df5cd443f1b4ff6d28430845da8b9019b3/scikit_learn-1.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e326c0eb5cf4d6ba40f93776a20e9a7a69524c4db0757e7ce24ba222471ee8a1", size = 10209999, upload_time = "2023-10-23T13:46:30.373Z" }, + { url = "https://files.pythonhosted.org/packages/70/d0/50ace22129f79830e3cf682d0a2bd4843ef91573299d43112d52790163a8/scikit_learn-1.3.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:535805c2a01ccb40ca4ab7d081d771aea67e535153e35a1fd99418fcedd1648a", size = 9479353, upload_time = "2023-10-23T13:46:34.368Z" }, + { url = "https://files.pythonhosted.org/packages/8f/46/fcc35ed7606c50d3072eae5a107a45cfa5b7f5fa8cc48610edd8cc8e8550/scikit_learn-1.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1215e5e58e9880b554b01187b8c9390bf4dc4692eedeaf542d3273f4785e342c", size = 10304705, upload_time = "2023-10-23T13:46:37.868Z" }, + { url = "https://files.pythonhosted.org/packages/d0/0b/26ad95cf0b747be967b15fb71a06f5ac67aba0fd2f9cd174de6edefc4674/scikit_learn-1.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ee107923a623b9f517754ea2f69ea3b62fc898a3641766cb7deb2f2ce450161", size = 10827807, upload_time = "2023-10-23T13:46:41.59Z" }, + { url = "https://files.pythonhosted.org/packages/69/8a/cf17d6443f5f537e099be81535a56ab68a473f9393fbffda38cd19899fc8/scikit_learn-1.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:35a22e8015048c628ad099da9df5ab3004cdbf81edc75b396fd0cff8699ac58c", size = 9255427, upload_time = "2023-10-23T13:46:44.826Z" }, + { url = "https://files.pythonhosted.org/packages/08/5d/e5acecd6e99a6b656e42e7a7b18284e2f9c9f512e8ed6979e1e75d25f05f/scikit_learn-1.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6fb6bc98f234fda43163ddbe36df8bcde1d13ee176c6dc9b92bb7d3fc842eb66", size = 10116376, upload_time = "2023-10-23T13:46:48.147Z" }, + { url = "https://files.pythonhosted.org/packages/40/c6/2e91eefb757822e70d351e02cc38d07c137212ae7c41ac12746415b4860a/scikit_learn-1.3.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:18424efee518a1cde7b0b53a422cde2f6625197de6af36da0b57ec502f126157", size = 9383415, upload_time = "2023-10-23T13:46:51.324Z" }, + { url = "https://files.pythonhosted.org/packages/fa/fd/b3637639e73bb72b12803c5245f2a7299e09b2acd85a0f23937c53369a1c/scikit_learn-1.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3271552a5eb16f208a6f7f617b8cc6d1f137b52c8a1ef8edf547db0259b2c9fb", size = 10279163, upload_time = "2023-10-23T13:46:54.642Z" }, + { url = "https://files.pythonhosted.org/packages/0c/2a/d3ff6091406bc2207e0adb832ebd15e40ac685811c7e2e3b432bfd969b71/scikit_learn-1.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4144a5004a676d5022b798d9e573b05139e77f271253a4703eed295bde0433", size = 10884422, upload_time = "2023-10-23T13:46:58.087Z" }, + { url = "https://files.pythonhosted.org/packages/4e/ba/ce9bd1cd4953336a0e213b29cb80bb11816f2a93de8c99f88ef0b446ad0c/scikit_learn-1.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:67f37d708f042a9b8d59551cf94d30431e01374e00dc2645fa186059c6c5d78b", size = 9207060, upload_time = "2023-10-23T13:47:00.948Z" }, + { url = "https://files.pythonhosted.org/packages/26/7e/2c3b82c8c29aa384c8bf859740419278627d2cdd0050db503c8840e72477/scikit_learn-1.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8db94cd8a2e038b37a80a04df8783e09caac77cbe052146432e67800e430c028", size = 9979322, upload_time = "2023-10-23T13:47:03.977Z" }, + { url = "https://files.pythonhosted.org/packages/cf/fc/6c52ffeb587259b6b893b7cac268f1eb1b5426bcce1aa20e53523bfe6944/scikit_learn-1.3.2-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:61a6efd384258789aa89415a410dcdb39a50e19d3d8410bd29be365bcdd512d5", size = 9270688, upload_time = "2023-10-23T13:47:07.316Z" }, + { url = "https://files.pythonhosted.org/packages/e5/a7/6f4ae76f72ae9de162b97acbf1f53acbe404c555f968d13da21e4112a002/scikit_learn-1.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb06f8dce3f5ddc5dee1715a9b9f19f20d295bed8e3cd4fa51e1d050347de525", size = 10280398, upload_time = "2023-10-23T13:47:10.796Z" }, + { url = "https://files.pythonhosted.org/packages/5d/b7/ee35904c07a0666784349529412fbb9814a56382b650d30fd9d6be5e5054/scikit_learn-1.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b2de18d86f630d68fe1f87af690d451388bb186480afc719e5f770590c2ef6c", size = 10796478, upload_time = "2023-10-23T13:47:14.077Z" }, + { url = "https://files.pythonhosted.org/packages/fe/6b/db949ed5ac367987b1f250f070f340b7715d22f0c9c965bdf07de6ca75a3/scikit_learn-1.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:0402638c9a7c219ee52c94cbebc8fcb5eb9fe9c773717965c1f4185588ad3107", size = 9133979, upload_time = "2023-10-23T13:47:17.389Z" }, ] [[package]] @@ -2317,53 +2375,65 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6e/1f/91144ba78dccea567a6466262922786ffc97be1e9b06ed9574ef0edc11e1/scipy-1.11.4.tar.gz", hash = "sha256:90a2b78e7f5733b9de748f589f09225013685f9b218275257f8a8168ededaeaa", size = 56336202 } +sdist = { url = "https://files.pythonhosted.org/packages/6e/1f/91144ba78dccea567a6466262922786ffc97be1e9b06ed9574ef0edc11e1/scipy-1.11.4.tar.gz", hash = "sha256:90a2b78e7f5733b9de748f589f09225013685f9b218275257f8a8168ededaeaa", size = 56336202, upload_time = "2023-11-18T21:06:08.277Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/34/c6/a32add319475d21f89733c034b99c81b3a7c6c7c19f96f80c7ca3ff1bbd4/scipy-1.11.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc9a714581f561af0848e6b69947fda0614915f072dfd14142ed1bfe1b806710", size = 37293259 }, - { url = "https://files.pythonhosted.org/packages/de/0d/4fa68303568c70fd56fbf40668b6c6807cfee4cad975f07d80bdd26d013e/scipy-1.11.4-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:cf00bd2b1b0211888d4dc75656c0412213a8b25e80d73898083f402b50f47e41", size = 29760656 }, - { url = "https://files.pythonhosted.org/packages/13/e5/8012be7857db6cbbbdbeea8a154dbacdfae845e95e1e19c028e82236d4a0/scipy-1.11.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9999c008ccf00e8fbcce1236f85ade5c569d13144f77a1946bef8863e8f6eb4", size = 32922489 }, - { url = "https://files.pythonhosted.org/packages/e0/9e/80e2205d138960a49caea391f3710600895dd8292b6868dc9aff7aa593f9/scipy-1.11.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:933baf588daa8dc9a92c20a0be32f56d43faf3d1a60ab11b3f08c356430f6e56", size = 36442040 }, - { url = "https://files.pythonhosted.org/packages/69/60/30a9c3fbe5066a3a93eefe3e2d44553df13587e6f792e1bff20dfed3d17e/scipy-1.11.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8fce70f39076a5aa62e92e69a7f62349f9574d8405c0a5de6ed3ef72de07f446", size = 36643257 }, - { url = "https://files.pythonhosted.org/packages/f8/ec/b46756f80e3f4c5f0989f6e4492c2851f156d9c239d554754a3c8cffd4e2/scipy-1.11.4-cp310-cp310-win_amd64.whl", hash = "sha256:6550466fbeec7453d7465e74d4f4b19f905642c89a7525571ee91dd7adabb5a3", size = 44149285 }, - { url = "https://files.pythonhosted.org/packages/b8/f2/1aefbd5e54ebd8c6163ccf7f73e5d17bc8cb38738d312befc524fce84bb4/scipy-1.11.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f313b39a7e94f296025e3cffc2c567618174c0b1dde173960cf23808f9fae4be", size = 37159197 }, - { url = "https://files.pythonhosted.org/packages/4b/48/20e77ddb1f473d4717a7d4d3fc8d15557f406f7708496054c59f635b7734/scipy-1.11.4-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:1b7c3dca977f30a739e0409fb001056484661cb2541a01aba0bb0029f7b68db8", size = 29675057 }, - { url = "https://files.pythonhosted.org/packages/75/2e/a781862190d0e7e76afa74752ef363488a9a9d6ea86e46d5e5506cee8df6/scipy-1.11.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00150c5eae7b610c32589dda259eacc7c4f1665aedf25d921907f4d08a951b1c", size = 32882747 }, - { url = "https://files.pythonhosted.org/packages/6b/d4/d62ce38ba00dc67d7ec4ec5cc19d36958d8ed70e63778715ad626bcbc796/scipy-1.11.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:530f9ad26440e85766509dbf78edcfe13ffd0ab7fec2560ee5c36ff74d6269ff", size = 36402732 }, - { url = "https://files.pythonhosted.org/packages/88/86/827b56aea1ed04adbb044a675672a73c84d81076a350092bbfcfc1ae723b/scipy-1.11.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5e347b14fe01003d3b78e196e84bd3f48ffe4c8a7b8a1afbcb8f5505cb710993", size = 36622138 }, - { url = "https://files.pythonhosted.org/packages/43/d0/f3cd75b62e1b90f48dbf091261b2fc7ceec14a700e308c50f6a69c83d337/scipy-1.11.4-cp311-cp311-win_amd64.whl", hash = "sha256:acf8ed278cc03f5aff035e69cb511741e0418681d25fbbb86ca65429c4f4d9cd", size = 44095631 }, - { url = "https://files.pythonhosted.org/packages/df/64/8a690570485b636da614acff35fd725fcbc487f8b1fa9bdb12871b77412f/scipy-1.11.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:028eccd22e654b3ea01ee63705681ee79933652b2d8f873e7949898dda6d11b6", size = 37053653 }, - { url = "https://files.pythonhosted.org/packages/5e/43/abf331745a7e5f4af51f13d40e2a72f516048db41ecbcf3ac6f86ada54a3/scipy-1.11.4-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:2c6ff6ef9cc27f9b3db93a6f8b38f97387e6e0591600369a297a50a8e96e835d", size = 29641601 }, - { url = "https://files.pythonhosted.org/packages/47/9b/62d0ec086dd2871009da8769c504bec6e39b80f4c182c6ead0fcebd8b323/scipy-1.11.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b030c6674b9230d37c5c60ab456e2cf12f6784596d15ce8da9365e70896effc4", size = 32272137 }, - { url = "https://files.pythonhosted.org/packages/08/77/f90f7306d755ac68bd159c50bb86fffe38400e533e8c609dd8484bd0f172/scipy-1.11.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad669df80528aeca5f557712102538f4f37e503f0c5b9541655016dd0932ca79", size = 35777534 }, - { url = "https://files.pythonhosted.org/packages/00/de/b9f6938090c37b5092969ba1c67118e9114e8e6ef9d197251671444e839c/scipy-1.11.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ce7fff2e23ab2cc81ff452a9444c215c28e6305f396b2ba88343a567feec9660", size = 35963721 }, - { url = "https://files.pythonhosted.org/packages/c6/a1/357e4cd43af2748e1e0407ae0e9a5ea8aaaa6b702833c81be11670dcbad8/scipy-1.11.4-cp312-cp312-win_amd64.whl", hash = "sha256:36750b7733d960d7994888f0d148d31ea3017ac15eef664194b4ef68d36a4a97", size = 43730653 }, + { url = "https://files.pythonhosted.org/packages/34/c6/a32add319475d21f89733c034b99c81b3a7c6c7c19f96f80c7ca3ff1bbd4/scipy-1.11.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc9a714581f561af0848e6b69947fda0614915f072dfd14142ed1bfe1b806710", size = 37293259, upload_time = "2023-11-18T21:01:18.805Z" }, + { url = "https://files.pythonhosted.org/packages/de/0d/4fa68303568c70fd56fbf40668b6c6807cfee4cad975f07d80bdd26d013e/scipy-1.11.4-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:cf00bd2b1b0211888d4dc75656c0412213a8b25e80d73898083f402b50f47e41", size = 29760656, upload_time = "2023-11-18T21:01:41.815Z" }, + { url = "https://files.pythonhosted.org/packages/13/e5/8012be7857db6cbbbdbeea8a154dbacdfae845e95e1e19c028e82236d4a0/scipy-1.11.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9999c008ccf00e8fbcce1236f85ade5c569d13144f77a1946bef8863e8f6eb4", size = 32922489, upload_time = "2023-11-18T21:01:50.637Z" }, + { url = "https://files.pythonhosted.org/packages/e0/9e/80e2205d138960a49caea391f3710600895dd8292b6868dc9aff7aa593f9/scipy-1.11.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:933baf588daa8dc9a92c20a0be32f56d43faf3d1a60ab11b3f08c356430f6e56", size = 36442040, upload_time = "2023-11-18T21:02:00.119Z" }, + { url = "https://files.pythonhosted.org/packages/69/60/30a9c3fbe5066a3a93eefe3e2d44553df13587e6f792e1bff20dfed3d17e/scipy-1.11.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8fce70f39076a5aa62e92e69a7f62349f9574d8405c0a5de6ed3ef72de07f446", size = 36643257, upload_time = "2023-11-18T21:02:06.798Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ec/b46756f80e3f4c5f0989f6e4492c2851f156d9c239d554754a3c8cffd4e2/scipy-1.11.4-cp310-cp310-win_amd64.whl", hash = "sha256:6550466fbeec7453d7465e74d4f4b19f905642c89a7525571ee91dd7adabb5a3", size = 44149285, upload_time = "2023-11-18T21:02:15.592Z" }, + { url = "https://files.pythonhosted.org/packages/b8/f2/1aefbd5e54ebd8c6163ccf7f73e5d17bc8cb38738d312befc524fce84bb4/scipy-1.11.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f313b39a7e94f296025e3cffc2c567618174c0b1dde173960cf23808f9fae4be", size = 37159197, upload_time = "2023-11-18T21:02:21.959Z" }, + { url = "https://files.pythonhosted.org/packages/4b/48/20e77ddb1f473d4717a7d4d3fc8d15557f406f7708496054c59f635b7734/scipy-1.11.4-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:1b7c3dca977f30a739e0409fb001056484661cb2541a01aba0bb0029f7b68db8", size = 29675057, upload_time = "2023-11-18T21:02:28.169Z" }, + { url = "https://files.pythonhosted.org/packages/75/2e/a781862190d0e7e76afa74752ef363488a9a9d6ea86e46d5e5506cee8df6/scipy-1.11.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00150c5eae7b610c32589dda259eacc7c4f1665aedf25d921907f4d08a951b1c", size = 32882747, upload_time = "2023-11-18T21:02:33.683Z" }, + { url = "https://files.pythonhosted.org/packages/6b/d4/d62ce38ba00dc67d7ec4ec5cc19d36958d8ed70e63778715ad626bcbc796/scipy-1.11.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:530f9ad26440e85766509dbf78edcfe13ffd0ab7fec2560ee5c36ff74d6269ff", size = 36402732, upload_time = "2023-11-18T21:02:39.762Z" }, + { url = "https://files.pythonhosted.org/packages/88/86/827b56aea1ed04adbb044a675672a73c84d81076a350092bbfcfc1ae723b/scipy-1.11.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5e347b14fe01003d3b78e196e84bd3f48ffe4c8a7b8a1afbcb8f5505cb710993", size = 36622138, upload_time = "2023-11-18T21:02:45.968Z" }, + { url = "https://files.pythonhosted.org/packages/43/d0/f3cd75b62e1b90f48dbf091261b2fc7ceec14a700e308c50f6a69c83d337/scipy-1.11.4-cp311-cp311-win_amd64.whl", hash = "sha256:acf8ed278cc03f5aff035e69cb511741e0418681d25fbbb86ca65429c4f4d9cd", size = 44095631, upload_time = "2023-11-18T21:02:52.859Z" }, + { url = "https://files.pythonhosted.org/packages/df/64/8a690570485b636da614acff35fd725fcbc487f8b1fa9bdb12871b77412f/scipy-1.11.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:028eccd22e654b3ea01ee63705681ee79933652b2d8f873e7949898dda6d11b6", size = 37053653, upload_time = "2023-11-18T21:03:00.107Z" }, + { url = "https://files.pythonhosted.org/packages/5e/43/abf331745a7e5f4af51f13d40e2a72f516048db41ecbcf3ac6f86ada54a3/scipy-1.11.4-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:2c6ff6ef9cc27f9b3db93a6f8b38f97387e6e0591600369a297a50a8e96e835d", size = 29641601, upload_time = "2023-11-18T21:03:06.708Z" }, + { url = "https://files.pythonhosted.org/packages/47/9b/62d0ec086dd2871009da8769c504bec6e39b80f4c182c6ead0fcebd8b323/scipy-1.11.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b030c6674b9230d37c5c60ab456e2cf12f6784596d15ce8da9365e70896effc4", size = 32272137, upload_time = "2023-11-18T21:03:14.877Z" }, + { url = "https://files.pythonhosted.org/packages/08/77/f90f7306d755ac68bd159c50bb86fffe38400e533e8c609dd8484bd0f172/scipy-1.11.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad669df80528aeca5f557712102538f4f37e503f0c5b9541655016dd0932ca79", size = 35777534, upload_time = "2023-11-18T21:03:21.451Z" }, + { url = "https://files.pythonhosted.org/packages/00/de/b9f6938090c37b5092969ba1c67118e9114e8e6ef9d197251671444e839c/scipy-1.11.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ce7fff2e23ab2cc81ff452a9444c215c28e6305f396b2ba88343a567feec9660", size = 35963721, upload_time = "2023-11-18T21:03:27.85Z" }, + { url = "https://files.pythonhosted.org/packages/c6/a1/357e4cd43af2748e1e0407ae0e9a5ea8aaaa6b702833c81be11670dcbad8/scipy-1.11.4-cp312-cp312-win_amd64.whl", hash = "sha256:36750b7733d960d7994888f0d148d31ea3017ac15eef664194b4ef68d36a4a97", size = 43730653, upload_time = "2023-11-18T21:03:34.758Z" }, ] [[package]] name = "setuptools" version = "70.3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/65/d8/10a70e86f6c28ae59f101a9de6d77bf70f147180fbf40c3af0f64080adc3/setuptools-70.3.0.tar.gz", hash = "sha256:f171bab1dfbc86b132997f26a119f6056a57950d058587841a0082e8830f9dc5", size = 2333112 } +sdist = { url = "https://files.pythonhosted.org/packages/65/d8/10a70e86f6c28ae59f101a9de6d77bf70f147180fbf40c3af0f64080adc3/setuptools-70.3.0.tar.gz", hash = "sha256:f171bab1dfbc86b132997f26a119f6056a57950d058587841a0082e8830f9dc5", size = 2333112, upload_time = "2024-07-09T16:08:06.251Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ef/15/88e46eb9387e905704b69849618e699dc2f54407d8953cc4ec4b8b46528d/setuptools-70.3.0-py3-none-any.whl", hash = "sha256:fe384da74336c398e0d956d1cae0669bc02eed936cdb1d49b57de1990dc11ffc", size = 931070 }, + { url = "https://files.pythonhosted.org/packages/ef/15/88e46eb9387e905704b69849618e699dc2f54407d8953cc4ec4b8b46528d/setuptools-70.3.0-py3-none-any.whl", hash = "sha256:fe384da74336c398e0d956d1cae0669bc02eed936cdb1d49b57de1990dc11ffc", size = 931070, upload_time = "2024-07-09T16:07:58.829Z" }, +] + +[[package]] +name = "simple-websocket" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wsproto" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b0/d4/bfa032f961103eba93de583b161f0e6a5b63cebb8f2c7d0c6e6efe1e3d2e/simple_websocket-1.1.0.tar.gz", hash = "sha256:7939234e7aa067c534abdab3a9ed933ec9ce4691b0713c78acb195560aa52ae4", size = 17300, upload_time = "2024-10-10T22:39:31.412Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl", hash = "sha256:4af6069630a38ed6c561010f0e11a5bc0d4ca569b36306eb257cd9a192497c8c", size = 13842, upload_time = "2024-10-10T22:39:29.645Z" }, ] [[package]] name = "six" version = "1.16.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/71/39/171f1c67cd00715f190ba0b100d606d440a28c93c7714febeca8b79af85e/six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", size = 34041 } +sdist = { url = "https://files.pythonhosted.org/packages/71/39/171f1c67cd00715f190ba0b100d606d440a28c93c7714febeca8b79af85e/six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", size = 34041, upload_time = "2021-05-05T14:18:18.379Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", size = 11053 }, + { url = "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", size = 11053, upload_time = "2021-05-05T14:18:17.237Z" }, ] [[package]] name = "sniffio" version = "1.3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cd/50/d49c388cae4ec10e8109b1b833fd265511840706808576df3ada99ecb0ac/sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101", size = 17103 } +sdist = { url = "https://files.pythonhosted.org/packages/cd/50/d49c388cae4ec10e8109b1b833fd265511840706808576df3ada99ecb0ac/sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101", size = 17103, upload_time = "2022-09-01T12:31:36.968Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c3/a0/5dba8ed157b0136607c7f2151db695885606968d1fae123dc3391e0cfdbf/sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384", size = 10165 }, + { url = "https://files.pythonhosted.org/packages/c3/a0/5dba8ed157b0136607c7f2151db695885606968d1fae123dc3391e0cfdbf/sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384", size = 10165, upload_time = "2022-09-01T12:31:34.186Z" }, ] [[package]] @@ -2373,9 +2443,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3e/da/1fb4bdb72ae12b834becd7e1e7e47001d32f91ec0ce8d7bc1b618d9f0bd9/starlette-0.41.2.tar.gz", hash = "sha256:9834fd799d1a87fd346deb76158668cfa0b0d56f85caefe8268e2d97c3468b62", size = 2573867 } +sdist = { url = "https://files.pythonhosted.org/packages/3e/da/1fb4bdb72ae12b834becd7e1e7e47001d32f91ec0ce8d7bc1b618d9f0bd9/starlette-0.41.2.tar.gz", hash = "sha256:9834fd799d1a87fd346deb76158668cfa0b0d56f85caefe8268e2d97c3468b62", size = 2573867, upload_time = "2024-10-27T08:20:02.818Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/54/43/f185bfd0ca1d213beb4293bed51d92254df23d8ceaf6c0e17146d508a776/starlette-0.41.2-py3-none-any.whl", hash = "sha256:fbc189474b4731cf30fcef52f18a8d070e3f3b46c6a04c97579e85e6ffca942d", size = 73259 }, + { url = "https://files.pythonhosted.org/packages/54/43/f185bfd0ca1d213beb4293bed51d92254df23d8ceaf6c0e17146d508a776/starlette-0.41.2-py3-none-any.whl", hash = "sha256:fbc189474b4731cf30fcef52f18a8d070e3f3b46c6a04c97579e85e6ffca942d", size = 73259, upload_time = "2024-10-27T08:20:00.052Z" }, ] [[package]] @@ -2385,18 +2455,18 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mpmath" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e5/57/3485a1a3dff51bfd691962768b14310dae452431754bfc091250be50dd29/sympy-1.12.tar.gz", hash = "sha256:ebf595c8dac3e0fdc4152c51878b498396ec7f30e7a914d6071e674d49420fb8", size = 6722203 } +sdist = { url = "https://files.pythonhosted.org/packages/e5/57/3485a1a3dff51bfd691962768b14310dae452431754bfc091250be50dd29/sympy-1.12.tar.gz", hash = "sha256:ebf595c8dac3e0fdc4152c51878b498396ec7f30e7a914d6071e674d49420fb8", size = 6722203, upload_time = "2023-05-10T18:23:00.378Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl", hash = "sha256:c3588cd4295d0c0f603d0f2ae780587e64e2efeedb3521e46b9bb1d08d184fa5", size = 5742435 }, + { url = "https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl", hash = "sha256:c3588cd4295d0c0f603d0f2ae780587e64e2efeedb3521e46b9bb1d08d184fa5", size = 5742435, upload_time = "2023-05-10T18:22:14.76Z" }, ] [[package]] name = "threadpoolctl" version = "3.2.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/47/8a/c05f7831beb32aff70f808766224f11c650f7edfd49b27a8fc6666107006/threadpoolctl-3.2.0.tar.gz", hash = "sha256:c96a0ba3bdddeaca37dc4cc7344aafad41cdb8c313f74fdfe387a867bba93355", size = 36266 } +sdist = { url = "https://files.pythonhosted.org/packages/47/8a/c05f7831beb32aff70f808766224f11c650f7edfd49b27a8fc6666107006/threadpoolctl-3.2.0.tar.gz", hash = "sha256:c96a0ba3bdddeaca37dc4cc7344aafad41cdb8c313f74fdfe387a867bba93355", size = 36266, upload_time = "2023-07-13T14:53:53.299Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/81/12/fd4dea011af9d69e1cad05c75f3f7202cdcbeac9b712eea58ca779a72865/threadpoolctl-3.2.0-py3-none-any.whl", hash = "sha256:2b7818516e423bdaebb97c723f86a7c6b0a83d3f3b0970328d66f4d9104dc032", size = 15539 }, + { url = "https://files.pythonhosted.org/packages/81/12/fd4dea011af9d69e1cad05c75f3f7202cdcbeac9b712eea58ca779a72865/threadpoolctl-3.2.0-py3-none-any.whl", hash = "sha256:2b7818516e423bdaebb97c723f86a7c6b0a83d3f3b0970328d66f4d9104dc032", size = 15539, upload_time = "2023-07-13T14:53:39.336Z" }, ] [[package]] @@ -2406,9 +2476,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f8/a4/6c0eadea1ccfcda27e6cce400c366098b5b082138a073f4252fe399f4148/tifffile-2023.12.9.tar.gz", hash = "sha256:9dd1da91180a6453018a241ff219e1905f169384355cd89c9ef4034c1b46cdb8", size = 353467 } +sdist = { url = "https://files.pythonhosted.org/packages/f8/a4/6c0eadea1ccfcda27e6cce400c366098b5b082138a073f4252fe399f4148/tifffile-2023.12.9.tar.gz", hash = "sha256:9dd1da91180a6453018a241ff219e1905f169384355cd89c9ef4034c1b46cdb8", size = 353467, upload_time = "2023-12-09T20:46:29.203Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/54/a4/569fc717831969cf48bced350bdaf070cdeab06918d179429899e144358d/tifffile-2023.12.9-py3-none-any.whl", hash = "sha256:9b066e4b1a900891ea42ffd33dab8ba34c537935618b9893ddef42d7d422692f", size = 223627 }, + { url = "https://files.pythonhosted.org/packages/54/a4/569fc717831969cf48bced350bdaf070cdeab06918d179429899e144358d/tifffile-2023.12.9-py3-none-any.whl", hash = "sha256:9b066e4b1a900891ea42ffd33dab8ba34c537935618b9893ddef42d7d422692f", size = 223627, upload_time = "2023-12-09T20:46:26.569Z" }, ] [[package]] @@ -2418,31 +2488,31 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "huggingface-hub" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/92/76/5ac0c97f1117b91b7eb7323dcd61af80d72f790b4df71249a7850c195f30/tokenizers-0.21.1.tar.gz", hash = "sha256:a1bb04dc5b448985f86ecd4b05407f5a8d97cb2c0532199b2a302a604a0165ab", size = 343256 } +sdist = { url = "https://files.pythonhosted.org/packages/92/76/5ac0c97f1117b91b7eb7323dcd61af80d72f790b4df71249a7850c195f30/tokenizers-0.21.1.tar.gz", hash = "sha256:a1bb04dc5b448985f86ecd4b05407f5a8d97cb2c0532199b2a302a604a0165ab", size = 343256, upload_time = "2025-03-13T10:51:18.189Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a5/1f/328aee25f9115bf04262e8b4e5a2050b7b7cf44b59c74e982db7270c7f30/tokenizers-0.21.1-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:e78e413e9e668ad790a29456e677d9d3aa50a9ad311a40905d6861ba7692cf41", size = 2780767 }, - { url = "https://files.pythonhosted.org/packages/ae/1a/4526797f3719b0287853f12c5ad563a9be09d446c44ac784cdd7c50f76ab/tokenizers-0.21.1-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:cd51cd0a91ecc801633829fcd1fda9cf8682ed3477c6243b9a095539de4aecf3", size = 2650555 }, - { url = "https://files.pythonhosted.org/packages/4d/7a/a209b29f971a9fdc1da86f917fe4524564924db50d13f0724feed37b2a4d/tokenizers-0.21.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28da6b72d4fb14ee200a1bd386ff74ade8992d7f725f2bde2c495a9a98cf4d9f", size = 2937541 }, - { url = "https://files.pythonhosted.org/packages/3c/1e/b788b50ffc6191e0b1fc2b0d49df8cff16fe415302e5ceb89f619d12c5bc/tokenizers-0.21.1-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:34d8cfde551c9916cb92014e040806122295a6800914bab5865deb85623931cf", size = 2819058 }, - { url = "https://files.pythonhosted.org/packages/36/aa/3626dfa09a0ecc5b57a8c58eeaeb7dd7ca9a37ad9dd681edab5acd55764c/tokenizers-0.21.1-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aaa852d23e125b73d283c98f007e06d4595732104b65402f46e8ef24b588d9f8", size = 3133278 }, - { url = "https://files.pythonhosted.org/packages/a4/4d/8fbc203838b3d26269f944a89459d94c858f5b3f9a9b6ee9728cdcf69161/tokenizers-0.21.1-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a21a15d5c8e603331b8a59548bbe113564136dc0f5ad8306dd5033459a226da0", size = 3144253 }, - { url = "https://files.pythonhosted.org/packages/d8/1b/2bd062adeb7c7511b847b32e356024980c0ffcf35f28947792c2d8ad2288/tokenizers-0.21.1-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2fdbd4c067c60a0ac7eca14b6bd18a5bebace54eb757c706b47ea93204f7a37c", size = 3398225 }, - { url = "https://files.pythonhosted.org/packages/8a/63/38be071b0c8e06840bc6046991636bcb30c27f6bb1e670f4f4bc87cf49cc/tokenizers-0.21.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dd9a0061e403546f7377df940e866c3e678d7d4e9643d0461ea442b4f89e61a", size = 3038874 }, - { url = "https://files.pythonhosted.org/packages/ec/83/afa94193c09246417c23a3c75a8a0a96bf44ab5630a3015538d0c316dd4b/tokenizers-0.21.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:db9484aeb2e200c43b915a1a0150ea885e35f357a5a8fabf7373af333dcc8dbf", size = 9014448 }, - { url = "https://files.pythonhosted.org/packages/ae/b3/0e1a37d4f84c0f014d43701c11eb8072704f6efe8d8fc2dcdb79c47d76de/tokenizers-0.21.1-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:ed248ab5279e601a30a4d67bdb897ecbe955a50f1e7bb62bd99f07dd11c2f5b6", size = 8937877 }, - { url = "https://files.pythonhosted.org/packages/ac/33/ff08f50e6d615eb180a4a328c65907feb6ded0b8f990ec923969759dc379/tokenizers-0.21.1-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:9ac78b12e541d4ce67b4dfd970e44c060a2147b9b2a21f509566d556a509c67d", size = 9186645 }, - { url = "https://files.pythonhosted.org/packages/5f/aa/8ae85f69a9f6012c6f8011c6f4aa1c96154c816e9eea2e1b758601157833/tokenizers-0.21.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e5a69c1a4496b81a5ee5d2c1f3f7fbdf95e90a0196101b0ee89ed9956b8a168f", size = 9384380 }, - { url = "https://files.pythonhosted.org/packages/e8/5b/a5d98c89f747455e8b7a9504910c865d5e51da55e825a7ae641fb5ff0a58/tokenizers-0.21.1-cp39-abi3-win32.whl", hash = "sha256:1039a3a5734944e09de1d48761ade94e00d0fa760c0e0551151d4dd851ba63e3", size = 2239506 }, - { url = "https://files.pythonhosted.org/packages/e6/b6/072a8e053ae600dcc2ac0da81a23548e3b523301a442a6ca900e92ac35be/tokenizers-0.21.1-cp39-abi3-win_amd64.whl", hash = "sha256:0f0dcbcc9f6e13e675a66d7a5f2f225a736745ce484c1a4e07476a89ccdad382", size = 2435481 }, + { url = "https://files.pythonhosted.org/packages/a5/1f/328aee25f9115bf04262e8b4e5a2050b7b7cf44b59c74e982db7270c7f30/tokenizers-0.21.1-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:e78e413e9e668ad790a29456e677d9d3aa50a9ad311a40905d6861ba7692cf41", size = 2780767, upload_time = "2025-03-13T10:51:09.459Z" }, + { url = "https://files.pythonhosted.org/packages/ae/1a/4526797f3719b0287853f12c5ad563a9be09d446c44ac784cdd7c50f76ab/tokenizers-0.21.1-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:cd51cd0a91ecc801633829fcd1fda9cf8682ed3477c6243b9a095539de4aecf3", size = 2650555, upload_time = "2025-03-13T10:51:07.692Z" }, + { url = "https://files.pythonhosted.org/packages/4d/7a/a209b29f971a9fdc1da86f917fe4524564924db50d13f0724feed37b2a4d/tokenizers-0.21.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28da6b72d4fb14ee200a1bd386ff74ade8992d7f725f2bde2c495a9a98cf4d9f", size = 2937541, upload_time = "2025-03-13T10:50:56.679Z" }, + { url = "https://files.pythonhosted.org/packages/3c/1e/b788b50ffc6191e0b1fc2b0d49df8cff16fe415302e5ceb89f619d12c5bc/tokenizers-0.21.1-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:34d8cfde551c9916cb92014e040806122295a6800914bab5865deb85623931cf", size = 2819058, upload_time = "2025-03-13T10:50:59.525Z" }, + { url = "https://files.pythonhosted.org/packages/36/aa/3626dfa09a0ecc5b57a8c58eeaeb7dd7ca9a37ad9dd681edab5acd55764c/tokenizers-0.21.1-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aaa852d23e125b73d283c98f007e06d4595732104b65402f46e8ef24b588d9f8", size = 3133278, upload_time = "2025-03-13T10:51:04.678Z" }, + { url = "https://files.pythonhosted.org/packages/a4/4d/8fbc203838b3d26269f944a89459d94c858f5b3f9a9b6ee9728cdcf69161/tokenizers-0.21.1-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a21a15d5c8e603331b8a59548bbe113564136dc0f5ad8306dd5033459a226da0", size = 3144253, upload_time = "2025-03-13T10:51:01.261Z" }, + { url = "https://files.pythonhosted.org/packages/d8/1b/2bd062adeb7c7511b847b32e356024980c0ffcf35f28947792c2d8ad2288/tokenizers-0.21.1-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2fdbd4c067c60a0ac7eca14b6bd18a5bebace54eb757c706b47ea93204f7a37c", size = 3398225, upload_time = "2025-03-13T10:51:03.243Z" }, + { url = "https://files.pythonhosted.org/packages/8a/63/38be071b0c8e06840bc6046991636bcb30c27f6bb1e670f4f4bc87cf49cc/tokenizers-0.21.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dd9a0061e403546f7377df940e866c3e678d7d4e9643d0461ea442b4f89e61a", size = 3038874, upload_time = "2025-03-13T10:51:06.235Z" }, + { url = "https://files.pythonhosted.org/packages/ec/83/afa94193c09246417c23a3c75a8a0a96bf44ab5630a3015538d0c316dd4b/tokenizers-0.21.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:db9484aeb2e200c43b915a1a0150ea885e35f357a5a8fabf7373af333dcc8dbf", size = 9014448, upload_time = "2025-03-13T10:51:10.927Z" }, + { url = "https://files.pythonhosted.org/packages/ae/b3/0e1a37d4f84c0f014d43701c11eb8072704f6efe8d8fc2dcdb79c47d76de/tokenizers-0.21.1-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:ed248ab5279e601a30a4d67bdb897ecbe955a50f1e7bb62bd99f07dd11c2f5b6", size = 8937877, upload_time = "2025-03-13T10:51:12.688Z" }, + { url = "https://files.pythonhosted.org/packages/ac/33/ff08f50e6d615eb180a4a328c65907feb6ded0b8f990ec923969759dc379/tokenizers-0.21.1-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:9ac78b12e541d4ce67b4dfd970e44c060a2147b9b2a21f509566d556a509c67d", size = 9186645, upload_time = "2025-03-13T10:51:14.723Z" }, + { url = "https://files.pythonhosted.org/packages/5f/aa/8ae85f69a9f6012c6f8011c6f4aa1c96154c816e9eea2e1b758601157833/tokenizers-0.21.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e5a69c1a4496b81a5ee5d2c1f3f7fbdf95e90a0196101b0ee89ed9956b8a168f", size = 9384380, upload_time = "2025-03-13T10:51:16.526Z" }, + { url = "https://files.pythonhosted.org/packages/e8/5b/a5d98c89f747455e8b7a9504910c865d5e51da55e825a7ae641fb5ff0a58/tokenizers-0.21.1-cp39-abi3-win32.whl", hash = "sha256:1039a3a5734944e09de1d48761ade94e00d0fa760c0e0551151d4dd851ba63e3", size = 2239506, upload_time = "2025-03-13T10:51:20.643Z" }, + { url = "https://files.pythonhosted.org/packages/e6/b6/072a8e053ae600dcc2ac0da81a23548e3b523301a442a6ca900e92ac35be/tokenizers-0.21.1-cp39-abi3-win_amd64.whl", hash = "sha256:0f0dcbcc9f6e13e675a66d7a5f2f225a736745ce484c1a4e07476a89ccdad382", size = 2435481, upload_time = "2025-03-13T10:51:19.243Z" }, ] [[package]] name = "tomli" version = "2.0.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c0/3f/d7af728f075fb08564c5949a9c95e44352e23dee646869fa104a3b2060a3/tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f", size = 15164 } +sdist = { url = "https://files.pythonhosted.org/packages/c0/3f/d7af728f075fb08564c5949a9c95e44352e23dee646869fa104a3b2060a3/tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f", size = 15164, upload_time = "2022-02-08T10:54:04.006Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", size = 12757 }, + { url = "https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", size = 12757, upload_time = "2022-02-08T10:54:02.017Z" }, ] [[package]] @@ -2452,18 +2522,18 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/03/00/6a9b3aedb0b60a80995ade30f718f1a9902612f22a1aaf531c85a02987f7/tqdm-4.66.3.tar.gz", hash = "sha256:23097a41eba115ba99ecae40d06444c15d1c0c698d527a01c6c8bd1c5d0647e5", size = 169551 } +sdist = { url = "https://files.pythonhosted.org/packages/03/00/6a9b3aedb0b60a80995ade30f718f1a9902612f22a1aaf531c85a02987f7/tqdm-4.66.3.tar.gz", hash = "sha256:23097a41eba115ba99ecae40d06444c15d1c0c698d527a01c6c8bd1c5d0647e5", size = 169551, upload_time = "2024-05-02T21:44:05.084Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/ad/7d47bbf2cae78ff79f29db0bed5016ec9c56b212a93fca624bb88b551a7c/tqdm-4.66.3-py3-none-any.whl", hash = "sha256:4f41d54107ff9a223dca80b53efe4fb654c67efaba7f47bada3ee9d50e05bd53", size = 78374 }, + { url = "https://files.pythonhosted.org/packages/d1/ad/7d47bbf2cae78ff79f29db0bed5016ec9c56b212a93fca624bb88b551a7c/tqdm-4.66.3-py3-none-any.whl", hash = "sha256:4f41d54107ff9a223dca80b53efe4fb654c67efaba7f47bada3ee9d50e05bd53", size = 78374, upload_time = "2024-05-02T21:44:01.541Z" }, ] [[package]] name = "types-pyyaml" version = "6.0.12.20250402" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2d/68/609eed7402f87c9874af39d35942744e39646d1ea9011765ec87b01b2a3c/types_pyyaml-6.0.12.20250402.tar.gz", hash = "sha256:d7c13c3e6d335b6af4b0122a01ff1d270aba84ab96d1a1a1063ecba3e13ec075", size = 17282 } +sdist = { url = "https://files.pythonhosted.org/packages/2d/68/609eed7402f87c9874af39d35942744e39646d1ea9011765ec87b01b2a3c/types_pyyaml-6.0.12.20250402.tar.gz", hash = "sha256:d7c13c3e6d335b6af4b0122a01ff1d270aba84ab96d1a1a1063ecba3e13ec075", size = 17282, upload_time = "2025-04-02T02:56:00.235Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/56/1fe61db05685fbb512c07ea9323f06ea727125951f1eb4dff110b3311da3/types_pyyaml-6.0.12.20250402-py3-none-any.whl", hash = "sha256:652348fa9e7a203d4b0d21066dfb00760d3cbd5a15ebb7cf8d33c88a49546681", size = 20329 }, + { url = "https://files.pythonhosted.org/packages/ed/56/1fe61db05685fbb512c07ea9323f06ea727125951f1eb4dff110b3311da3/types_pyyaml-6.0.12.20250402-py3-none-any.whl", hash = "sha256:652348fa9e7a203d4b0d21066dfb00760d3cbd5a15ebb7cf8d33c88a49546681", size = 20329, upload_time = "2025-04-02T02:55:59.382Z" }, ] [[package]] @@ -2473,9 +2543,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/00/7d/eb174f74e3f5634eaacb38031bbe467dfe2e545bc255e5c90096ec46bc46/types_requests-2.32.0.20250328.tar.gz", hash = "sha256:c9e67228ea103bd811c96984fac36ed2ae8da87a36a633964a21f199d60baf32", size = 22995 } +sdist = { url = "https://files.pythonhosted.org/packages/00/7d/eb174f74e3f5634eaacb38031bbe467dfe2e545bc255e5c90096ec46bc46/types_requests-2.32.0.20250328.tar.gz", hash = "sha256:c9e67228ea103bd811c96984fac36ed2ae8da87a36a633964a21f199d60baf32", size = 22995, upload_time = "2025-03-28T02:55:13.271Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cc/15/3700282a9d4ea3b37044264d3e4d1b1f0095a4ebf860a99914fd544e3be3/types_requests-2.32.0.20250328-py3-none-any.whl", hash = "sha256:72ff80f84b15eb3aa7a8e2625fffb6a93f2ad5a0c20215fc1dcfa61117bcb2a2", size = 20663 }, + { url = "https://files.pythonhosted.org/packages/cc/15/3700282a9d4ea3b37044264d3e4d1b1f0095a4ebf860a99914fd544e3be3/types_requests-2.32.0.20250328-py3-none-any.whl", hash = "sha256:72ff80f84b15eb3aa7a8e2625fffb6a93f2ad5a0c20215fc1dcfa61117bcb2a2", size = 20663, upload_time = "2025-03-28T02:55:11.946Z" }, ] [[package]] @@ -2485,36 +2555,36 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "setuptools" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b8/0f/2d1d000c2be3919bcdea15e5da48456bf1e55c18d02c5509ea59dade1408/types_setuptools-76.0.0.20250313.tar.gz", hash = "sha256:b2be66f550f95f3cad2a7d46177b273c7e9c80df7d257fa57addbbcfc8126a9e", size = 43627 } +sdist = { url = "https://files.pythonhosted.org/packages/b8/0f/2d1d000c2be3919bcdea15e5da48456bf1e55c18d02c5509ea59dade1408/types_setuptools-76.0.0.20250313.tar.gz", hash = "sha256:b2be66f550f95f3cad2a7d46177b273c7e9c80df7d257fa57addbbcfc8126a9e", size = 43627, upload_time = "2025-03-13T02:51:28.3Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ca/89/ea9669a0a76b160ffb312d0b02b15bad053c1bc81d2a54e42e3a402ca754/types_setuptools-76.0.0.20250313-py3-none-any.whl", hash = "sha256:bf454b2a49b8cfd7ebcf5844d4dd5fe4c8666782df1e3663c5866fd51a47460e", size = 65845 }, + { url = "https://files.pythonhosted.org/packages/ca/89/ea9669a0a76b160ffb312d0b02b15bad053c1bc81d2a54e42e3a402ca754/types_setuptools-76.0.0.20250313-py3-none-any.whl", hash = "sha256:bf454b2a49b8cfd7ebcf5844d4dd5fe4c8666782df1e3663c5866fd51a47460e", size = 65845, upload_time = "2025-03-13T02:51:27.055Z" }, ] [[package]] name = "types-simplejson" version = "3.20.0.20250326" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/af/14/e26fc55e1ea56f9ea470917d3e2f8240e6d043ca914181021d04115ae0f7/types_simplejson-3.20.0.20250326.tar.gz", hash = "sha256:b2689bc91e0e672d7a5a947b4cb546b76ae7ddc2899c6678e72a10bf96cd97d2", size = 10489 } +sdist = { url = "https://files.pythonhosted.org/packages/af/14/e26fc55e1ea56f9ea470917d3e2f8240e6d043ca914181021d04115ae0f7/types_simplejson-3.20.0.20250326.tar.gz", hash = "sha256:b2689bc91e0e672d7a5a947b4cb546b76ae7ddc2899c6678e72a10bf96cd97d2", size = 10489, upload_time = "2025-03-26T02:53:35.825Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/76/bf/d3f3a5ba47fd18115e8446d39f025b85905d2008677c29ee4d03b4cddd57/types_simplejson-3.20.0.20250326-py3-none-any.whl", hash = "sha256:db1ddea7b8f7623b27a137578f22fc6c618db8c83ccfb1828ca0d2f0ec11efa7", size = 10462 }, + { url = "https://files.pythonhosted.org/packages/76/bf/d3f3a5ba47fd18115e8446d39f025b85905d2008677c29ee4d03b4cddd57/types_simplejson-3.20.0.20250326-py3-none-any.whl", hash = "sha256:db1ddea7b8f7623b27a137578f22fc6c618db8c83ccfb1828ca0d2f0ec11efa7", size = 10462, upload_time = "2025-03-26T02:53:35.036Z" }, ] [[package]] name = "types-ujson" version = "5.10.0.20250326" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cc/5c/c974451c4babdb4ae3588925487edde492d59a8403010b4642a554d09954/types_ujson-5.10.0.20250326.tar.gz", hash = "sha256:5469e05f2c31ecb3c4c0267cc8fe41bcd116826fbb4ded69801a645c687dd014", size = 8340 } +sdist = { url = "https://files.pythonhosted.org/packages/cc/5c/c974451c4babdb4ae3588925487edde492d59a8403010b4642a554d09954/types_ujson-5.10.0.20250326.tar.gz", hash = "sha256:5469e05f2c31ecb3c4c0267cc8fe41bcd116826fbb4ded69801a645c687dd014", size = 8340, upload_time = "2025-03-26T02:53:39.197Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3e/c9/8a73a5f8fa6e70fc02eed506d5ac0ae9ceafbd2b8c9ad34a7de0f29900d6/types_ujson-5.10.0.20250326-py3-none-any.whl", hash = "sha256:acc0913f569def62ef6a892c8a47703f65d05669a3252391a97765cf207dca5b", size = 7644 }, + { url = "https://files.pythonhosted.org/packages/3e/c9/8a73a5f8fa6e70fc02eed506d5ac0ae9ceafbd2b8c9ad34a7de0f29900d6/types_ujson-5.10.0.20250326-py3-none-any.whl", hash = "sha256:acc0913f569def62ef6a892c8a47703f65d05669a3252391a97765cf207dca5b", size = 7644, upload_time = "2025-03-26T02:53:38.2Z" }, ] [[package]] name = "typing-extensions" version = "4.12.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 } +sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321, upload_time = "2024-06-07T18:52:15.995Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 }, + { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438, upload_time = "2024-06-07T18:52:13.582Z" }, ] [[package]] @@ -2524,32 +2594,32 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/82/5c/e6082df02e215b846b4b8c0b887a64d7d08ffaba30605502639d44c06b82/typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122", size = 76222 } +sdist = { url = "https://files.pythonhosted.org/packages/82/5c/e6082df02e215b846b4b8c0b887a64d7d08ffaba30605502639d44c06b82/typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122", size = 76222, upload_time = "2025-02-25T17:27:59.638Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/31/08/aa4fdfb71f7de5176385bd9e90852eaf6b5d622735020ad600f2bab54385/typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", size = 14125 }, + { url = "https://files.pythonhosted.org/packages/31/08/aa4fdfb71f7de5176385bd9e90852eaf6b5d622735020ad600f2bab54385/typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", size = 14125, upload_time = "2025-02-25T17:27:57.754Z" }, ] [[package]] name = "urllib3" version = "2.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/36/dd/a6b232f449e1bc71802a5b7950dc3675d32c6dbc2a1bd6d71f065551adb6/urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54", size = 263900 } +sdist = { url = "https://files.pythonhosted.org/packages/36/dd/a6b232f449e1bc71802a5b7950dc3675d32c6dbc2a1bd6d71f065551adb6/urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54", size = 263900, upload_time = "2023-11-13T12:29:45.049Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/96/94/c31f58c7a7f470d5665935262ebd7455c7e4c7782eb525658d3dbf4b9403/urllib3-2.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3", size = 104579 }, + { url = "https://files.pythonhosted.org/packages/96/94/c31f58c7a7f470d5665935262ebd7455c7e4c7782eb525658d3dbf4b9403/urllib3-2.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3", size = 104579, upload_time = "2023-11-13T12:29:42.719Z" }, ] [[package]] name = "uvicorn" -version = "0.34.0" +version = "0.34.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, { name = "h11" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4b/4d/938bd85e5bf2edeec766267a5015ad969730bb91e31b44021dfe8b22df6c/uvicorn-0.34.0.tar.gz", hash = "sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9", size = 76568 } +sdist = { url = "https://files.pythonhosted.org/packages/a6/ae/9bbb19b9e1c450cf9ecaef06463e40234d98d95bf572fab11b4f19ae5ded/uvicorn-0.34.2.tar.gz", hash = "sha256:0e929828f6186353a80b58ea719861d2629d766293b6d19baf086ba31d4f3328", size = 76815, upload_time = "2025-04-19T06:02:50.101Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl", hash = "sha256:023dc038422502fa28a09c7a30bf2b6991512da7dcdb8fd35fe57cfc154126f4", size = 62315 }, + { url = "https://files.pythonhosted.org/packages/b1/4b/4cef6ce21a2aaca9d852a6e84ef4f135d99fcd74fa75105e2fc0c8308acd/uvicorn-0.34.2-py3-none-any.whl", hash = "sha256:deb49af569084536d269fe0a6d67e3754f104cf03aba7c11c40f01aadf33c403", size = 62483, upload_time = "2025-04-19T06:02:48.42Z" }, ] [package.optional-dependencies] @@ -2567,26 +2637,26 @@ standard = [ name = "uvloop" version = "0.19.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9c/16/728cc5dde368e6eddb299c5aec4d10eaf25335a5af04e8c0abd68e2e9d32/uvloop-0.19.0.tar.gz", hash = "sha256:0246f4fd1bf2bf702e06b0d45ee91677ee5c31242f39aab4ea6fe0c51aedd0fd", size = 2318492 } +sdist = { url = "https://files.pythonhosted.org/packages/9c/16/728cc5dde368e6eddb299c5aec4d10eaf25335a5af04e8c0abd68e2e9d32/uvloop-0.19.0.tar.gz", hash = "sha256:0246f4fd1bf2bf702e06b0d45ee91677ee5c31242f39aab4ea6fe0c51aedd0fd", size = 2318492, upload_time = "2023-10-22T22:03:57.665Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/36/c2/27bf858a576b1fa35b5c2c2029c8cec424a8789e87545ed2f25466d1f21d/uvloop-0.19.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:de4313d7f575474c8f5a12e163f6d89c0a878bc49219641d49e6f1444369a90e", size = 1443484 }, - { url = "https://files.pythonhosted.org/packages/4e/35/05b6064b93f4113412d1fd92bdcb6018607e78ae94d1712e63e533f9b2fa/uvloop-0.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5588bd21cf1fcf06bded085f37e43ce0e00424197e7c10e77afd4bbefffef428", size = 793850 }, - { url = "https://files.pythonhosted.org/packages/aa/56/b62ab4e10458ce96bb30c98d327c127f989d3bb4ef899e4c410c739f7ef6/uvloop-0.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b1fd71c3843327f3bbc3237bedcdb6504fd50368ab3e04d0410e52ec293f5b8", size = 3418601 }, - { url = "https://files.pythonhosted.org/packages/ab/ed/12729fba5e3b7e02ee70b3ea230b88e60a50375cf63300db22607694d2f0/uvloop-0.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a05128d315e2912791de6088c34136bfcdd0c7cbc1cf85fd6fd1bb321b7c849", size = 3416731 }, - { url = "https://files.pythonhosted.org/packages/a2/23/80381a2d728d2a0c36e2eef202f5b77428990004d8fbdd3865558ff49fa5/uvloop-0.19.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:cd81bdc2b8219cb4b2556eea39d2e36bfa375a2dd021404f90a62e44efaaf957", size = 4128572 }, - { url = "https://files.pythonhosted.org/packages/6b/23/1ee41a15e1ad15182e2bd12cbfd37bcb6802f01d6bbcaddf6ca136cbb308/uvloop-0.19.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5f17766fb6da94135526273080f3455a112f82570b2ee5daa64d682387fe0dcd", size = 4129235 }, - { url = "https://files.pythonhosted.org/packages/41/2a/608ad69f27f51280098abee440c33e921d3ad203e2c86f7262e241e49c99/uvloop-0.19.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4ce6b0af8f2729a02a5d1575feacb2a94fc7b2e983868b009d51c9a9d2149bef", size = 1357681 }, - { url = "https://files.pythonhosted.org/packages/13/00/d0923d66d80c8717983493a4d7af747ce47f1c2147d82df057a846ba6bff/uvloop-0.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:31e672bb38b45abc4f26e273be83b72a0d28d074d5b370fc4dcf4c4eb15417d2", size = 746421 }, - { url = "https://files.pythonhosted.org/packages/1f/c7/e494c367b0c6e6453f9bed5a78548f5b2ff49add36302cd915a91d347d88/uvloop-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:570fc0ed613883d8d30ee40397b79207eedd2624891692471808a95069a007c1", size = 3481000 }, - { url = "https://files.pythonhosted.org/packages/86/cc/1829b3f740e4cb1baefff8240a1c6fc8db9e3caac7b93169aec7d4386069/uvloop-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5138821e40b0c3e6c9478643b4660bd44372ae1e16a322b8fc07478f92684e24", size = 3476361 }, - { url = "https://files.pythonhosted.org/packages/7a/4c/ca87e8f5a30629ffa2038c20907c8ab455c5859ff10e810227b76e60d927/uvloop-0.19.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:91ab01c6cd00e39cde50173ba4ec68a1e578fee9279ba64f5221810a9e786533", size = 4169571 }, - { url = "https://files.pythonhosted.org/packages/d2/a9/f947a00c47b1c87c937cac2423243a41ba08f0fb76d04eb0d1d170606e0a/uvloop-0.19.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:47bf3e9312f63684efe283f7342afb414eea4d3011542155c7e625cd799c3b12", size = 4170459 }, - { url = "https://files.pythonhosted.org/packages/85/57/6736733bb0e86a4b5380d04082463b289c0baecaa205934ba81e8a1d5ea4/uvloop-0.19.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:da8435a3bd498419ee8c13c34b89b5005130a476bda1d6ca8cfdde3de35cd650", size = 1355376 }, - { url = "https://files.pythonhosted.org/packages/eb/0c/51339463da912ed34b48d470538d98a91660749b2db56902f23db9b42fdd/uvloop-0.19.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:02506dc23a5d90e04d4f65c7791e65cf44bd91b37f24cfc3ef6cf2aff05dc7ec", size = 745031 }, - { url = "https://files.pythonhosted.org/packages/e6/fc/f0daaf19f5b2116a2d26eb9f98c4a45084aea87bf03c33bcca7aa1ff36e5/uvloop-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2693049be9d36fef81741fddb3f441673ba12a34a704e7b4361efb75cf30befc", size = 4077630 }, - { url = "https://files.pythonhosted.org/packages/fd/96/fdc318ffe82ae567592b213ec2fcd8ecedd927b5da068cf84d56b28c51a4/uvloop-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7010271303961c6f0fe37731004335401eb9075a12680738731e9c92ddd96ad6", size = 4159957 }, - { url = "https://files.pythonhosted.org/packages/71/bc/092068ae7fc16dcf20f3e389126ba7800cee75ffba83f78bf1d167aee3cd/uvloop-0.19.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5daa304d2161d2918fa9a17d5635099a2f78ae5b5960e742b2fcfbb7aefaa593", size = 4014951 }, - { url = "https://files.pythonhosted.org/packages/a6/f2/6ce1e73933eb038c89f929e26042e64b2cb8d4453410153eed14918ca9a8/uvloop-0.19.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7207272c9520203fea9b93843bb775d03e1cf88a80a936ce760f60bb5add92f3", size = 4100911 }, + { url = "https://files.pythonhosted.org/packages/36/c2/27bf858a576b1fa35b5c2c2029c8cec424a8789e87545ed2f25466d1f21d/uvloop-0.19.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:de4313d7f575474c8f5a12e163f6d89c0a878bc49219641d49e6f1444369a90e", size = 1443484, upload_time = "2023-10-22T22:02:54.169Z" }, + { url = "https://files.pythonhosted.org/packages/4e/35/05b6064b93f4113412d1fd92bdcb6018607e78ae94d1712e63e533f9b2fa/uvloop-0.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5588bd21cf1fcf06bded085f37e43ce0e00424197e7c10e77afd4bbefffef428", size = 793850, upload_time = "2023-10-22T22:02:56.311Z" }, + { url = "https://files.pythonhosted.org/packages/aa/56/b62ab4e10458ce96bb30c98d327c127f989d3bb4ef899e4c410c739f7ef6/uvloop-0.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b1fd71c3843327f3bbc3237bedcdb6504fd50368ab3e04d0410e52ec293f5b8", size = 3418601, upload_time = "2023-10-22T22:02:58.717Z" }, + { url = "https://files.pythonhosted.org/packages/ab/ed/12729fba5e3b7e02ee70b3ea230b88e60a50375cf63300db22607694d2f0/uvloop-0.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a05128d315e2912791de6088c34136bfcdd0c7cbc1cf85fd6fd1bb321b7c849", size = 3416731, upload_time = "2023-10-22T22:03:01.043Z" }, + { url = "https://files.pythonhosted.org/packages/a2/23/80381a2d728d2a0c36e2eef202f5b77428990004d8fbdd3865558ff49fa5/uvloop-0.19.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:cd81bdc2b8219cb4b2556eea39d2e36bfa375a2dd021404f90a62e44efaaf957", size = 4128572, upload_time = "2023-10-22T22:03:02.874Z" }, + { url = "https://files.pythonhosted.org/packages/6b/23/1ee41a15e1ad15182e2bd12cbfd37bcb6802f01d6bbcaddf6ca136cbb308/uvloop-0.19.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5f17766fb6da94135526273080f3455a112f82570b2ee5daa64d682387fe0dcd", size = 4129235, upload_time = "2023-10-22T22:03:05.361Z" }, + { url = "https://files.pythonhosted.org/packages/41/2a/608ad69f27f51280098abee440c33e921d3ad203e2c86f7262e241e49c99/uvloop-0.19.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4ce6b0af8f2729a02a5d1575feacb2a94fc7b2e983868b009d51c9a9d2149bef", size = 1357681, upload_time = "2023-10-22T22:03:07.158Z" }, + { url = "https://files.pythonhosted.org/packages/13/00/d0923d66d80c8717983493a4d7af747ce47f1c2147d82df057a846ba6bff/uvloop-0.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:31e672bb38b45abc4f26e273be83b72a0d28d074d5b370fc4dcf4c4eb15417d2", size = 746421, upload_time = "2023-10-22T22:03:09.4Z" }, + { url = "https://files.pythonhosted.org/packages/1f/c7/e494c367b0c6e6453f9bed5a78548f5b2ff49add36302cd915a91d347d88/uvloop-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:570fc0ed613883d8d30ee40397b79207eedd2624891692471808a95069a007c1", size = 3481000, upload_time = "2023-10-22T22:03:11.755Z" }, + { url = "https://files.pythonhosted.org/packages/86/cc/1829b3f740e4cb1baefff8240a1c6fc8db9e3caac7b93169aec7d4386069/uvloop-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5138821e40b0c3e6c9478643b4660bd44372ae1e16a322b8fc07478f92684e24", size = 3476361, upload_time = "2023-10-22T22:03:13.841Z" }, + { url = "https://files.pythonhosted.org/packages/7a/4c/ca87e8f5a30629ffa2038c20907c8ab455c5859ff10e810227b76e60d927/uvloop-0.19.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:91ab01c6cd00e39cde50173ba4ec68a1e578fee9279ba64f5221810a9e786533", size = 4169571, upload_time = "2023-10-22T22:03:15.618Z" }, + { url = "https://files.pythonhosted.org/packages/d2/a9/f947a00c47b1c87c937cac2423243a41ba08f0fb76d04eb0d1d170606e0a/uvloop-0.19.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:47bf3e9312f63684efe283f7342afb414eea4d3011542155c7e625cd799c3b12", size = 4170459, upload_time = "2023-10-22T22:03:17.988Z" }, + { url = "https://files.pythonhosted.org/packages/85/57/6736733bb0e86a4b5380d04082463b289c0baecaa205934ba81e8a1d5ea4/uvloop-0.19.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:da8435a3bd498419ee8c13c34b89b5005130a476bda1d6ca8cfdde3de35cd650", size = 1355376, upload_time = "2023-10-22T22:03:20.075Z" }, + { url = "https://files.pythonhosted.org/packages/eb/0c/51339463da912ed34b48d470538d98a91660749b2db56902f23db9b42fdd/uvloop-0.19.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:02506dc23a5d90e04d4f65c7791e65cf44bd91b37f24cfc3ef6cf2aff05dc7ec", size = 745031, upload_time = "2023-10-22T22:03:21.404Z" }, + { url = "https://files.pythonhosted.org/packages/e6/fc/f0daaf19f5b2116a2d26eb9f98c4a45084aea87bf03c33bcca7aa1ff36e5/uvloop-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2693049be9d36fef81741fddb3f441673ba12a34a704e7b4361efb75cf30befc", size = 4077630, upload_time = "2023-10-22T22:03:23.568Z" }, + { url = "https://files.pythonhosted.org/packages/fd/96/fdc318ffe82ae567592b213ec2fcd8ecedd927b5da068cf84d56b28c51a4/uvloop-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7010271303961c6f0fe37731004335401eb9075a12680738731e9c92ddd96ad6", size = 4159957, upload_time = "2023-10-22T22:03:25.278Z" }, + { url = "https://files.pythonhosted.org/packages/71/bc/092068ae7fc16dcf20f3e389126ba7800cee75ffba83f78bf1d167aee3cd/uvloop-0.19.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5daa304d2161d2918fa9a17d5635099a2f78ae5b5960e742b2fcfbb7aefaa593", size = 4014951, upload_time = "2023-10-22T22:03:27.055Z" }, + { url = "https://files.pythonhosted.org/packages/a6/f2/6ce1e73933eb038c89f929e26042e64b2cb8d4453410153eed14918ca9a8/uvloop-0.19.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7207272c9520203fea9b93843bb775d03e1cf88a80a936ce760f60bb5add92f3", size = 4100911, upload_time = "2023-10-22T22:03:29.39Z" }, ] [[package]] @@ -2596,106 +2666,115 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/66/79/0ee412e1228aaf6f9568aa180b43cb482472de52560fbd7c283c786534af/watchfiles-0.21.0.tar.gz", hash = "sha256:c76c635fabf542bb78524905718c39f736a98e5ab25b23ec6d4abede1a85a6a3", size = 37098 } +sdist = { url = "https://files.pythonhosted.org/packages/66/79/0ee412e1228aaf6f9568aa180b43cb482472de52560fbd7c283c786534af/watchfiles-0.21.0.tar.gz", hash = "sha256:c76c635fabf542bb78524905718c39f736a98e5ab25b23ec6d4abede1a85a6a3", size = 37098, upload_time = "2023-10-13T13:06:39.809Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6e/85/ea2a035b7d86bf0a29ee1c32bc2df8ad4da77e6602806e679d9735ff28cb/watchfiles-0.21.0-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:27b4035013f1ea49c6c0b42d983133b136637a527e48c132d368eb19bf1ac6aa", size = 428182 }, - { url = "https://files.pythonhosted.org/packages/b5/e5/240e5eb3ff0ee3da3b028ac5be2019c407bdd0f3fdb02bd75fdf3bd10aff/watchfiles-0.21.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c81818595eff6e92535ff32825f31c116f867f64ff8cdf6562cd1d6b2e1e8f3e", size = 418275 }, - { url = "https://files.pythonhosted.org/packages/5b/79/ecd0dfb04443a1900cd3952d7ea6493bf655c2db9a0d3736a5d98a15da39/watchfiles-0.21.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6c107ea3cf2bd07199d66f156e3ea756d1b84dfd43b542b2d870b77868c98c03", size = 1379785 }, - { url = "https://files.pythonhosted.org/packages/41/0e/3333b986b1889bb71f0e44b3fac0591824a679619b8b8ddd70ff8858edc4/watchfiles-0.21.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d9ac347653ebd95839a7c607608703b20bc07e577e870d824fa4801bc1cb124", size = 1349374 }, - { url = "https://files.pythonhosted.org/packages/18/c4/ad5ad16cad900a29aaa792e0ed121ff70d76f74062b051661090d88c6dfd/watchfiles-0.21.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5eb86c6acb498208e7663ca22dbe68ca2cf42ab5bf1c776670a50919a56e64ab", size = 1348033 }, - { url = "https://files.pythonhosted.org/packages/4e/d2/769254ff04ba88ceb179a6e892606ac4da17338eb010e85ca7a9c3339234/watchfiles-0.21.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f564bf68404144ea6b87a78a3f910cc8de216c6b12a4cf0b27718bf4ec38d303", size = 1464393 }, - { url = "https://files.pythonhosted.org/packages/14/d0/662800e778ca20e7664dd5df57751aa79ef18b6abb92224b03c8c2e852a6/watchfiles-0.21.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d0f32ebfaa9c6011f8454994f86108c2eb9c79b8b7de00b36d558cadcedaa3d", size = 1542953 }, - { url = "https://files.pythonhosted.org/packages/f7/4b/b90dcdc3bbaf3bb2db733e1beea2d01566b601c15fcf8e71dfcc8686c097/watchfiles-0.21.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6d45d9b699ecbac6c7bd8e0a2609767491540403610962968d258fd6405c17c", size = 1346961 }, - { url = "https://files.pythonhosted.org/packages/92/ff/75cc1b30c5abcad13a2a72e75625ec619c7a393028a111d7d24dba578d5e/watchfiles-0.21.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:aff06b2cac3ef4616e26ba17a9c250c1fe9dd8a5d907d0193f84c499b1b6e6a9", size = 1464393 }, - { url = "https://files.pythonhosted.org/packages/9a/65/12cbeb363bf220482a559c48107edfd87f09248f55e1ac315a36c2098a0f/watchfiles-0.21.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d9792dff410f266051025ecfaa927078b94cc7478954b06796a9756ccc7e14a9", size = 1463409 }, - { url = "https://files.pythonhosted.org/packages/f2/08/92e28867c66f0d9638bb131feca739057efc48dbcd391fd7f0a55507e470/watchfiles-0.21.0-cp310-none-win32.whl", hash = "sha256:214cee7f9e09150d4fb42e24919a1e74d8c9b8a9306ed1474ecaddcd5479c293", size = 268101 }, - { url = "https://files.pythonhosted.org/packages/4b/ea/80527adf1ad51488a96fc201715730af5879f4dfeccb5e2069ff82d890d4/watchfiles-0.21.0-cp310-none-win_amd64.whl", hash = "sha256:1ad7247d79f9f55bb25ab1778fd47f32d70cf36053941f07de0b7c4e96b5d235", size = 279675 }, - { url = "https://files.pythonhosted.org/packages/57/b9/2667286003dd305b81d3a3aa824d3dfc63dacbf2a96faae09e72d953c430/watchfiles-0.21.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:668c265d90de8ae914f860d3eeb164534ba2e836811f91fecc7050416ee70aa7", size = 428210 }, - { url = "https://files.pythonhosted.org/packages/a3/87/6793ac60d2e20c9c1883aec7431c2e7b501ee44a839f6da1b747c13baa23/watchfiles-0.21.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a23092a992e61c3a6a70f350a56db7197242f3490da9c87b500f389b2d01eef", size = 418196 }, - { url = "https://files.pythonhosted.org/packages/5d/12/e1d1d220c5b99196eea38c9a878964f30a2b55ec9d72fd713191725b35e8/watchfiles-0.21.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e7941bbcfdded9c26b0bf720cb7e6fd803d95a55d2c14b4bd1f6a2772230c586", size = 1380287 }, - { url = "https://files.pythonhosted.org/packages/0e/cf/126f0a8683f326d190c3539a769e45e747a80a5fcbf797de82e738c946ae/watchfiles-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:11cd0c3100e2233e9c53106265da31d574355c288e15259c0d40a4405cbae317", size = 1349653 }, - { url = "https://files.pythonhosted.org/packages/20/6e/6cffd795ec65dbc82f15d95b73d3042c1ddaffc4dd25f6c8240bfcf0640f/watchfiles-0.21.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d78f30cbe8b2ce770160d3c08cff01b2ae9306fe66ce899b73f0409dc1846c1b", size = 1348844 }, - { url = "https://files.pythonhosted.org/packages/d5/2a/f9633279d8937ad84c532997405dd106fa6100e8d2b83e364f1c87561f96/watchfiles-0.21.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6674b00b9756b0af620aa2a3346b01f8e2a3dc729d25617e1b89cf6af4a54eb1", size = 1464343 }, - { url = "https://files.pythonhosted.org/packages/d7/49/9b2199bbf3c89e7c8dd795fced9dac29f201be8a28a5df0c8ff625737df6/watchfiles-0.21.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fd7ac678b92b29ba630d8c842d8ad6c555abda1b9ef044d6cc092dacbfc9719d", size = 1542858 }, - { url = "https://files.pythonhosted.org/packages/35/e0/e8a9c1fe30e98c5b3507ad381abc4d9ee2c3b9c0ae62ffe9c164a5838186/watchfiles-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c873345680c1b87f1e09e0eaf8cf6c891b9851d8b4d3645e7efe2ec20a20cc7", size = 1347464 }, - { url = "https://files.pythonhosted.org/packages/ba/66/873739dd7defdfaee4b880114de9463fae18ba13ae2ddd784806b0ee33b6/watchfiles-0.21.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:49f56e6ecc2503e7dbe233fa328b2be1a7797d31548e7a193237dcdf1ad0eee0", size = 1464343 }, - { url = "https://files.pythonhosted.org/packages/bd/51/d7539aa258d8f0e5d7b870af8b9b8964b4f88a1e4517eeb8a2efb838e9b3/watchfiles-0.21.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:02d91cbac553a3ad141db016e3350b03184deaafeba09b9d6439826ee594b365", size = 1463338 }, - { url = "https://files.pythonhosted.org/packages/ee/92/219c539a2a93b6870fa7b84eace946983126b20a7e15c6c034d8d0472682/watchfiles-0.21.0-cp311-none-win32.whl", hash = "sha256:ebe684d7d26239e23d102a2bad2a358dedf18e462e8808778703427d1f584400", size = 267658 }, - { url = "https://files.pythonhosted.org/packages/f3/dc/2a8a447b783f5059c4bf7a6bad8fe59375a5a9ce872774763b25c21c2860/watchfiles-0.21.0-cp311-none-win_amd64.whl", hash = "sha256:4566006aa44cb0d21b8ab53baf4b9c667a0ed23efe4aaad8c227bfba0bf15cbe", size = 280113 }, - { url = "https://files.pythonhosted.org/packages/22/15/e4085181cf0210a6ec6eb29fee0c6088de867ee33d81555076a4a2726e8b/watchfiles-0.21.0-cp311-none-win_arm64.whl", hash = "sha256:c550a56bf209a3d987d5a975cdf2063b3389a5d16caf29db4bdddeae49f22078", size = 268688 }, - { url = "https://files.pythonhosted.org/packages/a1/fd/2f009eb17809afd32a143b442856628585c9ce3a9c6d5c1841e44e35a16c/watchfiles-0.21.0-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:51ddac60b96a42c15d24fbdc7a4bfcd02b5a29c047b7f8bf63d3f6f5a860949a", size = 426902 }, - { url = "https://files.pythonhosted.org/packages/e0/62/a2605f212a136e06f2d056ee7491ede9935ba0f1d5ceafd1f7da2a0c8625/watchfiles-0.21.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:511f0b034120cd1989932bf1e9081aa9fb00f1f949fbd2d9cab6264916ae89b1", size = 417300 }, - { url = "https://files.pythonhosted.org/packages/69/0e/29f158fa22eb2cc1f188b5ec20fb5c0a64eb801e3901ad5b7ad546cbaed0/watchfiles-0.21.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cfb92d49dbb95ec7a07511bc9efb0faff8fe24ef3805662b8d6808ba8409a71a", size = 1378126 }, - { url = "https://files.pythonhosted.org/packages/e8/f3/c67865cb5a174201c52d34e870cc7956b8408ee83ce9a02909d6a2a93a14/watchfiles-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f92944efc564867bbf841c823c8b71bb0be75e06b8ce45c084b46411475a915", size = 1348275 }, - { url = "https://files.pythonhosted.org/packages/d7/eb/b6f1184d1c7b9670f5bd1e184e4c221ecf25fd817cf2fcac6adc387882b5/watchfiles-0.21.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:642d66b75eda909fd1112d35c53816d59789a4b38c141a96d62f50a3ef9b3360", size = 1347255 }, - { url = "https://files.pythonhosted.org/packages/c8/27/e534e4b3fe739f4bf8bd5dc4c26cbc5d3baa427125d8ef78a6556acd6ff4/watchfiles-0.21.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d23bcd6c8eaa6324fe109d8cac01b41fe9a54b8c498af9ce464c1aeeb99903d6", size = 1462845 }, - { url = "https://files.pythonhosted.org/packages/b0/ba/a0d1c1c55f75e7e47c8f79f2314f7ec670b5177596f6d27764aecc7048cd/watchfiles-0.21.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18d5b4da8cf3e41895b34e8c37d13c9ed294954907929aacd95153508d5d89d7", size = 1528957 }, - { url = "https://files.pythonhosted.org/packages/1c/3a/4e38518c4dff58090c01fc8cc051fa08ac9ae00b361c855075809b0058ce/watchfiles-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b8d1eae0f65441963d805f766c7e9cd092f91e0c600c820c764a4ff71a0764c", size = 1345542 }, - { url = "https://files.pythonhosted.org/packages/9f/b7/783097f8137a710d5cd9ccbfcd92e4b453d38dab05cfcb5dbd2c587752e5/watchfiles-0.21.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1fd9a5205139f3c6bb60d11f6072e0552f0a20b712c85f43d42342d162be1235", size = 1462238 }, - { url = "https://files.pythonhosted.org/packages/6b/4c/b741eb38f2c408ae9c5a25235f6506b1dda43486ae0fdb4c462ef75bce11/watchfiles-0.21.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a1e3014a625bcf107fbf38eece0e47fa0190e52e45dc6eee5a8265ddc6dc5ea7", size = 1462406 }, - { url = "https://files.pythonhosted.org/packages/77/e4/8d2b3c67364671b0e1c0ce383895a5415f45ecb3e8586982deff4a8e85c9/watchfiles-0.21.0-cp312-none-win32.whl", hash = "sha256:9d09869f2c5a6f2d9df50ce3064b3391d3ecb6dced708ad64467b9e4f2c9bef3", size = 266789 }, - { url = "https://files.pythonhosted.org/packages/da/f2/6b1de38aeb21eb9dac1ae6a1ee4521566e79690117032036c737cfab52fa/watchfiles-0.21.0-cp312-none-win_amd64.whl", hash = "sha256:18722b50783b5e30a18a8a5db3006bab146d2b705c92eb9a94f78c72beb94094", size = 280292 }, - { url = "https://files.pythonhosted.org/packages/5a/a5/7aba9435beb863c2490bae3173a45f42044ac7a48155d3dd42ab49cfae45/watchfiles-0.21.0-cp312-none-win_arm64.whl", hash = "sha256:a3b9bec9579a15fb3ca2d9878deae789df72f2b0fdaf90ad49ee389cad5edab6", size = 268026 }, - { url = "https://files.pythonhosted.org/packages/62/66/7463ceb43eabc6deaa795c7969ff4d4fd938de54e655035483dfd1e97c84/watchfiles-0.21.0-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:ab03a90b305d2588e8352168e8c5a1520b721d2d367f31e9332c4235b30b8994", size = 429092 }, - { url = "https://files.pythonhosted.org/packages/fe/a3/42686af3a089f34aba35c39abac852869661938dae7025c1a0580dfe0fbf/watchfiles-0.21.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:927c589500f9f41e370b0125c12ac9e7d3a2fd166b89e9ee2828b3dda20bfe6f", size = 419188 }, - { url = "https://files.pythonhosted.org/packages/37/17/4825999346f15d650f4c69093efa64fb040fbff4f706a20e8c4745f64070/watchfiles-0.21.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bd467213195e76f838caf2c28cd65e58302d0254e636e7c0fca81efa4a2e62c", size = 1350366 }, - { url = "https://files.pythonhosted.org/packages/70/76/8d124e14cf51af4d6bba926c7473f253c6efd1539ba62577f079a2d71537/watchfiles-0.21.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02b73130687bc3f6bb79d8a170959042eb56eb3a42df3671c79b428cd73f17cc", size = 1346270 }, + { url = "https://files.pythonhosted.org/packages/6e/85/ea2a035b7d86bf0a29ee1c32bc2df8ad4da77e6602806e679d9735ff28cb/watchfiles-0.21.0-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:27b4035013f1ea49c6c0b42d983133b136637a527e48c132d368eb19bf1ac6aa", size = 428182, upload_time = "2023-10-13T13:04:34.803Z" }, + { url = "https://files.pythonhosted.org/packages/b5/e5/240e5eb3ff0ee3da3b028ac5be2019c407bdd0f3fdb02bd75fdf3bd10aff/watchfiles-0.21.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c81818595eff6e92535ff32825f31c116f867f64ff8cdf6562cd1d6b2e1e8f3e", size = 418275, upload_time = "2023-10-13T13:04:36.632Z" }, + { url = "https://files.pythonhosted.org/packages/5b/79/ecd0dfb04443a1900cd3952d7ea6493bf655c2db9a0d3736a5d98a15da39/watchfiles-0.21.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6c107ea3cf2bd07199d66f156e3ea756d1b84dfd43b542b2d870b77868c98c03", size = 1379785, upload_time = "2023-10-13T13:04:38.641Z" }, + { url = "https://files.pythonhosted.org/packages/41/0e/3333b986b1889bb71f0e44b3fac0591824a679619b8b8ddd70ff8858edc4/watchfiles-0.21.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d9ac347653ebd95839a7c607608703b20bc07e577e870d824fa4801bc1cb124", size = 1349374, upload_time = "2023-10-13T13:04:41.711Z" }, + { url = "https://files.pythonhosted.org/packages/18/c4/ad5ad16cad900a29aaa792e0ed121ff70d76f74062b051661090d88c6dfd/watchfiles-0.21.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5eb86c6acb498208e7663ca22dbe68ca2cf42ab5bf1c776670a50919a56e64ab", size = 1348033, upload_time = "2023-10-13T13:04:43.324Z" }, + { url = "https://files.pythonhosted.org/packages/4e/d2/769254ff04ba88ceb179a6e892606ac4da17338eb010e85ca7a9c3339234/watchfiles-0.21.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f564bf68404144ea6b87a78a3f910cc8de216c6b12a4cf0b27718bf4ec38d303", size = 1464393, upload_time = "2023-10-13T13:04:44.818Z" }, + { url = "https://files.pythonhosted.org/packages/14/d0/662800e778ca20e7664dd5df57751aa79ef18b6abb92224b03c8c2e852a6/watchfiles-0.21.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d0f32ebfaa9c6011f8454994f86108c2eb9c79b8b7de00b36d558cadcedaa3d", size = 1542953, upload_time = "2023-10-13T13:04:46.714Z" }, + { url = "https://files.pythonhosted.org/packages/f7/4b/b90dcdc3bbaf3bb2db733e1beea2d01566b601c15fcf8e71dfcc8686c097/watchfiles-0.21.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6d45d9b699ecbac6c7bd8e0a2609767491540403610962968d258fd6405c17c", size = 1346961, upload_time = "2023-10-13T13:04:48.072Z" }, + { url = "https://files.pythonhosted.org/packages/92/ff/75cc1b30c5abcad13a2a72e75625ec619c7a393028a111d7d24dba578d5e/watchfiles-0.21.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:aff06b2cac3ef4616e26ba17a9c250c1fe9dd8a5d907d0193f84c499b1b6e6a9", size = 1464393, upload_time = "2023-10-13T13:04:49.638Z" }, + { url = "https://files.pythonhosted.org/packages/9a/65/12cbeb363bf220482a559c48107edfd87f09248f55e1ac315a36c2098a0f/watchfiles-0.21.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d9792dff410f266051025ecfaa927078b94cc7478954b06796a9756ccc7e14a9", size = 1463409, upload_time = "2023-10-13T13:04:51.762Z" }, + { url = "https://files.pythonhosted.org/packages/f2/08/92e28867c66f0d9638bb131feca739057efc48dbcd391fd7f0a55507e470/watchfiles-0.21.0-cp310-none-win32.whl", hash = "sha256:214cee7f9e09150d4fb42e24919a1e74d8c9b8a9306ed1474ecaddcd5479c293", size = 268101, upload_time = "2023-10-13T13:04:53.78Z" }, + { url = "https://files.pythonhosted.org/packages/4b/ea/80527adf1ad51488a96fc201715730af5879f4dfeccb5e2069ff82d890d4/watchfiles-0.21.0-cp310-none-win_amd64.whl", hash = "sha256:1ad7247d79f9f55bb25ab1778fd47f32d70cf36053941f07de0b7c4e96b5d235", size = 279675, upload_time = "2023-10-13T13:04:55.113Z" }, + { url = "https://files.pythonhosted.org/packages/57/b9/2667286003dd305b81d3a3aa824d3dfc63dacbf2a96faae09e72d953c430/watchfiles-0.21.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:668c265d90de8ae914f860d3eeb164534ba2e836811f91fecc7050416ee70aa7", size = 428210, upload_time = "2023-10-13T13:04:56.894Z" }, + { url = "https://files.pythonhosted.org/packages/a3/87/6793ac60d2e20c9c1883aec7431c2e7b501ee44a839f6da1b747c13baa23/watchfiles-0.21.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a23092a992e61c3a6a70f350a56db7197242f3490da9c87b500f389b2d01eef", size = 418196, upload_time = "2023-10-13T13:04:58.19Z" }, + { url = "https://files.pythonhosted.org/packages/5d/12/e1d1d220c5b99196eea38c9a878964f30a2b55ec9d72fd713191725b35e8/watchfiles-0.21.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e7941bbcfdded9c26b0bf720cb7e6fd803d95a55d2c14b4bd1f6a2772230c586", size = 1380287, upload_time = "2023-10-13T13:04:59.923Z" }, + { url = "https://files.pythonhosted.org/packages/0e/cf/126f0a8683f326d190c3539a769e45e747a80a5fcbf797de82e738c946ae/watchfiles-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:11cd0c3100e2233e9c53106265da31d574355c288e15259c0d40a4405cbae317", size = 1349653, upload_time = "2023-10-13T13:05:01.622Z" }, + { url = "https://files.pythonhosted.org/packages/20/6e/6cffd795ec65dbc82f15d95b73d3042c1ddaffc4dd25f6c8240bfcf0640f/watchfiles-0.21.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d78f30cbe8b2ce770160d3c08cff01b2ae9306fe66ce899b73f0409dc1846c1b", size = 1348844, upload_time = "2023-10-13T13:05:03.805Z" }, + { url = "https://files.pythonhosted.org/packages/d5/2a/f9633279d8937ad84c532997405dd106fa6100e8d2b83e364f1c87561f96/watchfiles-0.21.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6674b00b9756b0af620aa2a3346b01f8e2a3dc729d25617e1b89cf6af4a54eb1", size = 1464343, upload_time = "2023-10-13T13:05:05.248Z" }, + { url = "https://files.pythonhosted.org/packages/d7/49/9b2199bbf3c89e7c8dd795fced9dac29f201be8a28a5df0c8ff625737df6/watchfiles-0.21.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fd7ac678b92b29ba630d8c842d8ad6c555abda1b9ef044d6cc092dacbfc9719d", size = 1542858, upload_time = "2023-10-13T13:05:06.791Z" }, + { url = "https://files.pythonhosted.org/packages/35/e0/e8a9c1fe30e98c5b3507ad381abc4d9ee2c3b9c0ae62ffe9c164a5838186/watchfiles-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c873345680c1b87f1e09e0eaf8cf6c891b9851d8b4d3645e7efe2ec20a20cc7", size = 1347464, upload_time = "2023-10-13T13:05:08.622Z" }, + { url = "https://files.pythonhosted.org/packages/ba/66/873739dd7defdfaee4b880114de9463fae18ba13ae2ddd784806b0ee33b6/watchfiles-0.21.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:49f56e6ecc2503e7dbe233fa328b2be1a7797d31548e7a193237dcdf1ad0eee0", size = 1464343, upload_time = "2023-10-13T13:05:10.584Z" }, + { url = "https://files.pythonhosted.org/packages/bd/51/d7539aa258d8f0e5d7b870af8b9b8964b4f88a1e4517eeb8a2efb838e9b3/watchfiles-0.21.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:02d91cbac553a3ad141db016e3350b03184deaafeba09b9d6439826ee594b365", size = 1463338, upload_time = "2023-10-13T13:05:12.671Z" }, + { url = "https://files.pythonhosted.org/packages/ee/92/219c539a2a93b6870fa7b84eace946983126b20a7e15c6c034d8d0472682/watchfiles-0.21.0-cp311-none-win32.whl", hash = "sha256:ebe684d7d26239e23d102a2bad2a358dedf18e462e8808778703427d1f584400", size = 267658, upload_time = "2023-10-13T13:05:13.972Z" }, + { url = "https://files.pythonhosted.org/packages/f3/dc/2a8a447b783f5059c4bf7a6bad8fe59375a5a9ce872774763b25c21c2860/watchfiles-0.21.0-cp311-none-win_amd64.whl", hash = "sha256:4566006aa44cb0d21b8ab53baf4b9c667a0ed23efe4aaad8c227bfba0bf15cbe", size = 280113, upload_time = "2023-10-13T13:05:15.289Z" }, + { url = "https://files.pythonhosted.org/packages/22/15/e4085181cf0210a6ec6eb29fee0c6088de867ee33d81555076a4a2726e8b/watchfiles-0.21.0-cp311-none-win_arm64.whl", hash = "sha256:c550a56bf209a3d987d5a975cdf2063b3389a5d16caf29db4bdddeae49f22078", size = 268688, upload_time = "2023-10-13T13:05:17.144Z" }, + { url = "https://files.pythonhosted.org/packages/a1/fd/2f009eb17809afd32a143b442856628585c9ce3a9c6d5c1841e44e35a16c/watchfiles-0.21.0-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:51ddac60b96a42c15d24fbdc7a4bfcd02b5a29c047b7f8bf63d3f6f5a860949a", size = 426902, upload_time = "2023-10-13T13:05:18.828Z" }, + { url = "https://files.pythonhosted.org/packages/e0/62/a2605f212a136e06f2d056ee7491ede9935ba0f1d5ceafd1f7da2a0c8625/watchfiles-0.21.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:511f0b034120cd1989932bf1e9081aa9fb00f1f949fbd2d9cab6264916ae89b1", size = 417300, upload_time = "2023-10-13T13:05:20.116Z" }, + { url = "https://files.pythonhosted.org/packages/69/0e/29f158fa22eb2cc1f188b5ec20fb5c0a64eb801e3901ad5b7ad546cbaed0/watchfiles-0.21.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cfb92d49dbb95ec7a07511bc9efb0faff8fe24ef3805662b8d6808ba8409a71a", size = 1378126, upload_time = "2023-10-13T13:05:21.508Z" }, + { url = "https://files.pythonhosted.org/packages/e8/f3/c67865cb5a174201c52d34e870cc7956b8408ee83ce9a02909d6a2a93a14/watchfiles-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f92944efc564867bbf841c823c8b71bb0be75e06b8ce45c084b46411475a915", size = 1348275, upload_time = "2023-10-13T13:05:22.995Z" }, + { url = "https://files.pythonhosted.org/packages/d7/eb/b6f1184d1c7b9670f5bd1e184e4c221ecf25fd817cf2fcac6adc387882b5/watchfiles-0.21.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:642d66b75eda909fd1112d35c53816d59789a4b38c141a96d62f50a3ef9b3360", size = 1347255, upload_time = "2023-10-13T13:05:24.618Z" }, + { url = "https://files.pythonhosted.org/packages/c8/27/e534e4b3fe739f4bf8bd5dc4c26cbc5d3baa427125d8ef78a6556acd6ff4/watchfiles-0.21.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d23bcd6c8eaa6324fe109d8cac01b41fe9a54b8c498af9ce464c1aeeb99903d6", size = 1462845, upload_time = "2023-10-13T13:05:26.531Z" }, + { url = "https://files.pythonhosted.org/packages/b0/ba/a0d1c1c55f75e7e47c8f79f2314f7ec670b5177596f6d27764aecc7048cd/watchfiles-0.21.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18d5b4da8cf3e41895b34e8c37d13c9ed294954907929aacd95153508d5d89d7", size = 1528957, upload_time = "2023-10-13T13:05:28.365Z" }, + { url = "https://files.pythonhosted.org/packages/1c/3a/4e38518c4dff58090c01fc8cc051fa08ac9ae00b361c855075809b0058ce/watchfiles-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b8d1eae0f65441963d805f766c7e9cd092f91e0c600c820c764a4ff71a0764c", size = 1345542, upload_time = "2023-10-13T13:05:29.862Z" }, + { url = "https://files.pythonhosted.org/packages/9f/b7/783097f8137a710d5cd9ccbfcd92e4b453d38dab05cfcb5dbd2c587752e5/watchfiles-0.21.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1fd9a5205139f3c6bb60d11f6072e0552f0a20b712c85f43d42342d162be1235", size = 1462238, upload_time = "2023-10-13T13:05:32.245Z" }, + { url = "https://files.pythonhosted.org/packages/6b/4c/b741eb38f2c408ae9c5a25235f6506b1dda43486ae0fdb4c462ef75bce11/watchfiles-0.21.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a1e3014a625bcf107fbf38eece0e47fa0190e52e45dc6eee5a8265ddc6dc5ea7", size = 1462406, upload_time = "2023-10-13T13:05:34.339Z" }, + { url = "https://files.pythonhosted.org/packages/77/e4/8d2b3c67364671b0e1c0ce383895a5415f45ecb3e8586982deff4a8e85c9/watchfiles-0.21.0-cp312-none-win32.whl", hash = "sha256:9d09869f2c5a6f2d9df50ce3064b3391d3ecb6dced708ad64467b9e4f2c9bef3", size = 266789, upload_time = "2023-10-13T13:05:35.606Z" }, + { url = "https://files.pythonhosted.org/packages/da/f2/6b1de38aeb21eb9dac1ae6a1ee4521566e79690117032036c737cfab52fa/watchfiles-0.21.0-cp312-none-win_amd64.whl", hash = "sha256:18722b50783b5e30a18a8a5db3006bab146d2b705c92eb9a94f78c72beb94094", size = 280292, upload_time = "2023-10-13T13:05:37.357Z" }, + { url = "https://files.pythonhosted.org/packages/5a/a5/7aba9435beb863c2490bae3173a45f42044ac7a48155d3dd42ab49cfae45/watchfiles-0.21.0-cp312-none-win_arm64.whl", hash = "sha256:a3b9bec9579a15fb3ca2d9878deae789df72f2b0fdaf90ad49ee389cad5edab6", size = 268026, upload_time = "2023-10-13T13:05:38.591Z" }, + { url = "https://files.pythonhosted.org/packages/62/66/7463ceb43eabc6deaa795c7969ff4d4fd938de54e655035483dfd1e97c84/watchfiles-0.21.0-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:ab03a90b305d2588e8352168e8c5a1520b721d2d367f31e9332c4235b30b8994", size = 429092, upload_time = "2023-10-13T13:06:21.419Z" }, + { url = "https://files.pythonhosted.org/packages/fe/a3/42686af3a089f34aba35c39abac852869661938dae7025c1a0580dfe0fbf/watchfiles-0.21.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:927c589500f9f41e370b0125c12ac9e7d3a2fd166b89e9ee2828b3dda20bfe6f", size = 419188, upload_time = "2023-10-13T13:06:22.934Z" }, + { url = "https://files.pythonhosted.org/packages/37/17/4825999346f15d650f4c69093efa64fb040fbff4f706a20e8c4745f64070/watchfiles-0.21.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bd467213195e76f838caf2c28cd65e58302d0254e636e7c0fca81efa4a2e62c", size = 1350366, upload_time = "2023-10-13T13:06:24.254Z" }, + { url = "https://files.pythonhosted.org/packages/70/76/8d124e14cf51af4d6bba926c7473f253c6efd1539ba62577f079a2d71537/watchfiles-0.21.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02b73130687bc3f6bb79d8a170959042eb56eb3a42df3671c79b428cd73f17cc", size = 1346270, upload_time = "2023-10-13T13:06:25.742Z" }, ] [[package]] name = "wcwidth" version = "0.2.13" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6c/63/53559446a878410fc5a5974feb13d31d78d752eb18aeba59c7fef1af7598/wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5", size = 101301 } +sdist = { url = "https://files.pythonhosted.org/packages/6c/63/53559446a878410fc5a5974feb13d31d78d752eb18aeba59c7fef1af7598/wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5", size = 101301, upload_time = "2024-01-06T02:10:57.829Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166 }, + { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166, upload_time = "2024-01-06T02:10:55.763Z" }, +] + +[[package]] +name = "websocket-client" +version = "1.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e6/30/fba0d96b4b5fbf5948ed3f4681f7da2f9f64512e1d303f94b4cc174c24a5/websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da", size = 54648, upload_time = "2024-04-23T22:16:16.976Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/84/44687a29792a70e111c5c477230a72c4b957d88d16141199bf9acb7537a3/websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526", size = 58826, upload_time = "2024-04-23T22:16:14.422Z" }, ] [[package]] name = "websockets" version = "12.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2e/62/7a7874b7285413c954a4cca3c11fd851f11b2fe5b4ae2d9bee4f6d9bdb10/websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b", size = 104994 } +sdist = { url = "https://files.pythonhosted.org/packages/2e/62/7a7874b7285413c954a4cca3c11fd851f11b2fe5b4ae2d9bee4f6d9bdb10/websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b", size = 104994, upload_time = "2023-10-21T14:21:11.88Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b1/b9/360b86ded0920a93bff0db4e4b0aa31370b0208ca240b2e98d62aad8d082/websockets-12.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374", size = 124025 }, - { url = "https://files.pythonhosted.org/packages/bb/d3/1eca0d8fb6f0665c96f0dc7c0d0ec8aa1a425e8c003e0c18e1451f65d177/websockets-12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be", size = 121261 }, - { url = "https://files.pythonhosted.org/packages/4e/e1/f6c3ecf7f1bfd9209e13949db027d7fdea2faf090c69b5f2d17d1d796d96/websockets-12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eb809e816916a3b210bed3c82fb88eaf16e8afcf9c115ebb2bacede1797d2547", size = 121328 }, - { url = "https://files.pythonhosted.org/packages/74/4d/f88eeceb23cb587c4aeca779e3f356cf54817af2368cb7f2bd41f93c8360/websockets-12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c588f6abc13f78a67044c6b1273a99e1cf31038ad51815b3b016ce699f0d75c2", size = 130925 }, - { url = "https://files.pythonhosted.org/packages/16/17/f63d9ee6ffd9afbeea021d5950d6e8db84cd4aead306c6c2ca523805699e/websockets-12.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5aa9348186d79a5f232115ed3fa9020eab66d6c3437d72f9d2c8ac0c6858c558", size = 129930 }, - { url = "https://files.pythonhosted.org/packages/9a/12/c7a7504f5bf74d6ee0533f6fc7d30d8f4b79420ab179d1df2484b07602eb/websockets-12.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6350b14a40c95ddd53e775dbdbbbc59b124a5c8ecd6fbb09c2e52029f7a9f480", size = 130245 }, - { url = "https://files.pythonhosted.org/packages/e4/6a/3600c7771eb31116d2e77383d7345618b37bb93709d041e328c08e2a8eb3/websockets-12.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:70ec754cc2a769bcd218ed8d7209055667b30860ffecb8633a834dde27d6307c", size = 134966 }, - { url = "https://files.pythonhosted.org/packages/22/26/df77c4b7538caebb78c9b97f43169ef742a4f445e032a5ea1aaef88f8f46/websockets-12.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6e96f5ed1b83a8ddb07909b45bd94833b0710f738115751cdaa9da1fb0cb66e8", size = 134196 }, - { url = "https://files.pythonhosted.org/packages/e5/18/18ce9a4a08203c8d0d3d561e3ea4f453daf32f099601fc831e60c8a9b0f2/websockets-12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4d87be612cbef86f994178d5186add3d94e9f31cc3cb499a0482b866ec477603", size = 134822 }, - { url = "https://files.pythonhosted.org/packages/45/51/1f823a341fc20a880e67ae62f6c38c4880a24a4b60fbe544a38f516f39a1/websockets-12.0-cp310-cp310-win32.whl", hash = "sha256:befe90632d66caaf72e8b2ed4d7f02b348913813c8b0a32fae1cc5fe3730902f", size = 124454 }, - { url = "https://files.pythonhosted.org/packages/41/b0/5ec054cfcf23adfc88d39359b85e81d043af8a141e3ac8ce40f45a5ce5f4/websockets-12.0-cp310-cp310-win_amd64.whl", hash = "sha256:363f57ca8bc8576195d0540c648aa58ac18cf85b76ad5202b9f976918f4219cf", size = 124974 }, - { url = "https://files.pythonhosted.org/packages/02/73/9c1e168a2e7fdf26841dc98f5f5502e91dea47428da7690a08101f616169/websockets-12.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5d873c7de42dea355d73f170be0f23788cf3fa9f7bed718fd2830eefedce01b4", size = 124047 }, - { url = "https://files.pythonhosted.org/packages/e4/2d/9a683359ad2ed11b2303a7a94800db19c61d33fa3bde271df09e99936022/websockets-12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3f61726cae9f65b872502ff3c1496abc93ffbe31b278455c418492016e2afc8f", size = 121282 }, - { url = "https://files.pythonhosted.org/packages/95/aa/75fa3b893142d6d98a48cb461169bd268141f2da8bfca97392d6462a02eb/websockets-12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed2fcf7a07334c77fc8a230755c2209223a7cc44fc27597729b8ef5425aa61a3", size = 121325 }, - { url = "https://files.pythonhosted.org/packages/6e/a4/51a25e591d645df71ee0dc3a2c880b28e5514c00ce752f98a40a87abcd1e/websockets-12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e332c210b14b57904869ca9f9bf4ca32f5427a03eeb625da9b616c85a3a506c", size = 131502 }, - { url = "https://files.pythonhosted.org/packages/cd/ea/0ceeea4f5b87398fe2d9f5bcecfa00a1bcd542e2bfcac2f2e5dd612c4e9e/websockets-12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5693ef74233122f8ebab026817b1b37fe25c411ecfca084b29bc7d6efc548f45", size = 130491 }, - { url = "https://files.pythonhosted.org/packages/e3/05/f52a60b66d9faf07a4f7d71dc056bffafe36a7e98c4eb5b78f04fe6e4e85/websockets-12.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e9e7db18b4539a29cc5ad8c8b252738a30e2b13f033c2d6e9d0549b45841c04", size = 130872 }, - { url = "https://files.pythonhosted.org/packages/ac/4e/c7361b2d7b964c40fea924d64881145164961fcd6c90b88b7e3ab2c4f431/websockets-12.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6e2df67b8014767d0f785baa98393725739287684b9f8d8a1001eb2839031447", size = 136318 }, - { url = "https://files.pythonhosted.org/packages/0a/31/337bf35ae5faeaf364c9cddec66681cdf51dc4414ee7a20f92a18e57880f/websockets-12.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bea88d71630c5900690fcb03161ab18f8f244805c59e2e0dc4ffadae0a7ee0ca", size = 135594 }, - { url = "https://files.pythonhosted.org/packages/95/aa/1ac767825c96f9d7e43c4c95683757d4ef28cf11fa47a69aca42428d3e3a/websockets-12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dff6cdf35e31d1315790149fee351f9e52978130cef6c87c4b6c9b3baf78bc53", size = 136191 }, - { url = "https://files.pythonhosted.org/packages/28/4b/344ec5cfeb6bc417da097f8253607c3aed11d9a305fb58346f506bf556d8/websockets-12.0-cp311-cp311-win32.whl", hash = "sha256:3e3aa8c468af01d70332a382350ee95f6986db479ce7af14d5e81ec52aa2b402", size = 124453 }, - { url = "https://files.pythonhosted.org/packages/d1/40/6b169cd1957476374f51f4486a3e85003149e62a14e6b78a958c2222337a/websockets-12.0-cp311-cp311-win_amd64.whl", hash = "sha256:25eb766c8ad27da0f79420b2af4b85d29914ba0edf69f547cc4f06ca6f1d403b", size = 124971 }, - { url = "https://files.pythonhosted.org/packages/a9/6d/23cc898647c8a614a0d9ca703695dd04322fb5135096a20c2684b7c852b6/websockets-12.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df", size = 124061 }, - { url = "https://files.pythonhosted.org/packages/39/34/364f30fdf1a375e4002a26ee3061138d1571dfda6421126127d379d13930/websockets-12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc", size = 121296 }, - { url = "https://files.pythonhosted.org/packages/2e/00/96ae1c9dcb3bc316ef683f2febd8c97dde9f254dc36c3afc65c7645f734c/websockets-12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b", size = 121326 }, - { url = "https://files.pythonhosted.org/packages/af/f1/bba1e64430685dd456c1a1fd6b0c791ae33104967b928aefeff261761e8d/websockets-12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b645f491f3c48d3f8a00d1fce07445fab7347fec54a3e65f0725d730d5b99cb", size = 131807 }, - { url = "https://files.pythonhosted.org/packages/62/3b/98ee269712f37d892b93852ce07b3e6d7653160ca4c0d4f8c8663f8021f8/websockets-12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9893d1aa45a7f8b3bc4510f6ccf8db8c3b62120917af15e3de247f0780294b92", size = 130751 }, - { url = "https://files.pythonhosted.org/packages/f1/00/d6f01ca2b191f8b0808e4132ccd2e7691f0453cbd7d0f72330eb97453c3a/websockets-12.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f38a7b376117ef7aff996e737583172bdf535932c9ca021746573bce40165ed", size = 131176 }, - { url = "https://files.pythonhosted.org/packages/af/9c/703ff3cd8109dcdee6152bae055d852ebaa7750117760ded697ab836cbcf/websockets-12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5", size = 136246 }, - { url = "https://files.pythonhosted.org/packages/0b/a5/1a38fb85a456b9dc874ec984f3ff34f6550eafd17a3da28753cd3c1628e8/websockets-12.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1e4b3f8ea6a9cfa8be8484c9221ec0257508e3a1ec43c36acdefb2a9c3b00aa2", size = 135466 }, - { url = "https://files.pythonhosted.org/packages/3c/98/1261f289dff7e65a38d59d2f591de6ed0a2580b729aebddec033c4d10881/websockets-12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9fdf06fd06c32205a07e47328ab49c40fc1407cdec801d698a7c41167ea45113", size = 136083 }, - { url = "https://files.pythonhosted.org/packages/a9/1c/f68769fba63ccb9c13fe0a25b616bd5aebeef1c7ddebc2ccc32462fb784d/websockets-12.0-cp312-cp312-win32.whl", hash = "sha256:baa386875b70cbd81798fa9f71be689c1bf484f65fd6fb08d051a0ee4e79924d", size = 124460 }, - { url = "https://files.pythonhosted.org/packages/20/52/8915f51f9aaef4e4361c89dd6cf69f72a0159f14e0d25026c81b6ad22525/websockets-12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae0a5da8f35a5be197f328d4727dbcfafa53d1824fac3d96cdd3a642fe09394f", size = 124985 }, - { url = "https://files.pythonhosted.org/packages/43/8b/554a8a8bb6da9dd1ce04c44125e2192af7b7beebf6e3dbfa5d0e285cc20f/websockets-12.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:248d8e2446e13c1d4326e0a6a4e9629cb13a11195051a73acf414812700badbd", size = 121110 }, - { url = "https://files.pythonhosted.org/packages/b0/8e/58b8812940d746ad74d395fb069497255cb5ef50748dfab1e8b386b1f339/websockets-12.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44069528d45a933997a6fef143030d8ca8042f0dfaad753e2906398290e2870", size = 123216 }, - { url = "https://files.pythonhosted.org/packages/81/ee/272cb67ace1786ce6d9f39d47b3c55b335e8b75dd1972a7967aad39178b6/websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c4e37d36f0d19f0a4413d3e18c0d03d0c268ada2061868c1e6f5ab1a6d575077", size = 122821 }, - { url = "https://files.pythonhosted.org/packages/a8/03/387fc902b397729df166763e336f4e5cec09fe7b9d60f442542c94a21be1/websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d829f975fc2e527a3ef2f9c8f25e553eb7bc779c6665e8e1d52aa22800bb38b", size = 122768 }, - { url = "https://files.pythonhosted.org/packages/50/f0/5939fbc9bc1979d79a774ce5b7c4b33c0cefe99af22fb70f7462d0919640/websockets-12.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2c71bd45a777433dd9113847af751aae36e448bc6b8c361a566cb043eda6ec30", size = 125009 }, - { url = "https://files.pythonhosted.org/packages/79/4d/9cc401e7b07e80532ebc8c8e993f42541534da9e9249c59ee0139dcb0352/websockets-12.0-py3-none-any.whl", hash = "sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e", size = 118370 }, + { url = "https://files.pythonhosted.org/packages/b1/b9/360b86ded0920a93bff0db4e4b0aa31370b0208ca240b2e98d62aad8d082/websockets-12.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374", size = 124025, upload_time = "2023-10-21T14:19:28.387Z" }, + { url = "https://files.pythonhosted.org/packages/bb/d3/1eca0d8fb6f0665c96f0dc7c0d0ec8aa1a425e8c003e0c18e1451f65d177/websockets-12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be", size = 121261, upload_time = "2023-10-21T14:19:30.203Z" }, + { url = "https://files.pythonhosted.org/packages/4e/e1/f6c3ecf7f1bfd9209e13949db027d7fdea2faf090c69b5f2d17d1d796d96/websockets-12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eb809e816916a3b210bed3c82fb88eaf16e8afcf9c115ebb2bacede1797d2547", size = 121328, upload_time = "2023-10-21T14:19:31.765Z" }, + { url = "https://files.pythonhosted.org/packages/74/4d/f88eeceb23cb587c4aeca779e3f356cf54817af2368cb7f2bd41f93c8360/websockets-12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c588f6abc13f78a67044c6b1273a99e1cf31038ad51815b3b016ce699f0d75c2", size = 130925, upload_time = "2023-10-21T14:19:33.36Z" }, + { url = "https://files.pythonhosted.org/packages/16/17/f63d9ee6ffd9afbeea021d5950d6e8db84cd4aead306c6c2ca523805699e/websockets-12.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5aa9348186d79a5f232115ed3fa9020eab66d6c3437d72f9d2c8ac0c6858c558", size = 129930, upload_time = "2023-10-21T14:19:35.109Z" }, + { url = "https://files.pythonhosted.org/packages/9a/12/c7a7504f5bf74d6ee0533f6fc7d30d8f4b79420ab179d1df2484b07602eb/websockets-12.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6350b14a40c95ddd53e775dbdbbbc59b124a5c8ecd6fbb09c2e52029f7a9f480", size = 130245, upload_time = "2023-10-21T14:19:36.761Z" }, + { url = "https://files.pythonhosted.org/packages/e4/6a/3600c7771eb31116d2e77383d7345618b37bb93709d041e328c08e2a8eb3/websockets-12.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:70ec754cc2a769bcd218ed8d7209055667b30860ffecb8633a834dde27d6307c", size = 134966, upload_time = "2023-10-21T14:19:38.481Z" }, + { url = "https://files.pythonhosted.org/packages/22/26/df77c4b7538caebb78c9b97f43169ef742a4f445e032a5ea1aaef88f8f46/websockets-12.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6e96f5ed1b83a8ddb07909b45bd94833b0710f738115751cdaa9da1fb0cb66e8", size = 134196, upload_time = "2023-10-21T14:19:40.264Z" }, + { url = "https://files.pythonhosted.org/packages/e5/18/18ce9a4a08203c8d0d3d561e3ea4f453daf32f099601fc831e60c8a9b0f2/websockets-12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4d87be612cbef86f994178d5186add3d94e9f31cc3cb499a0482b866ec477603", size = 134822, upload_time = "2023-10-21T14:19:41.836Z" }, + { url = "https://files.pythonhosted.org/packages/45/51/1f823a341fc20a880e67ae62f6c38c4880a24a4b60fbe544a38f516f39a1/websockets-12.0-cp310-cp310-win32.whl", hash = "sha256:befe90632d66caaf72e8b2ed4d7f02b348913813c8b0a32fae1cc5fe3730902f", size = 124454, upload_time = "2023-10-21T14:19:43.639Z" }, + { url = "https://files.pythonhosted.org/packages/41/b0/5ec054cfcf23adfc88d39359b85e81d043af8a141e3ac8ce40f45a5ce5f4/websockets-12.0-cp310-cp310-win_amd64.whl", hash = "sha256:363f57ca8bc8576195d0540c648aa58ac18cf85b76ad5202b9f976918f4219cf", size = 124974, upload_time = "2023-10-21T14:19:44.934Z" }, + { url = "https://files.pythonhosted.org/packages/02/73/9c1e168a2e7fdf26841dc98f5f5502e91dea47428da7690a08101f616169/websockets-12.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5d873c7de42dea355d73f170be0f23788cf3fa9f7bed718fd2830eefedce01b4", size = 124047, upload_time = "2023-10-21T14:19:46.519Z" }, + { url = "https://files.pythonhosted.org/packages/e4/2d/9a683359ad2ed11b2303a7a94800db19c61d33fa3bde271df09e99936022/websockets-12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3f61726cae9f65b872502ff3c1496abc93ffbe31b278455c418492016e2afc8f", size = 121282, upload_time = "2023-10-21T14:19:47.739Z" }, + { url = "https://files.pythonhosted.org/packages/95/aa/75fa3b893142d6d98a48cb461169bd268141f2da8bfca97392d6462a02eb/websockets-12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed2fcf7a07334c77fc8a230755c2209223a7cc44fc27597729b8ef5425aa61a3", size = 121325, upload_time = "2023-10-21T14:19:49.4Z" }, + { url = "https://files.pythonhosted.org/packages/6e/a4/51a25e591d645df71ee0dc3a2c880b28e5514c00ce752f98a40a87abcd1e/websockets-12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e332c210b14b57904869ca9f9bf4ca32f5427a03eeb625da9b616c85a3a506c", size = 131502, upload_time = "2023-10-21T14:19:50.683Z" }, + { url = "https://files.pythonhosted.org/packages/cd/ea/0ceeea4f5b87398fe2d9f5bcecfa00a1bcd542e2bfcac2f2e5dd612c4e9e/websockets-12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5693ef74233122f8ebab026817b1b37fe25c411ecfca084b29bc7d6efc548f45", size = 130491, upload_time = "2023-10-21T14:19:51.835Z" }, + { url = "https://files.pythonhosted.org/packages/e3/05/f52a60b66d9faf07a4f7d71dc056bffafe36a7e98c4eb5b78f04fe6e4e85/websockets-12.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e9e7db18b4539a29cc5ad8c8b252738a30e2b13f033c2d6e9d0549b45841c04", size = 130872, upload_time = "2023-10-21T14:19:53.071Z" }, + { url = "https://files.pythonhosted.org/packages/ac/4e/c7361b2d7b964c40fea924d64881145164961fcd6c90b88b7e3ab2c4f431/websockets-12.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6e2df67b8014767d0f785baa98393725739287684b9f8d8a1001eb2839031447", size = 136318, upload_time = "2023-10-21T14:19:54.41Z" }, + { url = "https://files.pythonhosted.org/packages/0a/31/337bf35ae5faeaf364c9cddec66681cdf51dc4414ee7a20f92a18e57880f/websockets-12.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bea88d71630c5900690fcb03161ab18f8f244805c59e2e0dc4ffadae0a7ee0ca", size = 135594, upload_time = "2023-10-21T14:19:55.982Z" }, + { url = "https://files.pythonhosted.org/packages/95/aa/1ac767825c96f9d7e43c4c95683757d4ef28cf11fa47a69aca42428d3e3a/websockets-12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dff6cdf35e31d1315790149fee351f9e52978130cef6c87c4b6c9b3baf78bc53", size = 136191, upload_time = "2023-10-21T14:19:57.349Z" }, + { url = "https://files.pythonhosted.org/packages/28/4b/344ec5cfeb6bc417da097f8253607c3aed11d9a305fb58346f506bf556d8/websockets-12.0-cp311-cp311-win32.whl", hash = "sha256:3e3aa8c468af01d70332a382350ee95f6986db479ce7af14d5e81ec52aa2b402", size = 124453, upload_time = "2023-10-21T14:19:59.11Z" }, + { url = "https://files.pythonhosted.org/packages/d1/40/6b169cd1957476374f51f4486a3e85003149e62a14e6b78a958c2222337a/websockets-12.0-cp311-cp311-win_amd64.whl", hash = "sha256:25eb766c8ad27da0f79420b2af4b85d29914ba0edf69f547cc4f06ca6f1d403b", size = 124971, upload_time = "2023-10-21T14:20:00.243Z" }, + { url = "https://files.pythonhosted.org/packages/a9/6d/23cc898647c8a614a0d9ca703695dd04322fb5135096a20c2684b7c852b6/websockets-12.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df", size = 124061, upload_time = "2023-10-21T14:20:02.221Z" }, + { url = "https://files.pythonhosted.org/packages/39/34/364f30fdf1a375e4002a26ee3061138d1571dfda6421126127d379d13930/websockets-12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc", size = 121296, upload_time = "2023-10-21T14:20:03.591Z" }, + { url = "https://files.pythonhosted.org/packages/2e/00/96ae1c9dcb3bc316ef683f2febd8c97dde9f254dc36c3afc65c7645f734c/websockets-12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b", size = 121326, upload_time = "2023-10-21T14:20:04.956Z" }, + { url = "https://files.pythonhosted.org/packages/af/f1/bba1e64430685dd456c1a1fd6b0c791ae33104967b928aefeff261761e8d/websockets-12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b645f491f3c48d3f8a00d1fce07445fab7347fec54a3e65f0725d730d5b99cb", size = 131807, upload_time = "2023-10-21T14:20:06.153Z" }, + { url = "https://files.pythonhosted.org/packages/62/3b/98ee269712f37d892b93852ce07b3e6d7653160ca4c0d4f8c8663f8021f8/websockets-12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9893d1aa45a7f8b3bc4510f6ccf8db8c3b62120917af15e3de247f0780294b92", size = 130751, upload_time = "2023-10-21T14:20:07.753Z" }, + { url = "https://files.pythonhosted.org/packages/f1/00/d6f01ca2b191f8b0808e4132ccd2e7691f0453cbd7d0f72330eb97453c3a/websockets-12.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f38a7b376117ef7aff996e737583172bdf535932c9ca021746573bce40165ed", size = 131176, upload_time = "2023-10-21T14:20:09.212Z" }, + { url = "https://files.pythonhosted.org/packages/af/9c/703ff3cd8109dcdee6152bae055d852ebaa7750117760ded697ab836cbcf/websockets-12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5", size = 136246, upload_time = "2023-10-21T14:20:10.423Z" }, + { url = "https://files.pythonhosted.org/packages/0b/a5/1a38fb85a456b9dc874ec984f3ff34f6550eafd17a3da28753cd3c1628e8/websockets-12.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1e4b3f8ea6a9cfa8be8484c9221ec0257508e3a1ec43c36acdefb2a9c3b00aa2", size = 135466, upload_time = "2023-10-21T14:20:11.826Z" }, + { url = "https://files.pythonhosted.org/packages/3c/98/1261f289dff7e65a38d59d2f591de6ed0a2580b729aebddec033c4d10881/websockets-12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9fdf06fd06c32205a07e47328ab49c40fc1407cdec801d698a7c41167ea45113", size = 136083, upload_time = "2023-10-21T14:20:13.451Z" }, + { url = "https://files.pythonhosted.org/packages/a9/1c/f68769fba63ccb9c13fe0a25b616bd5aebeef1c7ddebc2ccc32462fb784d/websockets-12.0-cp312-cp312-win32.whl", hash = "sha256:baa386875b70cbd81798fa9f71be689c1bf484f65fd6fb08d051a0ee4e79924d", size = 124460, upload_time = "2023-10-21T14:20:14.719Z" }, + { url = "https://files.pythonhosted.org/packages/20/52/8915f51f9aaef4e4361c89dd6cf69f72a0159f14e0d25026c81b6ad22525/websockets-12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae0a5da8f35a5be197f328d4727dbcfafa53d1824fac3d96cdd3a642fe09394f", size = 124985, upload_time = "2023-10-21T14:20:15.817Z" }, + { url = "https://files.pythonhosted.org/packages/43/8b/554a8a8bb6da9dd1ce04c44125e2192af7b7beebf6e3dbfa5d0e285cc20f/websockets-12.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:248d8e2446e13c1d4326e0a6a4e9629cb13a11195051a73acf414812700badbd", size = 121110, upload_time = "2023-10-21T14:20:48.335Z" }, + { url = "https://files.pythonhosted.org/packages/b0/8e/58b8812940d746ad74d395fb069497255cb5ef50748dfab1e8b386b1f339/websockets-12.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44069528d45a933997a6fef143030d8ca8042f0dfaad753e2906398290e2870", size = 123216, upload_time = "2023-10-21T14:20:50.083Z" }, + { url = "https://files.pythonhosted.org/packages/81/ee/272cb67ace1786ce6d9f39d47b3c55b335e8b75dd1972a7967aad39178b6/websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c4e37d36f0d19f0a4413d3e18c0d03d0c268ada2061868c1e6f5ab1a6d575077", size = 122821, upload_time = "2023-10-21T14:20:51.237Z" }, + { url = "https://files.pythonhosted.org/packages/a8/03/387fc902b397729df166763e336f4e5cec09fe7b9d60f442542c94a21be1/websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d829f975fc2e527a3ef2f9c8f25e553eb7bc779c6665e8e1d52aa22800bb38b", size = 122768, upload_time = "2023-10-21T14:20:52.59Z" }, + { url = "https://files.pythonhosted.org/packages/50/f0/5939fbc9bc1979d79a774ce5b7c4b33c0cefe99af22fb70f7462d0919640/websockets-12.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2c71bd45a777433dd9113847af751aae36e448bc6b8c361a566cb043eda6ec30", size = 125009, upload_time = "2023-10-21T14:20:54.419Z" }, + { url = "https://files.pythonhosted.org/packages/79/4d/9cc401e7b07e80532ebc8c8e993f42541534da9e9249c59ee0139dcb0352/websockets-12.0-py3-none-any.whl", hash = "sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e", size = 118370, upload_time = "2023-10-21T14:21:10.075Z" }, ] [[package]] @@ -2705,9 +2784,21 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markupsafe" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/02/51/2e0fc149e7a810d300422ab543f87f2bcf64d985eb6f1228c4efd6e4f8d4/werkzeug-3.0.3.tar.gz", hash = "sha256:097e5bfda9f0aba8da6b8545146def481d06aa7d3266e7448e2cccf67dd8bd18", size = 803342 } +sdist = { url = "https://files.pythonhosted.org/packages/02/51/2e0fc149e7a810d300422ab543f87f2bcf64d985eb6f1228c4efd6e4f8d4/werkzeug-3.0.3.tar.gz", hash = "sha256:097e5bfda9f0aba8da6b8545146def481d06aa7d3266e7448e2cccf67dd8bd18", size = 803342, upload_time = "2024-05-05T23:10:31.999Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9d/6e/e792999e816d19d7fcbfa94c730936750036d65656a76a5a688b57a656c4/werkzeug-3.0.3-py3-none-any.whl", hash = "sha256:fc9645dc43e03e4d630d23143a04a7f947a9a3b5727cd535fdfe155a17cc48c8", size = 227274 }, + { url = "https://files.pythonhosted.org/packages/9d/6e/e792999e816d19d7fcbfa94c730936750036d65656a76a5a688b57a656c4/werkzeug-3.0.3-py3-none-any.whl", hash = "sha256:fc9645dc43e03e4d630d23143a04a7f947a9a3b5727cd535fdfe155a17cc48c8", size = 227274, upload_time = "2024-05-05T23:10:29.567Z" }, +] + +[[package]] +name = "wsproto" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/4a/44d3c295350d776427904d73c189e10aeae66d7f555bb2feee16d1e4ba5a/wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065", size = 53425, upload_time = "2022-08-23T19:58:21.447Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736", size = 24226, upload_time = "2022-08-23T19:58:19.96Z" }, ] [[package]] @@ -2717,9 +2808,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "setuptools" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/46/c2/427f1867bb96555d1d34342f1dd97f8c420966ab564d58d18469a1db8736/zope.event-5.0.tar.gz", hash = "sha256:bac440d8d9891b4068e2b5a2c5e2c9765a9df762944bda6955f96bb9b91e67cd", size = 17350 } +sdist = { url = "https://files.pythonhosted.org/packages/46/c2/427f1867bb96555d1d34342f1dd97f8c420966ab564d58d18469a1db8736/zope.event-5.0.tar.gz", hash = "sha256:bac440d8d9891b4068e2b5a2c5e2c9765a9df762944bda6955f96bb9b91e67cd", size = 17350, upload_time = "2023-06-23T06:28:35.709Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/42/f8dbc2b9ad59e927940325a22d6d3931d630c3644dae7e2369ef5d9ba230/zope.event-5.0-py3-none-any.whl", hash = "sha256:2832e95014f4db26c47a13fdaef84cef2f4df37e66b59d8f1f4a8f319a632c26", size = 6824 }, + { url = "https://files.pythonhosted.org/packages/fe/42/f8dbc2b9ad59e927940325a22d6d3931d630c3644dae7e2369ef5d9ba230/zope.event-5.0-py3-none-any.whl", hash = "sha256:2832e95014f4db26c47a13fdaef84cef2f4df37e66b59d8f1f4a8f319a632c26", size = 6824, upload_time = "2023-06-23T06:28:32.652Z" }, ] [[package]] @@ -2729,24 +2820,24 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "setuptools" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/87/03/6b85c1df2dca1b9acca38b423d1e226d8ffdf30ebd78bcb398c511de8b54/zope.interface-6.1.tar.gz", hash = "sha256:2fdc7ccbd6eb6b7df5353012fbed6c3c5d04ceaca0038f75e601060e95345309", size = 293914 } +sdist = { url = "https://files.pythonhosted.org/packages/87/03/6b85c1df2dca1b9acca38b423d1e226d8ffdf30ebd78bcb398c511de8b54/zope.interface-6.1.tar.gz", hash = "sha256:2fdc7ccbd6eb6b7df5353012fbed6c3c5d04ceaca0038f75e601060e95345309", size = 293914, upload_time = "2023-10-05T11:24:38.943Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3c/ec/c1e7ce928dc10bfe02c6da7e964342d941aaf168f96f8084636167ea50d2/zope.interface-6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:43b576c34ef0c1f5a4981163b551a8781896f2a37f71b8655fd20b5af0386abb", size = 202417 }, - { url = "https://files.pythonhosted.org/packages/f7/0b/12f269ad049fc40a7a3ab85445d7855b6bc6f1e774c5ca9dd6f5c32becb3/zope.interface-6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:67be3ca75012c6e9b109860820a8b6c9a84bfb036fbd1076246b98e56951ca92", size = 202528 }, - { url = "https://files.pythonhosted.org/packages/7f/85/3a35144509eb4a5a2208b48ae8d116a969d67de62cc6513d85602144d9cd/zope.interface-6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b9bc671626281f6045ad61d93a60f52fd5e8209b1610972cf0ef1bbe6d808e3", size = 247532 }, - { url = "https://files.pythonhosted.org/packages/50/d6/6176aaa1f6588378f5a5a4a9c6ad50a36824e902b2f844ca8de7f1b0c4a7/zope.interface-6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbe81def9cf3e46f16ce01d9bfd8bea595e06505e51b7baf45115c77352675fd", size = 241703 }, - { url = "https://files.pythonhosted.org/packages/4f/20/94d4f221989b4bbdd09004b2afb329958e776b7015b7ea8bc915327e195a/zope.interface-6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dc998f6de015723196a904045e5a2217f3590b62ea31990672e31fbc5370b41", size = 247078 }, - { url = "https://files.pythonhosted.org/packages/97/7e/b790b4ab9605010816a91df26a715f163e228d60eb36c947c3118fb65190/zope.interface-6.1-cp310-cp310-win_amd64.whl", hash = "sha256:239a4a08525c080ff833560171d23b249f7f4d17fcbf9316ef4159f44997616f", size = 204155 }, - { url = "https://files.pythonhosted.org/packages/4a/0b/1d8817b8a3631384a26ff7faa4c1f3e6726f7e4950c3442721cfef2c95eb/zope.interface-6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9ffdaa5290422ac0f1688cb8adb1b94ca56cee3ad11f29f2ae301df8aecba7d1", size = 202441 }, - { url = "https://files.pythonhosted.org/packages/3e/1f/43557bb2b6e8537002a5a26af9b899171e26ddfcdf17a00ff729b00c036b/zope.interface-6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:34c15ca9248f2e095ef2e93af2d633358c5f048c49fbfddf5fdfc47d5e263736", size = 202530 }, - { url = "https://files.pythonhosted.org/packages/37/a1/5d2b265f4b7371630cad5873d0873965e35ca3de993d11b9336c720f7259/zope.interface-6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b012d023b4fb59183909b45d7f97fb493ef7a46d2838a5e716e3155081894605", size = 249584 }, - { url = "https://files.pythonhosted.org/packages/8b/6d/547bfa7465e5b296adba0aff5c7ace1150f2a9e429fbf6c33d6618275162/zope.interface-6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:97806e9ca3651588c1baaebb8d0c5ee3db95430b612db354c199b57378312ee8", size = 243737 }, - { url = "https://files.pythonhosted.org/packages/db/5f/46946b588c43eb28efe0e46f4cf455b1ed8b2d1ea62a21b0001c6610662f/zope.interface-6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fddbab55a2473f1d3b8833ec6b7ac31e8211b0aa608df5ab09ce07f3727326de", size = 249104 }, - { url = "https://files.pythonhosted.org/packages/6c/9c/9d3c0e7e5362ea59da3c42b3b2b9fc073db433a0fe3bc6cae0809ccec395/zope.interface-6.1-cp311-cp311-win_amd64.whl", hash = "sha256:a0da79117952a9a41253696ed3e8b560a425197d4e41634a23b1507efe3273f1", size = 204155 }, - { url = "https://files.pythonhosted.org/packages/3c/91/68a0bbc97c2554f87d39572091954e94d043bcd83897cd6a779ca85cb5cc/zope.interface-6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e8bb9c990ca9027b4214fa543fd4025818dc95f8b7abce79d61dc8a2112b561a", size = 202757 }, - { url = "https://files.pythonhosted.org/packages/e1/84/850092a8ab7e87a3ea615daf3f822f7196c52592e3e92f264621b4cfe5a2/zope.interface-6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b51b64432eed4c0744241e9ce5c70dcfecac866dff720e746d0a9c82f371dfa7", size = 202654 }, - { url = "https://files.pythonhosted.org/packages/57/23/508f7f79619ae4e025f5b264a9283efc3c805ed4c0ad75cb28c091179ced/zope.interface-6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa6fd016e9644406d0a61313e50348c706e911dca29736a3266fc9e28ec4ca6d", size = 254400 }, - { url = "https://files.pythonhosted.org/packages/7c/0d/db0ccf0d12767015f23b302aebe98d5eca218aaadc70c2e3908b85fecd2a/zope.interface-6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c8cf55261e15590065039696607f6c9c1aeda700ceee40c70478552d323b3ff", size = 248853 }, - { url = "https://files.pythonhosted.org/packages/fd/4f/8e80173ebcdefe0ff4164444c22b171cf8bd72533026befc2adf079f3ac8/zope.interface-6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e30506bcb03de8983f78884807e4fd95d8db6e65b69257eea05d13d519b83ac0", size = 255127 }, - { url = "https://files.pythonhosted.org/packages/0f/d5/81f9789311d9773a02ed048af7452fc6cedce059748dba956c1dc040340a/zope.interface-6.1-cp312-cp312-win_amd64.whl", hash = "sha256:e33e86fd65f369f10608b08729c8f1c92ec7e0e485964670b4d2633a4812d36b", size = 204268 }, + { url = "https://files.pythonhosted.org/packages/3c/ec/c1e7ce928dc10bfe02c6da7e964342d941aaf168f96f8084636167ea50d2/zope.interface-6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:43b576c34ef0c1f5a4981163b551a8781896f2a37f71b8655fd20b5af0386abb", size = 202417, upload_time = "2023-10-05T11:24:25.141Z" }, + { url = "https://files.pythonhosted.org/packages/f7/0b/12f269ad049fc40a7a3ab85445d7855b6bc6f1e774c5ca9dd6f5c32becb3/zope.interface-6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:67be3ca75012c6e9b109860820a8b6c9a84bfb036fbd1076246b98e56951ca92", size = 202528, upload_time = "2023-10-05T11:24:27.336Z" }, + { url = "https://files.pythonhosted.org/packages/7f/85/3a35144509eb4a5a2208b48ae8d116a969d67de62cc6513d85602144d9cd/zope.interface-6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b9bc671626281f6045ad61d93a60f52fd5e8209b1610972cf0ef1bbe6d808e3", size = 247532, upload_time = "2023-10-05T11:49:20.587Z" }, + { url = "https://files.pythonhosted.org/packages/50/d6/6176aaa1f6588378f5a5a4a9c6ad50a36824e902b2f844ca8de7f1b0c4a7/zope.interface-6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbe81def9cf3e46f16ce01d9bfd8bea595e06505e51b7baf45115c77352675fd", size = 241703, upload_time = "2023-10-05T11:25:33.542Z" }, + { url = "https://files.pythonhosted.org/packages/4f/20/94d4f221989b4bbdd09004b2afb329958e776b7015b7ea8bc915327e195a/zope.interface-6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dc998f6de015723196a904045e5a2217f3590b62ea31990672e31fbc5370b41", size = 247078, upload_time = "2023-10-05T11:25:48.235Z" }, + { url = "https://files.pythonhosted.org/packages/97/7e/b790b4ab9605010816a91df26a715f163e228d60eb36c947c3118fb65190/zope.interface-6.1-cp310-cp310-win_amd64.whl", hash = "sha256:239a4a08525c080ff833560171d23b249f7f4d17fcbf9316ef4159f44997616f", size = 204155, upload_time = "2023-10-05T11:37:56.715Z" }, + { url = "https://files.pythonhosted.org/packages/4a/0b/1d8817b8a3631384a26ff7faa4c1f3e6726f7e4950c3442721cfef2c95eb/zope.interface-6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9ffdaa5290422ac0f1688cb8adb1b94ca56cee3ad11f29f2ae301df8aecba7d1", size = 202441, upload_time = "2023-10-05T11:24:20.414Z" }, + { url = "https://files.pythonhosted.org/packages/3e/1f/43557bb2b6e8537002a5a26af9b899171e26ddfcdf17a00ff729b00c036b/zope.interface-6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:34c15ca9248f2e095ef2e93af2d633358c5f048c49fbfddf5fdfc47d5e263736", size = 202530, upload_time = "2023-10-05T11:24:22.975Z" }, + { url = "https://files.pythonhosted.org/packages/37/a1/5d2b265f4b7371630cad5873d0873965e35ca3de993d11b9336c720f7259/zope.interface-6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b012d023b4fb59183909b45d7f97fb493ef7a46d2838a5e716e3155081894605", size = 249584, upload_time = "2023-10-05T11:49:22.978Z" }, + { url = "https://files.pythonhosted.org/packages/8b/6d/547bfa7465e5b296adba0aff5c7ace1150f2a9e429fbf6c33d6618275162/zope.interface-6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:97806e9ca3651588c1baaebb8d0c5ee3db95430b612db354c199b57378312ee8", size = 243737, upload_time = "2023-10-05T11:25:35.439Z" }, + { url = "https://files.pythonhosted.org/packages/db/5f/46946b588c43eb28efe0e46f4cf455b1ed8b2d1ea62a21b0001c6610662f/zope.interface-6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fddbab55a2473f1d3b8833ec6b7ac31e8211b0aa608df5ab09ce07f3727326de", size = 249104, upload_time = "2023-10-05T11:25:51.355Z" }, + { url = "https://files.pythonhosted.org/packages/6c/9c/9d3c0e7e5362ea59da3c42b3b2b9fc073db433a0fe3bc6cae0809ccec395/zope.interface-6.1-cp311-cp311-win_amd64.whl", hash = "sha256:a0da79117952a9a41253696ed3e8b560a425197d4e41634a23b1507efe3273f1", size = 204155, upload_time = "2023-10-05T11:39:39.139Z" }, + { url = "https://files.pythonhosted.org/packages/3c/91/68a0bbc97c2554f87d39572091954e94d043bcd83897cd6a779ca85cb5cc/zope.interface-6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e8bb9c990ca9027b4214fa543fd4025818dc95f8b7abce79d61dc8a2112b561a", size = 202757, upload_time = "2023-10-05T11:25:05.865Z" }, + { url = "https://files.pythonhosted.org/packages/e1/84/850092a8ab7e87a3ea615daf3f822f7196c52592e3e92f264621b4cfe5a2/zope.interface-6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b51b64432eed4c0744241e9ce5c70dcfecac866dff720e746d0a9c82f371dfa7", size = 202654, upload_time = "2023-10-05T11:25:08.347Z" }, + { url = "https://files.pythonhosted.org/packages/57/23/508f7f79619ae4e025f5b264a9283efc3c805ed4c0ad75cb28c091179ced/zope.interface-6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa6fd016e9644406d0a61313e50348c706e911dca29736a3266fc9e28ec4ca6d", size = 254400, upload_time = "2023-10-05T11:49:25.326Z" }, + { url = "https://files.pythonhosted.org/packages/7c/0d/db0ccf0d12767015f23b302aebe98d5eca218aaadc70c2e3908b85fecd2a/zope.interface-6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c8cf55261e15590065039696607f6c9c1aeda700ceee40c70478552d323b3ff", size = 248853, upload_time = "2023-10-05T11:25:37.37Z" }, + { url = "https://files.pythonhosted.org/packages/fd/4f/8e80173ebcdefe0ff4164444c22b171cf8bd72533026befc2adf079f3ac8/zope.interface-6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e30506bcb03de8983f78884807e4fd95d8db6e65b69257eea05d13d519b83ac0", size = 255127, upload_time = "2023-10-05T11:25:53.819Z" }, + { url = "https://files.pythonhosted.org/packages/0f/d5/81f9789311d9773a02ed048af7452fc6cedce059748dba956c1dc040340a/zope.interface-6.1-cp312-cp312-win_amd64.whl", hash = "sha256:e33e86fd65f369f10608b08729c8f1c92ec7e0e485964670b4d2633a4812d36b", size = 204268, upload_time = "2023-10-05T11:41:22.778Z" }, ] diff --git a/mobile/android/app/src/main/AndroidManifest.xml b/mobile/android/app/src/main/AndroidManifest.xml index 58d7f0655a..eb81dc267b 100644 --- a/mobile/android/app/src/main/AndroidManifest.xml +++ b/mobile/android/app/src/main/AndroidManifest.xml @@ -6,7 +6,6 @@ android:maxSdkVersion="32" /> - @@ -125,4 +124,4 @@ - + \ No newline at end of file diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/BackgroundServicePlugin.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/BackgroundServicePlugin.kt index e7f787e8d8..ae2ec22a71 100644 --- a/mobile/android/app/src/main/kotlin/app/alextran/immich/BackgroundServicePlugin.kt +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/BackgroundServicePlugin.kt @@ -1,17 +1,17 @@ package app.alextran.immich +import android.app.Activity import android.content.ContentResolver import android.content.ContentUris -import android.content.ContentValues import android.content.Context import android.content.Intent import android.net.Uri import android.os.Build import android.os.Bundle -import android.os.Environment import android.provider.MediaStore import android.provider.Settings import android.util.Log +import androidx.annotation.RequiresApi import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.embedding.engine.plugins.activity.ActivityAware import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding @@ -23,6 +23,7 @@ import io.flutter.plugin.common.PluginRegistry import java.security.MessageDigest import java.io.FileInputStream import kotlinx.coroutines.* +import androidx.core.net.toUri /** * Android plugin for Dart `BackgroundService` and file trash operations @@ -33,7 +34,8 @@ class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler, private var fileTrashChannel: MethodChannel? = null private var context: Context? = null private var pendingResult: Result? = null - private val PERMISSION_REQUEST_CODE = 1001 + private val permissionRequestCode = 1001 + private val trashRequestCode = 1002 private var activityBinding: ActivityPluginBinding? = null override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) { @@ -138,36 +140,35 @@ class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler, // File Trash methods moved from MainActivity "moveToTrash" -> { - val fileName = call.argument("fileName") - if (fileName != null) { - if (hasManageStoragePermission()) { - val success = moveToTrash(fileName) - result.success(success) + val mediaUrls = call.argument>("mediaUrls") + if (mediaUrls != null) { + if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) && hasManageMediaPermission()) { + moveToTrash(mediaUrls, result) } else { - result.error("PERMISSION_DENIED", "Storage permission required", null) + result.error("PERMISSION_DENIED", "Media permission required", null) } } else { - result.error("INVALID_NAME", "The file name is not specified.", null) + result.error("INVALID_NAME", "The mediaUrls is not specified.", null) } } "restoreFromTrash" -> { val fileName = call.argument("fileName") - if (fileName != null) { - if (hasManageStoragePermission()) { - val success = untrashImage(fileName) - result.success(success) + val type = call.argument("type") + if (fileName != null && type != null) { + if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) && hasManageMediaPermission()) { + restoreFromTrash(fileName, type, result) } else { - result.error("PERMISSION_DENIED", "Storage permission required", null) + result.error("PERMISSION_DENIED", "Media permission required", null) } } else { result.error("INVALID_NAME", "The file name is not specified.", null) } } - "requestManageStoragePermission" -> { - if (!hasManageStoragePermission()) { - requestManageStoragePermission(result) + "requestManageMediaPermission" -> { + if (!hasManageMediaPermission()) { + requestManageMediaPermission(result) } else { Log.e("Manage storage permission", "Permission already granted") result.success(true) @@ -178,100 +179,98 @@ class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler, } } - // File Trash methods moved from MainActivity - private fun hasManageStoragePermission(): Boolean { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - Environment.isExternalStorageManager() - } else { - true + private fun hasManageMediaPermission(): Boolean { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + MediaStore.canManageMedia(context!!); + } else { + false } } - private fun requestManageStoragePermission(result: Result) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + private fun requestManageMediaPermission(result: Result) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { pendingResult = result // Store the result callback val activity = activityBinding?.activity ?: return - val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION) - intent.data = Uri.parse("package:${activity.packageName}") - activity.startActivityForResult(intent, PERMISSION_REQUEST_CODE) + val intent = Intent(Settings.ACTION_REQUEST_MANAGE_MEDIA) + intent.data = "package:${activity.packageName}".toUri() + activity.startActivityForResult(intent, permissionRequestCode) } else { - result.success(true) + result.success(false) } } - private fun moveToTrash(fileName: String): Boolean { - val contentResolver = context?.contentResolver ?: return false - val uri = getFileUri(fileName) + @RequiresApi(Build.VERSION_CODES.R) + private fun moveToTrash(mediaUrls: List, result: Result) { + val urisToTrash = mediaUrls.map { it.toUri() } + if (urisToTrash.isEmpty()) { + result.error("INVALID_ARGS", "No valid URIs provided", null) + return + } + + toggleTrash(urisToTrash, true, result); + } + + @RequiresApi(Build.VERSION_CODES.R) + private fun restoreFromTrash(name: String, type: Int, result: Result) { + val uri = getTrashedFileUri(name, type) + if (uri == null) { + Log.e("TrashError", "Asset Uri cannot be found obtained") + result.error("TrashError", "Asset Uri cannot be found obtained", null) + return + } Log.e("FILE_URI", uri.toString()) - return uri?.let { moveToTrash(it) } ?: false + uri.let { toggleTrash(listOf(it), false, result) } } - private fun moveToTrash(contentUri: Uri): Boolean { - val contentResolver = context?.contentResolver ?: return false - return try { - val values = ContentValues().apply { - put(MediaStore.MediaColumns.IS_TRASHED, 1) // Move to trash + @RequiresApi(Build.VERSION_CODES.R) + private fun toggleTrash(contentUris: List, isTrashed: Boolean, result: Result) { + val activity = activityBinding?.activity + val contentResolver = context?.contentResolver + if (activity == null || contentResolver == null) { + result.error("TrashError", "Activity or ContentResolver not available", null) + return } - val updated = contentResolver.update(contentUri, values, null, null) - updated > 0 - } catch (e: Exception) { - Log.e("TrashError", "Error moving to trash", e) - false + + try { + val pendingIntent = MediaStore.createTrashRequest(contentResolver, contentUris, isTrashed) + pendingResult = result // Store for onActivityResult + activity.startIntentSenderForResult( + pendingIntent.intentSender, + trashRequestCode, + null, 0, 0, 0 + ) + } catch (e: Exception) { + Log.e("TrashError", "Error creating or starting trash request", e) + result.error("TrashError", "Error creating or starting trash request", null) } } - private fun getFileUri(fileName: String): Uri? { + @RequiresApi(Build.VERSION_CODES.R) + private fun getTrashedFileUri(fileName: String, type: Int): Uri? { val contentResolver = context?.contentResolver ?: return null - val contentUri = MediaStore.Files.getContentUri("external") - val projection = arrayOf(MediaStore.Images.Media._ID) - val selection = "${MediaStore.Images.Media.DISPLAY_NAME} = ?" - val selectionArgs = arrayOf(fileName) - var fileUri: Uri? = null - - contentResolver.query(contentUri, projection, selection, selectionArgs, null)?.use { cursor -> - if (cursor.moveToFirst()) { - val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)) - fileUri = ContentUris.withAppendedId(contentUri, id) - } - } - return fileUri - } - - private fun untrashImage(name: String): Boolean { - val contentResolver = context?.contentResolver ?: return false - val uri = getTrashedFileUri(contentResolver, name) - Log.e("FILE_URI", uri.toString()) - return uri?.let { untrashImage(it) } ?: false - } - - private fun untrashImage(contentUri: Uri): Boolean { - val contentResolver = context?.contentResolver ?: return false - return try { - val values = ContentValues().apply { - put(MediaStore.MediaColumns.IS_TRASHED, 0) // Restore file - } - val updated = contentResolver.update(contentUri, values, null, null) - updated > 0 - } catch (e: Exception) { - Log.e("TrashError", "Error restoring file", e) - false - } - } - - private fun getTrashedFileUri(contentResolver: ContentResolver, fileName: String): Uri? { - val contentUri = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL) + val queryUri = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL) val projection = arrayOf(MediaStore.Files.FileColumns._ID) val queryArgs = Bundle().apply { - putString(ContentResolver.QUERY_ARG_SQL_SELECTION, "${MediaStore.Files.FileColumns.DISPLAY_NAME} = ?") + putString( + ContentResolver.QUERY_ARG_SQL_SELECTION, + "${MediaStore.Files.FileColumns.DISPLAY_NAME} = ?" + ) putStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS, arrayOf(fileName)) putInt(MediaStore.QUERY_ARG_MATCH_TRASHED, MediaStore.MATCH_ONLY) } - contentResolver.query(contentUri, projection, queryArgs, null)?.use { cursor -> + contentResolver.query(queryUri, projection, queryArgs, null)?.use { cursor -> if (cursor.moveToFirst()) { val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID)) + // same order as AssetType from dart + val contentUri = when (type) { + 1 -> MediaStore.Images.Media.EXTERNAL_CONTENT_URI + 2 -> MediaStore.Video.Media.EXTERNAL_CONTENT_URI + 3 -> MediaStore.Audio.Media.EXTERNAL_CONTENT_URI + else -> queryUri + } return ContentUris.withAppendedId(contentUri, id) } } @@ -301,12 +300,19 @@ class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler, // ActivityResultListener implementation override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean { - if (requestCode == PERMISSION_REQUEST_CODE) { - val granted = hasManageStoragePermission() + if (requestCode == permissionRequestCode) { + val granted = hasManageMediaPermission() pendingResult?.success(granted) pendingResult = null return true } + + if (requestCode == trashRequestCode) { + val approved = resultCode == Activity.RESULT_OK + pendingResult?.success(approved) + pendingResult = null + return true + } return false } } diff --git a/mobile/android/fastlane/Fastfile b/mobile/android/fastlane/Fastfile index 612e5084d2..a0b08bb316 100644 --- a/mobile/android/fastlane/Fastfile +++ b/mobile/android/fastlane/Fastfile @@ -35,8 +35,8 @@ platform :android do task: 'bundle', build_type: 'Release', properties: { - "android.injected.version.code" => 193, - "android.injected.version.name" => "1.131.3", + "android.injected.version.code" => 197, + "android.injected.version.name" => "1.132.3", } ) upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab') diff --git a/mobile/drift_schemas/main/drift_schema_v1.json b/mobile/drift_schemas/main/drift_schema_v1.json index 448691afd0..836a926b03 100644 --- a/mobile/drift_schemas/main/drift_schema_v1.json +++ b/mobile/drift_schemas/main/drift_schema_v1.json @@ -1 +1 @@ -{"_meta":{"description":"This file contains a serialized version of schema entities for drift.","version":"1.2.0"},"options":{"store_date_time_values_as_text":true},"entities":[{"id":0,"references":[],"type":"table","data":{"name":"user_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"blob","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_admin","getter_name":"isAdmin","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_admin\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_admin\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"email","getter_name":"email","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"profile_image_path","getter_name":"profileImagePath","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"quota_size_in_bytes","getter_name":"quotaSizeInBytes","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"quota_usage_in_bytes","getter_name":"quotaUsageInBytes","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":1,"references":[0],"type":"table","data":{"name":"user_metadata_entity","was_declared_in_moor":false,"columns":[{"name":"user_id","getter_name":"userId","moor_type":"blob","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"preferences","getter_name":"preferences","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"userPreferenceConverter","dart_type_name":"UserPreferences"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["user_id"]}},{"id":2,"references":[0],"type":"table","data":{"name":"partner_entity","was_declared_in_moor":false,"columns":[{"name":"shared_by_id","getter_name":"sharedById","moor_type":"blob","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"shared_with_id","getter_name":"sharedWithId","moor_type":"blob","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"in_timeline","getter_name":"inTimeline","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"in_timeline\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"in_timeline\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["shared_by_id","shared_with_id"]}},{"id":3,"references":[],"type":"table","data":{"name":"local_asset_entity","was_declared_in_moor":false,"columns":[{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AssetType.values)","dart_type_name":"AssetType"}},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"duration_in_seconds","getter_name":"durationInSeconds","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"local_id","getter_name":"localId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"checksum","getter_name":"checksum","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"width","getter_name":"width","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"height","getter_name":"height","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["local_id"]}},{"id":4,"references":[3],"type":"table","data":{"name":"local_album_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"asset_count","getter_name":"assetCount","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"thumbnail_id","getter_name":"thumbnailId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES local_asset_entity (local_id) ON DELETE SET NULL","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES local_asset_entity (local_id) ON DELETE SET NULL"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"backup_selection","getter_name":"backupSelection","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(BackupSelection.values)","dart_type_name":"BackupSelection"}},{"name":"is_all","getter_name":"isAll","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_all\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_all\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":5,"references":[3,4],"type":"table","data":{"name":"local_album_asset_entity","was_declared_in_moor":false,"columns":[{"name":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES local_asset_entity (local_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES local_asset_entity (local_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"album_id","getter_name":"albumId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES local_album_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES local_album_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["asset_id","album_id"]}},{"id":6,"references":[0],"type":"table","data":{"name":"remote_asset_entity","was_declared_in_moor":false,"columns":[{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AssetType.values)","dart_type_name":"AssetType"}},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"duration_in_seconds","getter_name":"durationInSeconds","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"remote_id","getter_name":"remoteId","moor_type":"blob","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"checksum","getter_name":"checksum","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"UNIQUE","dialectAwareDefaultConstraints":{"sqlite":"UNIQUE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"is_favorite","getter_name":"isFavorite","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_favorite\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_favorite\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"owner_id","getter_name":"ownerId","moor_type":"blob","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"local_date_time","getter_name":"localDateTime","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"thumbhash","getter_name":"thumbhash","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"deleted_at","getter_name":"deletedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["remote_id"]}},{"id":7,"references":[6],"type":"table","data":{"name":"exif_entity","was_declared_in_moor":false,"columns":[{"name":"asset_id","getter_name":"assetId","moor_type":"blob","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (remote_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (remote_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"city","getter_name":"city","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"state","getter_name":"state","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"country","getter_name":"country","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"date_time_original","getter_name":"dateTimeOriginal","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"description","getter_name":"description","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"height","getter_name":"height","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"width","getter_name":"width","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"exposure_time","getter_name":"exposureTime","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"f_number","getter_name":"fNumber","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"file_size","getter_name":"fileSize","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"focal_length","getter_name":"focalLength","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"latitude","getter_name":"latitude","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"longitude","getter_name":"longitude","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"iso","getter_name":"iso","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"make","getter_name":"make","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"model","getter_name":"model","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"orientation","getter_name":"orientation","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"time_zone","getter_name":"timeZone","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"rating","getter_name":"rating","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"projection_type","getter_name":"projectionType","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["asset_id"]}},{"id":8,"references":[3],"type":"index","data":{"on":3,"name":"local_asset_checksum","sql":null,"unique":false,"columns":["checksum"]}},{"id":9,"references":[6],"type":"index","data":{"on":6,"name":"remote_asset_checksum","sql":null,"unique":false,"columns":["checksum"]}}]} \ No newline at end of file +{"_meta":{"description":"This file contains a serialized version of schema entities for drift.","version":"1.2.0"},"options":{"store_date_time_values_as_text":true},"entities":[{"id":0,"references":[],"type":"table","data":{"name":"user_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"blob","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_admin","getter_name":"isAdmin","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_admin\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_admin\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"email","getter_name":"email","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"profile_image_path","getter_name":"profileImagePath","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"quota_size_in_bytes","getter_name":"quotaSizeInBytes","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"quota_usage_in_bytes","getter_name":"quotaUsageInBytes","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":1,"references":[0],"type":"table","data":{"name":"user_metadata_entity","was_declared_in_moor":false,"columns":[{"name":"user_id","getter_name":"userId","moor_type":"blob","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"preferences","getter_name":"preferences","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"userPreferenceConverter","dart_type_name":"UserPreferences"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["user_id"]}},{"id":2,"references":[0],"type":"table","data":{"name":"partner_entity","was_declared_in_moor":false,"columns":[{"name":"shared_by_id","getter_name":"sharedById","moor_type":"blob","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"shared_with_id","getter_name":"sharedWithId","moor_type":"blob","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"in_timeline","getter_name":"inTimeline","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"in_timeline\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"in_timeline\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["shared_by_id","shared_with_id"]}},{"id":3,"references":[],"type":"table","data":{"name":"local_asset_entity","was_declared_in_moor":false,"columns":[{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AssetType.values)","dart_type_name":"AssetType"}},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"duration_in_seconds","getter_name":"durationInSeconds","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"local_id","getter_name":"localId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"checksum","getter_name":"checksum","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_favorite","getter_name":"isFavorite","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_favorite\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_favorite\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["local_id"]}},{"id":4,"references":[3],"type":"table","data":{"name":"local_album_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"thumbnail_id","getter_name":"thumbnailId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES local_asset_entity (local_id) ON DELETE SET NULL","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES local_asset_entity (local_id) ON DELETE SET NULL"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"backup_selection","getter_name":"backupSelection","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(BackupSelection.values)","dart_type_name":"BackupSelection"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":5,"references":[3,4],"type":"table","data":{"name":"local_album_asset_entity","was_declared_in_moor":false,"columns":[{"name":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES local_asset_entity (local_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES local_asset_entity (local_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"album_id","getter_name":"albumId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES local_album_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES local_album_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["asset_id","album_id"]}},{"id":6,"references":[0],"type":"table","data":{"name":"remote_asset_entity","was_declared_in_moor":false,"columns":[{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AssetType.values)","dart_type_name":"AssetType"}},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"duration_in_seconds","getter_name":"durationInSeconds","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"remote_id","getter_name":"remoteId","moor_type":"blob","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"checksum","getter_name":"checksum","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"UNIQUE","dialectAwareDefaultConstraints":{"sqlite":"UNIQUE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"is_favorite","getter_name":"isFavorite","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_favorite\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_favorite\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"owner_id","getter_name":"ownerId","moor_type":"blob","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"local_date_time","getter_name":"localDateTime","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"thumbhash","getter_name":"thumbhash","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"deleted_at","getter_name":"deletedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["remote_id"]}},{"id":7,"references":[6],"type":"table","data":{"name":"exif_entity","was_declared_in_moor":false,"columns":[{"name":"asset_id","getter_name":"assetId","moor_type":"blob","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (remote_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (remote_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"city","getter_name":"city","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"state","getter_name":"state","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"country","getter_name":"country","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"date_time_original","getter_name":"dateTimeOriginal","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"description","getter_name":"description","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"height","getter_name":"height","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"width","getter_name":"width","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"exposure_time","getter_name":"exposureTime","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"f_number","getter_name":"fNumber","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"file_size","getter_name":"fileSize","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"focal_length","getter_name":"focalLength","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"latitude","getter_name":"latitude","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"longitude","getter_name":"longitude","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"iso","getter_name":"iso","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"make","getter_name":"make","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"model","getter_name":"model","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"orientation","getter_name":"orientation","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"time_zone","getter_name":"timeZone","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"rating","getter_name":"rating","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"projection_type","getter_name":"projectionType","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["asset_id"]}},{"id":8,"references":[3],"type":"index","data":{"on":3,"name":"local_asset_checksum","sql":null,"unique":false,"columns":["checksum"]}},{"id":9,"references":[6],"type":"index","data":{"on":6,"name":"remote_asset_checksum","sql":null,"unique":false,"columns":["checksum"]}}]} \ No newline at end of file diff --git a/mobile/ios/Podfile b/mobile/ios/Podfile index a98032db20..ca0166a382 100644 --- a/mobile/ios/Podfile +++ b/mobile/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '12.0' +platform :ios, '14.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -45,7 +45,7 @@ post_install do |installer| installer.generated_projects.each do |project| project.targets.each do |target| target.build_configurations.each do |config| - config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0' + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '14.0' end end end diff --git a/mobile/ios/Podfile.lock b/mobile/ios/Podfile.lock index 908ee84aed..9740d6aa52 100644 --- a/mobile/ios/Podfile.lock +++ b/mobile/ios/Podfile.lock @@ -224,7 +224,7 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/wakelock_plus/ios" SPEC CHECKSUMS: - background_downloader: b42a56120f5348bff70e74222f0e9e6f7f1a1537 + background_downloader: 50e91d979067b82081aba359d7d916b3ba5fadad connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c @@ -261,6 +261,6 @@ SPEC CHECKSUMS: url_launcher_ios: 694010445543906933d732453a59da0a173ae33d wakelock_plus: 04623e3f525556020ebd4034310f20fe7fda8b49 -PODFILE CHECKSUM: 03b7eead4ee77b9e778179eeb0f3b5513617451c +PODFILE CHECKSUM: 7ce312f2beab01395db96f6969d90a447279cf45 COCOAPODS: 1.16.2 diff --git a/mobile/ios/Runner.xcodeproj/project.pbxproj b/mobile/ios/Runner.xcodeproj/project.pbxproj index 83c231d741..744ddc053b 100644 --- a/mobile/ios/Runner.xcodeproj/project.pbxproj +++ b/mobile/ios/Runner.xcodeproj/project.pbxproj @@ -261,9 +261,11 @@ 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; }; FAC6F88F2D287C890078CB2F = { CreatedOnToolsVersion = 16.0; + ProvisioningStyle = Automatic; }; }; }; @@ -541,12 +543,12 @@ CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 201; + CURRENT_PROJECT_VERSION = 205; CUSTOM_GROUP_ID = group.app.immich.share; DEVELOPMENT_TEAM = 2F67MQ8R79; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -685,12 +687,12 @@ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 201; + CURRENT_PROJECT_VERSION = 205; CUSTOM_GROUP_ID = group.app.immich.share; DEVELOPMENT_TEAM = 2F67MQ8R79; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -715,12 +717,12 @@ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 201; + CURRENT_PROJECT_VERSION = 205; CUSTOM_GROUP_ID = group.app.immich.share; DEVELOPMENT_TEAM = 2F67MQ8R79; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -748,7 +750,7 @@ CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 201; + CURRENT_PROJECT_VERSION = 205; CUSTOM_GROUP_ID = group.app.immich.share; DEVELOPMENT_TEAM = 2F67MQ8R79; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -769,6 +771,7 @@ MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.vdebug.ShareExtension; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -791,7 +794,7 @@ CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 201; + CURRENT_PROJECT_VERSION = 205; CUSTOM_GROUP_ID = group.app.immich.share; DEVELOPMENT_TEAM = 2F67MQ8R79; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -811,6 +814,7 @@ MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.ShareExtension; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; @@ -831,7 +835,7 @@ CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 201; + CURRENT_PROJECT_VERSION = 205; CUSTOM_GROUP_ID = group.app.immich.share; DEVELOPMENT_TEAM = 2F67MQ8R79; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -851,6 +855,7 @@ MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = app.alextran.immich.profile.ShareExtension; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; diff --git a/mobile/ios/Runner/Info.plist b/mobile/ios/Runner/Info.plist index bad1ea42f2..38394f0f1b 100644 --- a/mobile/ios/Runner/Info.plist +++ b/mobile/ios/Runner/Info.plist @@ -78,7 +78,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.131.3 + 1.132.3 CFBundleSignature ???? CFBundleURLTypes @@ -93,7 +93,7 @@ CFBundleVersion - 201 + 205 FLTEnableImpeller ITSAppUsesNonExemptEncryption diff --git a/mobile/ios/fastlane/Fastfile b/mobile/ios/fastlane/Fastfile index 4853e9be43..3306fef1e2 100644 --- a/mobile/ios/fastlane/Fastfile +++ b/mobile/ios/fastlane/Fastfile @@ -18,8 +18,11 @@ default_platform(:ios) platform :ios do desc "iOS Release" lane :release do + enable_automatic_code_signing( + path: "./Runner.xcodeproj", + ) increment_version_number( - version_number: "1.131.3" + version_number: "1.132.3" ) increment_build_number( build_number: latest_testflight_build_number + 1, diff --git a/mobile/lib/domain/interfaces/album_media.interface.dart b/mobile/lib/domain/interfaces/album_media.interface.dart index 6257de9f17..feb3adeb25 100644 --- a/mobile/lib/domain/interfaces/album_media.interface.dart +++ b/mobile/lib/domain/interfaces/album_media.interface.dart @@ -1,4 +1,4 @@ -import 'package:immich_mobile/domain/models/asset/asset.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/local_album.model.dart'; abstract interface class IAlbumMediaRepository { diff --git a/mobile/lib/domain/interfaces/local_album.interface.dart b/mobile/lib/domain/interfaces/local_album.interface.dart index 85fff14893..611527d08a 100644 --- a/mobile/lib/domain/interfaces/local_album.interface.dart +++ b/mobile/lib/domain/interfaces/local_album.interface.dart @@ -1,9 +1,9 @@ import 'package:immich_mobile/domain/interfaces/db.interface.dart'; -import 'package:immich_mobile/domain/models/asset/asset.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/local_album.model.dart'; abstract interface class ILocalAlbumRepository implements IDatabaseRepository { - Future insert(LocalAlbum localAlbum, Iterable assets); + Future insert(LocalAlbum album, Iterable assets); Future addAssets(String albumId, Iterable assets); @@ -11,7 +11,7 @@ abstract interface class ILocalAlbumRepository implements IDatabaseRepository { Future> getAssetsForAlbum(String albumId); - Future update(LocalAlbum localAlbum); + Future update(LocalAlbum album); Future delete(String albumId); diff --git a/mobile/lib/domain/interfaces/local_asset.interface.dart b/mobile/lib/domain/interfaces/local_asset.interface.dart index 7cf05a55be..2f9fbd143f 100644 --- a/mobile/lib/domain/interfaces/local_asset.interface.dart +++ b/mobile/lib/domain/interfaces/local_asset.interface.dart @@ -1,5 +1,5 @@ import 'package:immich_mobile/domain/interfaces/db.interface.dart'; -import 'package:immich_mobile/domain/models/asset/asset.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; abstract interface class ILocalAssetRepository implements IDatabaseRepository { Future get(String assetId); diff --git a/mobile/lib/domain/models/asset/asset.model.dart b/mobile/lib/domain/models/asset/asset.model.dart index 36f8ada253..211d24985f 100644 --- a/mobile/lib/domain/models/asset/asset.model.dart +++ b/mobile/lib/domain/models/asset/asset.model.dart @@ -1,64 +1,46 @@ -import 'package:immich_mobile/utils/nullable_value.dart'; +part of 'base_asset.model.dart'; -part 'local_asset.model.dart'; -part 'merged_asset.model.dart'; -part 'remote_asset.model.dart'; - -enum AssetType { - // do not change this order! - other, - image, - video, - audio, -} - -sealed class Asset { - final String name; - final String? checksum; - final AssetType type; - final DateTime createdAt; - final DateTime updatedAt; - final int? durationInSeconds; +class Asset extends BaseAsset { + final String id; + final String? localId; const Asset({ - required this.name, - required this.checksum, - required this.type, - required this.createdAt, - required this.updatedAt, - this.durationInSeconds, + required this.id, + this.localId, + required super.name, + required super.checksum, + required super.type, + required super.createdAt, + required super.updatedAt, + super.width, + super.height, + super.durationInSeconds, + super.isFavorite = false, }); @override String toString() { return '''Asset { - name: $name, - type: $type, - createdAt: $createdAt, - updatedAt: $updatedAt, - durationInSeconds: ${durationInSeconds ?? ""} -}'''; + id: $id, + name: $name, + type: $type, + createdAt: $createdAt, + updatedAt: $updatedAt, + width: ${width ?? ""}, + height: ${height ?? ""}, + durationInSeconds: ${durationInSeconds ?? ""}, + localId: ${localId ?? ""}, + isFavorite: $isFavorite, + }'''; } @override bool operator ==(Object other) { + if (other is! Asset) return false; if (identical(this, other)) return true; - if (other is Asset) { - return name == other.name && - type == other.type && - createdAt == other.createdAt && - updatedAt == other.updatedAt && - durationInSeconds == other.durationInSeconds; - } - return false; + return super == other && id == other.id && localId == other.localId; } @override - int get hashCode { - return name.hashCode ^ - type.hashCode ^ - createdAt.hashCode ^ - updatedAt.hashCode ^ - durationInSeconds.hashCode; - } + int get hashCode => super.hashCode ^ id.hashCode ^ localId.hashCode; } diff --git a/mobile/lib/domain/models/asset/base_asset.model.dart b/mobile/lib/domain/models/asset/base_asset.model.dart new file mode 100644 index 0000000000..fb95437659 --- /dev/null +++ b/mobile/lib/domain/models/asset/base_asset.model.dart @@ -0,0 +1,76 @@ +part 'asset.model.dart'; +part 'local_asset.model.dart'; + +enum AssetType { + // do not change this order! + other, + image, + video, + audio, +} + +sealed class BaseAsset { + final String name; + final String? checksum; + final AssetType type; + final DateTime createdAt; + final DateTime updatedAt; + final int? width; + final int? height; + final int? durationInSeconds; + final bool isFavorite; + + const BaseAsset({ + required this.name, + required this.checksum, + required this.type, + required this.createdAt, + required this.updatedAt, + this.width, + this.height, + this.durationInSeconds, + this.isFavorite = false, + }); + + @override + String toString() { + return '''BaseAsset { + name: $name, + type: $type, + createdAt: $createdAt, + updatedAt: $updatedAt, + width: ${width ?? ""}, + height: ${height ?? ""}, + durationInSeconds: ${durationInSeconds ?? ""}, + isFavorite: $isFavorite, +}'''; + } + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + if (other is BaseAsset) { + return name == other.name && + type == other.type && + createdAt == other.createdAt && + updatedAt == other.updatedAt && + width == other.width && + height == other.height && + durationInSeconds == other.durationInSeconds && + isFavorite == other.isFavorite; + } + return false; + } + + @override + int get hashCode { + return name.hashCode ^ + type.hashCode ^ + createdAt.hashCode ^ + updatedAt.hashCode ^ + width.hashCode ^ + height.hashCode ^ + durationInSeconds.hashCode ^ + isFavorite.hashCode; + } +} diff --git a/mobile/lib/domain/models/asset/local_asset.model.dart b/mobile/lib/domain/models/asset/local_asset.model.dart index 28f3d8c9fb..25e617d8ed 100644 --- a/mobile/lib/domain/models/asset/local_asset.model.dart +++ b/mobile/lib/domain/models/asset/local_asset.model.dart @@ -1,33 +1,36 @@ -part of 'asset.model.dart'; +part of 'base_asset.model.dart'; -class LocalAsset extends Asset { - final String localId; - final int? width; - final int? height; +class LocalAsset extends BaseAsset { + final String id; + final String? remoteId; const LocalAsset({ - required this.localId, + required this.id, + this.remoteId, required super.name, super.checksum, required super.type, required super.createdAt, required super.updatedAt, - this.width, - this.height, + super.width, + super.height, super.durationInSeconds, + super.isFavorite = false, }); @override String toString() { return '''LocalAsset { - localId: $localId, + id: $id, name: $name, type: $type, createdAt: $createdAt, updatedAt: $updatedAt, width: ${width ?? ""}, height: ${height ?? ""}, - durationInSeconds: ${durationInSeconds ?? ""} + durationInSeconds: ${durationInSeconds ?? ""}, + remoteId: ${remoteId ?? ""} + isFavorite: $isFavorite, }'''; } @@ -35,38 +38,37 @@ class LocalAsset extends Asset { bool operator ==(Object other) { if (other is! LocalAsset) return false; if (identical(this, other)) return true; - return super == other && - localId == other.localId && - width == other.width && - height == other.height; + return super == other && id == other.id && remoteId == other.remoteId; } @override - int get hashCode { - return super.hashCode ^ localId.hashCode; - } + int get hashCode => super.hashCode ^ id.hashCode ^ remoteId.hashCode; LocalAsset copyWith({ - String? localId, + String? id, + String? remoteId, String? name, String? checksum, AssetType? type, DateTime? createdAt, DateTime? updatedAt, - NullableValue width = const NullableValue.absent(), - NullableValue height = const NullableValue.absent(), - NullableValue durationInSeconds = const NullableValue.absent(), + int? width, + int? height, + int? durationInSeconds, + bool? isFavorite, }) { return LocalAsset( - localId: localId ?? this.localId, + id: id ?? this.id, + remoteId: remoteId ?? this.remoteId, name: name ?? this.name, checksum: checksum ?? this.checksum, type: type ?? this.type, createdAt: createdAt ?? this.createdAt, updatedAt: updatedAt ?? this.updatedAt, - width: width.getOrDefault(this.width), - height: height.getOrDefault(this.height), - durationInSeconds: durationInSeconds.getOrDefault(this.durationInSeconds), + width: width ?? this.width, + height: height ?? this.height, + durationInSeconds: durationInSeconds ?? this.durationInSeconds, + isFavorite: isFavorite ?? this.isFavorite, ); } } diff --git a/mobile/lib/domain/models/asset/merged_asset.model.dart b/mobile/lib/domain/models/asset/merged_asset.model.dart deleted file mode 100644 index e02cdfcb89..0000000000 --- a/mobile/lib/domain/models/asset/merged_asset.model.dart +++ /dev/null @@ -1,44 +0,0 @@ -part of 'asset.model.dart'; - -class MergedAsset extends Asset { - final String remoteId; - final String localId; - - const MergedAsset({ - required this.remoteId, - required this.localId, - required super.name, - required super.checksum, - required super.type, - required super.createdAt, - required super.updatedAt, - super.durationInSeconds, - }); - - @override - String toString() { - return '''MergedAsset { - remoteId: $remoteId, - localId: $localId, - name: $name, - type: $type, - createdAt: $createdAt, - updatedAt: $updatedAt, - durationInSeconds: ${durationInSeconds ?? ""} - }'''; - } - - @override - bool operator ==(Object other) { - if (other is! MergedAsset) return false; - if (identical(this, other)) return true; - return super == other && - remoteId == other.remoteId && - localId == other.localId; - } - - @override - int get hashCode { - return super.hashCode ^ remoteId.hashCode ^ localId.hashCode; - } -} diff --git a/mobile/lib/domain/models/asset/remote_asset.model.dart b/mobile/lib/domain/models/asset/remote_asset.model.dart deleted file mode 100644 index 30c1fa2158..0000000000 --- a/mobile/lib/domain/models/asset/remote_asset.model.dart +++ /dev/null @@ -1,65 +0,0 @@ -part of 'asset.model.dart'; - -class RemoteAsset extends Asset { - final String remoteId; - final bool isFavorite; - final String ownerId; - final DateTime localDateTime; - final String? thumbhash; - final DateTime? deletedAt; - - const RemoteAsset({ - required this.remoteId, - required this.ownerId, - required super.name, - required super.checksum, - required super.type, - required this.isFavorite, - required this.localDateTime, - required super.createdAt, - required super.updatedAt, - this.deletedAt, - this.thumbhash, - super.durationInSeconds, - }); - - @override - String toString() { - return '''RemoteAsset { - remoteId: $remoteId, - ownerId: $ownerId, - name: $name, - type: $type, - isFavorite: $isFavorite, - createdAt: $createdAt, - updatedAt: $updatedAt, - localDateTime: $localDateTime, - deletedAt: ${deletedAt ?? ""}, - durationInSeconds: ${durationInSeconds ?? ""}, - }'''; - } - - @override - bool operator ==(Object other) { - if (other is! RemoteAsset) return false; - if (identical(this, other)) return true; - return super == other && - remoteId == other.remoteId && - isFavorite == other.isFavorite && - ownerId == other.ownerId && - localDateTime == other.localDateTime && - deletedAt == other.deletedAt && - thumbhash == other.thumbhash; - } - - @override - int get hashCode { - return super.hashCode ^ - remoteId.hashCode ^ - isFavorite.hashCode ^ - ownerId.hashCode ^ - localDateTime.hashCode ^ - deletedAt.hashCode ^ - thumbhash.hashCode; - } -} diff --git a/mobile/lib/domain/models/local_album.model.dart b/mobile/lib/domain/models/local_album.model.dart index eb005ee43a..a33584d579 100644 --- a/mobile/lib/domain/models/local_album.model.dart +++ b/mobile/lib/domain/models/local_album.model.dart @@ -11,8 +11,6 @@ class LocalAlbum { final String name; final DateTime updatedAt; - /// Whether the album contains all photos (i.e, the virtual "Recent" album) - final bool isAll; final int assetCount; final String? thumbnailId; final BackupSelection backupSelection; @@ -24,7 +22,6 @@ class LocalAlbum { this.assetCount = 0, this.thumbnailId, this.backupSelection = BackupSelection.none, - this.isAll = false, }); LocalAlbum copyWith({ @@ -34,7 +31,6 @@ class LocalAlbum { int? assetCount, NullableValue thumbnailId = const NullableValue.absent(), BackupSelection? backupSelection, - bool? isAll, }) { return LocalAlbum( id: id ?? this.id, @@ -43,7 +39,6 @@ class LocalAlbum { assetCount: assetCount ?? this.assetCount, thumbnailId: thumbnailId.getOrDefault(this.thumbnailId), backupSelection: backupSelection ?? this.backupSelection, - isAll: isAll ?? this.isAll, ); } @@ -56,7 +51,6 @@ class LocalAlbum { other.name == name && other.updatedAt == updatedAt && other.assetCount == assetCount && - other.isAll == isAll && other.thumbnailId == thumbnailId && other.backupSelection == backupSelection; } @@ -67,7 +61,6 @@ class LocalAlbum { name.hashCode ^ updatedAt.hashCode ^ assetCount.hashCode ^ - isAll.hashCode ^ thumbnailId.hashCode ^ backupSelection.hashCode; } @@ -81,7 +74,6 @@ updatedAt: $updatedAt, assetCount: $assetCount, thumbnailId: ${thumbnailId ?? ''}, backupSelection: $backupSelection, -isAll: $isAll }'''; } } diff --git a/mobile/lib/domain/services/device_sync.service.dart b/mobile/lib/domain/services/device_sync.service.dart index 09f71fe76e..4a7b1c7c07 100644 --- a/mobile/lib/domain/services/device_sync.service.dart +++ b/mobile/lib/domain/services/device_sync.service.dart @@ -5,7 +5,7 @@ import 'package:flutter/widgets.dart'; import 'package:immich_mobile/domain/interfaces/album_media.interface.dart'; import 'package:immich_mobile/domain/interfaces/local_album.interface.dart'; import 'package:immich_mobile/domain/interfaces/local_asset.interface.dart'; -import 'package:immich_mobile/domain/models/asset/asset.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/local_album.model.dart'; import 'package:immich_mobile/utils/diff.dart'; import 'package:immich_mobile/utils/nullable_value.dart'; @@ -34,6 +34,7 @@ class DeviceSyncService { // and not the albums. final deviceAlbums = (await _albumMediaRepository.getAll()).sortedBy((a) => a.id); + final dbAlbums = await _localAlbumRepository.getAll(sortBy: SortLocalAlbumsBy.id); @@ -64,7 +65,7 @@ class DeviceSyncService { final album = deviceAlbum.copyWith( // The below assumes the list is already sorted by createdDate from the filter - thumbnailId: NullableValue.valueOrEmpty(assets.firstOrNull?.localId), + thumbnailId: NullableValue.valueOrEmpty(assets.firstOrNull?.id), ); await _localAlbumRepository.insert(album, assets); @@ -100,7 +101,7 @@ class DeviceSyncService { return false; } - _log.fine("Device album ${dbAlbum.name} has changed. Syncing..."); + _log.info("Device album ${dbAlbum.name} has changed. Syncing..."); // Faster path - only new assets added if (await checkAddition(dbAlbum, deviceAlbum)) { @@ -157,13 +158,13 @@ class DeviceSyncService { String? thumbnailId = dbAlbum.thumbnailId; if (thumbnailId == null || newAssets.isNotEmpty) { if (thumbnailId == null) { - thumbnailId = newAssets.firstOrNull?.localId; + thumbnailId = newAssets.firstOrNull?.id; } else if (newAssets.isNotEmpty) { // The below assumes the list is already sorted by createdDate from the filter final oldThumbAsset = await _localAssetRepository.get(thumbnailId); if (oldThumbAsset.createdAt .isBefore(newAssets.firstOrNull!.createdAt)) { - thumbnailId = newAssets.firstOrNull?.localId; + thumbnailId = newAssets.firstOrNull?.id; } } } @@ -205,14 +206,14 @@ class DeviceSyncService { thumbnailId: const NullableValue.empty(), backupSelection: dbAlbum.backupSelection, ), - assetIdsToDelete: assetsInDb.map((a) => a.localId), + assetIdsToDelete: assetsInDb.map((a) => a.id), ); return true; } // The below assumes the list is already sorted by createdDate from the filter String? thumbnailId = assetsInDevice.isNotEmpty - ? assetsInDevice.firstOrNull?.localId + ? assetsInDevice.firstOrNull?.id : dbAlbum.thumbnailId; final updatedDeviceAlbum = deviceAlbum.copyWith( @@ -228,8 +229,8 @@ class DeviceSyncService { return true; } - assert(assetsInDb.isSortedBy((a) => a.localId)); - assetsInDevice.sort((a, b) => a.localId.compareTo(b.localId)); + assert(assetsInDb.isSortedBy((a) => a.id)); + assetsInDevice.sort((a, b) => a.id.compareTo(b.id)); final assetsToUpsert = []; final assetsToDelete = []; @@ -237,7 +238,7 @@ class DeviceSyncService { diffSortedListsSync( assetsInDb, assetsInDevice, - compare: (a, b) => a.localId.compareTo(b.localId), + compare: (a, b) => a.id.compareTo(b.id), both: (dbAsset, deviceAsset) { // Custom comparison to check if the asset has been modified without // comparing the checksum @@ -247,7 +248,7 @@ class DeviceSyncService { } return false; }, - onlyFirst: (dbAsset) => assetsToDelete.add(dbAsset.localId), + onlyFirst: (dbAsset) => assetsToDelete.add(dbAsset.id), onlySecond: (deviceAsset) => assetsToUpsert.add(deviceAsset), ); diff --git a/mobile/lib/infrastructure/entities/local_album.entity.dart b/mobile/lib/infrastructure/entities/local_album.entity.dart index 5d5f766fd4..4eff2a1154 100644 --- a/mobile/lib/infrastructure/entities/local_album.entity.dart +++ b/mobile/lib/infrastructure/entities/local_album.entity.dart @@ -10,12 +10,10 @@ class LocalAlbumEntity extends Table with DriftDefaultsMixin { TextColumn get id => text()(); TextColumn get name => text()(); DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)(); - IntColumn get assetCount => integer().withDefault(const Constant(0))(); TextColumn get thumbnailId => text() .nullable() .references(LocalAssetEntity, #localId, onDelete: KeyAction.setNull)(); IntColumn get backupSelection => intEnum()(); - BoolColumn get isAll => boolean().withDefault(const Constant(false))(); @override Set get primaryKey => {id}; @@ -30,7 +28,6 @@ extension LocalAlbumEntityX on LocalAlbumEntityData { assetCount: assetCount, thumbnailId: thumbnailId, backupSelection: backupSelection, - isAll: isAll, ); } } diff --git a/mobile/lib/infrastructure/entities/local_album.entity.drift.dart b/mobile/lib/infrastructure/entities/local_album.entity.drift.dart index 19ada47e87..ee6c5b8c61 100644 --- a/mobile/lib/infrastructure/entities/local_album.entity.drift.dart +++ b/mobile/lib/infrastructure/entities/local_album.entity.drift.dart @@ -16,20 +16,16 @@ typedef $$LocalAlbumEntityTableCreateCompanionBuilder required String id, required String name, i0.Value updatedAt, - i0.Value assetCount, i0.Value thumbnailId, required i2.BackupSelection backupSelection, - i0.Value isAll, }); typedef $$LocalAlbumEntityTableUpdateCompanionBuilder = i1.LocalAlbumEntityCompanion Function({ i0.Value id, i0.Value name, i0.Value updatedAt, - i0.Value assetCount, i0.Value thumbnailId, i0.Value backupSelection, - i0.Value isAll, }); final class $$LocalAlbumEntityTableReferences extends i0.BaseReferences< @@ -82,17 +78,11 @@ class $$LocalAlbumEntityTableFilterComposer i0.ColumnFilters get updatedAt => $composableBuilder( column: $table.updatedAt, builder: (column) => i0.ColumnFilters(column)); - i0.ColumnFilters get assetCount => $composableBuilder( - column: $table.assetCount, builder: (column) => i0.ColumnFilters(column)); - i0.ColumnWithTypeConverterFilters get backupSelection => $composableBuilder( column: $table.backupSelection, builder: (column) => i0.ColumnWithTypeConverterFilters(column)); - i0.ColumnFilters get isAll => $composableBuilder( - column: $table.isAll, builder: (column) => i0.ColumnFilters(column)); - i5.$$LocalAssetEntityTableFilterComposer get thumbnailId { final i5.$$LocalAssetEntityTableFilterComposer composer = $composerBuilder( composer: this, @@ -135,17 +125,10 @@ class $$LocalAlbumEntityTableOrderingComposer column: $table.updatedAt, builder: (column) => i0.ColumnOrderings(column)); - i0.ColumnOrderings get assetCount => $composableBuilder( - column: $table.assetCount, - builder: (column) => i0.ColumnOrderings(column)); - i0.ColumnOrderings get backupSelection => $composableBuilder( column: $table.backupSelection, builder: (column) => i0.ColumnOrderings(column)); - i0.ColumnOrderings get isAll => $composableBuilder( - column: $table.isAll, builder: (column) => i0.ColumnOrderings(column)); - i5.$$LocalAssetEntityTableOrderingComposer get thumbnailId { final i5.$$LocalAssetEntityTableOrderingComposer composer = $composerBuilder( @@ -189,16 +172,10 @@ class $$LocalAlbumEntityTableAnnotationComposer i0.GeneratedColumn get updatedAt => $composableBuilder(column: $table.updatedAt, builder: (column) => column); - i0.GeneratedColumn get assetCount => $composableBuilder( - column: $table.assetCount, builder: (column) => column); - i0.GeneratedColumnWithTypeConverter get backupSelection => $composableBuilder( column: $table.backupSelection, builder: (column) => column); - i0.GeneratedColumn get isAll => - $composableBuilder(column: $table.isAll, builder: (column) => column); - i5.$$LocalAssetEntityTableAnnotationComposer get thumbnailId { final i5.$$LocalAssetEntityTableAnnotationComposer composer = $composerBuilder( @@ -252,38 +229,30 @@ class $$LocalAlbumEntityTableTableManager extends i0.RootTableManager< i0.Value id = const i0.Value.absent(), i0.Value name = const i0.Value.absent(), i0.Value updatedAt = const i0.Value.absent(), - i0.Value assetCount = const i0.Value.absent(), i0.Value thumbnailId = const i0.Value.absent(), i0.Value backupSelection = const i0.Value.absent(), - i0.Value isAll = const i0.Value.absent(), }) => i1.LocalAlbumEntityCompanion( id: id, name: name, updatedAt: updatedAt, - assetCount: assetCount, thumbnailId: thumbnailId, backupSelection: backupSelection, - isAll: isAll, ), createCompanionCallback: ({ required String id, required String name, i0.Value updatedAt = const i0.Value.absent(), - i0.Value assetCount = const i0.Value.absent(), i0.Value thumbnailId = const i0.Value.absent(), required i2.BackupSelection backupSelection, - i0.Value isAll = const i0.Value.absent(), }) => i1.LocalAlbumEntityCompanion.insert( id: id, name: name, updatedAt: updatedAt, - assetCount: assetCount, thumbnailId: thumbnailId, backupSelection: backupSelection, - isAll: isAll, ), withReferenceMapper: (p0) => p0 .map((e) => ( @@ -368,14 +337,6 @@ class $LocalAlbumEntityTable extends i3.LocalAlbumEntity type: i0.DriftSqlType.dateTime, requiredDuringInsert: false, defaultValue: i4.currentDateAndTime); - static const i0.VerificationMeta _assetCountMeta = - const i0.VerificationMeta('assetCount'); - @override - late final i0.GeneratedColumn assetCount = i0.GeneratedColumn( - 'asset_count', aliasedName, false, - type: i0.DriftSqlType.int, - requiredDuringInsert: false, - defaultValue: const i4.Constant(0)); static const i0.VerificationMeta _thumbnailIdMeta = const i0.VerificationMeta('thumbnailId'); @override @@ -392,19 +353,9 @@ class $LocalAlbumEntityTable extends i3.LocalAlbumEntity type: i0.DriftSqlType.int, requiredDuringInsert: true) .withConverter( i1.$LocalAlbumEntityTable.$converterbackupSelection); - static const i0.VerificationMeta _isAllMeta = - const i0.VerificationMeta('isAll'); - @override - late final i0.GeneratedColumn isAll = i0.GeneratedColumn( - 'is_all', aliasedName, false, - type: i0.DriftSqlType.bool, - requiredDuringInsert: false, - defaultConstraints: - i0.GeneratedColumn.constraintIsAlways('CHECK ("is_all" IN (0, 1))'), - defaultValue: const i4.Constant(false)); @override List get $columns => - [id, name, updatedAt, assetCount, thumbnailId, backupSelection, isAll]; + [id, name, updatedAt, thumbnailId, backupSelection]; @override String get aliasedName => _alias ?? actualTableName; @override @@ -431,22 +382,12 @@ class $LocalAlbumEntityTable extends i3.LocalAlbumEntity context.handle(_updatedAtMeta, updatedAt.isAcceptableOrUnknown(data['updated_at']!, _updatedAtMeta)); } - if (data.containsKey('asset_count')) { - context.handle( - _assetCountMeta, - assetCount.isAcceptableOrUnknown( - data['asset_count']!, _assetCountMeta)); - } if (data.containsKey('thumbnail_id')) { context.handle( _thumbnailIdMeta, thumbnailId.isAcceptableOrUnknown( data['thumbnail_id']!, _thumbnailIdMeta)); } - if (data.containsKey('is_all')) { - context.handle( - _isAllMeta, isAll.isAcceptableOrUnknown(data['is_all']!, _isAllMeta)); - } return context; } @@ -463,15 +404,11 @@ class $LocalAlbumEntityTable extends i3.LocalAlbumEntity .read(i0.DriftSqlType.string, data['${effectivePrefix}name'])!, updatedAt: attachedDatabase.typeMapping.read( i0.DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, - assetCount: attachedDatabase.typeMapping - .read(i0.DriftSqlType.int, data['${effectivePrefix}asset_count'])!, thumbnailId: attachedDatabase.typeMapping .read(i0.DriftSqlType.string, data['${effectivePrefix}thumbnail_id']), backupSelection: i1.$LocalAlbumEntityTable.$converterbackupSelection .fromSql(attachedDatabase.typeMapping.read(i0.DriftSqlType.int, data['${effectivePrefix}backup_selection'])!), - isAll: attachedDatabase.typeMapping - .read(i0.DriftSqlType.bool, data['${effectivePrefix}is_all'])!, ); } @@ -495,25 +432,20 @@ class LocalAlbumEntityData extends i0.DataClass final String id; final String name; final DateTime updatedAt; - final int assetCount; final String? thumbnailId; final i2.BackupSelection backupSelection; - final bool isAll; const LocalAlbumEntityData( {required this.id, required this.name, required this.updatedAt, - required this.assetCount, this.thumbnailId, - required this.backupSelection, - required this.isAll}); + required this.backupSelection}); @override Map toColumns(bool nullToAbsent) { final map = {}; map['id'] = i0.Variable(id); map['name'] = i0.Variable(name); map['updated_at'] = i0.Variable(updatedAt); - map['asset_count'] = i0.Variable(assetCount); if (!nullToAbsent || thumbnailId != null) { map['thumbnail_id'] = i0.Variable(thumbnailId); } @@ -522,7 +454,6 @@ class LocalAlbumEntityData extends i0.DataClass .$LocalAlbumEntityTable.$converterbackupSelection .toSql(backupSelection)); } - map['is_all'] = i0.Variable(isAll); return map; } @@ -533,11 +464,9 @@ class LocalAlbumEntityData extends i0.DataClass id: serializer.fromJson(json['id']), name: serializer.fromJson(json['name']), updatedAt: serializer.fromJson(json['updatedAt']), - assetCount: serializer.fromJson(json['assetCount']), thumbnailId: serializer.fromJson(json['thumbnailId']), backupSelection: i1.$LocalAlbumEntityTable.$converterbackupSelection .fromJson(serializer.fromJson(json['backupSelection'])), - isAll: serializer.fromJson(json['isAll']), ); } @override @@ -547,12 +476,10 @@ class LocalAlbumEntityData extends i0.DataClass 'id': serializer.toJson(id), 'name': serializer.toJson(name), 'updatedAt': serializer.toJson(updatedAt), - 'assetCount': serializer.toJson(assetCount), 'thumbnailId': serializer.toJson(thumbnailId), 'backupSelection': serializer.toJson(i1 .$LocalAlbumEntityTable.$converterbackupSelection .toJson(backupSelection)), - 'isAll': serializer.toJson(isAll), }; } @@ -560,32 +487,25 @@ class LocalAlbumEntityData extends i0.DataClass {String? id, String? name, DateTime? updatedAt, - int? assetCount, i0.Value thumbnailId = const i0.Value.absent(), - i2.BackupSelection? backupSelection, - bool? isAll}) => + i2.BackupSelection? backupSelection}) => i1.LocalAlbumEntityData( id: id ?? this.id, name: name ?? this.name, updatedAt: updatedAt ?? this.updatedAt, - assetCount: assetCount ?? this.assetCount, thumbnailId: thumbnailId.present ? thumbnailId.value : this.thumbnailId, backupSelection: backupSelection ?? this.backupSelection, - isAll: isAll ?? this.isAll, ); LocalAlbumEntityData copyWithCompanion(i1.LocalAlbumEntityCompanion data) { return LocalAlbumEntityData( id: data.id.present ? data.id.value : this.id, name: data.name.present ? data.name.value : this.name, updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, - assetCount: - data.assetCount.present ? data.assetCount.value : this.assetCount, thumbnailId: data.thumbnailId.present ? data.thumbnailId.value : this.thumbnailId, backupSelection: data.backupSelection.present ? data.backupSelection.value : this.backupSelection, - isAll: data.isAll.present ? data.isAll.value : this.isAll, ); } @@ -595,17 +515,15 @@ class LocalAlbumEntityData extends i0.DataClass ..write('id: $id, ') ..write('name: $name, ') ..write('updatedAt: $updatedAt, ') - ..write('assetCount: $assetCount, ') ..write('thumbnailId: $thumbnailId, ') - ..write('backupSelection: $backupSelection, ') - ..write('isAll: $isAll') + ..write('backupSelection: $backupSelection') ..write(')')) .toString(); } @override - int get hashCode => Object.hash( - id, name, updatedAt, assetCount, thumbnailId, backupSelection, isAll); + int get hashCode => + Object.hash(id, name, updatedAt, thumbnailId, backupSelection); @override bool operator ==(Object other) => identical(this, other) || @@ -613,10 +531,8 @@ class LocalAlbumEntityData extends i0.DataClass other.id == this.id && other.name == this.name && other.updatedAt == this.updatedAt && - other.assetCount == this.assetCount && other.thumbnailId == this.thumbnailId && - other.backupSelection == this.backupSelection && - other.isAll == this.isAll); + other.backupSelection == this.backupSelection); } class LocalAlbumEntityCompanion @@ -624,27 +540,21 @@ class LocalAlbumEntityCompanion final i0.Value id; final i0.Value name; final i0.Value updatedAt; - final i0.Value assetCount; final i0.Value thumbnailId; final i0.Value backupSelection; - final i0.Value isAll; const LocalAlbumEntityCompanion({ this.id = const i0.Value.absent(), this.name = const i0.Value.absent(), this.updatedAt = const i0.Value.absent(), - this.assetCount = const i0.Value.absent(), this.thumbnailId = const i0.Value.absent(), this.backupSelection = const i0.Value.absent(), - this.isAll = const i0.Value.absent(), }); LocalAlbumEntityCompanion.insert({ required String id, required String name, this.updatedAt = const i0.Value.absent(), - this.assetCount = const i0.Value.absent(), this.thumbnailId = const i0.Value.absent(), required i2.BackupSelection backupSelection, - this.isAll = const i0.Value.absent(), }) : id = i0.Value(id), name = i0.Value(name), backupSelection = i0.Value(backupSelection); @@ -652,19 +562,15 @@ class LocalAlbumEntityCompanion i0.Expression? id, i0.Expression? name, i0.Expression? updatedAt, - i0.Expression? assetCount, i0.Expression? thumbnailId, i0.Expression? backupSelection, - i0.Expression? isAll, }) { return i0.RawValuesInsertable({ if (id != null) 'id': id, if (name != null) 'name': name, if (updatedAt != null) 'updated_at': updatedAt, - if (assetCount != null) 'asset_count': assetCount, if (thumbnailId != null) 'thumbnail_id': thumbnailId, if (backupSelection != null) 'backup_selection': backupSelection, - if (isAll != null) 'is_all': isAll, }); } @@ -672,18 +578,14 @@ class LocalAlbumEntityCompanion {i0.Value? id, i0.Value? name, i0.Value? updatedAt, - i0.Value? assetCount, i0.Value? thumbnailId, - i0.Value? backupSelection, - i0.Value? isAll}) { + i0.Value? backupSelection}) { return i1.LocalAlbumEntityCompanion( id: id ?? this.id, name: name ?? this.name, updatedAt: updatedAt ?? this.updatedAt, - assetCount: assetCount ?? this.assetCount, thumbnailId: thumbnailId ?? this.thumbnailId, backupSelection: backupSelection ?? this.backupSelection, - isAll: isAll ?? this.isAll, ); } @@ -699,9 +601,6 @@ class LocalAlbumEntityCompanion if (updatedAt.present) { map['updated_at'] = i0.Variable(updatedAt.value); } - if (assetCount.present) { - map['asset_count'] = i0.Variable(assetCount.value); - } if (thumbnailId.present) { map['thumbnail_id'] = i0.Variable(thumbnailId.value); } @@ -710,9 +609,6 @@ class LocalAlbumEntityCompanion .$LocalAlbumEntityTable.$converterbackupSelection .toSql(backupSelection.value)); } - if (isAll.present) { - map['is_all'] = i0.Variable(isAll.value); - } return map; } @@ -722,10 +618,8 @@ class LocalAlbumEntityCompanion ..write('id: $id, ') ..write('name: $name, ') ..write('updatedAt: $updatedAt, ') - ..write('assetCount: $assetCount, ') ..write('thumbnailId: $thumbnailId, ') - ..write('backupSelection: $backupSelection, ') - ..write('isAll: $isAll') + ..write('backupSelection: $backupSelection') ..write(')')) .toString(); } diff --git a/mobile/lib/infrastructure/entities/local_asset.entity.dart b/mobile/lib/infrastructure/entities/local_asset.entity.dart index 92ff3f2c62..2127ab1713 100644 --- a/mobile/lib/infrastructure/entities/local_asset.entity.dart +++ b/mobile/lib/infrastructure/entities/local_asset.entity.dart @@ -1,5 +1,5 @@ import 'package:drift/drift.dart'; -import 'package:immich_mobile/domain/models/asset/asset.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart'; import 'package:immich_mobile/infrastructure/utils/asset.mixin.dart'; import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart'; @@ -12,9 +12,8 @@ class LocalAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin { TextColumn get checksum => text().nullable()(); - IntColumn get width => integer().nullable()(); - - IntColumn get height => integer().nullable()(); + // Only used during backup to mirror the favorite status of the asset in the server + BoolColumn get isFavorite => boolean().withDefault(const Constant(false))(); @override Set get primaryKey => {localId}; @@ -23,15 +22,14 @@ class LocalAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin { extension LocalAssetEntityX on LocalAssetEntityData { LocalAsset toDto() { return LocalAsset( - localId: localId, + id: localId, name: name, checksum: checksum, type: type, createdAt: createdAt, updatedAt: updatedAt, - width: width, - height: height, durationInSeconds: durationInSeconds, + isFavorite: isFavorite, ); } } diff --git a/mobile/lib/infrastructure/entities/local_asset.entity.drift.dart b/mobile/lib/infrastructure/entities/local_asset.entity.drift.dart index d8635097b1..e6a567d033 100644 --- a/mobile/lib/infrastructure/entities/local_asset.entity.drift.dart +++ b/mobile/lib/infrastructure/entities/local_asset.entity.drift.dart @@ -3,7 +3,7 @@ import 'package:drift/drift.dart' as i0; import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart' as i1; -import 'package:immich_mobile/domain/models/asset/asset.model.dart' as i2; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart' as i2; import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart' as i3; import 'package:drift/src/runtime/query_builder/query_builder.dart' as i4; @@ -17,8 +17,7 @@ typedef $$LocalAssetEntityTableCreateCompanionBuilder i0.Value durationInSeconds, required String localId, i0.Value checksum, - i0.Value width, - i0.Value height, + i0.Value isFavorite, }); typedef $$LocalAssetEntityTableUpdateCompanionBuilder = i1.LocalAssetEntityCompanion Function({ @@ -29,8 +28,7 @@ typedef $$LocalAssetEntityTableUpdateCompanionBuilder i0.Value durationInSeconds, i0.Value localId, i0.Value checksum, - i0.Value width, - i0.Value height, + i0.Value isFavorite, }); class $$LocalAssetEntityTableFilterComposer @@ -66,11 +64,8 @@ class $$LocalAssetEntityTableFilterComposer i0.ColumnFilters get checksum => $composableBuilder( column: $table.checksum, builder: (column) => i0.ColumnFilters(column)); - i0.ColumnFilters get width => $composableBuilder( - column: $table.width, builder: (column) => i0.ColumnFilters(column)); - - i0.ColumnFilters get height => $composableBuilder( - column: $table.height, builder: (column) => i0.ColumnFilters(column)); + i0.ColumnFilters get isFavorite => $composableBuilder( + column: $table.isFavorite, builder: (column) => i0.ColumnFilters(column)); } class $$LocalAssetEntityTableOrderingComposer @@ -106,11 +101,9 @@ class $$LocalAssetEntityTableOrderingComposer i0.ColumnOrderings get checksum => $composableBuilder( column: $table.checksum, builder: (column) => i0.ColumnOrderings(column)); - i0.ColumnOrderings get width => $composableBuilder( - column: $table.width, builder: (column) => i0.ColumnOrderings(column)); - - i0.ColumnOrderings get height => $composableBuilder( - column: $table.height, builder: (column) => i0.ColumnOrderings(column)); + i0.ColumnOrderings get isFavorite => $composableBuilder( + column: $table.isFavorite, + builder: (column) => i0.ColumnOrderings(column)); } class $$LocalAssetEntityTableAnnotationComposer @@ -143,11 +136,8 @@ class $$LocalAssetEntityTableAnnotationComposer i0.GeneratedColumn get checksum => $composableBuilder(column: $table.checksum, builder: (column) => column); - i0.GeneratedColumn get width => - $composableBuilder(column: $table.width, builder: (column) => column); - - i0.GeneratedColumn get height => - $composableBuilder(column: $table.height, builder: (column) => column); + i0.GeneratedColumn get isFavorite => $composableBuilder( + column: $table.isFavorite, builder: (column) => column); } class $$LocalAssetEntityTableTableManager extends i0.RootTableManager< @@ -186,8 +176,7 @@ class $$LocalAssetEntityTableTableManager extends i0.RootTableManager< i0.Value durationInSeconds = const i0.Value.absent(), i0.Value localId = const i0.Value.absent(), i0.Value checksum = const i0.Value.absent(), - i0.Value width = const i0.Value.absent(), - i0.Value height = const i0.Value.absent(), + i0.Value isFavorite = const i0.Value.absent(), }) => i1.LocalAssetEntityCompanion( name: name, @@ -197,8 +186,7 @@ class $$LocalAssetEntityTableTableManager extends i0.RootTableManager< durationInSeconds: durationInSeconds, localId: localId, checksum: checksum, - width: width, - height: height, + isFavorite: isFavorite, ), createCompanionCallback: ({ required String name, @@ -208,8 +196,7 @@ class $$LocalAssetEntityTableTableManager extends i0.RootTableManager< i0.Value durationInSeconds = const i0.Value.absent(), required String localId, i0.Value checksum = const i0.Value.absent(), - i0.Value width = const i0.Value.absent(), - i0.Value height = const i0.Value.absent(), + i0.Value isFavorite = const i0.Value.absent(), }) => i1.LocalAssetEntityCompanion.insert( name: name, @@ -219,8 +206,7 @@ class $$LocalAssetEntityTableTableManager extends i0.RootTableManager< durationInSeconds: durationInSeconds, localId: localId, checksum: checksum, - width: width, - height: height, + isFavorite: isFavorite, ), withReferenceMapper: (p0) => p0 .map((e) => (e.readTable(table), i0.BaseReferences(db, table, e))) @@ -300,18 +286,16 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity late final i0.GeneratedColumn checksum = i0.GeneratedColumn( 'checksum', aliasedName, true, type: i0.DriftSqlType.string, requiredDuringInsert: false); - static const i0.VerificationMeta _widthMeta = - const i0.VerificationMeta('width'); + static const i0.VerificationMeta _isFavoriteMeta = + const i0.VerificationMeta('isFavorite'); @override - late final i0.GeneratedColumn width = i0.GeneratedColumn( - 'width', aliasedName, true, - type: i0.DriftSqlType.int, requiredDuringInsert: false); - static const i0.VerificationMeta _heightMeta = - const i0.VerificationMeta('height'); - @override - late final i0.GeneratedColumn height = i0.GeneratedColumn( - 'height', aliasedName, true, - type: i0.DriftSqlType.int, requiredDuringInsert: false); + late final i0.GeneratedColumn isFavorite = i0.GeneratedColumn( + 'is_favorite', aliasedName, false, + type: i0.DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: i0.GeneratedColumn.constraintIsAlways( + 'CHECK ("is_favorite" IN (0, 1))'), + defaultValue: const i4.Constant(false)); @override List get $columns => [ name, @@ -321,8 +305,7 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity durationInSeconds, localId, checksum, - width, - height + isFavorite ]; @override String get aliasedName => _alias ?? actualTableName; @@ -365,13 +348,11 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity context.handle(_checksumMeta, checksum.isAcceptableOrUnknown(data['checksum']!, _checksumMeta)); } - if (data.containsKey('width')) { + if (data.containsKey('is_favorite')) { context.handle( - _widthMeta, width.isAcceptableOrUnknown(data['width']!, _widthMeta)); - } - if (data.containsKey('height')) { - context.handle(_heightMeta, - height.isAcceptableOrUnknown(data['height']!, _heightMeta)); + _isFavoriteMeta, + isFavorite.isAcceptableOrUnknown( + data['is_favorite']!, _isFavoriteMeta)); } return context; } @@ -398,10 +379,8 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity .read(i0.DriftSqlType.string, data['${effectivePrefix}local_id'])!, checksum: attachedDatabase.typeMapping .read(i0.DriftSqlType.string, data['${effectivePrefix}checksum']), - width: attachedDatabase.typeMapping - .read(i0.DriftSqlType.int, data['${effectivePrefix}width']), - height: attachedDatabase.typeMapping - .read(i0.DriftSqlType.int, data['${effectivePrefix}height']), + isFavorite: attachedDatabase.typeMapping + .read(i0.DriftSqlType.bool, data['${effectivePrefix}is_favorite'])!, ); } @@ -427,8 +406,7 @@ class LocalAssetEntityData extends i0.DataClass final int? durationInSeconds; final String localId; final String? checksum; - final int? width; - final int? height; + final bool isFavorite; const LocalAssetEntityData( {required this.name, required this.type, @@ -437,8 +415,7 @@ class LocalAssetEntityData extends i0.DataClass this.durationInSeconds, required this.localId, this.checksum, - this.width, - this.height}); + required this.isFavorite}); @override Map toColumns(bool nullToAbsent) { final map = {}; @@ -456,12 +433,7 @@ class LocalAssetEntityData extends i0.DataClass if (!nullToAbsent || checksum != null) { map['checksum'] = i0.Variable(checksum); } - if (!nullToAbsent || width != null) { - map['width'] = i0.Variable(width); - } - if (!nullToAbsent || height != null) { - map['height'] = i0.Variable(height); - } + map['is_favorite'] = i0.Variable(isFavorite); return map; } @@ -477,8 +449,7 @@ class LocalAssetEntityData extends i0.DataClass durationInSeconds: serializer.fromJson(json['durationInSeconds']), localId: serializer.fromJson(json['localId']), checksum: serializer.fromJson(json['checksum']), - width: serializer.fromJson(json['width']), - height: serializer.fromJson(json['height']), + isFavorite: serializer.fromJson(json['isFavorite']), ); } @override @@ -493,8 +464,7 @@ class LocalAssetEntityData extends i0.DataClass 'durationInSeconds': serializer.toJson(durationInSeconds), 'localId': serializer.toJson(localId), 'checksum': serializer.toJson(checksum), - 'width': serializer.toJson(width), - 'height': serializer.toJson(height), + 'isFavorite': serializer.toJson(isFavorite), }; } @@ -506,8 +476,7 @@ class LocalAssetEntityData extends i0.DataClass i0.Value durationInSeconds = const i0.Value.absent(), String? localId, i0.Value checksum = const i0.Value.absent(), - i0.Value width = const i0.Value.absent(), - i0.Value height = const i0.Value.absent()}) => + bool? isFavorite}) => i1.LocalAssetEntityData( name: name ?? this.name, type: type ?? this.type, @@ -518,8 +487,7 @@ class LocalAssetEntityData extends i0.DataClass : this.durationInSeconds, localId: localId ?? this.localId, checksum: checksum.present ? checksum.value : this.checksum, - width: width.present ? width.value : this.width, - height: height.present ? height.value : this.height, + isFavorite: isFavorite ?? this.isFavorite, ); LocalAssetEntityData copyWithCompanion(i1.LocalAssetEntityCompanion data) { return LocalAssetEntityData( @@ -532,8 +500,8 @@ class LocalAssetEntityData extends i0.DataClass : this.durationInSeconds, localId: data.localId.present ? data.localId.value : this.localId, checksum: data.checksum.present ? data.checksum.value : this.checksum, - width: data.width.present ? data.width.value : this.width, - height: data.height.present ? data.height.value : this.height, + isFavorite: + data.isFavorite.present ? data.isFavorite.value : this.isFavorite, ); } @@ -547,15 +515,14 @@ class LocalAssetEntityData extends i0.DataClass ..write('durationInSeconds: $durationInSeconds, ') ..write('localId: $localId, ') ..write('checksum: $checksum, ') - ..write('width: $width, ') - ..write('height: $height') + ..write('isFavorite: $isFavorite') ..write(')')) .toString(); } @override int get hashCode => Object.hash(name, type, createdAt, updatedAt, - durationInSeconds, localId, checksum, width, height); + durationInSeconds, localId, checksum, isFavorite); @override bool operator ==(Object other) => identical(this, other) || @@ -567,8 +534,7 @@ class LocalAssetEntityData extends i0.DataClass other.durationInSeconds == this.durationInSeconds && other.localId == this.localId && other.checksum == this.checksum && - other.width == this.width && - other.height == this.height); + other.isFavorite == this.isFavorite); } class LocalAssetEntityCompanion @@ -580,8 +546,7 @@ class LocalAssetEntityCompanion final i0.Value durationInSeconds; final i0.Value localId; final i0.Value checksum; - final i0.Value width; - final i0.Value height; + final i0.Value isFavorite; const LocalAssetEntityCompanion({ this.name = const i0.Value.absent(), this.type = const i0.Value.absent(), @@ -590,8 +555,7 @@ class LocalAssetEntityCompanion this.durationInSeconds = const i0.Value.absent(), this.localId = const i0.Value.absent(), this.checksum = const i0.Value.absent(), - this.width = const i0.Value.absent(), - this.height = const i0.Value.absent(), + this.isFavorite = const i0.Value.absent(), }); LocalAssetEntityCompanion.insert({ required String name, @@ -601,8 +565,7 @@ class LocalAssetEntityCompanion this.durationInSeconds = const i0.Value.absent(), required String localId, this.checksum = const i0.Value.absent(), - this.width = const i0.Value.absent(), - this.height = const i0.Value.absent(), + this.isFavorite = const i0.Value.absent(), }) : name = i0.Value(name), type = i0.Value(type), localId = i0.Value(localId); @@ -614,8 +577,7 @@ class LocalAssetEntityCompanion i0.Expression? durationInSeconds, i0.Expression? localId, i0.Expression? checksum, - i0.Expression? width, - i0.Expression? height, + i0.Expression? isFavorite, }) { return i0.RawValuesInsertable({ if (name != null) 'name': name, @@ -625,8 +587,7 @@ class LocalAssetEntityCompanion if (durationInSeconds != null) 'duration_in_seconds': durationInSeconds, if (localId != null) 'local_id': localId, if (checksum != null) 'checksum': checksum, - if (width != null) 'width': width, - if (height != null) 'height': height, + if (isFavorite != null) 'is_favorite': isFavorite, }); } @@ -638,8 +599,7 @@ class LocalAssetEntityCompanion i0.Value? durationInSeconds, i0.Value? localId, i0.Value? checksum, - i0.Value? width, - i0.Value? height}) { + i0.Value? isFavorite}) { return i1.LocalAssetEntityCompanion( name: name ?? this.name, type: type ?? this.type, @@ -648,8 +608,7 @@ class LocalAssetEntityCompanion durationInSeconds: durationInSeconds ?? this.durationInSeconds, localId: localId ?? this.localId, checksum: checksum ?? this.checksum, - width: width ?? this.width, - height: height ?? this.height, + isFavorite: isFavorite ?? this.isFavorite, ); } @@ -678,11 +637,8 @@ class LocalAssetEntityCompanion if (checksum.present) { map['checksum'] = i0.Variable(checksum.value); } - if (width.present) { - map['width'] = i0.Variable(width.value); - } - if (height.present) { - map['height'] = i0.Variable(height.value); + if (isFavorite.present) { + map['is_favorite'] = i0.Variable(isFavorite.value); } return map; } @@ -697,8 +653,7 @@ class LocalAssetEntityCompanion ..write('durationInSeconds: $durationInSeconds, ') ..write('localId: $localId, ') ..write('checksum: $checksum, ') - ..write('width: $width, ') - ..write('height: $height') + ..write('isFavorite: $isFavorite') ..write(')')) .toString(); } diff --git a/mobile/lib/infrastructure/entities/remote_asset.entity.drift.dart b/mobile/lib/infrastructure/entities/remote_asset.entity.drift.dart index 4f036150b3..b868709c5b 100644 --- a/mobile/lib/infrastructure/entities/remote_asset.entity.drift.dart +++ b/mobile/lib/infrastructure/entities/remote_asset.entity.drift.dart @@ -3,7 +3,7 @@ import 'package:drift/drift.dart' as i0; import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.dart' as i1; -import 'package:immich_mobile/domain/models/asset/asset.model.dart' as i2; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart' as i2; import 'dart:typed_data' as i3; import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.dart' as i4; diff --git a/mobile/lib/infrastructure/repositories/album_media.repository.dart b/mobile/lib/infrastructure/repositories/album_media.repository.dart index c834169852..0a2da332fc 100644 --- a/mobile/lib/infrastructure/repositories/album_media.repository.dart +++ b/mobile/lib/infrastructure/repositories/album_media.repository.dart @@ -1,11 +1,15 @@ import 'package:immich_mobile/constants/constants.dart'; import 'package:immich_mobile/domain/interfaces/album_media.interface.dart'; -import 'package:immich_mobile/domain/models/asset/asset.model.dart' as asset; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart' + as asset; import 'package:immich_mobile/domain/models/local_album.model.dart'; import 'package:photo_manager/photo_manager.dart'; +import 'package:platform/platform.dart'; class AlbumMediaRepository implements IAlbumMediaRepository { - const AlbumMediaRepository(); + final Platform _platform; + const AlbumMediaRepository({Platform platform = const LocalPlatform()}) + : _platform = platform; PMFilter _getAlbumFilter({ withAssetTitle = false, @@ -42,7 +46,12 @@ class AlbumMediaRepository implements IAlbumMediaRepository { ); return PhotoManager.getAssetPathList(hasAll: true, filterOption: filter) - .then((e) => e.toDtoList()); + .then((e) { + if (_platform.isAndroid) { + e.removeWhere((a) => a.isAll); + } + return e.toDtoList(); + }); } @override @@ -85,7 +94,7 @@ class AlbumMediaRepository implements IAlbumMediaRepository { extension on AssetEntity { Future toDto() async => asset.LocalAsset( - localId: id, + id: id, name: title ?? await titleAsync, type: switch (type) { AssetType.other => asset.AssetType.other, @@ -114,7 +123,6 @@ extension on AssetPathEntity { // the assetCountAsync call is expensive for larger albums with several thousand assets assetCount: withAssetCount ? await assetCountAsync : 0, backupSelection: BackupSelection.none, - isAll: isAll, ); } diff --git a/mobile/lib/infrastructure/repositories/local_album.repository.dart b/mobile/lib/infrastructure/repositories/local_album.repository.dart index 557c264409..0ae0d0daf7 100644 --- a/mobile/lib/infrastructure/repositories/local_album.repository.dart +++ b/mobile/lib/infrastructure/repositories/local_album.repository.dart @@ -1,6 +1,6 @@ import 'package:drift/drift.dart'; import 'package:immich_mobile/domain/interfaces/local_album.interface.dart'; -import 'package:immich_mobile/domain/models/asset/asset.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/local_album.model.dart'; import 'package:immich_mobile/infrastructure/entities/local_album.entity.dart'; import 'package:immich_mobile/infrastructure/entities/local_album.entity.drift.dart'; @@ -137,10 +137,8 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository id: localAlbum.id, name: localAlbum.name, updatedAt: Value(localAlbum.updatedAt), - assetCount: Value(localAlbum.assetCount), thumbnailId: Value.absentIfNull(localAlbum.thumbnailId), backupSelection: localAlbum.backupSelection, - isAll: Value(localAlbum.isAll), ); return _db.localAlbumEntity @@ -160,7 +158,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository _db.localAlbumAssetEntity, assets.map( (a) => LocalAlbumAssetEntityCompanion.insert( - assetId: a.localId, + assetId: a.id, albumId: albumId, ), ), @@ -220,10 +218,8 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository type: a.type, createdAt: Value(a.createdAt), updatedAt: Value(a.updatedAt), - width: Value.absentIfNull(a.width), - height: Value.absentIfNull(a.height), durationInSeconds: Value.absentIfNull(a.durationInSeconds), - localId: a.localId, + localId: a.id, checksum: Value.absentIfNull(a.checksum), ), ), diff --git a/mobile/lib/infrastructure/repositories/local_asset.repository.dart b/mobile/lib/infrastructure/repositories/local_asset.repository.dart index c77e997d23..cb9119b653 100644 --- a/mobile/lib/infrastructure/repositories/local_asset.repository.dart +++ b/mobile/lib/infrastructure/repositories/local_asset.repository.dart @@ -1,5 +1,5 @@ import 'package:immich_mobile/domain/interfaces/local_asset.interface.dart'; -import 'package:immich_mobile/domain/models/asset/asset.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; diff --git a/mobile/lib/infrastructure/repositories/sync_stream.repository.dart b/mobile/lib/infrastructure/repositories/sync_stream.repository.dart index cc6c1e3e7a..03a3cdff4a 100644 --- a/mobile/lib/infrastructure/repositories/sync_stream.repository.dart +++ b/mobile/lib/infrastructure/repositories/sync_stream.repository.dart @@ -1,6 +1,6 @@ import 'package:drift/drift.dart'; import 'package:immich_mobile/domain/interfaces/sync_stream.interface.dart'; -import 'package:immich_mobile/domain/models/asset/asset.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/extensions/string_extensions.dart'; import 'package:immich_mobile/infrastructure/entities/exif.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/partner.entity.drift.dart'; diff --git a/mobile/lib/infrastructure/utils/asset.mixin.dart b/mobile/lib/infrastructure/utils/asset.mixin.dart index 4221ae27dd..8649550826 100644 --- a/mobile/lib/infrastructure/utils/asset.mixin.dart +++ b/mobile/lib/infrastructure/utils/asset.mixin.dart @@ -1,5 +1,5 @@ import 'package:drift/drift.dart'; -import 'package:immich_mobile/domain/models/asset/asset.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; mixin AssetEntityMixin on Table { TextColumn get name => text()(); diff --git a/mobile/lib/interfaces/asset.interface.dart b/mobile/lib/interfaces/asset.interface.dart index 76744c9172..ca9e9d64fb 100644 --- a/mobile/lib/interfaces/asset.interface.dart +++ b/mobile/lib/interfaces/asset.interface.dart @@ -61,7 +61,7 @@ abstract interface class IAssetRepository implements IDatabaseRepository { Future> getTrashAssets(String userId); - Future> getRecentlyAddedAssets(String userId); + Future> getRecentlyTakenAssets(String userId); Future> getMotionAssets(String userId); } diff --git a/mobile/lib/interfaces/local_files_manager.interface.dart b/mobile/lib/interfaces/local_files_manager.interface.dart index c8b83a7c93..07274b7e29 100644 --- a/mobile/lib/interfaces/local_files_manager.interface.dart +++ b/mobile/lib/interfaces/local_files_manager.interface.dart @@ -1,5 +1,5 @@ abstract interface class ILocalFilesManager { - Future moveToTrash(String fileName); - Future restoreFromTrash(String fileName); - Future requestManageStoragePermission(); + Future moveToTrash(List mediaUrls); + Future restoreFromTrash(String fileName, int type); + Future requestManageMediaPermission(); } diff --git a/mobile/lib/pages/common/gallery_viewer.page.dart b/mobile/lib/pages/common/gallery_viewer.page.dart index 7392a4d340..420b699730 100644 --- a/mobile/lib/pages/common/gallery_viewer.page.dart +++ b/mobile/lib/pages/common/gallery_viewer.page.dart @@ -63,9 +63,12 @@ class GalleryViewerPage extends HookConsumerWidget { final loadAsset = renderList.loadAsset; final isPlayingMotionVideo = ref.watch(isPlayingMotionVideoProvider); - // This key is to prevent the video player from being re-initialized during - // hero animation or device rotation. - final videoPlayerKey = useMemoized(() => GlobalKey()); + final videoPlayerKeys = useRef>({}); + + GlobalKey getVideoPlayerKey(int id) { + videoPlayerKeys.value.putIfAbsent(id, () => GlobalKey()); + return videoPlayerKeys.value[id]!; + } Future precacheNextImage(int index) async { if (!context.mounted) { @@ -243,7 +246,7 @@ class GalleryViewerPage extends HookConsumerWidget { width: context.width, height: context.height, child: NativeVideoViewerPage( - key: videoPlayerKey, + key: getVideoPlayerKey(asset.id), asset: asset, image: Image( key: ValueKey(asset), diff --git a/mobile/lib/pages/library/library.page.dart b/mobile/lib/pages/library/library.page.dart index 1852fb7877..1dc336d204 100644 --- a/mobile/lib/pages/library/library.page.dart +++ b/mobile/lib/pages/library/library.page.dart @@ -297,32 +297,34 @@ class LocalAlbumsCollectionCard extends HookConsumerWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Container( + SizedBox( height: size, width: size, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - gradient: LinearGradient( - colors: [ - context.colorScheme.primary.withAlpha(30), - context.colorScheme.primary.withAlpha(25), - ], - begin: Alignment.topCenter, - end: Alignment.bottomCenter, + child: DecoratedBox( + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(Radius.circular(20)), + gradient: LinearGradient( + colors: [ + context.colorScheme.primary.withAlpha(30), + context.colorScheme.primary.withAlpha(25), + ], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + ), + ), + child: GridView.count( + crossAxisCount: 2, + padding: const EdgeInsets.all(12), + crossAxisSpacing: 8, + mainAxisSpacing: 8, + physics: const NeverScrollableScrollPhysics(), + children: albums.take(4).map((album) { + return AlbumThumbnailCard( + album: album, + showTitle: false, + ); + }).toList(), ), - ), - child: GridView.count( - crossAxisCount: 2, - padding: const EdgeInsets.all(12), - crossAxisSpacing: 8, - mainAxisSpacing: 8, - physics: const NeverScrollableScrollPhysics(), - children: albums.take(4).map((album) { - return AlbumThumbnailCard( - album: album, - showTitle: false, - ); - }).toList(), ), ), Padding( @@ -354,27 +356,35 @@ class PlacesCollectionCard extends StatelessWidget { final size = context.width * widthFactor - 20.0; return GestureDetector( - onTap: () => context.pushRoute(const PlacesCollectionRoute()), + onTap: () => context.pushRoute( + PlacesCollectionRoute( + currentLocation: null, + ), + ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Container( + SizedBox( height: size, width: size, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - color: context.colorScheme.secondaryContainer.withAlpha(100), - ), - child: IgnorePointer( - child: MapThumbnail( - zoom: 8, - centre: const LatLng( - 21.44950, - -157.91959, + child: DecoratedBox( + decoration: BoxDecoration( + borderRadius: const BorderRadius.all(Radius.circular(20)), + color: + context.colorScheme.secondaryContainer.withAlpha(100), + ), + child: IgnorePointer( + child: MapThumbnail( + zoom: 8, + centre: const LatLng( + 21.44950, + -157.91959, + ), + showAttribution: false, + themeMode: context.isDarkTheme + ? ThemeMode.dark + : ThemeMode.light, ), - showAttribution: false, - themeMode: - context.isDarkTheme ? ThemeMode.dark : ThemeMode.light, ), ), ), diff --git a/mobile/lib/pages/library/places/places_collection.page.dart b/mobile/lib/pages/library/places/places_collection.page.dart index f9a2d4292c..5f2dea0dec 100644 --- a/mobile/lib/pages/library/places/places_collection.page.dart +++ b/mobile/lib/pages/library/places/places_collection.page.dart @@ -19,7 +19,8 @@ import 'package:maplibre_gl/maplibre_gl.dart'; @RoutePage() class PlacesCollectionPage extends HookConsumerWidget { - const PlacesCollectionPage({super.key}); + const PlacesCollectionPage({super.key, this.currentLocation}); + final LatLng? currentLocation; @override Widget build(BuildContext context, WidgetRef ref) { final places = ref.watch(getAllPlacesProvider); @@ -58,12 +59,14 @@ class PlacesCollectionPage extends HookConsumerWidget { height: 200, width: context.width, child: MapThumbnail( - onTap: (_, __) => context.pushRoute(const MapRoute()), + onTap: (_, __) => context + .pushRoute(MapRoute(initialLocation: currentLocation)), zoom: 8, - centre: const LatLng( - 21.44950, - -157.91959, - ), + centre: currentLocation ?? + const LatLng( + 21.44950, + -157.91959, + ), showAttribution: false, themeMode: context.isDarkTheme ? ThemeMode.dark : ThemeMode.light, diff --git a/mobile/lib/pages/onboarding/permission_onboarding.page.dart b/mobile/lib/pages/onboarding/permission_onboarding.page.dart index a6768cc207..b0a1b34b06 100644 --- a/mobile/lib/pages/onboarding/permission_onboarding.page.dart +++ b/mobile/lib/pages/onboarding/permission_onboarding.page.dart @@ -44,7 +44,7 @@ class PermissionOnboardingPage extends HookConsumerWidget { } }), child: const Text( - 'grant_permission', + 'continue', ).tr(), ), ], diff --git a/mobile/lib/pages/search/map/map.page.dart b/mobile/lib/pages/search/map/map.page.dart index 0e64759241..b80b96f94f 100644 --- a/mobile/lib/pages/search/map/map.page.dart +++ b/mobile/lib/pages/search/map/map.page.dart @@ -34,7 +34,8 @@ import 'package:maplibre_gl/maplibre_gl.dart'; @RoutePage() class MapPage extends HookConsumerWidget { - const MapPage({super.key}); + const MapPage({super.key, this.initialLocation}); + final LatLng? initialLocation; @override Widget build(BuildContext context, WidgetRef ref) { @@ -235,7 +236,8 @@ class MapPage extends HookConsumerWidget { } void onZoomToLocation() async { - final (location, error) = await MapUtils.checkPermAndGetLocation(context); + final (location, error) = + await MapUtils.checkPermAndGetLocation(context: context); if (error != null) { if (error == LocationPermission.unableToDetermine && context.mounted) { ImmichToast.show( @@ -272,6 +274,7 @@ class MapPage extends HookConsumerWidget { body: Stack( children: [ _MapWithMarker( + initialLocation: initialLocation, style: style, selectedMarker: selectedMarker, onMapCreated: onMapCreated, @@ -303,6 +306,7 @@ class MapPage extends HookConsumerWidget { body: Stack( children: [ _MapWithMarker( + initialLocation: initialLocation, style: style, selectedMarker: selectedMarker, onMapCreated: onMapCreated, @@ -368,6 +372,7 @@ class _MapWithMarker extends StatelessWidget { final OnStyleLoadedCallback onStyleLoaded; final Function()? onMarkerTapped; final ValueNotifier<_AssetMarkerMeta?> selectedMarker; + final LatLng? initialLocation; const _MapWithMarker({ required this.style, @@ -377,6 +382,7 @@ class _MapWithMarker extends StatelessWidget { required this.onStyleLoaded, required this.selectedMarker, this.onMarkerTapped, + this.initialLocation, }); @override @@ -389,8 +395,10 @@ class _MapWithMarker extends StatelessWidget { children: [ style.widgetWhen( onData: (style) => MapLibreMap( - initialCameraPosition: - const CameraPosition(target: LatLng(0, 0)), + initialCameraPosition: CameraPosition( + target: initialLocation ?? const LatLng(0, 0), + zoom: initialLocation != null ? 12 : 0, + ), styleString: style, // This is needed to update the selectedMarker's position on map camera updates // The changes are notified through the mapController ValueListener which is added in [onMapCreated] diff --git a/mobile/lib/pages/search/map/map_location_picker.page.dart b/mobile/lib/pages/search/map/map_location_picker.page.dart index 9d526d8080..f27deae052 100644 --- a/mobile/lib/pages/search/map/map_location_picker.page.dart +++ b/mobile/lib/pages/search/map/map_location_picker.page.dart @@ -46,7 +46,7 @@ class MapLocationPickerPage extends HookConsumerWidget { Future getCurrentLocation() async { var (currentLocation, _) = - await MapUtils.checkPermAndGetLocation(context); + await MapUtils.checkPermAndGetLocation(context: context); if (currentLocation == null) { return; diff --git a/mobile/lib/pages/search/recently_added.page.dart b/mobile/lib/pages/search/recently_taken.page.dart similarity index 74% rename from mobile/lib/pages/search/recently_added.page.dart rename to mobile/lib/pages/search/recently_taken.page.dart index b79527e222..cc1eb7086e 100644 --- a/mobile/lib/pages/search/recently_added.page.dart +++ b/mobile/lib/pages/search/recently_taken.page.dart @@ -4,19 +4,19 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/asyncvalue_extensions.dart'; import 'package:immich_mobile/widgets/asset_grid/immich_asset_grid.dart'; -import 'package:immich_mobile/providers/search/recently_added_asset.provider.dart'; +import 'package:immich_mobile/providers/search/recently_taken_asset.provider.dart'; @RoutePage() -class RecentlyAddedPage extends HookConsumerWidget { - const RecentlyAddedPage({super.key}); +class RecentlyTakenPage extends HookConsumerWidget { + const RecentlyTakenPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { - final recents = ref.watch(recentlyAddedAssetProvider); + final recents = ref.watch(recentlyTakenAssetProvider); return Scaffold( appBar: AppBar( - title: const Text('recently_added_page_title').tr(), + title: const Text('recently_taken_page_title').tr(), leading: IconButton( onPressed: () => context.maybePop(), icon: const Icon(Icons.arrow_back_ios_rounded), diff --git a/mobile/lib/pages/search/search.page.dart b/mobile/lib/pages/search/search.page.dart index 62a62d6c98..f7a87803de 100644 --- a/mobile/lib/pages/search/search.page.dart +++ b/mobile/lib/pages/search/search.page.dart @@ -843,10 +843,10 @@ class QuickLinkList extends StatelessWidget { physics: const NeverScrollableScrollPhysics(), children: [ QuickLink( - title: 'recently_added'.tr(), + title: 'recently_taken'.tr(), icon: Icons.schedule_outlined, isTop: true, - onTap: () => context.pushRoute(const RecentlyAddedRoute()), + onTap: () => context.pushRoute(const RecentlyTakenRoute()), ), QuickLink( title: 'videos'.tr(), diff --git a/mobile/lib/providers/image/immich_local_image_provider.dart b/mobile/lib/providers/image/immich_local_image_provider.dart index 36fd3334b9..4c77ee4b56 100644 --- a/mobile/lib/providers/image/immich_local_image_provider.dart +++ b/mobile/lib/providers/image/immich_local_image_provider.dart @@ -53,50 +53,35 @@ class ImmichLocalImageProvider extends ImageProvider { ImageDecoderCallback decode, StreamController chunkEvents, ) async* { - ui.ImmutableBuffer? buffer; try { final local = asset.local; if (local == null) { throw StateError('Asset ${asset.fileName} has no local data'); } - var thumbBytes = await local - .thumbnailDataWithSize(const ThumbnailSize.square(256), quality: 80); - if (thumbBytes == null) { - throw StateError("Loading thumbnail for ${asset.fileName} failed"); - } - buffer = await ui.ImmutableBuffer.fromUint8List(thumbBytes); - thumbBytes = null; - yield await decode(buffer); - buffer = null; - switch (asset.type) { case AssetType.image: final File? file = await local.originFile; if (file == null) { throw StateError("Opening file for asset ${asset.fileName} failed"); } - buffer = await ui.ImmutableBuffer.fromFilePath(file.path); + final buffer = await ui.ImmutableBuffer.fromFilePath(file.path); yield await decode(buffer); - buffer = null; break; case AssetType.video: final size = ThumbnailSize(width.ceil(), height.ceil()); - thumbBytes = await local.thumbnailDataWithSize(size); + final thumbBytes = await local.thumbnailDataWithSize(size); if (thumbBytes == null) { throw StateError("Failed to load preview for ${asset.fileName}"); } - buffer = await ui.ImmutableBuffer.fromUint8List(thumbBytes); - thumbBytes = null; + final buffer = await ui.ImmutableBuffer.fromUint8List(thumbBytes); yield await decode(buffer); - buffer = null; break; default: throw StateError('Unsupported asset type ${asset.type}'); } } catch (error, stack) { log.severe('Error loading local image ${asset.fileName}', error, stack); - buffer?.dispose(); } finally { chunkEvents.close(); } @@ -106,12 +91,11 @@ class ImmichLocalImageProvider extends ImageProvider { bool operator ==(Object other) { if (identical(this, other)) return true; if (other is ImmichLocalImageProvider) { - return asset == other.asset; + return asset.id == other.asset.id && asset.localId == other.asset.localId; } - return false; } @override - int get hashCode => asset.hashCode; + int get hashCode => Object.hash(asset.id, asset.localId); } diff --git a/mobile/lib/providers/image/immich_local_thumbnail_provider.dart b/mobile/lib/providers/image/immich_local_thumbnail_provider.dart index 69cdb105c0..edcf8a9458 100644 --- a/mobile/lib/providers/image/immich_local_thumbnail_provider.dart +++ b/mobile/lib/providers/image/immich_local_thumbnail_provider.dart @@ -2,11 +2,14 @@ import 'dart:async'; import 'dart:ui' as ui; import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter_cache_manager/flutter_cache_manager.dart'; +import 'package:immich_mobile/providers/image/cache/thumbnail_image_cache_manager.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/painting.dart'; import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:photo_manager/photo_manager.dart' show ThumbnailSize; +import 'package:logging/logging.dart'; /// The local image provider for an asset /// Only viable @@ -15,11 +18,16 @@ class ImmichLocalThumbnailProvider final Asset asset; final int height; final int width; + final CacheManager? cacheManager; + final Logger log = Logger("ImmichLocalThumbnailProvider"); + final String? userId; ImmichLocalThumbnailProvider({ required this.asset, this.height = 256, this.width = 256, + this.cacheManager, + this.userId, }) : assert(asset.local != null, 'Only usable when asset.local is set'); /// Converts an [ImageProvider]'s settings plus an [ImageConfiguration] to a key @@ -36,57 +44,62 @@ class ImmichLocalThumbnailProvider ImmichLocalThumbnailProvider key, ImageDecoderCallback decode, ) { - final chunkEvents = StreamController(); + final cache = cacheManager ?? ThumbnailImageCacheManager(); return MultiImageStreamCompleter( - codec: _codec(key.asset, decode, chunkEvents), + codec: _codec(key.asset, cache, decode), scale: 1.0, - chunkEvents: chunkEvents.stream, informationCollector: () sync* { - yield ErrorDescription(asset.fileName); + yield ErrorDescription(key.asset.fileName); }, ); } // Streams in each stage of the image as we ask for it Stream _codec( - Asset key, + Asset assetData, + CacheManager cache, ImageDecoderCallback decode, - StreamController chunkEvents, ) async* { - // Load a small thumbnail - final thumbBytes = await asset.local?.thumbnailDataWithSize( - const ThumbnailSize.square(32), - quality: 75, - ); - if (thumbBytes != null) { - final buffer = await ui.ImmutableBuffer.fromUint8List(thumbBytes); - final codec = await decode(buffer); - yield codec; - } else { - debugPrint("Loading thumb for ${asset.fileName} failed"); + final cacheKey = + '$userId${assetData.localId}${assetData.checksum}$width$height'; + final fileFromCache = await cache.getFileFromCache(cacheKey); + if (fileFromCache != null) { + try { + final buffer = + await ui.ImmutableBuffer.fromFilePath(fileFromCache.file.path); + final codec = await decode(buffer); + yield codec; + return; + } catch (error) { + log.severe('Found thumbnail in cache, but loading it failed', error); + } } - final normalThumbBytes = - await asset.local?.thumbnailDataWithSize(ThumbnailSize(width, height)); - if (normalThumbBytes == null) { + final thumbnailBytes = await assetData.local?.thumbnailDataWithSize( + ThumbnailSize(width, height), + quality: 80, + ); + if (thumbnailBytes == null) { throw StateError( - "Loading thumb for local photo ${asset.fileName} failed", + "Loading thumb for local photo ${assetData.fileName} failed", ); } - final buffer = await ui.ImmutableBuffer.fromUint8List(normalThumbBytes); + + final buffer = await ui.ImmutableBuffer.fromUint8List(thumbnailBytes); final codec = await decode(buffer); yield codec; - - chunkEvents.close(); + await cache.putFile(cacheKey, thumbnailBytes); } @override bool operator ==(Object other) { - if (other is! ImmichLocalThumbnailProvider) return false; if (identical(this, other)) return true; - return asset == other.asset; + if (other is ImmichLocalThumbnailProvider) { + return asset.id == other.asset.id && asset.localId == other.asset.localId; + } + return false; } @override - int get hashCode => asset.hashCode; + int get hashCode => Object.hash(asset.id, asset.localId); } diff --git a/mobile/lib/providers/image/immich_remote_image_provider.dart b/mobile/lib/providers/image/immich_remote_image_provider.dart index 9e1d8aa120..d5189fa4fc 100644 --- a/mobile/lib/providers/image/immich_remote_image_provider.dart +++ b/mobile/lib/providers/image/immich_remote_image_provider.dart @@ -57,12 +57,6 @@ class ImmichRemoteImageProvider AppSettingsEnum.loadOriginal.defaultValue, ); - /// Whether to load the preview thumbnail first or not - bool get _loadPreview => Store.get( - AppSettingsEnum.loadPreview.storeKey, - AppSettingsEnum.loadPreview.defaultValue, - ); - // Streams in each stage of the image as we ask for it Stream _codec( ImmichRemoteImageProvider key, @@ -70,21 +64,6 @@ class ImmichRemoteImageProvider ImageDecoderCallback decode, StreamController chunkEvents, ) async* { - // Load a preview to the chunk events - if (_loadPreview) { - final preview = getThumbnailUrlForRemoteId( - key.assetId, - type: api.AssetMediaSize.thumbnail, - ); - - yield await ImageLoader.loadImageFromCache( - preview, - cache: cache, - decode: decode, - chunkEvents: chunkEvents, - ); - } - // Load the higher resolution version of the image final url = getThumbnailUrlForRemoteId( key.assetId, diff --git a/mobile/lib/providers/search/recently_added_asset.provider.dart b/mobile/lib/providers/search/recently_taken_asset.provider.dart similarity index 68% rename from mobile/lib/providers/search/recently_added_asset.provider.dart rename to mobile/lib/providers/search/recently_taken_asset.provider.dart index c4819d9d44..157e7c2a74 100644 --- a/mobile/lib/providers/search/recently_added_asset.provider.dart +++ b/mobile/lib/providers/search/recently_taken_asset.provider.dart @@ -2,8 +2,8 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/services/asset.service.dart'; -final recentlyAddedAssetProvider = FutureProvider>((ref) async { +final recentlyTakenAssetProvider = FutureProvider>((ref) async { final assetService = ref.read(assetServiceProvider); - return assetService.getRecentlyAddedAssets(); + return assetService.getRecentlyTakenAssets(); }); diff --git a/mobile/lib/repositories/asset.repository.dart b/mobile/lib/repositories/asset.repository.dart index cda2b25e4d..60e5d09bcd 100644 --- a/mobile/lib/repositories/asset.repository.dart +++ b/mobile/lib/repositories/asset.repository.dart @@ -225,7 +225,7 @@ class AssetRepository extends DatabaseRepository implements IAssetRepository { } @override - Future> getRecentlyAddedAssets(String userId) { + Future> getRecentlyTakenAssets(String userId) { return db.assets .where() .ownerIdEqualToAnyChecksum(fastHash(userId)) diff --git a/mobile/lib/repositories/local_files_manager.repository.dart b/mobile/lib/repositories/local_files_manager.repository.dart index 522d7e7a05..c2e234d14d 100644 --- a/mobile/lib/repositories/local_files_manager.repository.dart +++ b/mobile/lib/repositories/local_files_manager.repository.dart @@ -3,21 +3,23 @@ import 'package:immich_mobile/interfaces/local_files_manager.interface.dart'; import 'package:immich_mobile/utils/local_files_manager.dart'; final localFilesManagerRepositoryProvider = - Provider((ref) => LocalFilesManagerRepository()); + Provider((ref) => const LocalFilesManagerRepository()); class LocalFilesManagerRepository implements ILocalFilesManager { + const LocalFilesManagerRepository(); + @override - Future moveToTrash(String fileName) async { - return await LocalFilesManager.moveToTrash(fileName); + Future moveToTrash(List mediaUrls) async { + return await LocalFilesManager.moveToTrash(mediaUrls); } @override - Future restoreFromTrash(String fileName) async { - return await LocalFilesManager.restoreFromTrash(fileName); + Future restoreFromTrash(String fileName, int type) async { + return await LocalFilesManager.restoreFromTrash(fileName, type); } @override - Future requestManageStoragePermission() async { - return await LocalFilesManager.requestManageStoragePermission(); + Future requestManageMediaPermission() async { + return await LocalFilesManager.requestManageMediaPermission(); } } diff --git a/mobile/lib/routing/router.dart b/mobile/lib/routing/router.dart index 5b771d3acc..b6229b9963 100644 --- a/mobile/lib/routing/router.dart +++ b/mobile/lib/routing/router.dart @@ -58,7 +58,7 @@ import 'package:immich_mobile/pages/search/all_videos.page.dart'; import 'package:immich_mobile/pages/search/map/map.page.dart'; import 'package:immich_mobile/pages/search/map/map_location_picker.page.dart'; import 'package:immich_mobile/pages/search/person_result.page.dart'; -import 'package:immich_mobile/pages/search/recently_added.page.dart'; +import 'package:immich_mobile/pages/search/recently_taken.page.dart'; import 'package:immich_mobile/pages/search/search.page.dart'; import 'package:immich_mobile/pages/share_intent/share_intent.page.dart'; import 'package:immich_mobile/presentation/pages/feat_in_development.page.dart'; @@ -161,7 +161,7 @@ class AppRouter extends RootStackRouter { guards: [_authGuard, _duplicateGuard], ), AutoRoute( - page: RecentlyAddedRoute.page, + page: RecentlyTakenRoute.page, guards: [_authGuard, _duplicateGuard], ), CustomRoute( diff --git a/mobile/lib/routing/router.gr.dart b/mobile/lib/routing/router.gr.dart index fbc730fed2..40025e8597 100644 --- a/mobile/lib/routing/router.gr.dart +++ b/mobile/lib/routing/router.gr.dart @@ -1043,10 +1043,17 @@ class MapLocationPickerRouteArgs { /// generated route for /// [MapPage] -class MapRoute extends PageRouteInfo { - const MapRoute({List? children}) - : super( +class MapRoute extends PageRouteInfo { + MapRoute({ + Key? key, + LatLng? initialLocation, + List? children, + }) : super( MapRoute.name, + args: MapRouteArgs( + key: key, + initialLocation: initialLocation, + ), initialChildren: children, ); @@ -1055,11 +1062,32 @@ class MapRoute extends PageRouteInfo { static PageInfo page = PageInfo( name, builder: (data) { - return const MapPage(); + final args = + data.argsAs(orElse: () => const MapRouteArgs()); + return MapPage( + key: args.key, + initialLocation: args.initialLocation, + ); }, ); } +class MapRouteArgs { + const MapRouteArgs({ + this.key, + this.initialLocation, + }); + + final Key? key; + + final LatLng? initialLocation; + + @override + String toString() { + return 'MapRouteArgs{key: $key, initialLocation: $initialLocation}'; + } +} + /// generated route for /// [MemoryPage] class MemoryRoute extends PageRouteInfo { @@ -1352,10 +1380,17 @@ class PhotosRoute extends PageRouteInfo { /// generated route for /// [PlacesCollectionPage] -class PlacesCollectionRoute extends PageRouteInfo { - const PlacesCollectionRoute({List? children}) - : super( +class PlacesCollectionRoute extends PageRouteInfo { + PlacesCollectionRoute({ + Key? key, + LatLng? currentLocation, + List? children, + }) : super( PlacesCollectionRoute.name, + args: PlacesCollectionRouteArgs( + key: key, + currentLocation: currentLocation, + ), initialChildren: children, ); @@ -1364,26 +1399,47 @@ class PlacesCollectionRoute extends PageRouteInfo { static PageInfo page = PageInfo( name, builder: (data) { - return const PlacesCollectionPage(); + final args = data.argsAs( + orElse: () => const PlacesCollectionRouteArgs()); + return PlacesCollectionPage( + key: args.key, + currentLocation: args.currentLocation, + ); }, ); } +class PlacesCollectionRouteArgs { + const PlacesCollectionRouteArgs({ + this.key, + this.currentLocation, + }); + + final Key? key; + + final LatLng? currentLocation; + + @override + String toString() { + return 'PlacesCollectionRouteArgs{key: $key, currentLocation: $currentLocation}'; + } +} + /// generated route for -/// [RecentlyAddedPage] -class RecentlyAddedRoute extends PageRouteInfo { - const RecentlyAddedRoute({List? children}) +/// [RecentlyTakenPage] +class RecentlyTakenRoute extends PageRouteInfo { + const RecentlyTakenRoute({List? children}) : super( - RecentlyAddedRoute.name, + RecentlyTakenRoute.name, initialChildren: children, ); - static const String name = 'RecentlyAddedRoute'; + static const String name = 'RecentlyTakenRoute'; static PageInfo page = PageInfo( name, builder: (data) { - return const RecentlyAddedPage(); + return const RecentlyTakenPage(); }, ); } diff --git a/mobile/lib/services/asset.service.dart b/mobile/lib/services/asset.service.dart index d187284d07..4bf62eca31 100644 --- a/mobile/lib/services/asset.service.dart +++ b/mobile/lib/services/asset.service.dart @@ -514,9 +514,9 @@ class AssetService { return _assetRepository.watchAsset(id, fireImmediately: fireImmediately); } - Future> getRecentlyAddedAssets() { + Future> getRecentlyTakenAssets() { final me = _userService.getMyUser(); - return _assetRepository.getRecentlyAddedAssets(me.id); + return _assetRepository.getRecentlyTakenAssets(me.id); } Future> getMotionAssets() { diff --git a/mobile/lib/services/oauth.service.dart b/mobile/lib/services/oauth.service.dart index ddd97522f8..9a54a8d7c9 100644 --- a/mobile/lib/services/oauth.service.dart +++ b/mobile/lib/services/oauth.service.dart @@ -13,6 +13,8 @@ class OAuthService { Future getOAuthServerUrl( String serverUrl, + String state, + String codeChallenge, ) async { // Resolve API server endpoint from user provided serverUrl await _apiService.resolveAndSetEndpoint(serverUrl); @@ -22,7 +24,11 @@ class OAuthService { ); final dto = await _apiService.oAuthApi.startOAuth( - OAuthConfigDto(redirectUri: redirectUri), + OAuthConfigDto( + redirectUri: redirectUri, + state: state, + codeChallenge: codeChallenge, + ), ); final authUrl = dto?.url; @@ -31,7 +37,11 @@ class OAuthService { return authUrl; } - Future oAuthLogin(String oauthUrl) async { + Future oAuthLogin( + String oauthUrl, + String state, + String codeVerifier, + ) async { String result = await FlutterWebAuth2.authenticate( url: oauthUrl, callbackUrlScheme: callbackUrlScheme, @@ -49,6 +59,8 @@ class OAuthService { return await _apiService.oAuthApi.finishOAuth( OAuthCallbackDto( url: result, + state: state, + codeVerifier: codeVerifier, ), ); } diff --git a/mobile/lib/services/sync.service.dart b/mobile/lib/services/sync.service.dart index 547e49c1a0..80950d8c00 100644 --- a/mobile/lib/services/sync.service.dart +++ b/mobile/lib/services/sync.service.dart @@ -255,9 +255,12 @@ class SyncService { .where((asset) => idsToDelete.contains(asset.remoteId)) .toList(); - for (var asset in matchedAssets) { - _localFilesManager.moveToTrash(asset.fileName); - } + final mediaUrls = await Future.wait( + matchedAssets + .map((asset) => asset.local?.getMediaUrl() ?? Future.value(null)), + ); + + await _localFilesManager.moveToTrash(mediaUrls.nonNulls.toList()); } /// Deletes remote-only assets, updates merged assets to be local-only @@ -819,13 +822,29 @@ class SyncService { } Future _toggleTrashStatusForAssets(List assetsList) async { - for (var asset in assetsList) { + final trashMediaUrls = []; + + for (final asset in assetsList) { if (asset.isTrashed) { - _localFilesManager.moveToTrash(asset.fileName); + final mediaUrl = await asset.local?.getMediaUrl(); + if (mediaUrl == null) { + _log.warning( + "Failed to get media URL for asset ${asset.name} while moving to trash", + ); + continue; + } + trashMediaUrls.add(mediaUrl); } else { - _localFilesManager.restoreFromTrash(asset.fileName); + await _localFilesManager.restoreFromTrash( + asset.fileName, + asset.type.index, + ); } } + + if (trashMediaUrls.isNotEmpty) { + await _localFilesManager.moveToTrash(trashMediaUrls); + } } /// Inserts or updates the assets in the database with their ExifInfo (if any) diff --git a/mobile/lib/utils/local_files_manager.dart b/mobile/lib/utils/local_files_manager.dart index da9308c3cf..a4cf41a6e6 100644 --- a/mobile/lib/utils/local_files_manager.dart +++ b/mobile/lib/utils/local_files_manager.dart @@ -1,38 +1,37 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; +import 'package:logging/logging.dart'; -class LocalFilesManager { +abstract final class LocalFilesManager { + static final Logger _logger = Logger('LocalFilesManager'); static const MethodChannel _channel = MethodChannel('file_trash'); - static Future moveToTrash(String fileName) async { + static Future moveToTrash(List mediaUrls) async { try { - final bool success = - await _channel.invokeMethod('moveToTrash', {'fileName': fileName}); - return success; - } on PlatformException catch (e) { - debugPrint('Error moving to trash: ${e.message}'); + return await _channel + .invokeMethod('moveToTrash', {'mediaUrls': mediaUrls}); + } catch (e, s) { + _logger.warning('Error moving file to trash', e, s); return false; } } - static Future restoreFromTrash(String fileName) async { + static Future restoreFromTrash(String fileName, int type) async { try { - final bool success = await _channel - .invokeMethod('restoreFromTrash', {'fileName': fileName}); - return success; - } on PlatformException catch (e) { - debugPrint('Error restoring file: ${e.message}'); + return await _channel.invokeMethod( + 'restoreFromTrash', + {'fileName': fileName, 'type': type}, + ); + } catch (e, s) { + _logger.warning('Error restore file from trash', e, s); return false; } } - static Future requestManageStoragePermission() async { + static Future requestManageMediaPermission() async { try { - final bool success = - await _channel.invokeMethod('requestManageStoragePermission'); - return success; - } on PlatformException catch (e) { - debugPrint('Error requesting permission: ${e.message}'); + return await _channel.invokeMethod('requestManageMediaPermission'); + } catch (e, s) { + _logger.warning('Error requesting manage media permission', e, s); return false; } } diff --git a/mobile/lib/utils/map_utils.dart b/mobile/lib/utils/map_utils.dart index 44f7ebf271..df1ff28d8f 100644 --- a/mobile/lib/utils/map_utils.dart +++ b/mobile/lib/utils/map_utils.dart @@ -64,12 +64,13 @@ class MapUtils { 'features': markers.map(_addFeature).toList(), }; - static Future<(Position?, LocationPermission?)> checkPermAndGetLocation( - BuildContext context, - ) async { + static Future<(Position?, LocationPermission?)> checkPermAndGetLocation({ + required BuildContext context, + bool silent = false, + }) async { try { bool serviceEnabled = await Geolocator.isLocationServiceEnabled(); - if (!serviceEnabled) { + if (!serviceEnabled && !silent) { showDialog( context: context, builder: (context) => _LocationServiceDisabledDialog(), @@ -80,7 +81,7 @@ class MapUtils { LocationPermission permission = await Geolocator.checkPermission(); bool shouldRequestPermission = false; - if (permission == LocationPermission.denied) { + if (permission == LocationPermission.denied && !silent) { shouldRequestPermission = await showDialog( context: context, builder: (context) => _LocationPermissionDisabledDialog(), @@ -94,15 +95,19 @@ class MapUtils { permission == LocationPermission.deniedForever) { // Open app settings only if you did not request for permission before if (permission == LocationPermission.deniedForever && - !shouldRequestPermission) { + !shouldRequestPermission && + !silent) { await Geolocator.openAppSettings(); } return (null, LocationPermission.deniedForever); } Position currentUserLocation = await Geolocator.getCurrentPosition( - desiredAccuracy: LocationAccuracy.medium, - timeLimit: const Duration(seconds: 5), + locationSettings: const LocationSettings( + accuracy: LocationAccuracy.high, + distanceFilter: 0, + timeLimit: Duration(seconds: 5), + ), ); return (currentUserLocation, null); } catch (error, stack) { diff --git a/mobile/lib/utils/migration.dart b/mobile/lib/utils/migration.dart index bebd7a027b..6a09f79ce2 100644 --- a/mobile/lib/utils/migration.dart +++ b/mobile/lib/utils/migration.dart @@ -3,7 +3,7 @@ import 'dart:async'; import 'dart:io'; -import 'package:flutter/widgets.dart'; +import 'package:flutter/foundation.dart'; import 'package:immich_mobile/domain/models/store.model.dart'; import 'package:immich_mobile/entities/album.entity.dart'; import 'package:immich_mobile/entities/android_device_asset.entity.dart'; @@ -17,6 +17,8 @@ import 'package:immich_mobile/infrastructure/entities/store.entity.dart'; import 'package:immich_mobile/infrastructure/entities/user.entity.dart'; import 'package:immich_mobile/utils/diff.dart'; import 'package:isar/isar.dart'; +// ignore: import_rule_photo_manager +import 'package:photo_manager/photo_manager.dart'; const int targetVersion = 10; @@ -69,14 +71,45 @@ Future _migrateDeviceAsset(Isar db) async { : (await db.iOSDeviceAssets.where().findAll()) .map((i) => _DeviceAsset(assetId: i.id, hash: i.hash)) .toList(); - final localAssets = (await db.assets - .where() - .anyOf(ids, (query, id) => query.localIdEqualTo(id.assetId)) - .findAll()) - .map((a) => _DeviceAsset(assetId: a.localId!, dateTime: a.fileModifiedAt)) - .toList(); - debugPrint("Device Asset Ids length - ${ids.length}"); - debugPrint("Local Asset Ids length - ${localAssets.length}"); + + final PermissionState ps = await PhotoManager.requestPermissionExtend(); + if (!ps.hasAccess) { + if (kDebugMode) { + debugPrint( + "[MIGRATION] Photo library permission not granted. Skipping device asset migration.", + ); + } + + return; + } + + List<_DeviceAsset> localAssets = []; + final List paths = + await PhotoManager.getAssetPathList(onlyAll: true); + + if (paths.isEmpty) { + localAssets = (await db.assets + .where() + .anyOf(ids, (query, id) => query.localIdEqualTo(id.assetId)) + .findAll()) + .map( + (a) => _DeviceAsset(assetId: a.localId!, dateTime: a.fileModifiedAt), + ) + .toList(); + } else { + final AssetPathEntity albumWithAll = paths.first; + final int assetCount = await albumWithAll.assetCountAsync; + + final List allDeviceAssets = + await albumWithAll.getAssetListRange(start: 0, end: assetCount); + + localAssets = allDeviceAssets + .map((a) => _DeviceAsset(assetId: a.id, dateTime: a.modifiedDateTime)) + .toList(); + } + + debugPrint("[MIGRATION] Device Asset Ids length - ${ids.length}"); + debugPrint("[MIGRATION] Local Asset Ids length - ${localAssets.length}"); ids.sort((a, b) => a.assetId.compareTo(b.assetId)); localAssets.sort((a, b) => a.assetId.compareTo(b.assetId)); final List toAdd = []; @@ -95,15 +128,27 @@ Future _migrateDeviceAsset(Isar db) async { return false; }, onlyFirst: (deviceAsset) { - debugPrint( - 'DeviceAsset not found in local assets: ${deviceAsset.assetId}', - ); + if (kDebugMode) { + debugPrint( + '[MIGRATION] Local asset not found in DeviceAsset: ${deviceAsset.assetId}', + ); + } }, onlySecond: (asset) { - debugPrint('Local asset not found in DeviceAsset: ${asset.assetId}'); + if (kDebugMode) { + debugPrint( + '[MIGRATION] Local asset not found in DeviceAsset: ${asset.assetId}', + ); + } }, ); - debugPrint("Total number of device assets migrated - ${toAdd.length}"); + + if (kDebugMode) { + debugPrint( + "[MIGRATION] Total number of device assets migrated - ${toAdd.length}", + ); + } + await db.writeTxn(() async { await db.deviceAssetEntitys.putAll(toAdd); }); diff --git a/mobile/lib/utils/selection_handlers.dart b/mobile/lib/utils/selection_handlers.dart index 4a9fcc8c99..c63d819153 100644 --- a/mobile/lib/utils/selection_handlers.dart +++ b/mobile/lib/utils/selection_handlers.dart @@ -8,6 +8,7 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/providers/asset.provider.dart'; import 'package:immich_mobile/services/asset.service.dart'; import 'package:immich_mobile/services/share.service.dart'; +import 'package:immich_mobile/utils/translation.dart'; import 'package:immich_mobile/widgets/common/date_time_picker.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart'; import 'package:immich_mobile/widgets/common/location_picker.dart'; @@ -57,12 +58,13 @@ Future handleArchiveAssets( .read(assetProvider.notifier) .toggleArchive(selection, shouldArchive); - final assetOrAssets = selection.length > 1 ? 'assets' : 'asset'; - final archiveOrLibrary = shouldArchive ? 'archive' : 'library'; + final message = shouldArchive + ? t('moved_to_archive', {'count': selection.length}) + : t('moved_to_library', {'count': selection.length}); if (context.mounted) { ImmichToast.show( context: context, - msg: 'Moved ${selection.length} $assetOrAssets to $archiveOrLibrary', + msg: message, gravity: toastGravity, ); } diff --git a/mobile/lib/utils/translation.dart b/mobile/lib/utils/translation.dart new file mode 100644 index 0000000000..461e88ead7 --- /dev/null +++ b/mobile/lib/utils/translation.dart @@ -0,0 +1,14 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:intl/message_format.dart'; + +String t(String key, [Map? args]) { + try { + String message = key.tr(); + if (args != null) { + return MessageFormat(message).format(args); + } + return message; + } catch (e) { + return key; + } +} diff --git a/mobile/lib/widgets/asset_grid/immich_asset_grid.dart b/mobile/lib/widgets/asset_grid/immich_asset_grid.dart index 2ec01e871f..da4c47e466 100644 --- a/mobile/lib/widgets/asset_grid/immich_asset_grid.dart +++ b/mobile/lib/widgets/asset_grid/immich_asset_grid.dart @@ -97,6 +97,7 @@ class ImmichAssetGrid extends HookConsumerWidget { ); if (7 - scaleFactor.value.toInt() != perRow.value) { perRow.value = 7 - scaleFactor.value.toInt(); + settings.setSetting(AppSettingsEnum.tilesPerRow, perRow.value); } }; }), diff --git a/mobile/lib/widgets/asset_grid/immich_asset_grid_view.dart b/mobile/lib/widgets/asset_grid/immich_asset_grid_view.dart index a7141c33b2..060898e270 100644 --- a/mobile/lib/widgets/asset_grid/immich_asset_grid_view.dart +++ b/mobile/lib/widgets/asset_grid/immich_asset_grid_view.dart @@ -755,7 +755,7 @@ class _MonthTitle extends StatelessWidget { key: Key("month-$title"), padding: const EdgeInsets.only(left: 12.0, top: 24.0), child: Text( - title, + toBeginningOfSentenceCase(title, context.locale.languageCode), style: const TextStyle( fontSize: 26, fontWeight: FontWeight.w500, @@ -786,7 +786,7 @@ class _Title extends StatelessWidget { @override Widget build(BuildContext context) { return GroupDividerTitle( - text: title, + text: toBeginningOfSentenceCase(title, context.locale.languageCode), multiselectEnabled: selectionActive, onSelect: () => selectAssets(assets), onDeselect: () => deselectAssets(assets), diff --git a/mobile/lib/widgets/common/immich_logo.dart b/mobile/lib/widgets/common/immich_logo.dart index 9f7725aa12..43987878cb 100644 --- a/mobile/lib/widgets/common/immich_logo.dart +++ b/mobile/lib/widgets/common/immich_logo.dart @@ -12,14 +12,11 @@ class ImmichLogo extends StatelessWidget { @override Widget build(BuildContext context) { - return Hero( - tag: heroTag, - child: Image( - image: const AssetImage('assets/immich-logo.png'), - width: size, - filterQuality: FilterQuality.high, - isAntiAlias: true, - ), + return Image( + image: const AssetImage('assets/immich-logo.png'), + width: size, + filterQuality: FilterQuality.high, + isAntiAlias: true, ); } } diff --git a/mobile/lib/widgets/common/immich_thumbnail.dart b/mobile/lib/widgets/common/immich_thumbnail.dart index 2ebead0083..35729ead7b 100644 --- a/mobile/lib/widgets/common/immich_thumbnail.dart +++ b/mobile/lib/widgets/common/immich_thumbnail.dart @@ -1,7 +1,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/providers/image/immich_local_thumbnail_provider.dart'; import 'package:immich_mobile/providers/image/immich_remote_thumbnail_provider.dart'; import 'package:immich_mobile/entities/asset.entity.dart'; @@ -9,8 +9,9 @@ import 'package:immich_mobile/utils/hooks/blurhash_hook.dart'; import 'package:immich_mobile/widgets/common/immich_image.dart'; import 'package:immich_mobile/widgets/common/thumbhash_placeholder.dart'; import 'package:octo_image/octo_image.dart'; +import 'package:immich_mobile/providers/user.provider.dart'; -class ImmichThumbnail extends HookWidget { +class ImmichThumbnail extends HookConsumerWidget { const ImmichThumbnail({ this.asset, this.width = 250, @@ -31,6 +32,7 @@ class ImmichThumbnail extends HookWidget { static ImageProvider imageProvider({ Asset? asset, String? assetId, + String? userId, int thumbnailSize = 256, }) { if (asset == null && assetId == null) { @@ -48,6 +50,7 @@ class ImmichThumbnail extends HookWidget { asset: asset, height: thumbnailSize, width: thumbnailSize, + userId: userId, ); } else { return ImmichRemoteThumbnailProvider( @@ -59,8 +62,10 @@ class ImmichThumbnail extends HookWidget { } @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { Uint8List? blurhash = useBlurHashRef(asset).value; + final userId = ref.watch(currentUserProvider)?.id; + if (asset == null) { return Container( color: Colors.grey, @@ -79,6 +84,7 @@ class ImmichThumbnail extends HookWidget { octoSet: blurHashOrPlaceholder(blurhash), image: ImmichThumbnail.imageProvider( asset: asset, + userId: userId, ), width: width, height: height, diff --git a/mobile/lib/widgets/forms/login/login_form.dart b/mobile/lib/widgets/forms/login/login_form.dart index 7af52b413d..5374d1ef33 100644 --- a/mobile/lib/widgets/forms/login/login_form.dart +++ b/mobile/lib/widgets/forms/login/login_form.dart @@ -1,6 +1,9 @@ +import 'dart:convert'; import 'dart:io'; +import 'dart:math'; import 'package:auto_route/auto_route.dart'; +import 'package:crypto/crypto.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -203,13 +206,51 @@ class LoginForm extends HookConsumerWidget { } } + String generateRandomString(int length) { + const chars = + 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890'; + final random = Random.secure(); + return String.fromCharCodes( + Iterable.generate( + length, + (_) => chars.codeUnitAt(random.nextInt(chars.length)), + ), + ); + } + + List randomBytes(int length) { + final random = Random.secure(); + return List.generate(length, (i) => random.nextInt(256)); + } + + /// Per specification, the code verifier must be 43-128 characters long + /// and consist of characters [A-Z, a-z, 0-9, "-", ".", "_", "~"] + /// https://datatracker.ietf.org/doc/html/rfc7636#section-4.1 + String randomCodeVerifier() { + return base64Url.encode(randomBytes(42)); + } + + Future generatePKCECodeChallenge(String codeVerifier) async { + var bytes = utf8.encode(codeVerifier); + var digest = sha256.convert(bytes); + return base64Url.encode(digest.bytes).replaceAll('=', ''); + } + oAuthLogin() async { var oAuthService = ref.watch(oAuthServiceProvider); String? oAuthServerUrl; + final state = generateRandomString(32); + + final codeVerifier = randomCodeVerifier(); + final codeChallenge = await generatePKCECodeChallenge(codeVerifier); + try { - oAuthServerUrl = await oAuthService - .getOAuthServerUrl(sanitizeUrl(serverEndpointController.text)); + oAuthServerUrl = await oAuthService.getOAuthServerUrl( + sanitizeUrl(serverEndpointController.text), + state, + codeChallenge, + ); isLoading.value = true; @@ -230,8 +271,11 @@ class LoginForm extends HookConsumerWidget { if (oAuthServerUrl != null) { try { - final loginResponseDto = - await oAuthService.oAuthLogin(oAuthServerUrl); + final loginResponseDto = await oAuthService.oAuthLogin( + oAuthServerUrl, + state, + codeVerifier, + ); if (loginResponseDto == null) { return; diff --git a/mobile/lib/widgets/map/map_asset_grid.dart b/mobile/lib/widgets/map/map_asset_grid.dart index 18003cf293..a9ddc86df9 100644 --- a/mobile/lib/widgets/map/map_asset_grid.dart +++ b/mobile/lib/widgets/map/map_asset_grid.dart @@ -46,12 +46,39 @@ class MapAssetGrid extends HookConsumerWidget { final gridScrollThrottler = useThrottler(interval: const Duration(milliseconds: 300)); + // Add a cache for assets we've already loaded + final assetCache = useRef>({}); + void handleMapEvents(MapEvent event) async { if (event is MapAssetsInBoundsUpdated) { - assetsInBounds.value = await ref - .read(dbProvider) - .assets - .getAllByRemoteId(event.assetRemoteIds); + final assetIds = event.assetRemoteIds; + final missingIds = []; + final currentAssets = []; + + for (final id in assetIds) { + final asset = assetCache.value[id]; + if (asset != null) { + currentAssets.add(asset); + } else { + missingIds.add(id); + } + } + + // Only fetch missing assets + if (missingIds.isNotEmpty) { + final newAssets = + await ref.read(dbProvider).assets.getAllByRemoteId(missingIds); + + // Add new assets to cache and current list + for (final asset in newAssets) { + if (asset.remoteId != null) { + assetCache.value[asset.remoteId!] = asset; + currentAssets.add(asset); + } + } + } + + assetsInBounds.value = currentAssets; return; } } @@ -124,7 +151,7 @@ class MapAssetGrid extends HookConsumerWidget { alignment: Alignment.bottomCenter, child: FractionallySizedBox( // Place it just below the drag handle - heightFactor: 0.80, + heightFactor: 0.87, child: assetsInBounds.value.isNotEmpty ? ref .watch(assetsTimelineProvider(assetsInBounds.value)) @@ -251,8 +278,18 @@ class _MapSheetDragRegion extends StatelessWidget { const SizedBox(height: 15), const CustomDraggingHandle(), const SizedBox(height: 15), - Text(assetsInBoundsText, style: context.textTheme.bodyLarge), - const Divider(height: 35), + Center( + child: Text( + assetsInBoundsText, + style: TextStyle( + fontSize: 20, + color: context.textTheme.displayLarge?.color + ?.withValues(alpha: 0.75), + fontWeight: FontWeight.w500, + ), + ), + ), + const SizedBox(height: 8), ], ), ValueListenableBuilder( @@ -260,14 +297,14 @@ class _MapSheetDragRegion extends StatelessWidget { builder: (_, value, __) => Visibility( visible: value != null, child: Positioned( - right: 15, - top: 15, + right: 18, + top: 24, child: IconButton( icon: Icon( Icons.map_outlined, color: context.textTheme.displayLarge?.color, ), - iconSize: 20, + iconSize: 24, tooltip: 'Zoom to bounds', onPressed: () => onZoomToAsset?.call(value!), ), diff --git a/mobile/lib/widgets/search/search_map_thumbnail.dart b/mobile/lib/widgets/search/search_map_thumbnail.dart index b4a12ab826..78af8f936b 100644 --- a/mobile/lib/widgets/search/search_map_thumbnail.dart +++ b/mobile/lib/widgets/search/search_map_thumbnail.dart @@ -20,7 +20,7 @@ class SearchMapThumbnail extends StatelessWidget { return ThumbnailWithInfoContainer( label: 'search_page_your_map'.tr(), onTap: () { - context.pushRoute(const MapRoute()); + context.pushRoute(MapRoute()); }, child: IgnorePointer( child: MapThumbnail( diff --git a/mobile/lib/widgets/settings/advanced_settings.dart b/mobile/lib/widgets/settings/advanced_settings.dart index 98c8728298..d65186a191 100644 --- a/mobile/lib/widgets/settings/advanced_settings.dart +++ b/mobile/lib/widgets/settings/advanced_settings.dart @@ -49,7 +49,7 @@ class AdvancedSettings extends HookConsumerWidget { DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; int sdkVersion = androidInfo.version.sdkInt; - return sdkVersion >= 30; + return sdkVersion >= 31; } return false; } @@ -74,7 +74,7 @@ class AdvancedSettings extends HookConsumerWidget { if (value) { final result = await ref .read(localFilesManagerRepositoryProvider) - .requestManageStoragePermission(); + .requestManageMediaPermission(); manageLocalMediaAndroid.value = result; } }, diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md index 0ae07e9efd..a4fbbf371a 100644 --- a/mobile/openapi/README.md +++ b/mobile/openapi/README.md @@ -3,7 +3,7 @@ Immich API This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: -- API version: 1.131.3 +- API version: 1.132.3 - Generator version: 7.8.0 - Build package: org.openapitools.codegen.languages.DartClientCodegen @@ -122,9 +122,6 @@ Class | Method | HTTP request | Description *FacesApi* | [**deleteFace**](doc//FacesApi.md#deleteface) | **DELETE** /faces/{id} | *FacesApi* | [**getFaces**](doc//FacesApi.md#getfaces) | **GET** /faces | *FacesApi* | [**reassignFacesById**](doc//FacesApi.md#reassignfacesbyid) | **PUT** /faces/{id} | -*FileReportsApi* | [**fixAuditFiles**](doc//FileReportsApi.md#fixauditfiles) | **POST** /reports/fix | -*FileReportsApi* | [**getAuditFiles**](doc//FileReportsApi.md#getauditfiles) | **GET** /reports | -*FileReportsApi* | [**getFileChecksums**](doc//FileReportsApi.md#getfilechecksums) | **POST** /reports/checksum | *JobsApi* | [**createJob**](doc//JobsApi.md#createjob) | **POST** /jobs | *JobsApi* | [**getAllJobsStatus**](doc//JobsApi.md#getalljobsstatus) | **GET** /jobs | *JobsApi* | [**sendJobCommand**](doc//JobsApi.md#sendjobcommand) | **PUT** /jobs/{id} | @@ -145,8 +142,15 @@ Class | Method | HTTP request | Description *MemoriesApi* | [**removeMemoryAssets**](doc//MemoriesApi.md#removememoryassets) | **DELETE** /memories/{id}/assets | *MemoriesApi* | [**searchMemories**](doc//MemoriesApi.md#searchmemories) | **GET** /memories | *MemoriesApi* | [**updateMemory**](doc//MemoriesApi.md#updatememory) | **PUT** /memories/{id} | -*NotificationsApi* | [**getNotificationTemplate**](doc//NotificationsApi.md#getnotificationtemplate) | **POST** /notifications/templates/{name} | -*NotificationsApi* | [**sendTestEmail**](doc//NotificationsApi.md#sendtestemail) | **POST** /notifications/test-email | +*NotificationsApi* | [**deleteNotification**](doc//NotificationsApi.md#deletenotification) | **DELETE** /notifications/{id} | +*NotificationsApi* | [**deleteNotifications**](doc//NotificationsApi.md#deletenotifications) | **DELETE** /notifications | +*NotificationsApi* | [**getNotification**](doc//NotificationsApi.md#getnotification) | **GET** /notifications/{id} | +*NotificationsApi* | [**getNotifications**](doc//NotificationsApi.md#getnotifications) | **GET** /notifications | +*NotificationsApi* | [**updateNotification**](doc//NotificationsApi.md#updatenotification) | **PUT** /notifications/{id} | +*NotificationsApi* | [**updateNotifications**](doc//NotificationsApi.md#updatenotifications) | **PUT** /notifications | +*NotificationsAdminApi* | [**createNotification**](doc//NotificationsAdminApi.md#createnotification) | **POST** /admin/notifications | +*NotificationsAdminApi* | [**getNotificationTemplateAdmin**](doc//NotificationsAdminApi.md#getnotificationtemplateadmin) | **POST** /admin/notifications/templates/{name} | +*NotificationsAdminApi* | [**sendTestEmailAdmin**](doc//NotificationsAdminApi.md#sendtestemailadmin) | **POST** /admin/notifications/test-email | *OAuthApi* | [**finishOAuth**](doc//OAuthApi.md#finishoauth) | **POST** /oauth/callback | *OAuthApi* | [**linkOAuthAccount**](doc//OAuthApi.md#linkoauthaccount) | **POST** /oauth/link | *OAuthApi* | [**redirectOAuthToMobile**](doc//OAuthApi.md#redirectoauthtomobile) | **GET** /oauth/mobile-redirect | @@ -300,7 +304,6 @@ Class | Method | HTTP request | Description - [AssetStatsResponseDto](doc//AssetStatsResponseDto.md) - [AssetTypeEnum](doc//AssetTypeEnum.md) - [AudioCodec](doc//AudioCodec.md) - - [AvatarResponse](doc//AvatarResponse.md) - [AvatarUpdate](doc//AvatarUpdate.md) - [BulkIdResponseDto](doc//BulkIdResponseDto.md) - [BulkIdsDto](doc//BulkIdsDto.md) @@ -326,11 +329,6 @@ Class | Method | HTTP request | Description - [ExifResponseDto](doc//ExifResponseDto.md) - [FaceDto](doc//FaceDto.md) - [FacialRecognitionConfig](doc//FacialRecognitionConfig.md) - - [FileChecksumDto](doc//FileChecksumDto.md) - - [FileChecksumResponseDto](doc//FileChecksumResponseDto.md) - - [FileReportDto](doc//FileReportDto.md) - - [FileReportFixDto](doc//FileReportFixDto.md) - - [FileReportItemDto](doc//FileReportItemDto.md) - [FoldersResponse](doc//FoldersResponse.md) - [FoldersUpdate](doc//FoldersUpdate.md) - [ImageFormat](doc//ImageFormat.md) @@ -361,14 +359,20 @@ Class | Method | HTTP request | Description - [MemoryUpdateDto](doc//MemoryUpdateDto.md) - [MergePersonDto](doc//MergePersonDto.md) - [MetadataSearchDto](doc//MetadataSearchDto.md) + - [NotificationCreateDto](doc//NotificationCreateDto.md) + - [NotificationDeleteAllDto](doc//NotificationDeleteAllDto.md) + - [NotificationDto](doc//NotificationDto.md) + - [NotificationLevel](doc//NotificationLevel.md) + - [NotificationType](doc//NotificationType.md) + - [NotificationUpdateAllDto](doc//NotificationUpdateAllDto.md) + - [NotificationUpdateDto](doc//NotificationUpdateDto.md) - [OAuthAuthorizeResponseDto](doc//OAuthAuthorizeResponseDto.md) - [OAuthCallbackDto](doc//OAuthCallbackDto.md) - [OAuthConfigDto](doc//OAuthConfigDto.md) + - [OAuthTokenEndpointAuthMethod](doc//OAuthTokenEndpointAuthMethod.md) - [OnThisDayDto](doc//OnThisDayDto.md) - [PartnerDirection](doc//PartnerDirection.md) - [PartnerResponseDto](doc//PartnerResponseDto.md) - - [PathEntityType](doc//PathEntityType.md) - - [PathType](doc//PathType.md) - [PeopleResponse](doc//PeopleResponse.md) - [PeopleResponseDto](doc//PeopleResponseDto.md) - [PeopleUpdate](doc//PeopleUpdate.md) diff --git a/mobile/openapi/lib/api.dart b/mobile/openapi/lib/api.dart index 3986362c96..78fa31691d 100644 --- a/mobile/openapi/lib/api.dart +++ b/mobile/openapi/lib/api.dart @@ -39,12 +39,12 @@ part 'api/deprecated_api.dart'; part 'api/download_api.dart'; part 'api/duplicates_api.dart'; part 'api/faces_api.dart'; -part 'api/file_reports_api.dart'; part 'api/jobs_api.dart'; part 'api/libraries_api.dart'; part 'api/map_api.dart'; part 'api/memories_api.dart'; part 'api/notifications_api.dart'; +part 'api/notifications_admin_api.dart'; part 'api/o_auth_api.dart'; part 'api/partners_api.dart'; part 'api/people_api.dart'; @@ -107,7 +107,6 @@ part 'model/asset_stack_response_dto.dart'; part 'model/asset_stats_response_dto.dart'; part 'model/asset_type_enum.dart'; part 'model/audio_codec.dart'; -part 'model/avatar_response.dart'; part 'model/avatar_update.dart'; part 'model/bulk_id_response_dto.dart'; part 'model/bulk_ids_dto.dart'; @@ -133,11 +132,6 @@ part 'model/email_notifications_update.dart'; part 'model/exif_response_dto.dart'; part 'model/face_dto.dart'; part 'model/facial_recognition_config.dart'; -part 'model/file_checksum_dto.dart'; -part 'model/file_checksum_response_dto.dart'; -part 'model/file_report_dto.dart'; -part 'model/file_report_fix_dto.dart'; -part 'model/file_report_item_dto.dart'; part 'model/folders_response.dart'; part 'model/folders_update.dart'; part 'model/image_format.dart'; @@ -168,14 +162,20 @@ part 'model/memory_type.dart'; part 'model/memory_update_dto.dart'; part 'model/merge_person_dto.dart'; part 'model/metadata_search_dto.dart'; +part 'model/notification_create_dto.dart'; +part 'model/notification_delete_all_dto.dart'; +part 'model/notification_dto.dart'; +part 'model/notification_level.dart'; +part 'model/notification_type.dart'; +part 'model/notification_update_all_dto.dart'; +part 'model/notification_update_dto.dart'; part 'model/o_auth_authorize_response_dto.dart'; part 'model/o_auth_callback_dto.dart'; part 'model/o_auth_config_dto.dart'; +part 'model/o_auth_token_endpoint_auth_method.dart'; part 'model/on_this_day_dto.dart'; part 'model/partner_direction.dart'; part 'model/partner_response_dto.dart'; -part 'model/path_entity_type.dart'; -part 'model/path_type.dart'; part 'model/people_response.dart'; part 'model/people_response_dto.dart'; part 'model/people_update.dart'; diff --git a/mobile/openapi/lib/api/file_reports_api.dart b/mobile/openapi/lib/api/notifications_admin_api.dart similarity index 51% rename from mobile/openapi/lib/api/file_reports_api.dart rename to mobile/openapi/lib/api/notifications_admin_api.dart index 73b3feaedb..409683a950 100644 --- a/mobile/openapi/lib/api/file_reports_api.dart +++ b/mobile/openapi/lib/api/notifications_admin_api.dart @@ -11,21 +11,21 @@ part of openapi.api; -class FileReportsApi { - FileReportsApi([ApiClient? apiClient]) : apiClient = apiClient ?? defaultApiClient; +class NotificationsAdminApi { + NotificationsAdminApi([ApiClient? apiClient]) : apiClient = apiClient ?? defaultApiClient; final ApiClient apiClient; - /// Performs an HTTP 'POST /reports/fix' operation and returns the [Response]. + /// Performs an HTTP 'POST /admin/notifications' operation and returns the [Response]. /// Parameters: /// - /// * [FileReportFixDto] fileReportFixDto (required): - Future fixAuditFilesWithHttpInfo(FileReportFixDto fileReportFixDto,) async { + /// * [NotificationCreateDto] notificationCreateDto (required): + Future createNotificationWithHttpInfo(NotificationCreateDto notificationCreateDto,) async { // ignore: prefer_const_declarations - final apiPath = r'/reports/fix'; + final apiPath = r'/admin/notifications'; // ignore: prefer_final_locals - Object? postBody = fileReportFixDto; + Object? postBody = notificationCreateDto; final queryParams = []; final headerParams = {}; @@ -47,42 +47,9 @@ class FileReportsApi { /// Parameters: /// - /// * [FileReportFixDto] fileReportFixDto (required): - Future fixAuditFiles(FileReportFixDto fileReportFixDto,) async { - final response = await fixAuditFilesWithHttpInfo(fileReportFixDto,); - if (response.statusCode >= HttpStatus.badRequest) { - throw ApiException(response.statusCode, await _decodeBodyBytes(response)); - } - } - - /// Performs an HTTP 'GET /reports' operation and returns the [Response]. - Future getAuditFilesWithHttpInfo() async { - // ignore: prefer_const_declarations - final apiPath = r'/reports'; - - // ignore: prefer_final_locals - Object? postBody; - - final queryParams = []; - final headerParams = {}; - final formParams = {}; - - const contentTypes = []; - - - return apiClient.invokeAPI( - apiPath, - 'GET', - queryParams, - postBody, - headerParams, - formParams, - contentTypes.isEmpty ? null : contentTypes.first, - ); - } - - Future getAuditFiles() async { - final response = await getAuditFilesWithHttpInfo(); + /// * [NotificationCreateDto] notificationCreateDto (required): + Future createNotification(NotificationCreateDto notificationCreateDto,) async { + final response = await createNotificationWithHttpInfo(notificationCreateDto,); if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, await _decodeBodyBytes(response)); } @@ -90,22 +57,25 @@ class FileReportsApi { // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" // FormatException when trying to decode an empty string. if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) { - return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'FileReportDto',) as FileReportDto; + return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'NotificationDto',) as NotificationDto; } return null; } - /// Performs an HTTP 'POST /reports/checksum' operation and returns the [Response]. + /// Performs an HTTP 'POST /admin/notifications/templates/{name}' operation and returns the [Response]. /// Parameters: /// - /// * [FileChecksumDto] fileChecksumDto (required): - Future getFileChecksumsWithHttpInfo(FileChecksumDto fileChecksumDto,) async { + /// * [String] name (required): + /// + /// * [TemplateDto] templateDto (required): + Future getNotificationTemplateAdminWithHttpInfo(String name, TemplateDto templateDto,) async { // ignore: prefer_const_declarations - final apiPath = r'/reports/checksum'; + final apiPath = r'/admin/notifications/templates/{name}' + .replaceAll('{name}', name); // ignore: prefer_final_locals - Object? postBody = fileChecksumDto; + Object? postBody = templateDto; final queryParams = []; final headerParams = {}; @@ -127,9 +97,11 @@ class FileReportsApi { /// Parameters: /// - /// * [FileChecksumDto] fileChecksumDto (required): - Future?> getFileChecksums(FileChecksumDto fileChecksumDto,) async { - final response = await getFileChecksumsWithHttpInfo(fileChecksumDto,); + /// * [String] name (required): + /// + /// * [TemplateDto] templateDto (required): + Future getNotificationTemplateAdmin(String name, TemplateDto templateDto,) async { + final response = await getNotificationTemplateAdminWithHttpInfo(name, templateDto,); if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, await _decodeBodyBytes(response)); } @@ -137,11 +109,55 @@ class FileReportsApi { // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" // FormatException when trying to decode an empty string. if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) { - final responseBody = await _decodeBodyBytes(response); - return (await apiClient.deserializeAsync(responseBody, 'List') as List) - .cast() - .toList(growable: false); + return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'TemplateResponseDto',) as TemplateResponseDto; + + } + return null; + } + /// Performs an HTTP 'POST /admin/notifications/test-email' operation and returns the [Response]. + /// Parameters: + /// + /// * [SystemConfigSmtpDto] systemConfigSmtpDto (required): + Future sendTestEmailAdminWithHttpInfo(SystemConfigSmtpDto systemConfigSmtpDto,) async { + // ignore: prefer_const_declarations + final apiPath = r'/admin/notifications/test-email'; + + // ignore: prefer_final_locals + Object? postBody = systemConfigSmtpDto; + + final queryParams = []; + final headerParams = {}; + final formParams = {}; + + const contentTypes = ['application/json']; + + + return apiClient.invokeAPI( + apiPath, + 'POST', + queryParams, + postBody, + headerParams, + formParams, + contentTypes.isEmpty ? null : contentTypes.first, + ); + } + + /// Parameters: + /// + /// * [SystemConfigSmtpDto] systemConfigSmtpDto (required): + Future sendTestEmailAdmin(SystemConfigSmtpDto systemConfigSmtpDto,) async { + final response = await sendTestEmailAdminWithHttpInfo(systemConfigSmtpDto,); + if (response.statusCode >= HttpStatus.badRequest) { + throw ApiException(response.statusCode, await _decodeBodyBytes(response)); + } + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) { + return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'TestEmailResponseDto',) as TestEmailResponseDto; + } return null; } diff --git a/mobile/openapi/lib/api/notifications_api.dart b/mobile/openapi/lib/api/notifications_api.dart index 518a1baa4a..501cc70a29 100644 --- a/mobile/openapi/lib/api/notifications_api.dart +++ b/mobile/openapi/lib/api/notifications_api.dart @@ -16,30 +16,28 @@ class NotificationsApi { final ApiClient apiClient; - /// Performs an HTTP 'POST /notifications/templates/{name}' operation and returns the [Response]. + /// Performs an HTTP 'DELETE /notifications/{id}' operation and returns the [Response]. /// Parameters: /// - /// * [String] name (required): - /// - /// * [TemplateDto] templateDto (required): - Future getNotificationTemplateWithHttpInfo(String name, TemplateDto templateDto,) async { + /// * [String] id (required): + Future deleteNotificationWithHttpInfo(String id,) async { // ignore: prefer_const_declarations - final apiPath = r'/notifications/templates/{name}' - .replaceAll('{name}', name); + final apiPath = r'/notifications/{id}' + .replaceAll('{id}', id); // ignore: prefer_final_locals - Object? postBody = templateDto; + Object? postBody; final queryParams = []; final headerParams = {}; final formParams = {}; - const contentTypes = ['application/json']; + const contentTypes = []; return apiClient.invokeAPI( apiPath, - 'POST', + 'DELETE', queryParams, postBody, headerParams, @@ -50,34 +48,24 @@ class NotificationsApi { /// Parameters: /// - /// * [String] name (required): - /// - /// * [TemplateDto] templateDto (required): - Future getNotificationTemplate(String name, TemplateDto templateDto,) async { - final response = await getNotificationTemplateWithHttpInfo(name, templateDto,); + /// * [String] id (required): + Future deleteNotification(String id,) async { + final response = await deleteNotificationWithHttpInfo(id,); if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, await _decodeBodyBytes(response)); } - // When a remote server returns no body with a status of 204, we shall not decode it. - // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" - // FormatException when trying to decode an empty string. - if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) { - return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'TemplateResponseDto',) as TemplateResponseDto; - - } - return null; } - /// Performs an HTTP 'POST /notifications/test-email' operation and returns the [Response]. + /// Performs an HTTP 'DELETE /notifications' operation and returns the [Response]. /// Parameters: /// - /// * [SystemConfigSmtpDto] systemConfigSmtpDto (required): - Future sendTestEmailWithHttpInfo(SystemConfigSmtpDto systemConfigSmtpDto,) async { + /// * [NotificationDeleteAllDto] notificationDeleteAllDto (required): + Future deleteNotificationsWithHttpInfo(NotificationDeleteAllDto notificationDeleteAllDto,) async { // ignore: prefer_const_declarations - final apiPath = r'/notifications/test-email'; + final apiPath = r'/notifications'; // ignore: prefer_final_locals - Object? postBody = systemConfigSmtpDto; + Object? postBody = notificationDeleteAllDto; final queryParams = []; final headerParams = {}; @@ -88,7 +76,7 @@ class NotificationsApi { return apiClient.invokeAPI( apiPath, - 'POST', + 'DELETE', queryParams, postBody, headerParams, @@ -99,9 +87,49 @@ class NotificationsApi { /// Parameters: /// - /// * [SystemConfigSmtpDto] systemConfigSmtpDto (required): - Future sendTestEmail(SystemConfigSmtpDto systemConfigSmtpDto,) async { - final response = await sendTestEmailWithHttpInfo(systemConfigSmtpDto,); + /// * [NotificationDeleteAllDto] notificationDeleteAllDto (required): + Future deleteNotifications(NotificationDeleteAllDto notificationDeleteAllDto,) async { + final response = await deleteNotificationsWithHttpInfo(notificationDeleteAllDto,); + if (response.statusCode >= HttpStatus.badRequest) { + throw ApiException(response.statusCode, await _decodeBodyBytes(response)); + } + } + + /// Performs an HTTP 'GET /notifications/{id}' operation and returns the [Response]. + /// Parameters: + /// + /// * [String] id (required): + Future getNotificationWithHttpInfo(String id,) async { + // ignore: prefer_const_declarations + final apiPath = r'/notifications/{id}' + .replaceAll('{id}', id); + + // ignore: prefer_final_locals + Object? postBody; + + final queryParams = []; + final headerParams = {}; + final formParams = {}; + + const contentTypes = []; + + + return apiClient.invokeAPI( + apiPath, + 'GET', + queryParams, + postBody, + headerParams, + formParams, + contentTypes.isEmpty ? null : contentTypes.first, + ); + } + + /// Parameters: + /// + /// * [String] id (required): + Future getNotification(String id,) async { + final response = await getNotificationWithHttpInfo(id,); if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, await _decodeBodyBytes(response)); } @@ -109,9 +137,175 @@ class NotificationsApi { // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" // FormatException when trying to decode an empty string. if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) { - return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'TestEmailResponseDto',) as TestEmailResponseDto; + return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'NotificationDto',) as NotificationDto; } return null; } + + /// Performs an HTTP 'GET /notifications' operation and returns the [Response]. + /// Parameters: + /// + /// * [String] id: + /// + /// * [NotificationLevel] level: + /// + /// * [NotificationType] type: + /// + /// * [bool] unread: + Future getNotificationsWithHttpInfo({ String? id, NotificationLevel? level, NotificationType? type, bool? unread, }) async { + // ignore: prefer_const_declarations + final apiPath = r'/notifications'; + + // ignore: prefer_final_locals + Object? postBody; + + final queryParams = []; + final headerParams = {}; + final formParams = {}; + + if (id != null) { + queryParams.addAll(_queryParams('', 'id', id)); + } + if (level != null) { + queryParams.addAll(_queryParams('', 'level', level)); + } + if (type != null) { + queryParams.addAll(_queryParams('', 'type', type)); + } + if (unread != null) { + queryParams.addAll(_queryParams('', 'unread', unread)); + } + + const contentTypes = []; + + + return apiClient.invokeAPI( + apiPath, + 'GET', + queryParams, + postBody, + headerParams, + formParams, + contentTypes.isEmpty ? null : contentTypes.first, + ); + } + + /// Parameters: + /// + /// * [String] id: + /// + /// * [NotificationLevel] level: + /// + /// * [NotificationType] type: + /// + /// * [bool] unread: + Future?> getNotifications({ String? id, NotificationLevel? level, NotificationType? type, bool? unread, }) async { + final response = await getNotificationsWithHttpInfo( id: id, level: level, type: type, unread: unread, ); + if (response.statusCode >= HttpStatus.badRequest) { + throw ApiException(response.statusCode, await _decodeBodyBytes(response)); + } + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) { + final responseBody = await _decodeBodyBytes(response); + return (await apiClient.deserializeAsync(responseBody, 'List') as List) + .cast() + .toList(growable: false); + + } + return null; + } + + /// Performs an HTTP 'PUT /notifications/{id}' operation and returns the [Response]. + /// Parameters: + /// + /// * [String] id (required): + /// + /// * [NotificationUpdateDto] notificationUpdateDto (required): + Future updateNotificationWithHttpInfo(String id, NotificationUpdateDto notificationUpdateDto,) async { + // ignore: prefer_const_declarations + final apiPath = r'/notifications/{id}' + .replaceAll('{id}', id); + + // ignore: prefer_final_locals + Object? postBody = notificationUpdateDto; + + final queryParams = []; + final headerParams = {}; + final formParams = {}; + + const contentTypes = ['application/json']; + + + return apiClient.invokeAPI( + apiPath, + 'PUT', + queryParams, + postBody, + headerParams, + formParams, + contentTypes.isEmpty ? null : contentTypes.first, + ); + } + + /// Parameters: + /// + /// * [String] id (required): + /// + /// * [NotificationUpdateDto] notificationUpdateDto (required): + Future updateNotification(String id, NotificationUpdateDto notificationUpdateDto,) async { + final response = await updateNotificationWithHttpInfo(id, notificationUpdateDto,); + if (response.statusCode >= HttpStatus.badRequest) { + throw ApiException(response.statusCode, await _decodeBodyBytes(response)); + } + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) { + return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'NotificationDto',) as NotificationDto; + + } + return null; + } + + /// Performs an HTTP 'PUT /notifications' operation and returns the [Response]. + /// Parameters: + /// + /// * [NotificationUpdateAllDto] notificationUpdateAllDto (required): + Future updateNotificationsWithHttpInfo(NotificationUpdateAllDto notificationUpdateAllDto,) async { + // ignore: prefer_const_declarations + final apiPath = r'/notifications'; + + // ignore: prefer_final_locals + Object? postBody = notificationUpdateAllDto; + + final queryParams = []; + final headerParams = {}; + final formParams = {}; + + const contentTypes = ['application/json']; + + + return apiClient.invokeAPI( + apiPath, + 'PUT', + queryParams, + postBody, + headerParams, + formParams, + contentTypes.isEmpty ? null : contentTypes.first, + ); + } + + /// Parameters: + /// + /// * [NotificationUpdateAllDto] notificationUpdateAllDto (required): + Future updateNotifications(NotificationUpdateAllDto notificationUpdateAllDto,) async { + final response = await updateNotificationsWithHttpInfo(notificationUpdateAllDto,); + if (response.statusCode >= HttpStatus.badRequest) { + throw ApiException(response.statusCode, await _decodeBodyBytes(response)); + } + } } diff --git a/mobile/openapi/lib/api_client.dart b/mobile/openapi/lib/api_client.dart index 5759217f41..9d0e80e58b 100644 --- a/mobile/openapi/lib/api_client.dart +++ b/mobile/openapi/lib/api_client.dart @@ -270,8 +270,6 @@ class ApiClient { return AssetTypeEnumTypeTransformer().decode(value); case 'AudioCodec': return AudioCodecTypeTransformer().decode(value); - case 'AvatarResponse': - return AvatarResponse.fromJson(value); case 'AvatarUpdate': return AvatarUpdate.fromJson(value); case 'BulkIdResponseDto': @@ -322,16 +320,6 @@ class ApiClient { return FaceDto.fromJson(value); case 'FacialRecognitionConfig': return FacialRecognitionConfig.fromJson(value); - case 'FileChecksumDto': - return FileChecksumDto.fromJson(value); - case 'FileChecksumResponseDto': - return FileChecksumResponseDto.fromJson(value); - case 'FileReportDto': - return FileReportDto.fromJson(value); - case 'FileReportFixDto': - return FileReportFixDto.fromJson(value); - case 'FileReportItemDto': - return FileReportItemDto.fromJson(value); case 'FoldersResponse': return FoldersResponse.fromJson(value); case 'FoldersUpdate': @@ -392,22 +380,34 @@ class ApiClient { return MergePersonDto.fromJson(value); case 'MetadataSearchDto': return MetadataSearchDto.fromJson(value); + case 'NotificationCreateDto': + return NotificationCreateDto.fromJson(value); + case 'NotificationDeleteAllDto': + return NotificationDeleteAllDto.fromJson(value); + case 'NotificationDto': + return NotificationDto.fromJson(value); + case 'NotificationLevel': + return NotificationLevelTypeTransformer().decode(value); + case 'NotificationType': + return NotificationTypeTypeTransformer().decode(value); + case 'NotificationUpdateAllDto': + return NotificationUpdateAllDto.fromJson(value); + case 'NotificationUpdateDto': + return NotificationUpdateDto.fromJson(value); case 'OAuthAuthorizeResponseDto': return OAuthAuthorizeResponseDto.fromJson(value); case 'OAuthCallbackDto': return OAuthCallbackDto.fromJson(value); case 'OAuthConfigDto': return OAuthConfigDto.fromJson(value); + case 'OAuthTokenEndpointAuthMethod': + return OAuthTokenEndpointAuthMethodTypeTransformer().decode(value); case 'OnThisDayDto': return OnThisDayDto.fromJson(value); case 'PartnerDirection': return PartnerDirectionTypeTransformer().decode(value); case 'PartnerResponseDto': return PartnerResponseDto.fromJson(value); - case 'PathEntityType': - return PathEntityTypeTypeTransformer().decode(value); - case 'PathType': - return PathTypeTypeTransformer().decode(value); case 'PeopleResponse': return PeopleResponse.fromJson(value); case 'PeopleResponseDto': diff --git a/mobile/openapi/lib/api_helper.dart b/mobile/openapi/lib/api_helper.dart index 1ebf8314ad..eec991e903 100644 --- a/mobile/openapi/lib/api_helper.dart +++ b/mobile/openapi/lib/api_helper.dart @@ -100,15 +100,18 @@ String parameterToString(dynamic value) { if (value is MemoryType) { return MemoryTypeTypeTransformer().encode(value).toString(); } + if (value is NotificationLevel) { + return NotificationLevelTypeTransformer().encode(value).toString(); + } + if (value is NotificationType) { + return NotificationTypeTypeTransformer().encode(value).toString(); + } + if (value is OAuthTokenEndpointAuthMethod) { + return OAuthTokenEndpointAuthMethodTypeTransformer().encode(value).toString(); + } if (value is PartnerDirection) { return PartnerDirectionTypeTransformer().encode(value).toString(); } - if (value is PathEntityType) { - return PathEntityTypeTypeTransformer().encode(value).toString(); - } - if (value is PathType) { - return PathTypeTypeTransformer().encode(value).toString(); - } if (value is Permission) { return PermissionTypeTransformer().encode(value).toString(); } diff --git a/mobile/openapi/lib/model/file_checksum_response_dto.dart b/mobile/openapi/lib/model/file_checksum_response_dto.dart deleted file mode 100644 index 7b963c8bd5..0000000000 --- a/mobile/openapi/lib/model/file_checksum_response_dto.dart +++ /dev/null @@ -1,107 +0,0 @@ -// -// AUTO-GENERATED FILE, DO NOT MODIFY! -// -// @dart=2.18 - -// ignore_for_file: unused_element, unused_import -// ignore_for_file: always_put_required_named_parameters_first -// ignore_for_file: constant_identifier_names -// ignore_for_file: lines_longer_than_80_chars - -part of openapi.api; - -class FileChecksumResponseDto { - /// Returns a new [FileChecksumResponseDto] instance. - FileChecksumResponseDto({ - required this.checksum, - required this.filename, - }); - - String checksum; - - String filename; - - @override - bool operator ==(Object other) => identical(this, other) || other is FileChecksumResponseDto && - other.checksum == checksum && - other.filename == filename; - - @override - int get hashCode => - // ignore: unnecessary_parenthesis - (checksum.hashCode) + - (filename.hashCode); - - @override - String toString() => 'FileChecksumResponseDto[checksum=$checksum, filename=$filename]'; - - Map toJson() { - final json = {}; - json[r'checksum'] = this.checksum; - json[r'filename'] = this.filename; - return json; - } - - /// Returns a new [FileChecksumResponseDto] instance and imports its values from - /// [value] if it's a [Map], null otherwise. - // ignore: prefer_constructors_over_static_methods - static FileChecksumResponseDto? fromJson(dynamic value) { - upgradeDto(value, "FileChecksumResponseDto"); - if (value is Map) { - final json = value.cast(); - - return FileChecksumResponseDto( - checksum: mapValueOfType(json, r'checksum')!, - filename: mapValueOfType(json, r'filename')!, - ); - } - return null; - } - - static List listFromJson(dynamic json, {bool growable = false,}) { - final result = []; - if (json is List && json.isNotEmpty) { - for (final row in json) { - final value = FileChecksumResponseDto.fromJson(row); - if (value != null) { - result.add(value); - } - } - } - return result.toList(growable: growable); - } - - static Map mapFromJson(dynamic json) { - final map = {}; - if (json is Map && json.isNotEmpty) { - json = json.cast(); // ignore: parameter_assignments - for (final entry in json.entries) { - final value = FileChecksumResponseDto.fromJson(entry.value); - if (value != null) { - map[entry.key] = value; - } - } - } - return map; - } - - // maps a json object with a list of FileChecksumResponseDto-objects as value to a dart map - static Map> mapListFromJson(dynamic json, {bool growable = false,}) { - final map = >{}; - if (json is Map && json.isNotEmpty) { - // ignore: parameter_assignments - json = json.cast(); - for (final entry in json.entries) { - map[entry.key] = FileChecksumResponseDto.listFromJson(entry.value, growable: growable,); - } - } - return map; - } - - /// The list of required keys that must be present in a JSON. - static const requiredKeys = { - 'checksum', - 'filename', - }; -} - diff --git a/mobile/openapi/lib/model/file_report_dto.dart b/mobile/openapi/lib/model/file_report_dto.dart deleted file mode 100644 index 3dc892e5e7..0000000000 --- a/mobile/openapi/lib/model/file_report_dto.dart +++ /dev/null @@ -1,109 +0,0 @@ -// -// AUTO-GENERATED FILE, DO NOT MODIFY! -// -// @dart=2.18 - -// ignore_for_file: unused_element, unused_import -// ignore_for_file: always_put_required_named_parameters_first -// ignore_for_file: constant_identifier_names -// ignore_for_file: lines_longer_than_80_chars - -part of openapi.api; - -class FileReportDto { - /// Returns a new [FileReportDto] instance. - FileReportDto({ - this.extras = const [], - this.orphans = const [], - }); - - List extras; - - List orphans; - - @override - bool operator ==(Object other) => identical(this, other) || other is FileReportDto && - _deepEquality.equals(other.extras, extras) && - _deepEquality.equals(other.orphans, orphans); - - @override - int get hashCode => - // ignore: unnecessary_parenthesis - (extras.hashCode) + - (orphans.hashCode); - - @override - String toString() => 'FileReportDto[extras=$extras, orphans=$orphans]'; - - Map toJson() { - final json = {}; - json[r'extras'] = this.extras; - json[r'orphans'] = this.orphans; - return json; - } - - /// Returns a new [FileReportDto] instance and imports its values from - /// [value] if it's a [Map], null otherwise. - // ignore: prefer_constructors_over_static_methods - static FileReportDto? fromJson(dynamic value) { - upgradeDto(value, "FileReportDto"); - if (value is Map) { - final json = value.cast(); - - return FileReportDto( - extras: json[r'extras'] is Iterable - ? (json[r'extras'] as Iterable).cast().toList(growable: false) - : const [], - orphans: FileReportItemDto.listFromJson(json[r'orphans']), - ); - } - return null; - } - - static List listFromJson(dynamic json, {bool growable = false,}) { - final result = []; - if (json is List && json.isNotEmpty) { - for (final row in json) { - final value = FileReportDto.fromJson(row); - if (value != null) { - result.add(value); - } - } - } - return result.toList(growable: growable); - } - - static Map mapFromJson(dynamic json) { - final map = {}; - if (json is Map && json.isNotEmpty) { - json = json.cast(); // ignore: parameter_assignments - for (final entry in json.entries) { - final value = FileReportDto.fromJson(entry.value); - if (value != null) { - map[entry.key] = value; - } - } - } - return map; - } - - // maps a json object with a list of FileReportDto-objects as value to a dart map - static Map> mapListFromJson(dynamic json, {bool growable = false,}) { - final map = >{}; - if (json is Map && json.isNotEmpty) { - // ignore: parameter_assignments - json = json.cast(); - for (final entry in json.entries) { - map[entry.key] = FileReportDto.listFromJson(entry.value, growable: growable,); - } - } - return map; - } - - /// The list of required keys that must be present in a JSON. - static const requiredKeys = { - 'extras', - 'orphans', - }; -} - diff --git a/mobile/openapi/lib/model/file_report_fix_dto.dart b/mobile/openapi/lib/model/file_report_fix_dto.dart deleted file mode 100644 index d46cdeb4b7..0000000000 --- a/mobile/openapi/lib/model/file_report_fix_dto.dart +++ /dev/null @@ -1,99 +0,0 @@ -// -// AUTO-GENERATED FILE, DO NOT MODIFY! -// -// @dart=2.18 - -// ignore_for_file: unused_element, unused_import -// ignore_for_file: always_put_required_named_parameters_first -// ignore_for_file: constant_identifier_names -// ignore_for_file: lines_longer_than_80_chars - -part of openapi.api; - -class FileReportFixDto { - /// Returns a new [FileReportFixDto] instance. - FileReportFixDto({ - this.items = const [], - }); - - List items; - - @override - bool operator ==(Object other) => identical(this, other) || other is FileReportFixDto && - _deepEquality.equals(other.items, items); - - @override - int get hashCode => - // ignore: unnecessary_parenthesis - (items.hashCode); - - @override - String toString() => 'FileReportFixDto[items=$items]'; - - Map toJson() { - final json = {}; - json[r'items'] = this.items; - return json; - } - - /// Returns a new [FileReportFixDto] instance and imports its values from - /// [value] if it's a [Map], null otherwise. - // ignore: prefer_constructors_over_static_methods - static FileReportFixDto? fromJson(dynamic value) { - upgradeDto(value, "FileReportFixDto"); - if (value is Map) { - final json = value.cast(); - - return FileReportFixDto( - items: FileReportItemDto.listFromJson(json[r'items']), - ); - } - return null; - } - - static List listFromJson(dynamic json, {bool growable = false,}) { - final result = []; - if (json is List && json.isNotEmpty) { - for (final row in json) { - final value = FileReportFixDto.fromJson(row); - if (value != null) { - result.add(value); - } - } - } - return result.toList(growable: growable); - } - - static Map mapFromJson(dynamic json) { - final map = {}; - if (json is Map && json.isNotEmpty) { - json = json.cast(); // ignore: parameter_assignments - for (final entry in json.entries) { - final value = FileReportFixDto.fromJson(entry.value); - if (value != null) { - map[entry.key] = value; - } - } - } - return map; - } - - // maps a json object with a list of FileReportFixDto-objects as value to a dart map - static Map> mapListFromJson(dynamic json, {bool growable = false,}) { - final map = >{}; - if (json is Map && json.isNotEmpty) { - // ignore: parameter_assignments - json = json.cast(); - for (final entry in json.entries) { - map[entry.key] = FileReportFixDto.listFromJson(entry.value, growable: growable,); - } - } - return map; - } - - /// The list of required keys that must be present in a JSON. - static const requiredKeys = { - 'items', - }; -} - diff --git a/mobile/openapi/lib/model/file_report_item_dto.dart b/mobile/openapi/lib/model/file_report_item_dto.dart deleted file mode 100644 index 1ef08c2b48..0000000000 --- a/mobile/openapi/lib/model/file_report_item_dto.dart +++ /dev/null @@ -1,140 +0,0 @@ -// -// AUTO-GENERATED FILE, DO NOT MODIFY! -// -// @dart=2.18 - -// ignore_for_file: unused_element, unused_import -// ignore_for_file: always_put_required_named_parameters_first -// ignore_for_file: constant_identifier_names -// ignore_for_file: lines_longer_than_80_chars - -part of openapi.api; - -class FileReportItemDto { - /// Returns a new [FileReportItemDto] instance. - FileReportItemDto({ - this.checksum, - required this.entityId, - required this.entityType, - required this.pathType, - required this.pathValue, - }); - - /// - /// Please note: This property should have been non-nullable! Since the specification file - /// does not include a default value (using the "default:" property), however, the generated - /// source code must fall back to having a nullable type. - /// Consider adding a "default:" property in the specification file to hide this note. - /// - String? checksum; - - String entityId; - - PathEntityType entityType; - - PathType pathType; - - String pathValue; - - @override - bool operator ==(Object other) => identical(this, other) || other is FileReportItemDto && - other.checksum == checksum && - other.entityId == entityId && - other.entityType == entityType && - other.pathType == pathType && - other.pathValue == pathValue; - - @override - int get hashCode => - // ignore: unnecessary_parenthesis - (checksum == null ? 0 : checksum!.hashCode) + - (entityId.hashCode) + - (entityType.hashCode) + - (pathType.hashCode) + - (pathValue.hashCode); - - @override - String toString() => 'FileReportItemDto[checksum=$checksum, entityId=$entityId, entityType=$entityType, pathType=$pathType, pathValue=$pathValue]'; - - Map toJson() { - final json = {}; - if (this.checksum != null) { - json[r'checksum'] = this.checksum; - } else { - // json[r'checksum'] = null; - } - json[r'entityId'] = this.entityId; - json[r'entityType'] = this.entityType; - json[r'pathType'] = this.pathType; - json[r'pathValue'] = this.pathValue; - return json; - } - - /// Returns a new [FileReportItemDto] instance and imports its values from - /// [value] if it's a [Map], null otherwise. - // ignore: prefer_constructors_over_static_methods - static FileReportItemDto? fromJson(dynamic value) { - upgradeDto(value, "FileReportItemDto"); - if (value is Map) { - final json = value.cast(); - - return FileReportItemDto( - checksum: mapValueOfType(json, r'checksum'), - entityId: mapValueOfType(json, r'entityId')!, - entityType: PathEntityType.fromJson(json[r'entityType'])!, - pathType: PathType.fromJson(json[r'pathType'])!, - pathValue: mapValueOfType(json, r'pathValue')!, - ); - } - return null; - } - - static List listFromJson(dynamic json, {bool growable = false,}) { - final result = []; - if (json is List && json.isNotEmpty) { - for (final row in json) { - final value = FileReportItemDto.fromJson(row); - if (value != null) { - result.add(value); - } - } - } - return result.toList(growable: growable); - } - - static Map mapFromJson(dynamic json) { - final map = {}; - if (json is Map && json.isNotEmpty) { - json = json.cast(); // ignore: parameter_assignments - for (final entry in json.entries) { - final value = FileReportItemDto.fromJson(entry.value); - if (value != null) { - map[entry.key] = value; - } - } - } - return map; - } - - // maps a json object with a list of FileReportItemDto-objects as value to a dart map - static Map> mapListFromJson(dynamic json, {bool growable = false,}) { - final map = >{}; - if (json is Map && json.isNotEmpty) { - // ignore: parameter_assignments - json = json.cast(); - for (final entry in json.entries) { - map[entry.key] = FileReportItemDto.listFromJson(entry.value, growable: growable,); - } - } - return map; - } - - /// The list of required keys that must be present in a JSON. - static const requiredKeys = { - 'entityId', - 'entityType', - 'pathType', - 'pathValue', - }; -} - diff --git a/mobile/openapi/lib/model/notification_create_dto.dart b/mobile/openapi/lib/model/notification_create_dto.dart new file mode 100644 index 0000000000..07985353b2 --- /dev/null +++ b/mobile/openapi/lib/model/notification_create_dto.dart @@ -0,0 +1,180 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.18 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class NotificationCreateDto { + /// Returns a new [NotificationCreateDto] instance. + NotificationCreateDto({ + this.data, + this.description, + this.level, + this.readAt, + required this.title, + this.type, + required this.userId, + }); + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + Object? data; + + String? description; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + NotificationLevel? level; + + DateTime? readAt; + + String title; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + NotificationType? type; + + String userId; + + @override + bool operator ==(Object other) => identical(this, other) || other is NotificationCreateDto && + other.data == data && + other.description == description && + other.level == level && + other.readAt == readAt && + other.title == title && + other.type == type && + other.userId == userId; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (data == null ? 0 : data!.hashCode) + + (description == null ? 0 : description!.hashCode) + + (level == null ? 0 : level!.hashCode) + + (readAt == null ? 0 : readAt!.hashCode) + + (title.hashCode) + + (type == null ? 0 : type!.hashCode) + + (userId.hashCode); + + @override + String toString() => 'NotificationCreateDto[data=$data, description=$description, level=$level, readAt=$readAt, title=$title, type=$type, userId=$userId]'; + + Map toJson() { + final json = {}; + if (this.data != null) { + json[r'data'] = this.data; + } else { + // json[r'data'] = null; + } + if (this.description != null) { + json[r'description'] = this.description; + } else { + // json[r'description'] = null; + } + if (this.level != null) { + json[r'level'] = this.level; + } else { + // json[r'level'] = null; + } + if (this.readAt != null) { + json[r'readAt'] = this.readAt!.toUtc().toIso8601String(); + } else { + // json[r'readAt'] = null; + } + json[r'title'] = this.title; + if (this.type != null) { + json[r'type'] = this.type; + } else { + // json[r'type'] = null; + } + json[r'userId'] = this.userId; + return json; + } + + /// Returns a new [NotificationCreateDto] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static NotificationCreateDto? fromJson(dynamic value) { + upgradeDto(value, "NotificationCreateDto"); + if (value is Map) { + final json = value.cast(); + + return NotificationCreateDto( + data: mapValueOfType(json, r'data'), + description: mapValueOfType(json, r'description'), + level: NotificationLevel.fromJson(json[r'level']), + readAt: mapDateTime(json, r'readAt', r''), + title: mapValueOfType(json, r'title')!, + type: NotificationType.fromJson(json[r'type']), + userId: mapValueOfType(json, r'userId')!, + ); + } + return null; + } + + static List listFromJson(dynamic json, {bool growable = false,}) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = NotificationCreateDto.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } + + static Map mapFromJson(dynamic json) { + final map = {}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = NotificationCreateDto.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of NotificationCreateDto-objects as value to a dart map + static Map> mapListFromJson(dynamic json, {bool growable = false,}) { + final map = >{}; + if (json is Map && json.isNotEmpty) { + // ignore: parameter_assignments + json = json.cast(); + for (final entry in json.entries) { + map[entry.key] = NotificationCreateDto.listFromJson(entry.value, growable: growable,); + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = { + 'title', + 'userId', + }; +} + diff --git a/mobile/openapi/lib/model/file_checksum_dto.dart b/mobile/openapi/lib/model/notification_delete_all_dto.dart similarity index 51% rename from mobile/openapi/lib/model/file_checksum_dto.dart rename to mobile/openapi/lib/model/notification_delete_all_dto.dart index 7dc9ccdf2f..4be1b89e92 100644 --- a/mobile/openapi/lib/model/file_checksum_dto.dart +++ b/mobile/openapi/lib/model/notification_delete_all_dto.dart @@ -10,54 +10,54 @@ part of openapi.api; -class FileChecksumDto { - /// Returns a new [FileChecksumDto] instance. - FileChecksumDto({ - this.filenames = const [], +class NotificationDeleteAllDto { + /// Returns a new [NotificationDeleteAllDto] instance. + NotificationDeleteAllDto({ + this.ids = const [], }); - List filenames; + List ids; @override - bool operator ==(Object other) => identical(this, other) || other is FileChecksumDto && - _deepEquality.equals(other.filenames, filenames); + bool operator ==(Object other) => identical(this, other) || other is NotificationDeleteAllDto && + _deepEquality.equals(other.ids, ids); @override int get hashCode => // ignore: unnecessary_parenthesis - (filenames.hashCode); + (ids.hashCode); @override - String toString() => 'FileChecksumDto[filenames=$filenames]'; + String toString() => 'NotificationDeleteAllDto[ids=$ids]'; Map toJson() { final json = {}; - json[r'filenames'] = this.filenames; + json[r'ids'] = this.ids; return json; } - /// Returns a new [FileChecksumDto] instance and imports its values from + /// Returns a new [NotificationDeleteAllDto] instance and imports its values from /// [value] if it's a [Map], null otherwise. // ignore: prefer_constructors_over_static_methods - static FileChecksumDto? fromJson(dynamic value) { - upgradeDto(value, "FileChecksumDto"); + static NotificationDeleteAllDto? fromJson(dynamic value) { + upgradeDto(value, "NotificationDeleteAllDto"); if (value is Map) { final json = value.cast(); - return FileChecksumDto( - filenames: json[r'filenames'] is Iterable - ? (json[r'filenames'] as Iterable).cast().toList(growable: false) + return NotificationDeleteAllDto( + ids: json[r'ids'] is Iterable + ? (json[r'ids'] as Iterable).cast().toList(growable: false) : const [], ); } return null; } - static List listFromJson(dynamic json, {bool growable = false,}) { - final result = []; + static List listFromJson(dynamic json, {bool growable = false,}) { + final result = []; if (json is List && json.isNotEmpty) { for (final row in json) { - final value = FileChecksumDto.fromJson(row); + final value = NotificationDeleteAllDto.fromJson(row); if (value != null) { result.add(value); } @@ -66,12 +66,12 @@ class FileChecksumDto { return result.toList(growable: growable); } - static Map mapFromJson(dynamic json) { - final map = {}; + static Map mapFromJson(dynamic json) { + final map = {}; if (json is Map && json.isNotEmpty) { json = json.cast(); // ignore: parameter_assignments for (final entry in json.entries) { - final value = FileChecksumDto.fromJson(entry.value); + final value = NotificationDeleteAllDto.fromJson(entry.value); if (value != null) { map[entry.key] = value; } @@ -80,14 +80,14 @@ class FileChecksumDto { return map; } - // maps a json object with a list of FileChecksumDto-objects as value to a dart map - static Map> mapListFromJson(dynamic json, {bool growable = false,}) { - final map = >{}; + // maps a json object with a list of NotificationDeleteAllDto-objects as value to a dart map + static Map> mapListFromJson(dynamic json, {bool growable = false,}) { + final map = >{}; if (json is Map && json.isNotEmpty) { // ignore: parameter_assignments json = json.cast(); for (final entry in json.entries) { - map[entry.key] = FileChecksumDto.listFromJson(entry.value, growable: growable,); + map[entry.key] = NotificationDeleteAllDto.listFromJson(entry.value, growable: growable,); } } return map; @@ -95,7 +95,7 @@ class FileChecksumDto { /// The list of required keys that must be present in a JSON. static const requiredKeys = { - 'filenames', + 'ids', }; } diff --git a/mobile/openapi/lib/model/notification_dto.dart b/mobile/openapi/lib/model/notification_dto.dart new file mode 100644 index 0000000000..4f730b4e50 --- /dev/null +++ b/mobile/openapi/lib/model/notification_dto.dart @@ -0,0 +1,182 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.18 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class NotificationDto { + /// Returns a new [NotificationDto] instance. + NotificationDto({ + required this.createdAt, + this.data, + this.description, + required this.id, + required this.level, + this.readAt, + required this.title, + required this.type, + }); + + DateTime createdAt; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + Object? data; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? description; + + String id; + + NotificationLevel level; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + DateTime? readAt; + + String title; + + NotificationType type; + + @override + bool operator ==(Object other) => identical(this, other) || other is NotificationDto && + other.createdAt == createdAt && + other.data == data && + other.description == description && + other.id == id && + other.level == level && + other.readAt == readAt && + other.title == title && + other.type == type; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (createdAt.hashCode) + + (data == null ? 0 : data!.hashCode) + + (description == null ? 0 : description!.hashCode) + + (id.hashCode) + + (level.hashCode) + + (readAt == null ? 0 : readAt!.hashCode) + + (title.hashCode) + + (type.hashCode); + + @override + String toString() => 'NotificationDto[createdAt=$createdAt, data=$data, description=$description, id=$id, level=$level, readAt=$readAt, title=$title, type=$type]'; + + Map toJson() { + final json = {}; + json[r'createdAt'] = this.createdAt.toUtc().toIso8601String(); + if (this.data != null) { + json[r'data'] = this.data; + } else { + // json[r'data'] = null; + } + if (this.description != null) { + json[r'description'] = this.description; + } else { + // json[r'description'] = null; + } + json[r'id'] = this.id; + json[r'level'] = this.level; + if (this.readAt != null) { + json[r'readAt'] = this.readAt!.toUtc().toIso8601String(); + } else { + // json[r'readAt'] = null; + } + json[r'title'] = this.title; + json[r'type'] = this.type; + return json; + } + + /// Returns a new [NotificationDto] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static NotificationDto? fromJson(dynamic value) { + upgradeDto(value, "NotificationDto"); + if (value is Map) { + final json = value.cast(); + + return NotificationDto( + createdAt: mapDateTime(json, r'createdAt', r'')!, + data: mapValueOfType(json, r'data'), + description: mapValueOfType(json, r'description'), + id: mapValueOfType(json, r'id')!, + level: NotificationLevel.fromJson(json[r'level'])!, + readAt: mapDateTime(json, r'readAt', r''), + title: mapValueOfType(json, r'title')!, + type: NotificationType.fromJson(json[r'type'])!, + ); + } + return null; + } + + static List listFromJson(dynamic json, {bool growable = false,}) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = NotificationDto.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } + + static Map mapFromJson(dynamic json) { + final map = {}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = NotificationDto.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of NotificationDto-objects as value to a dart map + static Map> mapListFromJson(dynamic json, {bool growable = false,}) { + final map = >{}; + if (json is Map && json.isNotEmpty) { + // ignore: parameter_assignments + json = json.cast(); + for (final entry in json.entries) { + map[entry.key] = NotificationDto.listFromJson(entry.value, growable: growable,); + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = { + 'createdAt', + 'id', + 'level', + 'title', + 'type', + }; +} + diff --git a/mobile/openapi/lib/model/notification_level.dart b/mobile/openapi/lib/model/notification_level.dart new file mode 100644 index 0000000000..554863ae4f --- /dev/null +++ b/mobile/openapi/lib/model/notification_level.dart @@ -0,0 +1,91 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.18 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + + +class NotificationLevel { + /// Instantiate a new enum with the provided [value]. + const NotificationLevel._(this.value); + + /// The underlying value of this enum member. + final String value; + + @override + String toString() => value; + + String toJson() => value; + + static const success = NotificationLevel._(r'success'); + static const error = NotificationLevel._(r'error'); + static const warning = NotificationLevel._(r'warning'); + static const info = NotificationLevel._(r'info'); + + /// List of all possible values in this [enum][NotificationLevel]. + static const values = [ + success, + error, + warning, + info, + ]; + + static NotificationLevel? fromJson(dynamic value) => NotificationLevelTypeTransformer().decode(value); + + static List listFromJson(dynamic json, {bool growable = false,}) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = NotificationLevel.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } +} + +/// Transformation class that can [encode] an instance of [NotificationLevel] to String, +/// and [decode] dynamic data back to [NotificationLevel]. +class NotificationLevelTypeTransformer { + factory NotificationLevelTypeTransformer() => _instance ??= const NotificationLevelTypeTransformer._(); + + const NotificationLevelTypeTransformer._(); + + String encode(NotificationLevel data) => data.value; + + /// Decodes a [dynamic value][data] to a NotificationLevel. + /// + /// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully, + /// then null is returned. However, if [allowNull] is false and the [dynamic value][data] + /// cannot be decoded successfully, then an [UnimplementedError] is thrown. + /// + /// The [allowNull] is very handy when an API changes and a new enum value is added or removed, + /// and users are still using an old app with the old code. + NotificationLevel? decode(dynamic data, {bool allowNull = true}) { + if (data != null) { + switch (data) { + case r'success': return NotificationLevel.success; + case r'error': return NotificationLevel.error; + case r'warning': return NotificationLevel.warning; + case r'info': return NotificationLevel.info; + default: + if (!allowNull) { + throw ArgumentError('Unknown enum value to decode: $data'); + } + } + } + return null; + } + + /// Singleton [NotificationLevelTypeTransformer] instance. + static NotificationLevelTypeTransformer? _instance; +} + diff --git a/mobile/openapi/lib/model/notification_type.dart b/mobile/openapi/lib/model/notification_type.dart new file mode 100644 index 0000000000..436d2d190f --- /dev/null +++ b/mobile/openapi/lib/model/notification_type.dart @@ -0,0 +1,91 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.18 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + + +class NotificationType { + /// Instantiate a new enum with the provided [value]. + const NotificationType._(this.value); + + /// The underlying value of this enum member. + final String value; + + @override + String toString() => value; + + String toJson() => value; + + static const jobFailed = NotificationType._(r'JobFailed'); + static const backupFailed = NotificationType._(r'BackupFailed'); + static const systemMessage = NotificationType._(r'SystemMessage'); + static const custom = NotificationType._(r'Custom'); + + /// List of all possible values in this [enum][NotificationType]. + static const values = [ + jobFailed, + backupFailed, + systemMessage, + custom, + ]; + + static NotificationType? fromJson(dynamic value) => NotificationTypeTypeTransformer().decode(value); + + static List listFromJson(dynamic json, {bool growable = false,}) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = NotificationType.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } +} + +/// Transformation class that can [encode] an instance of [NotificationType] to String, +/// and [decode] dynamic data back to [NotificationType]. +class NotificationTypeTypeTransformer { + factory NotificationTypeTypeTransformer() => _instance ??= const NotificationTypeTypeTransformer._(); + + const NotificationTypeTypeTransformer._(); + + String encode(NotificationType data) => data.value; + + /// Decodes a [dynamic value][data] to a NotificationType. + /// + /// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully, + /// then null is returned. However, if [allowNull] is false and the [dynamic value][data] + /// cannot be decoded successfully, then an [UnimplementedError] is thrown. + /// + /// The [allowNull] is very handy when an API changes and a new enum value is added or removed, + /// and users are still using an old app with the old code. + NotificationType? decode(dynamic data, {bool allowNull = true}) { + if (data != null) { + switch (data) { + case r'JobFailed': return NotificationType.jobFailed; + case r'BackupFailed': return NotificationType.backupFailed; + case r'SystemMessage': return NotificationType.systemMessage; + case r'Custom': return NotificationType.custom; + default: + if (!allowNull) { + throw ArgumentError('Unknown enum value to decode: $data'); + } + } + } + return null; + } + + /// Singleton [NotificationTypeTypeTransformer] instance. + static NotificationTypeTypeTransformer? _instance; +} + diff --git a/mobile/openapi/lib/model/notification_update_all_dto.dart b/mobile/openapi/lib/model/notification_update_all_dto.dart new file mode 100644 index 0000000000..a6393b275a --- /dev/null +++ b/mobile/openapi/lib/model/notification_update_all_dto.dart @@ -0,0 +1,112 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.18 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class NotificationUpdateAllDto { + /// Returns a new [NotificationUpdateAllDto] instance. + NotificationUpdateAllDto({ + this.ids = const [], + this.readAt, + }); + + List ids; + + DateTime? readAt; + + @override + bool operator ==(Object other) => identical(this, other) || other is NotificationUpdateAllDto && + _deepEquality.equals(other.ids, ids) && + other.readAt == readAt; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (ids.hashCode) + + (readAt == null ? 0 : readAt!.hashCode); + + @override + String toString() => 'NotificationUpdateAllDto[ids=$ids, readAt=$readAt]'; + + Map toJson() { + final json = {}; + json[r'ids'] = this.ids; + if (this.readAt != null) { + json[r'readAt'] = this.readAt!.toUtc().toIso8601String(); + } else { + // json[r'readAt'] = null; + } + return json; + } + + /// Returns a new [NotificationUpdateAllDto] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static NotificationUpdateAllDto? fromJson(dynamic value) { + upgradeDto(value, "NotificationUpdateAllDto"); + if (value is Map) { + final json = value.cast(); + + return NotificationUpdateAllDto( + ids: json[r'ids'] is Iterable + ? (json[r'ids'] as Iterable).cast().toList(growable: false) + : const [], + readAt: mapDateTime(json, r'readAt', r''), + ); + } + return null; + } + + static List listFromJson(dynamic json, {bool growable = false,}) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = NotificationUpdateAllDto.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } + + static Map mapFromJson(dynamic json) { + final map = {}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = NotificationUpdateAllDto.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of NotificationUpdateAllDto-objects as value to a dart map + static Map> mapListFromJson(dynamic json, {bool growable = false,}) { + final map = >{}; + if (json is Map && json.isNotEmpty) { + // ignore: parameter_assignments + json = json.cast(); + for (final entry in json.entries) { + map[entry.key] = NotificationUpdateAllDto.listFromJson(entry.value, growable: growable,); + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = { + 'ids', + }; +} + diff --git a/mobile/openapi/lib/model/avatar_response.dart b/mobile/openapi/lib/model/notification_update_dto.dart similarity index 51% rename from mobile/openapi/lib/model/avatar_response.dart rename to mobile/openapi/lib/model/notification_update_dto.dart index 8ce0287565..e76496eb97 100644 --- a/mobile/openapi/lib/model/avatar_response.dart +++ b/mobile/openapi/lib/model/notification_update_dto.dart @@ -10,52 +10,56 @@ part of openapi.api; -class AvatarResponse { - /// Returns a new [AvatarResponse] instance. - AvatarResponse({ - required this.color, +class NotificationUpdateDto { + /// Returns a new [NotificationUpdateDto] instance. + NotificationUpdateDto({ + this.readAt, }); - UserAvatarColor color; + DateTime? readAt; @override - bool operator ==(Object other) => identical(this, other) || other is AvatarResponse && - other.color == color; + bool operator ==(Object other) => identical(this, other) || other is NotificationUpdateDto && + other.readAt == readAt; @override int get hashCode => // ignore: unnecessary_parenthesis - (color.hashCode); + (readAt == null ? 0 : readAt!.hashCode); @override - String toString() => 'AvatarResponse[color=$color]'; + String toString() => 'NotificationUpdateDto[readAt=$readAt]'; Map toJson() { final json = {}; - json[r'color'] = this.color; + if (this.readAt != null) { + json[r'readAt'] = this.readAt!.toUtc().toIso8601String(); + } else { + // json[r'readAt'] = null; + } return json; } - /// Returns a new [AvatarResponse] instance and imports its values from + /// Returns a new [NotificationUpdateDto] instance and imports its values from /// [value] if it's a [Map], null otherwise. // ignore: prefer_constructors_over_static_methods - static AvatarResponse? fromJson(dynamic value) { - upgradeDto(value, "AvatarResponse"); + static NotificationUpdateDto? fromJson(dynamic value) { + upgradeDto(value, "NotificationUpdateDto"); if (value is Map) { final json = value.cast(); - return AvatarResponse( - color: UserAvatarColor.fromJson(json[r'color'])!, + return NotificationUpdateDto( + readAt: mapDateTime(json, r'readAt', r''), ); } return null; } - static List listFromJson(dynamic json, {bool growable = false,}) { - final result = []; + static List listFromJson(dynamic json, {bool growable = false,}) { + final result = []; if (json is List && json.isNotEmpty) { for (final row in json) { - final value = AvatarResponse.fromJson(row); + final value = NotificationUpdateDto.fromJson(row); if (value != null) { result.add(value); } @@ -64,12 +68,12 @@ class AvatarResponse { return result.toList(growable: growable); } - static Map mapFromJson(dynamic json) { - final map = {}; + static Map mapFromJson(dynamic json) { + final map = {}; if (json is Map && json.isNotEmpty) { json = json.cast(); // ignore: parameter_assignments for (final entry in json.entries) { - final value = AvatarResponse.fromJson(entry.value); + final value = NotificationUpdateDto.fromJson(entry.value); if (value != null) { map[entry.key] = value; } @@ -78,14 +82,14 @@ class AvatarResponse { return map; } - // maps a json object with a list of AvatarResponse-objects as value to a dart map - static Map> mapListFromJson(dynamic json, {bool growable = false,}) { - final map = >{}; + // maps a json object with a list of NotificationUpdateDto-objects as value to a dart map + static Map> mapListFromJson(dynamic json, {bool growable = false,}) { + final map = >{}; if (json is Map && json.isNotEmpty) { // ignore: parameter_assignments json = json.cast(); for (final entry in json.entries) { - map[entry.key] = AvatarResponse.listFromJson(entry.value, growable: growable,); + map[entry.key] = NotificationUpdateDto.listFromJson(entry.value, growable: growable,); } } return map; @@ -93,7 +97,6 @@ class AvatarResponse { /// The list of required keys that must be present in a JSON. static const requiredKeys = { - 'color', }; } diff --git a/mobile/openapi/lib/model/o_auth_callback_dto.dart b/mobile/openapi/lib/model/o_auth_callback_dto.dart index d0b98d5c6f..ea8cac31a0 100644 --- a/mobile/openapi/lib/model/o_auth_callback_dto.dart +++ b/mobile/openapi/lib/model/o_auth_callback_dto.dart @@ -13,25 +13,57 @@ part of openapi.api; class OAuthCallbackDto { /// Returns a new [OAuthCallbackDto] instance. OAuthCallbackDto({ + this.codeVerifier, + this.state, required this.url, }); + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? codeVerifier; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? state; + String url; @override bool operator ==(Object other) => identical(this, other) || other is OAuthCallbackDto && + other.codeVerifier == codeVerifier && + other.state == state && other.url == url; @override int get hashCode => // ignore: unnecessary_parenthesis + (codeVerifier == null ? 0 : codeVerifier!.hashCode) + + (state == null ? 0 : state!.hashCode) + (url.hashCode); @override - String toString() => 'OAuthCallbackDto[url=$url]'; + String toString() => 'OAuthCallbackDto[codeVerifier=$codeVerifier, state=$state, url=$url]'; Map toJson() { final json = {}; + if (this.codeVerifier != null) { + json[r'codeVerifier'] = this.codeVerifier; + } else { + // json[r'codeVerifier'] = null; + } + if (this.state != null) { + json[r'state'] = this.state; + } else { + // json[r'state'] = null; + } json[r'url'] = this.url; return json; } @@ -45,6 +77,8 @@ class OAuthCallbackDto { final json = value.cast(); return OAuthCallbackDto( + codeVerifier: mapValueOfType(json, r'codeVerifier'), + state: mapValueOfType(json, r'state'), url: mapValueOfType(json, r'url')!, ); } diff --git a/mobile/openapi/lib/model/o_auth_config_dto.dart b/mobile/openapi/lib/model/o_auth_config_dto.dart index 86c79b4e04..bb3e8d448d 100644 --- a/mobile/openapi/lib/model/o_auth_config_dto.dart +++ b/mobile/openapi/lib/model/o_auth_config_dto.dart @@ -13,26 +13,58 @@ part of openapi.api; class OAuthConfigDto { /// Returns a new [OAuthConfigDto] instance. OAuthConfigDto({ + this.codeChallenge, required this.redirectUri, + this.state, }); + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? codeChallenge; + String redirectUri; + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + String? state; + @override bool operator ==(Object other) => identical(this, other) || other is OAuthConfigDto && - other.redirectUri == redirectUri; + other.codeChallenge == codeChallenge && + other.redirectUri == redirectUri && + other.state == state; @override int get hashCode => // ignore: unnecessary_parenthesis - (redirectUri.hashCode); + (codeChallenge == null ? 0 : codeChallenge!.hashCode) + + (redirectUri.hashCode) + + (state == null ? 0 : state!.hashCode); @override - String toString() => 'OAuthConfigDto[redirectUri=$redirectUri]'; + String toString() => 'OAuthConfigDto[codeChallenge=$codeChallenge, redirectUri=$redirectUri, state=$state]'; Map toJson() { final json = {}; + if (this.codeChallenge != null) { + json[r'codeChallenge'] = this.codeChallenge; + } else { + // json[r'codeChallenge'] = null; + } json[r'redirectUri'] = this.redirectUri; + if (this.state != null) { + json[r'state'] = this.state; + } else { + // json[r'state'] = null; + } return json; } @@ -45,7 +77,9 @@ class OAuthConfigDto { final json = value.cast(); return OAuthConfigDto( + codeChallenge: mapValueOfType(json, r'codeChallenge'), redirectUri: mapValueOfType(json, r'redirectUri')!, + state: mapValueOfType(json, r'state'), ); } return null; diff --git a/mobile/openapi/lib/model/o_auth_token_endpoint_auth_method.dart b/mobile/openapi/lib/model/o_auth_token_endpoint_auth_method.dart new file mode 100644 index 0000000000..fc528888b3 --- /dev/null +++ b/mobile/openapi/lib/model/o_auth_token_endpoint_auth_method.dart @@ -0,0 +1,85 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.18 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + + +class OAuthTokenEndpointAuthMethod { + /// Instantiate a new enum with the provided [value]. + const OAuthTokenEndpointAuthMethod._(this.value); + + /// The underlying value of this enum member. + final String value; + + @override + String toString() => value; + + String toJson() => value; + + static const post = OAuthTokenEndpointAuthMethod._(r'client_secret_post'); + static const basic = OAuthTokenEndpointAuthMethod._(r'client_secret_basic'); + + /// List of all possible values in this [enum][OAuthTokenEndpointAuthMethod]. + static const values = [ + post, + basic, + ]; + + static OAuthTokenEndpointAuthMethod? fromJson(dynamic value) => OAuthTokenEndpointAuthMethodTypeTransformer().decode(value); + + static List listFromJson(dynamic json, {bool growable = false,}) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = OAuthTokenEndpointAuthMethod.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } +} + +/// Transformation class that can [encode] an instance of [OAuthTokenEndpointAuthMethod] to String, +/// and [decode] dynamic data back to [OAuthTokenEndpointAuthMethod]. +class OAuthTokenEndpointAuthMethodTypeTransformer { + factory OAuthTokenEndpointAuthMethodTypeTransformer() => _instance ??= const OAuthTokenEndpointAuthMethodTypeTransformer._(); + + const OAuthTokenEndpointAuthMethodTypeTransformer._(); + + String encode(OAuthTokenEndpointAuthMethod data) => data.value; + + /// Decodes a [dynamic value][data] to a OAuthTokenEndpointAuthMethod. + /// + /// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully, + /// then null is returned. However, if [allowNull] is false and the [dynamic value][data] + /// cannot be decoded successfully, then an [UnimplementedError] is thrown. + /// + /// The [allowNull] is very handy when an API changes and a new enum value is added or removed, + /// and users are still using an old app with the old code. + OAuthTokenEndpointAuthMethod? decode(dynamic data, {bool allowNull = true}) { + if (data != null) { + switch (data) { + case r'client_secret_post': return OAuthTokenEndpointAuthMethod.post; + case r'client_secret_basic': return OAuthTokenEndpointAuthMethod.basic; + default: + if (!allowNull) { + throw ArgumentError('Unknown enum value to decode: $data'); + } + } + } + return null; + } + + /// Singleton [OAuthTokenEndpointAuthMethodTypeTransformer] instance. + static OAuthTokenEndpointAuthMethodTypeTransformer? _instance; +} + diff --git a/mobile/openapi/lib/model/path_entity_type.dart b/mobile/openapi/lib/model/path_entity_type.dart deleted file mode 100644 index fdcdae4f1b..0000000000 --- a/mobile/openapi/lib/model/path_entity_type.dart +++ /dev/null @@ -1,88 +0,0 @@ -// -// AUTO-GENERATED FILE, DO NOT MODIFY! -// -// @dart=2.18 - -// ignore_for_file: unused_element, unused_import -// ignore_for_file: always_put_required_named_parameters_first -// ignore_for_file: constant_identifier_names -// ignore_for_file: lines_longer_than_80_chars - -part of openapi.api; - - -class PathEntityType { - /// Instantiate a new enum with the provided [value]. - const PathEntityType._(this.value); - - /// The underlying value of this enum member. - final String value; - - @override - String toString() => value; - - String toJson() => value; - - static const asset = PathEntityType._(r'asset'); - static const person = PathEntityType._(r'person'); - static const user = PathEntityType._(r'user'); - - /// List of all possible values in this [enum][PathEntityType]. - static const values = [ - asset, - person, - user, - ]; - - static PathEntityType? fromJson(dynamic value) => PathEntityTypeTypeTransformer().decode(value); - - static List listFromJson(dynamic json, {bool growable = false,}) { - final result = []; - if (json is List && json.isNotEmpty) { - for (final row in json) { - final value = PathEntityType.fromJson(row); - if (value != null) { - result.add(value); - } - } - } - return result.toList(growable: growable); - } -} - -/// Transformation class that can [encode] an instance of [PathEntityType] to String, -/// and [decode] dynamic data back to [PathEntityType]. -class PathEntityTypeTypeTransformer { - factory PathEntityTypeTypeTransformer() => _instance ??= const PathEntityTypeTypeTransformer._(); - - const PathEntityTypeTypeTransformer._(); - - String encode(PathEntityType data) => data.value; - - /// Decodes a [dynamic value][data] to a PathEntityType. - /// - /// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully, - /// then null is returned. However, if [allowNull] is false and the [dynamic value][data] - /// cannot be decoded successfully, then an [UnimplementedError] is thrown. - /// - /// The [allowNull] is very handy when an API changes and a new enum value is added or removed, - /// and users are still using an old app with the old code. - PathEntityType? decode(dynamic data, {bool allowNull = true}) { - if (data != null) { - switch (data) { - case r'asset': return PathEntityType.asset; - case r'person': return PathEntityType.person; - case r'user': return PathEntityType.user; - default: - if (!allowNull) { - throw ArgumentError('Unknown enum value to decode: $data'); - } - } - } - return null; - } - - /// Singleton [PathEntityTypeTypeTransformer] instance. - static PathEntityTypeTypeTransformer? _instance; -} - diff --git a/mobile/openapi/lib/model/path_type.dart b/mobile/openapi/lib/model/path_type.dart deleted file mode 100644 index 55453ed1e8..0000000000 --- a/mobile/openapi/lib/model/path_type.dart +++ /dev/null @@ -1,103 +0,0 @@ -// -// AUTO-GENERATED FILE, DO NOT MODIFY! -// -// @dart=2.18 - -// ignore_for_file: unused_element, unused_import -// ignore_for_file: always_put_required_named_parameters_first -// ignore_for_file: constant_identifier_names -// ignore_for_file: lines_longer_than_80_chars - -part of openapi.api; - - -class PathType { - /// Instantiate a new enum with the provided [value]. - const PathType._(this.value); - - /// The underlying value of this enum member. - final String value; - - @override - String toString() => value; - - String toJson() => value; - - static const original = PathType._(r'original'); - static const fullsize = PathType._(r'fullsize'); - static const preview = PathType._(r'preview'); - static const thumbnail = PathType._(r'thumbnail'); - static const encodedVideo = PathType._(r'encoded_video'); - static const sidecar = PathType._(r'sidecar'); - static const face = PathType._(r'face'); - static const profile = PathType._(r'profile'); - - /// List of all possible values in this [enum][PathType]. - static const values = [ - original, - fullsize, - preview, - thumbnail, - encodedVideo, - sidecar, - face, - profile, - ]; - - static PathType? fromJson(dynamic value) => PathTypeTypeTransformer().decode(value); - - static List listFromJson(dynamic json, {bool growable = false,}) { - final result = []; - if (json is List && json.isNotEmpty) { - for (final row in json) { - final value = PathType.fromJson(row); - if (value != null) { - result.add(value); - } - } - } - return result.toList(growable: growable); - } -} - -/// Transformation class that can [encode] an instance of [PathType] to String, -/// and [decode] dynamic data back to [PathType]. -class PathTypeTypeTransformer { - factory PathTypeTypeTransformer() => _instance ??= const PathTypeTypeTransformer._(); - - const PathTypeTypeTransformer._(); - - String encode(PathType data) => data.value; - - /// Decodes a [dynamic value][data] to a PathType. - /// - /// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully, - /// then null is returned. However, if [allowNull] is false and the [dynamic value][data] - /// cannot be decoded successfully, then an [UnimplementedError] is thrown. - /// - /// The [allowNull] is very handy when an API changes and a new enum value is added or removed, - /// and users are still using an old app with the old code. - PathType? decode(dynamic data, {bool allowNull = true}) { - if (data != null) { - switch (data) { - case r'original': return PathType.original; - case r'fullsize': return PathType.fullsize; - case r'preview': return PathType.preview; - case r'thumbnail': return PathType.thumbnail; - case r'encoded_video': return PathType.encodedVideo; - case r'sidecar': return PathType.sidecar; - case r'face': return PathType.face; - case r'profile': return PathType.profile; - default: - if (!allowNull) { - throw ArgumentError('Unknown enum value to decode: $data'); - } - } - } - return null; - } - - /// Singleton [PathTypeTypeTransformer] instance. - static PathTypeTypeTransformer? _instance; -} - diff --git a/mobile/openapi/lib/model/permission.dart b/mobile/openapi/lib/model/permission.dart index 1244a434b6..1735bc2eb5 100644 --- a/mobile/openapi/lib/model/permission.dart +++ b/mobile/openapi/lib/model/permission.dart @@ -66,6 +66,10 @@ class Permission { static const memoryPeriodRead = Permission._(r'memory.read'); static const memoryPeriodUpdate = Permission._(r'memory.update'); static const memoryPeriodDelete = Permission._(r'memory.delete'); + static const notificationPeriodCreate = Permission._(r'notification.create'); + static const notificationPeriodRead = Permission._(r'notification.read'); + static const notificationPeriodUpdate = Permission._(r'notification.update'); + static const notificationPeriodDelete = Permission._(r'notification.delete'); static const partnerPeriodCreate = Permission._(r'partner.create'); static const partnerPeriodRead = Permission._(r'partner.read'); static const partnerPeriodUpdate = Permission._(r'partner.update'); @@ -147,6 +151,10 @@ class Permission { memoryPeriodRead, memoryPeriodUpdate, memoryPeriodDelete, + notificationPeriodCreate, + notificationPeriodRead, + notificationPeriodUpdate, + notificationPeriodDelete, partnerPeriodCreate, partnerPeriodRead, partnerPeriodUpdate, @@ -263,6 +271,10 @@ class PermissionTypeTransformer { case r'memory.read': return Permission.memoryPeriodRead; case r'memory.update': return Permission.memoryPeriodUpdate; case r'memory.delete': return Permission.memoryPeriodDelete; + case r'notification.create': return Permission.notificationPeriodCreate; + case r'notification.read': return Permission.notificationPeriodRead; + case r'notification.update': return Permission.notificationPeriodUpdate; + case r'notification.delete': return Permission.notificationPeriodDelete; case r'partner.create': return Permission.partnerPeriodCreate; case r'partner.read': return Permission.partnerPeriodRead; case r'partner.update': return Permission.partnerPeriodUpdate; diff --git a/mobile/openapi/lib/model/system_config_o_auth_dto.dart b/mobile/openapi/lib/model/system_config_o_auth_dto.dart index 9125bb7bba..24384a47b1 100644 --- a/mobile/openapi/lib/model/system_config_o_auth_dto.dart +++ b/mobile/openapi/lib/model/system_config_o_auth_dto.dart @@ -28,6 +28,8 @@ class SystemConfigOAuthDto { required this.signingAlgorithm, required this.storageLabelClaim, required this.storageQuotaClaim, + required this.timeout, + required this.tokenEndpointAuthMethod, }); bool autoLaunch; @@ -61,6 +63,11 @@ class SystemConfigOAuthDto { String storageQuotaClaim; + /// Minimum value: 1 + int timeout; + + OAuthTokenEndpointAuthMethod tokenEndpointAuthMethod; + @override bool operator ==(Object other) => identical(this, other) || other is SystemConfigOAuthDto && other.autoLaunch == autoLaunch && @@ -77,7 +84,9 @@ class SystemConfigOAuthDto { other.scope == scope && other.signingAlgorithm == signingAlgorithm && other.storageLabelClaim == storageLabelClaim && - other.storageQuotaClaim == storageQuotaClaim; + other.storageQuotaClaim == storageQuotaClaim && + other.timeout == timeout && + other.tokenEndpointAuthMethod == tokenEndpointAuthMethod; @override int get hashCode => @@ -96,10 +105,12 @@ class SystemConfigOAuthDto { (scope.hashCode) + (signingAlgorithm.hashCode) + (storageLabelClaim.hashCode) + - (storageQuotaClaim.hashCode); + (storageQuotaClaim.hashCode) + + (timeout.hashCode) + + (tokenEndpointAuthMethod.hashCode); @override - String toString() => 'SystemConfigOAuthDto[autoLaunch=$autoLaunch, autoRegister=$autoRegister, buttonText=$buttonText, clientId=$clientId, clientSecret=$clientSecret, defaultStorageQuota=$defaultStorageQuota, enabled=$enabled, issuerUrl=$issuerUrl, mobileOverrideEnabled=$mobileOverrideEnabled, mobileRedirectUri=$mobileRedirectUri, profileSigningAlgorithm=$profileSigningAlgorithm, scope=$scope, signingAlgorithm=$signingAlgorithm, storageLabelClaim=$storageLabelClaim, storageQuotaClaim=$storageQuotaClaim]'; + String toString() => 'SystemConfigOAuthDto[autoLaunch=$autoLaunch, autoRegister=$autoRegister, buttonText=$buttonText, clientId=$clientId, clientSecret=$clientSecret, defaultStorageQuota=$defaultStorageQuota, enabled=$enabled, issuerUrl=$issuerUrl, mobileOverrideEnabled=$mobileOverrideEnabled, mobileRedirectUri=$mobileRedirectUri, profileSigningAlgorithm=$profileSigningAlgorithm, scope=$scope, signingAlgorithm=$signingAlgorithm, storageLabelClaim=$storageLabelClaim, storageQuotaClaim=$storageQuotaClaim, timeout=$timeout, tokenEndpointAuthMethod=$tokenEndpointAuthMethod]'; Map toJson() { final json = {}; @@ -118,6 +129,8 @@ class SystemConfigOAuthDto { json[r'signingAlgorithm'] = this.signingAlgorithm; json[r'storageLabelClaim'] = this.storageLabelClaim; json[r'storageQuotaClaim'] = this.storageQuotaClaim; + json[r'timeout'] = this.timeout; + json[r'tokenEndpointAuthMethod'] = this.tokenEndpointAuthMethod; return json; } @@ -145,6 +158,8 @@ class SystemConfigOAuthDto { signingAlgorithm: mapValueOfType(json, r'signingAlgorithm')!, storageLabelClaim: mapValueOfType(json, r'storageLabelClaim')!, storageQuotaClaim: mapValueOfType(json, r'storageQuotaClaim')!, + timeout: mapValueOfType(json, r'timeout')!, + tokenEndpointAuthMethod: OAuthTokenEndpointAuthMethod.fromJson(json[r'tokenEndpointAuthMethod'])!, ); } return null; @@ -207,6 +222,8 @@ class SystemConfigOAuthDto { 'signingAlgorithm', 'storageLabelClaim', 'storageQuotaClaim', + 'timeout', + 'tokenEndpointAuthMethod', }; } diff --git a/mobile/openapi/lib/model/user_admin_create_dto.dart b/mobile/openapi/lib/model/user_admin_create_dto.dart index 4bd1266426..1477c82ca1 100644 --- a/mobile/openapi/lib/model/user_admin_create_dto.dart +++ b/mobile/openapi/lib/model/user_admin_create_dto.dart @@ -13,6 +13,7 @@ part of openapi.api; class UserAdminCreateDto { /// Returns a new [UserAdminCreateDto] instance. UserAdminCreateDto({ + this.avatarColor, required this.email, required this.name, this.notify, @@ -22,6 +23,8 @@ class UserAdminCreateDto { this.storageLabel, }); + UserAvatarColor? avatarColor; + String email; String name; @@ -51,6 +54,7 @@ class UserAdminCreateDto { @override bool operator ==(Object other) => identical(this, other) || other is UserAdminCreateDto && + other.avatarColor == avatarColor && other.email == email && other.name == name && other.notify == notify && @@ -62,6 +66,7 @@ class UserAdminCreateDto { @override int get hashCode => // ignore: unnecessary_parenthesis + (avatarColor == null ? 0 : avatarColor!.hashCode) + (email.hashCode) + (name.hashCode) + (notify == null ? 0 : notify!.hashCode) + @@ -71,10 +76,15 @@ class UserAdminCreateDto { (storageLabel == null ? 0 : storageLabel!.hashCode); @override - String toString() => 'UserAdminCreateDto[email=$email, name=$name, notify=$notify, password=$password, quotaSizeInBytes=$quotaSizeInBytes, shouldChangePassword=$shouldChangePassword, storageLabel=$storageLabel]'; + String toString() => 'UserAdminCreateDto[avatarColor=$avatarColor, email=$email, name=$name, notify=$notify, password=$password, quotaSizeInBytes=$quotaSizeInBytes, shouldChangePassword=$shouldChangePassword, storageLabel=$storageLabel]'; Map toJson() { final json = {}; + if (this.avatarColor != null) { + json[r'avatarColor'] = this.avatarColor; + } else { + // json[r'avatarColor'] = null; + } json[r'email'] = this.email; json[r'name'] = this.name; if (this.notify != null) { @@ -110,6 +120,7 @@ class UserAdminCreateDto { final json = value.cast(); return UserAdminCreateDto( + avatarColor: UserAvatarColor.fromJson(json[r'avatarColor']), email: mapValueOfType(json, r'email')!, name: mapValueOfType(json, r'name')!, notify: mapValueOfType(json, r'notify'), diff --git a/mobile/openapi/lib/model/user_admin_update_dto.dart b/mobile/openapi/lib/model/user_admin_update_dto.dart index f0478c9b4c..951ee8ce84 100644 --- a/mobile/openapi/lib/model/user_admin_update_dto.dart +++ b/mobile/openapi/lib/model/user_admin_update_dto.dart @@ -13,6 +13,7 @@ part of openapi.api; class UserAdminUpdateDto { /// Returns a new [UserAdminUpdateDto] instance. UserAdminUpdateDto({ + this.avatarColor, this.email, this.name, this.password, @@ -21,6 +22,8 @@ class UserAdminUpdateDto { this.storageLabel, }); + UserAvatarColor? avatarColor; + /// /// Please note: This property should have been non-nullable! Since the specification file /// does not include a default value (using the "default:" property), however, the generated @@ -60,6 +63,7 @@ class UserAdminUpdateDto { @override bool operator ==(Object other) => identical(this, other) || other is UserAdminUpdateDto && + other.avatarColor == avatarColor && other.email == email && other.name == name && other.password == password && @@ -70,6 +74,7 @@ class UserAdminUpdateDto { @override int get hashCode => // ignore: unnecessary_parenthesis + (avatarColor == null ? 0 : avatarColor!.hashCode) + (email == null ? 0 : email!.hashCode) + (name == null ? 0 : name!.hashCode) + (password == null ? 0 : password!.hashCode) + @@ -78,10 +83,15 @@ class UserAdminUpdateDto { (storageLabel == null ? 0 : storageLabel!.hashCode); @override - String toString() => 'UserAdminUpdateDto[email=$email, name=$name, password=$password, quotaSizeInBytes=$quotaSizeInBytes, shouldChangePassword=$shouldChangePassword, storageLabel=$storageLabel]'; + String toString() => 'UserAdminUpdateDto[avatarColor=$avatarColor, email=$email, name=$name, password=$password, quotaSizeInBytes=$quotaSizeInBytes, shouldChangePassword=$shouldChangePassword, storageLabel=$storageLabel]'; Map toJson() { final json = {}; + if (this.avatarColor != null) { + json[r'avatarColor'] = this.avatarColor; + } else { + // json[r'avatarColor'] = null; + } if (this.email != null) { json[r'email'] = this.email; } else { @@ -124,6 +134,7 @@ class UserAdminUpdateDto { final json = value.cast(); return UserAdminUpdateDto( + avatarColor: UserAvatarColor.fromJson(json[r'avatarColor']), email: mapValueOfType(json, r'email'), name: mapValueOfType(json, r'name'), password: mapValueOfType(json, r'password'), diff --git a/mobile/openapi/lib/model/user_preferences_response_dto.dart b/mobile/openapi/lib/model/user_preferences_response_dto.dart index b244284eb0..215e691cb1 100644 --- a/mobile/openapi/lib/model/user_preferences_response_dto.dart +++ b/mobile/openapi/lib/model/user_preferences_response_dto.dart @@ -13,7 +13,6 @@ part of openapi.api; class UserPreferencesResponseDto { /// Returns a new [UserPreferencesResponseDto] instance. UserPreferencesResponseDto({ - required this.avatar, required this.download, required this.emailNotifications, required this.folders, @@ -25,8 +24,6 @@ class UserPreferencesResponseDto { required this.tags, }); - AvatarResponse avatar; - DownloadResponse download; EmailNotificationsResponse emailNotifications; @@ -47,7 +44,6 @@ class UserPreferencesResponseDto { @override bool operator ==(Object other) => identical(this, other) || other is UserPreferencesResponseDto && - other.avatar == avatar && other.download == download && other.emailNotifications == emailNotifications && other.folders == folders && @@ -61,7 +57,6 @@ class UserPreferencesResponseDto { @override int get hashCode => // ignore: unnecessary_parenthesis - (avatar.hashCode) + (download.hashCode) + (emailNotifications.hashCode) + (folders.hashCode) + @@ -73,11 +68,10 @@ class UserPreferencesResponseDto { (tags.hashCode); @override - String toString() => 'UserPreferencesResponseDto[avatar=$avatar, download=$download, emailNotifications=$emailNotifications, folders=$folders, memories=$memories, people=$people, purchase=$purchase, ratings=$ratings, sharedLinks=$sharedLinks, tags=$tags]'; + String toString() => 'UserPreferencesResponseDto[download=$download, emailNotifications=$emailNotifications, folders=$folders, memories=$memories, people=$people, purchase=$purchase, ratings=$ratings, sharedLinks=$sharedLinks, tags=$tags]'; Map toJson() { final json = {}; - json[r'avatar'] = this.avatar; json[r'download'] = this.download; json[r'emailNotifications'] = this.emailNotifications; json[r'folders'] = this.folders; @@ -99,7 +93,6 @@ class UserPreferencesResponseDto { final json = value.cast(); return UserPreferencesResponseDto( - avatar: AvatarResponse.fromJson(json[r'avatar'])!, download: DownloadResponse.fromJson(json[r'download'])!, emailNotifications: EmailNotificationsResponse.fromJson(json[r'emailNotifications'])!, folders: FoldersResponse.fromJson(json[r'folders'])!, @@ -156,7 +149,6 @@ class UserPreferencesResponseDto { /// The list of required keys that must be present in a JSON. static const requiredKeys = { - 'avatar', 'download', 'emailNotifications', 'folders', diff --git a/mobile/openapi/lib/model/user_update_me_dto.dart b/mobile/openapi/lib/model/user_update_me_dto.dart index 8f3f4df37a..779e07ffa6 100644 --- a/mobile/openapi/lib/model/user_update_me_dto.dart +++ b/mobile/openapi/lib/model/user_update_me_dto.dart @@ -13,11 +13,14 @@ part of openapi.api; class UserUpdateMeDto { /// Returns a new [UserUpdateMeDto] instance. UserUpdateMeDto({ + this.avatarColor, this.email, this.name, this.password, }); + UserAvatarColor? avatarColor; + /// /// Please note: This property should have been non-nullable! Since the specification file /// does not include a default value (using the "default:" property), however, the generated @@ -44,6 +47,7 @@ class UserUpdateMeDto { @override bool operator ==(Object other) => identical(this, other) || other is UserUpdateMeDto && + other.avatarColor == avatarColor && other.email == email && other.name == name && other.password == password; @@ -51,15 +55,21 @@ class UserUpdateMeDto { @override int get hashCode => // ignore: unnecessary_parenthesis + (avatarColor == null ? 0 : avatarColor!.hashCode) + (email == null ? 0 : email!.hashCode) + (name == null ? 0 : name!.hashCode) + (password == null ? 0 : password!.hashCode); @override - String toString() => 'UserUpdateMeDto[email=$email, name=$name, password=$password]'; + String toString() => 'UserUpdateMeDto[avatarColor=$avatarColor, email=$email, name=$name, password=$password]'; Map toJson() { final json = {}; + if (this.avatarColor != null) { + json[r'avatarColor'] = this.avatarColor; + } else { + // json[r'avatarColor'] = null; + } if (this.email != null) { json[r'email'] = this.email; } else { @@ -87,6 +97,7 @@ class UserUpdateMeDto { final json = value.cast(); return UserUpdateMeDto( + avatarColor: UserAvatarColor.fromJson(json[r'avatarColor']), email: mapValueOfType(json, r'email'), name: mapValueOfType(json, r'name'), password: mapValueOfType(json, r'password'), diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 0c99fe19fe..d9e821d332 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -303,7 +303,7 @@ packages: source: hosted version: "0.3.4+2" crypto: - dependency: transitive + dependency: "direct main" description: name: crypto sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" @@ -696,18 +696,18 @@ packages: dependency: "direct main" description: name: geolocator - sha256: "6cb9fb6e5928b58b9a84bdf85012d757fd07aab8215c5205337021c4999bad27" + sha256: e7ebfa04ce451daf39b5499108c973189a71a919aa53c1204effda1c5b93b822 url: "https://pub.dev" source: hosted - version: "11.1.0" + version: "14.0.0" geolocator_android: dependency: transitive description: name: geolocator_android - sha256: "7aefc530db47d90d0580b552df3242440a10fe60814496a979aa67aa98b1fd47" + sha256: "114072db5d1dce0ec0b36af2697f55c133bc89a2c8dd513e137c0afe59696ed4" url: "https://pub.dev" source: hosted - version: "4.6.1" + version: "5.0.1+1" geolocator_apple: dependency: transitive description: @@ -728,10 +728,10 @@ packages: dependency: transitive description: name: geolocator_web - sha256: "49d8f846ebeb5e2b6641fe477a7e97e5dd73f03cbfef3fd5c42177b7300fb0ed" + sha256: b1ae9bdfd90f861fde8fd4f209c37b953d65e92823cb73c7dee1fa021b06f172 url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "4.1.3" geolocator_windows: dependency: transitive description: diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 324b7c9e9e..cf0b9b9106 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -2,7 +2,7 @@ name: immich_mobile description: Immich - selfhosted backup media file on mobile phone publish_to: 'none' -version: 1.131.3+193 +version: 1.132.3+197 environment: sdk: '>=3.3.0 <4.0.0' @@ -22,6 +22,7 @@ dependencies: collection: ^1.18.0 connectivity_plus: ^6.1.3 crop_image: ^1.0.16 + crypto: ^3.0.6 device_info_plus: ^11.3.3 dynamic_color: ^1.7.0 easy_image_viewer: ^1.5.1 @@ -35,7 +36,7 @@ dependencies: flutter_udid: ^3.0.0 flutter_web_auth_2: ^5.0.0-alpha.0 fluttertoast: ^8.2.12 - geolocator: ^11.0.0 + geolocator: ^14.0.0 hooks_riverpod: ^2.6.1 http: ^1.3.0 image_picker: ^1.1.2 diff --git a/mobile/test/domain/services/device_sync_service_test.dart b/mobile/test/domain/services/device_sync_service_test.dart index a8c5894fec..d8424f903e 100644 --- a/mobile/test/domain/services/device_sync_service_test.dart +++ b/mobile/test/domain/services/device_sync_service_test.dart @@ -3,7 +3,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:immich_mobile/domain/interfaces/album_media.interface.dart'; import 'package:immich_mobile/domain/interfaces/local_album.interface.dart'; import 'package:immich_mobile/domain/interfaces/local_asset.interface.dart'; -import 'package:immich_mobile/domain/models/asset/asset.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/local_album.model.dart'; import 'package:immich_mobile/domain/services/device_sync.service.dart'; import 'package:immich_mobile/utils/nullable_value.dart'; @@ -257,9 +257,9 @@ void main() { newAlbum.copyWith(updatedAt: DateTime(2024), assetCount: 2); final assets = [ LocalAssetStub.image1 - .copyWith(localId: "asset1", createdAt: DateTime(2024, 1, 1)), + .copyWith(id: "asset1", createdAt: DateTime(2024, 1, 1)), LocalAssetStub.image2.copyWith( - localId: "asset2", + id: "asset2", createdAt: DateTime(2024, 1, 2), ), ]; @@ -284,7 +284,7 @@ void main() { expect(capturedAlbum.id, newAlbum.id); expect(capturedAlbum.assetCount, refreshedAlbum.assetCount); expect(capturedAlbum.updatedAt, refreshedAlbum.updatedAt); - expect(capturedAlbum.thumbnailId, assets.first.localId); + expect(capturedAlbum.thumbnailId, assets.first.id); expect(listEquals(capturedAssets, assets), isTrue); }, ); @@ -354,7 +354,7 @@ void main() { when(() => mockAlbumMediaRepo.refresh(dbAlbum.id)) .thenAnswer((_) async => refreshedAlbum); - final newAsset = LocalAssetStub.image2.copyWith(localId: "new_asset"); + final newAsset = LocalAssetStub.image2.copyWith(id: "new_asset"); when( () => mockAlbumMediaRepo.getAssetsForAlbum( dbAlbum.id, @@ -388,7 +388,7 @@ void main() { (a) => a.id == dbAlbum.id && a.assetCount == 2 && - a.thumbnailId == newAsset.localId, + a.thumbnailId == newAsset.id, ), ), ), @@ -447,7 +447,7 @@ void main() { ).called(1); verify( () => mockLocalAlbumRepo - .removeAssets(dbAlbum.id, [LocalAssetStub.image1.localId]), + .removeAssets(dbAlbum.id, [LocalAssetStub.image1.id]), ).called(1); }, ); @@ -520,7 +520,7 @@ void main() { test('returns true and updates assets/metadata on success', () async { final newAsset = LocalAssetStub.image2.copyWith( - localId: "asset2", + id: "asset2", createdAt: DateTime(2024, 1, 1, 10, 30, 0), ); when( @@ -532,7 +532,7 @@ void main() { when(() => mockLocalAssetRepo.get("thumb1")).thenAnswer( (_) async => LocalAssetStub.image1.copyWith( - localId: "thumb1", + id: "thumb1", createdAt: DateTime(2024, 1, 1, 9, 0, 0), ), ); @@ -557,7 +557,7 @@ void main() { a.id == dbAlbum.id && a.assetCount == 2 && a.updatedAt == refreshedAlbum.updatedAt && - a.thumbnailId == newAsset.localId, + a.thumbnailId == newAsset.id, ), ), ), @@ -568,7 +568,7 @@ void main() { test('returns true and keeps old thumbnail if newer', () async { final newAsset = LocalAssetStub.image2.copyWith( - localId: "asset2", + id: "asset2", createdAt: DateTime(2024, 1, 1, 8, 0, 0), ); when( @@ -580,7 +580,7 @@ void main() { when(() => mockLocalAssetRepo.get("thumb1")).thenAnswer( (_) async => LocalAssetStub.image1.copyWith( - localId: "thumb1", + id: "thumb1", createdAt: DateTime(2024, 1, 1, 9, 0, 0), ), ); @@ -616,7 +616,7 @@ void main() { final dbAlbumNoThumb = dbAlbum.copyWith(thumbnailId: const NullableValue.empty()); final newAsset = LocalAssetStub.image2.copyWith( - localId: "asset2", + id: "asset2", createdAt: DateTime(2024, 1, 1, 10, 30, 0), ); when( @@ -646,7 +646,7 @@ void main() { a.id == dbAlbum.id && a.assetCount == 2 && a.updatedAt == refreshedAlbum.updatedAt && - a.thumbnailId == newAsset.localId, + a.thumbnailId == newAsset.id, ), ), ), @@ -733,22 +733,22 @@ void main() { ); final dbAsset1 = LocalAssetStub.image1.copyWith( - localId: "asset1", + id: "asset1", createdAt: DateTime(2024), updatedAt: DateTime(2024), ); final dbAsset2 = LocalAssetStub.image2.copyWith( - localId: "asset2", + id: "asset2", createdAt: DateTime(2024), updatedAt: DateTime(2024), ); // To be deleted final deviceAsset1 = LocalAssetStub.image1.copyWith( - localId: "asset1", + id: "asset1", createdAt: DateTime(2024), updatedAt: DateTime(2025), ); // Updated final deviceAsset3 = LocalAssetStub.video1.copyWith( - localId: "asset3", + id: "asset3", createdAt: DateTime(2024), updatedAt: DateTime(2024), ); // Added @@ -821,7 +821,7 @@ void main() { a.id == emptyDbAlbum.id && a.assetCount == deviceAssets.length && a.updatedAt == refreshedWithAssets.updatedAt && - a.thumbnailId == deviceAssets.first.localId, + a.thumbnailId == deviceAssets.first.id, ), ), ), @@ -835,7 +835,7 @@ void main() { final deviceAssets = [deviceAsset1, deviceAsset3]; deviceAssets.sort((a, b) => a.createdAt.compareTo(b.createdAt)); final dbAssets = [dbAsset1, dbAsset2]; - dbAssets.sort((a, b) => a.localId.compareTo(b.localId)); + dbAssets.sort((a, b) => a.id.compareTo(b.id)); when(() => mockAlbumMediaRepo.getAssetsForAlbum(dbAlbum.id)).thenAnswer( (_) async => deviceAssets, @@ -859,10 +859,10 @@ void main() { return list.length == 2 && list.any( (a) => - a.localId == "asset1" && + a.id == "asset1" && a.updatedAt == deviceAsset1.updatedAt, ) && - list.any((a) => a.localId == "asset3"); + list.any((a) => a.id == "asset3"); }), ), ), @@ -876,7 +876,7 @@ void main() { a.id == dbAlbum.id && a.assetCount == 2 && a.updatedAt == currentRefreshedAlbum.updatedAt && - a.thumbnailId == deviceAssets.first.localId, + a.thumbnailId == deviceAssets.first.id, ), ), ), @@ -894,7 +894,7 @@ void main() { final dbAssets = [dbAsset1, dbAsset2]; final deviceAssets = [dbAsset1, dbAsset2]; deviceAssets.sort((a, b) => a.createdAt.compareTo(b.createdAt)); - dbAssets.sort((a, b) => a.localId.compareTo(b.localId)); + dbAssets.sort((a, b) => a.id.compareTo(b.id)); when(() => mockAlbumMediaRepo.getAssetsForAlbum(dbAlbum.id)) .thenAnswer((_) async => deviceAssets); @@ -917,7 +917,7 @@ void main() { a.id == dbAlbum.id && a.assetCount == 2 && a.updatedAt == currentRefreshedAlbum.updatedAt && - a.thumbnailId == deviceAssets.first.localId, + a.thumbnailId == deviceAssets.first.id, ), ), ), diff --git a/mobile/test/fixtures/local_album.stub.dart b/mobile/test/fixtures/local_album.stub.dart index 32d25ce254..517bdd5189 100644 --- a/mobile/test/fixtures/local_album.stub.dart +++ b/mobile/test/fixtures/local_album.stub.dart @@ -10,7 +10,6 @@ abstract final class LocalAlbumStub { assetCount: 1, thumbnailId: null, backupSelection: BackupSelection.none, - isAll: false, ); static LocalAlbum get album2 => LocalAlbum( @@ -20,7 +19,6 @@ abstract final class LocalAlbumStub { assetCount: 2, thumbnailId: null, backupSelection: BackupSelection.selected, - isAll: true, ); static LocalAlbum get album3 => LocalAlbum( @@ -30,6 +28,5 @@ abstract final class LocalAlbumStub { assetCount: 20, thumbnailId: "123", backupSelection: BackupSelection.excluded, - isAll: false, ); } diff --git a/mobile/test/fixtures/local_asset.stub.dart b/mobile/test/fixtures/local_asset.stub.dart index a399dfdc22..1d47e7abe5 100644 --- a/mobile/test/fixtures/local_asset.stub.dart +++ b/mobile/test/fixtures/local_asset.stub.dart @@ -1,10 +1,10 @@ -import 'package:immich_mobile/domain/models/asset/asset.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; abstract final class LocalAssetStub { const LocalAssetStub(); static LocalAsset get image1 => LocalAsset( - localId: "image1", + id: "image1", name: "image1.jpg", checksum: "image1-checksum", type: AssetType.image, @@ -16,7 +16,7 @@ abstract final class LocalAssetStub { ); static LocalAsset get image2 => LocalAsset( - localId: "image2", + id: "image2", name: "image2.jpg", checksum: "image2-checksum", type: AssetType.image, @@ -28,7 +28,7 @@ abstract final class LocalAssetStub { ); static LocalAsset get video1 => LocalAsset( - localId: "video1", + id: "video1", name: "video1.mov", checksum: "video1-checksum", type: AssetType.video, diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index c322420e59..a7919f07e7 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -206,6 +206,141 @@ ] } }, + "/admin/notifications": { + "post": { + "operationId": "createNotification", + "parameters": [], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotificationCreateDto" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotificationDto" + } + } + }, + "description": "" + } + }, + "security": [ + { + "bearer": [] + }, + { + "cookie": [] + }, + { + "api_key": [] + } + ], + "tags": [ + "Notifications (Admin)" + ] + } + }, + "/admin/notifications/templates/{name}": { + "post": { + "operationId": "getNotificationTemplateAdmin", + "parameters": [ + { + "name": "name", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateResponseDto" + } + } + }, + "description": "" + } + }, + "security": [ + { + "bearer": [] + }, + { + "cookie": [] + }, + { + "api_key": [] + } + ], + "tags": [ + "Notifications (Admin)" + ] + } + }, + "/admin/notifications/test-email": { + "post": { + "operationId": "sendTestEmailAdmin", + "parameters": [], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SystemConfigSmtpDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TestEmailResponseDto" + } + } + }, + "description": "" + } + }, + "security": [ + { + "bearer": [] + }, + { + "cookie": [] + }, + { + "api_key": [] + } + ], + "tags": [ + "Notifications (Admin)" + ] + } + }, "/admin/users": { "get": { "operationId": "searchUsersAdmin", @@ -3485,35 +3620,86 @@ ] } }, - "/notifications/templates/{name}": { - "post": { - "operationId": "getNotificationTemplate", - "parameters": [ - { - "name": "name", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], + "/notifications": { + "delete": { + "operationId": "deleteNotifications", + "parameters": [], "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TemplateDto" + "$ref": "#/components/schemas/NotificationDeleteAllDto" } } }, "required": true }, + "responses": { + "200": { + "description": "" + } + }, + "security": [ + { + "bearer": [] + }, + { + "cookie": [] + }, + { + "api_key": [] + } + ], + "tags": [ + "Notifications" + ] + }, + "get": { + "operationId": "getNotifications", + "parameters": [ + { + "name": "id", + "required": false, + "in": "query", + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "name": "level", + "required": false, + "in": "query", + "schema": { + "$ref": "#/components/schemas/NotificationLevel" + } + }, + { + "name": "type", + "required": false, + "in": "query", + "schema": { + "$ref": "#/components/schemas/NotificationType" + } + }, + { + "name": "unread", + "required": false, + "in": "query", + "schema": { + "type": "boolean" + } + } + ], "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TemplateResponseDto" + "items": { + "$ref": "#/components/schemas/NotificationDto" + }, + "type": "array" } } }, @@ -3534,17 +3720,133 @@ "tags": [ "Notifications" ] - } - }, - "/notifications/test-email": { - "post": { - "operationId": "sendTestEmail", + }, + "put": { + "operationId": "updateNotifications", "parameters": [], "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SystemConfigSmtpDto" + "$ref": "#/components/schemas/NotificationUpdateAllDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "" + } + }, + "security": [ + { + "bearer": [] + }, + { + "cookie": [] + }, + { + "api_key": [] + } + ], + "tags": [ + "Notifications" + ] + } + }, + "/notifications/{id}": { + "delete": { + "operationId": "deleteNotification", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "security": [ + { + "bearer": [] + }, + { + "cookie": [] + }, + { + "api_key": [] + } + ], + "tags": [ + "Notifications" + ] + }, + "get": { + "operationId": "getNotification", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotificationDto" + } + } + }, + "description": "" + } + }, + "security": [ + { + "bearer": [] + }, + { + "cookie": [] + }, + { + "api_key": [] + } + ], + "tags": [ + "Notifications" + ] + }, + "put": { + "operationId": "updateNotification", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotificationUpdateDto" } } }, @@ -3555,7 +3857,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TestEmailResponseDto" + "$ref": "#/components/schemas/NotificationDto" } } }, @@ -4349,118 +4651,6 @@ ] } }, - "/reports": { - "get": { - "operationId": "getAuditFiles", - "parameters": [], - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FileReportDto" - } - } - }, - "description": "" - } - }, - "security": [ - { - "bearer": [] - }, - { - "cookie": [] - }, - { - "api_key": [] - } - ], - "tags": [ - "File Reports" - ] - } - }, - "/reports/checksum": { - "post": { - "operationId": "getFileChecksums", - "parameters": [], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FileChecksumDto" - } - } - }, - "required": true - }, - "responses": { - "201": { - "content": { - "application/json": { - "schema": { - "items": { - "$ref": "#/components/schemas/FileChecksumResponseDto" - }, - "type": "array" - } - } - }, - "description": "" - } - }, - "security": [ - { - "bearer": [] - }, - { - "cookie": [] - }, - { - "api_key": [] - } - ], - "tags": [ - "File Reports" - ] - } - }, - "/reports/fix": { - "post": { - "operationId": "fixAuditFiles", - "parameters": [], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FileReportFixDto" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "" - } - }, - "security": [ - { - "bearer": [] - }, - { - "cookie": [] - }, - { - "api_key": [] - } - ], - "tags": [ - "File Reports" - ] - } - }, "/search/cities": { "get": { "operationId": "getAssetsByCity", @@ -7656,7 +7846,7 @@ "info": { "title": "Immich", "description": "Immich API", - "version": "1.131.3", + "version": "1.132.3", "contact": {} }, "tags": [], @@ -8884,21 +9074,6 @@ ], "type": "string" }, - "AvatarResponse": { - "properties": { - "color": { - "allOf": [ - { - "$ref": "#/components/schemas/UserAvatarColor" - } - ] - } - }, - "required": [ - "color" - ], - "type": "object" - }, "AvatarUpdate": { "properties": { "color": { @@ -9462,105 +9637,6 @@ ], "type": "object" }, - "FileChecksumDto": { - "properties": { - "filenames": { - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "filenames" - ], - "type": "object" - }, - "FileChecksumResponseDto": { - "properties": { - "checksum": { - "type": "string" - }, - "filename": { - "type": "string" - } - }, - "required": [ - "checksum", - "filename" - ], - "type": "object" - }, - "FileReportDto": { - "properties": { - "extras": { - "items": { - "type": "string" - }, - "type": "array" - }, - "orphans": { - "items": { - "$ref": "#/components/schemas/FileReportItemDto" - }, - "type": "array" - } - }, - "required": [ - "extras", - "orphans" - ], - "type": "object" - }, - "FileReportFixDto": { - "properties": { - "items": { - "items": { - "$ref": "#/components/schemas/FileReportItemDto" - }, - "type": "array" - } - }, - "required": [ - "items" - ], - "type": "object" - }, - "FileReportItemDto": { - "properties": { - "checksum": { - "type": "string" - }, - "entityId": { - "format": "uuid", - "type": "string" - }, - "entityType": { - "allOf": [ - { - "$ref": "#/components/schemas/PathEntityType" - } - ] - }, - "pathType": { - "allOf": [ - { - "$ref": "#/components/schemas/PathType" - } - ] - }, - "pathValue": { - "type": "string" - } - }, - "required": [ - "entityId", - "entityType", - "pathType", - "pathValue" - ], - "type": "object" - }, "FoldersResponse": { "properties": { "enabled": { @@ -10341,6 +10417,157 @@ }, "type": "object" }, + "NotificationCreateDto": { + "properties": { + "data": { + "type": "object" + }, + "description": { + "nullable": true, + "type": "string" + }, + "level": { + "allOf": [ + { + "$ref": "#/components/schemas/NotificationLevel" + } + ] + }, + "readAt": { + "format": "date-time", + "nullable": true, + "type": "string" + }, + "title": { + "type": "string" + }, + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/NotificationType" + } + ] + }, + "userId": { + "format": "uuid", + "type": "string" + } + }, + "required": [ + "title", + "userId" + ], + "type": "object" + }, + "NotificationDeleteAllDto": { + "properties": { + "ids": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "ids" + ], + "type": "object" + }, + "NotificationDto": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "data": { + "type": "object" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "level": { + "allOf": [ + { + "$ref": "#/components/schemas/NotificationLevel" + } + ] + }, + "readAt": { + "format": "date-time", + "type": "string" + }, + "title": { + "type": "string" + }, + "type": { + "allOf": [ + { + "$ref": "#/components/schemas/NotificationType" + } + ] + } + }, + "required": [ + "createdAt", + "id", + "level", + "title", + "type" + ], + "type": "object" + }, + "NotificationLevel": { + "enum": [ + "success", + "error", + "warning", + "info" + ], + "type": "string" + }, + "NotificationType": { + "enum": [ + "JobFailed", + "BackupFailed", + "SystemMessage", + "Custom" + ], + "type": "string" + }, + "NotificationUpdateAllDto": { + "properties": { + "ids": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + }, + "readAt": { + "format": "date-time", + "nullable": true, + "type": "string" + } + }, + "required": [ + "ids" + ], + "type": "object" + }, + "NotificationUpdateDto": { + "properties": { + "readAt": { + "format": "date-time", + "nullable": true, + "type": "string" + } + }, + "type": "object" + }, "OAuthAuthorizeResponseDto": { "properties": { "url": { @@ -10354,6 +10581,12 @@ }, "OAuthCallbackDto": { "properties": { + "codeVerifier": { + "type": "string" + }, + "state": { + "type": "string" + }, "url": { "type": "string" } @@ -10365,8 +10598,14 @@ }, "OAuthConfigDto": { "properties": { + "codeChallenge": { + "type": "string" + }, "redirectUri": { "type": "string" + }, + "state": { + "type": "string" } }, "required": [ @@ -10374,6 +10613,13 @@ ], "type": "object" }, + "OAuthTokenEndpointAuthMethod": { + "enum": [ + "client_secret_post", + "client_secret_basic" + ], + "type": "string" + }, "OnThisDayDto": { "properties": { "year": { @@ -10432,27 +10678,6 @@ ], "type": "object" }, - "PathEntityType": { - "enum": [ - "asset", - "person", - "user" - ], - "type": "string" - }, - "PathType": { - "enum": [ - "original", - "fullsize", - "preview", - "thumbnail", - "encoded_video", - "sidecar", - "face", - "profile" - ], - "type": "string" - }, "PeopleResponse": { "properties": { "enabled": { @@ -10603,6 +10828,10 @@ "memory.read", "memory.update", "memory.delete", + "notification.create", + "notification.read", + "notification.update", + "notification.delete", "partner.create", "partner.read", "partner.update", @@ -12954,6 +13183,17 @@ }, "storageQuotaClaim": { "type": "string" + }, + "timeout": { + "minimum": 1, + "type": "integer" + }, + "tokenEndpointAuthMethod": { + "allOf": [ + { + "$ref": "#/components/schemas/OAuthTokenEndpointAuthMethod" + } + ] } }, "required": [ @@ -12971,7 +13211,9 @@ "scope", "signingAlgorithm", "storageLabelClaim", - "storageQuotaClaim" + "storageQuotaClaim", + "timeout", + "tokenEndpointAuthMethod" ], "type": "object" }, @@ -13613,6 +13855,14 @@ }, "UserAdminCreateDto": { "properties": { + "avatarColor": { + "allOf": [ + { + "$ref": "#/components/schemas/UserAvatarColor" + } + ], + "nullable": true + }, "email": { "format": "email", "type": "string" @@ -13755,6 +14005,14 @@ }, "UserAdminUpdateDto": { "properties": { + "avatarColor": { + "allOf": [ + { + "$ref": "#/components/schemas/UserAvatarColor" + } + ], + "nullable": true + }, "email": { "format": "email", "type": "string" @@ -13818,9 +14076,6 @@ }, "UserPreferencesResponseDto": { "properties": { - "avatar": { - "$ref": "#/components/schemas/AvatarResponse" - }, "download": { "$ref": "#/components/schemas/DownloadResponse" }, @@ -13850,7 +14105,6 @@ } }, "required": [ - "avatar", "download", "emailNotifications", "folders", @@ -13944,6 +14198,14 @@ }, "UserUpdateMeDto": { "properties": { + "avatarColor": { + "allOf": [ + { + "$ref": "#/components/schemas/UserAvatarColor" + } + ], + "nullable": true + }, "email": { "format": "email", "type": "string" diff --git a/open-api/typescript-sdk/package-lock.json b/open-api/typescript-sdk/package-lock.json index 761a228de0..c102f594cf 100644 --- a/open-api/typescript-sdk/package-lock.json +++ b/open-api/typescript-sdk/package-lock.json @@ -1,18 +1,18 @@ { "name": "@immich/sdk", - "version": "1.131.3", + "version": "1.132.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@immich/sdk", - "version": "1.131.3", + "version": "1.132.3", "license": "GNU Affero General Public License version 3", "dependencies": { "@oazapfts/runtime": "^1.0.2" }, "devDependencies": { - "@types/node": "^22.14.0", + "@types/node": "^22.14.1", "typescript": "^5.3.3" } }, @@ -23,9 +23,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.14.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.0.tgz", - "integrity": "sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA==", + "version": "22.14.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz", + "integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/open-api/typescript-sdk/package.json b/open-api/typescript-sdk/package.json index 29fe50dcd9..70f76512b4 100644 --- a/open-api/typescript-sdk/package.json +++ b/open-api/typescript-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@immich/sdk", - "version": "1.131.3", + "version": "1.132.3", "description": "Auto-generated TypeScript SDK for the Immich API", "type": "module", "main": "./build/index.js", @@ -19,7 +19,7 @@ "@oazapfts/runtime": "^1.0.2" }, "devDependencies": { - "@types/node": "^22.14.0", + "@types/node": "^22.14.1", "typescript": "^5.3.3" }, "repository": { diff --git a/open-api/typescript-sdk/src/fetch-client.ts b/open-api/typescript-sdk/src/fetch-client.ts index f82f5bc9a7..2684d2558f 100644 --- a/open-api/typescript-sdk/src/fetch-client.ts +++ b/open-api/typescript-sdk/src/fetch-client.ts @@ -1,6 +1,6 @@ /** * Immich - * 1.131.3 + * 1.132.3 * DO NOT MODIFY - This file has been generated using oazapfts. * See https://www.npmjs.com/package/oazapfts */ @@ -39,6 +39,48 @@ export type ActivityCreateDto = { export type ActivityStatisticsResponseDto = { comments: number; }; +export type NotificationCreateDto = { + data?: object; + description?: string | null; + level?: NotificationLevel; + readAt?: string | null; + title: string; + "type"?: NotificationType; + userId: string; +}; +export type NotificationDto = { + createdAt: string; + data?: object; + description?: string; + id: string; + level: NotificationLevel; + readAt?: string; + title: string; + "type": NotificationType; +}; +export type TemplateDto = { + template: string; +}; +export type TemplateResponseDto = { + html: string; + name: string; +}; +export type SystemConfigSmtpTransportDto = { + host: string; + ignoreCert: boolean; + password: string; + port: number; + username: string; +}; +export type SystemConfigSmtpDto = { + enabled: boolean; + "from": string; + replyTo: string; + transport: SystemConfigSmtpTransportDto; +}; +export type TestEmailResponseDto = { + messageId: string; +}; export type UserLicense = { activatedAt: string; activationKey: string; @@ -64,6 +106,7 @@ export type UserAdminResponseDto = { updatedAt: string; }; export type UserAdminCreateDto = { + avatarColor?: (UserAvatarColor) | null; email: string; name: string; notify?: boolean; @@ -76,6 +119,7 @@ export type UserAdminDeleteDto = { force?: boolean; }; export type UserAdminUpdateDto = { + avatarColor?: (UserAvatarColor) | null; email?: string; name?: string; password?: string; @@ -83,9 +127,6 @@ export type UserAdminUpdateDto = { shouldChangePassword?: boolean; storageLabel?: string | null; }; -export type AvatarResponse = { - color: UserAvatarColor; -}; export type DownloadResponse = { archiveSize: number; includeEmbeddedVideos: boolean; @@ -122,7 +163,6 @@ export type TagsResponse = { sidebarWeb: boolean; }; export type UserPreferencesResponseDto = { - avatar: AvatarResponse; download: DownloadResponse; emailNotifications: EmailNotificationsResponse; folders: FoldersResponse; @@ -663,36 +703,27 @@ export type MemoryUpdateDto = { memoryAt?: string; seenAt?: string; }; -export type TemplateDto = { - template: string; +export type NotificationDeleteAllDto = { + ids: string[]; }; -export type TemplateResponseDto = { - html: string; - name: string; +export type NotificationUpdateAllDto = { + ids: string[]; + readAt?: string | null; }; -export type SystemConfigSmtpTransportDto = { - host: string; - ignoreCert: boolean; - password: string; - port: number; - username: string; -}; -export type SystemConfigSmtpDto = { - enabled: boolean; - "from": string; - replyTo: string; - transport: SystemConfigSmtpTransportDto; -}; -export type TestEmailResponseDto = { - messageId: string; +export type NotificationUpdateDto = { + readAt?: string | null; }; export type OAuthConfigDto = { + codeChallenge?: string; redirectUri: string; + state?: string; }; export type OAuthAuthorizeResponseDto = { url: string; }; export type OAuthCallbackDto = { + codeVerifier?: string; + state?: string; url: string; }; export type PartnerResponseDto = { @@ -769,27 +800,6 @@ export type AssetFaceUpdateDto = { export type PersonStatisticsResponseDto = { assets: number; }; -export type FileReportItemDto = { - checksum?: string; - entityId: string; - entityType: PathEntityType; - pathType: PathType; - pathValue: string; -}; -export type FileReportDto = { - extras: string[]; - orphans: FileReportItemDto[]; -}; -export type FileChecksumDto = { - filenames: string[]; -}; -export type FileChecksumResponseDto = { - checksum: string; - filename: string; -}; -export type FileReportFixDto = { - items: FileReportItemDto[]; -}; export type SearchExploreItem = { data: AssetResponseDto; value: string; @@ -1284,6 +1294,8 @@ export type SystemConfigOAuthDto = { signingAlgorithm: string; storageLabelClaim: string; storageQuotaClaim: string; + timeout: number; + tokenEndpointAuthMethod: OAuthTokenEndpointAuthMethod; }; export type SystemConfigPasswordLoginDto = { enabled: boolean; @@ -1384,6 +1396,7 @@ export type TrashResponseDto = { count: number; }; export type UserUpdateMeDto = { + avatarColor?: (UserAvatarColor) | null; email?: string; name?: string; password?: string; @@ -1450,6 +1463,43 @@ export function deleteActivity({ id }: { method: "DELETE" })); } +export function createNotification({ notificationCreateDto }: { + notificationCreateDto: NotificationCreateDto; +}, opts?: Oazapfts.RequestOpts) { + return oazapfts.ok(oazapfts.fetchJson<{ + status: 201; + data: NotificationDto; + }>("/admin/notifications", oazapfts.json({ + ...opts, + method: "POST", + body: notificationCreateDto + }))); +} +export function getNotificationTemplateAdmin({ name, templateDto }: { + name: string; + templateDto: TemplateDto; +}, opts?: Oazapfts.RequestOpts) { + return oazapfts.ok(oazapfts.fetchJson<{ + status: 200; + data: TemplateResponseDto; + }>(`/admin/notifications/templates/${encodeURIComponent(name)}`, oazapfts.json({ + ...opts, + method: "POST", + body: templateDto + }))); +} +export function sendTestEmailAdmin({ systemConfigSmtpDto }: { + systemConfigSmtpDto: SystemConfigSmtpDto; +}, opts?: Oazapfts.RequestOpts) { + return oazapfts.ok(oazapfts.fetchJson<{ + status: 200; + data: TestEmailResponseDto; + }>("/admin/notifications/test-email", oazapfts.json({ + ...opts, + method: "POST", + body: systemConfigSmtpDto + }))); +} export function searchUsersAdmin({ withDeleted }: { withDeleted?: boolean; }, opts?: Oazapfts.RequestOpts) { @@ -2318,29 +2368,71 @@ export function addMemoryAssets({ id, bulkIdsDto }: { body: bulkIdsDto }))); } -export function getNotificationTemplate({ name, templateDto }: { - name: string; - templateDto: TemplateDto; +export function deleteNotifications({ notificationDeleteAllDto }: { + notificationDeleteAllDto: NotificationDeleteAllDto; }, opts?: Oazapfts.RequestOpts) { - return oazapfts.ok(oazapfts.fetchJson<{ - status: 200; - data: TemplateResponseDto; - }>(`/notifications/templates/${encodeURIComponent(name)}`, oazapfts.json({ + return oazapfts.ok(oazapfts.fetchText("/notifications", oazapfts.json({ ...opts, - method: "POST", - body: templateDto + method: "DELETE", + body: notificationDeleteAllDto }))); } -export function sendTestEmail({ systemConfigSmtpDto }: { - systemConfigSmtpDto: SystemConfigSmtpDto; +export function getNotifications({ id, level, $type, unread }: { + id?: string; + level?: NotificationLevel; + $type?: NotificationType; + unread?: boolean; }, opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; - data: TestEmailResponseDto; - }>("/notifications/test-email", oazapfts.json({ + data: NotificationDto[]; + }>(`/notifications${QS.query(QS.explode({ + id, + level, + "type": $type, + unread + }))}`, { + ...opts + })); +} +export function updateNotifications({ notificationUpdateAllDto }: { + notificationUpdateAllDto: NotificationUpdateAllDto; +}, opts?: Oazapfts.RequestOpts) { + return oazapfts.ok(oazapfts.fetchText("/notifications", oazapfts.json({ ...opts, - method: "POST", - body: systemConfigSmtpDto + method: "PUT", + body: notificationUpdateAllDto + }))); +} +export function deleteNotification({ id }: { + id: string; +}, opts?: Oazapfts.RequestOpts) { + return oazapfts.ok(oazapfts.fetchText(`/notifications/${encodeURIComponent(id)}`, { + ...opts, + method: "DELETE" + })); +} +export function getNotification({ id }: { + id: string; +}, opts?: Oazapfts.RequestOpts) { + return oazapfts.ok(oazapfts.fetchJson<{ + status: 200; + data: NotificationDto; + }>(`/notifications/${encodeURIComponent(id)}`, { + ...opts + })); +} +export function updateNotification({ id, notificationUpdateDto }: { + id: string; + notificationUpdateDto: NotificationUpdateDto; +}, opts?: Oazapfts.RequestOpts) { + return oazapfts.ok(oazapfts.fetchJson<{ + status: 200; + data: NotificationDto; + }>(`/notifications/${encodeURIComponent(id)}`, oazapfts.json({ + ...opts, + method: "PUT", + body: notificationUpdateDto }))); } export function startOAuth({ oAuthConfigDto }: { @@ -2550,35 +2642,6 @@ export function getPersonThumbnail({ id }: { ...opts })); } -export function getAuditFiles(opts?: Oazapfts.RequestOpts) { - return oazapfts.ok(oazapfts.fetchJson<{ - status: 200; - data: FileReportDto; - }>("/reports", { - ...opts - })); -} -export function getFileChecksums({ fileChecksumDto }: { - fileChecksumDto: FileChecksumDto; -}, opts?: Oazapfts.RequestOpts) { - return oazapfts.ok(oazapfts.fetchJson<{ - status: 201; - data: FileChecksumResponseDto[]; - }>("/reports/checksum", oazapfts.json({ - ...opts, - method: "POST", - body: fileChecksumDto - }))); -} -export function fixAuditFiles({ fileReportFixDto }: { - fileReportFixDto: FileReportFixDto; -}, opts?: Oazapfts.RequestOpts) { - return oazapfts.ok(oazapfts.fetchText("/reports/fix", oazapfts.json({ - ...opts, - method: "POST", - body: fileReportFixDto - }))); -} export function getAssetsByCity(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3449,6 +3512,18 @@ export enum UserAvatarColor { Gray = "gray", Amber = "amber" } +export enum NotificationLevel { + Success = "success", + Error = "error", + Warning = "warning", + Info = "info" +} +export enum NotificationType { + JobFailed = "JobFailed", + BackupFailed = "BackupFailed", + SystemMessage = "SystemMessage", + Custom = "Custom" +} export enum UserStatus { Active = "active", Removing = "removing", @@ -3523,6 +3598,10 @@ export enum Permission { MemoryRead = "memory.read", MemoryUpdate = "memory.update", MemoryDelete = "memory.delete", + NotificationCreate = "notification.create", + NotificationRead = "notification.read", + NotificationUpdate = "notification.update", + NotificationDelete = "notification.delete", PartnerCreate = "partner.create", PartnerRead = "partner.read", PartnerUpdate = "partner.update", @@ -3622,21 +3701,6 @@ export enum PartnerDirection { SharedBy = "shared-by", SharedWith = "shared-with" } -export enum PathEntityType { - Asset = "asset", - Person = "person", - User = "user" -} -export enum PathType { - Original = "original", - Fullsize = "fullsize", - Preview = "preview", - Thumbnail = "thumbnail", - EncodedVideo = "encoded_video", - Sidecar = "sidecar", - Face = "face", - Profile = "profile" -} export enum SearchSuggestionType { Country = "country", State = "state", @@ -3732,6 +3796,10 @@ export enum LogLevel { Error = "error", Fatal = "fatal" } +export enum OAuthTokenEndpointAuthMethod { + ClientSecretPost = "client_secret_post", + ClientSecretBasic = "client_secret_basic" +} export enum TimeBucketSize { Day = "DAY", Month = "MONTH" diff --git a/server/Dockerfile b/server/Dockerfile index 84037031fd..5c0ef076c4 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -6,14 +6,14 @@ WORKDIR /usr/src/app COPY server/package.json server/package-lock.json ./ COPY server/patches ./patches RUN npm ci && \ - # exiftool-vendored.pl, sharp-linux-x64 and sharp-linux-arm64 are the only ones we need - # they're marked as optional dependencies, so we need to copy them manually after pruning - rm -rf node_modules/@img/sharp-libvips* && \ - rm -rf node_modules/@img/sharp-linuxmusl-x64 + # exiftool-vendored.pl, sharp-linux-x64 and sharp-linux-arm64 are the only ones we need + # they're marked as optional dependencies, so we need to copy them manually after pruning + rm -rf node_modules/@img/sharp-libvips* && \ + rm -rf node_modules/@img/sharp-linuxmusl-x64 ENV PATH="${PATH}:/usr/src/app/bin" \ - IMMICH_ENV=development \ - NVIDIA_DRIVER_CAPABILITIES=all \ - NVIDIA_VISIBLE_DEVICES=all + IMMICH_ENV=development \ + NVIDIA_DRIVER_CAPABILITIES=all \ + NVIDIA_VISIBLE_DEVICES=all ENTRYPOINT ["tini", "--", "/bin/sh"] @@ -26,7 +26,7 @@ COPY --from=dev /usr/src/app/node_modules/@img ./node_modules/@img COPY --from=dev /usr/src/app/node_modules/exiftool-vendored.pl ./node_modules/exiftool-vendored.pl # web build -FROM node:22.14.0-alpine3.20@sha256:40be979442621049f40b1d51a26b55e281246b5de4e5f51a18da7beb6e17e3f9 AS web +FROM node:22.15.0-alpine3.20@sha256:686b8892b69879ef5bfd6047589666933508f9a5451c67320df3070ba0e9807b AS web WORKDIR /usr/src/open-api/typescript-sdk COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./ @@ -47,8 +47,8 @@ FROM ghcr.io/immich-app/base-server-prod:202504081114@sha256:8353bcbdb4e6579300a WORKDIR /usr/src/app ENV NODE_ENV=production \ - NVIDIA_DRIVER_CAPABILITIES=all \ - NVIDIA_VISIBLE_DEVICES=all + NVIDIA_DRIVER_CAPABILITIES=all \ + NVIDIA_VISIBLE_DEVICES=all COPY --from=prod /usr/src/app/node_modules ./node_modules COPY --from=prod /usr/src/app/dist ./dist COPY --from=prod /usr/src/app/bin ./bin diff --git a/server/package-lock.json b/server/package-lock.json index 8045976b3c..4e451cc8e1 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -1,12 +1,12 @@ { "name": "immich", - "version": "1.131.3", + "version": "1.132.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "immich", - "version": "1.131.3", + "version": "1.132.3", "hasInstallScript": true, "license": "GNU Affero General Public License version 3", "dependencies": { @@ -19,7 +19,7 @@ "@nestjs/schedule": "^5.0.0", "@nestjs/swagger": "^11.0.2", "@nestjs/websockets": "^11.0.4", - "@opentelemetry/auto-instrumentations-node": "^0.57.0", + "@opentelemetry/auto-instrumentations-node": "^0.58.0", "@opentelemetry/context-async-hooks": "^2.0.0", "@opentelemetry/exporter-prometheus": "^0.200.0", "@opentelemetry/sdk-node": "^0.200.0", @@ -32,6 +32,7 @@ "chokidar": "^3.5.3", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", + "compression": "^1.8.0", "cookie": "^1.0.2", "cookie-parser": "^1.4.7", "exiftool-vendored": "^28.3.1", @@ -52,7 +53,7 @@ "nestjs-kysely": "^1.1.0", "nestjs-otel": "^6.0.0", "nodemailer": "^6.9.13", - "openid-client": "^5.4.3", + "openid-client": "^6.3.3", "pg": "^8.11.3", "picomatch": "^4.0.2", "react": "^19.0.0", @@ -63,7 +64,7 @@ "sanitize-filename": "^1.6.3", "sanitize-html": "^2.14.0", "semver": "^7.6.2", - "sharp": "^0.33.0", + "sharp": "^0.34.0", "sirv": "^3.0.0", "tailwindcss-preset-email": "^1.3.2", "thumbhash": "^0.1.1", @@ -83,6 +84,7 @@ "@types/archiver": "^6.0.0", "@types/async-lock": "^1.4.2", "@types/bcrypt": "^5.0.0", + "@types/compression": "^1.7.5", "@types/cookie-parser": "^1.4.8", "@types/express": "^4.17.17", "@types/fluent-ffmpeg": "^2.1.21", @@ -90,7 +92,7 @@ "@types/lodash": "^4.14.197", "@types/mock-fs": "^4.13.1", "@types/multer": "^1.4.7", - "@types/node": "^22.14.0", + "@types/node": "^22.14.1", "@types/nodemailer": "^6.4.14", "@types/picomatch": "^3.0.0", "@types/pngjs": "^6.0.5", @@ -105,8 +107,10 @@ "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-unicorn": "^57.0.0", "globals": "^16.0.0", + "jsdom": "^26.1.0", "mock-fs": "^5.2.0", - "node-addon-api": "^8.3.0", + "node-addon-api": "^8.3.1", + "node-gyp": "^11.2.0", "patch-package": "^8.0.0", "pngjs": "^7.0.0", "prettier": "^3.0.2", @@ -171,14 +175,14 @@ } }, "node_modules/@angular-devkit/schematics-cli": { - "version": "19.2.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-19.2.6.tgz", - "integrity": "sha512-OCLVk1YbTWfaZwpKPnd+9A34eMAZIRjntdugGvfw21ok9dUA8gICGDhfYATSfnU8/AbVQMTPK5sgG0xhUEm3UA==", + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-19.2.8.tgz", + "integrity": "sha512-RFnlyu4Ld8I4xvu/eqrhjbQ6kQTr27w79omMiTbQcQZvP3E6oUyZdBjobyih4Np+1VVQrbdEeNz76daP2iUDig==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "19.2.6", - "@angular-devkit/schematics": "19.2.6", + "@angular-devkit/core": "19.2.8", + "@angular-devkit/schematics": "19.2.8", "@inquirer/prompts": "7.3.2", "ansi-colors": "4.1.3", "symbol-observable": "4.0.0", @@ -194,9 +198,9 @@ } }, "node_modules/@angular-devkit/schematics-cli/node_modules/@angular-devkit/core": { - "version": "19.2.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.2.6.tgz", - "integrity": "sha512-WFgiYhrDMq83UNaGRAneIM7CYYdBozD+yYA9BjoU8AgBLKtrvn6S8ZcjKAk5heoHtY/u8pEb0mwDTz9gxFmJZQ==", + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.2.8.tgz", + "integrity": "sha512-kcxUHKf5Hi98r4gAvMP3ntJV8wuQ3/i6wuU9RcMP0UKUt2Rer5Ryis3MPqT92jvVVwg6lhrLIhXsFuWJMiYjXQ==", "dev": true, "license": "MIT", "dependencies": { @@ -221,6 +225,25 @@ } } }, + "node_modules/@angular-devkit/schematics-cli/node_modules/@angular-devkit/schematics": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.2.8.tgz", + "integrity": "sha512-QsmFuYdAyeCyg9WF/AJBhFXDUfCwmDFTEbsv5t5KPSP6slhk0GoLNZApniiFytU2siRlSxVNpve2uATyYuAYkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "19.2.8", + "jsonc-parser": "3.3.1", + "magic-string": "0.30.17", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, "node_modules/@angular-devkit/schematics-cli/node_modules/@inquirer/prompts": { "version": "7.3.2", "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.3.2.tgz", @@ -435,6 +458,20 @@ "node": ">= 8" } }, + "node_modules/@asamuzakjp/css-color": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.1.4.tgz", + "integrity": "sha512-SeuBV4rnjpFNjI8HSgKUwteuFdkHwkboq31HWzznuqgySQir+jSTczoWVVL4jvOjKjuH80fMDG0Fvg1Sb+OJsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^2.1.3", + "@csstools/css-color-parser": "^3.0.9", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "lru-cache": "^10.4.3" + } + }, "node_modules/@babel/code-frame": { "version": "7.26.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", @@ -720,272 +757,131 @@ "node": ">=0.1.90" } }, + "node_modules/@csstools/color-helpers": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz", + "integrity": "sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/css-calc": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.3.tgz", + "integrity": "sha512-XBG3talrhid44BY1x3MHzUx/aTG8+x/Zi57M4aTKK9RFB4aLlF3TTSzfzn8nWVHWL3FgAXAxmupmDd6VWww+pw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.9.tgz", + "integrity": "sha512-wILs5Zk7BU86UArYBJTPy/FMPPKVKHMj1ycCEyf3VUptol0JNRLFU/BZsJ4aiIHJEbSLiizzRrw8Pc1uAEDrXw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^5.0.2", + "@csstools/css-calc": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", + "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz", + "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/@emnapi/runtime": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.2.tgz", - "integrity": "sha512-+b+3BJl18a0LKeHvy5eLOwPkiaz10C2MUUYKQ25itZS50TlP5FuDh2Q5EiFlB++vAuCS6HnrihqVlbdcRYyp9w==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", + "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", "license": "MIT", "optional": true, "dependencies": { "tslib": "^2.4.0" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz", - "integrity": "sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.0.tgz", - "integrity": "sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz", - "integrity": "sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.0.tgz", - "integrity": "sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", - "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz", - "integrity": "sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz", - "integrity": "sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz", - "integrity": "sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz", - "integrity": "sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz", - "integrity": "sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz", - "integrity": "sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz", - "integrity": "sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==", - "cpu": [ - "loong64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz", - "integrity": "sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==", - "cpu": [ - "mips64el" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz", - "integrity": "sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz", - "integrity": "sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz", - "integrity": "sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@esbuild/linux-x64": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz", @@ -1002,135 +898,6 @@ "node": ">=18" } }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz", - "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz", - "integrity": "sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz", - "integrity": "sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz", - "integrity": "sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz", - "integrity": "sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz", - "integrity": "sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz", - "integrity": "sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz", - "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@eslint-community/eslint-utils": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.6.0.tgz", @@ -1199,9 +966,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", - "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", + "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1249,9 +1016,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.24.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.24.0.tgz", - "integrity": "sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==", + "version": "9.25.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.25.1.tgz", + "integrity": "sha512-dEIwmjntEx8u3Uvv+kr3PDeeArL8Hw07H9kyYxCjnM9pBjfEhk6uLXSchxxzgiwtRhhzVzqmUSDFBOi1TuZ7qg==", "dev": true, "license": "MIT", "engines": { @@ -1282,19 +1049,6 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", - "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, "node_modules/@fastify/busboy": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", @@ -1431,9 +1185,9 @@ } }, "node_modules/@img/sharp-darwin-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", - "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.1.tgz", + "integrity": "sha512-pn44xgBtgpEbZsu+lWf2KNb6OAf70X68k+yk69Ic2Xz11zHR/w24/U49XT7AeRwJ0Px+mhALhU5LPci1Aymk7A==", "cpu": [ "arm64" ], @@ -1449,13 +1203,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.0.4" + "@img/sharp-libvips-darwin-arm64": "1.1.0" } }, "node_modules/@img/sharp-darwin-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", - "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.1.tgz", + "integrity": "sha512-VfuYgG2r8BpYiOUN+BfYeFo69nP/MIwAtSJ7/Zpxc5QF3KS22z8Pvg3FkrSFJBPNQ7mmcUcYQFBmEQp7eu1F8Q==", "cpu": [ "x64" ], @@ -1471,13 +1225,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.0.4" + "@img/sharp-libvips-darwin-x64": "1.1.0" } }, "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", - "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.1.0.tgz", + "integrity": "sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==", "cpu": [ "arm64" ], @@ -1491,9 +1245,9 @@ } }, "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", - "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.1.0.tgz", + "integrity": "sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==", "cpu": [ "x64" ], @@ -1507,9 +1261,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", - "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.1.0.tgz", + "integrity": "sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==", "cpu": [ "arm" ], @@ -1523,9 +1277,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", - "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.1.0.tgz", + "integrity": "sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==", "cpu": [ "arm64" ], @@ -1538,10 +1292,26 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.1.0.tgz", + "integrity": "sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", - "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.1.0.tgz", + "integrity": "sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==", "cpu": [ "s390x" ], @@ -1555,9 +1325,9 @@ } }, "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", - "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.1.0.tgz", + "integrity": "sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==", "cpu": [ "x64" ], @@ -1571,9 +1341,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", - "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.1.0.tgz", + "integrity": "sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==", "cpu": [ "arm64" ], @@ -1587,9 +1357,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", - "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.1.0.tgz", + "integrity": "sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==", "cpu": [ "x64" ], @@ -1603,9 +1373,9 @@ } }, "node_modules/@img/sharp-linux-arm": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", - "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.1.tgz", + "integrity": "sha512-anKiszvACti2sGy9CirTlNyk7BjjZPiML1jt2ZkTdcvpLU1YH6CXwRAZCA2UmRXnhiIftXQ7+Oh62Ji25W72jA==", "cpu": [ "arm" ], @@ -1621,13 +1391,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.0.5" + "@img/sharp-libvips-linux-arm": "1.1.0" } }, "node_modules/@img/sharp-linux-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", - "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.1.tgz", + "integrity": "sha512-kX2c+vbvaXC6vly1RDf/IWNXxrlxLNpBVWkdpRq5Ka7OOKj6nr66etKy2IENf6FtOgklkg9ZdGpEu9kwdlcwOQ==", "cpu": [ "arm64" ], @@ -1643,13 +1413,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.0.4" + "@img/sharp-libvips-linux-arm64": "1.1.0" } }, "node_modules/@img/sharp-linux-s390x": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", - "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.1.tgz", + "integrity": "sha512-7s0KX2tI9mZI2buRipKIw2X1ufdTeaRgwmRabt5bi9chYfhur+/C1OXg3TKg/eag1W+6CCWLVmSauV1owmRPxA==", "cpu": [ "s390x" ], @@ -1665,13 +1435,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.0.4" + "@img/sharp-libvips-linux-s390x": "1.1.0" } }, "node_modules/@img/sharp-linux-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", - "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.1.tgz", + "integrity": "sha512-wExv7SH9nmoBW3Wr2gvQopX1k8q2g5V5Iag8Zk6AVENsjwd+3adjwxtp3Dcu2QhOXr8W9NusBU6XcQUohBZ5MA==", "cpu": [ "x64" ], @@ -1687,13 +1457,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.0.4" + "@img/sharp-libvips-linux-x64": "1.1.0" } }, "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", - "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.1.tgz", + "integrity": "sha512-DfvyxzHxw4WGdPiTF0SOHnm11Xv4aQexvqhRDAoD00MzHekAj9a/jADXeXYCDFH/DzYruwHbXU7uz+H+nWmSOQ==", "cpu": [ "arm64" ], @@ -1709,13 +1479,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" + "@img/sharp-libvips-linuxmusl-arm64": "1.1.0" } }, "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", - "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.1.tgz", + "integrity": "sha512-pax/kTR407vNb9qaSIiWVnQplPcGU8LRIJpDT5o8PdAx5aAA7AS3X9PS8Isw1/WfqgQorPotjrZL3Pqh6C5EBg==", "cpu": [ "x64" ], @@ -1731,20 +1501,20 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.0.4" + "@img/sharp-libvips-linuxmusl-x64": "1.1.0" } }, "node_modules/@img/sharp-wasm32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", - "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.1.tgz", + "integrity": "sha512-YDybQnYrLQfEpzGOQe7OKcyLUCML4YOXl428gOOzBgN6Gw0rv8dpsJ7PqTHxBnXnwXr8S1mYFSLSa727tpz0xg==", "cpu": [ "wasm32" ], "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { - "@emnapi/runtime": "^1.2.0" + "@emnapi/runtime": "^1.4.0" }, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" @@ -1754,9 +1524,9 @@ } }, "node_modules/@img/sharp-win32-ia32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", - "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.1.tgz", + "integrity": "sha512-WKf/NAZITnonBf3U1LfdjoMgNO5JYRSlhovhRhMxXVdvWYveM4kM3L8m35onYIdh75cOMCo1BexgVQcCDzyoWw==", "cpu": [ "ia32" ], @@ -1773,9 +1543,9 @@ } }, "node_modules/@img/sharp-win32-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", - "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.1.tgz", + "integrity": "sha512-hw1iIAHpNE8q3uMIRCgGOeDoz9KtFNarFLQclLxr/LK1VBkj8nby18RjFvr6aP7USRYAjTZW6yisnBWMX571Tw==", "cpu": [ "x64" ], @@ -2184,6 +1954,19 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", @@ -2335,58 +2118,6 @@ "integrity": "sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==", "license": "MIT" }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", - "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", - "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", - "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", - "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", @@ -2400,19 +2131,6 @@ "linux" ] }, - "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", - "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@nestjs/bull-shared": { "version": "11.0.2", "resolved": "https://registry.npmjs.org/@nestjs/bull-shared/-/bull-shared-11.0.2.tgz", @@ -2442,15 +2160,15 @@ } }, "node_modules/@nestjs/cli": { - "version": "11.0.6", - "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-11.0.6.tgz", - "integrity": "sha512-Xco8pTdWHCpTXPTYMkUGAE+C7JXvAv38oVUaQeL81o7UOAi39w8p456r+IjONN/7ekjzakWnqepDzuTtH5Xk5w==", + "version": "11.0.7", + "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-11.0.7.tgz", + "integrity": "sha512-svrP8j1R0/lQVJ8ZI3BlDtuZxmkvVJokUJSB04sr6uibunk2wHeVDDVLZvYBUorCdGU/RHJl1IufhqUBM91vAQ==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "19.2.6", - "@angular-devkit/schematics": "19.2.6", - "@angular-devkit/schematics-cli": "19.2.6", + "@angular-devkit/core": "19.2.8", + "@angular-devkit/schematics": "19.2.8", + "@angular-devkit/schematics-cli": "19.2.8", "@inquirer/prompts": "7.4.1", "@nestjs/schematics": "^11.0.1", "ansis": "3.17.0", @@ -2464,8 +2182,8 @@ "tree-kill": "1.2.2", "tsconfig-paths": "4.2.0", "tsconfig-paths-webpack-plugin": "4.2.0", - "typescript": "5.7.3", - "webpack": "5.98.0", + "typescript": "5.8.3", + "webpack": "5.99.6", "webpack-node-externals": "3.0.0" }, "bin": { @@ -2475,7 +2193,7 @@ "node": ">= 20.11" }, "peerDependencies": { - "@swc/cli": "^0.1.62 || ^0.3.0 || ^0.4.0 || ^0.5.0 || ^0.6.0", + "@swc/cli": "^0.1.62 || ^0.3.0 || ^0.4.0 || ^0.5.0 || ^0.6.0 || ^0.7.0", "@swc/core": "^1.3.62" }, "peerDependenciesMeta": { @@ -2488,9 +2206,9 @@ } }, "node_modules/@nestjs/cli/node_modules/@angular-devkit/core": { - "version": "19.2.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.2.6.tgz", - "integrity": "sha512-WFgiYhrDMq83UNaGRAneIM7CYYdBozD+yYA9BjoU8AgBLKtrvn6S8ZcjKAk5heoHtY/u8pEb0mwDTz9gxFmJZQ==", + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.2.8.tgz", + "integrity": "sha512-kcxUHKf5Hi98r4gAvMP3ntJV8wuQ3/i6wuU9RcMP0UKUt2Rer5Ryis3MPqT92jvVVwg6lhrLIhXsFuWJMiYjXQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2515,6 +2233,25 @@ } } }, + "node_modules/@nestjs/cli/node_modules/@angular-devkit/schematics": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.2.8.tgz", + "integrity": "sha512-QsmFuYdAyeCyg9WF/AJBhFXDUfCwmDFTEbsv5t5KPSP6slhk0GoLNZApniiFytU2siRlSxVNpve2uATyYuAYkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "19.2.8", + "jsonc-parser": "3.3.1", + "magic-string": "0.30.17", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, "node_modules/@nestjs/cli/node_modules/ajv": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", @@ -2589,27 +2326,15 @@ "node": ">= 8" } }, - "node_modules/@nestjs/cli/node_modules/typescript": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", - "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/@nestjs/common": { - "version": "11.0.17", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.0.17.tgz", - "integrity": "sha512-FwKylI/hVxaNvzBJdWMMG1LH0cLKz4Oh4jKOHet2JUVMM9j6CuodRbrSnL++KL6PJY/b2E6AY58UDPLNeCqJWw==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.1.0.tgz", + "integrity": "sha512-8MrajltjtIN6eW9cTpv+1IZogqz2Zsrc8YDt0LwQPUq8cSq0j50DETdQpPsNMeib+p9avkV41+NrzGk1z2o5Wg==", "license": "MIT", "dependencies": { + "file-type": "20.4.1", "iterare": "1.2.1", + "load-esm": "1.0.2", "tslib": "2.8.1", "uid": "2.0.2" }, @@ -2620,7 +2345,6 @@ "peerDependencies": { "class-transformer": "*", "class-validator": "*", - "file-type": "^20.4.1", "reflect-metadata": "^0.1.12 || ^0.2.0", "rxjs": "^7.1.0" }, @@ -2630,16 +2354,13 @@ }, "class-validator": { "optional": true - }, - "file-type": { - "optional": true } } }, "node_modules/@nestjs/core": { - "version": "11.0.17", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-11.0.17.tgz", - "integrity": "sha512-ImK6qNxtegKqK7EJLGTBpP5Ild/DTpcduEtAOS+WLLjZOMjK1k214G9roXvlrNQwlVt9ALAY2jcqnsasdEd7Ow==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-11.1.0.tgz", + "integrity": "sha512-IeXbTRPrr6xAVbETlDE+miSkNmYf/cPhCa9GU9gFtPO6pVNuAeG/dNrjLVc23mJtUlT/ibdsoW35TlSyHLkzEA==", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -2711,9 +2432,9 @@ } }, "node_modules/@nestjs/platform-express": { - "version": "11.0.17", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.0.17.tgz", - "integrity": "sha512-et6Ydd6dR0FlcE/WR/9VRnQoTqEpDdzBgGK+aWadA0dFJ65wlN+snJRg/9JGP4ngj90S6xwe0VKD/BbfUGj9cw==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.1.0.tgz", + "integrity": "sha512-lxv73GT9VdQaxndciqKcyzLsT2j3gMRX+tO6J06oa7RIfp4Dp4oMTIu57lM1gkIJ+gLGq29bob+mfPv/K8RIuw==", "license": "MIT", "dependencies": { "cors": "2.8.5", @@ -2732,9 +2453,9 @@ } }, "node_modules/@nestjs/platform-socket.io": { - "version": "11.0.17", - "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-11.0.17.tgz", - "integrity": "sha512-l9b8VNb7N7rB9IUwKeln2bMQDltsR9mpenzHOaYYqDkz5BtuQSiyT8NpLR2vWhxDjppxMY3DkW8fQAvXh54pMg==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-11.1.0.tgz", + "integrity": "sha512-aCNuHln9RmT/qHkCr0/bcHxUP4rNU9hXK8O1Rd6EpDhJ9UcgMhatjkYDE95Tc7QgSgjLVscQ47pI2J8ik9b0VQ==", "license": "MIT", "dependencies": { "socket.io": "4.8.1", @@ -2887,9 +2608,9 @@ } }, "node_modules/@nestjs/swagger": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-11.1.3.tgz", - "integrity": "sha512-vhbW/Xu05Diti/EwYQp3Ea7Hj2M++wiakCcxqUUDA2n7NvCZC8LKsrcGynw6/x/lugdXyklYS+s2FhdAfeAikg==", + "version": "11.1.5", + "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-11.1.5.tgz", + "integrity": "sha512-qVkyUSCvEmfTVWK92hsCeOQaOODlyBGkZC4ldqb4Fi0Gg8/kOWlcPJVN6i4a9edYYSdICUkGnt6UVFgi59fSrQ==", "license": "MIT", "dependencies": { "@microsoft/tsdoc": "0.15.1", @@ -2920,9 +2641,9 @@ } }, "node_modules/@nestjs/testing": { - "version": "11.0.17", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-11.0.17.tgz", - "integrity": "sha512-ryEx6fCYZFCsjEBZo8jOVikQluEHMESocVqHdXWOkkG7UqMPMHimf9gT2qij0GpNnYeDAGw+i7FhSJN3Cajoug==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-11.1.0.tgz", + "integrity": "sha512-gQ+NGshkHbNrDNXMVaPiwduqZ8YHpXrnsQqhSsnyNYOcDNPdBbB+0FDq7XiiklluXqjdLAN8i+bS7MbGlZIhKw==", "dev": true, "license": "MIT", "dependencies": { @@ -2948,9 +2669,9 @@ } }, "node_modules/@nestjs/websockets": { - "version": "11.0.17", - "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-11.0.17.tgz", - "integrity": "sha512-2LSjxA/lUKs5hv/g5lPk555CoRNTCt/XywHFteKMSrxo09Cq3yfOQOAPwEWG929EnqAjAAsQaDVbfUHUFisFCg==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-11.1.0.tgz", + "integrity": "sha512-nb96cbmk7u6XIj4yIieezX9qqDshauyQJ4SLtdg2BaxOrkeQSx2j34CQWn/DZHHoYIQimfnAj2ry3RYWET4+zw==", "license": "MIT", "dependencies": { "iterare": "1.2.1", @@ -3139,6 +2860,60 @@ "node": ">= 8" } }, + "node_modules/@npmcli/agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-3.0.0.tgz", + "integrity": "sha512-S79NdEgDQd/NGCay6TCoVzXSj74skRZIKJcpJjC5lOq34SZzyI6MqtiiWoiVWoVrTcGjNeC4ipbh1VIHlpfF5Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.3" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@npmcli/agent/node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/@npmcli/agent/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@npmcli/fs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-4.0.0.tgz", + "integrity": "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/@nuxt/opencollective": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@nuxt/opencollective/-/opencollective-0.4.1.tgz", @@ -3177,9 +2952,9 @@ } }, "node_modules/@opentelemetry/auto-instrumentations-node": { - "version": "0.57.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.57.1.tgz", - "integrity": "sha512-yy+K3vYybqJ6Z4XZCXYYxEC1DtEpPrnJdwxkhI0sTtVlrVnzx49iRLqpMmdvQ4b09+PrvXSN9t0jODMCGNrs8w==", + "version": "0.58.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.58.0.tgz", + "integrity": "sha512-gtqPqkXp8TG6vrmbzAJUKjJm3nrCiVGgImlV1tj8lsVqpnKDCB1Kl7bCcXod36+Tq/O4rCeTDmW90dCHeuv9jQ==", "license": "Apache-2.0", "dependencies": { "@opentelemetry/instrumentation": "^0.200.0", @@ -3192,7 +2967,7 @@ "@opentelemetry/instrumentation-cucumber": "^0.15.0", "@opentelemetry/instrumentation-dataloader": "^0.17.0", "@opentelemetry/instrumentation-dns": "^0.44.0", - "@opentelemetry/instrumentation-express": "^0.48.0", + "@opentelemetry/instrumentation-express": "^0.48.1", "@opentelemetry/instrumentation-fastify": "^0.45.0", "@opentelemetry/instrumentation-fs": "^0.20.0", "@opentelemetry/instrumentation-generic-pool": "^0.44.0", @@ -3201,7 +2976,7 @@ "@opentelemetry/instrumentation-hapi": "^0.46.0", "@opentelemetry/instrumentation-http": "^0.200.0", "@opentelemetry/instrumentation-ioredis": "^0.48.0", - "@opentelemetry/instrumentation-kafkajs": "^0.9.0", + "@opentelemetry/instrumentation-kafkajs": "^0.9.1", "@opentelemetry/instrumentation-knex": "^0.45.0", "@opentelemetry/instrumentation-koa": "^0.48.0", "@opentelemetry/instrumentation-lru-memoizer": "^0.45.0", @@ -3218,6 +2993,7 @@ "@opentelemetry/instrumentation-redis-4": "^0.47.0", "@opentelemetry/instrumentation-restify": "^0.46.0", "@opentelemetry/instrumentation-router": "^0.45.0", + "@opentelemetry/instrumentation-runtime-node": "^0.14.0", "@opentelemetry/instrumentation-socket.io": "^0.47.0", "@opentelemetry/instrumentation-tedious": "^0.19.0", "@opentelemetry/instrumentation-undici": "^0.11.0", @@ -3664,9 +3440,9 @@ } }, "node_modules/@opentelemetry/instrumentation-express": { - "version": "0.48.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.48.0.tgz", - "integrity": "sha512-x9L6YD7AfE+7hysSv8k0d0sFmq3Vo3zoa/5eeJBYkGWHnD92CvekKouPyqUt71oX0htmZRdIawrhrwrAi2sonQ==", + "version": "0.48.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.48.1.tgz", + "integrity": "sha512-j8NYOf9DRWtchbWor/zA0poI42TpZG9tViIKA0e1lC+6MshTqSJYtgNv8Fn1sx1Wn/TRyp+5OgSXiE4LDfvpEg==", "license": "Apache-2.0", "dependencies": { "@opentelemetry/core": "^2.0.0", @@ -3812,9 +3588,9 @@ } }, "node_modules/@opentelemetry/instrumentation-kafkajs": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.9.0.tgz", - "integrity": "sha512-Uxt/LTSmrzTYtnPpPn/L2W7+tjn38+v8tSnJ7hvaE3/aRXmZA5e72n+pHv0mlCI0pVNTihiQCUE62XYWPZ4jjA==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.9.1.tgz", + "integrity": "sha512-eGl5WKBqd0unOKm7PJKjEa1G+ac9nvpDjyv870nUYuSnUkyDc/Fag5keddIjHixTJwRp3FmyP7n+AadAjh52Vw==", "license": "Apache-2.0", "dependencies": { "@opentelemetry/instrumentation": "^0.200.0", @@ -4095,6 +3871,21 @@ "@opentelemetry/api": "^1.3.0" } }, + "node_modules/@opentelemetry/instrumentation-runtime-node": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-runtime-node/-/instrumentation-runtime-node-0.14.0.tgz", + "integrity": "sha512-y78dGoFMKwHSz0SD113Gt1dFTcfunpPZXIJh2SzJN27Lyb9FIzuMfjc3Iu3+s/N6qNOLuS9mKnPe3/qVGG4Waw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.200.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, "node_modules/@opentelemetry/instrumentation-socket.io": { "version": "0.47.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-socket.io/-/instrumentation-socket.io-0.47.0.tgz", @@ -4897,216 +4688,6 @@ } } }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.0.tgz", - "integrity": "sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.0.tgz", - "integrity": "sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.0.tgz", - "integrity": "sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.0.tgz", - "integrity": "sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.0.tgz", - "integrity": "sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.0.tgz", - "integrity": "sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.0.tgz", - "integrity": "sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.0.tgz", - "integrity": "sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.0.tgz", - "integrity": "sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.0.tgz", - "integrity": "sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.0.tgz", - "integrity": "sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.0.tgz", - "integrity": "sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.0.tgz", - "integrity": "sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.0.tgz", - "integrity": "sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.0.tgz", - "integrity": "sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, "node_modules/@rollup/rollup-linux-x64-gnu": { "version": "4.40.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.0.tgz", @@ -5135,48 +4716,6 @@ "linux" ] }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.0.tgz", - "integrity": "sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.0.tgz", - "integrity": "sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.0.tgz", - "integrity": "sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@scarf/scarf": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz", @@ -5303,91 +4842,6 @@ } } }, - "node_modules/@swc/core-darwin-arm64": { - "version": "1.11.21", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.11.21.tgz", - "integrity": "sha512-v6gjw9YFWvKulCw3ZA1dY+LGMafYzJksm1mD4UZFZ9b36CyHFowYVYug1ajYRIRqEvvfIhHUNV660zTLoVFR8g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-darwin-x64": { - "version": "1.11.21", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.11.21.tgz", - "integrity": "sha512-CUiTiqKlzskwswrx9Ve5NhNoab30L1/ScOfQwr1duvNlFvarC8fvQSgdtpw2Zh3MfnfNPpyLZnYg7ah4kbT9JQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.11.21", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.11.21.tgz", - "integrity": "sha512-YyBTAFM/QPqt1PscD8hDmCLnqPGKmUZpqeE25HXY8OLjl2MUs8+O4KjwPZZ+OGxpdTbwuWFyMoxjcLy80JODvg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.11.21", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.11.21.tgz", - "integrity": "sha512-DQD+ooJmwpNsh4acrftdkuwl5LNxxg8U4+C/RJNDd7m5FP9Wo4c0URi5U0a9Vk/6sQNh9aSGcYChDpqCDWEcBw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.11.21", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.11.21.tgz", - "integrity": "sha512-y1L49+snt1a1gLTYPY641slqy55QotPdtRK9Y6jMi4JBQyZwxC8swWYlQWb+MyILwxA614fi62SCNZNznB3XSA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, "node_modules/@swc/core-linux-x64-gnu": { "version": "1.11.21", "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.11.21.tgz", @@ -5422,57 +4876,6 @@ "node": ">=10" } }, - "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.11.21", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.11.21.tgz", - "integrity": "sha512-DJJe9k6gXR/15ZZVLv1SKhXkFst8lYCeZRNHH99SlBodvu4slhh/MKQ6YCixINRhCwliHrpXPym8/5fOq8b7Ig==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.11.21", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.11.21.tgz", - "integrity": "sha512-TqEXuy6wedId7bMwLIr9byds+mKsaXVHctTN88R1UIBPwJA92Pdk0uxDgip0pEFzHB/ugU27g6d8cwUH3h2eIw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.11.21", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.11.21.tgz", - "integrity": "sha512-BT9BNNbMxdpUM1PPAkYtviaV0A8QcXttjs2MDtOeSqqvSJaPtyM+Fof2/+xSwQDmDEFzbGCcn75M5+xy3lGqpA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", @@ -5521,6 +4924,30 @@ "testcontainers": "^10.24.2" } }, + "node_modules/@tokenizer/inflate": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.2.7.tgz", + "integrity": "sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "fflate": "^0.8.2", + "token-types": "^6.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "license": "MIT" + }, "node_modules/@turf/boolean-point-in-polygon": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@turf/boolean-point-in-polygon/-/boolean-point-in-polygon-7.2.0.tgz", @@ -5617,6 +5044,16 @@ "@types/node": "*" } }, + "node_modules/@types/compression": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.7.5.tgz", + "integrity": "sha512-AAQvK5pxMpaT+nDvhHrsBhLSYG5yQdtkaJE1WYieSNY2mVFKAgmU4ks65rkZD5oqnGCFLyQpUr1CqI4DmUMyDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, "node_modules/@types/connect": { "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", @@ -6090,17 +5527,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.30.1.tgz", - "integrity": "sha512-v+VWphxMjn+1t48/jO4t950D6KR8JaJuNXzi33Ve6P8sEmPr5k6CEXjdGwT6+LodVnEa91EQCtwjWNUCPweo+Q==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.31.0.tgz", + "integrity": "sha512-evaQJZ/J/S4wisevDvC1KFZkPzRetH8kYZbkgcTRyql3mcKsf+ZFDV1BVWUGTCAW5pQHoqn5gK5b8kn7ou9aFQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.30.1", - "@typescript-eslint/type-utils": "8.30.1", - "@typescript-eslint/utils": "8.30.1", - "@typescript-eslint/visitor-keys": "8.30.1", + "@typescript-eslint/scope-manager": "8.31.0", + "@typescript-eslint/type-utils": "8.31.0", + "@typescript-eslint/utils": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -6120,16 +5557,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.30.1.tgz", - "integrity": "sha512-H+vqmWwT5xoNrXqWs/fesmssOW70gxFlgcMlYcBaWNPIEWDgLa4W9nkSPmhuOgLnXq9QYgkZ31fhDyLhleCsAg==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.31.0.tgz", + "integrity": "sha512-67kYYShjBR0jNI5vsf/c3WG4u+zDnCTHTPqVMQguffaWWFs7artgwKmfwdifl+r6XyM5LYLas/dInj2T0SgJyw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.30.1", - "@typescript-eslint/types": "8.30.1", - "@typescript-eslint/typescript-estree": "8.30.1", - "@typescript-eslint/visitor-keys": "8.30.1", + "@typescript-eslint/scope-manager": "8.31.0", + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/typescript-estree": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0", "debug": "^4.3.4" }, "engines": { @@ -6145,14 +5582,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.30.1.tgz", - "integrity": "sha512-+C0B6ChFXZkuaNDl73FJxRYT0G7ufVPOSQkqkpM/U198wUwUFOtgo1k/QzFh1KjpBitaK7R1tgjVz6o9HmsRPg==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.31.0.tgz", + "integrity": "sha512-knO8UyF78Nt8O/B64i7TlGXod69ko7z6vJD9uhSlm0qkAbGeRUSudcm0+K/4CrRjrpiHfBCjMWlc08Vav1xwcw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.30.1", - "@typescript-eslint/visitor-keys": "8.30.1" + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6163,14 +5600,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.30.1.tgz", - "integrity": "sha512-64uBF76bfQiJyHgZISC7vcNz3adqQKIccVoKubyQcOnNcdJBvYOILV1v22Qhsw3tw3VQu5ll8ND6hycgAR5fEA==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.31.0.tgz", + "integrity": "sha512-DJ1N1GdjI7IS7uRlzJuEDCgDQix3ZVYVtgeWEyhyn4iaoitpMBX6Ndd488mXSx0xah/cONAkEaYyylDyAeHMHg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.30.1", - "@typescript-eslint/utils": "8.30.1", + "@typescript-eslint/typescript-estree": "8.31.0", + "@typescript-eslint/utils": "8.31.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.1" }, @@ -6187,9 +5624,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.30.1.tgz", - "integrity": "sha512-81KawPfkuulyWo5QdyG/LOKbspyyiW+p4vpn4bYO7DM/hZImlVnFwrpCTnmNMOt8CvLRr5ojI9nU1Ekpw4RcEw==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.31.0.tgz", + "integrity": "sha512-Ch8oSjVyYyJxPQk8pMiP2FFGYatqXQfQIaMp+TpuuLlDachRWpUAeEu1u9B/v/8LToehUIWyiKcA/w5hUFRKuQ==", "dev": true, "license": "MIT", "engines": { @@ -6201,14 +5638,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.30.1.tgz", - "integrity": "sha512-kQQnxymiUy9tTb1F2uep9W6aBiYODgq5EMSk6Nxh4Z+BDUoYUSa029ISs5zTzKBFnexQEh71KqwjKnRz58lusQ==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.0.tgz", + "integrity": "sha512-xLmgn4Yl46xi6aDSZ9KkyfhhtnYI15/CvHbpOy/eR5NWhK/BK8wc709KKwhAR0m4ZKRP7h07bm4BWUYOCuRpQQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.30.1", - "@typescript-eslint/visitor-keys": "8.30.1", + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -6254,16 +5691,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.30.1.tgz", - "integrity": "sha512-T/8q4R9En2tcEsWPQgB5BQ0XJVOtfARcUvOa8yJP3fh9M/mXraLxZrkCfGb6ChrO/V3W+Xbd04RacUEqk1CFEQ==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.31.0.tgz", + "integrity": "sha512-qi6uPLt9cjTFxAb1zGNgTob4x9ur7xC6mHQJ8GwEzGMGE9tYniublmJaowOJ9V2jUzxrltTPfdG2nKlWsq0+Ww==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.30.1", - "@typescript-eslint/types": "8.30.1", - "@typescript-eslint/typescript-estree": "8.30.1" + "@typescript-eslint/scope-manager": "8.31.0", + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/typescript-estree": "8.31.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6278,13 +5715,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.30.1.tgz", - "integrity": "sha512-aEhgas7aJ6vZnNFC7K4/vMGDGyOiqWcYZPpIWrTKuTAlsvDNKy2GFDqh9smL+iq069ZvR0YzEeq0B8NJlLzjFA==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.0.tgz", + "integrity": "sha512-QcGHmlRHWOl93o64ZUMNewCdwKGU6WItOU52H0djgNmn1EOrhVudrDzXz4OycCRSCPwFCDrE2iIt5vmuUdHxuQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.30.1", + "@typescript-eslint/types": "8.31.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -6296,9 +5733,9 @@ } }, "node_modules/@vitest/coverage-v8": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.1.1.tgz", - "integrity": "sha512-MgV6D2dhpD6Hp/uroUoAIvFqA8AuvXEFBC2eepG3WFc1pxTfdk1LEqqkWoWhjz+rytoqrnUUCdf6Lzco3iHkLQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.1.2.tgz", + "integrity": "sha512-XDdaDOeaTMAMYW7N63AqoK32sYUWbXnTkC6tEbVcu3RlU1bB9of32T+PGf8KZvxqLNqeXhafDFqCkwpf2+dyaQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6311,7 +5748,7 @@ "istanbul-reports": "^3.1.7", "magic-string": "^0.30.17", "magicast": "^0.3.5", - "std-env": "^3.8.1", + "std-env": "^3.9.0", "test-exclude": "^7.0.1", "tinyrainbow": "^2.0.0" }, @@ -6319,8 +5756,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "3.1.1", - "vitest": "3.1.1" + "@vitest/browser": "3.1.2", + "vitest": "3.1.2" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -6329,14 +5766,14 @@ } }, "node_modules/@vitest/expect": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.1.tgz", - "integrity": "sha512-q/zjrW9lgynctNbwvFtQkGK9+vvHA5UzVi2V8APrp1C6fG6/MuYYkmlx4FubuqLycCeSdHD5aadWfua/Vr0EUA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.2.tgz", + "integrity": "sha512-O8hJgr+zREopCAqWl3uCVaOdqJwZ9qaDwUP7vy3Xigad0phZe9APxKhPcDNqYYi0rX5oMvwJMSCAXY2afqeTSA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.1.1", - "@vitest/utils": "3.1.1", + "@vitest/spy": "3.1.2", + "@vitest/utils": "3.1.2", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" }, @@ -6345,13 +5782,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.1.tgz", - "integrity": "sha512-bmpJJm7Y7i9BBELlLuuM1J1Q6EQ6K5Ye4wcyOpOMXMcePYKSIYlpcrCm4l/O6ja4VJA5G2aMJiuZkZdnxlC3SA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.2.tgz", + "integrity": "sha512-kOtd6K2lc7SQ0mBqYv/wdGedlqPdM/B38paPY+OwJ1XiNi44w3Fpog82UfOibmHaV9Wod18A09I9SCKLyDMqgw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.1.1", + "@vitest/spy": "3.1.2", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -6382,9 +5819,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.1.tgz", - "integrity": "sha512-dg0CIzNx+hMMYfNmSqJlLSXEmnNhMswcn3sXO7Tpldr0LiGmg3eXdLLhwkv2ZqgHb/d5xg5F7ezNFRA1fA13yA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.2.tgz", + "integrity": "sha512-R0xAiHuWeDjTSB3kQ3OQpT8Rx3yhdOAIm/JM4axXxnG7Q/fS8XUwggv/A4xzbQA+drYRjzkMnpYnOGAc4oeq8w==", "dev": true, "license": "MIT", "dependencies": { @@ -6395,13 +5832,13 @@ } }, "node_modules/@vitest/runner": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.1.tgz", - "integrity": "sha512-X/d46qzJuEDO8ueyjtKfxffiXraPRfmYasoC4i5+mlLEJ10UvPb0XH5M9C3gWuxd7BAQhpK42cJgJtq53YnWVA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.2.tgz", + "integrity": "sha512-bhLib9l4xb4sUMPXnThbnhX2Yi8OutBMA8Yahxa7yavQsFDtwY/jrUZwpKp2XH9DhRFJIeytlyGpXCqZ65nR+g==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.1.1", + "@vitest/utils": "3.1.2", "pathe": "^2.0.3" }, "funding": { @@ -6409,13 +5846,13 @@ } }, "node_modules/@vitest/snapshot": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.1.tgz", - "integrity": "sha512-bByMwaVWe/+1WDf9exFxWWgAixelSdiwo2p33tpqIlM14vW7PRV5ppayVXtfycqze4Qhtwag5sVhX400MLBOOw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.2.tgz", + "integrity": "sha512-Q1qkpazSF/p4ApZg1vfZSQ5Yw6OCQxVMVrLjslbLFA1hMDrT2uxtqMaw8Tc/jy5DLka1sNs1Y7rBcftMiaSH/Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.1.1", + "@vitest/pretty-format": "3.1.2", "magic-string": "^0.30.17", "pathe": "^2.0.3" }, @@ -6424,9 +5861,9 @@ } }, "node_modules/@vitest/spy": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.1.tgz", - "integrity": "sha512-+EmrUOOXbKzLkTDwlsc/xrwOlPDXyVk3Z6P6K4oiCndxz7YLpp/0R0UsWVOKT0IXWjjBJuSMk6D27qipaupcvQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.2.tgz", + "integrity": "sha512-OEc5fSXMws6sHVe4kOFyDSj/+4MSwst0ib4un0DlcYgQvRuYQ0+M2HyqGaauUMnjq87tmUaMNDxKQx7wNfVqPA==", "dev": true, "license": "MIT", "dependencies": { @@ -6437,13 +5874,13 @@ } }, "node_modules/@vitest/utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.1.tgz", - "integrity": "sha512-1XIjflyaU2k3HMArJ50bwSh3wKWPD6Q47wz/NUSmRV0zNywPc4w79ARjg/i/aNINHwA+mIALhUVqD9/aUvZNgg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.2.tgz", + "integrity": "sha512-5GGd0ytZ7BH3H6JTj9Kw7Prn1Nbg0wZVrIvou+UWxm54d+WoXXgAgjFJ8wn3LdagWLFSEfpPeyYrByZaGEZHLg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.1.1", + "@vitest/pretty-format": "3.1.2", "loupe": "^3.1.3", "tinyrainbow": "^2.0.0" }, @@ -6970,12 +6407,6 @@ "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/archiver-utils/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC" - }, "node_modules/archiver-utils/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -7552,6 +6983,190 @@ "node": ">=8" } }, + "node_modules/cacache": { + "version": "19.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-19.0.1.tgz", + "integrity": "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/fs": "^4.0.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^7.0.2", + "ssri": "^12.0.0", + "tar": "^7.4.3", + "unique-filename": "^4.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/cacache/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/cacache/node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/cacache/node_modules/fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/cacache/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/minizlib": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", + "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/cacache/node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cacache/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -8033,6 +7648,60 @@ "node": ">= 14" } }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.0.tgz", + "integrity": "sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.0.2", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/compression/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -8311,6 +7980,20 @@ "node": ">=4" } }, + "node_modules/cssstyle": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.3.1.tgz", + "integrity": "sha512-ZgW+Jgdd7i52AaLYCriF8Mxqft0gD/R9i9wi6RWBhs1pqdPEzPjym7rvRKi397WmQFf3SlyUsszhw+VVCbx79Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^3.1.2", + "rrweb-cssom": "^0.8.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", @@ -8318,6 +8001,57 @@ "dev": true, "license": "MIT" }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-urls/node_modules/tr46": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-urls/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/data-urls/node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/dayjs": { "version": "1.11.13", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", @@ -8353,6 +8087,13 @@ } } }, + "node_modules/decimal.js": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", + "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", + "dev": true, + "license": "MIT" + }, "node_modules/deep-eql": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", @@ -8752,6 +8493,16 @@ "node": ">= 0.8" } }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -8886,6 +8637,23 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true, + "license": "MIT" + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -9014,20 +8782,20 @@ } }, "node_modules/eslint": { - "version": "9.24.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.24.0.tgz", - "integrity": "sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==", + "version": "9.25.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.25.1.tgz", + "integrity": "sha512-E6Mtz9oGQWDCpV12319d59n4tx9zOTXSTmc8BLVxBx+G/0RdM5MvEEJLU9c0+aleoePYYgVTOsRblx433qmhWQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.20.0", - "@eslint/config-helpers": "^0.2.0", - "@eslint/core": "^0.12.0", + "@eslint/config-helpers": "^0.2.1", + "@eslint/core": "^0.13.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.24.0", - "@eslint/plugin-kit": "^0.2.7", + "@eslint/js": "9.25.1", + "@eslint/plugin-kit": "^0.2.8", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", @@ -9343,16 +9111,6 @@ "exiftool-vendored.pl": "13.0.1" } }, - "node_modules/exiftool-vendored.exe": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/exiftool-vendored.exe/-/exiftool-vendored.exe-13.0.0.tgz", - "integrity": "sha512-4zAMuFGgxZkOoyQIzZMHv1HlvgyJK3AkNqjAgm8A8V0UmOZO7yv3pH49cDV1OduzFJqgs6yQ6eG4OGydhKtxlg==", - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/exiftool-vendored.pl": { "version": "13.0.1", "resolved": "https://registry.npmjs.org/exiftool-vendored.pl/-/exiftool-vendored.pl-13.0.1.tgz", @@ -9373,6 +9131,13 @@ "node": ">=12.0.0" } }, + "node_modules/exponential-backoff": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.2.tgz", + "integrity": "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/express": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", @@ -9547,6 +9312,27 @@ "reusify": "^1.0.4" } }, + "node_modules/fdir": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "license": "MIT" + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -9593,6 +9379,24 @@ "stream-source": "0.3" } }, + "node_modules/file-type": { + "version": "20.4.1", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-20.4.1.tgz", + "integrity": "sha512-hw9gNZXUfZ02Jo0uafWLaFVPter5/k2rfcrjFJJHX/77xtSDOfJuEFb6oKlFV86FLP1SuyHMW1PSk0U9M5tKkQ==", + "license": "MIT", + "dependencies": { + "@tokenizer/inflate": "^0.2.6", + "strtok3": "^10.2.0", + "token-types": "^6.0.0", + "uint8array-extras": "^1.4.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -9921,20 +9725,6 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "license": "ISC" }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -10399,12 +10189,18 @@ "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } }, "node_modules/html-escaper": { "version": "2.0.2", @@ -10448,6 +10244,13 @@ "entities": "^4.4.0" } }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true, + "license": "BSD-2-Clause" + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -10464,6 +10267,30 @@ "node": ">= 0.8" } }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -10698,6 +10525,20 @@ "url": "https://opencollective.com/ioredis" } }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -10829,6 +10670,13 @@ "node": ">=0.10.0" } }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, "node_modules/is-promise": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", @@ -11055,9 +10903,9 @@ } }, "node_modules/jose": { - "version": "4.15.9", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz", - "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==", + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.0.10.tgz", + "integrity": "sha512-skIAxZqcMkOrSwjJvplIPYrlXGpxTPnro2/QWTDCxAdWQrSTV5/KqspMWmi5WAx5+ULswASJiZ0a+1B/Lxt9cw==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/panva" @@ -11081,6 +10929,136 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsdom": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", + "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssstyle": "^4.2.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.5.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.6", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.16", + "parse5": "^7.2.1", + "rrweb-cssom": "^0.8.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.1.1", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.1.1", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/jsdom/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/jsdom/node_modules/tr46": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsdom/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdom/node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsdom/node_modules/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -11212,9 +11190,9 @@ } }, "node_modules/kysely": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/kysely/-/kysely-0.28.0.tgz", - "integrity": "sha512-hq8VcLy57Ww7oPTTVEOrT9ml+g8ehbbmEUkHmW4Xtubu+NHdKZi6SH6egmD4cjDhn3b/0s0h/6AjdPayOTJhNw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/kysely/-/kysely-0.28.2.tgz", + "integrity": "sha512-4YAVLoF0Sf0UTqlhgQMFU9iQECdah7n+13ANkiuVfRvlK+uI0Etbgd7bVP36dKlG+NXWbhGua8vnGt+sdhvT7A==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -11326,6 +11304,25 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "license": "MIT" }, + "node_modules/load-esm": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/load-esm/-/load-esm-1.0.2.tgz", + "integrity": "sha512-nVAvWk/jeyrWyXEAs84mpQCYccxRqgKY4OznLuJhJCa0XsPSfdOIr2zvBZEj3IHEHbX97jjscKRRV539bW0Gpw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + }, + { + "type": "buymeacoffee", + "url": "https://buymeacoffee.com/borewit" + } + ], + "license": "MIT", + "engines": { + "node": ">=13.2.0" + } + }, "node_modules/load-tsconfig": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", @@ -11423,16 +11420,10 @@ "license": "MIT" }, "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" }, "node_modules/luxon": { "version": "3.6.1", @@ -11489,6 +11480,29 @@ "semver": "bin/semver.js" } }, + "node_modules/make-fetch-happen": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz", + "integrity": "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/agent": "^3.0.0", + "cacache": "^19.0.1", + "http-cache-semantics": "^4.1.1", + "minipass": "^7.0.2", + "minipass-fetch": "^4.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^1.0.0", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1", + "ssri": "^12.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/marked": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/marked/-/marked-7.0.4.tgz", @@ -11690,6 +11704,128 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/minipass-collect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-fetch": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-4.0.1.tgz", + "integrity": "sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^3.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/minipass-fetch/node_modules/minizlib": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", + "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/minizlib": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", @@ -12055,9 +12191,9 @@ } }, "node_modules/nestjs-cls": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/nestjs-cls/-/nestjs-cls-5.4.2.tgz", - "integrity": "sha512-KQPOhD7ya82gSEc+XDwFKERPMaWK95bzV4E2pLmx8oC1hfMNuVc4dkWmEKJiu+o0hCWP/v51iWNgOGHKnJ9Raw==", + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/nestjs-cls/-/nestjs-cls-5.4.3.tgz", + "integrity": "sha512-yHEHyVoe6rsvj3XRPFonBKPXPjDREyHfKZ9PTStSLJTZAV3wey1Q89TquSj6QciqXB5387GiHv9DG+ja6iAUHw==", "license": "MIT", "engines": { "node": ">=18" @@ -12205,6 +12341,31 @@ } } }, + "node_modules/node-gyp": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.2.0.tgz", + "integrity": "sha512-T0S1zqskVUSxcsSTkAsLc7xCycrRYmtDHadDinzocrThjyQCn5kMlEBSj6H4qDbgsIOSLmmlRIeb0lZXj+UArA==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^14.0.3", + "nopt": "^8.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.5", + "tar": "^7.4.3", + "tinyglobby": "^0.2.12", + "which": "^5.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/node-gyp-build-optional-packages": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", @@ -12220,6 +12381,125 @@ "node-gyp-build-optional-packages-test": "build-test.js" } }, + "node_modules/node-gyp/node_modules/abbrev": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz", + "integrity": "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/node-gyp/node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/node-gyp/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "node_modules/node-gyp/node_modules/minizlib": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", + "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/node-gyp/node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/nopt": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz", + "integrity": "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "^3.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/node-gyp/node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/node-gyp/node_modules/which": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/node-gyp/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, "node_modules/node-releases": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", @@ -12293,6 +12573,22 @@ "set-blocking": "^2.0.0" } }, + "node_modules/nwsapi": { + "version": "2.2.20", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.20.tgz", + "integrity": "sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==", + "dev": true, + "license": "MIT" + }, + "node_modules/oauth4webapi": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.5.0.tgz", + "integrity": "sha512-DF3mLWNuxPkxJkHmWxbSFz4aE5CjWOsm465VBfBdWzmzX4Mg3vF8icxK+iKqfdWrIumBJ2TaoNQWx+SQc2bsPQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -12333,15 +12629,6 @@ "node": ">= 0.4" } }, - "node_modules/oidc-token-hash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.1.0.tgz", - "integrity": "sha512-y0W+X7Ppo7oZX6eovsRkuzcSM40Bicg2JEJkDJ4irIt1wsYAP5MLSNv+QAogO8xivMffw/9OvV3um1pxXgt1uA==", - "license": "MIT", - "engines": { - "node": "^10.13.0 || >=12.0.0" - } - }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -12405,29 +12692,18 @@ } }, "node_modules/openid-client": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.7.1.tgz", - "integrity": "sha512-jDBPgSVfTnkIh71Hg9pRvtJc6wTwqjRkN88+gCFtYWrlP4Yx2Dsrow8uPi3qLr/aeymPF3o2+dS+wOpglK04ew==", + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-6.4.2.tgz", + "integrity": "sha512-4zBRTsKNRTyKxV5cFzl+LtamsYx/FsWhejjax+qgMkFNGtLj1gMtng2iSoJqqWUT0FHU3IUhO53aeBePg7Sp/g==", "license": "MIT", "dependencies": { - "jose": "^4.15.9", - "lru-cache": "^6.0.0", - "object-hash": "^2.2.0", - "oidc-token-hash": "^5.0.3" + "jose": "^6.0.10", + "oauth4webapi": "^3.4.1" }, "funding": { "url": "https://github.com/sponsors/panva" } }, - "node_modules/openid-client/node_modules/object-hash": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", - "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -12531,6 +12807,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-map": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", + "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", @@ -12573,6 +12862,32 @@ "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==", "license": "MIT" }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz", + "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/parseley": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.12.1.tgz", @@ -12822,15 +13137,28 @@ "url": "https://ko-fi.com/killymxi" } }, + "node_modules/peek-readable": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-7.0.0.tgz", + "integrity": "sha512-nri2TO5JE3/mRryik9LlHFT53cgHfRK0Lt0BAZQXku/AW3E6XLt2GaY8siWi7dvW/m1z0ecn+J+bpDa9ZN3IsQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/pg": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.14.1.tgz", - "integrity": "sha512-0TdbqfjwIun9Fm/r89oB7RFQ0bLgduAhiIqIXOsyKoiC/L54DbuAAzIEN/9Op0f1Po9X7iCPXGoa/Ah+2aI8Xw==", + "version": "8.15.5", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.15.5.tgz", + "integrity": "sha512-EpAhHFQc+aH9VfeffWIVC+XXk6lmAhS9W1FxtxcPXs94yxhrI1I6w/zkWfIOII/OkBv3Be04X3xMOj0kQ78l6w==", "license": "MIT", "dependencies": { - "pg-connection-string": "^2.7.0", - "pg-pool": "^3.8.0", - "pg-protocol": "^1.8.0", + "pg-connection-string": "^2.8.5", + "pg-pool": "^3.9.5", + "pg-protocol": "^1.9.5", "pg-types": "^2.1.0", "pgpass": "1.x" }, @@ -12838,7 +13166,7 @@ "node": ">= 8.0.0" }, "optionalDependencies": { - "pg-cloudflare": "^1.1.1" + "pg-cloudflare": "^1.2.5" }, "peerDependencies": { "pg-native": ">=3.0.1" @@ -12850,16 +13178,16 @@ } }, "node_modules/pg-cloudflare": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.2.5.tgz", + "integrity": "sha512-OOX22Vt0vOSRrdoUPKJ8Wi2OpE/o/h9T8X1s4qSkCedbNah9ei2W2765be8iMVxQUsvgT7zIAT2eIa9fs5+vtg==", "license": "MIT", "optional": true }, "node_modules/pg-connection-string": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.7.0.tgz", - "integrity": "sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==", + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.8.5.tgz", + "integrity": "sha512-Ni8FuZ8yAF+sWZzojvtLE2b03cqjO5jNULcHFfM9ZZ0/JXrgom5pBREbtnAw7oxsxJqHw9Nz/XWORUEL3/IFow==", "license": "MIT" }, "node_modules/pg-int8": { @@ -12872,18 +13200,18 @@ } }, "node_modules/pg-pool": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.8.0.tgz", - "integrity": "sha512-VBw3jiVm6ZOdLBTIcXLNdSotb6Iy3uOCwDGFAksZCXmi10nyRvnP2v3jl4d+IsLYRyXf6o9hIm/ZtUzlByNUdw==", + "version": "3.9.6", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.9.6.tgz", + "integrity": "sha512-rFen0G7adh1YmgvrmE5IPIqbb+IgEzENUm+tzm6MLLDSlPRoZVhzU1WdML9PV2W5GOdRA9qBKURlbt1OsXOsPw==", "license": "MIT", "peerDependencies": { "pg": ">=8.0" } }, "node_modules/pg-protocol": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.8.0.tgz", - "integrity": "sha512-jvuYlEkL03NRvOoyoRktBK7+qU5kOvlAwvmrH8sr3wbLrOdVWsRxQfz8mMy9sZFsqJ1hEWNfdWKI4SAmoL+j7g==", + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.9.5.tgz", + "integrity": "sha512-DYTWtWpfd5FOro3UnAfwvhD8jh59r2ig8bPtc9H8Ds7MscE/9NYruUQWFAOuraRl29jwcT2kyMFQ3MxeaVjUhg==", "license": "MIT" }, "node_modules/pg-types": { @@ -13244,6 +13572,16 @@ "node": ">=6" } }, + "node_modules/proc-log": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz", + "integrity": "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -13259,6 +13597,20 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "license": "MIT" }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/proper-lockfile": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", @@ -13596,12 +13948,6 @@ "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/react-email/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC" - }, "node_modules/react-email/node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -14156,6 +14502,13 @@ "node": ">= 18" } }, + "node_modules/rrweb-cssom": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", + "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", + "dev": true, + "license": "MIT" + }, "node_modules/run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", @@ -14233,9 +14586,9 @@ } }, "node_modules/sanitize-html": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.15.0.tgz", - "integrity": "sha512-wIjst57vJGpLyBP8ioUbg6ThwJie5SuSIjHxJg53v5Fg+kUK+AXlb7bK3RNXpp315MvwM+0OBGCV6h5pPHsVhA==", + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.16.0.tgz", + "integrity": "sha512-0s4caLuHHaZFVxFTG74oW91+j6vW7gKbGD6CD2+miP73CE6z6YtOBN0ArtLd2UGyi4IC7K47v3ENUbQX4jV3Mg==", "license": "MIT", "dependencies": { "deepmerge": "^4.2.2", @@ -14246,6 +14599,19 @@ "postcss": "^8.3.11" } }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, "node_modules/scheduler": { "version": "0.26.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", @@ -14410,15 +14776,15 @@ "license": "MIT" }, "node_modules/sharp": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", - "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.1.tgz", + "integrity": "sha512-1j0w61+eVxu7DawFJtnfYcvSv6qPFvfTaqzTQ2BLknVhHTwGS8sc63ZBF4rzkWMBVKybo4S5OBtDdZahh2A1xg==", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", - "semver": "^7.6.3" + "semver": "^7.7.1" }, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" @@ -14427,25 +14793,26 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.33.5", - "@img/sharp-darwin-x64": "0.33.5", - "@img/sharp-libvips-darwin-arm64": "1.0.4", - "@img/sharp-libvips-darwin-x64": "1.0.4", - "@img/sharp-libvips-linux-arm": "1.0.5", - "@img/sharp-libvips-linux-arm64": "1.0.4", - "@img/sharp-libvips-linux-s390x": "1.0.4", - "@img/sharp-libvips-linux-x64": "1.0.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", - "@img/sharp-libvips-linuxmusl-x64": "1.0.4", - "@img/sharp-linux-arm": "0.33.5", - "@img/sharp-linux-arm64": "0.33.5", - "@img/sharp-linux-s390x": "0.33.5", - "@img/sharp-linux-x64": "0.33.5", - "@img/sharp-linuxmusl-arm64": "0.33.5", - "@img/sharp-linuxmusl-x64": "0.33.5", - "@img/sharp-wasm32": "0.33.5", - "@img/sharp-win32-ia32": "0.33.5", - "@img/sharp-win32-x64": "0.33.5" + "@img/sharp-darwin-arm64": "0.34.1", + "@img/sharp-darwin-x64": "0.34.1", + "@img/sharp-libvips-darwin-arm64": "1.1.0", + "@img/sharp-libvips-darwin-x64": "1.1.0", + "@img/sharp-libvips-linux-arm": "1.1.0", + "@img/sharp-libvips-linux-arm64": "1.1.0", + "@img/sharp-libvips-linux-ppc64": "1.1.0", + "@img/sharp-libvips-linux-s390x": "1.1.0", + "@img/sharp-libvips-linux-x64": "1.1.0", + "@img/sharp-libvips-linuxmusl-arm64": "1.1.0", + "@img/sharp-libvips-linuxmusl-x64": "1.1.0", + "@img/sharp-linux-arm": "0.34.1", + "@img/sharp-linux-arm64": "0.34.1", + "@img/sharp-linux-s390x": "0.34.1", + "@img/sharp-linux-x64": "0.34.1", + "@img/sharp-linuxmusl-arm64": "0.34.1", + "@img/sharp-linuxmusl-x64": "0.34.1", + "@img/sharp-wasm32": "0.34.1", + "@img/sharp-win32-ia32": "0.34.1", + "@img/sharp-win32-x64": "0.34.1" } }, "node_modules/shebang-command": { @@ -14611,6 +14978,17 @@ "integrity": "sha512-YiuPbxpCj4hD9Qs06hGAz/OZhQ0eDuALN0lRWJez0eD/RevzKqGdUx1IOMUnXgpr+sXZLq3g8ERwbAH0bCb8vg==", "license": "BSD-3-Clause" }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, "node_modules/socket.io": { "version": "4.8.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", @@ -14746,6 +15124,46 @@ "node": ">= 0.6" } }, + "node_modules/socks": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz", + "integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -14827,10 +15245,17 @@ "node": ">= 10.x" } }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/sql-formatter": { - "version": "15.5.2", - "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.5.2.tgz", - "integrity": "sha512-+9xZgiv1DP/c7GxkkBUHRZOf4j35gquVdwEm0rg16qKRYeFkv1+/vEeO13fsUbbz06KUotIyASJ+hyau8LM8Kg==", + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.6.1.tgz", + "integrity": "sha512-uoKbRLVbjzwa8ouY4lI9YM387zRxDv9Gg5kZBzu2iNls2wVBlDLshhudCstczddRvj7J+xOpHTTWX6Z0lRgYGA==", "dev": true, "license": "MIT", "dependencies": { @@ -14897,6 +15322,19 @@ "nan": "^2.20.0" } }, + "node_modules/ssri": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-12.0.0.tgz", + "integrity": "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", @@ -15109,6 +15547,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strtok3": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.2.2.tgz", + "integrity": "sha512-Xt18+h4s7Z8xyZ0tmBoRmzxcop97R4BAh+dXouUDCYn+Em+1P3qpkUfI5ueWLT8ynC5hZ+q4iPEmGG1urvQGBg==", + "license": "MIT", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/styled-jsx": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", @@ -15202,13 +15657,6 @@ "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/sucrase/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC", - "peer": true - }, "node_modules/sucrase/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -15320,6 +15768,13 @@ "node": ">=0.10" } }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, "node_modules/synckit": { "version": "0.11.4", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.4.tgz", @@ -15752,13 +16207,6 @@ "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/test-exclude/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, "node_modules/test-exclude/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -15891,6 +16339,23 @@ "dev": true, "license": "MIT" }, + "node_modules/tinyglobby": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", + "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, "node_modules/tinypool": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", @@ -15921,6 +16386,26 @@ "node": ">=14.0.0" } }, + "node_modules/tldts": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", + "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^6.1.86" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", + "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", + "dev": true, + "license": "MIT" + }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -15954,6 +16439,23 @@ "node": ">=0.6" } }, + "node_modules/token-types": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.0.0.tgz", + "integrity": "sha512-lbDrTLVsHhOMljPscd0yitpozq7Ga2M5Cvez5AjGg8GASBjtt6iERCAJ93yommPmz62fb45oFIXHEZ3u9bfJEA==", + "license": "MIT", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/totalist": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", @@ -15963,6 +16465,19 @@ "node": ">=6" } }, + "node_modules/tough-cookie": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", + "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -16291,12 +16806,6 @@ "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/typeorm/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC" - }, "node_modules/typeorm/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -16356,15 +16865,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.30.1.tgz", - "integrity": "sha512-D7lC0kcehVH7Mb26MRQi64LMyRJsj3dToJxM1+JVTl53DQSV5/7oUGWQLcKl1C1KnoVHxMMU2FNQMffr7F3Row==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.31.0.tgz", + "integrity": "sha512-u+93F0sB0An8WEAPtwxVhFby573E8ckdjwUUQUj9QA4v8JAvgtoDdIyYR3XFwFHq2W1KJ1AurwJCO+w+Y1ixyQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.30.1", - "@typescript-eslint/parser": "8.30.1", - "@typescript-eslint/utils": "8.30.1" + "@typescript-eslint/eslint-plugin": "8.31.0", + "@typescript-eslint/parser": "8.31.0", + "@typescript-eslint/utils": "8.31.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -16465,6 +16974,18 @@ "node": ">= 4.0.0" } }, + "node_modules/uint8array-extras": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.4.0.tgz", + "integrity": "sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/undici": { "version": "5.29.0", "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", @@ -16497,6 +17018,32 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/unique-filename": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-4.0.0.tgz", + "integrity": "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "unique-slug": "^5.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/unique-slug": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-5.0.0.tgz", + "integrity": "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -16531,9 +17078,9 @@ } }, "node_modules/unplugin-swc": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/unplugin-swc/-/unplugin-swc-1.5.1.tgz", - "integrity": "sha512-/ZLrPNjChhGx3Z95pxJ4tQgfI6rWqukgYHKflrNB4zAV1izOQuDhkTn55JWeivpBxDCoK7M/TStb2aS/14PS/g==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/unplugin-swc/-/unplugin-swc-1.5.2.tgz", + "integrity": "sha512-bf8DJO8lD1wpnwFglQpVH2XEaFfVsSU5C7yFyLwGT1gxskPtejlDeuttKxjtmHTSqrDsQrK0FCFdhw3Ny+K7hA==", "dev": true, "license": "MIT", "dependencies": { @@ -16734,9 +17281,9 @@ } }, "node_modules/vite-node": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.1.tgz", - "integrity": "sha512-V+IxPAE2FvXpTCHXyNem0M+gWm6J7eRyWPR6vYoG/Gl+IscNOjXzztUhimQgTxaAoUoj40Qqimaa0NLIOOAH4w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.2.tgz", + "integrity": "sha512-/8iMryv46J3aK13iUXsei5G/A3CUlW4665THCPS+K8xAaqrVWiGB4RfXMQXCLjpK9P2eK//BczrVkn5JLAk6DA==", "dev": true, "license": "MIT", "dependencies": { @@ -16776,278 +17323,6 @@ } } }, - "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz", - "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz", - "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz", - "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz", - "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz", - "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz", - "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz", - "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz", - "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz", - "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz", - "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz", - "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz", - "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz", - "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz", - "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz", - "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz", - "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/vite/node_modules/@esbuild/linux-x64": { "version": "0.25.2", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz", @@ -17065,125 +17340,6 @@ "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz", - "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz", - "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz", - "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz", - "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz", - "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz", - "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz", - "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/vite/node_modules/esbuild": { "version": "0.25.2", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", @@ -17255,31 +17411,32 @@ } }, "node_modules/vitest": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.1.tgz", - "integrity": "sha512-kiZc/IYmKICeBAZr9DQ5rT7/6bD9G7uqQEki4fxazi1jdVl2mWGzedtBs5s6llz59yQhVb7FFY2MbHzHCnT79Q==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.2.tgz", + "integrity": "sha512-WaxpJe092ID1C0mr+LH9MmNrhfzi8I65EX/NRU/Ld016KqQNRgxSOlGNP1hHN+a/F8L15Mh8klwaF77zR3GeDQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "3.1.1", - "@vitest/mocker": "3.1.1", - "@vitest/pretty-format": "^3.1.1", - "@vitest/runner": "3.1.1", - "@vitest/snapshot": "3.1.1", - "@vitest/spy": "3.1.1", - "@vitest/utils": "3.1.1", + "@vitest/expect": "3.1.2", + "@vitest/mocker": "3.1.2", + "@vitest/pretty-format": "^3.1.2", + "@vitest/runner": "3.1.2", + "@vitest/snapshot": "3.1.2", + "@vitest/spy": "3.1.2", + "@vitest/utils": "3.1.2", "chai": "^5.2.0", "debug": "^4.4.0", - "expect-type": "^1.2.0", + "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", - "std-env": "^3.8.1", + "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.13", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", - "vite-node": "3.1.1", + "vite-node": "3.1.2", "why-is-node-running": "^2.3.0" }, "bin": { @@ -17295,8 +17452,8 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.1.1", - "@vitest/ui": "3.1.1", + "@vitest/browser": "3.1.2", + "@vitest/ui": "3.1.2", "happy-dom": "*", "jsdom": "*" }, @@ -17324,6 +17481,19 @@ } } }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/watchpack": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", @@ -17354,9 +17524,9 @@ "license": "BSD-2-Clause" }, "node_modules/webpack": { - "version": "5.98.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.98.0.tgz", - "integrity": "sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA==", + "version": "5.99.6", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.6.tgz", + "integrity": "sha512-TJOLrJ6oeccsGWPl7ujCYuc0pIq2cNsuD6GZDma8i5o5Npvcco/z+NKvZSFsP0/x6SShVb0+X2JK/JHUjKY9dQ==", "dev": true, "license": "MIT", "dependencies": { @@ -17549,6 +17719,29 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -17717,6 +17910,23 @@ } } }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/server/package.json b/server/package.json index 8e149d961e..33d1450a53 100644 --- a/server/package.json +++ b/server/package.json @@ -1,6 +1,6 @@ { "name": "immich", - "version": "1.131.3", + "version": "1.132.3", "description": "", "author": "", "private": true, @@ -44,7 +44,7 @@ "@nestjs/schedule": "^5.0.0", "@nestjs/swagger": "^11.0.2", "@nestjs/websockets": "^11.0.4", - "@opentelemetry/auto-instrumentations-node": "^0.57.0", + "@opentelemetry/auto-instrumentations-node": "^0.58.0", "@opentelemetry/context-async-hooks": "^2.0.0", "@opentelemetry/exporter-prometheus": "^0.200.0", "@opentelemetry/sdk-node": "^0.200.0", @@ -57,6 +57,7 @@ "chokidar": "^3.5.3", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", + "compression": "^1.8.0", "cookie": "^1.0.2", "cookie-parser": "^1.4.7", "exiftool-vendored": "^28.3.1", @@ -77,7 +78,7 @@ "nestjs-kysely": "^1.1.0", "nestjs-otel": "^6.0.0", "nodemailer": "^6.9.13", - "openid-client": "^5.4.3", + "openid-client": "^6.3.3", "pg": "^8.11.3", "picomatch": "^4.0.2", "react": "^19.0.0", @@ -88,7 +89,7 @@ "sanitize-filename": "^1.6.3", "sanitize-html": "^2.14.0", "semver": "^7.6.2", - "sharp": "^0.33.0", + "sharp": "^0.34.0", "sirv": "^3.0.0", "tailwindcss-preset-email": "^1.3.2", "thumbhash": "^0.1.1", @@ -108,6 +109,7 @@ "@types/archiver": "^6.0.0", "@types/async-lock": "^1.4.2", "@types/bcrypt": "^5.0.0", + "@types/compression": "^1.7.5", "@types/cookie-parser": "^1.4.8", "@types/express": "^4.17.17", "@types/fluent-ffmpeg": "^2.1.21", @@ -115,7 +117,7 @@ "@types/lodash": "^4.14.197", "@types/mock-fs": "^4.13.1", "@types/multer": "^1.4.7", - "@types/node": "^22.14.0", + "@types/node": "^22.14.1", "@types/nodemailer": "^6.4.14", "@types/picomatch": "^3.0.0", "@types/pngjs": "^6.0.5", @@ -130,8 +132,10 @@ "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-unicorn": "^57.0.0", "globals": "^16.0.0", + "jsdom": "^26.1.0", "mock-fs": "^5.2.0", - "node-addon-api": "^8.3.0", + "node-addon-api": "^8.3.1", + "node-gyp": "^11.2.0", "patch-package": "^8.0.0", "pngjs": "^7.0.0", "prettier": "^3.0.2", @@ -151,5 +155,8 @@ }, "volta": { "node": "22.14.0" + }, + "overrides": { + "sharp": "^0.34.0" } } diff --git a/server/src/app.module.ts b/server/src/app.module.ts index 5720f7af0b..153b525fe5 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -17,12 +17,12 @@ import { LoggingInterceptor } from 'src/middleware/logging.interceptor'; import { repositories } from 'src/repositories'; import { ConfigRepository } from 'src/repositories/config.repository'; import { EventRepository } from 'src/repositories/event.repository'; -import { JobRepository } from 'src/repositories/job.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; import { teardownTelemetry, TelemetryRepository } from 'src/repositories/telemetry.repository'; import { services } from 'src/services'; import { AuthService } from 'src/services/auth.service'; import { CliService } from 'src/services/cli.service'; +import { JobService } from 'src/services/job.service'; import { getKyselyConfig } from 'src/utils/database'; const common = [...repositories, ...services, GlobalExceptionFilter]; @@ -44,7 +44,7 @@ const imports = [ BullModule.registerQueue(...bull.queues), ClsModule.forRoot(cls.config), OpenTelemetryModule.forRoot(otel), - KyselyModule.forRoot(getKyselyConfig(database.config.kysely)), + KyselyModule.forRoot(getKyselyConfig(database.config)), ]; class BaseModule implements OnModuleInit, OnModuleDestroy { @@ -52,7 +52,7 @@ class BaseModule implements OnModuleInit, OnModuleDestroy { @Inject(IWorker) private worker: ImmichWorker, logger: LoggingRepository, private eventRepository: EventRepository, - private jobRepository: JobRepository, + private jobService: JobService, private telemetryRepository: TelemetryRepository, private authService: AuthService, ) { @@ -62,10 +62,7 @@ class BaseModule implements OnModuleInit, OnModuleDestroy { async onModuleInit() { this.telemetryRepository.setup({ repositories }); - this.jobRepository.setup({ services }); - if (this.worker === ImmichWorker.MICROSERVICES) { - this.jobRepository.startWorkers(); - } + this.jobService.setServices(services); this.eventRepository.setAuthFn(async (client) => this.authService.authenticate({ diff --git a/server/src/bin/migrations.ts b/server/src/bin/migrations.ts index 2ddc6776fb..7b850f6166 100644 --- a/server/src/bin/migrations.ts +++ b/server/src/bin/migrations.ts @@ -10,7 +10,7 @@ import { DatabaseRepository } from 'src/repositories/database.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; import 'src/schema'; import { schemaDiff, schemaFromCode, schemaFromDatabase } from 'src/sql-tools'; -import { getKyselyConfig } from 'src/utils/database'; +import { asPostgresConnectionConfig, getKyselyConfig } from 'src/utils/database'; const main = async () => { const command = process.argv[2]; @@ -56,7 +56,7 @@ const main = async () => { const getDatabaseClient = () => { const configRepository = new ConfigRepository(); const { database } = configRepository.getEnv(); - return new Kysely(getKyselyConfig(database.config.kysely)); + return new Kysely(getKyselyConfig(database.config)); }; const runQuery = async (query: string) => { @@ -105,7 +105,7 @@ const create = (path: string, up: string[], down: string[]) => { const compare = async () => { const configRepository = new ConfigRepository(); const { database } = configRepository.getEnv(); - const db = postgres(database.config.kysely); + const db = postgres(asPostgresConnectionConfig(database.config)); const source = schemaFromCode(); const target = await schemaFromDatabase(db, {}); diff --git a/server/src/bin/sync-sql.ts b/server/src/bin/sync-sql.ts index 47e6610a74..b791358a90 100644 --- a/server/src/bin/sync-sql.ts +++ b/server/src/bin/sync-sql.ts @@ -78,7 +78,7 @@ class SqlGenerator { const moduleFixture = await Test.createTestingModule({ imports: [ KyselyModule.forRoot({ - ...getKyselyConfig(database.config.kysely), + ...getKyselyConfig(database.config), log: (event) => { if (event.level === 'query') { this.sqlLogger.logQuery(event.query.sql); diff --git a/server/src/config.ts b/server/src/config.ts index 566adbd693..a9fdffbd62 100644 --- a/server/src/config.ts +++ b/server/src/config.ts @@ -5,6 +5,7 @@ import { CQMode, ImageFormat, LogLevel, + OAuthTokenEndpointAuthMethod, QueueName, ToneMapping, TranscodeHWAccel, @@ -96,6 +97,8 @@ export interface SystemConfig { scope: string; signingAlgorithm: string; profileSigningAlgorithm: string; + tokenEndpointAuthMethod: OAuthTokenEndpointAuthMethod; + timeout: number; storageLabelClaim: string; storageQuotaClaim: string; }; @@ -260,6 +263,8 @@ export const defaults = Object.freeze({ profileSigningAlgorithm: 'none', storageLabelClaim: 'preferred_username', storageQuotaClaim: 'immich_quota', + tokenEndpointAuthMethod: OAuthTokenEndpointAuthMethod.CLIENT_SECRET_POST, + timeout: 30_000, }, passwordLogin: { enabled: true, diff --git a/server/src/controllers/file-report.controller.ts b/server/src/controllers/file-report.controller.ts deleted file mode 100644 index a51a94a50e..0000000000 --- a/server/src/controllers/file-report.controller.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Body, Controller, Get, Post } from '@nestjs/common'; -import { ApiTags } from '@nestjs/swagger'; -import { FileChecksumDto, FileChecksumResponseDto, FileReportDto, FileReportFixDto } from 'src/dtos/audit.dto'; -import { Authenticated } from 'src/middleware/auth.guard'; -import { AuditService } from 'src/services/audit.service'; - -@ApiTags('File Reports') -@Controller('reports') -export class ReportController { - constructor(private service: AuditService) {} - - @Get() - @Authenticated({ admin: true }) - getAuditFiles(): Promise { - return this.service.getFileReport(); - } - - @Post('checksum') - @Authenticated({ admin: true }) - getFileChecksums(@Body() dto: FileChecksumDto): Promise { - return this.service.getChecksums(dto); - } - - @Post('fix') - @Authenticated({ admin: true }) - fixAuditFiles(@Body() dto: FileReportFixDto): Promise { - return this.service.fixItems(dto.items); - } -} diff --git a/server/src/controllers/index.ts b/server/src/controllers/index.ts index c9d63f8bcd..9c39e580b6 100644 --- a/server/src/controllers/index.ts +++ b/server/src/controllers/index.ts @@ -8,11 +8,11 @@ import { AuthController } from 'src/controllers/auth.controller'; import { DownloadController } from 'src/controllers/download.controller'; import { DuplicateController } from 'src/controllers/duplicate.controller'; import { FaceController } from 'src/controllers/face.controller'; -import { ReportController } from 'src/controllers/file-report.controller'; import { JobController } from 'src/controllers/job.controller'; import { LibraryController } from 'src/controllers/library.controller'; import { MapController } from 'src/controllers/map.controller'; import { MemoryController } from 'src/controllers/memory.controller'; +import { NotificationAdminController } from 'src/controllers/notification-admin.controller'; import { NotificationController } from 'src/controllers/notification.controller'; import { OAuthController } from 'src/controllers/oauth.controller'; import { PartnerController } from 'src/controllers/partner.controller'; @@ -48,10 +48,10 @@ export const controllers = [ MapController, MemoryController, NotificationController, + NotificationAdminController, OAuthController, PartnerController, PersonController, - ReportController, SearchController, ServerController, SessionController, diff --git a/server/src/controllers/notification-admin.controller.ts b/server/src/controllers/notification-admin.controller.ts new file mode 100644 index 0000000000..9bac865bdf --- /dev/null +++ b/server/src/controllers/notification-admin.controller.ts @@ -0,0 +1,44 @@ +import { Body, Controller, HttpCode, HttpStatus, Param, Post } from '@nestjs/common'; +import { ApiTags } from '@nestjs/swagger'; +import { AuthDto } from 'src/dtos/auth.dto'; +import { + NotificationCreateDto, + NotificationDto, + TemplateDto, + TemplateResponseDto, + TestEmailResponseDto, +} from 'src/dtos/notification.dto'; +import { SystemConfigSmtpDto } from 'src/dtos/system-config.dto'; +import { Auth, Authenticated } from 'src/middleware/auth.guard'; +import { EmailTemplate } from 'src/repositories/email.repository'; +import { NotificationAdminService } from 'src/services/notification-admin.service'; + +@ApiTags('Notifications (Admin)') +@Controller('admin/notifications') +export class NotificationAdminController { + constructor(private service: NotificationAdminService) {} + + @Post() + @Authenticated({ admin: true }) + createNotification(@Auth() auth: AuthDto, @Body() dto: NotificationCreateDto): Promise { + return this.service.create(auth, dto); + } + + @Post('test-email') + @HttpCode(HttpStatus.OK) + @Authenticated({ admin: true }) + sendTestEmailAdmin(@Auth() auth: AuthDto, @Body() dto: SystemConfigSmtpDto): Promise { + return this.service.sendTestEmail(auth.user.id, dto); + } + + @Post('templates/:name') + @HttpCode(HttpStatus.OK) + @Authenticated({ admin: true }) + getNotificationTemplateAdmin( + @Auth() auth: AuthDto, + @Param('name') name: EmailTemplate, + @Body() dto: TemplateDto, + ): Promise { + return this.service.getTemplate(name, dto.template); + } +} diff --git a/server/src/controllers/notification.controller.ts b/server/src/controllers/notification.controller.ts index 39946a9fc9..c64f786850 100644 --- a/server/src/controllers/notification.controller.ts +++ b/server/src/controllers/notification.controller.ts @@ -1,32 +1,60 @@ -import { Body, Controller, HttpCode, HttpStatus, Param, Post } from '@nestjs/common'; +import { Body, Controller, Delete, Get, Param, Put, Query } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { AuthDto } from 'src/dtos/auth.dto'; -import { TemplateDto, TemplateResponseDto, TestEmailResponseDto } from 'src/dtos/notification.dto'; -import { SystemConfigSmtpDto } from 'src/dtos/system-config.dto'; +import { + NotificationDeleteAllDto, + NotificationDto, + NotificationSearchDto, + NotificationUpdateAllDto, + NotificationUpdateDto, +} from 'src/dtos/notification.dto'; +import { Permission } from 'src/enum'; import { Auth, Authenticated } from 'src/middleware/auth.guard'; -import { EmailTemplate } from 'src/repositories/notification.repository'; import { NotificationService } from 'src/services/notification.service'; +import { UUIDParamDto } from 'src/validation'; @ApiTags('Notifications') @Controller('notifications') export class NotificationController { constructor(private service: NotificationService) {} - @Post('test-email') - @HttpCode(HttpStatus.OK) - @Authenticated({ admin: true }) - sendTestEmail(@Auth() auth: AuthDto, @Body() dto: SystemConfigSmtpDto): Promise { - return this.service.sendTestEmail(auth.user.id, dto); + @Get() + @Authenticated({ permission: Permission.NOTIFICATION_READ }) + getNotifications(@Auth() auth: AuthDto, @Query() dto: NotificationSearchDto): Promise { + return this.service.search(auth, dto); } - @Post('templates/:name') - @HttpCode(HttpStatus.OK) - @Authenticated({ admin: true }) - getNotificationTemplate( + @Put() + @Authenticated({ permission: Permission.NOTIFICATION_UPDATE }) + updateNotifications(@Auth() auth: AuthDto, @Body() dto: NotificationUpdateAllDto): Promise { + return this.service.updateAll(auth, dto); + } + + @Delete() + @Authenticated({ permission: Permission.NOTIFICATION_DELETE }) + deleteNotifications(@Auth() auth: AuthDto, @Body() dto: NotificationDeleteAllDto): Promise { + return this.service.deleteAll(auth, dto); + } + + @Get(':id') + @Authenticated({ permission: Permission.NOTIFICATION_READ }) + getNotification(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise { + return this.service.get(auth, id); + } + + @Put(':id') + @Authenticated({ permission: Permission.NOTIFICATION_UPDATE }) + updateNotification( @Auth() auth: AuthDto, - @Param('name') name: EmailTemplate, - @Body() dto: TemplateDto, - ): Promise { - return this.service.getTemplate(name, dto.template); + @Param() { id }: UUIDParamDto, + @Body() dto: NotificationUpdateDto, + ): Promise { + return this.service.update(auth, id, dto); + } + + @Delete(':id') + @Authenticated({ permission: Permission.NOTIFICATION_DELETE }) + deleteNotification(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise { + return this.service.delete(auth, id); } } diff --git a/server/src/controllers/oauth.controller.ts b/server/src/controllers/oauth.controller.ts index b5b94030f2..23ddff5ddc 100644 --- a/server/src/controllers/oauth.controller.ts +++ b/server/src/controllers/oauth.controller.ts @@ -29,17 +29,35 @@ export class OAuthController { } @Post('authorize') - startOAuth(@Body() dto: OAuthConfigDto): Promise { - return this.service.authorize(dto); + async startOAuth( + @Body() dto: OAuthConfigDto, + @Res({ passthrough: true }) res: Response, + @GetLoginDetails() loginDetails: LoginDetails, + ): Promise { + const { url, state, codeVerifier } = await this.service.authorize(dto); + return respondWithCookie( + res, + { url }, + { + isSecure: loginDetails.isSecure, + values: [ + { key: ImmichCookie.OAUTH_STATE, value: state }, + { key: ImmichCookie.OAUTH_CODE_VERIFIER, value: codeVerifier }, + ], + }, + ); } @Post('callback') async finishOAuth( + @Req() request: Request, @Res({ passthrough: true }) res: Response, @Body() dto: OAuthCallbackDto, @GetLoginDetails() loginDetails: LoginDetails, ): Promise { - const body = await this.service.callback(dto, loginDetails); + const body = await this.service.callback(dto, request.headers, loginDetails); + res.clearCookie(ImmichCookie.OAUTH_STATE); + res.clearCookie(ImmichCookie.OAUTH_CODE_VERIFIER); return respondWithCookie(res, body, { isSecure: loginDetails.isSecure, values: [ @@ -52,8 +70,12 @@ export class OAuthController { @Post('link') @Authenticated() - linkOAuthAccount(@Auth() auth: AuthDto, @Body() dto: OAuthCallbackDto): Promise { - return this.service.link(auth, dto); + linkOAuthAccount( + @Req() request: Request, + @Auth() auth: AuthDto, + @Body() dto: OAuthCallbackDto, + ): Promise { + return this.service.link(auth, dto, request.headers); } @Post('unlink') diff --git a/server/src/cores/storage.core.ts b/server/src/cores/storage.core.ts index 9bd43a662d..1a8e31e86b 100644 --- a/server/src/cores/storage.core.ts +++ b/server/src/cores/storage.core.ts @@ -90,7 +90,7 @@ export class StorageCore { return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, person.ownerId, `${person.id}.jpeg`); } - static getImagePath(asset: ThumbnailPathEntity, type: GeneratedImageType, format: ImageFormat) { + static getImagePath(asset: ThumbnailPathEntity, type: GeneratedImageType, format: 'jpeg' | 'webp') { return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, asset.ownerId, `${asset.id}-${type}.${format}`); } diff --git a/server/src/database.ts b/server/src/database.ts index 32ecaa2a76..7ed1367f70 100644 --- a/server/src/database.ts +++ b/server/src/database.ts @@ -9,6 +9,7 @@ import { Permission, SharedLinkType, SourceType, + UserAvatarColor, UserStatus, } from 'src/enum'; import { OnThisDayData, UserMetadataItem } from 'src/types'; @@ -122,6 +123,7 @@ export type User = { id: string; name: string; email: string; + avatarColor: UserAvatarColor | null; profileImagePath: string; profileChangedAt: Date; }; @@ -264,7 +266,15 @@ export type AssetFace = { person?: Person | null; }; -const userColumns = ['id', 'name', 'email', 'profileImagePath', 'profileChangedAt'] as const; +const userColumns = ['id', 'name', 'email', 'avatarColor', 'profileImagePath', 'profileChangedAt'] as const; +const userWithPrefixColumns = [ + 'users.id', + 'users.name', + 'users.email', + 'users.avatarColor', + 'users.profileImagePath', + 'users.profileChangedAt', +] as const; export const columns = { asset: [ @@ -306,7 +316,7 @@ export const columns = { 'shared_links.password', ], user: userColumns, - userWithPrefix: ['users.id', 'users.name', 'users.email', 'users.profileImagePath', 'users.profileChangedAt'], + userWithPrefix: userWithPrefixColumns, userAdmin: [ ...userColumns, 'createdAt', @@ -323,6 +333,7 @@ export const columns = { ], tag: ['tags.id', 'tags.value', 'tags.createdAt', 'tags.updatedAt', 'tags.color', 'tags.parentId'], apiKey: ['id', 'name', 'userId', 'createdAt', 'updatedAt', 'permissions'], + notification: ['id', 'createdAt', 'level', 'type', 'title', 'description', 'data', 'readAt'], syncAsset: [ 'id', 'ownerId', diff --git a/server/src/db.d.ts b/server/src/db.d.ts index 4e9738ecec..85be9d5208 100644 --- a/server/src/db.d.ts +++ b/server/src/db.d.ts @@ -11,6 +11,8 @@ import { AssetStatus, AssetType, MemoryType, + NotificationLevel, + NotificationType, Permission, SharedLinkType, SourceType, @@ -263,6 +265,21 @@ export interface Memories { updateId: Generated; } +export interface Notifications { + id: Generated; + createdAt: Generated; + updatedAt: Generated; + deletedAt: Timestamp | null; + updateId: Generated; + userId: string; + level: Generated; + type: NotificationType; + title: string; + description: string | null; + data: any | null; + readAt: Timestamp | null; +} + export interface MemoriesAssetsAssets { assetsId: string; memoriesId: string; @@ -463,6 +480,7 @@ export interface DB { memories: Memories; memories_assets_assets: MemoriesAssetsAssets; migrations: Migrations; + notifications: Notifications; move_history: MoveHistory; naturalearth_countries: NaturalearthCountries; partners_audit: PartnersAudit; diff --git a/server/src/dtos/audit.dto.ts b/server/src/dtos/audit.dto.ts deleted file mode 100644 index 434da46eba..0000000000 --- a/server/src/dtos/audit.dto.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { Type } from 'class-transformer'; -import { IsArray, IsEnum, IsString, IsUUID, ValidateNested } from 'class-validator'; -import { AssetPathType, EntityType, PathType, PersonPathType, UserPathType } from 'src/enum'; -import { Optional, ValidateDate, ValidateUUID } from 'src/validation'; - -const PathEnum = Object.values({ ...AssetPathType, ...PersonPathType, ...UserPathType }); - -export class AuditDeletesDto { - @ValidateDate() - after!: Date; - - @ApiProperty({ enum: EntityType, enumName: 'EntityType' }) - @IsEnum(EntityType) - entityType!: EntityType; - - @Optional() - @IsUUID('4') - @ApiProperty({ format: 'uuid' }) - userId?: string; -} - -export enum PathEntityType { - ASSET = 'asset', - PERSON = 'person', - USER = 'user', -} - -export class AuditDeletesResponseDto { - needsFullSync!: boolean; - ids!: string[]; -} - -export class FileReportDto { - orphans!: FileReportItemDto[]; - extras!: string[]; -} - -export class FileChecksumDto { - @IsString({ each: true }) - filenames!: string[]; -} - -export class FileChecksumResponseDto { - filename!: string; - checksum!: string; -} - -export class FileReportFixDto { - @IsArray() - @ValidateNested({ each: true }) - @Type(() => FileReportItemDto) - items!: FileReportItemDto[]; -} - -// used both as request and response dto -export class FileReportItemDto { - @ValidateUUID() - entityId!: string; - - @ApiProperty({ enumName: 'PathEntityType', enum: PathEntityType }) - @IsEnum(PathEntityType) - entityType!: PathEntityType; - - @ApiProperty({ enumName: 'PathType', enum: PathEnum }) - @IsEnum(PathEnum) - pathType!: PathType; - - @IsString() - pathValue!: string; - - checksum?: string; -} diff --git a/server/src/dtos/auth.dto.ts b/server/src/dtos/auth.dto.ts index 7f2ffa5878..a1978d39dd 100644 --- a/server/src/dtos/auth.dto.ts +++ b/server/src/dtos/auth.dto.ts @@ -3,11 +3,11 @@ import { Transform } from 'class-transformer'; import { IsEmail, IsNotEmpty, IsString, MinLength } from 'class-validator'; import { AuthApiKey, AuthSession, AuthSharedLink, AuthUser, UserAdmin } from 'src/database'; import { ImmichCookie } from 'src/enum'; -import { toEmail } from 'src/validation'; +import { Optional, toEmail } from 'src/validation'; export type CookieResponse = { isSecure: boolean; - values: Array<{ key: ImmichCookie; value: string }>; + values: Array<{ key: ImmichCookie; value: string | null }>; }; export class AuthDto { @@ -87,12 +87,28 @@ export class OAuthCallbackDto { @IsString() @ApiProperty() url!: string; + + @Optional() + @IsString() + state?: string; + + @Optional() + @IsString() + codeVerifier?: string; } export class OAuthConfigDto { @IsNotEmpty() @IsString() redirectUri!: string; + + @Optional() + @IsString() + state?: string; + + @Optional() + @IsString() + codeChallenge?: string; } export class OAuthAuthorizeResponseDto { diff --git a/server/src/dtos/notification.dto.ts b/server/src/dtos/notification.dto.ts index c1a09c801c..d9847cda17 100644 --- a/server/src/dtos/notification.dto.ts +++ b/server/src/dtos/notification.dto.ts @@ -1,4 +1,7 @@ -import { IsString } from 'class-validator'; +import { ApiProperty } from '@nestjs/swagger'; +import { IsEnum, IsString } from 'class-validator'; +import { NotificationLevel, NotificationType } from 'src/enum'; +import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/validation'; export class TestEmailResponseDto { messageId!: string; @@ -11,3 +14,106 @@ export class TemplateDto { @IsString() template!: string; } + +export class NotificationDto { + id!: string; + @ValidateDate() + createdAt!: Date; + @ApiProperty({ enum: NotificationLevel, enumName: 'NotificationLevel' }) + level!: NotificationLevel; + @ApiProperty({ enum: NotificationType, enumName: 'NotificationType' }) + type!: NotificationType; + title!: string; + description?: string; + data?: any; + readAt?: Date; +} + +export class NotificationSearchDto { + @Optional() + @ValidateUUID({ optional: true }) + id?: string; + + @IsEnum(NotificationLevel) + @Optional() + @ApiProperty({ enum: NotificationLevel, enumName: 'NotificationLevel' }) + level?: NotificationLevel; + + @IsEnum(NotificationType) + @Optional() + @ApiProperty({ enum: NotificationType, enumName: 'NotificationType' }) + type?: NotificationType; + + @ValidateBoolean({ optional: true }) + unread?: boolean; +} + +export class NotificationCreateDto { + @Optional() + @IsEnum(NotificationLevel) + @ApiProperty({ enum: NotificationLevel, enumName: 'NotificationLevel' }) + level?: NotificationLevel; + + @IsEnum(NotificationType) + @Optional() + @ApiProperty({ enum: NotificationType, enumName: 'NotificationType' }) + type?: NotificationType; + + @IsString() + title!: string; + + @IsString() + @Optional({ nullable: true }) + description?: string | null; + + @Optional({ nullable: true }) + data?: any; + + @ValidateDate({ optional: true, nullable: true }) + readAt?: Date | null; + + @ValidateUUID() + userId!: string; +} + +export class NotificationUpdateDto { + @ValidateDate({ optional: true, nullable: true }) + readAt?: Date | null; +} + +export class NotificationUpdateAllDto { + @ValidateUUID({ each: true, optional: true }) + ids!: string[]; + + @ValidateDate({ optional: true, nullable: true }) + readAt?: Date | null; +} + +export class NotificationDeleteAllDto { + @ValidateUUID({ each: true }) + ids!: string[]; +} + +export type MapNotification = { + id: string; + createdAt: Date; + updateId?: string; + level: NotificationLevel; + type: NotificationType; + data: any | null; + title: string; + description: string | null; + readAt: Date | null; +}; +export const mapNotification = (notification: MapNotification): NotificationDto => { + return { + id: notification.id, + createdAt: notification.createdAt, + level: notification.level, + type: notification.type, + title: notification.title, + description: notification.description ?? undefined, + data: notification.data ?? undefined, + readAt: notification.readAt ?? undefined, + }; +}; diff --git a/server/src/dtos/system-config.dto.ts b/server/src/dtos/system-config.dto.ts index eaef40a5e1..6991baf109 100644 --- a/server/src/dtos/system-config.dto.ts +++ b/server/src/dtos/system-config.dto.ts @@ -25,6 +25,7 @@ import { Colorspace, ImageFormat, LogLevel, + OAuthTokenEndpointAuthMethod, QueueName, ToneMapping, TranscodeHWAccel, @@ -33,7 +34,7 @@ import { VideoContainer, } from 'src/enum'; import { ConcurrentQueueName } from 'src/types'; -import { IsCronExpression, ValidateBoolean } from 'src/validation'; +import { IsCronExpression, Optional, ValidateBoolean } from 'src/validation'; const isLibraryScanEnabled = (config: SystemConfigLibraryScanDto) => config.enabled; const isOAuthEnabled = (config: SystemConfigOAuthDto) => config.enabled; @@ -344,10 +345,19 @@ class SystemConfigOAuthDto { clientId!: string; @ValidateIf(isOAuthEnabled) - @IsNotEmpty() @IsString() clientSecret!: string; + @IsEnum(OAuthTokenEndpointAuthMethod) + @ApiProperty({ enum: OAuthTokenEndpointAuthMethod, enumName: 'OAuthTokenEndpointAuthMethod' }) + tokenEndpointAuthMethod!: OAuthTokenEndpointAuthMethod; + + @IsInt() + @IsPositive() + @Optional() + @ApiProperty({ type: 'integer' }) + timeout!: number; + @IsNumber() @Min(0) defaultStorageQuota!: number; diff --git a/server/src/dtos/user-preferences.dto.ts b/server/src/dtos/user-preferences.dto.ts index fe92838fdb..a9d32523ae 100644 --- a/server/src/dtos/user-preferences.dto.ts +++ b/server/src/dtos/user-preferences.dto.ts @@ -137,11 +137,6 @@ export class UserPreferencesUpdateDto { purchase?: PurchaseUpdate; } -class AvatarResponse { - @ApiProperty({ enumName: 'UserAvatarColor', enum: UserAvatarColor }) - color!: UserAvatarColor; -} - class RatingsResponse { enabled: boolean = false; } @@ -195,7 +190,6 @@ export class UserPreferencesResponseDto implements UserPreferences { ratings!: RatingsResponse; sharedLinks!: SharedLinksResponse; tags!: TagsResponse; - avatar!: AvatarResponse; emailNotifications!: EmailNotificationsResponse; download!: DownloadResponse; purchase!: PurchaseResponse; diff --git a/server/src/dtos/user.dto.ts b/server/src/dtos/user.dto.ts index 72e5c83b35..31275f9c28 100644 --- a/server/src/dtos/user.dto.ts +++ b/server/src/dtos/user.dto.ts @@ -1,10 +1,9 @@ import { ApiProperty } from '@nestjs/swagger'; import { Transform } from 'class-transformer'; -import { IsBoolean, IsEmail, IsNotEmpty, IsNumber, IsString, Min } from 'class-validator'; +import { IsBoolean, IsEmail, IsEnum, IsNotEmpty, IsNumber, IsString, Min } from 'class-validator'; import { User, UserAdmin } from 'src/database'; import { UserAvatarColor, UserMetadataKey, UserStatus } from 'src/enum'; import { UserMetadataItem } from 'src/types'; -import { getPreferences } from 'src/utils/preferences'; import { Optional, ValidateBoolean, toEmail, toSanitized } from 'src/validation'; export class UserUpdateMeDto { @@ -23,6 +22,11 @@ export class UserUpdateMeDto { @IsString() @IsNotEmpty() name?: string; + + @Optional({ nullable: true }) + @IsEnum(UserAvatarColor) + @ApiProperty({ enumName: 'UserAvatarColor', enum: UserAvatarColor }) + avatarColor?: UserAvatarColor | null; } export class UserResponseDto { @@ -41,13 +45,21 @@ export class UserLicense { activatedAt!: Date; } +const emailToAvatarColor = (email: string): UserAvatarColor => { + const values = Object.values(UserAvatarColor); + const randomIndex = Math.floor( + [...email].map((letter) => letter.codePointAt(0) ?? 0).reduce((a, b) => a + b, 0) % values.length, + ); + return values[randomIndex]; +}; + export const mapUser = (entity: User | UserAdmin): UserResponseDto => { return { id: entity.id, email: entity.email, name: entity.name, profileImagePath: entity.profileImagePath, - avatarColor: getPreferences(entity.email, (entity as UserAdmin).metadata || []).avatar.color, + avatarColor: entity.avatarColor ?? emailToAvatarColor(entity.email), profileChangedAt: entity.profileChangedAt, }; }; @@ -69,6 +81,11 @@ export class UserAdminCreateDto { @IsString() name!: string; + @Optional({ nullable: true }) + @IsEnum(UserAvatarColor) + @ApiProperty({ enumName: 'UserAvatarColor', enum: UserAvatarColor }) + avatarColor?: UserAvatarColor | null; + @Optional({ nullable: true }) @IsString() @Transform(toSanitized) @@ -104,6 +121,11 @@ export class UserAdminUpdateDto { @IsNotEmpty() name?: string; + @Optional({ nullable: true }) + @IsEnum(UserAvatarColor) + @ApiProperty({ enumName: 'UserAvatarColor', enum: UserAvatarColor }) + avatarColor?: UserAvatarColor | null; + @Optional({ nullable: true }) @IsString() @Transform(toSanitized) diff --git a/server/src/emails/album-invite.email.tsx b/server/src/emails/album-invite.email.tsx index 4bd7abc305..fdc189af97 100644 --- a/server/src/emails/album-invite.email.tsx +++ b/server/src/emails/album-invite.email.tsx @@ -2,7 +2,7 @@ import { Img, Link, Section, Text } from '@react-email/components'; import * as React from 'react'; import { ImmichButton } from 'src/emails/components/button.component'; import ImmichLayout from 'src/emails/components/immich.layout'; -import { AlbumInviteEmailProps } from 'src/repositories/notification.repository'; +import { AlbumInviteEmailProps } from 'src/repositories/email.repository'; import { replaceTemplateTags } from 'src/utils/replace-template-tags'; export const AlbumInviteEmail = ({ diff --git a/server/src/emails/album-update.email.tsx b/server/src/emails/album-update.email.tsx index 2311e896e1..3bed3a5b36 100644 --- a/server/src/emails/album-update.email.tsx +++ b/server/src/emails/album-update.email.tsx @@ -2,7 +2,7 @@ import { Img, Link, Section, Text } from '@react-email/components'; import * as React from 'react'; import { ImmichButton } from 'src/emails/components/button.component'; import ImmichLayout from 'src/emails/components/immich.layout'; -import { AlbumUpdateEmailProps } from 'src/repositories/notification.repository'; +import { AlbumUpdateEmailProps } from 'src/repositories/email.repository'; import { replaceTemplateTags } from 'src/utils/replace-template-tags'; export const AlbumUpdateEmail = ({ diff --git a/server/src/emails/test.email.tsx b/server/src/emails/test.email.tsx index ac9bdbe0ea..0d87307080 100644 --- a/server/src/emails/test.email.tsx +++ b/server/src/emails/test.email.tsx @@ -1,7 +1,7 @@ import { Link, Row, Text } from '@react-email/components'; import * as React from 'react'; import ImmichLayout from 'src/emails/components/immich.layout'; -import { TestEmailProps } from 'src/repositories/notification.repository'; +import { TestEmailProps } from 'src/repositories/email.repository'; export const TestEmail = ({ baseUrl, displayName }: TestEmailProps) => ( diff --git a/server/src/emails/welcome.email.tsx b/server/src/emails/welcome.email.tsx index 11a6602711..57e86ab252 100644 --- a/server/src/emails/welcome.email.tsx +++ b/server/src/emails/welcome.email.tsx @@ -2,7 +2,7 @@ import { Link, Section, Text } from '@react-email/components'; import * as React from 'react'; import { ImmichButton } from 'src/emails/components/button.component'; import ImmichLayout from 'src/emails/components/immich.layout'; -import { WelcomeEmailProps } from 'src/repositories/notification.repository'; +import { WelcomeEmailProps } from 'src/repositories/email.repository'; import { replaceTemplateTags } from 'src/utils/replace-template-tags'; export const WelcomeEmail = ({ baseUrl, displayName, username, password, customTemplate }: WelcomeEmailProps) => { diff --git a/server/src/enum.ts b/server/src/enum.ts index e5c6039be8..4e725e1c13 100644 --- a/server/src/enum.ts +++ b/server/src/enum.ts @@ -8,6 +8,8 @@ export enum ImmichCookie { AUTH_TYPE = 'immich_auth_type', IS_AUTHENTICATED = 'immich_is_authenticated', SHARED_LINK_TOKEN = 'immich_shared_link_token', + OAUTH_STATE = 'immich_oauth_state', + OAUTH_CODE_VERIFIER = 'immich_oauth_code_verifier', } export enum ImmichHeader { @@ -124,6 +126,11 @@ export enum Permission { MEMORY_UPDATE = 'memory.update', MEMORY_DELETE = 'memory.delete', + NOTIFICATION_CREATE = 'notification.create', + NOTIFICATION_READ = 'notification.read', + NOTIFICATION_UPDATE = 'notification.update', + NOTIFICATION_DELETE = 'notification.delete', + PARTNER_CREATE = 'partner.create', PARTNER_READ = 'partner.read', PARTNER_UPDATE = 'partner.update', @@ -330,6 +337,11 @@ export enum ImageFormat { WEBP = 'webp', } +export enum RawExtractedFormat { + JPEG = 'jpeg', + JXL = 'jxl', +} + export enum LogLevel { VERBOSE = 'verbose', DEBUG = 'debug', @@ -405,6 +417,8 @@ export enum DatabaseExtension { export enum BootstrapEventPriority { // Database service should be initialized before anything else, most other services need database access DatabaseService = -200, + // Other services may need to queue jobs on bootstrap. + JobService = -190, // Initialise config after other bootstrap services, stop other services from using config on bootstrap SystemConfig = 100, } @@ -511,6 +525,7 @@ export enum JobName { NOTIFY_SIGNUP = 'notify-signup', NOTIFY_ALBUM_INVITE = 'notify-album-invite', NOTIFY_ALBUM_UPDATE = 'notify-album-update', + NOTIFICATIONS_CLEANUP = 'notifications-cleanup', SEND_EMAIL = 'notification-send-email', // Version check @@ -576,3 +591,22 @@ export enum SyncEntityType { PartnerAssetDeleteV1 = 'PartnerAssetDeleteV1', PartnerAssetExifV1 = 'PartnerAssetExifV1', } + +export enum NotificationLevel { + Success = 'success', + Error = 'error', + Warning = 'warning', + Info = 'info', +} + +export enum NotificationType { + JobFailed = 'JobFailed', + BackupFailed = 'BackupFailed', + SystemMessage = 'SystemMessage', + Custom = 'Custom', +} + +export enum OAuthTokenEndpointAuthMethod { + CLIENT_SECRET_POST = 'client_secret_post', + CLIENT_SECRET_BASIC = 'client_secret_basic', +} diff --git a/server/src/migrations/1700713994428-AddCLIPEmbeddingIndex.ts b/server/src/migrations/1700713994428-AddCLIPEmbeddingIndex.ts index 993e12f822..b5d47bb8cd 100644 --- a/server/src/migrations/1700713994428-AddCLIPEmbeddingIndex.ts +++ b/server/src/migrations/1700713994428-AddCLIPEmbeddingIndex.ts @@ -1,5 +1,5 @@ -import { DatabaseExtension } from 'src/enum'; import { ConfigRepository } from 'src/repositories/config.repository'; +import { vectorIndexQuery } from 'src/utils/database'; import { MigrationInterface, QueryRunner } from 'typeorm'; const vectorExtension = new ConfigRepository().getEnv().database.vectorExtension; @@ -8,15 +8,9 @@ export class AddCLIPEmbeddingIndex1700713994428 implements MigrationInterface { name = 'AddCLIPEmbeddingIndex1700713994428'; public async up(queryRunner: QueryRunner): Promise { - if (vectorExtension === DatabaseExtension.VECTORS) { - await queryRunner.query(`SET vectors.pgvector_compatibility=on`); - } await queryRunner.query(`SET search_path TO "$user", public, vectors`); - await queryRunner.query(` - CREATE INDEX IF NOT EXISTS clip_index ON smart_search - USING hnsw (embedding vector_cosine_ops) - WITH (ef_construction = 300, m = 16)`); + await queryRunner.query(vectorIndexQuery({ vectorExtension, table: 'smart_search', indexName: 'clip_index' })); } public async down(queryRunner: QueryRunner): Promise { diff --git a/server/src/migrations/1700714033632-AddFaceEmbeddingIndex.ts b/server/src/migrations/1700714033632-AddFaceEmbeddingIndex.ts index 182aae4e42..2b41788fe4 100644 --- a/server/src/migrations/1700714033632-AddFaceEmbeddingIndex.ts +++ b/server/src/migrations/1700714033632-AddFaceEmbeddingIndex.ts @@ -1,5 +1,5 @@ -import { DatabaseExtension } from 'src/enum'; import { ConfigRepository } from 'src/repositories/config.repository'; +import { vectorIndexQuery } from 'src/utils/database'; import { MigrationInterface, QueryRunner } from 'typeorm'; const vectorExtension = new ConfigRepository().getEnv().database.vectorExtension; @@ -8,15 +8,9 @@ export class AddFaceEmbeddingIndex1700714033632 implements MigrationInterface { name = 'AddFaceEmbeddingIndex1700714033632'; public async up(queryRunner: QueryRunner): Promise { - if (vectorExtension === DatabaseExtension.VECTORS) { - await queryRunner.query(`SET vectors.pgvector_compatibility=on`); - } await queryRunner.query(`SET search_path TO "$user", public, vectors`); - await queryRunner.query(` - CREATE INDEX IF NOT EXISTS face_index ON asset_faces - USING hnsw (embedding vector_cosine_ops) - WITH (ef_construction = 300, m = 16)`); + await queryRunner.query(vectorIndexQuery({ vectorExtension, table: 'asset_faces', indexName: 'face_index' })); } public async down(queryRunner: QueryRunner): Promise { diff --git a/server/src/migrations/1718486162779-AddFaceSearchRelation.ts b/server/src/migrations/1718486162779-AddFaceSearchRelation.ts index e08bcb8e25..64849708d2 100644 --- a/server/src/migrations/1718486162779-AddFaceSearchRelation.ts +++ b/server/src/migrations/1718486162779-AddFaceSearchRelation.ts @@ -1,5 +1,6 @@ import { DatabaseExtension } from 'src/enum'; import { ConfigRepository } from 'src/repositories/config.repository'; +import { vectorIndexQuery } from 'src/utils/database'; import { MigrationInterface, QueryRunner } from 'typeorm'; const vectorExtension = new ConfigRepository().getEnv().database.vectorExtension; @@ -8,7 +9,6 @@ export class AddFaceSearchRelation1718486162779 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise { if (vectorExtension === DatabaseExtension.VECTORS) { await queryRunner.query(`SET search_path TO "$user", public, vectors`); - await queryRunner.query(`SET vectors.pgvector_compatibility=on`); } const hasEmbeddings = async (tableName: string): Promise => { @@ -47,21 +47,14 @@ export class AddFaceSearchRelation1718486162779 implements MigrationInterface { await queryRunner.query(`ALTER TABLE face_search ALTER COLUMN embedding SET DATA TYPE real[]`); await queryRunner.query(`ALTER TABLE face_search ALTER COLUMN embedding SET DATA TYPE vector(512)`); - await queryRunner.query(` - CREATE INDEX IF NOT EXISTS clip_index ON smart_search - USING hnsw (embedding vector_cosine_ops) - WITH (ef_construction = 300, m = 16)`); + await queryRunner.query(vectorIndexQuery({ vectorExtension, table: 'smart_search', indexName: 'clip_index' })); - await queryRunner.query(` - CREATE INDEX face_index ON face_search - USING hnsw (embedding vector_cosine_ops) - WITH (ef_construction = 300, m = 16)`); + await queryRunner.query(vectorIndexQuery({ vectorExtension, table: 'face_search', indexName: 'face_index' })); } public async down(queryRunner: QueryRunner): Promise { if (vectorExtension === DatabaseExtension.VECTORS) { await queryRunner.query(`SET search_path TO "$user", public, vectors`); - await queryRunner.query(`SET vectors.pgvector_compatibility=on`); } await queryRunner.query(`ALTER TABLE asset_faces ADD COLUMN "embedding" vector(512)`); @@ -74,9 +67,6 @@ export class AddFaceSearchRelation1718486162779 implements MigrationInterface { WHERE id = fs."faceId"`); await queryRunner.query(`DROP TABLE face_search`); - await queryRunner.query(` - CREATE INDEX face_index ON asset_faces - USING hnsw (embedding vector_cosine_ops) - WITH (ef_construction = 300, m = 16)`); + await queryRunner.query(vectorIndexQuery({ vectorExtension, table: 'asset_faces', indexName: 'face_index' })); } } diff --git a/server/src/queries/access.repository.sql b/server/src/queries/access.repository.sql index dd58aebcb2..03f1af3b28 100644 --- a/server/src/queries/access.repository.sql +++ b/server/src/queries/access.repository.sql @@ -157,6 +157,15 @@ where and "memories"."ownerId" = $2 and "memories"."deletedAt" is null +-- AccessRepository.notification.checkOwnerAccess +select + "notifications"."id" +from + "notifications" +where + "notifications"."id" in ($1) + and "notifications"."userId" = $2 + -- AccessRepository.person.checkOwnerAccess select "person"."id" diff --git a/server/src/queries/activity.repository.sql b/server/src/queries/activity.repository.sql index c6e4c60a19..3040de8e03 100644 --- a/server/src/queries/activity.repository.sql +++ b/server/src/queries/activity.repository.sql @@ -13,6 +13,7 @@ from "users"."id", "users"."name", "users"."email", + "users"."avatarColor", "users"."profileImagePath", "users"."profileChangedAt" from @@ -44,6 +45,7 @@ returning "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt" from diff --git a/server/src/queries/album.repository.sql b/server/src/queries/album.repository.sql index b89cbfb0b9..f4eb6a9929 100644 --- a/server/src/queries/album.repository.sql +++ b/server/src/queries/album.repository.sql @@ -12,6 +12,7 @@ select "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt" from @@ -36,6 +37,7 @@ select "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt" from @@ -100,6 +102,7 @@ select "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt" from @@ -124,6 +127,7 @@ select "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt" from @@ -191,6 +195,7 @@ select "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt" from @@ -215,6 +220,7 @@ select "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt" from @@ -269,6 +275,7 @@ select "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt" from @@ -292,6 +299,7 @@ select "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt" from @@ -353,6 +361,7 @@ select "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt" from diff --git a/server/src/queries/asset.job.repository.sql b/server/src/queries/asset.job.repository.sql index bf96ae80d6..d8e8430be7 100644 --- a/server/src/queries/asset.job.repository.sql +++ b/server/src/queries/asset.job.repository.sql @@ -194,6 +194,43 @@ where "asset_files"."assetId" = $1 and "asset_files"."type" = $2 +-- AssetJobRepository.streamForSearchDuplicates +select + "assets"."id" +from + "assets" + inner join "asset_job_status" as "job_status" on "assetId" = "assets"."id" +where + "assets"."isVisible" = $1 + and "assets"."deletedAt" is null + and "job_status"."previewAt" is not null + and not exists ( + select + from + "smart_search" + where + "assetId" = "assets"."id" + ) + and "job_status"."duplicatesDetectedAt" is null + +-- AssetJobRepository.streamForEncodeClip +select + "assets"."id" +from + "assets" + inner join "asset_job_status" as "job_status" on "assetId" = "assets"."id" +where + "assets"."isVisible" = $1 + and "assets"."deletedAt" is null + and "job_status"."previewAt" is not null + and not exists ( + select + from + "smart_search" + where + "assetId" = "assets"."id" + ) + -- AssetJobRepository.getForClipEncoding select "assets"."id", @@ -259,6 +296,130 @@ from where "assets"."id" = $2 +-- AssetJobRepository.getForSyncAssets +select + "assets"."id", + "assets"."isOffline", + "assets"."libraryId", + "assets"."originalPath", + "assets"."status", + "assets"."fileModifiedAt" +from + "assets" +where + "assets"."id" = any ($1::uuid[]) + +-- AssetJobRepository.getForAssetDeletion +select + "assets"."id", + "assets"."isVisible", + "assets"."libraryId", + "assets"."ownerId", + "assets"."livePhotoVideoId", + "assets"."sidecarPath", + "assets"."encodedVideoPath", + "assets"."originalPath", + to_json("exif") as "exifInfo", + ( + select + coalesce(json_agg(agg), '[]') + from + ( + select + "asset_faces".*, + "person" as "person" + from + "asset_faces" + left join lateral ( + select + "person".* + from + "person" + where + "asset_faces"."personId" = "person"."id" + ) as "person" on true + where + "asset_faces"."assetId" = "assets"."id" + and "asset_faces"."deletedAt" is null + ) as agg + ) as "faces", + ( + select + coalesce(json_agg(agg), '[]') + from + ( + select + "asset_files"."id", + "asset_files"."path", + "asset_files"."type" + from + "asset_files" + where + "asset_files"."assetId" = "assets"."id" + ) as agg + ) as "files", + to_json("stacked_assets") as "stack" +from + "assets" + left join "exif" on "assets"."id" = "exif"."assetId" + left join "asset_stack" on "asset_stack"."id" = "assets"."stackId" + left join lateral ( + select + "asset_stack"."id", + "asset_stack"."primaryAssetId", + array_agg("stacked") as "assets" + from + "assets" as "stacked" + where + "stacked"."deletedAt" is not null + and "stacked"."isArchived" = $1 + and "stacked"."stackId" = "asset_stack"."id" + group by + "asset_stack"."id" + ) as "stacked_assets" on "asset_stack"."id" is not null +where + "assets"."id" = $2 + +-- AssetJobRepository.streamForVideoConversion +select + "assets"."id" +from + "assets" +where + "assets"."type" = $1 + and ( + "assets"."encodedVideoPath" is null + or "assets"."encodedVideoPath" = $2 + ) + and "assets"."isVisible" = $3 + and "assets"."deletedAt" is null + +-- AssetJobRepository.getForVideoConversion +select + "assets"."id", + "assets"."ownerId", + "assets"."originalPath", + "assets"."encodedVideoPath" +from + "assets" +where + "assets"."id" = $1 + and "assets"."type" = $2 + +-- AssetJobRepository.streamForMetadataExtraction +select + "assets"."id" +from + "assets" + left join "asset_job_status" on "asset_job_status"."assetId" = "assets"."id" +where + ( + "asset_job_status"."metadataExtractedAt" is null + or "asset_job_status"."assetId" is null + ) + and "assets"."isVisible" = $1 + and "assets"."deletedAt" is null + -- AssetJobRepository.getForStorageTemplateJob select "assets"."id", @@ -308,3 +469,37 @@ from "assets" where "assets"."deletedAt" <= $1 + +-- AssetJobRepository.streamForSidecar +select + "assets"."id" +from + "assets" +where + ( + "assets"."sidecarPath" = $1 + or "assets"."sidecarPath" is null + ) + and "assets"."isVisible" = $2 + +-- AssetJobRepository.streamForDetectFacesJob +select + "assets"."id" +from + "assets" + inner join "asset_job_status" as "job_status" on "assetId" = "assets"."id" +where + "assets"."isVisible" = $1 + and "assets"."deletedAt" is null + and "job_status"."previewAt" is not null + and "job_status"."facesRecognizedAt" is null +order by + "assets"."createdAt" desc + +-- AssetJobRepository.streamForMigrationJob +select + "id" +from + "assets" +where + "assets"."deletedAt" is null diff --git a/server/src/queries/asset.repository.sql b/server/src/queries/asset.repository.sql index a3dcb08c1e..cb438e1c6d 100644 --- a/server/src/queries/asset.repository.sql +++ b/server/src/queries/asset.repository.sql @@ -232,25 +232,6 @@ where limit $3 --- AssetRepository.getWithout (sidecar) -select - "assets".* -from - "assets" -where - ( - "assets"."sidecarPath" = $1 - or "assets"."sidecarPath" is null - ) - and "assets"."isVisible" = $2 - and "deletedAt" is null -order by - "createdAt" -limit - $3 -offset - $4 - -- AssetRepository.getTimeBuckets with "assets" as ( diff --git a/server/src/queries/notification.repository.sql b/server/src/queries/notification.repository.sql new file mode 100644 index 0000000000..c55e00d226 --- /dev/null +++ b/server/src/queries/notification.repository.sql @@ -0,0 +1,58 @@ +-- NOTE: This file is auto generated by ./sql-generator + +-- NotificationRepository.cleanup +delete from "notifications" +where + ( + ( + "deletedAt" is not null + and "deletedAt" < $1 + ) + or ( + "readAt" > $2 + and "createdAt" < $3 + ) + or ( + "readAt" = $4 + and "createdAt" < $5 + ) + ) + +-- NotificationRepository.search +select + "id", + "createdAt", + "level", + "type", + "title", + "description", + "data", + "readAt" +from + "notifications" +where + "userId" = $1 + and "deletedAt" is null +order by + "createdAt" desc + +-- NotificationRepository.search (unread) +select + "id", + "createdAt", + "level", + "type", + "title", + "description", + "data", + "readAt" +from + "notifications" +where + ( + "userId" = $1 + and "readAt" is null + ) + and "deletedAt" is null +order by + "createdAt" desc diff --git a/server/src/queries/partner.repository.sql b/server/src/queries/partner.repository.sql index e115dc34b9..e7170f367e 100644 --- a/server/src/queries/partner.repository.sql +++ b/server/src/queries/partner.repository.sql @@ -12,6 +12,7 @@ select "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt" from @@ -29,6 +30,7 @@ select "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt" from @@ -61,6 +63,7 @@ select "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt" from @@ -78,6 +81,7 @@ select "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt" from @@ -112,6 +116,7 @@ returning "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt" from @@ -129,6 +134,7 @@ returning "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt" from @@ -156,6 +162,7 @@ returning "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt" from @@ -173,6 +180,7 @@ returning "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt" from diff --git a/server/src/queries/user.repository.sql b/server/src/queries/user.repository.sql index 1212d0f2bd..e8ab5018fc 100644 --- a/server/src/queries/user.repository.sql +++ b/server/src/queries/user.repository.sql @@ -5,6 +5,7 @@ select "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt", "createdAt", @@ -43,6 +44,7 @@ select "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt", "createdAt", @@ -90,6 +92,7 @@ select "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt", "createdAt", @@ -128,6 +131,7 @@ select "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt", "createdAt", @@ -152,6 +156,7 @@ select "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt", "createdAt", @@ -198,6 +203,7 @@ select "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt", "createdAt", @@ -235,6 +241,7 @@ select "id", "name", "email", + "avatarColor", "profileImagePath", "profileChangedAt", "createdAt", diff --git a/server/src/repositories/access.repository.ts b/server/src/repositories/access.repository.ts index 961cccbf3e..c24209e482 100644 --- a/server/src/repositories/access.repository.ts +++ b/server/src/repositories/access.repository.ts @@ -279,6 +279,26 @@ class AuthDeviceAccess { } } +class NotificationAccess { + constructor(private db: Kysely) {} + + @GenerateSql({ params: [DummyValue.UUID, DummyValue.UUID_SET] }) + @ChunkedSet({ paramIndex: 1 }) + async checkOwnerAccess(userId: string, notificationIds: Set) { + if (notificationIds.size === 0) { + return new Set(); + } + + return this.db + .selectFrom('notifications') + .select('notifications.id') + .where('notifications.id', 'in', [...notificationIds]) + .where('notifications.userId', '=', userId) + .execute() + .then((stacks) => new Set(stacks.map((stack) => stack.id))); + } +} + class StackAccess { constructor(private db: Kysely) {} @@ -426,6 +446,7 @@ export class AccessRepository { asset: AssetAccess; authDevice: AuthDeviceAccess; memory: MemoryAccess; + notification: NotificationAccess; person: PersonAccess; partner: PartnerAccess; stack: StackAccess; @@ -438,6 +459,7 @@ export class AccessRepository { this.asset = new AssetAccess(db); this.authDevice = new AuthDeviceAccess(db); this.memory = new MemoryAccess(db); + this.notification = new NotificationAccess(db); this.person = new PersonAccess(db); this.partner = new PartnerAccess(db); this.stack = new StackAccess(db); diff --git a/server/src/repositories/asset-job.repository.ts b/server/src/repositories/asset-job.repository.ts index 4a2d52566f..1506f2997f 100644 --- a/server/src/repositories/asset-job.repository.ts +++ b/server/src/repositories/asset-job.repository.ts @@ -2,12 +2,21 @@ import { Injectable } from '@nestjs/common'; import { Kysely } from 'kysely'; import { jsonArrayFrom } from 'kysely/helpers/postgres'; import { InjectKysely } from 'nestjs-kysely'; -import { columns } from 'src/database'; +import { Asset, columns } from 'src/database'; import { DB } from 'src/db'; import { DummyValue, GenerateSql } from 'src/decorators'; -import { AssetFileType } from 'src/enum'; +import { AssetFileType, AssetType } from 'src/enum'; import { StorageAsset } from 'src/types'; -import { anyUuid, asUuid, withExifInner, withFaces, withFiles } from 'src/utils/database'; +import { + anyUuid, + asUuid, + toJson, + withExif, + withExifInner, + withFaces, + withFacesAndPeople, + withFiles, +} from 'src/utils/database'; @Injectable() export class AssetJobRepository { @@ -126,6 +135,36 @@ export class AssetJobRepository { .execute(); } + private assetsWithPreviews() { + return this.db + .selectFrom('assets') + .where('assets.isVisible', '=', true) + .where('assets.deletedAt', 'is', null) + .innerJoin('asset_job_status as job_status', 'assetId', 'assets.id') + .where('job_status.previewAt', 'is not', null); + } + + @GenerateSql({ params: [], stream: true }) + streamForSearchDuplicates(force?: boolean) { + return this.assetsWithPreviews() + .where((eb) => eb.not((eb) => eb.exists(eb.selectFrom('smart_search').whereRef('assetId', '=', 'assets.id')))) + .$if(!force, (qb) => qb.where('job_status.duplicatesDetectedAt', 'is', null)) + .select(['assets.id']) + .stream(); + } + + @GenerateSql({ params: [], stream: true }) + streamForEncodeClip(force?: boolean) { + return this.assetsWithPreviews() + .select(['assets.id']) + .$if(!force, (qb) => + qb.where((eb) => + eb.not((eb) => eb.exists(eb.selectFrom('smart_search').whereRef('assetId', '=', 'assets.id'))), + ), + ) + .stream(); + } + @GenerateSql({ params: [DummyValue.UUID] }) getForClipEncoding(id: string) { return this.db @@ -148,6 +187,7 @@ export class AssetJobRepository { .executeTakeFirst(); } + @GenerateSql({ params: [[DummyValue.UUID]] }) getForSyncAssets(ids: string[]) { return this.db .selectFrom('assets') @@ -163,6 +203,84 @@ export class AssetJobRepository { .execute(); } + @GenerateSql({ params: [DummyValue.UUID] }) + getForAssetDeletion(id: string) { + return this.db + .selectFrom('assets') + .select([ + 'assets.id', + 'assets.isVisible', + 'assets.libraryId', + 'assets.ownerId', + 'assets.livePhotoVideoId', + 'assets.sidecarPath', + 'assets.encodedVideoPath', + 'assets.originalPath', + ]) + .$call(withExif) + .select(withFacesAndPeople) + .select(withFiles) + .leftJoin('asset_stack', 'asset_stack.id', 'assets.stackId') + .leftJoinLateral( + (eb) => + eb + .selectFrom('assets as stacked') + .select(['asset_stack.id', 'asset_stack.primaryAssetId']) + .select((eb) => eb.fn('array_agg', [eb.table('stacked')]).as('assets')) + .where('stacked.deletedAt', 'is not', null) + .where('stacked.isArchived', '=', false) + .whereRef('stacked.stackId', '=', 'asset_stack.id') + .groupBy('asset_stack.id') + .as('stacked_assets'), + (join) => join.on('asset_stack.id', 'is not', null), + ) + .select((eb) => toJson(eb, 'stacked_assets').as('stack')) + .where('assets.id', '=', id) + .executeTakeFirst(); + } + + @GenerateSql({ params: [], stream: true }) + streamForVideoConversion(force?: boolean) { + return this.db + .selectFrom('assets') + .select(['assets.id']) + .where('assets.type', '=', AssetType.VIDEO) + .$if(!force, (qb) => + qb + .where((eb) => eb.or([eb('assets.encodedVideoPath', 'is', null), eb('assets.encodedVideoPath', '=', '')])) + .where('assets.isVisible', '=', true), + ) + .where('assets.deletedAt', 'is', null) + .stream(); + } + + @GenerateSql({ params: [DummyValue.UUID] }) + getForVideoConversion(id: string) { + return this.db + .selectFrom('assets') + .select(['assets.id', 'assets.ownerId', 'assets.originalPath', 'assets.encodedVideoPath']) + .where('assets.id', '=', id) + .where('assets.type', '=', AssetType.VIDEO) + .executeTakeFirst(); + } + + @GenerateSql({ params: [], stream: true }) + streamForMetadataExtraction(force?: boolean) { + return this.db + .selectFrom('assets') + .select(['assets.id']) + .$if(!force, (qb) => + qb + .leftJoin('asset_job_status', 'asset_job_status.assetId', 'assets.id') + .where((eb) => + eb.or([eb('asset_job_status.metadataExtractedAt', 'is', null), eb('asset_job_status.assetId', 'is', null)]), + ) + .where('assets.isVisible', '=', true), + ) + .where('assets.deletedAt', 'is', null) + .stream(); + } + private storageTemplateAssetQuery() { return this.db .selectFrom('assets') @@ -204,4 +322,30 @@ export class AssetJobRepository { .where('assets.deletedAt', '<=', trashedBefore) .stream(); } + + @GenerateSql({ params: [], stream: true }) + streamForSidecar(force?: boolean) { + return this.db + .selectFrom('assets') + .select(['assets.id']) + .$if(!force, (qb) => + qb.where((eb) => eb.or([eb('assets.sidecarPath', '=', ''), eb('assets.sidecarPath', 'is', null)])), + ) + .where('assets.isVisible', '=', true) + .stream(); + } + + @GenerateSql({ params: [], stream: true }) + streamForDetectFacesJob(force?: boolean) { + return this.assetsWithPreviews() + .$if(!force, (qb) => qb.where('job_status.facesRecognizedAt', 'is', null)) + .select(['assets.id']) + .orderBy('assets.createdAt', 'desc') + .stream(); + } + + @GenerateSql({ params: [DummyValue.DATE], stream: true }) + streamForMigrationJob() { + return this.db.selectFrom('assets').select(['id']).where('assets.deletedAt', 'is', null).stream(); + } } diff --git a/server/src/repositories/asset.repository.ts b/server/src/repositories/asset.repository.ts index 7a68ba907f..d1c08b90bc 100644 --- a/server/src/repositories/asset.repository.ts +++ b/server/src/repositories/asset.repository.ts @@ -7,13 +7,12 @@ import { AssetFiles, AssetJobStatus, Assets, DB, Exif } from 'src/db'; import { Chunked, ChunkedArray, DummyValue, GenerateSql } from 'src/decorators'; import { MapAsset } from 'src/dtos/asset-response.dto'; import { AssetFileType, AssetOrder, AssetStatus, AssetType } from 'src/enum'; -import { AssetSearchOptions, SearchExploreItem, SearchExploreItemSet } from 'src/repositories/search.repository'; +import { SearchExploreItem, SearchExploreItemSet } from 'src/repositories/search.repository'; import { anyUuid, asUuid, hasPeople, removeUndefinedKeys, - searchAssetBuilder, truncatedDate, unnest, withExif, @@ -27,7 +26,6 @@ import { withTags, } from 'src/utils/database'; import { globToSqlPattern } from 'src/utils/misc'; -import { PaginationOptions, paginationHelper } from 'src/utils/pagination'; export type AssetStats = Record; @@ -45,16 +43,6 @@ export interface LivePhotoSearchOptions { type: AssetType; } -export enum WithoutProperty { - THUMBNAIL = 'thumbnail', - ENCODED_VIDEO = 'encoded-video', - EXIF = 'exif', - SMART_SEARCH = 'smart-search', - DUPLICATE = 'duplicate', - FACES = 'faces', - SIDECAR = 'sidecar', -} - export enum WithProperty { SIDECAR = 'sidecar', } @@ -336,10 +324,6 @@ export class AssetRepository { return assets.map((asset) => asset.deviceAssetId); } - getByUserId(pagination: PaginationOptions, userId: string, options: Omit = {}) { - return this.getAll(pagination, { ...options, userIds: [userId] }); - } - @GenerateSql({ params: [DummyValue.UUID, DummyValue.STRING] }) getByLibraryIdAndOriginalPath(libraryId: string, originalPath: string) { return this.db @@ -351,16 +335,6 @@ export class AssetRepository { .executeTakeFirst(); } - async getAll(pagination: PaginationOptions, { orderDirection, ...options }: AssetSearchOptions = {}) { - const builder = searchAssetBuilder(this.db, options) - .select(withFiles) - .orderBy('assets.createdAt', orderDirection ?? 'asc') - .limit(pagination.take + 1) - .offset(pagination.skip ?? 0); - const items = await builder.execute(); - return paginationHelper(items, pagination.take); - } - /** * Get assets by device's Id on the database * @param ownerId @@ -530,77 +504,6 @@ export class AssetRepository { .executeTakeFirst(); } - @GenerateSql( - ...Object.values(WithProperty).map((property) => ({ - name: property, - params: [DummyValue.PAGINATION, property], - })), - ) - async getWithout(pagination: PaginationOptions, property: WithoutProperty) { - const items = await this.db - .selectFrom('assets') - .selectAll('assets') - .$if(property === WithoutProperty.DUPLICATE, (qb) => - qb - .innerJoin('asset_job_status as job_status', 'assets.id', 'job_status.assetId') - .where('job_status.duplicatesDetectedAt', 'is', null) - .where('job_status.previewAt', 'is not', null) - .where((eb) => eb.exists(eb.selectFrom('smart_search').where('assetId', '=', eb.ref('assets.id')))) - .where('assets.isVisible', '=', true), - ) - .$if(property === WithoutProperty.ENCODED_VIDEO, (qb) => - qb - .where('assets.type', '=', AssetType.VIDEO) - .where((eb) => eb.or([eb('assets.encodedVideoPath', 'is', null), eb('assets.encodedVideoPath', '=', '')])), - ) - .$if(property === WithoutProperty.EXIF, (qb) => - qb - .leftJoin('asset_job_status as job_status', 'assets.id', 'job_status.assetId') - .where((eb) => eb.or([eb('job_status.metadataExtractedAt', 'is', null), eb('assetId', 'is', null)])) - .where('assets.isVisible', '=', true), - ) - .$if(property === WithoutProperty.FACES, (qb) => - qb - .innerJoin('asset_job_status as job_status', 'assetId', 'assets.id') - .where('job_status.previewAt', 'is not', null) - .where('job_status.facesRecognizedAt', 'is', null) - .where('assets.isVisible', '=', true), - ) - .$if(property === WithoutProperty.SIDECAR, (qb) => - qb - .where((eb) => eb.or([eb('assets.sidecarPath', '=', ''), eb('assets.sidecarPath', 'is', null)])) - .where('assets.isVisible', '=', true), - ) - .$if(property === WithoutProperty.SMART_SEARCH, (qb) => - qb - .innerJoin('asset_job_status as job_status', 'assetId', 'assets.id') - .where('job_status.previewAt', 'is not', null) - .where('assets.isVisible', '=', true) - .where((eb) => - eb.not((eb) => eb.exists(eb.selectFrom('smart_search').whereRef('assetId', '=', 'assets.id'))), - ), - ) - .$if(property === WithoutProperty.THUMBNAIL, (qb) => - qb - .innerJoin('asset_job_status as job_status', 'assetId', 'assets.id') - .where('assets.isVisible', '=', true) - .where((eb) => - eb.or([ - eb('job_status.previewAt', 'is', null), - eb('job_status.thumbnailAt', 'is', null), - eb('assets.thumbhash', 'is', null), - ]), - ), - ) - .where('deletedAt', 'is', null) - .limit(pagination.take + 1) - .offset(pagination.skip ?? 0) - .orderBy('createdAt') - .execute(); - - return paginationHelper(items, pagination.take); - } - getStatistics(ownerId: string, { isArchived, isFavorite, isTrashed }: AssetStatsOptions): Promise { return this.db .selectFrom('assets') diff --git a/server/src/repositories/config.repository.spec.ts b/server/src/repositories/config.repository.spec.ts index 888d5c33ec..9e9ed71191 100644 --- a/server/src/repositories/config.repository.spec.ts +++ b/server/src/repositories/config.repository.spec.ts @@ -80,21 +80,12 @@ describe('getEnv', () => { const { database } = getEnv(); expect(database).toEqual({ config: { - kysely: expect.objectContaining({ - host: 'database', - port: 5432, - database: 'immich', - username: 'postgres', - password: 'postgres', - }), - typeorm: expect.objectContaining({ - type: 'postgres', - host: 'database', - port: 5432, - database: 'immich', - username: 'postgres', - password: 'postgres', - }), + connectionType: 'parts', + host: 'database', + port: 5432, + database: 'immich', + username: 'postgres', + password: 'postgres', }, skipMigrations: false, vectorExtension: 'vectors', @@ -110,88 +101,9 @@ describe('getEnv', () => { it('should use DB_URL', () => { process.env.DB_URL = 'postgres://postgres1:postgres2@database1:54320/immich'; const { database } = getEnv(); - expect(database.config.kysely).toMatchObject({ - host: 'database1', - password: 'postgres2', - user: 'postgres1', - port: 54_320, - database: 'immich', - }); - }); - - it('should handle sslmode=require', () => { - process.env.DB_URL = 'postgres://postgres1:postgres2@database1:54320/immich?sslmode=require'; - - const { database } = getEnv(); - - expect(database.config.kysely).toMatchObject({ ssl: {} }); - }); - - it('should handle sslmode=prefer', () => { - process.env.DB_URL = 'postgres://postgres1:postgres2@database1:54320/immich?sslmode=prefer'; - - const { database } = getEnv(); - - expect(database.config.kysely).toMatchObject({ ssl: {} }); - }); - - it('should handle sslmode=verify-ca', () => { - process.env.DB_URL = 'postgres://postgres1:postgres2@database1:54320/immich?sslmode=verify-ca'; - - const { database } = getEnv(); - - expect(database.config.kysely).toMatchObject({ ssl: {} }); - }); - - it('should handle sslmode=verify-full', () => { - process.env.DB_URL = 'postgres://postgres1:postgres2@database1:54320/immich?sslmode=verify-full'; - - const { database } = getEnv(); - - expect(database.config.kysely).toMatchObject({ ssl: {} }); - }); - - it('should handle sslmode=no-verify', () => { - process.env.DB_URL = 'postgres://postgres1:postgres2@database1:54320/immich?sslmode=no-verify'; - - const { database } = getEnv(); - - expect(database.config.kysely).toMatchObject({ ssl: { rejectUnauthorized: false } }); - }); - - it('should handle ssl=true', () => { - process.env.DB_URL = 'postgres://postgres1:postgres2@database1:54320/immich?ssl=true'; - - const { database } = getEnv(); - - expect(database.config.kysely).toMatchObject({ ssl: true }); - }); - - it('should reject invalid ssl', () => { - process.env.DB_URL = 'postgres://postgres1:postgres2@database1:54320/immich?ssl=invalid'; - - expect(() => getEnv()).toThrowError('Invalid ssl option: invalid'); - }); - - it('should handle socket: URLs', () => { - process.env.DB_URL = 'socket:/run/postgresql?db=database1'; - - const { database } = getEnv(); - - expect(database.config.kysely).toMatchObject({ - host: '/run/postgresql', - database: 'database1', - }); - }); - - it('should handle sockets in postgres: URLs', () => { - process.env.DB_URL = 'postgres:///database2?host=/path/to/socket'; - - const { database } = getEnv(); - - expect(database.config.kysely).toMatchObject({ - host: '/path/to/socket', - database: 'database2', + expect(database.config).toMatchObject({ + connectionType: 'url', + url: 'postgres://postgres1:postgres2@database1:54320/immich', }); }); }); diff --git a/server/src/repositories/config.repository.ts b/server/src/repositories/config.repository.ts index f689641d4f..9b88a78e6b 100644 --- a/server/src/repositories/config.repository.ts +++ b/server/src/repositories/config.repository.ts @@ -7,8 +7,7 @@ import { Request, Response } from 'express'; import { RedisOptions } from 'ioredis'; import { CLS_ID, ClsModuleOptions } from 'nestjs-cls'; import { OpenTelemetryModuleOptions } from 'nestjs-otel/lib/interfaces'; -import { join, resolve } from 'node:path'; -import { parse } from 'pg-connection-string'; +import { join } from 'node:path'; import { citiesFile, excludePaths, IWorker } from 'src/constants'; import { Telemetry } from 'src/decorators'; import { EnvDto } from 'src/dtos/env.dto'; @@ -22,9 +21,7 @@ import { QueueName, } from 'src/enum'; import { DatabaseConnectionParams, VectorExtension } from 'src/types'; -import { isValidSsl, PostgresConnectionConfig } from 'src/utils/database'; import { setDifference } from 'src/utils/set'; -import { PostgresConnectionOptions } from 'typeorm/driver/postgres/PostgresConnectionOptions.js'; export interface EnvData { host?: string; @@ -59,7 +56,7 @@ export interface EnvData { }; database: { - config: { typeorm: PostgresConnectionOptions & DatabaseConnectionParams; kysely: PostgresConnectionConfig }; + config: DatabaseConnectionParams; skipMigrations: boolean; vectorExtension: VectorExtension; }; @@ -152,14 +149,10 @@ const getEnv = (): EnvData => { const isProd = environment === ImmichEnvironment.PRODUCTION; const buildFolder = dto.IMMICH_BUILD_DATA || '/build'; const folders = { - // eslint-disable-next-line unicorn/prefer-module - dist: resolve(`${__dirname}/..`), geodata: join(buildFolder, 'geodata'), web: join(buildFolder, 'www'), }; - const databaseUrl = dto.DB_URL; - let redisConfig = { host: dto.REDIS_HOSTNAME || 'redis', port: dto.REDIS_PORT || 6379, @@ -191,30 +184,16 @@ const getEnv = (): EnvData => { } } - const parts = { - connectionType: 'parts', - host: dto.DB_HOSTNAME || 'database', - port: dto.DB_PORT || 5432, - username: dto.DB_USERNAME || 'postgres', - password: dto.DB_PASSWORD || 'postgres', - database: dto.DB_DATABASE_NAME || 'immich', - } as const; - - let parsedOptions: PostgresConnectionConfig = parts; - if (dto.DB_URL) { - const parsed = parse(dto.DB_URL); - if (!isValidSsl(parsed.ssl)) { - throw new Error(`Invalid ssl option: ${parsed.ssl}`); - } - - parsedOptions = { - ...parsed, - ssl: parsed.ssl, - host: parsed.host ?? undefined, - port: parsed.port ? Number(parsed.port) : undefined, - database: parsed.database ?? undefined, - }; - } + const databaseConnection: DatabaseConnectionParams = dto.DB_URL + ? { connectionType: 'url', url: dto.DB_URL } + : { + connectionType: 'parts', + host: dto.DB_HOSTNAME || 'database', + port: dto.DB_PORT || 5432, + username: dto.DB_USERNAME || 'postgres', + password: dto.DB_PASSWORD || 'postgres', + database: dto.DB_DATABASE_NAME || 'immich', + }; return { host: dto.IMMICH_HOST, @@ -269,21 +248,7 @@ const getEnv = (): EnvData => { }, database: { - config: { - typeorm: { - type: 'postgres', - entities: [], - migrations: [`${folders.dist}/migrations` + '/*.{js,ts}'], - subscribers: [], - migrationsRun: false, - synchronize: false, - connectTimeoutMS: 10_000, // 10 seconds - parseInt8: true, - ...(databaseUrl ? { connectionType: 'url', url: databaseUrl } : parts), - }, - kysely: parsedOptions, - }, - + config: databaseConnection, skipMigrations: dto.DB_SKIP_MIGRATIONS ?? false, vectorExtension: dto.DB_VECTOR_EXTENSION === 'pgvector' ? DatabaseExtension.VECTOR : DatabaseExtension.VECTORS, }, diff --git a/server/src/repositories/database.repository.ts b/server/src/repositories/database.repository.ts index c70c2cbdd4..addf6bcff0 100644 --- a/server/src/repositories/database.repository.ts +++ b/server/src/repositories/database.repository.ts @@ -3,7 +3,7 @@ import AsyncLock from 'async-lock'; import { FileMigrationProvider, Kysely, Migrator, sql, Transaction } from 'kysely'; import { InjectKysely } from 'nestjs-kysely'; import { readdir } from 'node:fs/promises'; -import { join } from 'node:path'; +import { join, resolve } from 'node:path'; import semver from 'semver'; import { EXTENSION_NAMES, POSTGRES_VERSION_RANGE, VECTOR_VERSION_RANGE, VECTORS_VERSION_RANGE } from 'src/constants'; import { DB } from 'src/db'; @@ -12,6 +12,7 @@ import { DatabaseExtension, DatabaseLock, VectorIndex } from 'src/enum'; import { ConfigRepository } from 'src/repositories/config.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; import { ExtensionVersion, VectorExtension, VectorUpdateResult } from 'src/types'; +import { vectorIndexQuery } from 'src/utils/database'; import { isValidInteger } from 'src/validation'; import { DataSource } from 'typeorm'; @@ -119,12 +120,7 @@ export class DatabaseRepository { await sql`ALTER TABLE ${sql.raw(table)} ALTER COLUMN embedding SET DATA TYPE vector(${sql.raw(String(dimSize))})`.execute( tx, ); - await sql`SET vectors.pgvector_compatibility=on`.execute(tx); - await sql` - CREATE INDEX IF NOT EXISTS ${sql.raw(index)} ON ${sql.raw(table)} - USING hnsw (embedding vector_cosine_ops) - WITH (ef_construction = 300, m = 16) - `.execute(tx); + await sql.raw(vectorIndexQuery({ vectorExtension: this.vectorExtension, table, indexName: index })).execute(tx); }); } } @@ -205,8 +201,29 @@ export class DatabaseRepository { const { rows } = await tableExists.execute(this.db); const hasTypeOrmMigrations = !!rows[0]?.result; if (hasTypeOrmMigrations) { + // eslint-disable-next-line unicorn/prefer-module + const dist = resolve(`${__dirname}/..`); + this.logger.debug('Running typeorm migrations'); - const dataSource = new DataSource(database.config.typeorm); + const dataSource = new DataSource({ + type: 'postgres', + entities: [], + subscribers: [], + migrations: [`${dist}/migrations` + '/*.{js,ts}'], + migrationsRun: false, + synchronize: false, + connectTimeoutMS: 10_000, // 10 seconds + parseInt8: true, + ...(database.config.connectionType === 'url' + ? { url: database.config.url } + : { + host: database.config.host, + port: database.config.port, + username: database.config.username, + password: database.config.password, + database: database.config.database, + }), + }); await dataSource.initialize(); await dataSource.runMigrations(options); await dataSource.destroy(); diff --git a/server/src/repositories/notification.repository.spec.ts b/server/src/repositories/email.repository.spec.ts similarity index 87% rename from server/src/repositories/notification.repository.spec.ts rename to server/src/repositories/email.repository.spec.ts index 1d0770af6b..5640b26bf6 100644 --- a/server/src/repositories/notification.repository.spec.ts +++ b/server/src/repositories/email.repository.spec.ts @@ -1,13 +1,13 @@ +import { EmailRenderRequest, EmailRepository, EmailTemplate } from 'src/repositories/email.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; -import { EmailRenderRequest, EmailTemplate, NotificationRepository } from 'src/repositories/notification.repository'; import { automock } from 'test/utils'; -describe(NotificationRepository.name, () => { - let sut: NotificationRepository; +describe(EmailRepository.name, () => { + let sut: EmailRepository; beforeEach(() => { // eslint-disable-next-line no-sparse-arrays - sut = new NotificationRepository(automock(LoggingRepository, { args: [, { getEnv: () => ({}) }], strict: false })); + sut = new EmailRepository(automock(LoggingRepository, { args: [, { getEnv: () => ({}) }], strict: false })); }); describe('renderEmail', () => { diff --git a/server/src/repositories/email.repository.ts b/server/src/repositories/email.repository.ts new file mode 100644 index 0000000000..78c89b4a9d --- /dev/null +++ b/server/src/repositories/email.repository.ts @@ -0,0 +1,174 @@ +import { Injectable } from '@nestjs/common'; +import { render } from '@react-email/render'; +import { createTransport } from 'nodemailer'; +import React from 'react'; +import { AlbumInviteEmail } from 'src/emails/album-invite.email'; +import { AlbumUpdateEmail } from 'src/emails/album-update.email'; +import { TestEmail } from 'src/emails/test.email'; +import { WelcomeEmail } from 'src/emails/welcome.email'; +import { LoggingRepository } from 'src/repositories/logging.repository'; +import { EmailImageAttachment } from 'src/types'; + +export type SendEmailOptions = { + from: string; + to: string; + replyTo?: string; + subject: string; + html: string; + text: string; + imageAttachments?: EmailImageAttachment[]; + smtp: SmtpOptions; +}; + +export type SmtpOptions = { + host: string; + port?: number; + username?: string; + password?: string; + ignoreCert?: boolean; +}; + +export enum EmailTemplate { + TEST_EMAIL = 'test', + + // AUTH + WELCOME = 'welcome', + RESET_PASSWORD = 'reset-password', + + // ALBUM + ALBUM_INVITE = 'album-invite', + ALBUM_UPDATE = 'album-update', +} + +interface BaseEmailProps { + baseUrl: string; + customTemplate?: string; +} + +export interface TestEmailProps extends BaseEmailProps { + displayName: string; +} + +export interface WelcomeEmailProps extends BaseEmailProps { + displayName: string; + username: string; + password?: string; +} + +export interface AlbumInviteEmailProps extends BaseEmailProps { + albumName: string; + albumId: string; + senderName: string; + recipientName: string; + cid?: string; +} + +export interface AlbumUpdateEmailProps extends BaseEmailProps { + albumName: string; + albumId: string; + recipientName: string; + cid?: string; +} + +export type EmailRenderRequest = + | { + template: EmailTemplate.TEST_EMAIL; + data: TestEmailProps; + customTemplate: string; + } + | { + template: EmailTemplate.WELCOME; + data: WelcomeEmailProps; + customTemplate: string; + } + | { + template: EmailTemplate.ALBUM_INVITE; + data: AlbumInviteEmailProps; + customTemplate: string; + } + | { + template: EmailTemplate.ALBUM_UPDATE; + data: AlbumUpdateEmailProps; + customTemplate: string; + }; + +export type SendEmailResponse = { + messageId: string; + response: any; +}; + +@Injectable() +export class EmailRepository { + constructor(private logger: LoggingRepository) { + this.logger.setContext(EmailRepository.name); + } + + verifySmtp(options: SmtpOptions): Promise { + const transport = this.createTransport(options); + try { + return transport.verify(); + } finally { + transport.close(); + } + } + + async renderEmail(request: EmailRenderRequest): Promise<{ html: string; text: string }> { + const component = this.render(request); + const html = await render(component, { pretty: false }); + const text = await render(component, { plainText: true }); + return { html, text }; + } + + sendEmail({ to, from, subject, html, text, smtp, imageAttachments }: SendEmailOptions): Promise { + this.logger.debug(`Sending email to ${to} with subject: ${subject}`); + const transport = this.createTransport(smtp); + + const attachments = imageAttachments?.map((attachment) => ({ + filename: attachment.filename, + path: attachment.path, + cid: attachment.cid, + })); + + try { + return transport.sendMail({ to, from, subject, html, text, attachments }); + } finally { + transport.close(); + } + } + + private render({ template, data, customTemplate }: EmailRenderRequest): React.FunctionComponentElement { + switch (template) { + case EmailTemplate.TEST_EMAIL: { + return React.createElement(TestEmail, { ...data, customTemplate }); + } + + case EmailTemplate.WELCOME: { + return React.createElement(WelcomeEmail, { ...data, customTemplate }); + } + + case EmailTemplate.ALBUM_INVITE: { + return React.createElement(AlbumInviteEmail, { ...data, customTemplate }); + } + + case EmailTemplate.ALBUM_UPDATE: { + return React.createElement(AlbumUpdateEmail, { ...data, customTemplate }); + } + } + } + + private createTransport(options: SmtpOptions) { + return createTransport({ + host: options.host, + port: options.port, + tls: { rejectUnauthorized: !options.ignoreCert }, + auth: + options.username || options.password + ? { + user: options.username, + pass: options.password, + } + : undefined, + connectionTimeout: 5000, + }); + } +} diff --git a/server/src/repositories/event.repository.ts b/server/src/repositories/event.repository.ts index 3156804d09..b41c007ef5 100644 --- a/server/src/repositories/event.repository.ts +++ b/server/src/repositories/event.repository.ts @@ -14,6 +14,7 @@ import { SystemConfig } from 'src/config'; import { EventConfig } from 'src/decorators'; import { AssetResponseDto } from 'src/dtos/asset-response.dto'; import { AuthDto } from 'src/dtos/auth.dto'; +import { NotificationDto } from 'src/dtos/notification.dto'; import { ReleaseNotification, ServerVersionResponseDto } from 'src/dtos/server.dto'; import { ImmichWorker, MetadataKey, QueueName } from 'src/enum'; import { ConfigRepository } from 'src/repositories/config.repository'; @@ -64,6 +65,7 @@ type EventMap = { 'assets.restore': [{ assetIds: string[]; userId: string }]; 'job.start': [QueueName, JobItem]; + 'job.failed': [{ job: JobItem; error: Error | any }]; // session events 'session.delete': [{ sessionId: string }]; @@ -104,6 +106,7 @@ export interface ClientEventMap { on_server_version: [ServerVersionResponseDto]; on_config_update: []; on_new_release: [ReleaseNotification]; + on_notification: [NotificationDto]; on_session_delete: [string]; } diff --git a/server/src/repositories/index.ts b/server/src/repositories/index.ts index ef36a2b3f8..453e515fe0 100644 --- a/server/src/repositories/index.ts +++ b/server/src/repositories/index.ts @@ -11,6 +11,7 @@ import { CronRepository } from 'src/repositories/cron.repository'; import { CryptoRepository } from 'src/repositories/crypto.repository'; import { DatabaseRepository } from 'src/repositories/database.repository'; import { DownloadRepository } from 'src/repositories/download.repository'; +import { EmailRepository } from 'src/repositories/email.repository'; import { EventRepository } from 'src/repositories/event.repository'; import { JobRepository } from 'src/repositories/job.repository'; import { LibraryRepository } from 'src/repositories/library.repository'; @@ -55,6 +56,7 @@ export const repositories = [ CryptoRepository, DatabaseRepository, DownloadRepository, + EmailRepository, EventRepository, JobRepository, LibraryRepository, diff --git a/server/src/repositories/job.repository.ts b/server/src/repositories/job.repository.ts index fd9f4c5363..0912759d1c 100644 --- a/server/src/repositories/job.repository.ts +++ b/server/src/repositories/job.repository.ts @@ -33,7 +33,7 @@ export class JobRepository { this.logger.setContext(JobRepository.name); } - setup({ services }: { services: ClassConstructor[] }) { + setup(services: ClassConstructor[]) { const reflector = this.moduleRef.get(Reflector, { strict: false }); // discovery diff --git a/server/src/repositories/logging.repository.ts b/server/src/repositories/logging.repository.ts index 05d2d45f4d..2ac3715a50 100644 --- a/server/src/repositories/logging.repository.ts +++ b/server/src/repositories/logging.repository.ts @@ -5,7 +5,7 @@ import { Telemetry } from 'src/decorators'; import { LogLevel } from 'src/enum'; import { ConfigRepository } from 'src/repositories/config.repository'; -type LogDetails = any[]; +type LogDetails = any; type LogFunction = () => string; const LOG_LEVELS = [LogLevel.VERBOSE, LogLevel.DEBUG, LogLevel.LOG, LogLevel.WARN, LogLevel.ERROR, LogLevel.FATAL]; diff --git a/server/src/repositories/media.repository.ts b/server/src/repositories/media.repository.ts index 1e41dd6bb2..d0ced19a6e 100644 --- a/server/src/repositories/media.repository.ts +++ b/server/src/repositories/media.repository.ts @@ -7,7 +7,7 @@ import { Writable } from 'node:stream'; import sharp from 'sharp'; import { ORIENTATION_TO_SHARP_ROTATION } from 'src/constants'; import { Exif } from 'src/database'; -import { Colorspace, LogLevel } from 'src/enum'; +import { Colorspace, LogLevel, RawExtractedFormat } from 'src/enum'; import { LoggingRepository } from 'src/repositories/logging.repository'; import { DecodeToBufferOptions, @@ -36,34 +36,51 @@ type ProgressEvent = { percent?: number; }; +export type ExtractResult = { + buffer: Buffer; + format: RawExtractedFormat; +}; + @Injectable() export class MediaRepository { constructor(private logger: LoggingRepository) { this.logger.setContext(MediaRepository.name); } - async extract(input: string, output: string): Promise { + /** + * + * @param input file path to the input image + * @returns ExtractResult if succeeded, or null if failed + */ + async extract(input: string): Promise { try { - // remove existing output file if it exists - // as exiftool-vendored does not support overwriting via "-w!" flag - // and throws "1 files could not be read" error when the output file exists - await fs.unlink(output).catch(() => null); - await exiftool.extractBinaryTag('JpgFromRaw2', input, output); - } catch { - try { - this.logger.debug('Extracting JPEG from RAW image:', input); - await exiftool.extractJpgFromRaw(input, output); - } catch (error: any) { - this.logger.debug('Could not extract JPEG from image, trying preview', error.message); - try { - await exiftool.extractPreview(input, output); - } catch (error: any) { - this.logger.debug('Could not extract preview from image', error.message); - return false; - } - } + const buffer = await exiftool.extractBinaryTagToBuffer('JpgFromRaw2', input); + return { buffer, format: RawExtractedFormat.JPEG }; + } catch (error: any) { + this.logger.debug('Could not extract JpgFromRaw2 buffer from image, trying JPEG from RAW next', error.message); + } + + try { + const buffer = await exiftool.extractBinaryTagToBuffer('JpgFromRaw', input); + return { buffer, format: RawExtractedFormat.JPEG }; + } catch (error: any) { + this.logger.debug('Could not extract JPEG buffer from image, trying PreviewJXL next', error.message); + } + + try { + const buffer = await exiftool.extractBinaryTagToBuffer('PreviewJXL', input); + return { buffer, format: RawExtractedFormat.JXL }; + } catch (error: any) { + this.logger.debug('Could not extract PreviewJXL buffer from image, trying PreviewImage next', error.message); + } + + try { + const buffer = await exiftool.extractBinaryTagToBuffer('PreviewImage', input); + return { buffer, format: RawExtractedFormat.JPEG }; + } catch (error: any) { + this.logger.debug('Could not extract preview buffer from image', error.message); + return null; } - return true; } async writeExif(tags: Partial, output: string): Promise { @@ -104,7 +121,7 @@ export class MediaRepository { } } - decodeImage(input: string, options: DecodeToBufferOptions) { + decodeImage(input: string | Buffer, options: DecodeToBufferOptions) { return this.getImageDecodingPipeline(input, options).raw().toBuffer({ resolveWithObject: true }); } @@ -235,7 +252,7 @@ export class MediaRepository { }); } - async getImageDimensions(input: string): Promise { + async getImageDimensions(input: string | Buffer): Promise { const { width = 0, height = 0 } = await sharp(input).metadata(); return { width, height }; } diff --git a/server/src/repositories/notification.repository.ts b/server/src/repositories/notification.repository.ts index 91f03b928b..112bb97e60 100644 --- a/server/src/repositories/notification.repository.ts +++ b/server/src/repositories/notification.repository.ts @@ -1,174 +1,103 @@ -import { Injectable } from '@nestjs/common'; -import { render } from '@react-email/render'; -import { createTransport } from 'nodemailer'; -import React from 'react'; -import { AlbumInviteEmail } from 'src/emails/album-invite.email'; -import { AlbumUpdateEmail } from 'src/emails/album-update.email'; -import { TestEmail } from 'src/emails/test.email'; -import { WelcomeEmail } from 'src/emails/welcome.email'; -import { LoggingRepository } from 'src/repositories/logging.repository'; -import { EmailImageAttachment } from 'src/types'; +import { Insertable, Kysely, Updateable } from 'kysely'; +import { DateTime } from 'luxon'; +import { InjectKysely } from 'nestjs-kysely'; +import { columns } from 'src/database'; +import { DB, Notifications } from 'src/db'; +import { DummyValue, GenerateSql } from 'src/decorators'; +import { NotificationSearchDto } from 'src/dtos/notification.dto'; -export type SendEmailOptions = { - from: string; - to: string; - replyTo?: string; - subject: string; - html: string; - text: string; - imageAttachments?: EmailImageAttachment[]; - smtp: SmtpOptions; -}; - -export type SmtpOptions = { - host: string; - port?: number; - username?: string; - password?: string; - ignoreCert?: boolean; -}; - -export enum EmailTemplate { - TEST_EMAIL = 'test', - - // AUTH - WELCOME = 'welcome', - RESET_PASSWORD = 'reset-password', - - // ALBUM - ALBUM_INVITE = 'album-invite', - ALBUM_UPDATE = 'album-update', -} - -interface BaseEmailProps { - baseUrl: string; - customTemplate?: string; -} - -export interface TestEmailProps extends BaseEmailProps { - displayName: string; -} - -export interface WelcomeEmailProps extends BaseEmailProps { - displayName: string; - username: string; - password?: string; -} - -export interface AlbumInviteEmailProps extends BaseEmailProps { - albumName: string; - albumId: string; - senderName: string; - recipientName: string; - cid?: string; -} - -export interface AlbumUpdateEmailProps extends BaseEmailProps { - albumName: string; - albumId: string; - recipientName: string; - cid?: string; -} - -export type EmailRenderRequest = - | { - template: EmailTemplate.TEST_EMAIL; - data: TestEmailProps; - customTemplate: string; - } - | { - template: EmailTemplate.WELCOME; - data: WelcomeEmailProps; - customTemplate: string; - } - | { - template: EmailTemplate.ALBUM_INVITE; - data: AlbumInviteEmailProps; - customTemplate: string; - } - | { - template: EmailTemplate.ALBUM_UPDATE; - data: AlbumUpdateEmailProps; - customTemplate: string; - }; - -export type SendEmailResponse = { - messageId: string; - response: any; -}; - -@Injectable() export class NotificationRepository { - constructor(private logger: LoggingRepository) { - this.logger.setContext(NotificationRepository.name); + constructor(@InjectKysely() private db: Kysely) {} + + @GenerateSql({ params: [DummyValue.UUID] }) + cleanup() { + return this.db + .deleteFrom('notifications') + .where((eb) => + eb.or([ + // remove soft-deleted notifications + eb.and([eb('deletedAt', 'is not', null), eb('deletedAt', '<', DateTime.now().minus({ days: 3 }).toJSDate())]), + + // remove old, read notifications + eb.and([ + // keep recently read messages around for a few days + eb('readAt', '>', DateTime.now().minus({ days: 2 }).toJSDate()), + eb('createdAt', '<', DateTime.now().minus({ days: 15 }).toJSDate()), + ]), + + eb.and([ + // remove super old, unread notifications + eb('readAt', '=', null), + eb('createdAt', '<', DateTime.now().minus({ days: 30 }).toJSDate()), + ]), + ]), + ) + .execute(); } - verifySmtp(options: SmtpOptions): Promise { - const transport = this.createTransport(options); - try { - return transport.verify(); - } finally { - transport.close(); - } + @GenerateSql({ params: [DummyValue.UUID, {}] }, { name: 'unread', params: [DummyValue.UUID, { unread: true }] }) + search(userId: string, dto: NotificationSearchDto) { + return this.db + .selectFrom('notifications') + .select(columns.notification) + .where((qb) => + qb.and({ + userId, + id: dto.id, + level: dto.level, + type: dto.type, + readAt: dto.unread ? null : undefined, + }), + ) + .where('deletedAt', 'is', null) + .orderBy('createdAt', 'desc') + .execute(); } - async renderEmail(request: EmailRenderRequest): Promise<{ html: string; text: string }> { - const component = this.render(request); - const html = await render(component, { pretty: false }); - const text = await render(component, { plainText: true }); - return { html, text }; + create(notification: Insertable) { + return this.db + .insertInto('notifications') + .values(notification) + .returning(columns.notification) + .executeTakeFirstOrThrow(); } - sendEmail({ to, from, subject, html, text, smtp, imageAttachments }: SendEmailOptions): Promise { - this.logger.debug(`Sending email to ${to} with subject: ${subject}`); - const transport = this.createTransport(smtp); - - const attachments = imageAttachments?.map((attachment) => ({ - filename: attachment.filename, - path: attachment.path, - cid: attachment.cid, - })); - - try { - return transport.sendMail({ to, from, subject, html, text, attachments }); - } finally { - transport.close(); - } + get(id: string) { + return this.db + .selectFrom('notifications') + .select(columns.notification) + .where('id', '=', id) + .where('deletedAt', 'is not', null) + .executeTakeFirst(); } - private render({ template, data, customTemplate }: EmailRenderRequest): React.FunctionComponentElement { - switch (template) { - case EmailTemplate.TEST_EMAIL: { - return React.createElement(TestEmail, { ...data, customTemplate }); - } - - case EmailTemplate.WELCOME: { - return React.createElement(WelcomeEmail, { ...data, customTemplate }); - } - - case EmailTemplate.ALBUM_INVITE: { - return React.createElement(AlbumInviteEmail, { ...data, customTemplate }); - } - - case EmailTemplate.ALBUM_UPDATE: { - return React.createElement(AlbumUpdateEmail, { ...data, customTemplate }); - } - } + update(id: string, notification: Updateable) { + return this.db + .updateTable('notifications') + .set(notification) + .where('deletedAt', 'is', null) + .where('id', '=', id) + .returning(columns.notification) + .executeTakeFirstOrThrow(); } - private createTransport(options: SmtpOptions) { - return createTransport({ - host: options.host, - port: options.port, - tls: { rejectUnauthorized: !options.ignoreCert }, - auth: - options.username || options.password - ? { - user: options.username, - pass: options.password, - } - : undefined, - connectionTimeout: 5000, - }); + async updateAll(ids: string[], notification: Updateable) { + await this.db.updateTable('notifications').set(notification).where('id', 'in', ids).execute(); + } + + async delete(id: string) { + await this.db + .updateTable('notifications') + .set({ deletedAt: DateTime.now().toJSDate() }) + .where('id', '=', id) + .execute(); + } + + async deleteAll(ids: string[]) { + await this.db + .updateTable('notifications') + .set({ deletedAt: DateTime.now().toJSDate() }) + .where('id', 'in', ids) + .execute(); } } diff --git a/server/src/repositories/oauth.repository.ts b/server/src/repositories/oauth.repository.ts index dc19a1fe01..ea9f0b1901 100644 --- a/server/src/repositories/oauth.repository.ts +++ b/server/src/repositories/oauth.repository.ts @@ -1,18 +1,21 @@ import { Injectable, InternalServerErrorException } from '@nestjs/common'; -import { custom, generators, Issuer, UserinfoResponse } from 'openid-client'; +import type { UserInfoResponse } from 'openid-client' with { 'resolution-mode': 'import' }; +import { OAuthTokenEndpointAuthMethod } from 'src/enum'; import { LoggingRepository } from 'src/repositories/logging.repository'; export type OAuthConfig = { clientId: string; - clientSecret: string; + clientSecret?: string; issuerUrl: string; mobileOverrideEnabled: boolean; mobileRedirectUri: string; profileSigningAlgorithm: string; scope: string; signingAlgorithm: string; + tokenEndpointAuthMethod: OAuthTokenEndpointAuthMethod; + timeout: number; }; -export type OAuthProfile = UserinfoResponse; +export type OAuthProfile = UserInfoResponse; @Injectable() export class OAuthRepository { @@ -20,30 +23,47 @@ export class OAuthRepository { this.logger.setContext(OAuthRepository.name); } - init() { - custom.setHttpOptionsDefaults({ timeout: 30_000 }); - } - - async authorize(config: OAuthConfig, redirectUrl: string) { + async authorize(config: OAuthConfig, redirectUrl: string, state?: string, codeChallenge?: string) { + const { buildAuthorizationUrl, randomState, randomPKCECodeVerifier, calculatePKCECodeChallenge } = await import( + 'openid-client' + ); const client = await this.getClient(config); - return client.authorizationUrl({ + state ??= randomState(); + let codeVerifier: string | null; + if (codeChallenge) { + codeVerifier = null; + } else { + codeVerifier = randomPKCECodeVerifier(); + codeChallenge = await calculatePKCECodeChallenge(codeVerifier); + } + const url = buildAuthorizationUrl(client, { redirect_uri: redirectUrl, scope: config.scope, - state: generators.state(), - }); + state, + code_challenge: codeChallenge, + code_challenge_method: 'S256', + }).toString(); + return { url, state, codeVerifier }; } async getLogoutEndpoint(config: OAuthConfig) { const client = await this.getClient(config); - return client.issuer.metadata.end_session_endpoint; + return client.serverMetadata().end_session_endpoint; } - async getProfile(config: OAuthConfig, url: string, redirectUrl: string): Promise { + async getProfile( + config: OAuthConfig, + url: string, + expectedState: string, + codeVerifier: string, + ): Promise { + const { authorizationCodeGrant, fetchUserInfo, ...oidc } = await import('openid-client'); const client = await this.getClient(config); - const params = client.callbackParams(url); + const pkceCodeVerifier = client.serverMetadata().supportsPKCE() ? codeVerifier : undefined; + try { - const tokens = await client.callback(redirectUrl, params, { state: params.state }); - const profile = await client.userinfo(tokens.access_token || ''); + const tokens = await authorizationCodeGrant(client, new URL(url), { expectedState, pkceCodeVerifier }); + const profile = await fetchUserInfo(client, tokens.access_token, oidc.skipSubjectCheck); if (!profile.sub) { throw new Error('Unexpected profile response, no `sub`'); } @@ -59,7 +79,10 @@ export class OAuthRepository { ); } - throw error; + this.logger.error(`OAuth login failed: ${error.message}`); + this.logger.error(error); + + throw new Error('OAuth login failed', { cause: error }); } } @@ -81,19 +104,51 @@ export class OAuthRepository { clientSecret, profileSigningAlgorithm, signingAlgorithm, + tokenEndpointAuthMethod, + timeout, }: OAuthConfig) { try { - const issuer = await Issuer.discover(issuerUrl); - return new issuer.Client({ - client_id: clientId, - client_secret: clientSecret, - response_types: ['code'], - userinfo_signed_response_alg: profileSigningAlgorithm === 'none' ? undefined : profileSigningAlgorithm, - id_token_signed_response_alg: signingAlgorithm, - }); + const { allowInsecureRequests, discovery } = await import('openid-client'); + return await discovery( + new URL(issuerUrl), + clientId, + { + client_secret: clientSecret, + response_types: ['code'], + userinfo_signed_response_alg: profileSigningAlgorithm === 'none' ? undefined : profileSigningAlgorithm, + id_token_signed_response_alg: signingAlgorithm, + }, + await this.getTokenAuthMethod(tokenEndpointAuthMethod, clientSecret), + { + execute: [allowInsecureRequests], + timeout, + }, + ); } catch (error: any | AggregateError) { this.logger.error(`Error in OAuth discovery: ${error}`, error?.stack, error?.errors); throw new InternalServerErrorException(`Error in OAuth discovery: ${error}`, { cause: error }); } } + + private async getTokenAuthMethod(tokenEndpointAuthMethod: OAuthTokenEndpointAuthMethod, clientSecret?: string) { + const { None, ClientSecretPost, ClientSecretBasic } = await import('openid-client'); + + if (!clientSecret) { + return None(); + } + + switch (tokenEndpointAuthMethod) { + case OAuthTokenEndpointAuthMethod.CLIENT_SECRET_POST: { + return ClientSecretPost(clientSecret); + } + + case OAuthTokenEndpointAuthMethod.CLIENT_SECRET_BASIC: { + return ClientSecretBasic(clientSecret); + } + + default: { + return None(); + } + } + } } diff --git a/server/src/repositories/search.repository.ts b/server/src/repositories/search.repository.ts index 5c1ebae69d..0c958fec02 100644 --- a/server/src/repositories/search.repository.ts +++ b/server/src/repositories/search.repository.ts @@ -6,7 +6,8 @@ import { DB, Exif } from 'src/db'; import { DummyValue, GenerateSql } from 'src/decorators'; import { MapAsset } from 'src/dtos/asset-response.dto'; import { AssetStatus, AssetType } from 'src/enum'; -import { anyUuid, asUuid, searchAssetBuilder } from 'src/utils/database'; +import { ConfigRepository } from 'src/repositories/config.repository'; +import { anyUuid, asUuid, searchAssetBuilder, vectorIndexQuery } from 'src/utils/database'; import { isValidInteger } from 'src/validation'; export interface SearchResult { @@ -201,7 +202,10 @@ export interface GetCameraMakesOptions { @Injectable() export class SearchRepository { - constructor(@InjectKysely() private db: Kysely) {} + constructor( + @InjectKysely() private db: Kysely, + private configRepository: ConfigRepository, + ) {} @GenerateSql({ params: [ @@ -446,8 +450,8 @@ export class SearchRepository { async upsert(assetId: string, embedding: string): Promise { await this.db .insertInto('smart_search') - .values({ assetId: asUuid(assetId), embedding } as any) - .onConflict((oc) => oc.column('assetId').doUpdateSet({ embedding } as any)) + .values({ assetId, embedding }) + .onConflict((oc) => oc.column('assetId').doUpdateSet((eb) => ({ embedding: eb.ref('excluded.embedding') }))) .execute(); } @@ -469,19 +473,32 @@ export class SearchRepository { return dimSize; } - setDimensionSize(dimSize: number): Promise { + async setDimensionSize(dimSize: number): Promise { if (!isValidInteger(dimSize, { min: 1, max: 2 ** 16 })) { throw new Error(`Invalid CLIP dimension size: ${dimSize}`); } - return this.db.transaction().execute(async (trx) => { - await sql`truncate ${sql.table('smart_search')}`.execute(trx); + // this is done in two transactions to handle concurrent writes + await this.db.transaction().execute(async (trx) => { + await sql`delete from ${sql.table('smart_search')}`.execute(trx); + await trx.schema.alterTable('smart_search').dropConstraint('dim_size_constraint').ifExists().execute(); + await sql`alter table ${sql.table('smart_search')} add constraint dim_size_constraint check (array_length(embedding::real[], 1) = ${sql.lit(dimSize)})`.execute( + trx, + ); + }); + + const vectorExtension = this.configRepository.getEnv().database.vectorExtension; + await this.db.transaction().execute(async (trx) => { + await sql`drop index if exists clip_index`.execute(trx); await trx.schema .alterTable('smart_search') .alterColumn('embedding', (col) => col.setDataType(sql.raw(`vector(${dimSize})`))) .execute(); - await sql`reindex index clip_index`.execute(trx); + await sql.raw(vectorIndexQuery({ vectorExtension, table: 'smart_search', indexName: 'clip_index' })).execute(trx); + await trx.schema.alterTable('smart_search').dropConstraint('dim_size_constraint').ifExists().execute(); }); + + await sql`vacuum analyze ${sql.table('smart_search')}`.execute(this.db); } async deleteAllSearchEmbeddings(): Promise { diff --git a/server/src/repositories/server-info.repository.ts b/server/src/repositories/server-info.repository.ts index deb24123d0..4500094899 100644 --- a/server/src/repositories/server-info.repository.ts +++ b/server/src/repositories/server-info.repository.ts @@ -73,26 +73,54 @@ export class ServerInfoRepository { } } + buildVersions?: ServerBuildVersions; + + private async retrieveVersionFallback( + command: string, + commandTransform?: (output: string) => string, + version?: string, + ): Promise { + if (!version) { + const output = await maybeFirstLine(command); + version = commandTransform ? commandTransform(output) : output; + } + return version; + } + async getBuildVersions(): Promise { - const { nodeVersion, resourcePaths } = this.configRepository.getEnv(); + if (!this.buildVersions) { + const { nodeVersion, resourcePaths } = this.configRepository.getEnv(); - const [nodejsOutput, ffmpegOutput, magickOutput] = await Promise.all([ - maybeFirstLine('node --version'), - maybeFirstLine('ffmpeg -version'), - maybeFirstLine('convert --version'), - ]); + const lockfile: BuildLockfile | undefined = await readFile(resourcePaths.lockFile) + .then((buffer) => JSON.parse(buffer.toString())) + .catch(() => this.logger.warn(`Failed to read ${resourcePaths.lockFile}`)); - const lockfile = await readFile(resourcePaths.lockFile) - .then((buffer) => JSON.parse(buffer.toString())) - .catch(() => this.logger.warn(`Failed to read ${resourcePaths.lockFile}`)); + const [nodejsVersion, ffmpegVersion, magickVersion, exiftoolVersion] = await Promise.all([ + this.retrieveVersionFallback('node --version', undefined, nodeVersion), + this.retrieveVersionFallback( + 'ffmpeg -version', + (output) => output.replaceAll('ffmpeg version ', ''), + getLockfileVersion('ffmpeg', lockfile), + ), + this.retrieveVersionFallback( + 'magick --version', + (output) => output.replaceAll('Version: ImageMagick ', ''), + getLockfileVersion('imagemagick', lockfile), + ), + exiftool.version(), + ]); - return { - nodejs: nodejsOutput || nodeVersion || '', - exiftool: await exiftool.version(), - ffmpeg: getLockfileVersion('ffmpeg', lockfile) || ffmpegOutput.replaceAll('ffmpeg version', '') || '', - libvips: getLockfileVersion('libvips', lockfile) || sharp.versions.vips, - imagemagick: - getLockfileVersion('imagemagick', lockfile) || magickOutput.replaceAll('Version: ImageMagick ', '') || '', - }; + const libvipsVersion = getLockfileVersion('libvips', lockfile) || sharp.versions.vips; + + this.buildVersions = { + nodejs: nodejsVersion, + exiftool: exiftoolVersion, + ffmpeg: ffmpegVersion, + libvips: libvipsVersion, + imagemagick: magickVersion, + }; + } + + return this.buildVersions; } } diff --git a/server/src/schema/index.ts b/server/src/schema/index.ts index fe4b86d65c..c62681d049 100644 --- a/server/src/schema/index.ts +++ b/server/src/schema/index.ts @@ -28,6 +28,7 @@ import { MemoryTable } from 'src/schema/tables/memory.table'; import { MemoryAssetTable } from 'src/schema/tables/memory_asset.table'; import { MoveTable } from 'src/schema/tables/move.table'; import { NaturalEarthCountriesTable } from 'src/schema/tables/natural-earth-countries.table'; +import { NotificationTable } from 'src/schema/tables/notification.table'; import { PartnerAuditTable } from 'src/schema/tables/partner-audit.table'; import { PartnerTable } from 'src/schema/tables/partner.table'; import { PersonTable } from 'src/schema/tables/person.table'; @@ -46,14 +47,8 @@ import { UserTable } from 'src/schema/tables/user.table'; import { VersionHistoryTable } from 'src/schema/tables/version-history.table'; import { ConfigurationParameter, Database, Extensions } from 'src/sql-tools'; -@Extensions(['uuid-ossp', 'unaccent', 'cube', 'earthdistance', 'pg_trgm', 'vectors', 'plpgsql']) +@Extensions(['uuid-ossp', 'unaccent', 'cube', 'earthdistance', 'pg_trgm', 'plpgsql']) @ConfigurationParameter({ name: 'search_path', value: () => '"$user", public, vectors', scope: 'database' }) -@ConfigurationParameter({ - name: 'vectors.pgvector_compatibility', - value: () => 'on', - scope: 'user', - synchronize: false, -}) @Database({ name: 'immich' }) export class ImmichDatabase { tables = [ @@ -76,6 +71,7 @@ export class ImmichDatabase { MemoryTable, MoveTable, NaturalEarthCountriesTable, + NotificationTable, PartnerAuditTable, PartnerTable, PersonTable, diff --git a/server/src/schema/migrations/1744910873969-InitialMigration.ts b/server/src/schema/migrations/1744910873969-InitialMigration.ts index 459534a26a..ce4a37ae3b 100644 --- a/server/src/schema/migrations/1744910873969-InitialMigration.ts +++ b/server/src/schema/migrations/1744910873969-InitialMigration.ts @@ -2,6 +2,7 @@ import { Kysely, sql } from 'kysely'; import { DatabaseExtension } from 'src/enum'; import { ConfigRepository } from 'src/repositories/config.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; +import { vectorIndexQuery } from 'src/utils/database'; const vectorExtension = new ConfigRepository().getEnv().database.vectorExtension; const lastMigrationSql = sql<{ name: string }>`SELECT "name" FROM "migrations" ORDER BY "timestamp" DESC LIMIT 1;`; @@ -29,7 +30,7 @@ export async function up(db: Kysely): Promise { await sql`CREATE EXTENSION IF NOT EXISTS "cube";`.execute(db); await sql`CREATE EXTENSION IF NOT EXISTS "earthdistance";`.execute(db); await sql`CREATE EXTENSION IF NOT EXISTS "pg_trgm";`.execute(db); - await sql`CREATE EXTENSION IF NOT EXISTS "vectors";`.execute(db); + await sql`CREATE EXTENSION IF NOT EXISTS ${sql.raw(vectorExtension)}`.execute(db); await sql`CREATE OR REPLACE FUNCTION immich_uuid_v7(p_timestamp timestamp with time zone default clock_timestamp()) RETURNS uuid VOLATILE LANGUAGE SQL @@ -108,7 +109,6 @@ export async function up(db: Kysely): Promise { $$;`.execute(db); if (vectorExtension === DatabaseExtension.VECTORS) { await sql`SET search_path TO "$user", public, vectors`.execute(db); - await sql`SET vectors.pgvector_compatibility=on`.execute(db); } await sql`CREATE TYPE "assets_status_enum" AS ENUM ('active','trashed','deleted');`.execute(db); await sql`CREATE TYPE "sourcetype" AS ENUM ('machine-learning','exif','manual');`.execute(db); @@ -293,7 +293,7 @@ export async function up(db: Kysely): Promise { await sql`CREATE INDEX "IDX_live_photo_cid" ON "exif" ("livePhotoCID")`.execute(db); await sql`CREATE INDEX "IDX_auto_stack_id" ON "exif" ("autoStackId")`.execute(db); await sql`CREATE INDEX "IDX_asset_exif_update_id" ON "exif" ("updateId")`.execute(db); - await sql`CREATE INDEX "face_index" ON "face_search" USING hnsw (embedding vector_cosine_ops) WITH (ef_construction = 300, m = 16)`.execute(db); + await sql.raw(vectorIndexQuery({ vectorExtension, table: 'face_search', indexName: 'face_index' })).execute(db); await sql`CREATE INDEX "IDX_geodata_gist_earthcoord" ON "geodata_places" (ll_to_earth_public(latitude, longitude))`.execute(db); await sql`CREATE INDEX "idx_geodata_places_name" ON "geodata_places" USING gin (f_unaccent("name") gin_trgm_ops)`.execute(db); await sql`CREATE INDEX "idx_geodata_places_admin2_name" ON "geodata_places" USING gin (f_unaccent("admin2Name") gin_trgm_ops)`.execute(db); @@ -316,7 +316,7 @@ export async function up(db: Kysely): Promise { await sql`CREATE INDEX "IDX_sharedlink_albumId" ON "shared_links" ("albumId")`.execute(db); await sql`CREATE INDEX "IDX_5b7decce6c8d3db9593d6111a6" ON "shared_link__asset" ("assetsId")`.execute(db); await sql`CREATE INDEX "IDX_c9fab4aa97ffd1b034f3d6581a" ON "shared_link__asset" ("sharedLinksId")`.execute(db); - await sql`CREATE INDEX "clip_index" ON "smart_search" USING hnsw (embedding vector_cosine_ops) WITH (ef_construction = 300, m = 16)`.execute(db); + await sql.raw(vectorIndexQuery({ vectorExtension, table: 'smart_search', indexName: 'clip_index' })).execute(db); await sql`CREATE INDEX "IDX_d8ddd9d687816cc490432b3d4b" ON "session_sync_checkpoints" ("sessionId")`.execute(db); await sql`CREATE INDEX "IDX_session_sync_checkpoints_update_id" ON "session_sync_checkpoints" ("updateId")`.execute(db); await sql`CREATE INDEX "IDX_92e67dc508c705dd66c9461557" ON "tags" ("userId")`.execute(db); diff --git a/server/src/schema/migrations/1744991379464-AddNotificationsTable.ts b/server/src/schema/migrations/1744991379464-AddNotificationsTable.ts new file mode 100644 index 0000000000..28dca6658c --- /dev/null +++ b/server/src/schema/migrations/1744991379464-AddNotificationsTable.ts @@ -0,0 +1,22 @@ +import { Kysely, sql } from 'kysely'; + +export async function up(db: Kysely): Promise { + await sql`CREATE TABLE "notifications" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" timestamp with time zone NOT NULL DEFAULT now(), "updatedAt" timestamp with time zone NOT NULL DEFAULT now(), "deletedAt" timestamp with time zone, "updateId" uuid NOT NULL DEFAULT immich_uuid_v7(), "userId" uuid, "level" character varying NOT NULL DEFAULT 'info', "type" character varying NOT NULL DEFAULT 'info', "data" jsonb, "title" character varying NOT NULL, "description" text, "readAt" timestamp with time zone);`.execute(db); + await sql`ALTER TABLE "notifications" ADD CONSTRAINT "PK_6a72c3c0f683f6462415e653c3a" PRIMARY KEY ("id");`.execute(db); + await sql`ALTER TABLE "notifications" ADD CONSTRAINT "FK_692a909ee0fa9383e7859f9b406" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON UPDATE CASCADE ON DELETE CASCADE;`.execute(db); + await sql`CREATE INDEX "IDX_notifications_update_id" ON "notifications" ("updateId")`.execute(db); + await sql`CREATE INDEX "IDX_692a909ee0fa9383e7859f9b40" ON "notifications" ("userId")`.execute(db); + await sql`CREATE OR REPLACE TRIGGER "notifications_updated_at" + BEFORE UPDATE ON "notifications" + FOR EACH ROW + EXECUTE FUNCTION updated_at();`.execute(db); +} + +export async function down(db: Kysely): Promise { + await sql`DROP TRIGGER "notifications_updated_at" ON "notifications";`.execute(db); + await sql`DROP INDEX "IDX_notifications_update_id";`.execute(db); + await sql`DROP INDEX "IDX_692a909ee0fa9383e7859f9b40";`.execute(db); + await sql`ALTER TABLE "notifications" DROP CONSTRAINT "PK_6a72c3c0f683f6462415e653c3a";`.execute(db); + await sql`ALTER TABLE "notifications" DROP CONSTRAINT "FK_692a909ee0fa9383e7859f9b406";`.execute(db); + await sql`DROP TABLE "notifications";`.execute(db); +} diff --git a/server/src/schema/migrations/1745244781846-AddUserAvatarColorColumn.ts b/server/src/schema/migrations/1745244781846-AddUserAvatarColorColumn.ts new file mode 100644 index 0000000000..5f3fdbedc8 --- /dev/null +++ b/server/src/schema/migrations/1745244781846-AddUserAvatarColorColumn.ts @@ -0,0 +1,14 @@ +import { Kysely, sql } from 'kysely'; + +export async function up(db: Kysely): Promise { + await sql`ALTER TABLE "users" ADD "avatarColor" character varying;`.execute(db); + await sql` + UPDATE "users" + SET "avatarColor" = "user_metadata"."value"->'avatar'->>'color' + FROM "user_metadata" + WHERE "users"."id" = "user_metadata"."userId" AND "user_metadata"."key" = 'preferences';`.execute(db); +} + +export async function down(db: Kysely): Promise { + await sql`ALTER TABLE "users" DROP COLUMN "avatarColor";`.execute(db); +} diff --git a/server/src/schema/tables/notification.table.ts b/server/src/schema/tables/notification.table.ts new file mode 100644 index 0000000000..bf9b8bdf3b --- /dev/null +++ b/server/src/schema/tables/notification.table.ts @@ -0,0 +1,52 @@ +import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators'; +import { NotificationLevel, NotificationType } from 'src/enum'; +import { UserTable } from 'src/schema/tables/user.table'; +import { + Column, + CreateDateColumn, + DeleteDateColumn, + ForeignKeyColumn, + PrimaryGeneratedColumn, + Table, + UpdateDateColumn, +} from 'src/sql-tools'; + +@Table('notifications') +@UpdatedAtTrigger('notifications_updated_at') +export class NotificationTable { + @PrimaryGeneratedColumn() + id!: string; + + @CreateDateColumn() + createdAt!: Date; + + @UpdateDateColumn() + updatedAt!: Date; + + @DeleteDateColumn() + deletedAt?: Date; + + @UpdateIdColumn({ indexName: 'IDX_notifications_update_id' }) + updateId?: string; + + @ForeignKeyColumn(() => UserTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE', nullable: true }) + userId!: string; + + @Column({ default: NotificationLevel.Info }) + level!: NotificationLevel; + + @Column({ default: NotificationLevel.Info }) + type!: NotificationType; + + @Column({ type: 'jsonb', nullable: true }) + data!: any | null; + + @Column() + title!: string; + + @Column({ type: 'text', nullable: true }) + description!: string; + + @Column({ type: 'timestamp with time zone', nullable: true }) + readAt?: Date | null; +} diff --git a/server/src/schema/tables/user.table.ts b/server/src/schema/tables/user.table.ts index eeef923796..7525a739a6 100644 --- a/server/src/schema/tables/user.table.ts +++ b/server/src/schema/tables/user.table.ts @@ -1,6 +1,6 @@ import { ColumnType } from 'kysely'; import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators'; -import { UserStatus } from 'src/enum'; +import { UserAvatarColor, UserStatus } from 'src/enum'; import { users_delete_audit } from 'src/schema/functions'; import { AfterDeleteTrigger, @@ -49,6 +49,9 @@ export class UserTable { @Column({ type: 'boolean', default: true }) shouldChangePassword!: Generated; + @Column({ default: null }) + avatarColor!: UserAvatarColor | null; + @DeleteDateColumn() deletedAt!: Timestamp | null; diff --git a/server/src/services/asset.service.spec.ts b/server/src/services/asset.service.spec.ts index a3f536ac33..af4fef5bd5 100755 --- a/server/src/services/asset.service.spec.ts +++ b/server/src/services/asset.service.spec.ts @@ -565,7 +565,7 @@ describe(AssetService.name, () => { it('should remove faces', async () => { const assetWithFace = { ...assetStub.image, faces: [faceStub.face1, faceStub.mergeFace1] }; - mocks.asset.getById.mockResolvedValue(assetWithFace); + mocks.assetJob.getForAssetDeletion.mockResolvedValue(assetWithFace); await sut.handleAssetDeletion({ id: assetWithFace.id, deleteOnDisk: true }); @@ -592,7 +592,7 @@ describe(AssetService.name, () => { it('should update stack primary asset if deleted asset was primary asset in a stack', async () => { mocks.stack.update.mockResolvedValue(factory.stack() as any); - mocks.asset.getById.mockResolvedValue(assetStub.primaryImage); + mocks.assetJob.getForAssetDeletion.mockResolvedValue(assetStub.primaryImage); await sut.handleAssetDeletion({ id: assetStub.primaryImage.id, deleteOnDisk: true }); @@ -604,7 +604,7 @@ describe(AssetService.name, () => { it('should delete the entire stack if deleted asset was the primary asset and the stack would only contain one asset afterwards', async () => { mocks.stack.delete.mockResolvedValue(); - mocks.asset.getById.mockResolvedValue({ + mocks.assetJob.getForAssetDeletion.mockResolvedValue({ ...assetStub.primaryImage, stack: { ...assetStub.primaryImage.stack, assets: assetStub.primaryImage.stack!.assets.slice(0, 2) }, }); @@ -615,7 +615,7 @@ describe(AssetService.name, () => { }); it('should delete a live photo', async () => { - mocks.asset.getById.mockResolvedValue(assetStub.livePhotoStillAsset); + mocks.assetJob.getForAssetDeletion.mockResolvedValue(assetStub.livePhotoStillAsset as any); mocks.asset.getLivePhotoCount.mockResolvedValue(0); await sut.handleAssetDeletion({ @@ -653,7 +653,7 @@ describe(AssetService.name, () => { it('should not delete a live motion part if it is being used by another asset', async () => { mocks.asset.getLivePhotoCount.mockResolvedValue(2); - mocks.asset.getById.mockResolvedValue(assetStub.livePhotoStillAsset); + mocks.assetJob.getForAssetDeletion.mockResolvedValue(assetStub.livePhotoStillAsset as any); await sut.handleAssetDeletion({ id: assetStub.livePhotoStillAsset.id, @@ -680,12 +680,13 @@ describe(AssetService.name, () => { }); it('should update usage', async () => { - mocks.asset.getById.mockResolvedValue(assetStub.image); + mocks.assetJob.getForAssetDeletion.mockResolvedValue(assetStub.image); await sut.handleAssetDeletion({ id: assetStub.image.id, deleteOnDisk: true }); expect(mocks.user.updateUsage).toHaveBeenCalledWith(assetStub.image.ownerId, -5000); }); it('should fail if asset could not be found', async () => { + mocks.assetJob.getForAssetDeletion.mockResolvedValue(void 0); await expect(sut.handleAssetDeletion({ id: assetStub.image.id, deleteOnDisk: true })).resolves.toBe( JobStatus.FAILED, ); diff --git a/server/src/services/asset.service.ts b/server/src/services/asset.service.ts index 16f60907ba..3e13ed0b8e 100644 --- a/server/src/services/asset.service.ts +++ b/server/src/services/asset.service.ts @@ -189,13 +189,7 @@ export class AssetService extends BaseService { async handleAssetDeletion(job: JobOf): Promise { const { id, deleteOnDisk } = job; - const asset = await this.assetRepository.getById(id, { - faces: { person: true }, - library: true, - stack: { assets: true }, - exifInfo: true, - files: true, - }); + const asset = await this.assetJobRepository.getForAssetDeletion(id); if (!asset) { return JobStatus.FAILED; diff --git a/server/src/services/audit.service.spec.ts b/server/src/services/audit.service.spec.ts index 6ef139f506..381b2ec7e8 100644 --- a/server/src/services/audit.service.spec.ts +++ b/server/src/services/audit.service.spec.ts @@ -1,6 +1,4 @@ -import { BadRequestException } from '@nestjs/common'; -import { FileReportItemDto } from 'src/dtos/audit.dto'; -import { AssetFileType, AssetPathType, JobStatus, PersonPathType, UserPathType } from 'src/enum'; +import { JobStatus } from 'src/enum'; import { AuditService } from 'src/services/audit.service'; import { newTestService, ServiceMocks } from 'test/utils'; @@ -25,148 +23,4 @@ describe(AuditService.name, () => { expect(mocks.audit.removeBefore).toHaveBeenCalledWith(expect.any(Date)); }); }); - - describe('getChecksums', () => { - it('should fail if the file is not in the immich path', async () => { - await expect(sut.getChecksums({ filenames: ['foo/bar'] })).rejects.toBeInstanceOf(BadRequestException); - - expect(mocks.crypto.hashFile).not.toHaveBeenCalled(); - }); - - it('should get checksum for valid file', async () => { - await expect(sut.getChecksums({ filenames: ['./upload/my-file.jpg'] })).resolves.toEqual([ - { filename: './upload/my-file.jpg', checksum: expect.any(String) }, - ]); - - expect(mocks.crypto.hashFile).toHaveBeenCalledWith('./upload/my-file.jpg'); - }); - }); - - describe('fixItems', () => { - it('should fail if the file is not in the immich path', async () => { - await expect( - sut.fixItems([ - { entityId: 'my-id', pathType: AssetPathType.ORIGINAL, pathValue: 'foo/bar' } as FileReportItemDto, - ]), - ).rejects.toBeInstanceOf(BadRequestException); - - expect(mocks.asset.update).not.toHaveBeenCalled(); - expect(mocks.asset.upsertFile).not.toHaveBeenCalled(); - expect(mocks.person.update).not.toHaveBeenCalled(); - expect(mocks.user.update).not.toHaveBeenCalled(); - }); - - it('should update encoded video path', async () => { - await sut.fixItems([ - { - entityId: 'my-id', - pathType: AssetPathType.ENCODED_VIDEO, - pathValue: './upload/my-video.mp4', - } as FileReportItemDto, - ]); - - expect(mocks.asset.update).toHaveBeenCalledWith({ id: 'my-id', encodedVideoPath: './upload/my-video.mp4' }); - expect(mocks.asset.upsertFile).not.toHaveBeenCalled(); - expect(mocks.person.update).not.toHaveBeenCalled(); - expect(mocks.user.update).not.toHaveBeenCalled(); - }); - - it('should update preview path', async () => { - await sut.fixItems([ - { - entityId: 'my-id', - pathType: AssetPathType.PREVIEW, - pathValue: './upload/my-preview.png', - } as FileReportItemDto, - ]); - - expect(mocks.asset.upsertFile).toHaveBeenCalledWith({ - assetId: 'my-id', - type: AssetFileType.PREVIEW, - path: './upload/my-preview.png', - }); - expect(mocks.asset.update).not.toHaveBeenCalled(); - expect(mocks.person.update).not.toHaveBeenCalled(); - expect(mocks.user.update).not.toHaveBeenCalled(); - }); - - it('should update thumbnail path', async () => { - await sut.fixItems([ - { - entityId: 'my-id', - pathType: AssetPathType.THUMBNAIL, - pathValue: './upload/my-thumbnail.webp', - } as FileReportItemDto, - ]); - - expect(mocks.asset.upsertFile).toHaveBeenCalledWith({ - assetId: 'my-id', - type: AssetFileType.THUMBNAIL, - path: './upload/my-thumbnail.webp', - }); - expect(mocks.asset.update).not.toHaveBeenCalled(); - expect(mocks.person.update).not.toHaveBeenCalled(); - expect(mocks.user.update).not.toHaveBeenCalled(); - }); - - it('should update original path', async () => { - await sut.fixItems([ - { - entityId: 'my-id', - pathType: AssetPathType.ORIGINAL, - pathValue: './upload/my-original.png', - } as FileReportItemDto, - ]); - - expect(mocks.asset.update).toHaveBeenCalledWith({ id: 'my-id', originalPath: './upload/my-original.png' }); - expect(mocks.asset.upsertFile).not.toHaveBeenCalled(); - expect(mocks.person.update).not.toHaveBeenCalled(); - expect(mocks.user.update).not.toHaveBeenCalled(); - }); - - it('should update sidecar path', async () => { - await sut.fixItems([ - { - entityId: 'my-id', - pathType: AssetPathType.SIDECAR, - pathValue: './upload/my-sidecar.xmp', - } as FileReportItemDto, - ]); - - expect(mocks.asset.update).toHaveBeenCalledWith({ id: 'my-id', sidecarPath: './upload/my-sidecar.xmp' }); - expect(mocks.asset.upsertFile).not.toHaveBeenCalled(); - expect(mocks.person.update).not.toHaveBeenCalled(); - expect(mocks.user.update).not.toHaveBeenCalled(); - }); - - it('should update face path', async () => { - await sut.fixItems([ - { - entityId: 'my-id', - pathType: PersonPathType.FACE, - pathValue: './upload/my-face.jpg', - } as FileReportItemDto, - ]); - - expect(mocks.person.update).toHaveBeenCalledWith({ id: 'my-id', thumbnailPath: './upload/my-face.jpg' }); - expect(mocks.asset.update).not.toHaveBeenCalled(); - expect(mocks.asset.upsertFile).not.toHaveBeenCalled(); - expect(mocks.user.update).not.toHaveBeenCalled(); - }); - - it('should update profile path', async () => { - await sut.fixItems([ - { - entityId: 'my-id', - pathType: UserPathType.PROFILE, - pathValue: './upload/my-profile-pic.jpg', - } as FileReportItemDto, - ]); - - expect(mocks.user.update).toHaveBeenCalledWith('my-id', { profileImagePath: './upload/my-profile-pic.jpg' }); - expect(mocks.asset.update).not.toHaveBeenCalled(); - expect(mocks.asset.upsertFile).not.toHaveBeenCalled(); - expect(mocks.person.update).not.toHaveBeenCalled(); - }); - }); }); diff --git a/server/src/services/audit.service.ts b/server/src/services/audit.service.ts index a049a9c64b..7c9a070dd0 100644 --- a/server/src/services/audit.service.ts +++ b/server/src/services/audit.service.ts @@ -1,23 +1,9 @@ -import { BadRequestException, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { DateTime } from 'luxon'; -import { resolve } from 'node:path'; -import { AUDIT_LOG_MAX_DURATION, JOBS_ASSET_PAGINATION_SIZE } from 'src/constants'; -import { StorageCore } from 'src/cores/storage.core'; +import { AUDIT_LOG_MAX_DURATION } from 'src/constants'; import { OnJob } from 'src/decorators'; -import { FileChecksumDto, FileChecksumResponseDto, FileReportItemDto, PathEntityType } from 'src/dtos/audit.dto'; -import { - AssetFileType, - AssetPathType, - JobName, - JobStatus, - PersonPathType, - QueueName, - StorageFolder, - UserPathType, -} from 'src/enum'; +import { JobName, JobStatus, QueueName } from 'src/enum'; import { BaseService } from 'src/services/base.service'; -import { getAssetFiles } from 'src/utils/asset.util'; -import { usePagination } from 'src/utils/pagination'; @Injectable() export class AuditService extends BaseService { @@ -26,187 +12,4 @@ export class AuditService extends BaseService { await this.auditRepository.removeBefore(DateTime.now().minus(AUDIT_LOG_MAX_DURATION).toJSDate()); return JobStatus.SUCCESS; } - - async getChecksums(dto: FileChecksumDto) { - const results: FileChecksumResponseDto[] = []; - for (const filename of dto.filenames) { - if (!StorageCore.isImmichPath(filename)) { - throw new BadRequestException( - `Could not get the checksum of ${filename} because the file isn't accessible by Immich`, - ); - } - - const checksum = await this.cryptoRepository.hashFile(filename); - results.push({ filename, checksum: checksum.toString('base64') }); - } - return results; - } - - async fixItems(items: FileReportItemDto[]) { - for (const { entityId: id, pathType, pathValue } of items) { - if (!StorageCore.isImmichPath(pathValue)) { - throw new BadRequestException( - `Could not fix item ${id} with path ${pathValue} because the file isn't accessible by Immich`, - ); - } - - switch (pathType) { - case AssetPathType.ENCODED_VIDEO: { - await this.assetRepository.update({ id, encodedVideoPath: pathValue }); - break; - } - - case AssetPathType.PREVIEW: { - await this.assetRepository.upsertFile({ assetId: id, type: AssetFileType.PREVIEW, path: pathValue }); - break; - } - - case AssetPathType.THUMBNAIL: { - await this.assetRepository.upsertFile({ assetId: id, type: AssetFileType.THUMBNAIL, path: pathValue }); - break; - } - - case AssetPathType.ORIGINAL: { - await this.assetRepository.update({ id, originalPath: pathValue }); - break; - } - - case AssetPathType.SIDECAR: { - await this.assetRepository.update({ id, sidecarPath: pathValue }); - break; - } - - case PersonPathType.FACE: { - await this.personRepository.update({ id, thumbnailPath: pathValue }); - break; - } - - case UserPathType.PROFILE: { - await this.userRepository.update(id, { profileImagePath: pathValue }); - break; - } - } - } - } - - private fullPath(filename: string) { - return resolve(filename); - } - - async getFileReport() { - const hasFile = (items: Set, filename: string) => items.has(filename) || items.has(this.fullPath(filename)); - const crawl = async (folder: StorageFolder) => - new Set( - await this.storageRepository.crawl({ - includeHidden: true, - pathsToCrawl: [StorageCore.getBaseFolder(folder)], - }), - ); - - const uploadFiles = await crawl(StorageFolder.UPLOAD); - const libraryFiles = await crawl(StorageFolder.LIBRARY); - const thumbFiles = await crawl(StorageFolder.THUMBNAILS); - const videoFiles = await crawl(StorageFolder.ENCODED_VIDEO); - const profileFiles = await crawl(StorageFolder.PROFILE); - const allFiles = new Set(); - for (const list of [libraryFiles, thumbFiles, videoFiles, profileFiles, uploadFiles]) { - for (const item of list) { - allFiles.add(item); - } - } - - const track = (filename: string | null | undefined) => { - if (!filename) { - return; - } - allFiles.delete(filename); - allFiles.delete(this.fullPath(filename)); - }; - - this.logger.log( - `Found ${libraryFiles.size} original files, ${thumbFiles.size} thumbnails, ${videoFiles.size} encoded videos, ${profileFiles.size} profile files`, - ); - const pagination = usePagination(JOBS_ASSET_PAGINATION_SIZE, (options) => - this.assetRepository.getAll(options, { withDeleted: true, withArchived: true }), - ); - - let assetCount = 0; - - const orphans: FileReportItemDto[] = []; - for await (const assets of pagination) { - assetCount += assets.length; - for (const { id, files, originalPath, encodedVideoPath, isExternal, checksum } of assets) { - const { fullsizeFile, previewFile, thumbnailFile } = getAssetFiles(files); - for (const file of [ - originalPath, - fullsizeFile?.path, - previewFile?.path, - encodedVideoPath, - thumbnailFile?.path, - ]) { - track(file); - } - - const entity = { entityId: id, entityType: PathEntityType.ASSET, checksum: checksum.toString('base64') }; - if ( - originalPath && - !hasFile(libraryFiles, originalPath) && - !hasFile(uploadFiles, originalPath) && - // Android motion assets - !hasFile(videoFiles, originalPath) && - // ignore external library assets - !isExternal - ) { - orphans.push({ ...entity, pathType: AssetPathType.ORIGINAL, pathValue: originalPath }); - } - if (previewFile && !hasFile(thumbFiles, previewFile.path)) { - orphans.push({ ...entity, pathType: AssetPathType.PREVIEW, pathValue: previewFile.path }); - } - if (thumbnailFile && !hasFile(thumbFiles, thumbnailFile.path)) { - orphans.push({ ...entity, pathType: AssetPathType.THUMBNAIL, pathValue: thumbnailFile.path }); - } - if (encodedVideoPath && !hasFile(videoFiles, encodedVideoPath)) { - orphans.push({ ...entity, pathType: AssetPathType.THUMBNAIL, pathValue: encodedVideoPath }); - } - } - } - - const users = await this.userRepository.getList(); - for (const { id, profileImagePath } of users) { - track(profileImagePath); - - const entity = { entityId: id, entityType: PathEntityType.USER }; - if (profileImagePath && !hasFile(profileFiles, profileImagePath)) { - orphans.push({ ...entity, pathType: UserPathType.PROFILE, pathValue: profileImagePath }); - } - } - - let peopleCount = 0; - for await (const { id, thumbnailPath } of this.personRepository.getAll()) { - track(thumbnailPath); - const entity = { entityId: id, entityType: PathEntityType.PERSON }; - if (thumbnailPath && !hasFile(thumbFiles, thumbnailPath)) { - orphans.push({ ...entity, pathType: PersonPathType.FACE, pathValue: thumbnailPath }); - } - - if (peopleCount === JOBS_ASSET_PAGINATION_SIZE) { - this.logger.log(`Found ${assetCount} assets, ${users.length} users, ${peopleCount} people`); - peopleCount = 0; - } - } - - this.logger.log(`Found ${assetCount} assets, ${users.length} users, ${peopleCount} people`); - - const extras: string[] = []; - for (const file of allFiles) { - extras.push(file); - } - - // send as absolute paths - for (const orphan of orphans) { - orphan.pathValue = this.fullPath(orphan.pathValue); - } - - return { orphans, extras }; - } } diff --git a/server/src/services/auth.service.spec.ts b/server/src/services/auth.service.spec.ts index b1bfe00e85..75f5b8a52d 100644 --- a/server/src/services/auth.service.spec.ts +++ b/server/src/services/auth.service.spec.ts @@ -55,7 +55,7 @@ describe(AuthService.name, () => { beforeEach(() => { ({ sut, mocks } = newTestService(AuthService)); - mocks.oauth.authorize.mockResolvedValue('access-token'); + mocks.oauth.authorize.mockResolvedValue({ url: 'http://test', state: 'state', codeVerifier: 'codeVerifier' }); mocks.oauth.getProfile.mockResolvedValue({ sub, email }); mocks.oauth.getLogoutEndpoint.mockResolvedValue('http://end-session-endpoint'); }); @@ -64,16 +64,6 @@ describe(AuthService.name, () => { expect(sut).toBeDefined(); }); - describe('onBootstrap', () => { - it('should init the repo', () => { - mocks.oauth.init.mockResolvedValue(); - - sut.onBootstrap(); - - expect(mocks.oauth.init).toHaveBeenCalled(); - }); - }); - describe('login', () => { it('should throw an error if password login is disabled', async () => { mocks.systemMetadata.get.mockResolvedValue(systemConfigStub.disabled); @@ -519,16 +509,22 @@ describe(AuthService.name, () => { describe('callback', () => { it('should throw an error if OAuth is not enabled', async () => { - await expect(sut.callback({ url: '' }, loginDetails)).rejects.toBeInstanceOf(BadRequestException); + await expect( + sut.callback({ url: '', state: 'xyz789', codeVerifier: 'foo' }, {}, loginDetails), + ).rejects.toBeInstanceOf(BadRequestException); }); it('should not allow auto registering', async () => { mocks.systemMetadata.get.mockResolvedValue(systemConfigStub.oauthEnabled); mocks.user.getByEmail.mockResolvedValue(void 0); - await expect(sut.callback({ url: 'http://immich/auth/login?code=abc123' }, loginDetails)).rejects.toBeInstanceOf( - BadRequestException, - ); + await expect( + sut.callback( + { url: 'http://immich/auth/login?code=abc123', state: 'xyz789', codeVerifier: 'foo' }, + {}, + loginDetails, + ), + ).rejects.toBeInstanceOf(BadRequestException); expect(mocks.user.getByEmail).toHaveBeenCalledTimes(1); }); @@ -541,9 +537,13 @@ describe(AuthService.name, () => { mocks.user.update.mockResolvedValue(user); mocks.session.create.mockResolvedValue(factory.session()); - await expect(sut.callback({ url: 'http://immich/auth/login?code=abc123' }, loginDetails)).resolves.toEqual( - oauthResponse(user), - ); + await expect( + sut.callback( + { url: 'http://immich/auth/login?code=abc123', state: 'xyz789', codeVerifier: 'foobar' }, + {}, + loginDetails, + ), + ).resolves.toEqual(oauthResponse(user)); expect(mocks.user.getByEmail).toHaveBeenCalledTimes(1); expect(mocks.user.update).toHaveBeenCalledWith(user.id, { oauthId: sub }); @@ -557,9 +557,13 @@ describe(AuthService.name, () => { mocks.user.getAdmin.mockResolvedValue(user); mocks.user.create.mockResolvedValue(user); - await expect(sut.callback({ url: 'http://immich/auth/login?code=abc123' }, loginDetails)).rejects.toThrow( - BadRequestException, - ); + await expect( + sut.callback( + { url: 'http://immich/auth/login?code=abc123', state: 'xyz789', codeVerifier: 'foobar' }, + {}, + loginDetails, + ), + ).rejects.toThrow(BadRequestException); expect(mocks.user.update).not.toHaveBeenCalled(); expect(mocks.user.create).not.toHaveBeenCalled(); @@ -574,9 +578,13 @@ describe(AuthService.name, () => { mocks.user.create.mockResolvedValue(user); mocks.session.create.mockResolvedValue(factory.session()); - await expect(sut.callback({ url: 'http://immich/auth/login?code=abc123' }, loginDetails)).resolves.toEqual( - oauthResponse(user), - ); + await expect( + sut.callback( + { url: 'http://immich/auth/login?code=abc123', state: 'xyz789', codeVerifier: 'foobar' }, + {}, + loginDetails, + ), + ).resolves.toEqual(oauthResponse(user)); expect(mocks.user.getByEmail).toHaveBeenCalledTimes(2); // second call is for domain check before create expect(mocks.user.create).toHaveBeenCalledTimes(1); @@ -592,18 +600,19 @@ describe(AuthService.name, () => { mocks.session.create.mockResolvedValue(factory.session()); mocks.oauth.getProfile.mockResolvedValue({ sub, email: undefined }); - await expect(sut.callback({ url: 'http://immich/auth/login?code=abc123' }, loginDetails)).rejects.toBeInstanceOf( - BadRequestException, - ); + await expect( + sut.callback( + { url: 'http://immich/auth/login?code=abc123', state: 'xyz789', codeVerifier: 'foobar' }, + {}, + loginDetails, + ), + ).rejects.toBeInstanceOf(BadRequestException); expect(mocks.user.getByEmail).not.toHaveBeenCalled(); expect(mocks.user.create).not.toHaveBeenCalled(); }); for (const url of [ - 'app.immich:/', - 'app.immich://', - 'app.immich:///', 'app.immich:/oauth-callback?code=abc123', 'app.immich://oauth-callback?code=abc123', 'app.immich:///oauth-callback?code=abc123', @@ -615,9 +624,14 @@ describe(AuthService.name, () => { mocks.user.getByOAuthId.mockResolvedValue(user); mocks.session.create.mockResolvedValue(factory.session()); - await sut.callback({ url }, loginDetails); + await sut.callback({ url, state: 'xyz789', codeVerifier: 'foo' }, {}, loginDetails); - expect(mocks.oauth.getProfile).toHaveBeenCalledWith(expect.objectContaining({}), url, 'http://mobile-redirect'); + expect(mocks.oauth.getProfile).toHaveBeenCalledWith( + expect.objectContaining({}), + 'http://mobile-redirect?code=abc123', + 'xyz789', + 'foo', + ); }); } @@ -630,9 +644,13 @@ describe(AuthService.name, () => { mocks.user.create.mockResolvedValue(user); mocks.session.create.mockResolvedValue(factory.session()); - await expect(sut.callback({ url: 'http://immich/auth/login?code=abc123' }, loginDetails)).resolves.toEqual( - oauthResponse(user), - ); + await expect( + sut.callback( + { url: 'http://immich/auth/login?code=abc123', state: 'xyz789', codeVerifier: 'foo' }, + {}, + loginDetails, + ), + ).resolves.toEqual(oauthResponse(user)); expect(mocks.user.create).toHaveBeenCalledWith(expect.objectContaining({ quotaSizeInBytes: 1_073_741_824 })); }); @@ -647,9 +665,13 @@ describe(AuthService.name, () => { mocks.user.create.mockResolvedValue(user); mocks.session.create.mockResolvedValue(factory.session()); - await expect(sut.callback({ url: 'http://immich/auth/login?code=abc123' }, loginDetails)).resolves.toEqual( - oauthResponse(user), - ); + await expect( + sut.callback( + { url: 'http://immich/auth/login?code=abc123', state: 'xyz789', codeVerifier: 'foo' }, + {}, + loginDetails, + ), + ).resolves.toEqual(oauthResponse(user)); expect(mocks.user.create).toHaveBeenCalledWith(expect.objectContaining({ quotaSizeInBytes: 1_073_741_824 })); }); @@ -664,9 +686,13 @@ describe(AuthService.name, () => { mocks.user.create.mockResolvedValue(user); mocks.session.create.mockResolvedValue(factory.session()); - await expect(sut.callback({ url: 'http://immich/auth/login?code=abc123' }, loginDetails)).resolves.toEqual( - oauthResponse(user), - ); + await expect( + sut.callback( + { url: 'http://immich/auth/login?code=abc123', state: 'xyz789', codeVerifier: 'foo' }, + {}, + loginDetails, + ), + ).resolves.toEqual(oauthResponse(user)); expect(mocks.user.create).toHaveBeenCalledWith(expect.objectContaining({ quotaSizeInBytes: 1_073_741_824 })); }); @@ -681,9 +707,13 @@ describe(AuthService.name, () => { mocks.user.create.mockResolvedValue(user); mocks.session.create.mockResolvedValue(factory.session()); - await expect(sut.callback({ url: 'http://immich/auth/login?code=abc123' }, loginDetails)).resolves.toEqual( - oauthResponse(user), - ); + await expect( + sut.callback( + { url: 'http://immich/auth/login?code=abc123', state: 'xyz789', codeVerifier: 'foo' }, + {}, + loginDetails, + ), + ).resolves.toEqual(oauthResponse(user)); expect(mocks.user.create).toHaveBeenCalledWith({ email: user.email, @@ -705,9 +735,13 @@ describe(AuthService.name, () => { mocks.user.create.mockResolvedValue(user); mocks.session.create.mockResolvedValue(factory.session()); - await expect(sut.callback({ url: 'http://immich/auth/login?code=abc123' }, loginDetails)).resolves.toEqual( - oauthResponse(user), - ); + await expect( + sut.callback( + { url: 'http://immich/auth/login?code=abc123', state: 'xyz789', codeVerifier: 'foo' }, + {}, + loginDetails, + ), + ).resolves.toEqual(oauthResponse(user)); expect(mocks.user.create).toHaveBeenCalledWith({ email: user.email, @@ -738,9 +772,13 @@ describe(AuthService.name, () => { mocks.user.update.mockResolvedValue(user); mocks.session.create.mockResolvedValue(factory.session()); - await expect(sut.callback({ url: 'http://immich/auth/login?code=abc123' }, loginDetails)).resolves.toEqual( - oauthResponse(user), - ); + await expect( + sut.callback( + { url: 'http://immich/auth/login?code=abc123', state: 'xyz789', codeVerifier: 'foo' }, + {}, + loginDetails, + ), + ).resolves.toEqual(oauthResponse(user)); expect(mocks.user.update).toHaveBeenCalledWith(user.id, { profileImagePath: `upload/profile/${user.id}/${fileId}.jpg`, @@ -762,9 +800,13 @@ describe(AuthService.name, () => { mocks.user.update.mockResolvedValue(user); mocks.session.create.mockResolvedValue(factory.session()); - await expect(sut.callback({ url: 'http://immich/auth/login?code=abc123' }, loginDetails)).resolves.toEqual( - oauthResponse(user), - ); + await expect( + sut.callback( + { url: 'http://immich/auth/login?code=abc123', state: 'xyz789', codeVerifier: 'foo' }, + {}, + loginDetails, + ), + ).resolves.toEqual(oauthResponse(user)); expect(mocks.user.update).not.toHaveBeenCalled(); expect(mocks.oauth.getProfilePicture).not.toHaveBeenCalled(); @@ -779,7 +821,11 @@ describe(AuthService.name, () => { mocks.systemMetadata.get.mockResolvedValue(systemConfigStub.enabled); mocks.user.update.mockResolvedValue(user); - await sut.link(auth, { url: 'http://immich/user-settings?code=abc123' }); + await sut.link( + auth, + { url: 'http://immich/user-settings?code=abc123', state: 'xyz789', codeVerifier: 'foo' }, + {}, + ); expect(mocks.user.update).toHaveBeenCalledWith(auth.user.id, { oauthId: sub }); }); @@ -792,9 +838,9 @@ describe(AuthService.name, () => { mocks.systemMetadata.get.mockResolvedValue(systemConfigStub.enabled); mocks.user.getByOAuthId.mockResolvedValue({ id: 'other-user' } as UserAdmin); - await expect(sut.link(auth, { url: 'http://immich/user-settings?code=abc123' })).rejects.toBeInstanceOf( - BadRequestException, - ); + await expect( + sut.link(auth, { url: 'http://immich/user-settings?code=abc123', state: 'xyz789', codeVerifier: 'foo' }, {}), + ).rejects.toBeInstanceOf(BadRequestException); expect(mocks.user.update).not.toHaveBeenCalled(); }); diff --git a/server/src/services/auth.service.ts b/server/src/services/auth.service.ts index ee4ca4dc5d..b250b63a5e 100644 --- a/server/src/services/auth.service.ts +++ b/server/src/services/auth.service.ts @@ -7,13 +7,11 @@ import { join } from 'node:path'; import { LOGIN_URL, MOBILE_REDIRECT, SALT_ROUNDS } from 'src/constants'; import { StorageCore } from 'src/cores/storage.core'; import { UserAdmin } from 'src/database'; -import { OnEvent } from 'src/decorators'; import { AuthDto, ChangePasswordDto, LoginCredentialDto, LogoutResponseDto, - OAuthAuthorizeResponseDto, OAuthCallbackDto, OAuthConfigDto, SignUpDto, @@ -52,11 +50,6 @@ export type ValidateRequest = { @Injectable() export class AuthService extends BaseService { - @OnEvent({ name: 'app.bootstrap' }) - onBootstrap() { - this.oauthRepository.init(); - } - async login(dto: LoginCredentialDto, details: LoginDetails) { const config = await this.getConfig({ withCache: false }); if (!config.passwordLogin.enabled) { @@ -176,20 +169,35 @@ export class AuthService extends BaseService { return `${MOBILE_REDIRECT}?${url.split('?')[1] || ''}`; } - async authorize(dto: OAuthConfigDto): Promise { + async authorize(dto: OAuthConfigDto) { const { oauth } = await this.getConfig({ withCache: false }); if (!oauth.enabled) { throw new BadRequestException('OAuth is not enabled'); } - const url = await this.oauthRepository.authorize(oauth, this.resolveRedirectUri(oauth, dto.redirectUri)); - return { url }; + return await this.oauthRepository.authorize( + oauth, + this.resolveRedirectUri(oauth, dto.redirectUri), + dto.state, + dto.codeChallenge, + ); } - async callback(dto: OAuthCallbackDto, loginDetails: LoginDetails) { + async callback(dto: OAuthCallbackDto, headers: IncomingHttpHeaders, loginDetails: LoginDetails) { + const expectedState = dto.state ?? this.getCookieOauthState(headers); + if (!expectedState?.length) { + throw new BadRequestException('OAuth state is missing'); + } + + const codeVerifier = dto.codeVerifier ?? this.getCookieCodeVerifier(headers); + if (!codeVerifier?.length) { + throw new BadRequestException('OAuth code verifier is missing'); + } + const { oauth } = await this.getConfig({ withCache: false }); - const profile = await this.oauthRepository.getProfile(oauth, dto.url, this.resolveRedirectUri(oauth, dto.url)); + const url = this.resolveRedirectUri(oauth, dto.url); + const profile = await this.oauthRepository.getProfile(oauth, url, expectedState, codeVerifier); const { autoRegister, defaultStorageQuota, storageLabelClaim, storageQuotaClaim } = oauth; this.logger.debug(`Logging in with OAuth: ${JSON.stringify(profile)}`); let user: UserAdmin | undefined = await this.userRepository.getByOAuthId(profile.sub); @@ -271,13 +279,19 @@ export class AuthService extends BaseService { } } - async link(auth: AuthDto, dto: OAuthCallbackDto): Promise { + async link(auth: AuthDto, dto: OAuthCallbackDto, headers: IncomingHttpHeaders): Promise { + const expectedState = dto.state ?? this.getCookieOauthState(headers); + if (!expectedState?.length) { + throw new BadRequestException('OAuth state is missing'); + } + + const codeVerifier = dto.codeVerifier ?? this.getCookieCodeVerifier(headers); + if (!codeVerifier?.length) { + throw new BadRequestException('OAuth code verifier is missing'); + } + const { oauth } = await this.getConfig({ withCache: false }); - const { sub: oauthId } = await this.oauthRepository.getProfile( - oauth, - dto.url, - this.resolveRedirectUri(oauth, dto.url), - ); + const { sub: oauthId } = await this.oauthRepository.getProfile(oauth, dto.url, expectedState, codeVerifier); const duplicate = await this.userRepository.getByOAuthId(oauthId); if (duplicate && duplicate.id !== auth.user.id) { this.logger.warn(`OAuth link account failed: sub is already linked to another user (${duplicate.email}).`); @@ -320,6 +334,16 @@ export class AuthService extends BaseService { return cookies[ImmichCookie.ACCESS_TOKEN] || null; } + private getCookieOauthState(headers: IncomingHttpHeaders): string | null { + const cookies = parse(headers.cookie || ''); + return cookies[ImmichCookie.OAUTH_STATE] || null; + } + + private getCookieCodeVerifier(headers: IncomingHttpHeaders): string | null { + const cookies = parse(headers.cookie || ''); + return cookies[ImmichCookie.OAUTH_CODE_VERIFIER] || null; + } + async validateSharedLink(key: string | string[]): Promise { key = Array.isArray(key) ? key[0] : key; @@ -399,11 +423,9 @@ export class AuthService extends BaseService { { mobileRedirectUri, mobileOverrideEnabled }: { mobileRedirectUri: string; mobileOverrideEnabled: boolean }, url: string, ) { - const redirectUri = url.split('?')[0]; - const isMobile = redirectUri.startsWith('app.immich:/'); - if (isMobile && mobileOverrideEnabled && mobileRedirectUri) { - return mobileRedirectUri; + if (mobileOverrideEnabled && mobileRedirectUri) { + return url.replace(/app\.immich:\/+oauth-callback/, mobileRedirectUri); } - return redirectUri; + return url; } } diff --git a/server/src/services/backup.service.spec.ts b/server/src/services/backup.service.spec.ts index 704087ab05..aa72fd588a 100644 --- a/server/src/services/backup.service.spec.ts +++ b/server/src/services/backup.service.spec.ts @@ -142,52 +142,55 @@ describe(BackupService.name, () => { mocks.systemMetadata.get.mockResolvedValue(systemConfigStub.backupEnabled); mocks.storage.createWriteStream.mockReturnValue(new PassThrough()); }); + it('should run a database backup successfully', async () => { const result = await sut.handleBackupDatabase(); expect(result).toBe(JobStatus.SUCCESS); expect(mocks.storage.createWriteStream).toHaveBeenCalled(); }); + it('should rename file on success', async () => { const result = await sut.handleBackupDatabase(); expect(result).toBe(JobStatus.SUCCESS); expect(mocks.storage.rename).toHaveBeenCalled(); }); + it('should fail if pg_dumpall fails', async () => { mocks.process.spawn.mockReturnValueOnce(mockSpawn(1, '', 'error')); - const result = await sut.handleBackupDatabase(); - expect(result).toBe(JobStatus.FAILED); + await expect(sut.handleBackupDatabase()).rejects.toThrow('Backup failed with code 1'); }); + it('should not rename file if pgdump fails and gzip succeeds', async () => { mocks.process.spawn.mockReturnValueOnce(mockSpawn(1, '', 'error')); - const result = await sut.handleBackupDatabase(); - expect(result).toBe(JobStatus.FAILED); + await expect(sut.handleBackupDatabase()).rejects.toThrow('Backup failed with code 1'); expect(mocks.storage.rename).not.toHaveBeenCalled(); }); + it('should fail if gzip fails', async () => { mocks.process.spawn.mockReturnValueOnce(mockSpawn(0, 'data', '')); mocks.process.spawn.mockReturnValueOnce(mockSpawn(1, '', 'error')); - const result = await sut.handleBackupDatabase(); - expect(result).toBe(JobStatus.FAILED); + await expect(sut.handleBackupDatabase()).rejects.toThrow('Gzip failed with code 1'); }); + it('should fail if write stream fails', async () => { mocks.storage.createWriteStream.mockImplementation(() => { throw new Error('error'); }); - const result = await sut.handleBackupDatabase(); - expect(result).toBe(JobStatus.FAILED); + await expect(sut.handleBackupDatabase()).rejects.toThrow('error'); }); + it('should fail if rename fails', async () => { mocks.storage.rename.mockRejectedValue(new Error('error')); - const result = await sut.handleBackupDatabase(); - expect(result).toBe(JobStatus.FAILED); + await expect(sut.handleBackupDatabase()).rejects.toThrow('error'); }); + it('should ignore unlink failing and still return failed job status', async () => { mocks.process.spawn.mockReturnValueOnce(mockSpawn(1, '', 'error')); mocks.storage.unlink.mockRejectedValue(new Error('error')); - const result = await sut.handleBackupDatabase(); + await expect(sut.handleBackupDatabase()).rejects.toThrow('Backup failed with code 1'); expect(mocks.storage.unlink).toHaveBeenCalled(); - expect(result).toBe(JobStatus.FAILED); }); + it.each` postgresVersion | expectedVersion ${'14.10'} | ${14} diff --git a/server/src/services/backup.service.ts b/server/src/services/backup.service.ts index dc4f71b992..10f7becc7d 100644 --- a/server/src/services/backup.service.ts +++ b/server/src/services/backup.service.ts @@ -70,7 +70,7 @@ export class BackupService extends BaseService { async handleBackupDatabase(): Promise { this.logger.debug(`Database Backup Started`); const { database } = this.configRepository.getEnv(); - const config = database.config.typeorm; + const config = database.config; const isUrlConnection = config.connectionType === 'url'; @@ -174,7 +174,7 @@ export class BackupService extends BaseService { await this.storageRepository .unlink(backupFilePath) .catch((error) => this.logger.error('Failed to delete failed backup file', error)); - return JobStatus.FAILED; + throw error; } this.logger.log(`Database Backup Success`); diff --git a/server/src/services/base.service.ts b/server/src/services/base.service.ts index 2fbdd6e4c0..3381ad7222 100644 --- a/server/src/services/base.service.ts +++ b/server/src/services/base.service.ts @@ -18,6 +18,7 @@ import { CronRepository } from 'src/repositories/cron.repository'; import { CryptoRepository } from 'src/repositories/crypto.repository'; import { DatabaseRepository } from 'src/repositories/database.repository'; import { DownloadRepository } from 'src/repositories/download.repository'; +import { EmailRepository } from 'src/repositories/email.repository'; import { EventRepository } from 'src/repositories/event.repository'; import { JobRepository } from 'src/repositories/job.repository'; import { LibraryRepository } from 'src/repositories/library.repository'; @@ -70,6 +71,7 @@ export class BaseService { protected cryptoRepository: CryptoRepository, protected databaseRepository: DatabaseRepository, protected downloadRepository: DownloadRepository, + protected emailRepository: EmailRepository, protected eventRepository: EventRepository, protected jobRepository: JobRepository, protected libraryRepository: LibraryRepository, diff --git a/server/src/services/database.service.spec.ts b/server/src/services/database.service.spec.ts index 4e45ec3ae0..e0ab4a624d 100644 --- a/server/src/services/database.service.spec.ts +++ b/server/src/services/database.service.spec.ts @@ -53,22 +53,12 @@ describe(DatabaseService.name, () => { mockEnvData({ database: { config: { - kysely: { - host: 'database', - port: 5432, - user: 'postgres', - password: 'postgres', - database: 'immich', - }, - typeorm: { - connectionType: 'parts', - type: 'postgres', - host: 'database', - port: 5432, - username: 'postgres', - password: 'postgres', - database: 'immich', - }, + connectionType: 'parts', + host: 'database', + port: 5432, + username: 'postgres', + password: 'postgres', + database: 'immich', }, skipMigrations: false, vectorExtension: extension, @@ -292,22 +282,12 @@ describe(DatabaseService.name, () => { mockEnvData({ database: { config: { - kysely: { - host: 'database', - port: 5432, - user: 'postgres', - password: 'postgres', - database: 'immich', - }, - typeorm: { - connectionType: 'parts', - type: 'postgres', - host: 'database', - port: 5432, - username: 'postgres', - password: 'postgres', - database: 'immich', - }, + connectionType: 'parts', + host: 'database', + port: 5432, + username: 'postgres', + password: 'postgres', + database: 'immich', }, skipMigrations: true, vectorExtension: DatabaseExtension.VECTORS, @@ -325,22 +305,12 @@ describe(DatabaseService.name, () => { mockEnvData({ database: { config: { - kysely: { - host: 'database', - port: 5432, - user: 'postgres', - password: 'postgres', - database: 'immich', - }, - typeorm: { - connectionType: 'parts', - type: 'postgres', - host: 'database', - port: 5432, - username: 'postgres', - password: 'postgres', - database: 'immich', - }, + connectionType: 'parts', + host: 'database', + port: 5432, + username: 'postgres', + password: 'postgres', + database: 'immich', }, skipMigrations: true, vectorExtension: DatabaseExtension.VECTOR, diff --git a/server/src/services/download.service.ts b/server/src/services/download.service.ts index cb664aea32..02711b9bfd 100644 --- a/server/src/services/download.service.ts +++ b/server/src/services/download.service.ts @@ -33,7 +33,7 @@ export class DownloadService extends BaseService { const targetSize = dto.archiveSize || HumanReadableSize.GiB * 4; const metadata = await this.userRepository.getMetadata(auth.user.id); - const preferences = getPreferences(auth.user.email, metadata); + const preferences = getPreferences(metadata); const motionIds = new Set(); const archives: DownloadArchiveInfo[] = []; let archive: DownloadArchiveInfo = { size: 0, assetIds: [] }; diff --git a/server/src/services/duplicate.service.spec.ts b/server/src/services/duplicate.service.spec.ts index 57ab955514..ed8f2cf177 100644 --- a/server/src/services/duplicate.service.spec.ts +++ b/server/src/services/duplicate.service.spec.ts @@ -1,10 +1,9 @@ import { AssetFileType, AssetType, JobName, JobStatus } from 'src/enum'; -import { WithoutProperty } from 'src/repositories/asset.repository'; import { DuplicateService } from 'src/services/duplicate.service'; import { SearchService } from 'src/services/search.service'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; -import { newTestService, ServiceMocks } from 'test/utils'; +import { makeStream, newTestService, ServiceMocks } from 'test/utils'; import { beforeEach, vitest } from 'vitest'; vitest.useFakeTimers(); @@ -113,14 +112,11 @@ describe(SearchService.name, () => { }); it('should queue missing assets', async () => { - mocks.asset.getWithout.mockResolvedValue({ - items: [assetStub.image], - hasNextPage: false, - }); + mocks.assetJob.streamForSearchDuplicates.mockReturnValue(makeStream([assetStub.image])); await sut.handleQueueSearchDuplicates({}); - expect(mocks.asset.getWithout).toHaveBeenCalledWith({ skip: 0, take: 1000 }, WithoutProperty.DUPLICATE); + expect(mocks.assetJob.streamForSearchDuplicates).toHaveBeenCalledWith(undefined); expect(mocks.job.queueAll).toHaveBeenCalledWith([ { name: JobName.DUPLICATE_DETECTION, @@ -130,14 +126,11 @@ describe(SearchService.name, () => { }); it('should queue all assets', async () => { - mocks.asset.getAll.mockResolvedValue({ - items: [assetStub.image], - hasNextPage: false, - }); + mocks.assetJob.streamForSearchDuplicates.mockReturnValue(makeStream([assetStub.image])); await sut.handleQueueSearchDuplicates({ force: true }); - expect(mocks.asset.getAll).toHaveBeenCalled(); + expect(mocks.assetJob.streamForSearchDuplicates).toHaveBeenCalledWith(true); expect(mocks.job.queueAll).toHaveBeenCalledWith([ { name: JobName.DUPLICATE_DETECTION, diff --git a/server/src/services/duplicate.service.ts b/server/src/services/duplicate.service.ts index c504b1a305..41e3f13c4d 100644 --- a/server/src/services/duplicate.service.ts +++ b/server/src/services/duplicate.service.ts @@ -5,13 +5,11 @@ import { mapAsset } from 'src/dtos/asset-response.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { DuplicateResponseDto } from 'src/dtos/duplicate.dto'; import { AssetFileType, JobName, JobStatus, QueueName } from 'src/enum'; -import { WithoutProperty } from 'src/repositories/asset.repository'; import { AssetDuplicateResult } from 'src/repositories/search.repository'; import { BaseService } from 'src/services/base.service'; -import { JobOf } from 'src/types'; +import { JobItem, JobOf } from 'src/types'; import { getAssetFile } from 'src/utils/asset.util'; import { isDuplicateDetectionEnabled } from 'src/utils/misc'; -import { usePagination } from 'src/utils/pagination'; @Injectable() export class DuplicateService extends BaseService { @@ -30,18 +28,22 @@ export class DuplicateService extends BaseService { return JobStatus.SKIPPED; } - const assetPagination = usePagination(JOBS_ASSET_PAGINATION_SIZE, (pagination) => { - return force - ? this.assetRepository.getAll(pagination, { isVisible: true }) - : this.assetRepository.getWithout(pagination, WithoutProperty.DUPLICATE); - }); + let jobs: JobItem[] = []; + const queueAll = async () => { + await this.jobRepository.queueAll(jobs); + jobs = []; + }; - for await (const assets of assetPagination) { - await this.jobRepository.queueAll( - assets.map((asset) => ({ name: JobName.DUPLICATE_DETECTION, data: { id: asset.id } })), - ); + const assets = this.assetJobRepository.streamForSearchDuplicates(force); + for await (const asset of assets) { + jobs.push({ name: JobName.DUPLICATE_DETECTION, data: { id: asset.id } }); + if (jobs.length >= JOBS_ASSET_PAGINATION_SIZE) { + await queueAll(); + } } + await queueAll(); + return JobStatus.SUCCESS; } diff --git a/server/src/services/index.ts b/server/src/services/index.ts index b214dd14f6..88b68d2c13 100644 --- a/server/src/services/index.ts +++ b/server/src/services/index.ts @@ -17,6 +17,7 @@ import { MapService } from 'src/services/map.service'; import { MediaService } from 'src/services/media.service'; import { MemoryService } from 'src/services/memory.service'; import { MetadataService } from 'src/services/metadata.service'; +import { NotificationAdminService } from 'src/services/notification-admin.service'; import { NotificationService } from 'src/services/notification.service'; import { PartnerService } from 'src/services/partner.service'; import { PersonService } from 'src/services/person.service'; @@ -60,6 +61,7 @@ export const services = [ MemoryService, MetadataService, NotificationService, + NotificationAdminService, PartnerService, PersonService, SearchService, diff --git a/server/src/services/job.service.spec.ts b/server/src/services/job.service.spec.ts index baac0af428..9acc81ceb7 100644 --- a/server/src/services/job.service.spec.ts +++ b/server/src/services/job.service.spec.ts @@ -230,7 +230,7 @@ describe(JobService.name, () => { expect(mocks.logger.error).not.toHaveBeenCalled(); }); - const tests: Array<{ item: JobItem; jobs: JobName[] }> = [ + const tests: Array<{ item: JobItem; jobs: JobName[]; stub?: any }> = [ { item: { name: JobName.SIDECAR_SYNC, data: { id: 'asset-1' } }, jobs: [JobName.METADATA_EXTRACTION], @@ -258,14 +258,22 @@ describe(JobService.name, () => { { item: { name: JobName.GENERATE_THUMBNAILS, data: { id: 'asset-1' } }, jobs: [], + stub: [assetStub.image], + }, + { + item: { name: JobName.GENERATE_THUMBNAILS, data: { id: 'asset-1' } }, + jobs: [], + stub: [assetStub.video], + }, + { + item: { name: JobName.GENERATE_THUMBNAILS, data: { id: 'asset-1', source: 'upload' } }, + jobs: [JobName.SMART_SEARCH, JobName.FACE_DETECTION], + stub: [assetStub.livePhotoStillAsset], }, { item: { name: JobName.GENERATE_THUMBNAILS, data: { id: 'asset-1', source: 'upload' } }, jobs: [JobName.SMART_SEARCH, JobName.FACE_DETECTION, JobName.VIDEO_CONVERSION], - }, - { - item: { name: JobName.GENERATE_THUMBNAILS, data: { id: 'asset-live-image', source: 'upload' } }, - jobs: [JobName.SMART_SEARCH, JobName.FACE_DETECTION, JobName.VIDEO_CONVERSION], + stub: [assetStub.video], }, { item: { name: JobName.SMART_SEARCH, data: { id: 'asset-1' } }, @@ -281,14 +289,10 @@ describe(JobService.name, () => { }, ]; - for (const { item, jobs } of tests) { + for (const { item, jobs, stub } of tests) { it(`should queue ${jobs.length} jobs when a ${item.name} job finishes successfully`, async () => { - if (item.name === JobName.GENERATE_THUMBNAILS && item.data.source === 'upload') { - if (item.data.id === 'asset-live-image') { - mocks.asset.getByIdsWithAllRelationsButStacks.mockResolvedValue([assetStub.livePhotoStillAsset as any]); - } else { - mocks.asset.getByIdsWithAllRelationsButStacks.mockResolvedValue([assetStub.livePhotoMotionAsset as any]); - } + if (stub) { + mocks.asset.getByIdsWithAllRelationsButStacks.mockResolvedValue(stub); } mocks.job.run.mockResolvedValue(JobStatus.SUCCESS); diff --git a/server/src/services/job.service.ts b/server/src/services/job.service.ts index edd018d7b1..a387e6e099 100644 --- a/server/src/services/job.service.ts +++ b/server/src/services/job.service.ts @@ -1,10 +1,12 @@ import { BadRequestException, Injectable } from '@nestjs/common'; +import { ClassConstructor } from 'class-transformer'; import { snakeCase } from 'lodash'; import { OnEvent } from 'src/decorators'; import { mapAsset } from 'src/dtos/asset-response.dto'; import { AllJobStatusResponseDto, JobCommandDto, JobCreateDto, JobStatusDto } from 'src/dtos/job.dto'; import { AssetType, + BootstrapEventPriority, ImmichWorker, JobCommand, JobName, @@ -51,6 +53,8 @@ const asJobItem = (dto: JobCreateDto): JobItem => { @Injectable() export class JobService extends BaseService { + private services: ClassConstructor[] = []; + @OnEvent({ name: 'config.init', workers: [ImmichWorker.MICROSERVICES] }) onConfigInit({ newConfig: config }: ArgOf<'config.init'>) { this.logger.debug(`Updating queue concurrency settings`); @@ -69,6 +73,18 @@ export class JobService extends BaseService { this.onConfigInit({ newConfig: config }); } + @OnEvent({ name: 'app.bootstrap', priority: BootstrapEventPriority.JobService }) + onBootstrap() { + this.jobRepository.setup(this.services); + if (this.worker === ImmichWorker.MICROSERVICES) { + this.jobRepository.startWorkers(); + } + } + + setServices(services: ClassConstructor[]) { + this.services = services; + } + async create(dto: JobCreateDto): Promise { await this.jobRepository.queue(asJobItem(dto)); } @@ -199,11 +215,7 @@ export class JobService extends BaseService { await this.onDone(job); } } catch (error: Error | any) { - this.logger.error( - `Unable to run job handler (${queueName}/${job.name}): ${error}`, - error?.stack, - JSON.stringify(job.data), - ); + await this.eventRepository.emit('job.failed', { job, error }); } finally { this.telemetryRepository.jobs.addToGauge(queueMetric, -1); } @@ -297,8 +309,6 @@ export class JobService extends BaseService { if (asset.type === AssetType.VIDEO) { jobs.push({ name: JobName.VIDEO_CONVERSION, data: item.data }); - } else if (asset.livePhotoVideoId) { - jobs.push({ name: JobName.VIDEO_CONVERSION, data: { id: asset.livePhotoVideoId } }); } await this.jobRepository.queueAll(jobs); diff --git a/server/src/services/library.service.spec.ts b/server/src/services/library.service.spec.ts index 15b150f551..6b0817dd3b 100644 --- a/server/src/services/library.service.spec.ts +++ b/server/src/services/library.service.spec.ts @@ -273,7 +273,6 @@ describe(LibraryService.name, () => { mocks.library.get.mockResolvedValue(library); mocks.storage.walk.mockImplementation(async function* generator() {}); - mocks.asset.getAll.mockResolvedValue({ items: [assetStub.external], hasNextPage: false }); mocks.asset.getLibraryAssetCount.mockResolvedValue(1); mocks.asset.detectOfflineExternalAssets.mockResolvedValue({ numUpdatedRows: BigInt(1) }); @@ -292,7 +291,6 @@ describe(LibraryService.name, () => { mocks.library.get.mockResolvedValue(library); mocks.storage.walk.mockImplementation(async function* generator() {}); - mocks.asset.getAll.mockResolvedValue({ items: [assetStub.external], hasNextPage: false }); mocks.asset.getLibraryAssetCount.mockResolvedValue(0); mocks.asset.detectOfflineExternalAssets.mockResolvedValue({ numUpdatedRows: BigInt(1) }); diff --git a/server/src/services/media.service.spec.ts b/server/src/services/media.service.spec.ts index 8990ad86a6..d747ee0ba8 100644 --- a/server/src/services/media.service.spec.ts +++ b/server/src/services/media.service.spec.ts @@ -1,7 +1,6 @@ import { OutputInfo } from 'sharp'; import { SystemConfig } from 'src/config'; import { Exif } from 'src/database'; -import { AssetMediaSize } from 'src/dtos/asset-media.dto'; import { AssetFileType, AssetPathType, @@ -11,11 +10,11 @@ import { ImageFormat, JobName, JobStatus, + RawExtractedFormat, TranscodeHWAccel, TranscodePolicy, VideoCodec, } from 'src/enum'; -import { WithoutProperty } from 'src/repositories/asset.repository'; import { MediaService } from 'src/services/media.service'; import { JobCounts, RawImageInfo } from 'src/types'; import { assetStub } from 'test/fixtures/asset.stub'; @@ -39,10 +38,6 @@ describe(MediaService.name, () => { describe('handleQueueGenerateThumbnails', () => { it('should queue all assets', async () => { mocks.assetJob.streamForThumbnailJob.mockReturnValue(makeStream([assetStub.image])); - mocks.asset.getAll.mockResolvedValue({ - items: [assetStub.image], - hasNextPage: false, - }); mocks.person.getAll.mockReturnValue(makeStream([personStub.newThumbnail])); mocks.person.getFacesByIds.mockResolvedValue([faceStub.face1]); @@ -68,10 +63,6 @@ describe(MediaService.name, () => { it('should queue trashed assets when force is true', async () => { mocks.assetJob.streamForThumbnailJob.mockReturnValue(makeStream([assetStub.archived])); - mocks.asset.getAll.mockResolvedValue({ - items: [assetStub.trashed], - hasNextPage: false, - }); mocks.person.getAll.mockReturnValue(makeStream()); await sut.handleQueueGenerateThumbnails({ force: true }); @@ -172,7 +163,7 @@ describe(MediaService.name, () => { describe('handleQueueMigration', () => { it('should remove empty directories and queue jobs', async () => { - mocks.asset.getAll.mockResolvedValue({ hasNextPage: false, items: [assetStub.image] }); + mocks.assetJob.streamForMigrationJob.mockReturnValue(makeStream([assetStub.image])); mocks.job.getJobCounts.mockResolvedValue({ active: 1, waiting: 0 } as JobCounts); mocks.person.getAll.mockReturnValue(makeStream([personStub.withName])); @@ -232,17 +223,19 @@ describe(MediaService.name, () => { describe('handleGenerateThumbnails', () => { let rawBuffer: Buffer; let fullsizeBuffer: Buffer; + let extractedBuffer: Buffer; let rawInfo: RawImageInfo; beforeEach(() => { fullsizeBuffer = Buffer.from('embedded image data'); - rawBuffer = Buffer.from('image data'); + rawBuffer = Buffer.from('raw image data'); + extractedBuffer = Buffer.from('embedded image file'); rawInfo = { width: 100, height: 100, channels: 3 }; - mocks.media.decodeImage.mockImplementation((path) => + mocks.media.decodeImage.mockImplementation((input) => Promise.resolve( - path.includes(AssetMediaSize.FULLSIZE) - ? { data: fullsizeBuffer, info: rawInfo as OutputInfo } - : { data: rawBuffer, info: rawInfo as OutputInfo }, + typeof input === 'string' + ? { data: rawBuffer, info: rawInfo as OutputInfo } // string implies original file + : { data: fullsizeBuffer, info: rawInfo as OutputInfo }, // buffer implies embedded image extracted ), ); }); @@ -585,16 +578,15 @@ describe(MediaService.name, () => { }); it('should extract embedded image if enabled and available', async () => { - mocks.media.extract.mockResolvedValue(true); + mocks.media.extract.mockResolvedValue({ buffer: extractedBuffer, format: RawExtractedFormat.JPEG }); mocks.media.getImageDimensions.mockResolvedValue({ width: 3840, height: 2160 }); mocks.systemMetadata.get.mockResolvedValue({ image: { extractEmbedded: true } }); mocks.assetJob.getForGenerateThumbnailJob.mockResolvedValue(assetStub.imageDng); await sut.handleGenerateThumbnails({ id: assetStub.image.id }); - const convertedPath = mocks.media.extract.mock.lastCall?.[1].toString(); expect(mocks.media.decodeImage).toHaveBeenCalledOnce(); - expect(mocks.media.decodeImage).toHaveBeenCalledWith(convertedPath, { + expect(mocks.media.decodeImage).toHaveBeenCalledWith(extractedBuffer, { colorspace: Colorspace.P3, processInvalidImages: false, size: 1440, @@ -602,16 +594,13 @@ describe(MediaService.name, () => { }); it('should resize original image if embedded image is too small', async () => { - mocks.media.extract.mockResolvedValue(true); + mocks.media.extract.mockResolvedValue({ buffer: extractedBuffer, format: RawExtractedFormat.JPEG }); mocks.media.getImageDimensions.mockResolvedValue({ width: 1000, height: 1000 }); mocks.systemMetadata.get.mockResolvedValue({ image: { extractEmbedded: true } }); mocks.assetJob.getForGenerateThumbnailJob.mockResolvedValue(assetStub.imageDng); await sut.handleGenerateThumbnails({ id: assetStub.image.id }); - const extractedPath = mocks.media.extract.mock.lastCall?.[1].toString(); - expect(extractedPath).toMatch(/-fullsize\.jpeg$/); - expect(mocks.media.decodeImage).toHaveBeenCalledWith(assetStub.imageDng.originalPath, { colorspace: Colorspace.P3, processInvalidImages: false, @@ -666,38 +655,40 @@ describe(MediaService.name, () => { expect(mocks.media.generateThumbnail).toHaveBeenCalledTimes(2); expect(mocks.media.generateThumbnail).toHaveBeenCalledWith( rawBuffer, - expect.objectContaining({ processInvalidImages: true }), + expect.objectContaining({ processInvalidImages: false }), 'upload/thumbs/user-id/as/se/asset-id-preview.jpeg', ); expect(mocks.media.generateThumbnail).toHaveBeenCalledWith( rawBuffer, - expect.objectContaining({ processInvalidImages: true }), + expect.objectContaining({ processInvalidImages: false }), 'upload/thumbs/user-id/as/se/asset-id-thumbnail.webp', ); expect(mocks.media.generateThumbhash).toHaveBeenCalledOnce(); expect(mocks.media.generateThumbhash).toHaveBeenCalledWith( rawBuffer, - expect.objectContaining({ processInvalidImages: true }), + expect.objectContaining({ processInvalidImages: false }), ); expect(mocks.media.getImageDimensions).not.toHaveBeenCalled(); vi.unstubAllEnvs(); }); - it('should generate full-size preview using embedded JPEG from RAW images when extractEmbedded is true', async () => { - mocks.systemMetadata.get.mockResolvedValue({ image: { fullsize: { enabled: true }, extractEmbedded: true } }); - mocks.media.extract.mockResolvedValue(true); + it('should extract full-size JPEG preview from RAW', async () => { + mocks.systemMetadata.get.mockResolvedValue({ + image: { fullsize: { enabled: true, format: ImageFormat.WEBP }, extractEmbedded: true }, + }); + mocks.media.extract.mockResolvedValue({ buffer: extractedBuffer, format: RawExtractedFormat.JPEG }); mocks.media.getImageDimensions.mockResolvedValue({ width: 3840, height: 2160 }); mocks.assetJob.getForGenerateThumbnailJob.mockResolvedValue(assetStub.imageDng); await sut.handleGenerateThumbnails({ id: assetStub.image.id }); - const extractedPath = mocks.media.extract.mock.lastCall?.[1].toString(); expect(mocks.media.decodeImage).toHaveBeenCalledOnce(); - expect(mocks.media.decodeImage).toHaveBeenCalledWith(extractedPath, { + expect(mocks.media.decodeImage).toHaveBeenCalledWith(extractedBuffer, { colorspace: Colorspace.P3, processInvalidImages: false, + size: 1440, // capped to preview size as fullsize conversion is skipped }); expect(mocks.media.generateThumbnail).toHaveBeenCalledTimes(2); @@ -715,9 +706,51 @@ describe(MediaService.name, () => { ); }); + it('should convert full-size WEBP preview from JXL preview of RAW', async () => { + mocks.systemMetadata.get.mockResolvedValue({ + image: { fullsize: { enabled: true, format: ImageFormat.WEBP }, extractEmbedded: true }, + }); + mocks.media.extract.mockResolvedValue({ buffer: extractedBuffer, format: RawExtractedFormat.JXL }); + mocks.media.getImageDimensions.mockResolvedValue({ width: 3840, height: 2160 }); + mocks.assetJob.getForGenerateThumbnailJob.mockResolvedValue(assetStub.imageDng); + + await sut.handleGenerateThumbnails({ id: assetStub.image.id }); + + expect(mocks.media.decodeImage).toHaveBeenCalledOnce(); + expect(mocks.media.decodeImage).toHaveBeenCalledWith(extractedBuffer, { + colorspace: Colorspace.P3, + processInvalidImages: false, + }); + + expect(mocks.media.generateThumbnail).toHaveBeenCalledTimes(3); + expect(mocks.media.generateThumbnail).toHaveBeenCalledWith( + fullsizeBuffer, + { + colorspace: Colorspace.P3, + format: ImageFormat.WEBP, + quality: 80, + processInvalidImages: false, + raw: rawInfo, + }, + 'upload/thumbs/user-id/as/se/asset-id-fullsize.webp', + ); + expect(mocks.media.generateThumbnail).toHaveBeenCalledWith( + fullsizeBuffer, + { + colorspace: Colorspace.P3, + format: ImageFormat.JPEG, + size: 1440, + quality: 80, + processInvalidImages: false, + raw: rawInfo, + }, + 'upload/thumbs/user-id/as/se/asset-id-preview.jpeg', + ); + }); + it('should generate full-size preview directly from RAW images when extractEmbedded is false', async () => { mocks.systemMetadata.get.mockResolvedValue({ image: { fullsize: { enabled: true }, extractEmbedded: false } }); - mocks.media.extract.mockResolvedValue(true); + mocks.media.extract.mockResolvedValue({ buffer: extractedBuffer, format: RawExtractedFormat.JPEG }); mocks.media.getImageDimensions.mockResolvedValue({ width: 3840, height: 2160 }); mocks.assetJob.getForGenerateThumbnailJob.mockResolvedValue(assetStub.imageDng); @@ -757,7 +790,7 @@ describe(MediaService.name, () => { it('should generate full-size preview from non-web-friendly images', async () => { mocks.systemMetadata.get.mockResolvedValue({ image: { fullsize: { enabled: true } } }); - mocks.media.extract.mockResolvedValue(true); + mocks.media.extract.mockResolvedValue({ buffer: extractedBuffer, format: RawExtractedFormat.JPEG }); mocks.media.getImageDimensions.mockResolvedValue({ width: 3840, height: 2160 }); // HEIF/HIF image taken by cameras are not web-friendly, only has limited support on Safari. mocks.assetJob.getForGenerateThumbnailJob.mockResolvedValue(assetStub.imageHif); @@ -786,7 +819,7 @@ describe(MediaService.name, () => { it('should skip generating full-size preview for web-friendly images', async () => { mocks.systemMetadata.get.mockResolvedValue({ image: { fullsize: { enabled: true } } }); - mocks.media.extract.mockResolvedValue(true); + mocks.media.extract.mockResolvedValue({ buffer: extractedBuffer, format: RawExtractedFormat.JPEG }); mocks.media.getImageDimensions.mockResolvedValue({ width: 3840, height: 2160 }); mocks.assetJob.getForGenerateThumbnailJob.mockResolvedValue(assetStub.image); @@ -811,7 +844,7 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ image: { fullsize: { enabled: true, format: ImageFormat.WEBP, quality: 90 } }, }); - mocks.media.extract.mockResolvedValue(true); + mocks.media.extract.mockResolvedValue({ buffer: extractedBuffer, format: RawExtractedFormat.JPEG }); mocks.media.getImageDimensions.mockResolvedValue({ width: 3840, height: 2160 }); // HEIF/HIF image taken by cameras are not web-friendly, only has limited support on Safari. mocks.assetJob.getForGenerateThumbnailJob.mockResolvedValue(assetStub.imageHif); @@ -841,16 +874,12 @@ describe(MediaService.name, () => { describe('handleQueueVideoConversion', () => { it('should queue all video assets', async () => { - mocks.asset.getAll.mockResolvedValue({ - items: [assetStub.video], - hasNextPage: false, - }); + mocks.assetJob.streamForVideoConversion.mockReturnValue(makeStream([assetStub.video])); mocks.person.getAll.mockReturnValue(makeStream()); await sut.handleQueueVideoConversion({ force: true }); - expect(mocks.asset.getAll).toHaveBeenCalledWith({ skip: 0, take: 1000 }, { type: AssetType.VIDEO }); - expect(mocks.asset.getWithout).not.toHaveBeenCalled(); + expect(mocks.assetJob.streamForVideoConversion).toHaveBeenCalledWith(true); expect(mocks.job.queueAll).toHaveBeenCalledWith([ { name: JobName.VIDEO_CONVERSION, @@ -860,15 +889,11 @@ describe(MediaService.name, () => { }); it('should queue all video assets without encoded videos', async () => { - mocks.asset.getWithout.mockResolvedValue({ - items: [assetStub.video], - hasNextPage: false, - }); + mocks.assetJob.streamForVideoConversion.mockReturnValue(makeStream([assetStub.video])); await sut.handleQueueVideoConversion({}); - expect(mocks.asset.getAll).not.toHaveBeenCalled(); - expect(mocks.asset.getWithout).toHaveBeenCalledWith({ skip: 0, take: 1000 }, WithoutProperty.ENCODED_VIDEO); + expect(mocks.assetJob.streamForVideoConversion).toHaveBeenCalledWith(void 0); expect(mocks.job.queueAll).toHaveBeenCalledWith([ { name: JobName.VIDEO_CONVERSION, @@ -880,26 +905,18 @@ describe(MediaService.name, () => { describe('handleVideoConversion', () => { beforeEach(() => { - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); + mocks.assetJob.getForVideoConversion.mockResolvedValue(assetStub.video); sut.videoInterfaces = { dri: ['renderD128'], mali: true }; }); it('should skip transcoding if asset not found', async () => { - mocks.asset.getByIds.mockResolvedValue([]); + mocks.assetJob.getForVideoConversion.mockResolvedValue(void 0); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.probe).not.toHaveBeenCalled(); expect(mocks.media.transcode).not.toHaveBeenCalled(); }); - it('should skip transcoding if non-video asset', async () => { - mocks.asset.getByIds.mockResolvedValue([assetStub.image]); - await sut.handleVideoConversion({ id: assetStub.image.id }); - expect(mocks.media.probe).not.toHaveBeenCalled(); - expect(mocks.media.transcode).not.toHaveBeenCalled(); - }); - it('should transcode the longest stream', async () => { - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); mocks.logger.isLevelEnabled.mockReturnValue(false); mocks.media.probe.mockResolvedValue(probeStub.multipleVideoStreams); @@ -921,14 +938,12 @@ describe(MediaService.name, () => { it('should skip a video without any streams', async () => { mocks.media.probe.mockResolvedValue(probeStub.noVideoStreams); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).not.toHaveBeenCalled(); }); it('should skip a video without any height', async () => { mocks.media.probe.mockResolvedValue(probeStub.noHeight); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).not.toHaveBeenCalled(); }); @@ -936,7 +951,6 @@ describe(MediaService.name, () => { it('should throw an error if an unknown transcode policy is configured', async () => { mocks.media.probe.mockResolvedValue(probeStub.noAudioStreams); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: 'foo' } } as never as SystemConfig); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await expect(sut.handleVideoConversion({ id: assetStub.video.id })).rejects.toThrowError(); expect(mocks.media.transcode).not.toHaveBeenCalled(); @@ -947,7 +961,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.ALL, accel: TranscodeHWAccel.DISABLED }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); mocks.media.transcode.mockRejectedValue(new Error('Error transcoding video')); await expect(sut.handleVideoConversion({ id: assetStub.video.id })).resolves.toBe(JobStatus.FAILED); @@ -957,7 +970,6 @@ describe(MediaService.name, () => { it('should transcode when set to all', async () => { mocks.media.probe.mockResolvedValue(probeStub.multipleVideoStreams); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.ALL } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1035,7 +1047,6 @@ describe(MediaService.name, () => { it('should scale horizontally when video is horizontal', async () => { mocks.media.probe.mockResolvedValue(probeStub.videoStream2160p); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.OPTIMAL } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1051,7 +1062,6 @@ describe(MediaService.name, () => { it('should scale vertically when video is vertical', async () => { mocks.media.probe.mockResolvedValue(probeStub.videoStreamVertical2160p); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.OPTIMAL } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1069,7 +1079,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.ALL, targetResolution: 'original' }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1087,7 +1096,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.ALL, targetResolution: 'original' }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1105,7 +1113,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { targetVideoCodec: VideoCodec.HEVC, acceptedAudioCodecs: [AudioCodec.AAC] }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1127,7 +1134,6 @@ describe(MediaService.name, () => { acceptedAudioCodecs: [AudioCodec.AAC], }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1149,7 +1155,6 @@ describe(MediaService.name, () => { acceptedAudioCodecs: [AudioCodec.AAC], }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1165,7 +1170,6 @@ describe(MediaService.name, () => { it('should copy audio stream when audio matches target', async () => { mocks.media.probe.mockResolvedValue(probeStub.audioStreamAac); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.OPTIMAL } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1180,7 +1184,6 @@ describe(MediaService.name, () => { it('should remux when input is not an accepted container', async () => { mocks.media.probe.mockResolvedValue(probeStub.videoStreamAvi); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1204,7 +1207,6 @@ describe(MediaService.name, () => { it('should not transcode if transcoding is disabled', async () => { mocks.media.probe.mockResolvedValue(probeStub.videoStream2160p); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.DISABLED } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).not.toHaveBeenCalled(); }); @@ -1212,7 +1214,6 @@ describe(MediaService.name, () => { it('should not remux when input is not an accepted container and transcoding is disabled', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.DISABLED } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).not.toHaveBeenCalled(); }); @@ -1220,7 +1221,6 @@ describe(MediaService.name, () => { it('should not transcode if target codec is invalid', async () => { mocks.media.probe.mockResolvedValue(probeStub.videoStream2160p); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { targetVideoCodec: 'invalid' as any } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).not.toHaveBeenCalled(); }); @@ -1229,7 +1229,7 @@ describe(MediaService.name, () => { const asset = assetStub.hasEncodedVideo; mocks.media.probe.mockResolvedValue(probeStub.videoStream2160p); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.DISABLED } }); - mocks.asset.getByIds.mockResolvedValue([asset]); + mocks.assetJob.getForVideoConversion.mockResolvedValue(asset); await sut.handleVideoConversion({ id: asset.id }); @@ -1243,7 +1243,6 @@ describe(MediaService.name, () => { it('should set max bitrate if above 0', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { maxBitrate: '4500k' } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1259,7 +1258,6 @@ describe(MediaService.name, () => { it('should default max bitrate to kbps if no unit is provided', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { maxBitrate: '4500' } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1275,7 +1273,6 @@ describe(MediaService.name, () => { it('should transcode in two passes for h264/h265 when enabled and max bitrate is above 0', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { twoPass: true, maxBitrate: '4500k' } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1291,7 +1288,6 @@ describe(MediaService.name, () => { it('should fallback to one pass for h264/h265 if two-pass is enabled but no max bitrate is set', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { twoPass: true } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1313,7 +1309,6 @@ describe(MediaService.name, () => { targetVideoCodec: VideoCodec.VP9, }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1335,7 +1330,6 @@ describe(MediaService.name, () => { targetVideoCodec: VideoCodec.VP9, }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1351,7 +1345,6 @@ describe(MediaService.name, () => { it('should configure preset for vp9', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { targetVideoCodec: VideoCodec.VP9, preset: 'slow' } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1367,7 +1360,6 @@ describe(MediaService.name, () => { it('should not configure preset for vp9 if invalid', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { preset: 'invalid', targetVideoCodec: VideoCodec.VP9 } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1383,7 +1375,6 @@ describe(MediaService.name, () => { it('should configure threads if above 0', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { targetVideoCodec: VideoCodec.VP9, threads: 2 } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1399,7 +1390,6 @@ describe(MediaService.name, () => { it('should disable thread pooling for h264 if thread limit is 1', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { threads: 1 } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1415,7 +1405,6 @@ describe(MediaService.name, () => { it('should omit thread flags for h264 if thread limit is at or below 0', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { threads: 0 } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1431,7 +1420,6 @@ describe(MediaService.name, () => { it('should disable thread pooling for hevc if thread limit is 1', async () => { mocks.media.probe.mockResolvedValue(probeStub.videoStreamVp9); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { threads: 1, targetVideoCodec: VideoCodec.HEVC } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1447,7 +1435,6 @@ describe(MediaService.name, () => { it('should omit thread flags for hevc if thread limit is at or below 0', async () => { mocks.media.probe.mockResolvedValue(probeStub.videoStreamVp9); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { threads: 0, targetVideoCodec: VideoCodec.HEVC } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1463,7 +1450,6 @@ describe(MediaService.name, () => { it('should use av1 if specified', async () => { mocks.media.probe.mockResolvedValue(probeStub.videoStreamVp9); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { targetVideoCodec: VideoCodec.AV1 } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1489,7 +1475,6 @@ describe(MediaService.name, () => { it('should map `veryslow` preset to 4 for av1', async () => { mocks.media.probe.mockResolvedValue(probeStub.videoStreamVp9); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { targetVideoCodec: VideoCodec.AV1, preset: 'veryslow' } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1505,7 +1490,6 @@ describe(MediaService.name, () => { it('should set max bitrate for av1 if specified', async () => { mocks.media.probe.mockResolvedValue(probeStub.videoStreamVp9); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { targetVideoCodec: VideoCodec.AV1, maxBitrate: '2M' } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1521,7 +1505,6 @@ describe(MediaService.name, () => { it('should set threads for av1 if specified', async () => { mocks.media.probe.mockResolvedValue(probeStub.videoStreamVp9); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { targetVideoCodec: VideoCodec.AV1, threads: 4 } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1539,7 +1522,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { targetVideoCodec: VideoCodec.AV1, threads: 4, maxBitrate: '2M' }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1561,7 +1543,6 @@ describe(MediaService.name, () => { targetResolution: '1080p', }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).not.toHaveBeenCalled(); }); @@ -1571,7 +1552,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.NVENC, targetVideoCodec: VideoCodec.VP9 }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await expect(sut.handleVideoConversion({ id: assetStub.video.id })).rejects.toThrowError(); expect(mocks.media.transcode).not.toHaveBeenCalled(); }); @@ -1579,7 +1559,6 @@ describe(MediaService.name, () => { it('should fail if hwaccel option is invalid', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: 'invalid' as any } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await expect(sut.handleVideoConversion({ id: assetStub.video.id })).rejects.toThrowError(); expect(mocks.media.transcode).not.toHaveBeenCalled(); }); @@ -1587,7 +1566,6 @@ describe(MediaService.name, () => { it('should set options for nvenc', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.NVENC } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1625,7 +1603,6 @@ describe(MediaService.name, () => { twoPass: true, }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1641,7 +1618,6 @@ describe(MediaService.name, () => { it('should set vbr options for nvenc when max bitrate is enabled', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.NVENC, maxBitrate: '10000k' } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1657,7 +1633,6 @@ describe(MediaService.name, () => { it('should set cq options for nvenc when max bitrate is disabled', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.NVENC, maxBitrate: '10000k' } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1673,7 +1648,6 @@ describe(MediaService.name, () => { it('should omit preset for nvenc if invalid', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.NVENC, preset: 'invalid' } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1689,7 +1663,6 @@ describe(MediaService.name, () => { it('should ignore two pass for nvenc if max bitrate is disabled', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.NVENC } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1707,7 +1680,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.NVENC, accelDecode: true }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1730,7 +1702,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.NVENC, accelDecode: true }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1752,7 +1723,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.NVENC, accelDecode: true }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1768,7 +1738,6 @@ describe(MediaService.name, () => { it('should set options for qsv', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.QSV, maxBitrate: '10000k' } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1809,7 +1778,6 @@ describe(MediaService.name, () => { preferredHwDevice: '/dev/dri/renderD128', }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1828,7 +1796,6 @@ describe(MediaService.name, () => { it('should omit preset for qsv if invalid', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.QSV, preset: 'invalid' } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1849,7 +1816,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.QSV, targetVideoCodec: VideoCodec.VP9 }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1869,7 +1835,6 @@ describe(MediaService.name, () => { sut.videoInterfaces = { dri: [], mali: false }; mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.QSV } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await expect(sut.handleVideoConversion({ id: assetStub.video.id })).rejects.toThrowError(); @@ -1880,7 +1845,6 @@ describe(MediaService.name, () => { sut.videoInterfaces = { dri: ['card1', 'renderD129', 'card0', 'renderD128'], mali: false }; mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.QSV } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -1901,7 +1865,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.QSV, accelDecode: true }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); @@ -1928,7 +1891,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.QSV, accelDecode: true }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); @@ -1958,7 +1920,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.QSV, accelDecode: true, preferredHwDevice: 'renderD129' }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( @@ -1977,7 +1938,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.QSV, accelDecode: true }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); @@ -2000,7 +1960,6 @@ describe(MediaService.name, () => { it('should set options for vaapi', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -2031,7 +1990,6 @@ describe(MediaService.name, () => { it('should set vbr options for vaapi when max bitrate is enabled', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI, maxBitrate: '10000k' } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -2056,7 +2014,6 @@ describe(MediaService.name, () => { it('should set cq options for vaapi when max bitrate is disabled', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -2081,7 +2038,6 @@ describe(MediaService.name, () => { it('should omit preset for vaapi if invalid', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI, preset: 'invalid' } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -2101,7 +2057,6 @@ describe(MediaService.name, () => { sut.videoInterfaces = { dri: ['card1', 'renderD129', 'card0', 'renderD128'], mali: false }; mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -2123,7 +2078,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI, preferredHwDevice: '/dev/dri/renderD128' }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -2144,7 +2098,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI, accelDecode: true }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); @@ -2170,7 +2123,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI, accelDecode: true }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); @@ -2194,7 +2146,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI, accelDecode: true }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); @@ -2215,7 +2166,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI, accelDecode: true, preferredHwDevice: 'renderD129' }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( @@ -2232,7 +2182,6 @@ describe(MediaService.name, () => { it('should fallback to hw encoding and sw decoding if hw transcoding fails and hw decoding is enabled', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI, accelDecode: true } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); mocks.media.transcode.mockRejectedValueOnce(new Error('error')); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledTimes(2); @@ -2253,7 +2202,6 @@ describe(MediaService.name, () => { it('should fallback to sw decoding if fallback to sw decoding + hw encoding fails', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI, accelDecode: true } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); mocks.media.transcode.mockRejectedValueOnce(new Error('error')); mocks.media.transcode.mockRejectedValueOnce(new Error('error')); await sut.handleVideoConversion({ id: assetStub.video.id }); @@ -2272,7 +2220,6 @@ describe(MediaService.name, () => { it('should fallback to sw transcoding if hw transcoding fails and hw decoding is disabled', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); mocks.media.transcode.mockRejectedValueOnce(new Error('error')); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledTimes(2); @@ -2291,7 +2238,6 @@ describe(MediaService.name, () => { sut.videoInterfaces = { dri: [], mali: true }; mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.VAAPI } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await expect(sut.handleVideoConversion({ id: assetStub.video.id })).rejects.toThrowError(); expect(mocks.media.transcode).not.toHaveBeenCalled(); }); @@ -2299,7 +2245,6 @@ describe(MediaService.name, () => { it('should set options for rkmpp', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.RKMPP, accelDecode: true } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -2340,7 +2285,6 @@ describe(MediaService.name, () => { targetVideoCodec: VideoCodec.HEVC, }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -2358,7 +2302,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.RKMPP, accelDecode: true, crf: 30, maxBitrate: '0' }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -2376,7 +2319,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.RKMPP, accelDecode: true, crf: 30, maxBitrate: '0' }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -2399,7 +2341,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.RKMPP, accelDecode: true, crf: 30, maxBitrate: '0' }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -2419,7 +2360,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.RKMPP, accelDecode: false, crf: 30, maxBitrate: '0' }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -2442,7 +2382,6 @@ describe(MediaService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHWAccel.RKMPP, accelDecode: true, crf: 30, maxBitrate: '0' }, }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -2462,7 +2401,6 @@ describe(MediaService.name, () => { it('should tonemap when policy is required and video is hdr', async () => { mocks.media.probe.mockResolvedValue(probeStub.videoStreamHDR); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.REQUIRED } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -2482,7 +2420,6 @@ describe(MediaService.name, () => { it('should tonemap when policy is optimal and video is hdr', async () => { mocks.media.probe.mockResolvedValue(probeStub.videoStreamHDR); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.OPTIMAL } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -2502,7 +2439,6 @@ describe(MediaService.name, () => { it('should transcode when policy is required and video is not yuv420p', async () => { mocks.media.probe.mockResolvedValue(probeStub.videoStream10Bit); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.REQUIRED } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -2518,7 +2454,6 @@ describe(MediaService.name, () => { it('should convert to yuv420p when scaling without tone-mapping', async () => { mocks.media.probe.mockResolvedValue(probeStub.videoStream4K10Bit); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { transcode: TranscodePolicy.REQUIRED } }); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.transcode).toHaveBeenCalledWith( '/original/path.ext', @@ -2534,7 +2469,6 @@ describe(MediaService.name, () => { it('should count frames for progress when log level is debug', async () => { mocks.media.probe.mockResolvedValue(probeStub.matroskaContainer); mocks.logger.isLevelEnabled.mockReturnValue(true); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); @@ -2557,7 +2491,6 @@ describe(MediaService.name, () => { it('should not count frames for progress when log level is not debug', async () => { mocks.media.probe.mockResolvedValue(probeStub.videoStream2160p); mocks.logger.isLevelEnabled.mockReturnValue(false); - mocks.asset.getByIds.mockResolvedValue([assetStub.video]); await sut.handleVideoConversion({ id: assetStub.video.id }); expect(mocks.media.probe).toHaveBeenCalledWith(assetStub.video.originalPath, { countFrames: false }); @@ -2582,48 +2515,39 @@ describe(MediaService.name, () => { describe('isSRGB', () => { it('should return true for srgb colorspace', () => { - const asset = { ...assetStub.image, exifInfo: { colorspace: 'sRGB' } as Exif }; - expect(sut.isSRGB(asset)).toEqual(true); + expect(sut.isSRGB({ colorspace: 'sRGB' } as Exif)).toEqual(true); }); it('should return true for srgb profile description', () => { - const asset = { ...assetStub.image, exifInfo: { profileDescription: 'sRGB v1.31' } as Exif }; - expect(sut.isSRGB(asset)).toEqual(true); + expect(sut.isSRGB({ profileDescription: 'sRGB v1.31' } as Exif)).toEqual(true); }); it('should return true for 8-bit image with no colorspace metadata', () => { - const asset = { ...assetStub.image, exifInfo: { bitsPerSample: 8 } as Exif }; - expect(sut.isSRGB(asset)).toEqual(true); + expect(sut.isSRGB({ bitsPerSample: 8 } as Exif)).toEqual(true); }); it('should return true for image with no colorspace or bit depth metadata', () => { - const asset = { ...assetStub.image, exifInfo: {} as Exif }; - expect(sut.isSRGB(asset)).toEqual(true); + expect(sut.isSRGB({} as Exif)).toEqual(true); }); it('should return false for non-srgb colorspace', () => { - const asset = { ...assetStub.image, exifInfo: { colorspace: 'Adobe RGB' } as Exif }; - expect(sut.isSRGB(asset)).toEqual(false); + expect(sut.isSRGB({ colorspace: 'Adobe RGB' } as Exif)).toEqual(false); }); it('should return false for non-srgb profile description', () => { - const asset = { ...assetStub.image, exifInfo: { profileDescription: 'sP3C' } as Exif }; - expect(sut.isSRGB(asset)).toEqual(false); + expect(sut.isSRGB({ profileDescription: 'sP3C' } as Exif)).toEqual(false); }); it('should return false for 16-bit image with no colorspace metadata', () => { - const asset = { ...assetStub.image, exifInfo: { bitsPerSample: 16 } as Exif }; - expect(sut.isSRGB(asset)).toEqual(false); + expect(sut.isSRGB({ bitsPerSample: 16 } as Exif)).toEqual(false); }); it('should return true for 16-bit image with sRGB colorspace', () => { - const asset = { ...assetStub.image, exifInfo: { colorspace: 'sRGB', bitsPerSample: 16 } as Exif }; - expect(sut.isSRGB(asset)).toEqual(true); + expect(sut.isSRGB({ colorspace: 'sRGB', bitsPerSample: 16 } as Exif)).toEqual(true); }); it('should return true for 16-bit image with sRGB profile', () => { - const asset = { ...assetStub.image, exifInfo: { profileDescription: 'sRGB', bitsPerSample: 16 } as Exif }; - expect(sut.isSRGB(asset)).toEqual(true); + expect(sut.isSRGB({ profileDescription: 'sRGB', bitsPerSample: 16 } as Exif)).toEqual(true); }); }); }); diff --git a/server/src/services/media.service.ts b/server/src/services/media.service.ts index 59d708772b..35d28a175b 100644 --- a/server/src/services/media.service.ts +++ b/server/src/services/media.service.ts @@ -10,11 +10,11 @@ import { AssetType, AudioCodec, Colorspace, - ImageFormat, JobName, JobStatus, LogLevel, QueueName, + RawExtractedFormat, StorageFolder, TranscodeHWAccel, TranscodePolicy, @@ -22,12 +22,11 @@ import { VideoCodec, VideoContainer, } from 'src/enum'; -import { UpsertFileOptions, WithoutProperty } from 'src/repositories/asset.repository'; +import { UpsertFileOptions } from 'src/repositories/asset.repository'; import { BaseService } from 'src/services/base.service'; import { AudioStreamInfo, DecodeToBufferOptions, - GenerateThumbnailOptions, JobItem, JobOf, VideoFormat, @@ -37,7 +36,6 @@ import { import { getAssetFiles } from 'src/utils/asset.util'; import { BaseConfig, ThumbnailConfig } from 'src/utils/media'; import { mimeTypes } from 'src/utils/mime-types'; -import { usePagination } from 'src/utils/pagination'; @Injectable() export class MediaService extends BaseService { @@ -51,18 +49,26 @@ export class MediaService extends BaseService { @OnJob({ name: JobName.QUEUE_GENERATE_THUMBNAILS, queue: QueueName.THUMBNAIL_GENERATION }) async handleQueueGenerateThumbnails({ force }: JobOf): Promise { - const thumbJobs: JobItem[] = []; + let jobs: JobItem[] = []; + + const queueAll = async () => { + await this.jobRepository.queueAll(jobs); + jobs = []; + }; + for await (const asset of this.assetJobRepository.streamForThumbnailJob(!!force)) { const { previewFile, thumbnailFile } = getAssetFiles(asset.files); if (!previewFile || !thumbnailFile || !asset.thumbhash || force) { - thumbJobs.push({ name: JobName.GENERATE_THUMBNAILS, data: { id: asset.id } }); - continue; + jobs.push({ name: JobName.GENERATE_THUMBNAILS, data: { id: asset.id } }); + } + + if (jobs.length >= JOBS_ASSET_PAGINATION_SIZE) { + await queueAll(); } } - await this.jobRepository.queueAll(thumbJobs); - const jobs: JobItem[] = []; + await queueAll(); const people = this.personRepository.getAll(force ? undefined : { thumbnailPath: '' }); @@ -77,32 +83,36 @@ export class MediaService extends BaseService { } jobs.push({ name: JobName.GENERATE_PERSON_THUMBNAIL, data: { id: person.id } }); + if (jobs.length >= JOBS_ASSET_PAGINATION_SIZE) { + await queueAll(); + } } - await this.jobRepository.queueAll(jobs); + await queueAll(); return JobStatus.SUCCESS; } @OnJob({ name: JobName.QUEUE_MIGRATION, queue: QueueName.MIGRATION }) async handleQueueMigration(): Promise { - const assetPagination = usePagination(JOBS_ASSET_PAGINATION_SIZE, (pagination) => - this.assetRepository.getAll(pagination), - ); - const { active, waiting } = await this.jobRepository.getJobCounts(QueueName.MIGRATION); if (active === 1 && waiting === 0) { await this.storageCore.removeEmptyDirs(StorageFolder.THUMBNAILS); await this.storageCore.removeEmptyDirs(StorageFolder.ENCODED_VIDEO); } - for await (const assets of assetPagination) { - await this.jobRepository.queueAll( - assets.map((asset) => ({ name: JobName.MIGRATE_ASSET, data: { id: asset.id } })), - ); + let jobs: JobItem[] = []; + const assets = this.assetJobRepository.streamForMigrationJob(); + for await (const asset of assets) { + jobs.push({ name: JobName.MIGRATE_ASSET, data: { id: asset.id } }); + if (jobs.length >= JOBS_ASSET_PAGINATION_SIZE) { + await this.jobRepository.queueAll(jobs); + jobs = []; + } } - let jobs: { name: JobName.MIGRATE_PERSON; data: { id: string } }[] = []; + await this.jobRepository.queueAll(jobs); + jobs = []; for await (const person of this.personRepository.getAll()) { jobs.push({ name: JobName.MIGRATE_PERSON, data: { id: person.id } }); @@ -213,6 +223,29 @@ export class MediaService extends BaseService { return JobStatus.SUCCESS; } + private async extractImage(originalPath: string, minSize: number) { + let extracted = await this.mediaRepository.extract(originalPath); + if (extracted && !(await this.shouldUseExtractedImage(extracted.buffer, minSize))) { + extracted = null; + } + + return extracted; + } + + private async decodeImage(thumbSource: string | Buffer, exifInfo: Exif, targetSize?: number) { + const { image } = await this.getConfig({ withCache: true }); + const colorspace = this.isSRGB(exifInfo) ? Colorspace.SRGB : image.colorspace; + const decodeOptions: DecodeToBufferOptions = { + colorspace, + processInvalidImages: process.env.IMMICH_PROCESS_INVALID_IMAGES === 'true', + size: targetSize, + orientation: exifInfo.orientation ? Number(exifInfo.orientation) : undefined, + }; + + const { info, data } = await this.mediaRepository.decodeImage(thumbSource, decodeOptions); + return { info, data, colorspace }; + } + private async generateImageThumbnails(asset: { id: string; ownerId: string; @@ -225,68 +258,48 @@ export class MediaService extends BaseService { const thumbnailPath = StorageCore.getImagePath(asset, AssetPathType.THUMBNAIL, image.thumbnail.format); this.storageCore.ensureFolders(previewPath); - const processInvalidImages = process.env.IMMICH_PROCESS_INVALID_IMAGES === 'true'; - const colorspace = this.isSRGB(asset) ? Colorspace.SRGB : image.colorspace; + // Handle embedded preview extraction for RAW files + const extractEmbedded = image.extractEmbedded && mimeTypes.isRaw(asset.originalFileName); + const extracted = extractEmbedded ? await this.extractImage(asset.originalPath, image.preview.size) : null; + const generateFullsize = image.fullsize.enabled && !mimeTypes.isWebSupportedImage(asset.originalPath); + const convertFullsize = generateFullsize && (!extracted || !mimeTypes.isWebSupportedImage(` .${extracted.format}`)); - // prevents this extra "enabled" from leaking into fullsizeOptions later - const { enabled: imageFullsizeEnabled, ...imageFullsizeConfig } = image.fullsize; + const { info, data, colorspace } = await this.decodeImage( + extracted ? extracted.buffer : asset.originalPath, + asset.exifInfo, + convertFullsize ? undefined : image.preview.size, + ); - const shouldConvertFullsize = imageFullsizeEnabled && !mimeTypes.isWebSupportedImage(asset.originalFileName); - const shouldExtractEmbedded = image.extractEmbedded && mimeTypes.isRaw(asset.originalFileName); - const decodeOptions: DecodeToBufferOptions = { colorspace, processInvalidImages, size: image.preview.size }; - - let useExtracted = false; - let decodeInputPath: string = asset.originalPath; - // Converted or extracted image from non-web-supported formats (e.g. RAW) - let fullsizePath: string | undefined; - - if (shouldConvertFullsize) { - // unset size to decode fullsize image - decodeOptions.size = undefined; - fullsizePath = StorageCore.getImagePath(asset, AssetPathType.FULLSIZE, image.fullsize.format); - } - - if (shouldExtractEmbedded) { - // For RAW files, try extracting embedded preview first - // Assume extracted image from RAW always in JPEG format, as implied from the `jpgFromRaw` tag name - const extractedPath = StorageCore.getImagePath(asset, AssetPathType.FULLSIZE, ImageFormat.JPEG); - const didExtract = await this.mediaRepository.extract(asset.originalPath, extractedPath); - useExtracted = didExtract && (await this.shouldUseExtractedImage(extractedPath, image.preview.size)); - - if (useExtracted) { - if (shouldConvertFullsize) { - // skip re-encoding and directly use extracted as fullsize preview - // as usually the extracted image is already heavily compressed, no point doing lossy conversion again - fullsizePath = extractedPath; - } - // use this as origin of preview and thumbnail - decodeInputPath = extractedPath; - if (asset.exifInfo) { - // write essential orientation and colorspace EXIF for correct fullsize preview and subsequent processing - const exif = { orientation: asset.exifInfo.orientation, colorspace: asset.exifInfo.colorspace }; - await this.mediaRepository.writeExif(exif, extractedPath); - } - } - } - - const { info, data } = await this.mediaRepository.decodeImage(decodeInputPath, decodeOptions); - - const thumbnailOptions = { colorspace, processInvalidImages, raw: info }; + // generate final images + const thumbnailOptions = { colorspace, processInvalidImages: false, raw: info }; const promises = [ this.mediaRepository.generateThumbhash(data, thumbnailOptions), this.mediaRepository.generateThumbnail(data, { ...image.thumbnail, ...thumbnailOptions }, thumbnailPath), this.mediaRepository.generateThumbnail(data, { ...image.preview, ...thumbnailOptions }, previewPath), ]; - // did not extract a usable image from RAW - if (fullsizePath && !useExtracted) { - const fullsizeOptions: GenerateThumbnailOptions = { - ...imageFullsizeConfig, - ...thumbnailOptions, - size: undefined, - }; + let fullsizePath: string | undefined; + + if (convertFullsize) { + // convert a new fullsize image from the same source as the thumbnail + fullsizePath = StorageCore.getImagePath(asset, AssetPathType.FULLSIZE, image.fullsize.format); + const fullsizeOptions = { format: image.fullsize.format, quality: image.fullsize.quality, ...thumbnailOptions }; promises.push(this.mediaRepository.generateThumbnail(data, fullsizeOptions, fullsizePath)); + } else if (generateFullsize && extracted && extracted.format === RawExtractedFormat.JPEG) { + fullsizePath = StorageCore.getImagePath(asset, AssetPathType.FULLSIZE, extracted.format); + this.storageCore.ensureFolders(fullsizePath); + + // Write the buffer to disk with essential EXIF data + await this.storageRepository.createOrOverwriteFile(fullsizePath, extracted.buffer); + await this.mediaRepository.writeExif( + { + orientation: asset.exifInfo.orientation, + colorspace: asset.exifInfo.colorspace, + }, + fullsizePath, + ); } + const outputs = await Promise.all(promises); return { previewPath, thumbnailPath, fullsizePath, thumbhash: outputs[0] as Buffer }; @@ -330,25 +343,25 @@ export class MediaService extends BaseService { async handleQueueVideoConversion(job: JobOf): Promise { const { force } = job; - const assetPagination = usePagination(JOBS_ASSET_PAGINATION_SIZE, (pagination) => { - return force - ? this.assetRepository.getAll(pagination, { type: AssetType.VIDEO }) - : this.assetRepository.getWithout(pagination, WithoutProperty.ENCODED_VIDEO); - }); + let queue: { name: JobName.VIDEO_CONVERSION; data: { id: string } }[] = []; + for await (const asset of this.assetJobRepository.streamForVideoConversion(force)) { + queue.push({ name: JobName.VIDEO_CONVERSION, data: { id: asset.id } }); - for await (const assets of assetPagination) { - await this.jobRepository.queueAll( - assets.map((asset) => ({ name: JobName.VIDEO_CONVERSION, data: { id: asset.id } })), - ); + if (queue.length >= JOBS_ASSET_PAGINATION_SIZE) { + await this.jobRepository.queueAll(queue); + queue = []; + } } + await this.jobRepository.queueAll(queue); + return JobStatus.SUCCESS; } @OnJob({ name: JobName.VIDEO_CONVERSION, queue: QueueName.VIDEO_CONVERSION }) async handleVideoConversion({ id }: JobOf): Promise { - const [asset] = await this.assetRepository.getByIds([id]); - if (!asset || asset.type !== AssetType.VIDEO) { + const asset = await this.assetJobRepository.getForVideoConversion(id); + if (!asset) { return JobStatus.FAILED; } @@ -521,8 +534,7 @@ export class MediaService extends BaseService { return name !== VideoContainer.MP4 && !ffmpegConfig.acceptedContainers.includes(name); } - isSRGB(asset: { exifInfo: Exif }): boolean { - const { colorspace, profileDescription, bitsPerSample } = asset.exifInfo; + isSRGB({ colorspace, profileDescription, bitsPerSample }: Exif): boolean { if (colorspace || profileDescription) { return [colorspace, profileDescription].some((s) => s?.toLowerCase().includes('srgb')); } else if (bitsPerSample) { @@ -550,10 +562,9 @@ export class MediaService extends BaseService { } } - private async shouldUseExtractedImage(extractedPath: string, targetSize: number) { - const { width, height } = await this.mediaRepository.getImageDimensions(extractedPath); + private async shouldUseExtractedImage(extractedPathOrBuffer: string | Buffer, targetSize: number) { + const { width, height } = await this.mediaRepository.getImageDimensions(extractedPathOrBuffer); const extractedSize = Math.min(width, height); - return extractedSize >= targetSize; } diff --git a/server/src/services/metadata.service.spec.ts b/server/src/services/metadata.service.spec.ts index e412b1c31f..e0a283b02a 100644 --- a/server/src/services/metadata.service.spec.ts +++ b/server/src/services/metadata.service.spec.ts @@ -5,7 +5,6 @@ import { constants } from 'node:fs/promises'; import { defaults } from 'src/config'; import { MapAsset } from 'src/dtos/asset-response.dto'; import { AssetType, ExifOrientation, ImmichWorker, JobName, JobStatus, SourceType } from 'src/enum'; -import { WithoutProperty } from 'src/repositories/asset.repository'; import { ImmichTags } from 'src/repositories/metadata.repository'; import { MetadataService } from 'src/services/metadata.service'; import { assetStub } from 'test/fixtures/asset.stub'; @@ -14,7 +13,7 @@ import { probeStub } from 'test/fixtures/media.stub'; import { personStub } from 'test/fixtures/person.stub'; import { tagStub } from 'test/fixtures/tag.stub'; import { factory } from 'test/small.factory'; -import { newTestService, ServiceMocks } from 'test/utils'; +import { makeStream, newTestService, ServiceMocks } from 'test/utils'; const makeFaceTags = (face: Partial<{ Name: string }> = {}) => ({ RegionInfo: { @@ -104,10 +103,10 @@ describe(MetadataService.name, () => { describe('handleQueueMetadataExtraction', () => { it('should queue metadata extraction for all assets without exif values', async () => { - mocks.asset.getWithout.mockResolvedValue({ items: [assetStub.image], hasNextPage: false }); + mocks.assetJob.streamForMetadataExtraction.mockReturnValue(makeStream([assetStub.image])); await expect(sut.handleQueueMetadataExtraction({ force: false })).resolves.toBe(JobStatus.SUCCESS); - expect(mocks.asset.getWithout).toHaveBeenCalled(); + expect(mocks.assetJob.streamForMetadataExtraction).toHaveBeenCalledWith(false); expect(mocks.job.queueAll).toHaveBeenCalledWith([ { name: JobName.METADATA_EXTRACTION, @@ -117,10 +116,10 @@ describe(MetadataService.name, () => { }); it('should queue metadata extraction for all assets', async () => { - mocks.asset.getAll.mockResolvedValue({ items: [assetStub.image], hasNextPage: false }); + mocks.assetJob.streamForMetadataExtraction.mockReturnValue(makeStream([assetStub.image])); await expect(sut.handleQueueMetadataExtraction({ force: true })).resolves.toBe(JobStatus.SUCCESS); - expect(mocks.asset.getAll).toHaveBeenCalled(); + expect(mocks.assetJob.streamForMetadataExtraction).toHaveBeenCalledWith(true); expect(mocks.job.queueAll).toHaveBeenCalledWith([ { name: JobName.METADATA_EXTRACTION, @@ -598,6 +597,10 @@ describe(MetadataService.name, () => { livePhotoVideoId: fileStub.livePhotoMotion.uuid, }); expect(mocks.asset.update).toHaveBeenCalledTimes(3); + expect(mocks.job.queue).toHaveBeenCalledExactlyOnceWith({ + name: JobName.VIDEO_CONVERSION, + data: { id: assetStub.livePhotoMotionAsset.id }, + }); }); it('should extract the EmbeddedVideo tag from Samsung JPEG motion photos', async () => { @@ -652,6 +655,10 @@ describe(MetadataService.name, () => { livePhotoVideoId: fileStub.livePhotoMotion.uuid, }); expect(mocks.asset.update).toHaveBeenCalledTimes(3); + expect(mocks.job.queue).toHaveBeenCalledExactlyOnceWith({ + name: JobName.VIDEO_CONVERSION, + data: { id: assetStub.livePhotoMotionAsset.id }, + }); }); it('should extract the motion photo video from the XMP directory entry ', async () => { @@ -706,6 +713,10 @@ describe(MetadataService.name, () => { livePhotoVideoId: fileStub.livePhotoMotion.uuid, }); expect(mocks.asset.update).toHaveBeenCalledTimes(3); + expect(mocks.job.queue).toHaveBeenCalledExactlyOnceWith({ + name: JobName.VIDEO_CONVERSION, + data: { id: assetStub.livePhotoMotionAsset.id }, + }); }); it('should delete old motion photo video assets if they do not match what is extracted', async () => { @@ -1334,12 +1345,11 @@ describe(MetadataService.name, () => { describe('handleQueueSidecar', () => { it('should queue assets with sidecar files', async () => { - mocks.asset.getAll.mockResolvedValue({ items: [assetStub.sidecar], hasNextPage: false }); + mocks.assetJob.streamForSidecar.mockReturnValue(makeStream([assetStub.image])); await sut.handleQueueSidecar({ force: true }); + expect(mocks.assetJob.streamForSidecar).toHaveBeenCalledWith(true); - expect(mocks.asset.getAll).toHaveBeenCalledWith({ take: 1000, skip: 0 }); - expect(mocks.asset.getWithout).not.toHaveBeenCalled(); expect(mocks.job.queueAll).toHaveBeenCalledWith([ { name: JobName.SIDECAR_SYNC, @@ -1349,12 +1359,11 @@ describe(MetadataService.name, () => { }); it('should queue assets without sidecar files', async () => { - mocks.asset.getWithout.mockResolvedValue({ items: [assetStub.image], hasNextPage: false }); + mocks.assetJob.streamForSidecar.mockReturnValue(makeStream([assetStub.image])); await sut.handleQueueSidecar({ force: false }); - expect(mocks.asset.getWithout).toHaveBeenCalledWith({ take: 1000, skip: 0 }, WithoutProperty.SIDECAR); - expect(mocks.asset.getAll).not.toHaveBeenCalled(); + expect(mocks.assetJob.streamForSidecar).toHaveBeenCalledWith(false); expect(mocks.job.queueAll).toHaveBeenCalledWith([ { name: JobName.SIDECAR_DISCOVERY, diff --git a/server/src/services/metadata.service.ts b/server/src/services/metadata.service.ts index faf146a2be..fd7382e163 100644 --- a/server/src/services/metadata.service.ts +++ b/server/src/services/metadata.service.ts @@ -22,14 +22,12 @@ import { QueueName, SourceType, } from 'src/enum'; -import { WithoutProperty } from 'src/repositories/asset.repository'; import { ArgOf } from 'src/repositories/event.repository'; import { ReverseGeocodeResult } from 'src/repositories/map.repository'; import { ImmichTags } from 'src/repositories/metadata.repository'; import { BaseService } from 'src/services/base.service'; -import { JobOf } from 'src/types'; +import { JobItem, JobOf } from 'src/types'; import { isFaceImportEnabled } from 'src/utils/misc'; -import { usePagination } from 'src/utils/pagination'; import { upsertTags } from 'src/utils/tag'; /** look for a date from these tags (in order) */ @@ -168,18 +166,18 @@ export class MetadataService extends BaseService { @OnJob({ name: JobName.QUEUE_METADATA_EXTRACTION, queue: QueueName.METADATA_EXTRACTION }) async handleQueueMetadataExtraction(job: JobOf): Promise { const { force } = job; - const assetPagination = usePagination(JOBS_ASSET_PAGINATION_SIZE, (pagination) => { - return force - ? this.assetRepository.getAll(pagination) - : this.assetRepository.getWithout(pagination, WithoutProperty.EXIF); - }); - for await (const assets of assetPagination) { - await this.jobRepository.queueAll( - assets.map((asset) => ({ name: JobName.METADATA_EXTRACTION, data: { id: asset.id } })), - ); + let queue: { name: JobName.METADATA_EXTRACTION; data: { id: string } }[] = []; + for await (const asset of this.assetJobRepository.streamForMetadataExtraction(force)) { + queue.push({ name: JobName.METADATA_EXTRACTION, data: { id: asset.id } }); + + if (queue.length >= JOBS_ASSET_PAGINATION_SIZE) { + await this.jobRepository.queueAll(queue); + queue = []; + } } + await this.jobRepository.queueAll(queue); return JobStatus.SUCCESS; } @@ -289,23 +287,23 @@ export class MetadataService extends BaseService { } @OnJob({ name: JobName.QUEUE_SIDECAR, queue: QueueName.SIDECAR }) - async handleQueueSidecar(job: JobOf): Promise { - const { force } = job; - const assetPagination = usePagination(JOBS_ASSET_PAGINATION_SIZE, (pagination) => { - return force - ? this.assetRepository.getAll(pagination) - : this.assetRepository.getWithout(pagination, WithoutProperty.SIDECAR); - }); + async handleQueueSidecar({ force }: JobOf): Promise { + let jobs: JobItem[] = []; + const queueAll = async () => { + await this.jobRepository.queueAll(jobs); + jobs = []; + }; - for await (const assets of assetPagination) { - await this.jobRepository.queueAll( - assets.map((asset) => ({ - name: force ? JobName.SIDECAR_SYNC : JobName.SIDECAR_DISCOVERY, - data: { id: asset.id }, - })), - ); + const assets = this.assetJobRepository.streamForSidecar(force); + for await (const asset of assets) { + jobs.push({ name: force ? JobName.SIDECAR_SYNC : JobName.SIDECAR_DISCOVERY, data: { id: asset.id } }); + if (jobs.length >= JOBS_ASSET_PAGINATION_SIZE) { + await queueAll(); + } } + await queueAll(); + return JobStatus.SUCCESS; } @@ -576,6 +574,7 @@ export class MetadataService extends BaseService { this.logger.log(`Wrote motion photo video to ${motionAsset.originalPath}`); await this.handleMetadataExtraction({ id: motionAsset.id }); + await this.jobRepository.queue({ name: JobName.VIDEO_CONVERSION, data: { id: motionAsset.id } }); } this.logger.debug(`Finished motion photo video extraction for asset ${asset.id}: ${asset.originalPath}`); diff --git a/server/src/services/notification-admin.service.spec.ts b/server/src/services/notification-admin.service.spec.ts new file mode 100644 index 0000000000..4a747d41a3 --- /dev/null +++ b/server/src/services/notification-admin.service.spec.ts @@ -0,0 +1,111 @@ +import { defaults, SystemConfig } from 'src/config'; +import { EmailTemplate } from 'src/repositories/email.repository'; +import { NotificationService } from 'src/services/notification.service'; +import { userStub } from 'test/fixtures/user.stub'; +import { newTestService, ServiceMocks } from 'test/utils'; + +const smtpTransport = Object.freeze({ + ...defaults, + notifications: { + smtp: { + ...defaults.notifications.smtp, + enabled: true, + transport: { + ignoreCert: false, + host: 'localhost', + port: 587, + username: 'test', + password: 'test', + }, + }, + }, +}); + +describe(NotificationService.name, () => { + let sut: NotificationService; + let mocks: ServiceMocks; + + beforeEach(() => { + ({ sut, mocks } = newTestService(NotificationService)); + }); + + it('should work', () => { + expect(sut).toBeDefined(); + }); + + describe('sendTestEmail', () => { + it('should throw error if user could not be found', async () => { + await expect(sut.sendTestEmail('', smtpTransport.notifications.smtp)).rejects.toThrow('User not found'); + }); + + it('should throw error if smtp validation fails', async () => { + mocks.user.get.mockResolvedValue(userStub.admin); + mocks.email.verifySmtp.mockRejectedValue(''); + + await expect(sut.sendTestEmail('', smtpTransport.notifications.smtp)).rejects.toThrow( + 'Failed to verify SMTP configuration', + ); + }); + + it('should send email to default domain', async () => { + mocks.user.get.mockResolvedValue(userStub.admin); + mocks.email.verifySmtp.mockResolvedValue(true); + mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' }); + mocks.email.sendEmail.mockResolvedValue({ messageId: 'message-1', response: '' }); + + await expect(sut.sendTestEmail('', smtpTransport.notifications.smtp)).resolves.not.toThrow(); + expect(mocks.email.renderEmail).toHaveBeenCalledWith({ + template: EmailTemplate.TEST_EMAIL, + data: { baseUrl: 'https://my.immich.app', displayName: userStub.admin.name }, + }); + expect(mocks.email.sendEmail).toHaveBeenCalledWith( + expect.objectContaining({ + subject: 'Test email from Immich', + smtp: smtpTransport.notifications.smtp.transport, + }), + ); + }); + + it('should send email to external domain', async () => { + mocks.user.get.mockResolvedValue(userStub.admin); + mocks.email.verifySmtp.mockResolvedValue(true); + mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' }); + mocks.systemMetadata.get.mockResolvedValue({ server: { externalDomain: 'https://demo.immich.app' } }); + mocks.email.sendEmail.mockResolvedValue({ messageId: 'message-1', response: '' }); + + await expect(sut.sendTestEmail('', smtpTransport.notifications.smtp)).resolves.not.toThrow(); + expect(mocks.email.renderEmail).toHaveBeenCalledWith({ + template: EmailTemplate.TEST_EMAIL, + data: { baseUrl: 'https://demo.immich.app', displayName: userStub.admin.name }, + }); + expect(mocks.email.sendEmail).toHaveBeenCalledWith( + expect.objectContaining({ + subject: 'Test email from Immich', + smtp: smtpTransport.notifications.smtp.transport, + }), + ); + }); + + it('should send email with replyTo', async () => { + mocks.user.get.mockResolvedValue(userStub.admin); + mocks.email.verifySmtp.mockResolvedValue(true); + mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' }); + mocks.email.sendEmail.mockResolvedValue({ messageId: 'message-1', response: '' }); + + await expect( + sut.sendTestEmail('', { ...smtpTransport.notifications.smtp, replyTo: 'demo@immich.app' }), + ).resolves.not.toThrow(); + expect(mocks.email.renderEmail).toHaveBeenCalledWith({ + template: EmailTemplate.TEST_EMAIL, + data: { baseUrl: 'https://my.immich.app', displayName: userStub.admin.name }, + }); + expect(mocks.email.sendEmail).toHaveBeenCalledWith( + expect.objectContaining({ + subject: 'Test email from Immich', + smtp: smtpTransport.notifications.smtp.transport, + replyTo: 'demo@immich.app', + }), + ); + }); + }); +}); diff --git a/server/src/services/notification-admin.service.ts b/server/src/services/notification-admin.service.ts new file mode 100644 index 0000000000..bf0d2bba41 --- /dev/null +++ b/server/src/services/notification-admin.service.ts @@ -0,0 +1,120 @@ +import { BadRequestException, Injectable } from '@nestjs/common'; +import { AuthDto } from 'src/dtos/auth.dto'; +import { mapNotification, NotificationCreateDto } from 'src/dtos/notification.dto'; +import { SystemConfigSmtpDto } from 'src/dtos/system-config.dto'; +import { NotificationLevel, NotificationType } from 'src/enum'; +import { EmailTemplate } from 'src/repositories/email.repository'; +import { BaseService } from 'src/services/base.service'; +import { getExternalDomain } from 'src/utils/misc'; + +@Injectable() +export class NotificationAdminService extends BaseService { + async create(auth: AuthDto, dto: NotificationCreateDto) { + const item = await this.notificationRepository.create({ + userId: dto.userId, + type: dto.type ?? NotificationType.Custom, + level: dto.level ?? NotificationLevel.Info, + title: dto.title, + description: dto.description, + data: dto.data, + }); + + return mapNotification(item); + } + + async sendTestEmail(id: string, dto: SystemConfigSmtpDto, tempTemplate?: string) { + const user = await this.userRepository.get(id, { withDeleted: false }); + if (!user) { + throw new Error('User not found'); + } + + try { + await this.emailRepository.verifySmtp(dto.transport); + } catch (error) { + throw new BadRequestException('Failed to verify SMTP configuration', { cause: error }); + } + + const { server } = await this.getConfig({ withCache: false }); + const { html, text } = await this.emailRepository.renderEmail({ + template: EmailTemplate.TEST_EMAIL, + data: { + baseUrl: getExternalDomain(server), + displayName: user.name, + }, + customTemplate: tempTemplate!, + }); + const { messageId } = await this.emailRepository.sendEmail({ + to: user.email, + subject: 'Test email from Immich', + html, + text, + from: dto.from, + replyTo: dto.replyTo || dto.from, + smtp: dto.transport, + }); + + return { messageId }; + } + + async getTemplate(name: EmailTemplate, customTemplate: string) { + const { server, templates } = await this.getConfig({ withCache: false }); + + let templateResponse = ''; + + switch (name) { + case EmailTemplate.WELCOME: { + const { html: _welcomeHtml } = await this.emailRepository.renderEmail({ + template: EmailTemplate.WELCOME, + data: { + baseUrl: getExternalDomain(server), + displayName: 'John Doe', + username: 'john@doe.com', + password: 'thisIsAPassword123', + }, + customTemplate: customTemplate || templates.email.welcomeTemplate, + }); + + templateResponse = _welcomeHtml; + break; + } + case EmailTemplate.ALBUM_UPDATE: { + const { html: _updateAlbumHtml } = await this.emailRepository.renderEmail({ + template: EmailTemplate.ALBUM_UPDATE, + data: { + baseUrl: getExternalDomain(server), + albumId: '1', + albumName: 'Favorite Photos', + recipientName: 'Jane Doe', + cid: undefined, + }, + customTemplate: customTemplate || templates.email.albumInviteTemplate, + }); + templateResponse = _updateAlbumHtml; + break; + } + + case EmailTemplate.ALBUM_INVITE: { + const { html } = await this.emailRepository.renderEmail({ + template: EmailTemplate.ALBUM_INVITE, + data: { + baseUrl: getExternalDomain(server), + albumId: '1', + albumName: "John Doe's Favorites", + senderName: 'John Doe', + recipientName: 'Jane Doe', + cid: undefined, + }, + customTemplate: customTemplate || templates.email.albumInviteTemplate, + }); + templateResponse = html; + break; + } + default: { + templateResponse = ''; + break; + } + } + + return { name, html: templateResponse }; + } +} diff --git a/server/src/services/notification.service.spec.ts b/server/src/services/notification.service.spec.ts index 85e425b11f..133eb9e7f6 100644 --- a/server/src/services/notification.service.spec.ts +++ b/server/src/services/notification.service.spec.ts @@ -3,7 +3,6 @@ import { defaults, SystemConfig } from 'src/config'; import { AlbumUser } from 'src/database'; import { SystemConfigDto } from 'src/dtos/system-config.dto'; import { AssetFileType, JobName, JobStatus, UserMetadataKey } from 'src/enum'; -import { EmailTemplate } from 'src/repositories/notification.repository'; import { NotificationService } from 'src/services/notification.service'; import { INotifyAlbumUpdateJob } from 'src/types'; import { albumStub } from 'test/fixtures/album.stub'; @@ -74,18 +73,18 @@ describe(NotificationService.name, () => { const oldConfig = configs.smtpDisabled; const newConfig = configs.smtpEnabled; - mocks.notification.verifySmtp.mockResolvedValue(true); + mocks.email.verifySmtp.mockResolvedValue(true); await expect(sut.onConfigValidate({ oldConfig, newConfig })).resolves.not.toThrow(); - expect(mocks.notification.verifySmtp).toHaveBeenCalledWith(newConfig.notifications.smtp.transport); + expect(mocks.email.verifySmtp).toHaveBeenCalledWith(newConfig.notifications.smtp.transport); }); it('validates smtp config when transport changes', async () => { const oldConfig = configs.smtpEnabled; const newConfig = configs.smtpTransport; - mocks.notification.verifySmtp.mockResolvedValue(true); + mocks.email.verifySmtp.mockResolvedValue(true); await expect(sut.onConfigValidate({ oldConfig, newConfig })).resolves.not.toThrow(); - expect(mocks.notification.verifySmtp).toHaveBeenCalledWith(newConfig.notifications.smtp.transport); + expect(mocks.email.verifySmtp).toHaveBeenCalledWith(newConfig.notifications.smtp.transport); }); it('skips smtp validation when there are no changes', async () => { @@ -93,7 +92,7 @@ describe(NotificationService.name, () => { const newConfig = { ...configs.smtpEnabled }; await expect(sut.onConfigValidate({ oldConfig, newConfig })).resolves.not.toThrow(); - expect(mocks.notification.verifySmtp).not.toHaveBeenCalled(); + expect(mocks.email.verifySmtp).not.toHaveBeenCalled(); }); it('skips smtp validation with DTO when there are no changes', async () => { @@ -101,7 +100,7 @@ describe(NotificationService.name, () => { const newConfig = plainToInstance(SystemConfigDto, configs.smtpEnabled); await expect(sut.onConfigValidate({ oldConfig, newConfig })).resolves.not.toThrow(); - expect(mocks.notification.verifySmtp).not.toHaveBeenCalled(); + expect(mocks.email.verifySmtp).not.toHaveBeenCalled(); }); it('skips smtp validation when smtp is disabled', async () => { @@ -109,14 +108,14 @@ describe(NotificationService.name, () => { const newConfig = { ...configs.smtpDisabled }; await expect(sut.onConfigValidate({ oldConfig, newConfig })).resolves.not.toThrow(); - expect(mocks.notification.verifySmtp).not.toHaveBeenCalled(); + expect(mocks.email.verifySmtp).not.toHaveBeenCalled(); }); it('should fail if smtp configuration is invalid', async () => { const oldConfig = configs.smtpDisabled; const newConfig = configs.smtpEnabled; - mocks.notification.verifySmtp.mockRejectedValue(new Error('Failed validating smtp')); + mocks.email.verifySmtp.mockRejectedValue(new Error('Failed validating smtp')); await expect(sut.onConfigValidate({ oldConfig, newConfig })).rejects.toBeInstanceOf(Error); }); }); @@ -241,82 +240,6 @@ describe(NotificationService.name, () => { }); }); - describe('sendTestEmail', () => { - it('should throw error if user could not be found', async () => { - await expect(sut.sendTestEmail('', configs.smtpTransport.notifications.smtp)).rejects.toThrow('User not found'); - }); - - it('should throw error if smtp validation fails', async () => { - mocks.user.get.mockResolvedValue(userStub.admin); - mocks.notification.verifySmtp.mockRejectedValue(''); - - await expect(sut.sendTestEmail('', configs.smtpTransport.notifications.smtp)).rejects.toThrow( - 'Failed to verify SMTP configuration', - ); - }); - - it('should send email to default domain', async () => { - mocks.user.get.mockResolvedValue(userStub.admin); - mocks.notification.verifySmtp.mockResolvedValue(true); - mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' }); - mocks.notification.sendEmail.mockResolvedValue({ messageId: 'message-1', response: '' }); - - await expect(sut.sendTestEmail('', configs.smtpTransport.notifications.smtp)).resolves.not.toThrow(); - expect(mocks.notification.renderEmail).toHaveBeenCalledWith({ - template: EmailTemplate.TEST_EMAIL, - data: { baseUrl: 'https://my.immich.app', displayName: userStub.admin.name }, - }); - expect(mocks.notification.sendEmail).toHaveBeenCalledWith( - expect.objectContaining({ - subject: 'Test email from Immich', - smtp: configs.smtpTransport.notifications.smtp.transport, - }), - ); - }); - - it('should send email to external domain', async () => { - mocks.user.get.mockResolvedValue(userStub.admin); - mocks.notification.verifySmtp.mockResolvedValue(true); - mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' }); - mocks.systemMetadata.get.mockResolvedValue({ server: { externalDomain: 'https://demo.immich.app' } }); - mocks.notification.sendEmail.mockResolvedValue({ messageId: 'message-1', response: '' }); - - await expect(sut.sendTestEmail('', configs.smtpTransport.notifications.smtp)).resolves.not.toThrow(); - expect(mocks.notification.renderEmail).toHaveBeenCalledWith({ - template: EmailTemplate.TEST_EMAIL, - data: { baseUrl: 'https://demo.immich.app', displayName: userStub.admin.name }, - }); - expect(mocks.notification.sendEmail).toHaveBeenCalledWith( - expect.objectContaining({ - subject: 'Test email from Immich', - smtp: configs.smtpTransport.notifications.smtp.transport, - }), - ); - }); - - it('should send email with replyTo', async () => { - mocks.user.get.mockResolvedValue(userStub.admin); - mocks.notification.verifySmtp.mockResolvedValue(true); - mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' }); - mocks.notification.sendEmail.mockResolvedValue({ messageId: 'message-1', response: '' }); - - await expect( - sut.sendTestEmail('', { ...configs.smtpTransport.notifications.smtp, replyTo: 'demo@immich.app' }), - ).resolves.not.toThrow(); - expect(mocks.notification.renderEmail).toHaveBeenCalledWith({ - template: EmailTemplate.TEST_EMAIL, - data: { baseUrl: 'https://my.immich.app', displayName: userStub.admin.name }, - }); - expect(mocks.notification.sendEmail).toHaveBeenCalledWith( - expect.objectContaining({ - subject: 'Test email from Immich', - smtp: configs.smtpTransport.notifications.smtp.transport, - replyTo: 'demo@immich.app', - }), - ); - }); - }); - describe('handleUserSignup', () => { it('should skip if user could not be found', async () => { await expect(sut.handleUserSignup({ id: '' })).resolves.toBe(JobStatus.SKIPPED); @@ -325,7 +248,7 @@ describe(NotificationService.name, () => { it('should be successful', async () => { mocks.user.get.mockResolvedValue(userStub.admin); mocks.systemMetadata.get.mockResolvedValue({ server: {} }); - mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' }); + mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' }); await expect(sut.handleUserSignup({ id: '' })).resolves.toBe(JobStatus.SUCCESS); expect(mocks.job.queue).toHaveBeenCalledWith({ @@ -390,7 +313,7 @@ describe(NotificationService.name, () => { ], }); mocks.systemMetadata.get.mockResolvedValue({ server: {} }); - mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' }); + mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' }); await expect(sut.handleAlbumInvite({ id: '', recipientId: '' })).resolves.toBe(JobStatus.SUCCESS); expect(mocks.job.queue).toHaveBeenCalledWith({ @@ -411,7 +334,7 @@ describe(NotificationService.name, () => { ], }); mocks.systemMetadata.get.mockResolvedValue({ server: {} }); - mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' }); + mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' }); mocks.assetJob.getAlbumThumbnailFiles.mockResolvedValue([]); await expect(sut.handleAlbumInvite({ id: '', recipientId: '' })).resolves.toBe(JobStatus.SUCCESS); @@ -440,7 +363,7 @@ describe(NotificationService.name, () => { ], }); mocks.systemMetadata.get.mockResolvedValue({ server: {} }); - mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' }); + mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' }); mocks.assetJob.getAlbumThumbnailFiles.mockResolvedValue([ { id: '1', type: AssetFileType.THUMBNAIL, path: 'path-to-thumb.jpg' }, ]); @@ -471,7 +394,7 @@ describe(NotificationService.name, () => { ], }); mocks.systemMetadata.get.mockResolvedValue({ server: {} }); - mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' }); + mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' }); mocks.assetJob.getAlbumThumbnailFiles.mockResolvedValue([assetStub.image.files[2]]); await expect(sut.handleAlbumInvite({ id: '', recipientId: '' })).resolves.toBe(JobStatus.SUCCESS); @@ -508,12 +431,12 @@ describe(NotificationService.name, () => { albumUsers: [{ user: { id: userStub.user1.id } } as AlbumUser], }); mocks.user.get.mockResolvedValueOnce(userStub.user1); - mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' }); + mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' }); mocks.assetJob.getAlbumThumbnailFiles.mockResolvedValue([]); await sut.handleAlbumUpdate({ id: '', recipientIds: [userStub.user1.id] }); expect(mocks.user.get).toHaveBeenCalledWith(userStub.user1.id, { withDeleted: false }); - expect(mocks.notification.renderEmail).not.toHaveBeenCalled(); + expect(mocks.email.renderEmail).not.toHaveBeenCalled(); }); it('should skip recipient with disabled email notifications', async () => { @@ -530,12 +453,12 @@ describe(NotificationService.name, () => { }, ], }); - mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' }); + mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' }); mocks.assetJob.getAlbumThumbnailFiles.mockResolvedValue([]); await sut.handleAlbumUpdate({ id: '', recipientIds: [userStub.user1.id] }); expect(mocks.user.get).toHaveBeenCalledWith(userStub.user1.id, { withDeleted: false }); - expect(mocks.notification.renderEmail).not.toHaveBeenCalled(); + expect(mocks.email.renderEmail).not.toHaveBeenCalled(); }); it('should skip recipient with disabled email notifications for the album update event', async () => { @@ -552,12 +475,12 @@ describe(NotificationService.name, () => { }, ], }); - mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' }); + mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' }); mocks.assetJob.getAlbumThumbnailFiles.mockResolvedValue([]); await sut.handleAlbumUpdate({ id: '', recipientIds: [userStub.user1.id] }); expect(mocks.user.get).toHaveBeenCalledWith(userStub.user1.id, { withDeleted: false }); - expect(mocks.notification.renderEmail).not.toHaveBeenCalled(); + expect(mocks.email.renderEmail).not.toHaveBeenCalled(); }); it('should send email', async () => { @@ -566,12 +489,12 @@ describe(NotificationService.name, () => { albumUsers: [{ user: { id: userStub.user1.id } } as AlbumUser], }); mocks.user.get.mockResolvedValue(userStub.user1); - mocks.notification.renderEmail.mockResolvedValue({ html: '', text: '' }); + mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' }); mocks.assetJob.getAlbumThumbnailFiles.mockResolvedValue([]); await sut.handleAlbumUpdate({ id: '', recipientIds: [userStub.user1.id] }); expect(mocks.user.get).toHaveBeenCalledWith(userStub.user1.id, { withDeleted: false }); - expect(mocks.notification.renderEmail).toHaveBeenCalled(); + expect(mocks.email.renderEmail).toHaveBeenCalled(); expect(mocks.job.queue).toHaveBeenCalled(); }); @@ -599,24 +522,20 @@ describe(NotificationService.name, () => { mocks.systemMetadata.get.mockResolvedValue({ notifications: { smtp: { enabled: true, from: 'test@immich.app' } }, }); - mocks.notification.sendEmail.mockResolvedValue({ messageId: '', response: '' }); + mocks.email.sendEmail.mockResolvedValue({ messageId: '', response: '' }); await expect(sut.handleSendEmail({ html: '', subject: '', text: '', to: '' })).resolves.toBe(JobStatus.SUCCESS); - expect(mocks.notification.sendEmail).toHaveBeenCalledWith( - expect.objectContaining({ replyTo: 'test@immich.app' }), - ); + expect(mocks.email.sendEmail).toHaveBeenCalledWith(expect.objectContaining({ replyTo: 'test@immich.app' })); }); it('should send mail with replyTo successfully', async () => { mocks.systemMetadata.get.mockResolvedValue({ notifications: { smtp: { enabled: true, from: 'test@immich.app', replyTo: 'demo@immich.app' } }, }); - mocks.notification.sendEmail.mockResolvedValue({ messageId: '', response: '' }); + mocks.email.sendEmail.mockResolvedValue({ messageId: '', response: '' }); await expect(sut.handleSendEmail({ html: '', subject: '', text: '', to: '' })).resolves.toBe(JobStatus.SUCCESS); - expect(mocks.notification.sendEmail).toHaveBeenCalledWith( - expect.objectContaining({ replyTo: 'demo@immich.app' }), - ); + expect(mocks.email.sendEmail).toHaveBeenCalledWith(expect.objectContaining({ replyTo: 'demo@immich.app' })); }); }); }); diff --git a/server/src/services/notification.service.ts b/server/src/services/notification.service.ts index 2c4cc76756..be475d1dca 100644 --- a/server/src/services/notification.service.ts +++ b/server/src/services/notification.service.ts @@ -1,9 +1,26 @@ import { BadRequestException, Injectable } from '@nestjs/common'; import { OnEvent, OnJob } from 'src/decorators'; +import { AuthDto } from 'src/dtos/auth.dto'; +import { + mapNotification, + NotificationDeleteAllDto, + NotificationDto, + NotificationSearchDto, + NotificationUpdateAllDto, + NotificationUpdateDto, +} from 'src/dtos/notification.dto'; import { SystemConfigSmtpDto } from 'src/dtos/system-config.dto'; -import { AssetFileType, JobName, JobStatus, QueueName } from 'src/enum'; +import { + AssetFileType, + JobName, + JobStatus, + NotificationLevel, + NotificationType, + Permission, + QueueName, +} from 'src/enum'; +import { EmailTemplate } from 'src/repositories/email.repository'; import { ArgOf } from 'src/repositories/event.repository'; -import { EmailTemplate } from 'src/repositories/notification.repository'; import { BaseService } from 'src/services/base.service'; import { EmailImageAttachment, IEntityJob, INotifyAlbumUpdateJob, JobItem, JobOf } from 'src/types'; import { getFilenameExtension } from 'src/utils/file'; @@ -15,6 +32,80 @@ import { getPreferences } from 'src/utils/preferences'; export class NotificationService extends BaseService { private static albumUpdateEmailDelayMs = 300_000; + async search(auth: AuthDto, dto: NotificationSearchDto): Promise { + const items = await this.notificationRepository.search(auth.user.id, dto); + return items.map((item) => mapNotification(item)); + } + + async updateAll(auth: AuthDto, dto: NotificationUpdateAllDto) { + await this.requireAccess({ auth, ids: dto.ids, permission: Permission.NOTIFICATION_UPDATE }); + await this.notificationRepository.updateAll(dto.ids, { + readAt: dto.readAt, + }); + } + + async deleteAll(auth: AuthDto, dto: NotificationDeleteAllDto) { + await this.requireAccess({ auth, ids: dto.ids, permission: Permission.NOTIFICATION_DELETE }); + await this.notificationRepository.deleteAll(dto.ids); + } + + async get(auth: AuthDto, id: string) { + await this.requireAccess({ auth, ids: [id], permission: Permission.NOTIFICATION_READ }); + const item = await this.notificationRepository.get(id); + if (!item) { + throw new BadRequestException('Notification not found'); + } + return mapNotification(item); + } + + async update(auth: AuthDto, id: string, dto: NotificationUpdateDto) { + await this.requireAccess({ auth, ids: [id], permission: Permission.NOTIFICATION_UPDATE }); + const item = await this.notificationRepository.update(id, { + readAt: dto.readAt, + }); + return mapNotification(item); + } + + async delete(auth: AuthDto, id: string) { + await this.requireAccess({ auth, ids: [id], permission: Permission.NOTIFICATION_DELETE }); + await this.notificationRepository.delete(id); + } + + @OnJob({ name: JobName.NOTIFICATIONS_CLEANUP, queue: QueueName.BACKGROUND_TASK }) + async onNotificationsCleanup() { + await this.notificationRepository.cleanup(); + } + + @OnEvent({ name: 'job.failed' }) + async onJobFailed({ job, error }: ArgOf<'job.failed'>) { + const admin = await this.userRepository.getAdmin(); + if (!admin) { + return; + } + + this.logger.error(`Unable to run job handler (${job.name}): ${error}`, error?.stack, JSON.stringify(job.data)); + + switch (job.name) { + case JobName.BACKUP_DATABASE: { + const errorMessage = error instanceof Error ? error.message : error; + const item = await this.notificationRepository.create({ + userId: admin.id, + type: NotificationType.JobFailed, + level: NotificationLevel.Error, + title: 'Job Failed', + description: `Job ${[job.name]} failed with error: ${errorMessage}`, + }); + + this.eventRepository.clientSend('on_notification', admin.id, mapNotification(item)); + break; + } + + default: { + return; + } + } + } + @OnEvent({ name: 'config.update' }) onConfigUpdate({ oldConfig, newConfig }: ArgOf<'config.update'>) { this.eventRepository.clientBroadcast('on_config_update'); @@ -28,7 +119,7 @@ export class NotificationService extends BaseService { newConfig.notifications.smtp.enabled && !isEqualObject(oldConfig.notifications.smtp, newConfig.notifications.smtp) ) { - await this.notificationRepository.verifySmtp(newConfig.notifications.smtp.transport); + await this.emailRepository.verifySmtp(newConfig.notifications.smtp.transport); } } catch (error: Error | any) { this.logger.error(`Failed to validate SMTP configuration: ${error}`, error?.stack); @@ -138,13 +229,13 @@ export class NotificationService extends BaseService { } try { - await this.notificationRepository.verifySmtp(dto.transport); + await this.emailRepository.verifySmtp(dto.transport); } catch (error) { throw new BadRequestException('Failed to verify SMTP configuration', { cause: error }); } const { server } = await this.getConfig({ withCache: false }); - const { html, text } = await this.notificationRepository.renderEmail({ + const { html, text } = await this.emailRepository.renderEmail({ template: EmailTemplate.TEST_EMAIL, data: { baseUrl: getExternalDomain(server), @@ -152,7 +243,7 @@ export class NotificationService extends BaseService { }, customTemplate: tempTemplate!, }); - const { messageId } = await this.notificationRepository.sendEmail({ + const { messageId } = await this.emailRepository.sendEmail({ to: user.email, subject: 'Test email from Immich', html, @@ -172,7 +263,7 @@ export class NotificationService extends BaseService { switch (name) { case EmailTemplate.WELCOME: { - const { html: _welcomeHtml } = await this.notificationRepository.renderEmail({ + const { html: _welcomeHtml } = await this.emailRepository.renderEmail({ template: EmailTemplate.WELCOME, data: { baseUrl: getExternalDomain(server), @@ -187,7 +278,7 @@ export class NotificationService extends BaseService { break; } case EmailTemplate.ALBUM_UPDATE: { - const { html: _updateAlbumHtml } = await this.notificationRepository.renderEmail({ + const { html: _updateAlbumHtml } = await this.emailRepository.renderEmail({ template: EmailTemplate.ALBUM_UPDATE, data: { baseUrl: getExternalDomain(server), @@ -203,7 +294,7 @@ export class NotificationService extends BaseService { } case EmailTemplate.ALBUM_INVITE: { - const { html } = await this.notificationRepository.renderEmail({ + const { html } = await this.emailRepository.renderEmail({ template: EmailTemplate.ALBUM_INVITE, data: { baseUrl: getExternalDomain(server), @@ -235,7 +326,7 @@ export class NotificationService extends BaseService { } const { server, templates } = await this.getConfig({ withCache: true }); - const { html, text } = await this.notificationRepository.renderEmail({ + const { html, text } = await this.emailRepository.renderEmail({ template: EmailTemplate.WELCOME, data: { baseUrl: getExternalDomain(server), @@ -271,7 +362,7 @@ export class NotificationService extends BaseService { return JobStatus.SKIPPED; } - const { emailNotifications } = getPreferences(recipient.email, recipient.metadata); + const { emailNotifications } = getPreferences(recipient.metadata); if (!emailNotifications.enabled || !emailNotifications.albumInvite) { return JobStatus.SKIPPED; @@ -280,7 +371,7 @@ export class NotificationService extends BaseService { const attachment = await this.getAlbumThumbnailAttachment(album); const { server, templates } = await this.getConfig({ withCache: false }); - const { html, text } = await this.notificationRepository.renderEmail({ + const { html, text } = await this.emailRepository.renderEmail({ template: EmailTemplate.ALBUM_INVITE, data: { baseUrl: getExternalDomain(server), @@ -333,13 +424,13 @@ export class NotificationService extends BaseService { continue; } - const { emailNotifications } = getPreferences(user.email, user.metadata); + const { emailNotifications } = getPreferences(user.metadata); if (!emailNotifications.enabled || !emailNotifications.albumUpdate) { continue; } - const { html, text } = await this.notificationRepository.renderEmail({ + const { html, text } = await this.emailRepository.renderEmail({ template: EmailTemplate.ALBUM_UPDATE, data: { baseUrl: getExternalDomain(server), @@ -374,7 +465,7 @@ export class NotificationService extends BaseService { } const { to, subject, html, text: plain } = data; - const response = await this.notificationRepository.sendEmail({ + const response = await this.emailRepository.sendEmail({ to, subject, html, diff --git a/server/src/services/person.service.spec.ts b/server/src/services/person.service.spec.ts index 9808522434..5b88883472 100644 --- a/server/src/services/person.service.spec.ts +++ b/server/src/services/person.service.spec.ts @@ -2,7 +2,6 @@ import { BadRequestException, NotFoundException } from '@nestjs/common'; import { BulkIdErrorReason } from 'src/dtos/asset-ids.response.dto'; import { mapFaces, mapPerson, PersonResponseDto } from 'src/dtos/person.dto'; import { CacheControl, Colorspace, ImageFormat, JobName, JobStatus, SourceType, SystemMetadataKey } from 'src/enum'; -import { WithoutProperty } from 'src/repositories/asset.repository'; import { DetectedFaces } from 'src/repositories/machine-learning.repository'; import { FaceSearchResult } from 'src/repositories/search.repository'; import { PersonService } from 'src/services/person.service'; @@ -455,14 +454,11 @@ describe(PersonService.name, () => { }); it('should queue missing assets', async () => { - mocks.asset.getWithout.mockResolvedValue({ - items: [assetStub.image], - hasNextPage: false, - }); + mocks.assetJob.streamForDetectFacesJob.mockReturnValue(makeStream([assetStub.image])); await sut.handleQueueDetectFaces({ force: false }); - expect(mocks.asset.getWithout).toHaveBeenCalledWith({ skip: 0, take: 1000 }, WithoutProperty.FACES); + expect(mocks.assetJob.streamForDetectFacesJob).toHaveBeenCalledWith(false); expect(mocks.job.queueAll).toHaveBeenCalledWith([ { name: JobName.FACE_DETECTION, @@ -472,10 +468,7 @@ describe(PersonService.name, () => { }); it('should queue all assets', async () => { - mocks.asset.getAll.mockResolvedValue({ - items: [assetStub.image], - hasNextPage: false, - }); + mocks.assetJob.streamForDetectFacesJob.mockReturnValue(makeStream([assetStub.image])); mocks.person.getAllWithoutFaces.mockResolvedValue([personStub.withName]); await sut.handleQueueDetectFaces({ force: true }); @@ -483,7 +476,7 @@ describe(PersonService.name, () => { expect(mocks.person.deleteFaces).toHaveBeenCalledWith({ sourceType: SourceType.MACHINE_LEARNING }); expect(mocks.person.delete).toHaveBeenCalledWith([personStub.withName.id]); expect(mocks.storage.unlink).toHaveBeenCalledWith(personStub.withName.thumbnailPath); - expect(mocks.asset.getAll).toHaveBeenCalled(); + expect(mocks.assetJob.streamForDetectFacesJob).toHaveBeenCalledWith(true); expect(mocks.job.queueAll).toHaveBeenCalledWith([ { name: JobName.FACE_DETECTION, @@ -493,17 +486,14 @@ describe(PersonService.name, () => { }); it('should refresh all assets', async () => { - mocks.asset.getAll.mockResolvedValue({ - items: [assetStub.image], - hasNextPage: false, - }); + mocks.assetJob.streamForDetectFacesJob.mockReturnValue(makeStream([assetStub.image])); await sut.handleQueueDetectFaces({ force: undefined }); expect(mocks.person.delete).not.toHaveBeenCalled(); expect(mocks.person.deleteFaces).not.toHaveBeenCalled(); expect(mocks.storage.unlink).not.toHaveBeenCalled(); - expect(mocks.asset.getAll).toHaveBeenCalled(); + expect(mocks.assetJob.streamForDetectFacesJob).toHaveBeenCalledWith(undefined); expect(mocks.job.queueAll).toHaveBeenCalledWith([ { name: JobName.FACE_DETECTION, @@ -516,16 +506,13 @@ describe(PersonService.name, () => { it('should delete existing people and faces if forced', async () => { mocks.person.getAll.mockReturnValue(makeStream([faceStub.face1.person, personStub.randomPerson])); mocks.person.getAllFaces.mockReturnValue(makeStream([faceStub.face1])); - mocks.asset.getAll.mockResolvedValue({ - items: [assetStub.image], - hasNextPage: false, - }); + mocks.assetJob.streamForDetectFacesJob.mockReturnValue(makeStream([assetStub.image])); mocks.person.getAllWithoutFaces.mockResolvedValue([personStub.randomPerson]); mocks.person.deleteFaces.mockResolvedValue(); await sut.handleQueueDetectFaces({ force: true }); - expect(mocks.asset.getAll).toHaveBeenCalled(); + expect(mocks.assetJob.streamForDetectFacesJob).toHaveBeenCalledWith(true); expect(mocks.job.queueAll).toHaveBeenCalledWith([ { name: JobName.FACE_DETECTION, diff --git a/server/src/services/person.service.ts b/server/src/services/person.service.ts index 66d68857a0..227ea3c1c2 100644 --- a/server/src/services/person.service.ts +++ b/server/src/services/person.service.ts @@ -36,7 +36,6 @@ import { SourceType, SystemMetadataKey, } from 'src/enum'; -import { WithoutProperty } from 'src/repositories/asset.repository'; import { BoundingBox } from 'src/repositories/machine-learning.repository'; import { UpdateFacesData } from 'src/repositories/person.repository'; import { BaseService } from 'src/services/base.service'; @@ -44,7 +43,6 @@ import { CropOptions, ImageDimensions, InputDimensions, JobItem, JobOf } from 's import { ImmichFileResponse } from 'src/utils/file'; import { mimeTypes } from 'src/utils/mime-types'; import { isFaceImportEnabled, isFacialRecognitionEnabled } from 'src/utils/misc'; -import { usePagination } from 'src/utils/pagination'; @Injectable() export class PersonService extends BaseService { @@ -265,23 +263,19 @@ export class PersonService extends BaseService { await this.handlePersonCleanup(); } - const assetPagination = usePagination(JOBS_ASSET_PAGINATION_SIZE, (pagination) => { - return force === false - ? this.assetRepository.getWithout(pagination, WithoutProperty.FACES) - : this.assetRepository.getAll(pagination, { - orderDirection: 'desc', - withFaces: true, - withArchived: true, - isVisible: true, - }); - }); + let jobs: JobItem[] = []; + const assets = this.assetJobRepository.streamForDetectFacesJob(force); + for await (const asset of assets) { + jobs.push({ name: JobName.FACE_DETECTION, data: { id: asset.id } }); - for await (const assets of assetPagination) { - await this.jobRepository.queueAll( - assets.map((asset) => ({ name: JobName.FACE_DETECTION, data: { id: asset.id } })), - ); + if (jobs.length >= JOBS_ASSET_PAGINATION_SIZE) { + await this.jobRepository.queueAll(jobs); + jobs = []; + } } + await this.jobRepository.queueAll(jobs); + if (force === undefined) { await this.jobRepository.queue({ name: JobName.PERSON_CLEANUP }); } diff --git a/server/src/services/smart-info.service.spec.ts b/server/src/services/smart-info.service.spec.ts index df26e69108..9cc97a8f0d 100644 --- a/server/src/services/smart-info.service.spec.ts +++ b/server/src/services/smart-info.service.spec.ts @@ -1,11 +1,10 @@ import { SystemConfig } from 'src/config'; import { ImmichWorker, JobName, JobStatus } from 'src/enum'; -import { WithoutProperty } from 'src/repositories/asset.repository'; import { SmartInfoService } from 'src/services/smart-info.service'; import { getCLIPModelInfo } from 'src/utils/misc'; import { assetStub } from 'test/fixtures/asset.stub'; import { systemConfigStub } from 'test/fixtures/system-config.stub'; -import { newTestService, ServiceMocks } from 'test/utils'; +import { makeStream, newTestService, ServiceMocks } from 'test/utils'; describe(SmartInfoService.name, () => { let sut: SmartInfoService; @@ -58,10 +57,6 @@ describe(SmartInfoService.name, () => { expect(mocks.search.getDimensionSize).not.toHaveBeenCalled(); expect(mocks.search.setDimensionSize).not.toHaveBeenCalled(); expect(mocks.search.deleteAllSearchEmbeddings).not.toHaveBeenCalled(); - expect(mocks.job.getQueueStatus).not.toHaveBeenCalled(); - expect(mocks.job.pause).not.toHaveBeenCalled(); - expect(mocks.job.waitForQueueCompletion).not.toHaveBeenCalled(); - expect(mocks.job.resume).not.toHaveBeenCalled(); }); it('should return if model and DB dimension size are equal', async () => { @@ -72,38 +67,15 @@ describe(SmartInfoService.name, () => { expect(mocks.search.getDimensionSize).toHaveBeenCalledTimes(1); expect(mocks.search.setDimensionSize).not.toHaveBeenCalled(); expect(mocks.search.deleteAllSearchEmbeddings).not.toHaveBeenCalled(); - expect(mocks.job.getQueueStatus).not.toHaveBeenCalled(); - expect(mocks.job.pause).not.toHaveBeenCalled(); - expect(mocks.job.waitForQueueCompletion).not.toHaveBeenCalled(); - expect(mocks.job.resume).not.toHaveBeenCalled(); }); it('should update DB dimension size if model and DB have different values', async () => { mocks.search.getDimensionSize.mockResolvedValue(768); - mocks.job.getQueueStatus.mockResolvedValue({ isActive: false, isPaused: false }); await sut.onConfigInit({ newConfig: systemConfigStub.machineLearningEnabled as SystemConfig }); expect(mocks.search.getDimensionSize).toHaveBeenCalledTimes(1); expect(mocks.search.setDimensionSize).toHaveBeenCalledWith(512); - expect(mocks.job.getQueueStatus).toHaveBeenCalledTimes(1); - expect(mocks.job.pause).toHaveBeenCalledTimes(1); - expect(mocks.job.waitForQueueCompletion).toHaveBeenCalledTimes(1); - expect(mocks.job.resume).toHaveBeenCalledTimes(1); - }); - - it('should skip pausing and resuming queue if already paused', async () => { - mocks.search.getDimensionSize.mockResolvedValue(768); - mocks.job.getQueueStatus.mockResolvedValue({ isActive: false, isPaused: true }); - - await sut.onConfigInit({ newConfig: systemConfigStub.machineLearningEnabled as SystemConfig }); - - expect(mocks.search.getDimensionSize).toHaveBeenCalledTimes(1); - expect(mocks.search.setDimensionSize).toHaveBeenCalledWith(512); - expect(mocks.job.getQueueStatus).toHaveBeenCalledTimes(1); - expect(mocks.job.pause).not.toHaveBeenCalled(); - expect(mocks.job.waitForQueueCompletion).toHaveBeenCalledTimes(1); - expect(mocks.job.resume).not.toHaveBeenCalled(); }); }); @@ -120,10 +92,6 @@ describe(SmartInfoService.name, () => { expect(mocks.search.getDimensionSize).not.toHaveBeenCalled(); expect(mocks.search.setDimensionSize).not.toHaveBeenCalled(); expect(mocks.search.deleteAllSearchEmbeddings).not.toHaveBeenCalled(); - expect(mocks.job.getQueueStatus).not.toHaveBeenCalled(); - expect(mocks.job.pause).not.toHaveBeenCalled(); - expect(mocks.job.waitForQueueCompletion).not.toHaveBeenCalled(); - expect(mocks.job.resume).not.toHaveBeenCalled(); }); it('should return if model and DB dimension size are equal', async () => { @@ -141,15 +109,10 @@ describe(SmartInfoService.name, () => { expect(mocks.search.getDimensionSize).toHaveBeenCalledTimes(1); expect(mocks.search.setDimensionSize).not.toHaveBeenCalled(); expect(mocks.search.deleteAllSearchEmbeddings).not.toHaveBeenCalled(); - expect(mocks.job.getQueueStatus).not.toHaveBeenCalled(); - expect(mocks.job.pause).not.toHaveBeenCalled(); - expect(mocks.job.waitForQueueCompletion).not.toHaveBeenCalled(); - expect(mocks.job.resume).not.toHaveBeenCalled(); }); it('should update DB dimension size if model and DB have different values', async () => { mocks.search.getDimensionSize.mockResolvedValue(512); - mocks.job.getQueueStatus.mockResolvedValue({ isActive: false, isPaused: false }); await sut.onConfigUpdate({ newConfig: { @@ -162,15 +125,10 @@ describe(SmartInfoService.name, () => { expect(mocks.search.getDimensionSize).toHaveBeenCalledTimes(1); expect(mocks.search.setDimensionSize).toHaveBeenCalledWith(768); - expect(mocks.job.getQueueStatus).toHaveBeenCalledTimes(1); - expect(mocks.job.pause).toHaveBeenCalledTimes(1); - expect(mocks.job.waitForQueueCompletion).toHaveBeenCalledTimes(1); - expect(mocks.job.resume).toHaveBeenCalledTimes(1); }); it('should clear embeddings if old and new models are different', async () => { mocks.search.getDimensionSize.mockResolvedValue(512); - mocks.job.getQueueStatus.mockResolvedValue({ isActive: false, isPaused: false }); await sut.onConfigUpdate({ newConfig: { @@ -184,31 +142,6 @@ describe(SmartInfoService.name, () => { expect(mocks.search.deleteAllSearchEmbeddings).toHaveBeenCalled(); expect(mocks.search.getDimensionSize).toHaveBeenCalledTimes(1); expect(mocks.search.setDimensionSize).not.toHaveBeenCalled(); - expect(mocks.job.getQueueStatus).toHaveBeenCalledTimes(1); - expect(mocks.job.pause).toHaveBeenCalledTimes(1); - expect(mocks.job.waitForQueueCompletion).toHaveBeenCalledTimes(1); - expect(mocks.job.resume).toHaveBeenCalledTimes(1); - }); - - it('should skip pausing and resuming queue if already paused', async () => { - mocks.search.getDimensionSize.mockResolvedValue(512); - mocks.job.getQueueStatus.mockResolvedValue({ isActive: false, isPaused: true }); - - await sut.onConfigUpdate({ - newConfig: { - machineLearning: { clip: { modelName: 'ViT-B-32__openai', enabled: true }, enabled: true }, - } as SystemConfig, - oldConfig: { - machineLearning: { clip: { modelName: 'ViT-B-16__openai', enabled: true }, enabled: true }, - } as SystemConfig, - }); - - expect(mocks.search.getDimensionSize).toHaveBeenCalledTimes(1); - expect(mocks.search.setDimensionSize).not.toHaveBeenCalled(); - expect(mocks.job.getQueueStatus).toHaveBeenCalledTimes(1); - expect(mocks.job.pause).not.toHaveBeenCalled(); - expect(mocks.job.waitForQueueCompletion).toHaveBeenCalledTimes(1); - expect(mocks.job.resume).not.toHaveBeenCalled(); }); }); @@ -218,38 +151,31 @@ describe(SmartInfoService.name, () => { await sut.handleQueueEncodeClip({}); - expect(mocks.asset.getAll).not.toHaveBeenCalled(); - expect(mocks.asset.getWithout).not.toHaveBeenCalled(); + expect(mocks.search.setDimensionSize).not.toHaveBeenCalled(); }); it('should queue the assets without clip embeddings', async () => { - mocks.asset.getWithout.mockResolvedValue({ - items: [assetStub.image], - hasNextPage: false, - }); + mocks.assetJob.streamForEncodeClip.mockReturnValue(makeStream([assetStub.image])); await sut.handleQueueEncodeClip({ force: false }); expect(mocks.job.queueAll).toHaveBeenCalledWith([ { name: JobName.SMART_SEARCH, data: { id: assetStub.image.id } }, ]); - expect(mocks.asset.getWithout).toHaveBeenCalledWith({ skip: 0, take: 1000 }, WithoutProperty.SMART_SEARCH); - expect(mocks.search.deleteAllSearchEmbeddings).not.toHaveBeenCalled(); + expect(mocks.assetJob.streamForEncodeClip).toHaveBeenCalledWith(false); + expect(mocks.search.setDimensionSize).not.toHaveBeenCalled(); }); it('should queue all the assets', async () => { - mocks.asset.getAll.mockResolvedValue({ - items: [assetStub.image], - hasNextPage: false, - }); + mocks.assetJob.streamForEncodeClip.mockReturnValue(makeStream([assetStub.image])); await sut.handleQueueEncodeClip({ force: true }); expect(mocks.job.queueAll).toHaveBeenCalledWith([ { name: JobName.SMART_SEARCH, data: { id: assetStub.image.id } }, ]); - expect(mocks.asset.getAll).toHaveBeenCalled(); - expect(mocks.search.deleteAllSearchEmbeddings).toHaveBeenCalled(); + expect(mocks.assetJob.streamForEncodeClip).toHaveBeenCalledWith(true); + expect(mocks.search.setDimensionSize).toHaveBeenCalledExactlyOnceWith(512); }); }); diff --git a/server/src/services/smart-info.service.ts b/server/src/services/smart-info.service.ts index 411114eb17..5ee5dac57e 100644 --- a/server/src/services/smart-info.service.ts +++ b/server/src/services/smart-info.service.ts @@ -3,12 +3,10 @@ import { SystemConfig } from 'src/config'; import { JOBS_ASSET_PAGINATION_SIZE } from 'src/constants'; import { OnEvent, OnJob } from 'src/decorators'; import { DatabaseLock, ImmichWorker, JobName, JobStatus, QueueName } from 'src/enum'; -import { WithoutProperty } from 'src/repositories/asset.repository'; import { ArgOf } from 'src/repositories/event.repository'; import { BaseService } from 'src/services/base.service'; -import { JobOf } from 'src/types'; +import { JobItem, JobOf } from 'src/types'; import { getCLIPModelInfo, isSmartSearchEnabled } from 'src/utils/misc'; -import { usePagination } from 'src/utils/pagination'; @Injectable() export class SmartInfoService extends BaseService { @@ -50,12 +48,6 @@ export class SmartInfoService extends BaseService { return; } - const { isPaused } = await this.jobRepository.getQueueStatus(QueueName.SMART_SEARCH); - if (!isPaused) { - await this.jobRepository.pause(QueueName.SMART_SEARCH); - } - await this.jobRepository.waitForQueueCompletion(QueueName.SMART_SEARCH); - if (dimSizeChange) { this.logger.log( `Dimension size of model ${newConfig.machineLearning.clip.modelName} is ${dimSize}, but database expects ${dbDimSize}.`, @@ -67,9 +59,8 @@ export class SmartInfoService extends BaseService { await this.searchRepository.deleteAllSearchEmbeddings(); } - if (!isPaused) { - await this.jobRepository.resume(QueueName.SMART_SEARCH); - } + // TODO: A job to reindex all assets should be scheduled, though user + // confirmation should probably be requested before doing that. }); } @@ -81,21 +72,23 @@ export class SmartInfoService extends BaseService { } if (force) { - await this.searchRepository.deleteAllSearchEmbeddings(); + const { dimSize } = getCLIPModelInfo(machineLearning.clip.modelName); + // in addition to deleting embeddings, update the dimension size in case it failed earlier + await this.searchRepository.setDimensionSize(dimSize); } - const assetPagination = usePagination(JOBS_ASSET_PAGINATION_SIZE, (pagination) => { - return force - ? this.assetRepository.getAll(pagination, { isVisible: true }) - : this.assetRepository.getWithout(pagination, WithoutProperty.SMART_SEARCH); - }); - - for await (const assets of assetPagination) { - await this.jobRepository.queueAll( - assets.map((asset) => ({ name: JobName.SMART_SEARCH, data: { id: asset.id } })), - ); + let queue: JobItem[] = []; + const assets = this.assetJobRepository.streamForEncodeClip(force); + for await (const asset of assets) { + queue.push({ name: JobName.SMART_SEARCH, data: { id: asset.id } }); + if (queue.length >= JOBS_ASSET_PAGINATION_SIZE) { + await this.jobRepository.queueAll(queue); + queue = []; + } } + await this.jobRepository.queueAll(queue); + return JobStatus.SUCCESS; } @@ -126,6 +119,12 @@ export class SmartInfoService extends BaseService { await this.databaseRepository.wait(DatabaseLock.CLIPDimSize); } + const newConfig = await this.getConfig({ withCache: true }); + if (machineLearning.clip.modelName !== newConfig.machineLearning.clip.modelName) { + // Skip the job if the the model has changed since the embedding was generated. + return JobStatus.SKIPPED; + } + await this.searchRepository.upsert(asset.id, embedding); return JobStatus.SUCCESS; diff --git a/server/src/services/storage-template.service.spec.ts b/server/src/services/storage-template.service.spec.ts index 971a9e8302..9c4fe02f3e 100644 --- a/server/src/services/storage-template.service.spec.ts +++ b/server/src/services/storage-template.service.spec.ts @@ -69,6 +69,7 @@ describe(StorageTemplateService.name, () => { '{{y}}/{{MMMM}}-{{dd}}/{{filename}}', '{{y}}/{{MM}}/{{filename}}', '{{y}}/{{#if album}}{{album}}{{else}}Other/{{MM}}{{/if}}/{{filename}}', + '{{#if album}}{{album-startDate-y}}/{{album}}{{else}}{{y}}/Other/{{MM}}{{/if}}/{{filename}}', '{{y}}/{{MMM}}/{{filename}}', '{{y}}/{{MMMM}}/{{filename}}', '{{y}}/{{MM}}/{{dd}}/{{filename}}', @@ -182,6 +183,63 @@ describe(StorageTemplateService.name, () => { }); }); + it('should handle album startDate', async () => { + const asset = assetStub.storageAsset(); + const user = userStub.user1; + const album = albumStub.oneAsset; + const config = structuredClone(defaults); + config.storageTemplate.template = + '{{#if album}}{{album-startDate-y}}/{{album-startDate-MM}} - {{album}}{{else}}{{y}}/{{MM}}/{{/if}}/{{filename}}'; + + sut.onConfigInit({ newConfig: config }); + + mocks.user.get.mockResolvedValue(user); + mocks.assetJob.getForStorageTemplateJob.mockResolvedValueOnce(asset); + mocks.album.getByAssetId.mockResolvedValueOnce([album]); + mocks.album.getMetadataForIds.mockResolvedValueOnce([ + { + startDate: asset.fileCreatedAt, + endDate: asset.fileCreatedAt, + albumId: album.id, + assetCount: 1, + lastModifiedAssetTimestamp: null, + }, + ]); + + expect(await sut.handleMigrationSingle({ id: asset.id })).toBe(JobStatus.SUCCESS); + + const month = (asset.fileCreatedAt.getMonth() + 1).toString().padStart(2, '0'); + expect(mocks.move.create).toHaveBeenCalledWith({ + entityId: asset.id, + newPath: `upload/library/${user.id}/${asset.fileCreatedAt.getFullYear()}/${month} - ${album.albumName}/${asset.originalFileName}`, + oldPath: asset.originalPath, + pathType: AssetPathType.ORIGINAL, + }); + }); + + it('should handle else condition from album startDate', async () => { + const asset = assetStub.storageAsset(); + const user = userStub.user1; + const config = structuredClone(defaults); + config.storageTemplate.template = + '{{#if album}}{{album-startDate-y}}/{{album-startDate-MM}} - {{album}}{{else}}{{y}}/{{MM}}/{{/if}}/{{filename}}'; + + sut.onConfigInit({ newConfig: config }); + + mocks.user.get.mockResolvedValue(user); + mocks.assetJob.getForStorageTemplateJob.mockResolvedValueOnce(asset); + + expect(await sut.handleMigrationSingle({ id: asset.id })).toBe(JobStatus.SUCCESS); + + const month = (asset.fileCreatedAt.getMonth() + 1).toString().padStart(2, '0'); + expect(mocks.move.create).toHaveBeenCalledWith({ + entityId: asset.id, + newPath: `upload/library/${user.id}/${asset.fileCreatedAt.getFullYear()}/${month}/${asset.originalFileName}`, + oldPath: asset.originalPath, + pathType: AssetPathType.ORIGINAL, + }); + }); + it('should migrate previously failed move from original path when it still exists', async () => { mocks.user.get.mockResolvedValue(userStub.user1); diff --git a/server/src/services/storage-template.service.ts b/server/src/services/storage-template.service.ts index 71a0160ee2..542633a03f 100644 --- a/server/src/services/storage-template.service.ts +++ b/server/src/services/storage-template.service.ts @@ -28,6 +28,7 @@ const storagePresets = [ '{{y}}/{{MMMM}}-{{dd}}/{{filename}}', '{{y}}/{{MM}}/{{filename}}', '{{y}}/{{#if album}}{{album}}{{else}}Other/{{MM}}{{/if}}/{{filename}}', + '{{#if album}}{{album-startDate-y}}/{{album}}{{else}}{{y}}/Other/{{MM}}{{/if}}/{{filename}}', '{{y}}/{{MMM}}/{{filename}}', '{{y}}/{{MMMM}}/{{filename}}', '{{y}}/{{MM}}/{{dd}}/{{filename}}', @@ -54,6 +55,8 @@ interface RenderMetadata { filename: string; extension: string; albumName: string | null; + albumStartDate: Date | null; + albumEndDate: Date | null; } @Injectable() @@ -62,6 +65,7 @@ export class StorageTemplateService extends BaseService { compiled: HandlebarsTemplateDelegate; raw: string; needsAlbum: boolean; + needsAlbumMetadata: boolean; } | null = null; private get template() { @@ -99,6 +103,8 @@ export class StorageTemplateService extends BaseService { filename: 'IMG_123', extension: 'jpg', albumName: 'album', + albumStartDate: new Date(), + albumEndDate: new Date(), }); } catch (error) { this.logger.warn(`Storage template validation failed: ${JSON.stringify(error)}`); @@ -255,9 +261,20 @@ export class StorageTemplateService extends BaseService { } let albumName = null; + let albumStartDate = null; + let albumEndDate = null; if (this.template.needsAlbum) { const albums = await this.albumRepository.getByAssetId(asset.ownerId, asset.id); - albumName = albums?.[0]?.albumName || null; + const album = albums?.[0]; + if (album) { + albumName = album.albumName || null; + + if (this.template.needsAlbumMetadata) { + const [metadata] = await this.albumRepository.getMetadataForIds([album.id]); + albumStartDate = metadata?.startDate || null; + albumEndDate = metadata?.endDate || null; + } + } } const storagePath = this.render(this.template.compiled, { @@ -265,6 +282,8 @@ export class StorageTemplateService extends BaseService { filename: sanitized, extension, albumName, + albumStartDate, + albumEndDate, }); const fullPath = path.normalize(path.join(rootPath, storagePath)); let destination = `${fullPath}.${extension}`; @@ -323,12 +342,13 @@ export class StorageTemplateService extends BaseService { return { raw: template, compiled: handlebar.compile(template, { knownHelpers: undefined, strict: true }), - needsAlbum: template.includes('{{album}}'), + needsAlbum: template.includes('album'), + needsAlbumMetadata: template.includes('album-startDate') || template.includes('album-endDate'), }; } private render(template: HandlebarsTemplateDelegate, options: RenderMetadata) { - const { filename, extension, asset, albumName } = options; + const { filename, extension, asset, albumName, albumStartDate, albumEndDate } = options; const substitutions: Record = { filename, ext: extension, @@ -346,6 +366,15 @@ export class StorageTemplateService extends BaseService { for (const token of Object.values(storageTokens).flat()) { substitutions[token] = dt.toFormat(token); + if (albumName) { + // Use system time zone for album dates to ensure all assets get the exact same date. + substitutions['album-startDate-' + token] = albumStartDate + ? DateTime.fromJSDate(albumStartDate, { zone: systemTimeZone }).toFormat(token) + : ''; + substitutions['album-endDate-' + token] = albumEndDate + ? DateTime.fromJSDate(albumEndDate, { zone: systemTimeZone }).toFormat(token) + : ''; + } } return template(substitutions).replaceAll(/\/{2,}/gm, '/'); diff --git a/server/src/services/system-config.service.spec.ts b/server/src/services/system-config.service.spec.ts index 936acf27ad..176e6d6f04 100644 --- a/server/src/services/system-config.service.spec.ts +++ b/server/src/services/system-config.service.spec.ts @@ -6,6 +6,7 @@ import { CQMode, ImageFormat, LogLevel, + OAuthTokenEndpointAuthMethod, QueueName, ToneMapping, TranscodeHWAccel, @@ -119,6 +120,8 @@ const updatedConfig = Object.freeze({ scope: 'openid email profile', signingAlgorithm: 'RS256', profileSigningAlgorithm: 'none', + tokenEndpointAuthMethod: OAuthTokenEndpointAuthMethod.CLIENT_SECRET_POST, + timeout: 30_000, storageLabelClaim: 'preferred_username', storageQuotaClaim: 'immich_quota', }, diff --git a/server/src/services/user-admin.service.ts b/server/src/services/user-admin.service.ts index 0cba749d36..c1c6cc49ec 100644 --- a/server/src/services/user-admin.service.ts +++ b/server/src/services/user-admin.service.ts @@ -106,21 +106,19 @@ export class UserAdminService extends BaseService { } async getPreferences(auth: AuthDto, id: string): Promise { - const { email } = await this.findOrFail(id, { withDeleted: true }); + await this.findOrFail(id, { withDeleted: true }); const metadata = await this.userRepository.getMetadata(id); - const preferences = getPreferences(email, metadata); - return mapPreferences(preferences); + return mapPreferences(getPreferences(metadata)); } async updatePreferences(auth: AuthDto, id: string, dto: UserPreferencesUpdateDto) { - const { email } = await this.findOrFail(id, { withDeleted: false }); + await this.findOrFail(id, { withDeleted: false }); const metadata = await this.userRepository.getMetadata(id); - const preferences = getPreferences(email, metadata); - const newPreferences = mergePreferences(preferences, dto); + const newPreferences = mergePreferences(getPreferences(metadata), dto); await this.userRepository.upsertMetadata(id, { key: UserMetadataKey.PREFERENCES, - value: getPreferencesPartial({ email }, newPreferences), + value: getPreferencesPartial(newPreferences), }); return mapPreferences(newPreferences); diff --git a/server/src/services/user.service.ts b/server/src/services/user.service.ts index 327328eb1c..a0304d51ad 100644 --- a/server/src/services/user.service.ts +++ b/server/src/services/user.service.ts @@ -53,6 +53,7 @@ export class UserService extends BaseService { const update: Updateable = { email: dto.email, name: dto.name, + avatarColor: dto.avatarColor, }; if (dto.password) { @@ -68,18 +69,16 @@ export class UserService extends BaseService { async getMyPreferences(auth: AuthDto): Promise { const metadata = await this.userRepository.getMetadata(auth.user.id); - const preferences = getPreferences(auth.user.email, metadata); - return mapPreferences(preferences); + return mapPreferences(getPreferences(metadata)); } async updateMyPreferences(auth: AuthDto, dto: UserPreferencesUpdateDto) { const metadata = await this.userRepository.getMetadata(auth.user.id); - const current = getPreferences(auth.user.email, metadata); - const updated = mergePreferences(current, dto); + const updated = mergePreferences(getPreferences(metadata), dto); await this.userRepository.upsertMetadata(auth.user.id, { key: UserMetadataKey.PREFERENCES, - value: getPreferencesPartial(auth.user, updated), + value: getPreferencesPartial(updated), }); return mapPreferences(updated); diff --git a/server/src/types.ts b/server/src/types.ts index 88ba644739..ba33e97aad 100644 --- a/server/src/types.ts +++ b/server/src/types.ts @@ -11,7 +11,6 @@ import { SyncEntityType, SystemMetadataKey, TranscodeTarget, - UserAvatarColor, UserMetadataKey, VideoCodec, } from 'src/enum'; @@ -298,6 +297,10 @@ export type JobItem = // Metadata Extraction | { name: JobName.QUEUE_METADATA_EXTRACTION; data: IBaseJob } | { name: JobName.METADATA_EXTRACTION; data: IEntityJob } + + // Notifications + | { name: JobName.NOTIFICATIONS_CLEANUP; data?: IBaseJob } + // Sidecar Scanning | { name: JobName.QUEUE_SIDECAR; data: IBaseJob } | { name: JobName.SIDECAR_DISCOVERY; data: IEntityJob } @@ -486,9 +489,6 @@ export interface UserPreferences { enabled: boolean; sidebarWeb: boolean; }; - avatar: { - color: UserAvatarColor; - }; emailNotifications: { enabled: boolean; albumInvite: boolean; diff --git a/server/src/utils/access.ts b/server/src/utils/access.ts index 4e21a9226e..b04d23f114 100644 --- a/server/src/utils/access.ts +++ b/server/src/utils/access.ts @@ -221,6 +221,12 @@ const checkOtherAccess = async (access: AccessRepository, request: OtherAccessRe return access.person.checkFaceOwnerAccess(auth.user.id, ids); } + case Permission.NOTIFICATION_READ: + case Permission.NOTIFICATION_UPDATE: + case Permission.NOTIFICATION_DELETE: { + return access.notification.checkOwnerAccess(auth.user.id, ids); + } + case Permission.TAG_ASSET: case Permission.TAG_READ: case Permission.TAG_UPDATE: diff --git a/server/src/utils/database.spec.ts b/server/src/utils/database.spec.ts new file mode 100644 index 0000000000..4c6a82ad8f --- /dev/null +++ b/server/src/utils/database.spec.ts @@ -0,0 +1,83 @@ +import { asPostgresConnectionConfig } from 'src/utils/database'; + +describe('database utils', () => { + describe('asPostgresConnectionConfig', () => { + it('should handle sslmode=require', () => { + expect( + asPostgresConnectionConfig({ + connectionType: 'url', + url: 'postgres://postgres1:postgres2@database1:54320/immich?sslmode=require', + }), + ).toMatchObject({ ssl: {} }); + }); + + it('should handle sslmode=prefer', () => { + expect( + asPostgresConnectionConfig({ + connectionType: 'url', + url: 'postgres://postgres1:postgres2@database1:54320/immich?sslmode=prefer', + }), + ).toMatchObject({ ssl: {} }); + }); + + it('should handle sslmode=verify-ca', () => { + expect( + asPostgresConnectionConfig({ + connectionType: 'url', + url: 'postgres://postgres1:postgres2@database1:54320/immich?sslmode=verify-ca', + }), + ).toMatchObject({ ssl: {} }); + }); + + it('should handle sslmode=verify-full', () => { + expect( + asPostgresConnectionConfig({ + connectionType: 'url', + url: 'postgres://postgres1:postgres2@database1:54320/immich?sslmode=verify-full', + }), + ).toMatchObject({ ssl: {} }); + }); + + it('should handle sslmode=no-verify', () => { + expect( + asPostgresConnectionConfig({ + connectionType: 'url', + url: 'postgres://postgres1:postgres2@database1:54320/immich?sslmode=no-verify', + }), + ).toMatchObject({ ssl: { rejectUnauthorized: false } }); + }); + + it('should handle ssl=true', () => { + expect( + asPostgresConnectionConfig({ + connectionType: 'url', + url: 'postgres://postgres1:postgres2@database1:54320/immich?ssl=true', + }), + ).toMatchObject({ ssl: true }); + }); + + it('should reject invalid ssl', () => { + expect(() => + asPostgresConnectionConfig({ + connectionType: 'url', + url: 'postgres://postgres1:postgres2@database1:54320/immich?ssl=invalid', + }), + ).toThrowError('Invalid ssl option'); + }); + + it('should handle socket: URLs', () => { + expect( + asPostgresConnectionConfig({ connectionType: 'url', url: 'socket:/run/postgresql?db=database1' }), + ).toMatchObject({ host: '/run/postgresql', database: 'database1' }); + }); + + it('should handle sockets in postgres: URLs', () => { + expect( + asPostgresConnectionConfig({ connectionType: 'url', url: 'postgres:///database2?host=/path/to/socket' }), + ).toMatchObject({ + host: '/path/to/socket', + database: 'database2', + }); + }); + }); +}); diff --git a/server/src/utils/database.ts b/server/src/utils/database.ts index 1af0aa4b4e..b44ea5da46 100644 --- a/server/src/utils/database.ts +++ b/server/src/utils/database.ts @@ -13,33 +13,57 @@ import { } from 'kysely'; import { PostgresJSDialect } from 'kysely-postgres-js'; import { jsonArrayFrom, jsonObjectFrom } from 'kysely/helpers/postgres'; +import { parse } from 'pg-connection-string'; import postgres, { Notice } from 'postgres'; import { columns, Exif, Person } from 'src/database'; import { DB } from 'src/db'; -import { AssetFileType } from 'src/enum'; +import { AssetFileType, DatabaseExtension } from 'src/enum'; import { TimeBucketSize } from 'src/repositories/asset.repository'; import { AssetSearchBuilderOptions } from 'src/repositories/search.repository'; +import { DatabaseConnectionParams, VectorExtension } from 'src/types'; type Ssl = 'require' | 'allow' | 'prefer' | 'verify-full' | boolean | object; -export type PostgresConnectionConfig = { - host?: string; - password?: string; - user?: string; - port?: number; - database?: string; - max?: number; - client_encoding?: string; - ssl?: Ssl; - application_name?: string; - fallback_application_name?: string; - options?: string; -}; - -export const isValidSsl = (ssl?: string | boolean | object): ssl is Ssl => +const isValidSsl = (ssl?: string | boolean | object): ssl is Ssl => typeof ssl !== 'string' || ssl === 'require' || ssl === 'allow' || ssl === 'prefer' || ssl === 'verify-full'; -export const getKyselyConfig = (options: PostgresConnectionConfig): KyselyConfig => { +export const asPostgresConnectionConfig = (params: DatabaseConnectionParams) => { + if (params.connectionType === 'parts') { + return { + host: params.host, + port: params.port, + username: params.username, + password: params.password, + database: params.database, + ssl: undefined, + }; + } + + const { host, port, user, password, database, ...rest } = parse(params.url); + let ssl: Ssl | undefined; + if (rest.ssl) { + if (!isValidSsl(rest.ssl)) { + throw new Error(`Invalid ssl option: ${rest.ssl}`); + } + ssl = rest.ssl; + } + + return { + host: host ?? undefined, + port: port ? Number(port) : undefined, + username: user, + password, + database: database ?? undefined, + ssl, + }; +}; + +export const getKyselyConfig = ( + params: DatabaseConnectionParams, + options: Partial>> = {}, +): KyselyConfig => { + const config = asPostgresConnectionConfig(params); + return { dialect: new PostgresJSDialect({ postgres: postgres({ @@ -66,6 +90,12 @@ export const getKyselyConfig = (options: PostgresConnectionConfig): KyselyConfig connection: { TimeZone: 'UTC', }, + host: config.host, + port: config.port, + username: config.username, + password: config.password, + database: config.database, + ssl: config.ssl, ...options, }), }), @@ -343,3 +373,28 @@ export function searchAssetBuilder(kysely: Kysely, options: AssetSearchBuild .$if(!!(options.withFaces || options.withPeople || options.personIds), (qb) => qb.select(withFacesAndPeople)) .$if(!options.withDeleted, (qb) => qb.where('assets.deletedAt', 'is', null)); } + +type VectorIndexOptions = { vectorExtension: VectorExtension; table: string; indexName: string }; + +export function vectorIndexQuery({ vectorExtension, table, indexName }: VectorIndexOptions): string { + switch (vectorExtension) { + case DatabaseExtension.VECTORS: { + return ` + CREATE INDEX IF NOT EXISTS ${indexName} ON ${table} + USING vectors (embedding vector_cos_ops) WITH (options = $$ + [indexing.hnsw] + m = 16 + ef_construction = 300 + $$)`; + } + case DatabaseExtension.VECTOR: { + return ` + CREATE INDEX IF NOT EXISTS ${indexName} ON ${table} + USING hnsw (embedding vector_cosine_ops) + WITH (ef_construction = 300, m = 16)`; + } + default: { + throw new Error(`Unsupported vector extension: '${vectorExtension}'`); + } + } +} diff --git a/server/src/utils/mime-types.ts b/server/src/utils/mime-types.ts index b1a9c77588..6aad418d9f 100644 --- a/server/src/utils/mime-types.ts +++ b/server/src/utils/mime-types.ts @@ -34,45 +34,40 @@ const raw: Record = { '.x3f': ['image/x3f', 'image/x-sigma-x3f'], }; +/** + * list of supported image extensions from https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types excluding svg + * @TODO share with the client + * @see {@link web/src/lib/utils/asset-utils.ts#L329} + **/ +const webSupportedImage = { + '.avif': ['image/avif'], + '.gif': ['image/gif'], + '.jpeg': ['image/jpeg'], + '.jpg': ['image/jpeg'], + '.png': ['image/png', 'image/apng'], + '.webp': ['image/webp'], +}; + const image: Record = { ...raw, - '.avif': ['image/avif'], + ...webSupportedImage, '.bmp': ['image/bmp'], - '.gif': ['image/gif'], '.heic': ['image/heic'], '.heif': ['image/heif'], '.hif': ['image/hif'], '.insp': ['image/jpeg'], '.jp2': ['image/jp2'], '.jpe': ['image/jpeg'], - '.jpeg': ['image/jpeg'], - '.jpg': ['image/jpeg'], '.jxl': ['image/jxl'], - '.png': ['image/png'], '.svg': ['image/svg'], '.tif': ['image/tiff'], '.tiff': ['image/tiff'], - '.webp': ['image/webp'], }; const extensionOverrides: Record = { 'image/jpeg': '.jpg', }; -/** - * list of supported image extensions from https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types excluding svg - * @TODO share with the client - * @see {@link web/src/lib/utils/asset-utils.ts#L329} - **/ -const webSupportedImageMimeTypes = new Set([ - 'image/apng', - 'image/avif', - 'image/gif', - 'image/jpeg', - 'image/png', - 'image/webp', -]); - const profileExtensions = new Set(['.avif', '.dng', '.heic', '.heif', '.jpeg', '.jpg', '.png', '.webp', '.svg']); const profile: Record = Object.fromEntries( Object.entries(image).filter(([key]) => profileExtensions.has(key)), @@ -123,7 +118,7 @@ export const mimeTypes = { isAsset: (filename: string) => isType(filename, image) || isType(filename, video), isImage: (filename: string) => isType(filename, image), - isWebSupportedImage: (filename: string) => webSupportedImageMimeTypes.has(lookup(filename)), + isWebSupportedImage: (filename: string) => isType(filename, webSupportedImage), isProfile: (filename: string) => isType(filename, profile), isSidecar: (filename: string) => isType(filename, sidecar), isVideo: (filename: string) => isType(filename, video), diff --git a/server/src/utils/preferences.ts b/server/src/utils/preferences.ts index 584c5300cd..a013c0b74e 100644 --- a/server/src/utils/preferences.ts +++ b/server/src/utils/preferences.ts @@ -1,16 +1,11 @@ import _ from 'lodash'; import { UserPreferencesUpdateDto } from 'src/dtos/user-preferences.dto'; -import { UserAvatarColor, UserMetadataKey } from 'src/enum'; +import { UserMetadataKey } from 'src/enum'; import { DeepPartial, UserMetadataItem, UserPreferences } from 'src/types'; import { HumanReadableSize } from 'src/utils/bytes'; import { getKeysDeep } from 'src/utils/misc'; -const getDefaultPreferences = (user: { email: string }): UserPreferences => { - const values = Object.values(UserAvatarColor); - const randomIndex = Math.floor( - [...user.email].map((letter) => letter.codePointAt(0) ?? 0).reduce((a, b) => a + b, 0) % values.length, - ); - +const getDefaultPreferences = (): UserPreferences => { return { folders: { enabled: false, @@ -34,9 +29,6 @@ const getDefaultPreferences = (user: { email: string }): UserPreferences => { enabled: false, sidebarWeb: false, }, - avatar: { - color: values[randomIndex], - }, emailNotifications: { enabled: true, albumInvite: true, @@ -53,8 +45,8 @@ const getDefaultPreferences = (user: { email: string }): UserPreferences => { }; }; -export const getPreferences = (email: string, metadata: UserMetadataItem[]): UserPreferences => { - const preferences = getDefaultPreferences({ email }); +export const getPreferences = (metadata: UserMetadataItem[]): UserPreferences => { + const preferences = getDefaultPreferences(); const item = metadata.find(({ key }) => key === UserMetadataKey.PREFERENCES); const partial = item?.value || {}; for (const property of getKeysDeep(partial)) { @@ -64,8 +56,8 @@ export const getPreferences = (email: string, metadata: UserMetadataItem[]): Use return preferences; }; -export const getPreferencesPartial = (user: { email: string }, newPreferences: UserPreferences) => { - const defaultPreferences = getDefaultPreferences(user); +export const getPreferencesPartial = (newPreferences: UserPreferences) => { + const defaultPreferences = getDefaultPreferences(); const partial: DeepPartial = {}; for (const property of getKeysDeep(defaultPreferences)) { const newValue = _.get(newPreferences, property); diff --git a/server/src/utils/response.ts b/server/src/utils/response.ts index 679d947afb..a50e86a4ff 100644 --- a/server/src/utils/response.ts +++ b/server/src/utils/response.ts @@ -15,6 +15,8 @@ export const respondWithCookie = (res: Response, body: T, { isSecure, values const cookieOptions: Record = { [ImmichCookie.AUTH_TYPE]: defaults, [ImmichCookie.ACCESS_TOKEN]: defaults, + [ImmichCookie.OAUTH_STATE]: defaults, + [ImmichCookie.OAUTH_CODE_VERIFIER]: defaults, // no httpOnly so that the client can know the auth state [ImmichCookie.IS_AUTHENTICATED]: { ...defaults, httpOnly: false }, [ImmichCookie.SHARED_LINK_TOKEN]: { ...defaults, maxAge: Duration.fromObject({ days: 1 }).toMillis() }, diff --git a/server/src/workers/api.ts b/server/src/workers/api.ts index ddf6e50aa2..4248b23d30 100644 --- a/server/src/workers/api.ts +++ b/server/src/workers/api.ts @@ -1,6 +1,7 @@ import { NestFactory } from '@nestjs/core'; import { NestExpressApplication } from '@nestjs/platform-express'; import { json } from 'body-parser'; +import compression from 'compression'; import cookieParser from 'cookie-parser'; import { existsSync } from 'node:fs'; import sirv from 'sirv'; @@ -60,6 +61,7 @@ async function bootstrap() { ); } app.use(app.get(ApiService).ssr(excludePaths)); + app.use(compression()); const server = await (host ? app.listen(port, host) : app.listen(port)); server.requestTimeout = 24 * 60 * 60 * 1000; diff --git a/server/test/fixtures/user.stub.ts b/server/test/fixtures/user.stub.ts index f0043d174a..0db58e2eed 100644 --- a/server/test/fixtures/user.stub.ts +++ b/server/test/fixtures/user.stub.ts @@ -1,5 +1,5 @@ import { UserAdmin } from 'src/database'; -import { UserAvatarColor, UserMetadataKey, UserStatus } from 'src/enum'; +import { UserStatus } from 'src/enum'; import { authStub } from 'test/fixtures/auth.stub'; export const userStub = { @@ -12,6 +12,7 @@ export const userStub = { storageLabel: 'admin', oauthId: '', shouldChangePassword: false, + avatarColor: null, profileImagePath: '', createdAt: new Date('2021-01-01'), deletedAt: null, @@ -28,16 +29,12 @@ export const userStub = { storageLabel: null, oauthId: '', shouldChangePassword: false, + avatarColor: null, profileImagePath: '', createdAt: new Date('2021-01-01'), deletedAt: null, updatedAt: new Date('2021-01-01'), - metadata: [ - { - key: UserMetadataKey.PREFERENCES, - value: { avatar: { color: UserAvatarColor.PRIMARY } }, - }, - ], + metadata: [], quotaSizeInBytes: null, quotaUsageInBytes: 0, }, @@ -50,6 +47,7 @@ export const userStub = { storageLabel: null, oauthId: '', shouldChangePassword: false, + avatarColor: null, profileImagePath: '', createdAt: new Date('2021-01-01'), deletedAt: null, diff --git a/server/test/medium.factory.ts b/server/test/medium.factory.ts index d3ab876e07..388c4df96b 100644 --- a/server/test/medium.factory.ts +++ b/server/test/medium.factory.ts @@ -13,9 +13,11 @@ import { AssetRepository } from 'src/repositories/asset.repository'; import { ConfigRepository } from 'src/repositories/config.repository'; import { CryptoRepository } from 'src/repositories/crypto.repository'; import { DatabaseRepository } from 'src/repositories/database.repository'; +import { EmailRepository } from 'src/repositories/email.repository'; import { JobRepository } from 'src/repositories/job.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; import { MemoryRepository } from 'src/repositories/memory.repository'; +import { NotificationRepository } from 'src/repositories/notification.repository'; import { PartnerRepository } from 'src/repositories/partner.repository'; import { PersonRepository } from 'src/repositories/person.repository'; import { SearchRepository } from 'src/repositories/search.repository'; @@ -42,10 +44,12 @@ type RepositoriesTypes = { config: ConfigRepository; crypto: CryptoRepository; database: DatabaseRepository; + email: EmailRepository; job: JobRepository; user: UserRepository; logger: LoggingRepository; memory: MemoryRepository; + notification: NotificationRepository; partner: PartnerRepository; person: PersonRepository; search: SearchRepository; @@ -142,6 +146,11 @@ export const getRepository = (key: K, db: Kys return new DatabaseRepository(db, new LoggingRepository(undefined, configRepo), configRepo); } + case 'email': { + const logger = new LoggingRepository(undefined, new ConfigRepository()); + return new EmailRepository(logger); + } + case 'logger': { const configMock = { getEnv: () => ({ noColor: false }) }; return new LoggingRepository(undefined, configMock as ConfigRepository); @@ -151,6 +160,10 @@ export const getRepository = (key: K, db: Kys return new MemoryRepository(db); } + case 'notification': { + return new NotificationRepository(db); + } + case 'partner': { return new PartnerRepository(db); } @@ -160,7 +173,7 @@ export const getRepository = (key: K, db: Kys } case 'search': { - return new SearchRepository(db); + return new SearchRepository(db, new ConfigRepository()); } case 'session': { @@ -221,6 +234,10 @@ const getRepositoryMock = (key: K) => { }); } + case 'email': { + return automock(EmailRepository, { args: [{ setContext: () => {} }] }); + } + case 'job': { return automock(JobRepository, { args: [undefined, undefined, undefined, { setContext: () => {} }] }); } @@ -234,6 +251,10 @@ const getRepositoryMock = (key: K) => { return automock(MemoryRepository); } + case 'notification': { + return automock(NotificationRepository); + } + case 'partner': { return automock(PartnerRepository); } @@ -284,6 +305,7 @@ export const asDeps = (repositories: ServiceOverrides) => { repositories.crypto || getRepositoryMock('crypto'), repositories.database || getRepositoryMock('database'), repositories.downloadRepository, + repositories.email || getRepositoryMock('email'), repositories.event, repositories.job || getRepositoryMock('job'), repositories.library, @@ -293,7 +315,7 @@ export const asDeps = (repositories: ServiceOverrides) => { repositories.memory || getRepositoryMock('memory'), repositories.metadata, repositories.move, - repositories.notification, + repositories.notification || getRepositoryMock('notification'), repositories.oauth, repositories.partner || getRepositoryMock('partner'), repositories.person || getRepositoryMock('person'), diff --git a/server/test/medium/globalSetup.ts b/server/test/medium/globalSetup.ts index 46eb1a733f..e63c9f5224 100644 --- a/server/test/medium/globalSetup.ts +++ b/server/test/medium/globalSetup.ts @@ -1,5 +1,4 @@ import { Kysely } from 'kysely'; -import { parse } from 'pg-connection-string'; import { DB } from 'src/db'; import { ConfigRepository } from 'src/repositories/config.repository'; import { DatabaseRepository } from 'src/repositories/database.repository'; @@ -37,19 +36,10 @@ const globalSetup = async () => { const postgresPort = postgresContainer.getMappedPort(5432); const postgresUrl = `postgres://postgres:postgres@localhost:${postgresPort}/immich`; - const parsed = parse(postgresUrl); process.env.IMMICH_TEST_POSTGRES_URL = postgresUrl; - const db = new Kysely( - getKyselyConfig({ - ...parsed, - ssl: false, - host: parsed.host ?? undefined, - port: parsed.port ? Number(parsed.port) : undefined, - database: parsed.database ?? undefined, - }), - ); + const db = new Kysely(getKyselyConfig({ connectionType: 'url', url: postgresUrl })); const configRepository = new ConfigRepository(); const logger = new LoggingRepository(undefined, configRepository); diff --git a/server/test/medium/specs/controllers/notification.controller.spec.ts b/server/test/medium/specs/controllers/notification.controller.spec.ts new file mode 100644 index 0000000000..f4a0ec82d5 --- /dev/null +++ b/server/test/medium/specs/controllers/notification.controller.spec.ts @@ -0,0 +1,86 @@ +import { NotificationController } from 'src/controllers/notification.controller'; +import { AuthService } from 'src/services/auth.service'; +import { NotificationService } from 'src/services/notification.service'; +import request from 'supertest'; +import { errorDto } from 'test/medium/responses'; +import { createControllerTestApp, TestControllerApp } from 'test/medium/utils'; +import { factory } from 'test/small.factory'; + +describe(NotificationController.name, () => { + let realApp: TestControllerApp; + let mockApp: TestControllerApp; + + beforeEach(async () => { + realApp = await createControllerTestApp({ authType: 'real' }); + mockApp = await createControllerTestApp({ authType: 'mock' }); + }); + + describe('GET /notifications', () => { + it('should require authentication', async () => { + const { status, body } = await request(realApp.getHttpServer()).get('/notifications'); + expect(status).toBe(401); + expect(body).toEqual(errorDto.unauthorized); + }); + + it('should call the service with an auth dto', async () => { + const auth = factory.auth({ user: factory.user() }); + mockApp.getMockedService(AuthService).authenticate.mockResolvedValue(auth); + const service = mockApp.getMockedService(NotificationService); + + const { status } = await request(mockApp.getHttpServer()) + .get('/notifications') + .set('Authorization', `Bearer token`); + + expect(status).toBe(200); + expect(service.search).toHaveBeenCalledWith(auth, {}); + }); + + it(`should reject an invalid notification level`, async () => { + const auth = factory.auth({ user: factory.user() }); + mockApp.getMockedService(AuthService).authenticate.mockResolvedValue(auth); + const service = mockApp.getMockedService(NotificationService); + + const { status, body } = await request(mockApp.getHttpServer()) + .get(`/notifications`) + .query({ level: 'invalid' }) + .set('Authorization', `Bearer token`); + + expect(status).toBe(400); + expect(body).toEqual(errorDto.badRequest([expect.stringContaining('level must be one of the following values')])); + expect(service.search).not.toHaveBeenCalled(); + }); + }); + + describe('PUT /notifications', () => { + it('should require authentication', async () => { + const { status, body } = await request(realApp.getHttpServer()) + .put(`/notifications`) + .send({ ids: [], readAt: new Date().toISOString() }); + expect(status).toBe(401); + expect(body).toEqual(errorDto.unauthorized); + }); + }); + + describe('GET /notifications/:id', () => { + it('should require authentication', async () => { + const { status, body } = await request(realApp.getHttpServer()).get(`/notifications/${factory.uuid()}`); + expect(status).toBe(401); + expect(body).toEqual(errorDto.unauthorized); + }); + }); + + describe('PUT /notifications/:id', () => { + it('should require authentication', async () => { + const { status, body } = await request(realApp.getHttpServer()) + .put(`/notifications/${factory.uuid()}`) + .send({ readAt: factory.date() }); + expect(status).toBe(401); + expect(body).toEqual(errorDto.unauthorized); + }); + }); + + afterAll(async () => { + await realApp.close(); + await mockApp.close(); + }); +}); diff --git a/server/test/repositories/access.repository.mock.ts b/server/test/repositories/access.repository.mock.ts index ec5115b839..5b98b95e27 100644 --- a/server/test/repositories/access.repository.mock.ts +++ b/server/test/repositories/access.repository.mock.ts @@ -37,6 +37,10 @@ export const newAccessRepositoryMock = (): IAccessRepositoryMock => { checkOwnerAccess: vitest.fn().mockResolvedValue(new Set()), }, + notification: { + checkOwnerAccess: vitest.fn().mockResolvedValue(new Set()), + }, + person: { checkFaceOwnerAccess: vitest.fn().mockResolvedValue(new Set()), checkOwnerAccess: vitest.fn().mockResolvedValue(new Set()), diff --git a/server/test/repositories/asset.repository.mock.ts b/server/test/repositories/asset.repository.mock.ts index d540e55b2a..d8230a23f3 100644 --- a/server/test/repositories/asset.repository.mock.ts +++ b/server/test/repositories/asset.repository.mock.ts @@ -13,14 +13,11 @@ export const newAssetRepositoryMock = (): Mocked Promise.resolve()), generateThumbhash: vitest.fn().mockResolvedValue(Buffer.from('')), decodeImage: vitest.fn().mockResolvedValue({ data: Buffer.from(''), info: {} }), - extract: vitest.fn().mockResolvedValue(false), + extract: vitest.fn().mockResolvedValue(null), probe: vitest.fn(), transcode: vitest.fn(), getImageDimensions: vitest.fn(), diff --git a/server/test/small.factory.ts b/server/test/small.factory.ts index 29eef7002e..d2742f7f80 100644 --- a/server/test/small.factory.ts +++ b/server/test/small.factory.ts @@ -140,6 +140,7 @@ const userFactory = (user: Partial = {}) => ({ id: newUuid(), name: 'Test User', email: 'test@immich.cloud', + avatarColor: null, profileImagePath: '', profileChangedAt: newDate(), ...user, @@ -155,6 +156,7 @@ const userAdminFactory = (user: Partial = {}) => { storageLabel = null, shouldChangePassword = false, isAdmin = false, + avatarColor = null, createdAt = newDate(), updatedAt = newDate(), deletedAt = null, @@ -173,6 +175,7 @@ const userAdminFactory = (user: Partial = {}) => { storageLabel, shouldChangePassword, isAdmin, + avatarColor, createdAt, updatedAt, deletedAt, @@ -311,4 +314,5 @@ export const factory = { sidecarWrite: assetSidecarWriteFactory, }, uuid: newUuid, + date: newDate, }; diff --git a/server/test/utils.ts b/server/test/utils.ts index 52984d97a2..2c444f491e 100644 --- a/server/test/utils.ts +++ b/server/test/utils.ts @@ -1,9 +1,9 @@ import { ClassConstructor } from 'class-transformer'; -import { Kysely, sql } from 'kysely'; +import { Kysely } from 'kysely'; import { ChildProcessWithoutNullStreams } from 'node:child_process'; import { Writable } from 'node:stream'; -import { parse } from 'pg-connection-string'; import { PNG } from 'pngjs'; +import postgres from 'postgres'; import { DB } from 'src/db'; import { AccessRepository } from 'src/repositories/access.repository'; import { ActivityRepository } from 'src/repositories/activity.repository'; @@ -18,6 +18,7 @@ import { CronRepository } from 'src/repositories/cron.repository'; import { CryptoRepository } from 'src/repositories/crypto.repository'; import { DatabaseRepository } from 'src/repositories/database.repository'; import { DownloadRepository } from 'src/repositories/download.repository'; +import { EmailRepository } from 'src/repositories/email.repository'; import { EventRepository } from 'src/repositories/event.repository'; import { JobRepository } from 'src/repositories/job.repository'; import { LibraryRepository } from 'src/repositories/library.repository'; @@ -49,7 +50,7 @@ import { VersionHistoryRepository } from 'src/repositories/version-history.repos import { ViewRepository } from 'src/repositories/view-repository'; import { BaseService } from 'src/services/base.service'; import { RepositoryInterface } from 'src/types'; -import { getKyselyConfig } from 'src/utils/database'; +import { asPostgresConnectionConfig, getKyselyConfig } from 'src/utils/database'; import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock'; import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock'; import { newConfigRepositoryMock } from 'test/repositories/config.repository.mock'; @@ -124,6 +125,7 @@ export type ServiceOverrides = { crypto: CryptoRepository; database: DatabaseRepository; downloadRepository: DownloadRepository; + email: EmailRepository; event: EventRepository; job: JobRepository; library: LibraryRepository; @@ -190,6 +192,7 @@ export const newTestService = ( config: newConfigRepositoryMock(), database: newDatabaseRepositoryMock(), downloadRepository: automock(DownloadRepository, { strict: false }), + email: automock(EmailRepository, { args: [loggerMock] }), // eslint-disable-next-line no-sparse-arrays event: automock(EventRepository, { args: [, , loggerMock], strict: false }), job: newJobRepositoryMock(), @@ -201,7 +204,7 @@ export const newTestService = ( memory: automock(MemoryRepository), metadata: newMetadataRepositoryMock(), move: automock(MoveRepository, { strict: false }), - notification: automock(NotificationRepository, { args: [loggerMock] }), + notification: automock(NotificationRepository), oauth: automock(OAuthRepository, { args: [loggerMock] }), partner: automock(PartnerRepository, { strict: false }), person: newPersonRepositoryMock(), @@ -240,6 +243,7 @@ export const newTestService = ( overrides.crypto || (mocks.crypto as As), overrides.database || (mocks.database as As), overrides.downloadRepository || (mocks.downloadRepository as As), + overrides.email || (mocks.email as As), overrides.event || (mocks.event as As), overrides.job || (mocks.job as As), overrides.library || (mocks.library as As), @@ -297,24 +301,20 @@ function* newPngFactory() { const pngFactory = newPngFactory(); +const withDatabase = (url: string, name: string) => url.replace('/immich', `/${name}`); + export const getKyselyDB = async (suffix?: string): Promise> => { - const parsed = parse(process.env.IMMICH_TEST_POSTGRES_URL!); + const testUrl = process.env.IMMICH_TEST_POSTGRES_URL!; + const sql = postgres({ + ...asPostgresConnectionConfig({ connectionType: 'url', url: withDatabase(testUrl, 'postgres') }), + max: 1, + }); - const parsedOptions = { - ...parsed, - ssl: false, - host: parsed.host ?? undefined, - port: parsed.port ? Number(parsed.port) : undefined, - database: parsed.database ?? undefined, - }; - - const kysely = new Kysely(getKyselyConfig({ ...parsedOptions, max: 1, database: 'postgres' })); const randomSuffix = Math.random().toString(36).slice(2, 7); const dbName = `immich_${suffix ?? randomSuffix}`; + await sql.unsafe(`CREATE DATABASE ${dbName} WITH TEMPLATE immich OWNER postgres;`); - await sql.raw(`CREATE DATABASE ${dbName} WITH TEMPLATE immich OWNER postgres;`).execute(kysely); - - return new Kysely(getKyselyConfig({ ...parsedOptions, database: dbName })); + return new Kysely(getKyselyConfig({ connectionType: 'url', url: withDatabase(testUrl, dbName) })); }; export const newRandomImage = () => { diff --git a/server/test/vitest.config.mjs b/server/test/vitest.config.mjs index a6929bf806..a22a6751c3 100644 --- a/server/test/vitest.config.mjs +++ b/server/test/vitest.config.mjs @@ -20,12 +20,6 @@ export default defineConfig({ 'src/services/index.ts', 'src/sql-tools/from-database/index.ts', ], - thresholds: { - lines: 85, - statements: 85, - branches: 90, - functions: 85, - }, }, server: { deps: { diff --git a/web/Dockerfile b/web/Dockerfile index 8c2e67e62e..c4244a1aa0 100644 --- a/web/Dockerfile +++ b/web/Dockerfile @@ -1,4 +1,4 @@ -FROM node:22.14.0-alpine3.20@sha256:40be979442621049f40b1d51a26b55e281246b5de4e5f51a18da7beb6e17e3f9 +FROM node:22.15.0-alpine3.20@sha256:686b8892b69879ef5bfd6047589666933508f9a5451c67320df3070ba0e9807b RUN apk add --no-cache tini USER node diff --git a/web/bin/immich-web b/web/bin/immich-web index 6b2880d6d2..ea748863db 100755 --- a/web/bin/immich-web +++ b/web/bin/immich-web @@ -5,10 +5,17 @@ TYPESCRIPT_SDK=/usr/src/open-api/typescript-sdk npm --prefix "$TYPESCRIPT_SDK" install npm --prefix "$TYPESCRIPT_SDK" run build + +COUNT=0 UPSTREAM="${IMMICH_SERVER_URL:-http://immich-server:2283/}" -until wget --spider --quiet "${UPSTREAM}/api/server/config"; do - echo 'waiting for api server...' +until wget --spider --quiet "${UPSTREAM}/api/server/config" > /dev/null 2>&1; do + if [ $((COUNT % 10)) -eq 0 ]; then + echo "Waiting for $UPSTREAM to start..." + fi + COUNT=$((COUNT + 1)) sleep 1 done +echo "Connected to $UPSTREAM" + node ./node_modules/.bin/vite dev --host 0.0.0.0 --port 3000 diff --git a/web/eslint.config.js b/web/eslint.config.js index 5c24cd1aeb..9ced619504 100644 --- a/web/eslint.config.js +++ b/web/eslint.config.js @@ -58,6 +58,8 @@ export default typescriptEslint.config( }, }, + ignores: ['**/service-worker/**'], + rules: { '@typescript-eslint/no-unused-vars': [ 'warn', diff --git a/web/package-lock.json b/web/package-lock.json index 57af7fa56d..c76dd64840 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1,17 +1,17 @@ { "name": "immich-web", - "version": "1.131.3", + "version": "1.132.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "immich-web", - "version": "1.131.3", + "version": "1.132.3", "license": "GNU Affero General Public License version 3", "dependencies": { "@formatjs/icu-messageformat-parser": "^2.9.8", "@immich/sdk": "file:../open-api/typescript-sdk", - "@immich/ui": "^0.17.3", + "@immich/ui": "^0.18.1", "@mapbox/mapbox-gl-rtl-text": "0.2.3", "@mdi/js": "^7.4.47", "@photo-sphere-viewer/core": "^5.11.5", @@ -59,6 +59,7 @@ "dotenv": "^16.4.7", "eslint": "^9.18.0", "eslint-config-prettier": "^10.0.0", + "eslint-p": "^0.21.0", "eslint-plugin-svelte": "^3.0.0", "eslint-plugin-unicorn": "^57.0.0", "factory.ts": "^1.4.1", @@ -81,13 +82,13 @@ }, "../open-api/typescript-sdk": { "name": "@immich/sdk", - "version": "1.131.3", + "version": "1.132.3", "license": "GNU Affero General Public License version 3", "dependencies": { "@oazapfts/runtime": "^1.0.2" }, "devDependencies": { - "@types/node": "^22.14.0", + "@types/node": "^22.14.1", "typescript": "^5.3.3" } }, @@ -495,9 +496,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz", - "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.3.tgz", + "integrity": "sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==", "cpu": [ "arm64" ], @@ -528,9 +529,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz", - "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.3.tgz", + "integrity": "sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==", "cpu": [ "arm64" ], @@ -692,9 +693,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", - "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", + "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -742,9 +743,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.24.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.24.0.tgz", - "integrity": "sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==", + "version": "9.25.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.25.1.tgz", + "integrity": "sha512-dEIwmjntEx8u3Uvv+kr3PDeeArL8Hw07H9kyYxCjnM9pBjfEhk6uLXSchxxzgiwtRhhzVzqmUSDFBOi1TuZ7qg==", "dev": true, "license": "MIT", "engines": { @@ -775,19 +776,6 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", - "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, "node_modules/@faker-js/faker": { "version": "9.7.0", "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-9.7.0.tgz", @@ -1332,9 +1320,9 @@ "link": true }, "node_modules/@immich/ui": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@immich/ui/-/ui-0.17.4.tgz", - "integrity": "sha512-a6M7Fxno5fwY5A0kxdluS8r+A4L6xZhSTKMW8c8hoFhQHvbBTHAsGFKQF3GOEQLOlUuvsS2Lt7dMevBlAPgo/A==", + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/@immich/ui/-/ui-0.18.1.tgz", + "integrity": "sha512-XWWO6OTfH3MektyxCn0hWefZyOGyWwwx/2zHinuShpxTHSyfveJ4mOkFP8DkyMz0dnvJ1EfdkPBMkld3y5R/Hw==", "license": "GNU Affero General Public License version 3", "dependencies": { "@mdi/js": "^7.4.47", @@ -1705,50 +1693,50 @@ } }, "node_modules/@photo-sphere-viewer/core": { - "version": "5.13.1", - "resolved": "https://registry.npmjs.org/@photo-sphere-viewer/core/-/core-5.13.1.tgz", - "integrity": "sha512-f5fkoGPCBUt5BD9S9U37h+UDmo2slMZThesoH82iyjKR6uRyYnJvJXwopwo+iMfc6x1ZAWmustBBuES4qKzx+g==", + "version": "5.13.2", + "resolved": "https://registry.npmjs.org/@photo-sphere-viewer/core/-/core-5.13.2.tgz", + "integrity": "sha512-rL4Ey39Prx4Iyxt1f2tAqlXvqu4/ovXfUvIpLt540OpZJiFjWccs6qLywof9vuhBJ7PXHudHWCjRPce0W8kx8w==", "license": "MIT", "dependencies": { "three": "^0.175.0" } }, "node_modules/@photo-sphere-viewer/equirectangular-video-adapter": { - "version": "5.13.1", - "resolved": "https://registry.npmjs.org/@photo-sphere-viewer/equirectangular-video-adapter/-/equirectangular-video-adapter-5.13.1.tgz", - "integrity": "sha512-5LCMMc1bnKMFvR//TKguSwyBEBF+fTYLOGnnCzS7HHHNr8jc+bmaxBsPhOENZf8VcoupXYxo4KRNfYwIB0nTEA==", + "version": "5.13.2", + "resolved": "https://registry.npmjs.org/@photo-sphere-viewer/equirectangular-video-adapter/-/equirectangular-video-adapter-5.13.2.tgz", + "integrity": "sha512-Ln9VyZSGAEjqtJ5dYluiSYkUF87FsOwzZvQoEgAt4odQR/q7ktSaVDdRfuuTMcbBKq6kTdsavNzdg+g877WyhA==", "license": "MIT", "peerDependencies": { - "@photo-sphere-viewer/core": "5.13.1", - "@photo-sphere-viewer/video-plugin": "5.13.1" + "@photo-sphere-viewer/core": "5.13.2", + "@photo-sphere-viewer/video-plugin": "5.13.2" } }, "node_modules/@photo-sphere-viewer/resolution-plugin": { - "version": "5.13.1", - "resolved": "https://registry.npmjs.org/@photo-sphere-viewer/resolution-plugin/-/resolution-plugin-5.13.1.tgz", - "integrity": "sha512-XVxR5rAtGYbcy0PQfgGgMAuRAg5gb/tRjgMiB9zzQ6sESLviWCqvk247z4Q6J4TxNYeGSQzKbyous1eS+nUqTg==", + "version": "5.13.2", + "resolved": "https://registry.npmjs.org/@photo-sphere-viewer/resolution-plugin/-/resolution-plugin-5.13.2.tgz", + "integrity": "sha512-T2bUvtKqhPk7FVqRJfynWhnglMpar5FNxCgf3EsnFjV9g+Xnc0LmOLlCeNmsCWXv0lRmNbohDMRN1WpY1O3ojA==", "license": "MIT", "peerDependencies": { - "@photo-sphere-viewer/core": "5.13.1", - "@photo-sphere-viewer/settings-plugin": "5.13.1" + "@photo-sphere-viewer/core": "5.13.2", + "@photo-sphere-viewer/settings-plugin": "5.13.2" } }, "node_modules/@photo-sphere-viewer/settings-plugin": { - "version": "5.13.1", - "resolved": "https://registry.npmjs.org/@photo-sphere-viewer/settings-plugin/-/settings-plugin-5.13.1.tgz", - "integrity": "sha512-W2naZCP9huhN6cmFcGfgJEvxqrBB481/an8o/qice5iIH9xw50qXiDq6czLCtUo8GD4P9ULtsoWo9DUT2EsWzw==", + "version": "5.13.2", + "resolved": "https://registry.npmjs.org/@photo-sphere-viewer/settings-plugin/-/settings-plugin-5.13.2.tgz", + "integrity": "sha512-z1539qy4XC9UextvgxFBBZqiNKQ1DzaI4EZRbrRbfG6LnSsjKwGgX8gIZ8ZpBHoZdU+b2d8PRPmNKiSjhYOvGA==", "license": "MIT", "peerDependencies": { - "@photo-sphere-viewer/core": "5.13.1" + "@photo-sphere-viewer/core": "5.13.2" } }, "node_modules/@photo-sphere-viewer/video-plugin": { - "version": "5.13.1", - "resolved": "https://registry.npmjs.org/@photo-sphere-viewer/video-plugin/-/video-plugin-5.13.1.tgz", - "integrity": "sha512-GmjI4weoKRCOACNEIloL3XSAbYVyrO6s8esJfmpjdGKdDr3kQjKK+oiplRSD28ALIhSxyqemNOGodfgzWH7xLA==", + "version": "5.13.2", + "resolved": "https://registry.npmjs.org/@photo-sphere-viewer/video-plugin/-/video-plugin-5.13.2.tgz", + "integrity": "sha512-6/tajOJaPUDP7mwtdQZul+KNfjL2sUPUt7EcAHZ9KcSq1WcwqZfaUYSCdKaW2uxdpn4BLESSD1h0mJdWNw7vJA==", "license": "MIT", "peerDependencies": { - "@photo-sphere-viewer/core": "5.13.1" + "@photo-sphere-viewer/core": "5.13.2" } }, "node_modules/@pkgjs/parseargs": { @@ -2455,17 +2443,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.30.1.tgz", - "integrity": "sha512-v+VWphxMjn+1t48/jO4t950D6KR8JaJuNXzi33Ve6P8sEmPr5k6CEXjdGwT6+LodVnEa91EQCtwjWNUCPweo+Q==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.31.0.tgz", + "integrity": "sha512-evaQJZ/J/S4wisevDvC1KFZkPzRetH8kYZbkgcTRyql3mcKsf+ZFDV1BVWUGTCAW5pQHoqn5gK5b8kn7ou9aFQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.30.1", - "@typescript-eslint/type-utils": "8.30.1", - "@typescript-eslint/utils": "8.30.1", - "@typescript-eslint/visitor-keys": "8.30.1", + "@typescript-eslint/scope-manager": "8.31.0", + "@typescript-eslint/type-utils": "8.31.0", + "@typescript-eslint/utils": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -2485,16 +2473,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.30.1.tgz", - "integrity": "sha512-H+vqmWwT5xoNrXqWs/fesmssOW70gxFlgcMlYcBaWNPIEWDgLa4W9nkSPmhuOgLnXq9QYgkZ31fhDyLhleCsAg==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.31.0.tgz", + "integrity": "sha512-67kYYShjBR0jNI5vsf/c3WG4u+zDnCTHTPqVMQguffaWWFs7artgwKmfwdifl+r6XyM5LYLas/dInj2T0SgJyw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.30.1", - "@typescript-eslint/types": "8.30.1", - "@typescript-eslint/typescript-estree": "8.30.1", - "@typescript-eslint/visitor-keys": "8.30.1", + "@typescript-eslint/scope-manager": "8.31.0", + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/typescript-estree": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0", "debug": "^4.3.4" }, "engines": { @@ -2510,14 +2498,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.30.1.tgz", - "integrity": "sha512-+C0B6ChFXZkuaNDl73FJxRYT0G7ufVPOSQkqkpM/U198wUwUFOtgo1k/QzFh1KjpBitaK7R1tgjVz6o9HmsRPg==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.31.0.tgz", + "integrity": "sha512-knO8UyF78Nt8O/B64i7TlGXod69ko7z6vJD9uhSlm0qkAbGeRUSudcm0+K/4CrRjrpiHfBCjMWlc08Vav1xwcw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.30.1", - "@typescript-eslint/visitor-keys": "8.30.1" + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2528,14 +2516,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.30.1.tgz", - "integrity": "sha512-64uBF76bfQiJyHgZISC7vcNz3adqQKIccVoKubyQcOnNcdJBvYOILV1v22Qhsw3tw3VQu5ll8ND6hycgAR5fEA==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.31.0.tgz", + "integrity": "sha512-DJ1N1GdjI7IS7uRlzJuEDCgDQix3ZVYVtgeWEyhyn4iaoitpMBX6Ndd488mXSx0xah/cONAkEaYyylDyAeHMHg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.30.1", - "@typescript-eslint/utils": "8.30.1", + "@typescript-eslint/typescript-estree": "8.31.0", + "@typescript-eslint/utils": "8.31.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.1" }, @@ -2552,9 +2540,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.30.1.tgz", - "integrity": "sha512-81KawPfkuulyWo5QdyG/LOKbspyyiW+p4vpn4bYO7DM/hZImlVnFwrpCTnmNMOt8CvLRr5ojI9nU1Ekpw4RcEw==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.31.0.tgz", + "integrity": "sha512-Ch8oSjVyYyJxPQk8pMiP2FFGYatqXQfQIaMp+TpuuLlDachRWpUAeEu1u9B/v/8LToehUIWyiKcA/w5hUFRKuQ==", "dev": true, "license": "MIT", "engines": { @@ -2566,14 +2554,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.30.1.tgz", - "integrity": "sha512-kQQnxymiUy9tTb1F2uep9W6aBiYODgq5EMSk6Nxh4Z+BDUoYUSa029ISs5zTzKBFnexQEh71KqwjKnRz58lusQ==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.0.tgz", + "integrity": "sha512-xLmgn4Yl46xi6aDSZ9KkyfhhtnYI15/CvHbpOy/eR5NWhK/BK8wc709KKwhAR0m4ZKRP7h07bm4BWUYOCuRpQQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.30.1", - "@typescript-eslint/visitor-keys": "8.30.1", + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2619,16 +2607,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.30.1.tgz", - "integrity": "sha512-T/8q4R9En2tcEsWPQgB5BQ0XJVOtfARcUvOa8yJP3fh9M/mXraLxZrkCfGb6ChrO/V3W+Xbd04RacUEqk1CFEQ==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.31.0.tgz", + "integrity": "sha512-qi6uPLt9cjTFxAb1zGNgTob4x9ur7xC6mHQJ8GwEzGMGE9tYniublmJaowOJ9V2jUzxrltTPfdG2nKlWsq0+Ww==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.30.1", - "@typescript-eslint/types": "8.30.1", - "@typescript-eslint/typescript-estree": "8.30.1" + "@typescript-eslint/scope-manager": "8.31.0", + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/typescript-estree": "8.31.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2643,13 +2631,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.30.1.tgz", - "integrity": "sha512-aEhgas7aJ6vZnNFC7K4/vMGDGyOiqWcYZPpIWrTKuTAlsvDNKy2GFDqh9smL+iq069ZvR0YzEeq0B8NJlLzjFA==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.0.tgz", + "integrity": "sha512-QcGHmlRHWOl93o64ZUMNewCdwKGU6WItOU52H0djgNmn1EOrhVudrDzXz4OycCRSCPwFCDrE2iIt5vmuUdHxuQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.30.1", + "@typescript-eslint/types": "8.31.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -2661,9 +2649,9 @@ } }, "node_modules/@vitest/coverage-v8": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.1.1.tgz", - "integrity": "sha512-MgV6D2dhpD6Hp/uroUoAIvFqA8AuvXEFBC2eepG3WFc1pxTfdk1LEqqkWoWhjz+rytoqrnUUCdf6Lzco3iHkLQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.1.2.tgz", + "integrity": "sha512-XDdaDOeaTMAMYW7N63AqoK32sYUWbXnTkC6tEbVcu3RlU1bB9of32T+PGf8KZvxqLNqeXhafDFqCkwpf2+dyaQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2676,7 +2664,7 @@ "istanbul-reports": "^3.1.7", "magic-string": "^0.30.17", "magicast": "^0.3.5", - "std-env": "^3.8.1", + "std-env": "^3.9.0", "test-exclude": "^7.0.1", "tinyrainbow": "^2.0.0" }, @@ -2684,8 +2672,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "3.1.1", - "vitest": "3.1.1" + "@vitest/browser": "3.1.2", + "vitest": "3.1.2" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -2694,14 +2682,14 @@ } }, "node_modules/@vitest/expect": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.1.tgz", - "integrity": "sha512-q/zjrW9lgynctNbwvFtQkGK9+vvHA5UzVi2V8APrp1C6fG6/MuYYkmlx4FubuqLycCeSdHD5aadWfua/Vr0EUA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.2.tgz", + "integrity": "sha512-O8hJgr+zREopCAqWl3uCVaOdqJwZ9qaDwUP7vy3Xigad0phZe9APxKhPcDNqYYi0rX5oMvwJMSCAXY2afqeTSA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.1.1", - "@vitest/utils": "3.1.1", + "@vitest/spy": "3.1.2", + "@vitest/utils": "3.1.2", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" }, @@ -2710,13 +2698,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.1.tgz", - "integrity": "sha512-bmpJJm7Y7i9BBELlLuuM1J1Q6EQ6K5Ye4wcyOpOMXMcePYKSIYlpcrCm4l/O6ja4VJA5G2aMJiuZkZdnxlC3SA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.2.tgz", + "integrity": "sha512-kOtd6K2lc7SQ0mBqYv/wdGedlqPdM/B38paPY+OwJ1XiNi44w3Fpog82UfOibmHaV9Wod18A09I9SCKLyDMqgw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.1.1", + "@vitest/spy": "3.1.2", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -2747,9 +2735,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.1.tgz", - "integrity": "sha512-dg0CIzNx+hMMYfNmSqJlLSXEmnNhMswcn3sXO7Tpldr0LiGmg3eXdLLhwkv2ZqgHb/d5xg5F7ezNFRA1fA13yA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.2.tgz", + "integrity": "sha512-R0xAiHuWeDjTSB3kQ3OQpT8Rx3yhdOAIm/JM4axXxnG7Q/fS8XUwggv/A4xzbQA+drYRjzkMnpYnOGAc4oeq8w==", "dev": true, "license": "MIT", "dependencies": { @@ -2760,13 +2748,13 @@ } }, "node_modules/@vitest/runner": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.1.tgz", - "integrity": "sha512-X/d46qzJuEDO8ueyjtKfxffiXraPRfmYasoC4i5+mlLEJ10UvPb0XH5M9C3gWuxd7BAQhpK42cJgJtq53YnWVA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.2.tgz", + "integrity": "sha512-bhLib9l4xb4sUMPXnThbnhX2Yi8OutBMA8Yahxa7yavQsFDtwY/jrUZwpKp2XH9DhRFJIeytlyGpXCqZ65nR+g==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.1.1", + "@vitest/utils": "3.1.2", "pathe": "^2.0.3" }, "funding": { @@ -2774,13 +2762,13 @@ } }, "node_modules/@vitest/snapshot": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.1.tgz", - "integrity": "sha512-bByMwaVWe/+1WDf9exFxWWgAixelSdiwo2p33tpqIlM14vW7PRV5ppayVXtfycqze4Qhtwag5sVhX400MLBOOw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.2.tgz", + "integrity": "sha512-Q1qkpazSF/p4ApZg1vfZSQ5Yw6OCQxVMVrLjslbLFA1hMDrT2uxtqMaw8Tc/jy5DLka1sNs1Y7rBcftMiaSH/Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.1.1", + "@vitest/pretty-format": "3.1.2", "magic-string": "^0.30.17", "pathe": "^2.0.3" }, @@ -2789,9 +2777,9 @@ } }, "node_modules/@vitest/spy": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.1.tgz", - "integrity": "sha512-+EmrUOOXbKzLkTDwlsc/xrwOlPDXyVk3Z6P6K4oiCndxz7YLpp/0R0UsWVOKT0IXWjjBJuSMk6D27qipaupcvQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.2.tgz", + "integrity": "sha512-OEc5fSXMws6sHVe4kOFyDSj/+4MSwst0ib4un0DlcYgQvRuYQ0+M2HyqGaauUMnjq87tmUaMNDxKQx7wNfVqPA==", "dev": true, "license": "MIT", "dependencies": { @@ -2802,13 +2790,13 @@ } }, "node_modules/@vitest/utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.1.tgz", - "integrity": "sha512-1XIjflyaU2k3HMArJ50bwSh3wKWPD6Q47wz/NUSmRV0zNywPc4w79ARjg/i/aNINHwA+mIALhUVqD9/aUvZNgg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.2.tgz", + "integrity": "sha512-5GGd0ytZ7BH3H6JTj9Kw7Prn1Nbg0wZVrIvou+UWxm54d+WoXXgAgjFJ8wn3LdagWLFSEfpPeyYrByZaGEZHLg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.1.1", + "@vitest/pretty-format": "3.1.2", "loupe": "^3.1.3", "tinyrainbow": "^2.0.0" }, @@ -4018,9 +4006,9 @@ } }, "node_modules/es-module-lexer": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", - "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", "dev": true, "license": "MIT" }, @@ -4189,20 +4177,20 @@ } }, "node_modules/eslint": { - "version": "9.24.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.24.0.tgz", - "integrity": "sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==", + "version": "9.25.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.25.1.tgz", + "integrity": "sha512-E6Mtz9oGQWDCpV12319d59n4tx9zOTXSTmc8BLVxBx+G/0RdM5MvEEJLU9c0+aleoePYYgVTOsRblx433qmhWQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.20.0", - "@eslint/config-helpers": "^0.2.0", - "@eslint/core": "^0.12.0", + "@eslint/config-helpers": "^0.2.1", + "@eslint/core": "^0.13.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.24.0", - "@eslint/plugin-kit": "^0.2.7", + "@eslint/js": "9.25.1", + "@eslint/plugin-kit": "^0.2.8", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", @@ -4262,6 +4250,22 @@ "eslint": ">=7.0.0" } }, + "node_modules/eslint-p": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/eslint-p/-/eslint-p-0.21.0.tgz", + "integrity": "sha512-w6krTooDpMF5Rezfc14FOQwX87QyH2ouZoTDySixbL8auiBRsxA4JPBrzOS5IfuLxcJHJPHjf/FnGfjlvI/kDw==", + "dev": true, + "license": "ISC", + "dependencies": { + "eslint": "9.25.1" + }, + "bin": { + "eslint-p": "lib/eslint-p.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/eslint-plugin-svelte": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-3.5.1.tgz", @@ -4601,9 +4605,9 @@ } }, "node_modules/fdir": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", - "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==", + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", "dev": true, "license": "MIT", "peerDependencies": { @@ -5961,9 +5965,9 @@ } }, "node_modules/maplibre-gl": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-5.3.1.tgz", - "integrity": "sha512-Ihx+oUUSsZkjMou1Cw5J6silE+5OtFFQSPslWF9+7v4yFC/XDHrpsORYO9lWE4KZI0djCEUpZQJpkpnMArAbeA==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-5.4.0.tgz", + "integrity": "sha512-ZVrtdFIhFAqt53H2k5Ssqn7QIKNI19fW+He5tr4loxZxWZffp1aZYY9ImNncAJaALU/NYlV6Eul7UVB56/N7WQ==", "license": "BSD-3-Clause", "dependencies": { "@mapbox/geojson-rewind": "^0.5.2", @@ -8174,9 +8178,9 @@ } }, "node_modules/svelte": { - "version": "5.27.0", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.27.0.tgz", - "integrity": "sha512-Uai13Ydt1ZE+bUHme6b9U38PCYVNCqBRoBMkUKbFbKiD7kHWjdUUrklYAQZJxyKK81qII4mrBwe/YmvEMSlC9w==", + "version": "5.28.2", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.28.2.tgz", + "integrity": "sha512-FbWBxgWOpQfhKvoGJv/TFwzqb4EhJbwCD17dB0tEpQiw1XyUEKZJtgm4nA4xq3LLsMo7hu5UY/BOFmroAxKTMg==", "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0", @@ -8252,9 +8256,9 @@ } }, "node_modules/svelte-gestures": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/svelte-gestures/-/svelte-gestures-5.1.3.tgz", - "integrity": "sha512-ELOlzuH9E4+S1biCCTfusRlvzFpnqRPlljEqayoBTu5STH42u0kTT45D1m3Py3E9UmIyZTgrSLw6Fus/fh75Dw==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/svelte-gestures/-/svelte-gestures-5.1.4.tgz", + "integrity": "sha512-gfSO/GqWLu9nRMCz12jqdyA0+NTsojYcIBcRqZjwWrpQbqMXr0zWPFpZBtzfYbRHtuFxZImMZp9MrVaFCYbhDg==", "license": "MIT" }, "node_modules/svelte-i18n": { @@ -8741,6 +8745,23 @@ "dev": true, "license": "MIT" }, + "node_modules/tinyglobby": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", + "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, "node_modules/tinypool": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", @@ -8901,15 +8922,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.30.1.tgz", - "integrity": "sha512-D7lC0kcehVH7Mb26MRQi64LMyRJsj3dToJxM1+JVTl53DQSV5/7oUGWQLcKl1C1KnoVHxMMU2FNQMffr7F3Row==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.31.0.tgz", + "integrity": "sha512-u+93F0sB0An8WEAPtwxVhFby573E8ckdjwUUQUj9QA4v8JAvgtoDdIyYR3XFwFHq2W1KJ1AurwJCO+w+Y1ixyQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.30.1", - "@typescript-eslint/parser": "8.30.1", - "@typescript-eslint/utils": "8.30.1" + "@typescript-eslint/eslint-plugin": "8.31.0", + "@typescript-eslint/parser": "8.31.0", + "@typescript-eslint/utils": "8.31.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -9036,15 +9057,18 @@ } }, "node_modules/vite": { - "version": "6.2.6", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.6.tgz", - "integrity": "sha512-9xpjNl3kR4rVDZgPNdTL0/c6ao4km69a/2ihNQbcANz8RuCOK3hQBmLSJf3bRKVQjVMda+YvizNE8AwvogcPbw==", + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.3.tgz", + "integrity": "sha512-5nXH+QsELbFKhsEfWLkHrvgRpTdGJzqOZ+utSdmPTvwHmvU6ITTm3xx+mRusihkcI8GeC7lCDyn3kDtiki9scw==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", "postcss": "^8.5.3", - "rollup": "^4.30.1" + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" }, "bin": { "vite": "bin/vite.js" @@ -9123,9 +9147,9 @@ } }, "node_modules/vite-node": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.1.tgz", - "integrity": "sha512-V+IxPAE2FvXpTCHXyNem0M+gWm6J7eRyWPR6vYoG/Gl+IscNOjXzztUhimQgTxaAoUoj40Qqimaa0NLIOOAH4w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.2.tgz", + "integrity": "sha512-/8iMryv46J3aK13iUXsei5G/A3CUlW4665THCPS+K8xAaqrVWiGB4RfXMQXCLjpK9P2eK//BczrVkn5JLAk6DA==", "dev": true, "license": "MIT", "dependencies": { @@ -9146,9 +9170,9 @@ } }, "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz", - "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.3.tgz", + "integrity": "sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==", "cpu": [ "ppc64" ], @@ -9163,9 +9187,9 @@ } }, "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz", - "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.3.tgz", + "integrity": "sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==", "cpu": [ "arm" ], @@ -9180,9 +9204,9 @@ } }, "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz", - "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.3.tgz", + "integrity": "sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==", "cpu": [ "arm64" ], @@ -9197,9 +9221,9 @@ } }, "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz", - "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.3.tgz", + "integrity": "sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==", "cpu": [ "x64" ], @@ -9214,9 +9238,9 @@ } }, "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz", - "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.3.tgz", + "integrity": "sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==", "cpu": [ "arm64" ], @@ -9231,9 +9255,9 @@ } }, "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz", - "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.3.tgz", + "integrity": "sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==", "cpu": [ "x64" ], @@ -9248,9 +9272,9 @@ } }, "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz", - "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.3.tgz", + "integrity": "sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==", "cpu": [ "arm64" ], @@ -9265,9 +9289,9 @@ } }, "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz", - "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.3.tgz", + "integrity": "sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==", "cpu": [ "x64" ], @@ -9282,9 +9306,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz", - "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.3.tgz", + "integrity": "sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==", "cpu": [ "arm" ], @@ -9299,9 +9323,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz", - "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.3.tgz", + "integrity": "sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==", "cpu": [ "arm64" ], @@ -9316,9 +9340,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz", - "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.3.tgz", + "integrity": "sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==", "cpu": [ "ia32" ], @@ -9333,9 +9357,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz", - "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.3.tgz", + "integrity": "sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==", "cpu": [ "loong64" ], @@ -9350,9 +9374,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz", - "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.3.tgz", + "integrity": "sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==", "cpu": [ "mips64el" ], @@ -9367,9 +9391,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz", - "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.3.tgz", + "integrity": "sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==", "cpu": [ "ppc64" ], @@ -9384,9 +9408,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz", - "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.3.tgz", + "integrity": "sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==", "cpu": [ "riscv64" ], @@ -9401,9 +9425,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz", - "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.3.tgz", + "integrity": "sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==", "cpu": [ "s390x" ], @@ -9418,9 +9442,9 @@ } }, "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz", - "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.3.tgz", + "integrity": "sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==", "cpu": [ "x64" ], @@ -9435,9 +9459,9 @@ } }, "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz", - "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.3.tgz", + "integrity": "sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==", "cpu": [ "x64" ], @@ -9452,9 +9476,9 @@ } }, "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz", - "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.3.tgz", + "integrity": "sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==", "cpu": [ "x64" ], @@ -9469,9 +9493,9 @@ } }, "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz", - "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.3.tgz", + "integrity": "sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==", "cpu": [ "x64" ], @@ -9486,9 +9510,9 @@ } }, "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz", - "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.3.tgz", + "integrity": "sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==", "cpu": [ "arm64" ], @@ -9503,9 +9527,9 @@ } }, "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz", - "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.3.tgz", + "integrity": "sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==", "cpu": [ "ia32" ], @@ -9520,9 +9544,9 @@ } }, "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz", - "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.3.tgz", + "integrity": "sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==", "cpu": [ "x64" ], @@ -9537,9 +9561,9 @@ } }, "node_modules/vite/node_modules/esbuild": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", - "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.3.tgz", + "integrity": "sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -9550,31 +9574,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.2", - "@esbuild/android-arm": "0.25.2", - "@esbuild/android-arm64": "0.25.2", - "@esbuild/android-x64": "0.25.2", - "@esbuild/darwin-arm64": "0.25.2", - "@esbuild/darwin-x64": "0.25.2", - "@esbuild/freebsd-arm64": "0.25.2", - "@esbuild/freebsd-x64": "0.25.2", - "@esbuild/linux-arm": "0.25.2", - "@esbuild/linux-arm64": "0.25.2", - "@esbuild/linux-ia32": "0.25.2", - "@esbuild/linux-loong64": "0.25.2", - "@esbuild/linux-mips64el": "0.25.2", - "@esbuild/linux-ppc64": "0.25.2", - "@esbuild/linux-riscv64": "0.25.2", - "@esbuild/linux-s390x": "0.25.2", - "@esbuild/linux-x64": "0.25.2", - "@esbuild/netbsd-arm64": "0.25.2", - "@esbuild/netbsd-x64": "0.25.2", - "@esbuild/openbsd-arm64": "0.25.2", - "@esbuild/openbsd-x64": "0.25.2", - "@esbuild/sunos-x64": "0.25.2", - "@esbuild/win32-arm64": "0.25.2", - "@esbuild/win32-ia32": "0.25.2", - "@esbuild/win32-x64": "0.25.2" + "@esbuild/aix-ppc64": "0.25.3", + "@esbuild/android-arm": "0.25.3", + "@esbuild/android-arm64": "0.25.3", + "@esbuild/android-x64": "0.25.3", + "@esbuild/darwin-arm64": "0.25.3", + "@esbuild/darwin-x64": "0.25.3", + "@esbuild/freebsd-arm64": "0.25.3", + "@esbuild/freebsd-x64": "0.25.3", + "@esbuild/linux-arm": "0.25.3", + "@esbuild/linux-arm64": "0.25.3", + "@esbuild/linux-ia32": "0.25.3", + "@esbuild/linux-loong64": "0.25.3", + "@esbuild/linux-mips64el": "0.25.3", + "@esbuild/linux-ppc64": "0.25.3", + "@esbuild/linux-riscv64": "0.25.3", + "@esbuild/linux-s390x": "0.25.3", + "@esbuild/linux-x64": "0.25.3", + "@esbuild/netbsd-arm64": "0.25.3", + "@esbuild/netbsd-x64": "0.25.3", + "@esbuild/openbsd-arm64": "0.25.3", + "@esbuild/openbsd-x64": "0.25.3", + "@esbuild/sunos-x64": "0.25.3", + "@esbuild/win32-arm64": "0.25.3", + "@esbuild/win32-ia32": "0.25.3", + "@esbuild/win32-x64": "0.25.3" } }, "node_modules/vitefu": { @@ -9597,31 +9621,32 @@ } }, "node_modules/vitest": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.1.tgz", - "integrity": "sha512-kiZc/IYmKICeBAZr9DQ5rT7/6bD9G7uqQEki4fxazi1jdVl2mWGzedtBs5s6llz59yQhVb7FFY2MbHzHCnT79Q==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.2.tgz", + "integrity": "sha512-WaxpJe092ID1C0mr+LH9MmNrhfzi8I65EX/NRU/Ld016KqQNRgxSOlGNP1hHN+a/F8L15Mh8klwaF77zR3GeDQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "3.1.1", - "@vitest/mocker": "3.1.1", - "@vitest/pretty-format": "^3.1.1", - "@vitest/runner": "3.1.1", - "@vitest/snapshot": "3.1.1", - "@vitest/spy": "3.1.1", - "@vitest/utils": "3.1.1", + "@vitest/expect": "3.1.2", + "@vitest/mocker": "3.1.2", + "@vitest/pretty-format": "^3.1.2", + "@vitest/runner": "3.1.2", + "@vitest/snapshot": "3.1.2", + "@vitest/spy": "3.1.2", + "@vitest/utils": "3.1.2", "chai": "^5.2.0", "debug": "^4.4.0", - "expect-type": "^1.2.0", + "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", - "std-env": "^3.8.1", + "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.13", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", - "vite-node": "3.1.1", + "vite-node": "3.1.2", "why-is-node-running": "^2.3.0" }, "bin": { @@ -9637,8 +9662,8 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.1.1", - "@vitest/ui": "3.1.1", + "@vitest/browser": "3.1.2", + "@vitest/ui": "3.1.2", "happy-dom": "*", "jsdom": "*" }, diff --git a/web/package.json b/web/package.json index 4ee7c015c8..9aa9bee6bc 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "immich-web", - "version": "1.131.3", + "version": "1.132.3", "license": "GNU Affero General Public License version 3", "type": "module", "scripts": { @@ -12,9 +12,10 @@ "check:svelte": "svelte-check --no-tsconfig --fail-on-warnings --compiler-warnings 'reactive_declaration_non_reactive_property:ignore' --ignore src/lib/components/photos-page/asset-grid.svelte", "check:typescript": "tsc --noEmit", "check:watch": "npm run check:svelte -- --watch", - "check:code": "npm run format && npm run lint && npm run check:svelte && npm run check:typescript", + "check:code": "npm run format && npm run lint:p && npm run check:svelte && npm run check:typescript", "check:all": "npm run check:code && npm run test:cov", "lint": "eslint . --max-warnings 0", + "lint:p": "eslint-p . --max-warnings 0 --concurrency=4", "lint:fix": "npm run lint -- --fix", "format": "prettier --check .", "format:fix": "prettier --write .", @@ -26,7 +27,7 @@ "dependencies": { "@formatjs/icu-messageformat-parser": "^2.9.8", "@immich/sdk": "file:../open-api/typescript-sdk", - "@immich/ui": "^0.17.3", + "@immich/ui": "^0.18.1", "@mapbox/mapbox-gl-rtl-text": "0.2.3", "@mdi/js": "^7.4.47", "@photo-sphere-viewer/core": "^5.11.5", @@ -74,6 +75,7 @@ "dotenv": "^16.4.7", "eslint": "^9.18.0", "eslint-config-prettier": "^10.0.0", + "eslint-p": "^0.21.0", "eslint-plugin-svelte": "^3.0.0", "eslint-plugin-unicorn": "^57.0.0", "factory.ts": "^1.4.1", diff --git a/web/src/lib/actions/__test__/focus-trap.spec.ts b/web/src/lib/actions/__test__/focus-trap.spec.ts index d92d8e037d..b03064a91d 100644 --- a/web/src/lib/actions/__test__/focus-trap.spec.ts +++ b/web/src/lib/actions/__test__/focus-trap.spec.ts @@ -1,8 +1,11 @@ import FocusTrapTest from '$lib/actions/__test__/focus-trap-test.svelte'; +import { setDefaultTabbleOptions } from '$lib/utils/focus-util'; import { render, screen } from '@testing-library/svelte'; import userEvent from '@testing-library/user-event'; import { tick } from 'svelte'; +setDefaultTabbleOptions({ displayCheck: 'none' }); + describe('focusTrap action', () => { const user = userEvent.setup(); @@ -38,6 +41,7 @@ describe('focusTrap action', () => { const openButton = screen.getByText('Open'); await user.click(openButton); + await tick(); expect(document.activeElement).toEqual(screen.getByTestId('one')); screen.getByText('Close').click(); diff --git a/web/src/lib/actions/focus-trap.ts b/web/src/lib/actions/focus-trap.ts index 1564dd90d0..2b03282c2d 100644 --- a/web/src/lib/actions/focus-trap.ts +++ b/web/src/lib/actions/focus-trap.ts @@ -1,5 +1,5 @@ import { shortcuts } from '$lib/actions/shortcut'; -import { getFocusable } from '$lib/utils/focus-util'; +import { getTabbable } from '$lib/utils/focus-util'; import { tick } from 'svelte'; interface Options { @@ -18,18 +18,21 @@ export function focusTrap(container: HTMLElement, options?: Options) { }; }; - const setInitialFocus = () => { - const focusableElement = getFocusable(container)[0]; - // Use tick() to ensure focus trap works correctly inside - void tick().then(() => focusableElement?.focus()); + const setInitialFocus = async () => { + const focusableElement = getTabbable(container, false)[0]; + if (focusableElement) { + // Use tick() to ensure focus trap works correctly inside + await tick(); + focusableElement?.focus(); + } }; if (withDefaults(options).active) { - setInitialFocus(); + void setInitialFocus(); } const getFocusableElements = () => { - const focusableElements = getFocusable(container); + const focusableElements = getTabbable(container); return [ focusableElements.at(0), // focusableElements.at(-1), @@ -67,7 +70,7 @@ export function focusTrap(container: HTMLElement, options?: Options) { update(newOptions?: Options) { options = newOptions; if (withDefaults(options).active) { - setInitialFocus(); + void setInitialFocus(); } }, destroy() { diff --git a/web/src/lib/components/admin-page/jobs/job-tile.svelte b/web/src/lib/components/admin-page/jobs/job-tile.svelte index 80dd29e0be..c77ff60f22 100644 --- a/web/src/lib/components/admin-page/jobs/job-tile.svelte +++ b/web/src/lib/components/admin-page/jobs/job-tile.svelte @@ -51,7 +51,7 @@ let isIdle = $derived(!queueStatus.isActive && !queueStatus.isPaused); let multipleButtons = $derived(allText || refreshText); - const commonClasses = 'flex place-items-center justify-between w-full py-2 sm:py-4 pr-4 pl-6'; + const commonClasses = 'flex place-items-center justify-between w-full py-2 sm:py-4 pe-4 ps-6';

{$t('active')}

@@ -119,7 +119,7 @@

{waitingCount.toLocaleString($locale)} diff --git a/web/src/lib/components/admin-page/server-stats/server-stats-panel.svelte b/web/src/lib/components/admin-page/server-stats/server-stats-panel.svelte index bb288511ac..8bae8fee4b 100644 --- a/web/src/lib/components/admin-page/server-stats/server-stats-panel.svelte +++ b/web/src/lib/components/admin-page/server-stats/server-stats-panel.svelte @@ -79,7 +79,7 @@ {zeros(statsUsage)}{statsUsage} - {statsUsageUnit} + {statsUsageUnit}

@@ -88,7 +88,7 @@

{$t('user_usage_detail').toUpperCase()}

- +
diff --git a/web/src/lib/components/admin-page/server-stats/stats-card.svelte b/web/src/lib/components/admin-page/server-stats/stats-card.svelte index 14d32c055f..b1804427e9 100644 --- a/web/src/lib/components/admin-page/server-stats/stats-card.svelte +++ b/web/src/lib/components/admin-page/server-stats/stats-card.svelte @@ -31,7 +31,7 @@ class="text-immich-primary dark:text-immich-dark-primary">{value} {#if unit} - {unit} + {unit} {/if} diff --git a/web/src/lib/components/admin-page/settings/auth/auth-settings.svelte b/web/src/lib/components/admin-page/settings/auth/auth-settings.svelte index 5380a76286..b2454b06c3 100644 --- a/web/src/lib/components/admin-page/settings/auth/auth-settings.svelte +++ b/web/src/lib/components/admin-page/settings/auth/auth-settings.svelte @@ -1,16 +1,17 @@ -
+
@@ -48,18 +48,18 @@ class="block w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray dark:text-immich-dark-fg" > toggleAlbumGroupCollapsing(albumGroup.id)} aria-expanded={!isCollapsed} > - diff --git a/web/src/lib/components/album-page/user-selection-modal.svelte b/web/src/lib/components/album-page/user-selection-modal.svelte index 1496c1ce66..9ee7cc550d 100644 --- a/web/src/lib/components/album-page/user-selection-modal.svelte +++ b/web/src/lib/components/album-page/user-selection-modal.svelte @@ -94,7 +94,7 @@ -
+

{user.name}

@@ -136,7 +136,7 @@ class="flex w-full place-items-center gap-4 p-4" > -
+

{user.name}

diff --git a/web/src/lib/components/asset-viewer/activity-viewer.svelte b/web/src/lib/components/asset-viewer/activity-viewer.svelte index caa1ced290..e98769d495 100644 --- a/web/src/lib/components/asset-viewer/activity-viewer.svelte +++ b/web/src/lib/components/asset-viewer/activity-viewer.svelte @@ -1,32 +1,24 @@ -{#if !isSharedLink() && $preferences?.ratings.enabled} +{#if !authManager.key && $preferences?.ratings.enabled}
handlePromiseError(handleChangeRating(rating))} />
diff --git a/web/src/lib/components/asset-viewer/detail-panel-tags.svelte b/web/src/lib/components/asset-viewer/detail-panel-tags.svelte index 39ca096efd..eee7a7c0b6 100644 --- a/web/src/lib/components/asset-viewer/detail-panel-tags.svelte +++ b/web/src/lib/components/asset-viewer/detail-panel-tags.svelte @@ -3,7 +3,7 @@ import TagAssetForm from '$lib/components/forms/tag-asset-form.svelte'; import Portal from '$lib/components/shared-components/portal/portal.svelte'; import { AppRoute } from '$lib/constants'; - import { isSharedLink } from '$lib/utils'; + import { authManager } from '$lib/managers/auth-manager.svelte'; import { removeTag, tagAssets } from '$lib/utils/asset-utils'; import { getAssetInfo, type AssetResponseDto } from '@immich/sdk'; import { mdiClose, mdiPlus } from '@mdi/js'; @@ -41,7 +41,7 @@ }; -{#if isOwner && !isSharedLink()} +{#if isOwner && !authManager.key}

{$t('tags').toUpperCase()}

@@ -50,7 +50,7 @@ {#each tags as tag (tag.id)}

@@ -60,7 +60,7 @@

- +
diff --git a/web/src/lib/components/asset-viewer/image-panorama-viewer.svelte b/web/src/lib/components/asset-viewer/image-panorama-viewer.svelte index 7b9fd85b4a..d678b00ddb 100644 --- a/web/src/lib/components/asset-viewer/image-panorama-viewer.svelte +++ b/web/src/lib/components/asset-viewer/image-panorama-viewer.svelte @@ -1,10 +1,11 @@ diff --git a/web/src/lib/components/asset-viewer/photo-viewer.svelte b/web/src/lib/components/asset-viewer/photo-viewer.svelte index d3a9da3633..531f075b86 100644 --- a/web/src/lib/components/asset-viewer/photo-viewer.svelte +++ b/web/src/lib/components/asset-viewer/photo-viewer.svelte @@ -21,6 +21,7 @@ import FaceEditor from '$lib/components/asset-viewer/face-editor/face-editor.svelte'; import { photoViewerImgElement } from '$lib/stores/assets-store.svelte'; import { isFaceEditMode } from '$lib/stores/face-edit.svelte'; + import { cancelImageUrl, preloadImageUrl } from '$lib/utils/sw-messaging'; interface Props { asset: AssetResponseDto; @@ -71,8 +72,7 @@ const preload = (targetSize: AssetMediaSize | 'original', preloadAssets?: AssetResponseDto[]) => { for (const preloadAsset of preloadAssets || []) { if (preloadAsset.type === AssetTypeEnum.Image) { - let img = new Image(); - img.src = getAssetUrl(preloadAsset.id, targetSize, preloadAsset.thumbhash); + preloadImageUrl(getAssetUrl(preloadAsset.id, targetSize, preloadAsset.thumbhash)); } } }; @@ -168,6 +168,7 @@ return () => { loader?.removeEventListener('load', onload); loader?.removeEventListener('error', onerror); + cancelImageUrl(imageLoaderUrl); }; }); @@ -213,7 +214,7 @@ {$getAltText(asset)} {/if} diff --git a/web/src/lib/components/assets/thumbnail/__test__/thumbnail.spec.ts b/web/src/lib/components/assets/thumbnail/__test__/thumbnail.spec.ts index f7447551f0..7f6a9d588e 100644 --- a/web/src/lib/components/assets/thumbnail/__test__/thumbnail.spec.ts +++ b/web/src/lib/components/assets/thumbnail/__test__/thumbnail.spec.ts @@ -1,7 +1,8 @@ import { getIntersectionObserverMock } from '$lib/__mocks__/intersection-observer.mock'; import Thumbnail from '$lib/components/assets/thumbnail/thumbnail.svelte'; +import { getTabbable } from '$lib/utils/focus-util'; import { assetFactory } from '@test-data/factories/asset-factory'; -import { fireEvent, render, screen } from '@testing-library/svelte'; +import { fireEvent, render } from '@testing-library/svelte'; vi.hoisted(() => { Object.defineProperty(globalThis, 'matchMedia', { @@ -25,56 +26,53 @@ describe('Thumbnail component', () => { vi.stubGlobal('IntersectionObserver', getIntersectionObserverMock()); vi.mock('$lib/utils/navigation', () => ({ currentUrlReplaceAssetId: vi.fn(), + isSharedLinkRoute: vi.fn().mockReturnValue(false), })); }); it('should only contain a single tabbable element (the container)', () => { const asset = assetFactory.build({ originalPath: 'image.jpg', originalMimeType: 'image/jpeg' }); - render(Thumbnail, { + const { baseElement } = render(Thumbnail, { asset, - focussed: false, selected: true, }); - const container = screen.getByTestId('container-with-tabindex'); - expect(container.getAttribute('tabindex')).toBe('0'); + const container = baseElement.querySelector('[data-thumbnail-focus-container]'); + expect(container).not.toBeNull(); + expect(container!.getAttribute('tabindex')).toBe('0'); - // This isn't capturing all tabbable elements, but should be the most likely ones. Mainly guarding against - // inserting extra tabbable elments in future in - let allTabbableElements = screen.queryAllByRole('link'); - allTabbableElements = allTabbableElements.concat(screen.queryAllByRole('checkbox')); - expect(allTabbableElements.length).toBeGreaterThan(0); - for (const tabbableElement of allTabbableElements) { - const testIdValue = tabbableElement.dataset.testid; - if (testIdValue === null || testIdValue !== 'container-with-tabindex') { - expect(tabbableElement.getAttribute('tabindex')).toBe('-1'); - } - } + // Guarding against inserting extra tabbable elments in future in + const tabbables = getTabbable(container!); + expect(tabbables.length).toBe(0); }); it('handleFocus should be called on focus of container', async () => { const asset = assetFactory.build({ originalPath: 'image.jpg', originalMimeType: 'image/jpeg' }); const handleFocusSpy = vi.fn(); - render(Thumbnail, { + const { baseElement } = render(Thumbnail, { asset, handleFocus: handleFocusSpy, }); - const container = screen.getByTestId('container-with-tabindex'); - await fireEvent(container, new FocusEvent('focus')); + const container = baseElement.querySelector('[data-thumbnail-focus-container]'); + expect(container).not.toBeNull(); + await fireEvent(container as HTMLElement, new FocusEvent('focus')); expect(handleFocusSpy).toBeCalled(); }); - it('element will be focussed if not already', () => { + it('element will be focussed if not already', async () => { const asset = assetFactory.build({ originalPath: 'image.jpg', originalMimeType: 'image/jpeg' }); const handleFocusSpy = vi.fn(); - render(Thumbnail, { + const { baseElement } = render(Thumbnail, { asset, - focussed: true, handleFocus: handleFocusSpy, }); + const container = baseElement.querySelector('[data-thumbnail-focus-container]'); + expect(container).not.toBeNull(); + await fireEvent(container as HTMLElement, new FocusEvent('focus')); + expect(handleFocusSpy).toBeCalled(); }); }); diff --git a/web/src/lib/components/assets/thumbnail/image-thumbnail.svelte b/web/src/lib/components/assets/thumbnail/image-thumbnail.svelte index 55357abbc0..04493b273c 100644 --- a/web/src/lib/components/assets/thumbnail/image-thumbnail.svelte +++ b/web/src/lib/components/assets/thumbnail/image-thumbnail.svelte @@ -2,9 +2,11 @@ import { thumbhash } from '$lib/actions/thumbhash'; import BrokenAsset from '$lib/components/assets/broken-asset.svelte'; import Icon from '$lib/components/elements/icon.svelte'; + import { cancelImageUrl } from '$lib/utils/sw-messaging'; import { TUNABLES } from '$lib/utils/tunables'; import { mdiEyeOffOutline } from '@mdi/js'; import type { ClassValue } from 'svelte/elements'; + import type { ActionReturn } from 'svelte/action'; import { fade } from 'svelte/transition'; interface Props { @@ -59,11 +61,14 @@ onComplete?.(true); }; - function mount(elem: HTMLImageElement) { + function mount(elem: HTMLImageElement): ActionReturn { if (elem.complete) { loaded = true; onComplete?.(false); } + return { + destroy: () => cancelImageUrl(url), + }; } let optionalClasses = $derived( @@ -101,7 +106,7 @@ {/if} {#if hidden} -
+
{/if} diff --git a/web/src/lib/components/assets/thumbnail/thumbnail.svelte b/web/src/lib/components/assets/thumbnail/thumbnail.svelte index c21acd8f86..3a00af34ad 100644 --- a/web/src/lib/components/assets/thumbnail/thumbnail.svelte +++ b/web/src/lib/components/assets/thumbnail/thumbnail.svelte @@ -2,7 +2,7 @@ import Icon from '$lib/components/elements/icon.svelte'; import { ProjectionType } from '$lib/constants'; import { locale, playVideoThumbnailOnHover } from '$lib/stores/preferences.store'; - import { getAssetPlaybackUrl, getAssetThumbnailUrl, isSharedLink } from '$lib/utils'; + import { getAssetPlaybackUrl, getAssetThumbnailUrl } from '$lib/utils'; import { timeToSeconds } from '$lib/utils/date-time'; import { getAltText } from '$lib/utils/thumbnail-util'; import { AssetMediaSize, AssetTypeEnum, type AssetResponseDto } from '@immich/sdk'; @@ -17,15 +17,16 @@ } from '@mdi/js'; import { thumbhash } from '$lib/actions/thumbhash'; + import { authManager } from '$lib/managers/auth-manager.svelte'; import { mobileDevice } from '$lib/stores/mobile-device.svelte'; + import { focusNext } from '$lib/utils/focus-util'; import { currentUrlReplaceAssetId } from '$lib/utils/navigation'; import { TUNABLES } from '$lib/utils/tunables'; + import { onMount } from 'svelte'; import type { ClassValue } from 'svelte/elements'; import { fade } from 'svelte/transition'; import ImageThumbnail from './image-thumbnail.svelte'; import VideoThumbnail from './video-thumbnail.svelte'; - import { onMount } from 'svelte'; - import { getFocusable } from '$lib/utils/focus-util'; interface Props { asset: AssetResponseDto; @@ -34,7 +35,6 @@ thumbnailWidth?: number | undefined; thumbnailHeight?: number | undefined; selected?: boolean; - focussed?: boolean; selectionCandidate?: boolean; disabled?: boolean; disableLinkMouseOver?: boolean; @@ -57,7 +57,6 @@ thumbnailWidth = undefined, thumbnailHeight = undefined, selected = false, - focussed = false, selectionCandidate = false, disabled = false, disableLinkMouseOver = false, @@ -78,17 +77,11 @@ } = TUNABLES; let usingMobileDevice = $derived(mobileDevice.pointerCoarse); - let focussableElement: HTMLElement | undefined = $state(); + let element: HTMLElement | undefined = $state(); let mouseOver = $state(false); let loaded = $state(false); let thumbError = $state(false); - $effect(() => { - if (focussed && document.activeElement !== focussableElement) { - focussableElement?.focus(); - } - }); - let width = $derived(thumbnailSize || thumbnailWidth || 235); let height = $derived(thumbnailSize || thumbnailHeight || 235); @@ -235,31 +228,14 @@ if (evt.key === 'x') { onSelect?.(asset); } - if (document.activeElement === focussableElement && evt.key === 'Escape') { - const focusable = getFocusable(document); - const index = focusable.indexOf(focussableElement); - - let i = index + 1; - while (i !== index) { - const next = focusable[i]; - if (next.dataset.thumbnailFocusContainer !== undefined) { - if (i === focusable.length - 1) { - i = 0; - } else { - i++; - } - continue; - } - next.focus(); - break; - } + if (document.activeElement === element && evt.key === 'Escape') { + focusNext((element) => element.dataset.thumbnailFocusContainer === undefined, true); } }} onclick={handleClick} - bind:this={focussableElement} + bind:this={element} onfocus={handleFocus} data-thumbnail-focus-container - data-testid="container-with-tabindex" tabindex={0} role="link" > @@ -331,21 +307,21 @@ >
- {#if !isSharedLink() && asset.isFavorite} -
+ {#if !authManager.key && asset.isFavorite} +
{/if} - {#if !isSharedLink() && showArchiveIcon && asset.isArchived} -
+ {#if !authManager.key && showArchiveIcon && asset.isArchived} +
{/if} {#if asset.type === AssetTypeEnum.Image && asset.exifInfo?.projectionType === ProjectionType.EQUIRECTANGULAR} -
- +
+
@@ -356,10 +332,10 @@
- +

{asset.stack.assetCount.toLocaleString($locale)}

diff --git a/web/src/lib/components/assets/thumbnail/video-thumbnail.svelte b/web/src/lib/components/assets/thumbnail/video-thumbnail.svelte index fc3cb2e951..9959c86548 100644 --- a/web/src/lib/components/assets/thumbnail/video-thumbnail.svelte +++ b/web/src/lib/components/assets/thumbnail/video-thumbnail.svelte @@ -55,7 +55,7 @@ }; -
+
{#if showTime} {#if remainingSeconds < 60} @@ -69,7 +69,7 @@ {/if} - + {#if enablePlayback} {#if loading} diff --git a/web/src/lib/components/elements/buttons/button.svelte b/web/src/lib/components/elements/buttons/button.svelte index 991bbaecee..ac7d9808f3 100644 --- a/web/src/lib/components/elements/buttons/button.svelte +++ b/web/src/lib/components/elements/buttons/button.svelte @@ -79,7 +79,7 @@ }; const sizeClasses: Record = { - tiny: 'p-0 ml-2 mr-0 align-top', + tiny: 'p-0 ms-2 me-0 align-top', icon: 'p-2.5', link: 'p-2 font-medium', sm: 'px-4 py-2 text-sm font-medium', diff --git a/web/src/lib/components/elements/buttons/skip-link.svelte b/web/src/lib/components/elements/buttons/skip-link.svelte index a1a24634c4..a21fc60caf 100644 --- a/web/src/lib/components/elements/buttons/skip-link.svelte +++ b/web/src/lib/components/elements/buttons/skip-link.svelte @@ -1,6 +1,7 @@ -
+
{$t('merge')} {/snippet} diff --git a/web/src/lib/components/faces-page/people-card.svelte b/web/src/lib/components/faces-page/people-card.svelte index 4aff4e96f8..b740953340 100644 --- a/web/src/lib/components/faces-page/people-card.svelte +++ b/web/src/lib/components/faces-page/people-card.svelte @@ -54,7 +54,7 @@ circle /> {#if person.isFavorite} -
+
{/if} @@ -62,7 +62,7 @@ {#if showVerticalDots} -
+
($boundingBoxesArray = [peopleWithFaces[index]])} onmouseover={() => ($boundingBoxesArray = [peopleWithFaces[index]])} onmouseleave={() => ($boundingBoxesArray = [])} @@ -303,7 +303,7 @@

{/if} -
+
{#if selectedPersonToCreate[face.id] || selectedPersonToReassign[face.id]} handleReset(face.id)} /> {:else} @@ -321,29 +321,29 @@ title={$t('select_new_face')} size="18" padding="1" - class="absolute left-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform" + class="absolute start-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform" onclick={() => handleFacePicker(face)} /> {/if}
-
+
{#if !selectedPersonToCreate[face.id] && !selectedPersonToReassign[face.id] && !face.person}
{/if}
{#if face.person != null} -
+
deleteAssetFace(face)} />
diff --git a/web/src/lib/components/faces-page/unmerge-face-selector.svelte b/web/src/lib/components/faces-page/unmerge-face-selector.svelte index e808c98748..41c584d602 100644 --- a/web/src/lib/components/faces-page/unmerge-face-selector.svelte +++ b/web/src/lib/components/faces-page/unmerge-face-selector.svelte @@ -120,7 +120,7 @@
{#snippet leading()} @@ -140,7 +140,7 @@ {:else} {/if} - {$t('create_new_person')} {$t('create_new_person')} {$t('reassign')}
{/snippet} diff --git a/web/src/lib/components/forms/library-import-paths-form.svelte b/web/src/lib/components/forms/library-import-paths-form.svelte index 639b81071f..64c32532ef 100644 --- a/web/src/lib/components/forms/library-import-paths-form.svelte +++ b/web/src/lib/components/forms/library-import-paths-form.svelte @@ -173,7 +173,7 @@ {/if} -
+ {albumGroup.name} - + ({$t('albums_count', { values: { count: albumGroup.albums.length } })})
+
{#each validatedPaths as validatedPath, listIndex (validatedPath.importPath)} -
+ {#if validatedPath.isValid} - +
{#each exclusionPatterns as exclusionPattern, listIndex (exclusionPattern)}

{tag.value} @@ -81,7 +81,7 @@ diff --git a/web/src/lib/components/shared-components/navigation-bar/notification-panel.svelte b/web/src/lib/components/shared-components/navigation-bar/notification-panel.svelte new file mode 100644 index 0000000000..be9fcd2a44 --- /dev/null +++ b/web/src/lib/components/shared-components/navigation-bar/notification-panel.svelte @@ -0,0 +1,82 @@ + + +

+ +
+ {$t('notifications')} +
+ +
+
+ +
+ + {#if noUnreadNotifications} + + + {$t('no_notifications')} + + {:else} + + + {#each notificationManager.notifications as notification (notification.id)} +
+ markAsRead(id)} /> +
+ {/each} +
+
+ {/if} +
+
diff --git a/web/src/lib/components/shared-components/navigation-loading-bar.svelte b/web/src/lib/components/shared-components/navigation-loading-bar.svelte index bd5f15ae4e..afdb8ee967 100644 --- a/web/src/lib/components/shared-components/navigation-loading-bar.svelte +++ b/web/src/lib/components/shared-components/navigation-loading-bar.svelte @@ -26,7 +26,7 @@ {#if showing} -
+
{/if} diff --git a/web/src/lib/components/shared-components/notification/notification-card.svelte b/web/src/lib/components/shared-components/notification/notification-card.svelte index 5054c18695..30c8622bba 100644 --- a/web/src/lib/components/shared-components/notification/notification-card.svelte +++ b/web/src/lib/components/shared-components/notification/notification-card.svelte @@ -100,7 +100,7 @@ />
-

+

{#if isComponentNotification(notification)} {:else} @@ -109,7 +109,7 @@

{#if notification.button} -

+

@@ -145,7 +145,7 @@ type="button" in:scale={{ duration: 250, easing: quartInOut }} onclick={() => (showDetail = true)} - class="absolute -right-4 -top-4 flex h-10 w-10 place-content-center place-items-center rounded-full bg-immich-error p-5 text-xs text-gray-200" + class="absolute -end-4 -top-4 flex h-10 w-10 place-content-center place-items-center rounded-full bg-immich-error p-5 text-xs text-gray-200" > {$stats.errors.toLocaleString($locale)} diff --git a/web/src/lib/components/user-settings-page/app-settings.svelte b/web/src/lib/components/user-settings-page/app-settings.svelte index 63209ca289..f1d8e14787 100644 --- a/web/src/lib/components/user-settings-page/app-settings.svelte +++ b/web/src/lib/components/user-settings-page/app-settings.svelte @@ -1,11 +1,12 @@

-
+
diff --git a/web/src/lib/components/user-settings-page/user-profile-settings.svelte b/web/src/lib/components/user-settings-page/user-profile-settings.svelte index c36c36d7cc..90487f532f 100644 --- a/web/src/lib/components/user-settings-page/user-profile-settings.svelte +++ b/web/src/lib/components/user-settings-page/user-profile-settings.svelte @@ -42,7 +42,7 @@
-
+
{#if isServerProduct}
@@ -152,7 +152,7 @@ {/if} {:else}
diff --git a/web/src/lib/components/user-settings-page/user-usage-statistic.svelte b/web/src/lib/components/user-settings-page/user-usage-statistic.svelte index f7de1d8f64..ad77516d55 100644 --- a/web/src/lib/components/user-settings-page/user-usage-statistic.svelte +++ b/web/src/lib/components/user-settings-page/user-usage-statistic.svelte @@ -68,7 +68,7 @@

{$t('photos_and_videos')}

-
+
@@ -92,7 +92,7 @@

{$t('albums')}

-
+
diff --git a/web/src/lib/components/utilities-page/duplicates/duplicate-asset.svelte b/web/src/lib/components/utilities-page/duplicates/duplicate-asset.svelte index 97f44e3ec4..b8409cb0ef 100644 --- a/web/src/lib/components/utilities-page/duplicates/duplicate-asset.svelte +++ b/web/src/lib/components/utilities-page/duplicates/duplicate-asset.svelte @@ -44,14 +44,14 @@ {#if asset.isFavorite} -
+
{/if}
@@ -59,7 +59,7 @@
-
+
{#if isFromExternalLibrary}
{$t('external')} @@ -68,7 +68,7 @@ {#if asset.stack?.assetCount}
-
{asset.stack.assetCount}
+
{asset.stack.assetCount}
@@ -79,7 +79,7 @@
@@ -143,21 +132,11 @@
{#if trashCount === 0} - {:else} -
+ +
+ {#each assets as asset (asset.id)} + setAsset(asset)} + /> + {/each} +
{#if $showAssetViewer} diff --git a/web/src/lib/constants.ts b/web/src/lib/constants.ts index 2c21d04865..f5b044cd41 100644 --- a/web/src/lib/constants.ts +++ b/web/src/lib/constants.ts @@ -268,8 +268,8 @@ export const defaultLang = { name: 'English', code: 'en', loader: () => import(' export const langs = [ { name: 'Afrikaans', code: 'af', loader: () => import('$i18n/af.json') }, - { name: 'Arabic', code: 'ar', loader: () => import('$i18n/ar.json') }, - { name: 'Azerbaijani', code: 'az', loader: () => import('$i18n/az.json') }, + { name: 'Arabic', code: 'ar', loader: () => import('$i18n/ar.json'), rtl: true }, + { name: 'Azerbaijani', code: 'az', loader: () => import('$i18n/az.json'), rtl: true }, { name: 'Belarusian', code: 'be', loader: () => import('$i18n/be.json') }, { name: 'Bulgarian', code: 'bg', loader: () => import('$i18n/bg.json') }, { name: 'Bislama', code: 'bi', loader: () => import('$i18n/bi.json') }, @@ -284,12 +284,12 @@ export const langs = [ { name: 'Spanish', code: 'es', loader: () => import('$i18n/es.json') }, { name: 'Estonian', code: 'et', loader: () => import('$i18n/et.json') }, { name: 'Basque', code: 'eu', loader: () => import('$i18n/eu.json') }, - { name: 'Persian', code: 'fa', loader: () => import('$i18n/fa.json') }, + { name: 'Persian', code: 'fa', loader: () => import('$i18n/fa.json'), rtl: true }, { name: 'Finnish', code: 'fi', loader: () => import('$i18n/fi.json') }, { name: 'Filipino', code: 'fil', loader: () => import('$i18n/fil.json') }, { name: 'French', code: 'fr', loader: () => import('$i18n/fr.json') }, { name: 'Galician', code: 'gl', loader: () => import('$i18n/gl.json') }, - { name: 'Hebrew', code: 'he', loader: () => import('$i18n/he.json') }, + { name: 'Hebrew', code: 'he', loader: () => import('$i18n/he.json'), rtl: true }, { name: 'Hindi', code: 'hi', loader: () => import('$i18n/hi.json') }, { name: 'Croatian', code: 'hr', loader: () => import('$i18n/hr.json') }, { name: 'Hungarian', code: 'hu', loader: () => import('$i18n/hu.json') }, @@ -299,7 +299,7 @@ export const langs = [ { name: 'Japanese', code: 'ja', loader: () => import('$i18n/ja.json') }, { name: 'Georgian', code: 'ka', loader: () => import('$i18n/ka.json') }, { name: 'Kazakh', code: 'kk', loader: () => import('$i18n/kk.json') }, - { name: 'Kurdish (Northern)', code: 'kmr', loader: () => import('$i18n/kmr.json') }, + { name: 'Kurdish (Northern)', code: 'kmr', loader: () => import('$i18n/kmr.json'), rtl: true }, { name: 'Kannada', code: 'kn', loader: () => import('$i18n/kn.json') }, { name: 'Korean', code: 'ko', loader: () => import('$i18n/ko.json') }, { name: 'Luxembourgish', code: 'lb', loader: () => import('$i18n/lb.json') }, @@ -335,7 +335,7 @@ export const langs = [ { name: 'Thai', code: 'th', loader: () => import('$i18n/th.json') }, { name: 'Turkish', code: 'tr', loader: () => import('$i18n/tr.json') }, { name: 'Ukrainian', code: 'uk', loader: () => import('$i18n/uk.json') }, - { name: 'Urdu', code: 'ur', loader: () => import('$i18n/ur.json') }, + { name: 'Urdu', code: 'ur', loader: () => import('$i18n/ur.json'), rtl: true }, { name: 'Vietnamese', code: 'vi', loader: () => import('$i18n/vi.json') }, { name: 'Chinese (Traditional)', diff --git a/web/src/lib/managers/activity-manager.svelte.ts b/web/src/lib/managers/activity-manager.svelte.ts new file mode 100644 index 0000000000..a527778bb1 --- /dev/null +++ b/web/src/lib/managers/activity-manager.svelte.ts @@ -0,0 +1,113 @@ +import { user } from '$lib/stores/user.store'; +import { handlePromiseError } from '$lib/utils'; +import { + createActivity, + deleteActivity, + getActivities, + getActivityStatistics, + ReactionLevel, + ReactionType, + type ActivityCreateDto, + type ActivityResponseDto, +} from '@immich/sdk'; +import { get } from 'svelte/store'; + +class ActivityManager { + #albumId = $state(); + #assetId = $state(); + #activities = $state([]); + #commentCount = $state(0); + #isLiked = $state(null); + + get activities() { + return this.#activities; + } + + get commentCount() { + return this.#commentCount; + } + + get isLiked() { + return this.#isLiked; + } + + init(albumId: string, assetId?: string) { + this.#albumId = albumId; + this.#assetId = assetId; + } + + async addActivity(dto: ActivityCreateDto) { + if (this.#albumId === undefined) { + return; + } + + const activity = await createActivity({ activityCreateDto: dto }); + this.#activities = [...this.#activities, activity]; + + if (activity.type === ReactionType.Comment) { + this.#commentCount++; + } + + handlePromiseError(this.refreshActivities(this.#albumId, this.#assetId)); + return activity; + } + + async deleteActivity(activity: ActivityResponseDto, index?: number) { + if (!this.#albumId) { + return; + } + + if (activity.type === ReactionType.Comment) { + this.#commentCount--; + } + + this.#activities = index + ? this.#activities.splice(index, 1) + : this.#activities.filter(({ id }) => id !== activity.id); + + await deleteActivity({ id: activity.id }); + handlePromiseError(this.refreshActivities(this.#albumId, this.#assetId)); + } + + async toggleLike() { + if (!this.#albumId) { + return; + } + + if (this.#isLiked) { + await this.deleteActivity(this.#isLiked); + this.#isLiked = null; + } else { + this.#isLiked = (await this.addActivity({ + albumId: this.#albumId, + assetId: this.#assetId, + type: ReactionType.Like, + }))!; + } + } + + async refreshActivities(albumId: string, assetId?: string) { + this.#activities = await getActivities({ albumId, assetId }); + + const [liked] = await getActivities({ + albumId, + assetId, + userId: get(user).id, + $type: ReactionType.Like, + level: assetId ? undefined : ReactionLevel.Album, + }); + this.#isLiked = liked ?? null; + + const { comments } = await getActivityStatistics({ albumId, assetId }); + this.#commentCount = comments; + } + + reset() { + this.#albumId = undefined; + this.#assetId = undefined; + this.#activities = []; + this.#commentCount = 0; + } +} + +export const activityManager = new ActivityManager(); diff --git a/web/src/lib/managers/auth-manager.svelte.ts b/web/src/lib/managers/auth-manager.svelte.ts new file mode 100644 index 0000000000..9e8e30b773 --- /dev/null +++ b/web/src/lib/managers/auth-manager.svelte.ts @@ -0,0 +1,37 @@ +import { goto } from '$app/navigation'; +import { page } from '$app/state'; +import { AppRoute } from '$lib/constants'; +import { eventManager } from '$lib/managers/event-manager.svelte'; +import { isSharedLinkRoute } from '$lib/utils/navigation'; +import { logout } from '@immich/sdk'; + +class AuthManager { + key = $derived(isSharedLinkRoute(page.route?.id) ? page.params.key : undefined); + + async logout() { + let redirectUri; + + try { + const response = await logout(); + if (response.redirectUri) { + redirectUri = response.redirectUri; + } + } catch (error) { + console.log('Error logging out:', error); + } + + redirectUri = redirectUri ?? AppRoute.AUTH_LOGIN; + + try { + if (redirectUri.startsWith('/')) { + await goto(redirectUri); + } else { + globalThis.location.href = redirectUri; + } + } finally { + eventManager.emit('auth.logout'); + } + } +} + +export const authManager = new AuthManager(); diff --git a/web/src/lib/stores/download-store.svelte.ts b/web/src/lib/managers/download-manager.svelte.ts similarity index 74% rename from web/src/lib/stores/download-store.svelte.ts rename to web/src/lib/managers/download-manager.svelte.ts index 8c03671e73..107f80b8dc 100644 --- a/web/src/lib/stores/download-store.svelte.ts +++ b/web/src/lib/managers/download-manager.svelte.ts @@ -5,7 +5,7 @@ export interface DownloadProgress { abort: AbortController | null; } -class DownloadStore { +class DownloadManager { assets = $state>({}); isDownloading = $derived(Object.keys(this.assets).length > 0); @@ -42,10 +42,4 @@ class DownloadStore { } } -export const downloadStore = new DownloadStore(); - -export const downloadManager = { - add: (key: string, total: number, abort?: AbortController) => downloadStore.add(key, total, abort), - clear: (key: string) => downloadStore.clear(key), - update: (key: string, progress: number, total?: number) => downloadStore.update(key, progress, total), -}; +export const downloadManager = new DownloadManager(); diff --git a/web/src/lib/managers/event-manager.svelte.ts b/web/src/lib/managers/event-manager.svelte.ts new file mode 100644 index 0000000000..f8e39411cf --- /dev/null +++ b/web/src/lib/managers/event-manager.svelte.ts @@ -0,0 +1,61 @@ +import type { ThemeSetting } from '$lib/managers/theme-manager.svelte'; +import type { LoginResponseDto } from '@immich/sdk'; + +type Listener, K extends keyof EventMap> = (...params: EventMap[K]) => void; + +class EventManager> { + private listeners: { + [K in keyof EventMap]?: { + listener: Listener; + once?: boolean; + }[]; + } = {}; + + on(key: T, listener: (...params: EventMap[T]) => void) { + return this.addListener(key, listener, false); + } + + once(key: T, listener: (...params: EventMap[T]) => void) { + return this.addListener(key, listener, true); + } + + off(key: K, listener: Listener) { + if (this.listeners[key]) { + this.listeners[key] = this.listeners[key].filter((item) => item.listener !== listener); + } + + return this; + } + + emit(key: T, ...params: EventMap[T]) { + if (!this.listeners[key]) { + return; + } + + for (const { listener } of this.listeners[key]) { + listener(...params); + } + + // remove one time listeners + this.listeners[key] = this.listeners[key].filter((item) => !item.once); + } + + private addListener(key: T, listener: (...params: EventMap[T]) => void, once: boolean) { + if (!this.listeners[key]) { + this.listeners[key] = []; + } + + this.listeners[key].push({ listener, once }); + + return this; + } +} + +export const eventManager = new EventManager<{ + 'app.init': []; + 'user.login': []; + 'auth.login': [LoginResponseDto]; + 'auth.logout': []; + 'language.change': [{ name: string; code: string; rtl?: boolean }]; + 'theme.change': [ThemeSetting]; +}>(); diff --git a/web/src/lib/managers/language-manager.svelte.ts b/web/src/lib/managers/language-manager.svelte.ts new file mode 100644 index 0000000000..5acae27aa3 --- /dev/null +++ b/web/src/lib/managers/language-manager.svelte.ts @@ -0,0 +1,26 @@ +import { langs } from '$lib/constants'; +import { eventManager } from '$lib/managers/event-manager.svelte'; +import { lang } from '$lib/stores/preferences.store'; + +class LanguageManager { + constructor() { + eventManager.on('app.init', () => lang.subscribe((lang) => this.setLanguage(lang))); + } + + rtl = $state(false); + + setLanguage(code: string) { + const item = langs.find((item) => item.code === code); + if (!item) { + return; + } + + this.rtl = item.rtl ?? false; + + document.body.setAttribute('dir', item.rtl ? 'rtl' : 'ltr'); + + eventManager.emit('language.change', item); + } +} + +export const languageManager = new LanguageManager(); diff --git a/web/src/lib/managers/theme-manager.svelte.ts b/web/src/lib/managers/theme-manager.svelte.ts new file mode 100644 index 0000000000..a20e5f9a98 --- /dev/null +++ b/web/src/lib/managers/theme-manager.svelte.ts @@ -0,0 +1,78 @@ +import { browser } from '$app/environment'; +import { Theme } from '$lib/constants'; +import { eventManager } from '$lib/managers/event-manager.svelte'; +import { PersistedLocalStorage } from '$lib/utils/persisted'; + +export interface ThemeSetting { + value: Theme; + system: boolean; +} + +const getDefaultTheme = () => { + if (!browser) { + return Theme.DARK; + } + + return globalThis.matchMedia('(prefers-color-scheme: dark)').matches ? Theme.DARK : Theme.LIGHT; +}; + +class ThemeManager { + #theme = new PersistedLocalStorage( + 'color-theme', + { value: getDefaultTheme(), system: false }, + { + valid: (value): value is ThemeSetting => { + return Object.values(Theme).includes((value as ThemeSetting)?.value); + }, + }, + ); + + get theme() { + return this.#theme.current; + } + + value = $derived(this.theme.value); + + isDark = $derived(this.value === Theme.DARK); + + constructor() { + eventManager.on('app.init', () => this.#onAppInit()); + } + + setSystem(system: boolean) { + this.#update(system ? 'system' : getDefaultTheme()); + } + + setTheme(theme: Theme) { + this.#update(theme); + } + + toggleTheme() { + this.#update(this.value === Theme.DARK ? Theme.LIGHT : Theme.DARK); + } + + #onAppInit() { + globalThis.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => { + if (this.theme.system) { + this.#update('system'); + } + }); + } + + #update(value: Theme | 'system') { + const theme: ThemeSetting = + value === 'system' ? { system: true, value: getDefaultTheme() } : { system: false, value }; + + if (theme.value === Theme.LIGHT) { + document.documentElement.classList.remove('dark'); + } else { + document.documentElement.classList.add('dark'); + } + + this.#theme.current = theme; + + eventManager.emit('theme.change', theme); + } +} + +export const themeManager = new ThemeManager(); diff --git a/web/src/lib/stores/activity.store.ts b/web/src/lib/stores/activity.store.ts deleted file mode 100644 index 897f835063..0000000000 --- a/web/src/lib/stores/activity.store.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { writable } from 'svelte/store'; - -export const numberOfComments = writable(0); - -export const setNumberOfComments = (number: number) => { - numberOfComments.set(number); -}; - -export const updateNumberOfComments = (addOrRemove: 1 | -1) => { - numberOfComments.update((n) => n + addOrRemove); -}; diff --git a/web/src/lib/stores/asset-interaction.svelte.ts b/web/src/lib/stores/asset-interaction.svelte.ts index 39bf9968c9..bcf37c6e43 100644 --- a/web/src/lib/stores/asset-interaction.svelte.ts +++ b/web/src/lib/stores/asset-interaction.svelte.ts @@ -14,7 +14,6 @@ export class AssetInteraction { return this.assetSelectionCandidates.some((asset) => asset.id === assetId); } assetSelectionStart = $state(null); - focussedAssetId = $state(null); selectionActive = $derived(this.selectedAssets.length > 0); private user = fromStore(user); @@ -73,8 +72,4 @@ export class AssetInteraction { this.assetSelectionCandidates = []; this.assetSelectionStart = null; } - - isFocussedAsset(assetId: string) { - return this.focussedAssetId === assetId; - } } diff --git a/web/src/lib/stores/asset-viewing.store.ts b/web/src/lib/stores/asset-viewing.store.ts index 689556b522..98b9e99aa2 100644 --- a/web/src/lib/stores/asset-viewing.store.ts +++ b/web/src/lib/stores/asset-viewing.store.ts @@ -1,4 +1,4 @@ -import { getKey } from '$lib/utils'; +import { authManager } from '$lib/managers/auth-manager.svelte'; import { type AssetGridRouteSearchParams } from '$lib/utils/navigation'; import { getAssetInfo, type AssetResponseDto } from '@immich/sdk'; import { readonly, writable } from 'svelte/store'; @@ -16,7 +16,7 @@ function createAssetViewingStore() { }; const setAssetId = async (id: string): Promise => { - const asset = await getAssetInfo({ id, key: getKey() }); + const asset = await getAssetInfo({ id, key: authManager.key }); setAsset(asset); return asset; }; diff --git a/web/src/lib/stores/assets-store.spec.ts b/web/src/lib/stores/assets-store.spec.ts index 0685103a1b..3d0292bde8 100644 --- a/web/src/lib/stores/assets-store.spec.ts +++ b/web/src/lib/stores/assets-store.spec.ts @@ -48,15 +48,15 @@ describe('AssetStore', () => { expect(plainBuckets).toEqual( expect.arrayContaining([ - expect.objectContaining({ bucketDate: '2024-03-01T00:00:00.000Z', bucketHeight: 304 }), - expect.objectContaining({ bucketDate: '2024-02-01T00:00:00.000Z', bucketHeight: 4515.333_333_333_333 }), + expect.objectContaining({ bucketDate: '2024-03-01T00:00:00.000Z', bucketHeight: 303 }), + expect.objectContaining({ bucketDate: '2024-02-01T00:00:00.000Z', bucketHeight: 4514.333_333_333_333 }), expect.objectContaining({ bucketDate: '2024-01-01T00:00:00.000Z', bucketHeight: 286 }), ]), ); }); it('calculates timeline height', () => { - expect(assetStore.timelineHeight).toBe(5105.333_333_333_333); + expect(assetStore.timelineHeight).toBe(5103.333_333_333_333); }); }); diff --git a/web/src/lib/stores/assets-store.svelte.ts b/web/src/lib/stores/assets-store.svelte.ts index f523406a31..b4b4a4ade2 100644 --- a/web/src/lib/stores/assets-store.svelte.ts +++ b/web/src/lib/stores/assets-store.svelte.ts @@ -1,5 +1,4 @@ import { locale } from '$lib/stores/preferences.store'; -import { getKey } from '$lib/utils'; import { CancellableTask } from '$lib/utils/cancellable-task'; import { getJustifiedLayoutFromAssets, @@ -21,6 +20,7 @@ import { clamp, debounce, isEqual, throttle } from 'lodash-es'; import { DateTime } from 'luxon'; import { t } from 'svelte-i18n'; +import { authManager } from '$lib/managers/auth-manager.svelte'; import { SvelteSet } from 'svelte/reactivity'; import { get, writable, type Unsubscriber } from 'svelte/store'; import { handleError } from '../utils/handle-error'; @@ -35,9 +35,7 @@ export type AssetStoreOptions = Omit & { timelineAlbumId?: string; deferInit?: boolean; }; -export type AssetStoreLayoutOptions = { - rowHeight: number; -}; + // eslint-disable-next-line @typescript-eslint/no-explicit-any function updateObject(target: any, source: any): boolean { if (!target) { @@ -110,7 +108,6 @@ export class AssetDateGroup { readonly date: DateTime; readonly dayOfMonth: number; intersetingAssets: IntersectingAsset[] = $state([]); - dodo: IntersectingAsset[] = $state([]); height = $state(0); width = $state(0); @@ -121,6 +118,7 @@ export class AssetDateGroup { left: number = $state(0); row = $state(0); col = $state(0); + deferredLayout = false; constructor(bucket: AssetBucket, index: number, date: DateTime, dayOfMonth: number) { this.index = index; @@ -195,6 +193,10 @@ export class AssetDateGroup { } layout(options: CommonLayoutOptions) { + if (!this.bucket.intersecting) { + this.deferredLayout = true; + return; + } const assets = this.intersetingAssets.map((intersetingAsset) => intersetingAsset.asset!); const geometry = getJustifiedLayoutFromAssets(assets, options); this.width = geometry.containerWidth; @@ -547,6 +549,11 @@ export type LiteBucket = { bucketDateFormattted: string; }; +type AssetStoreLayoutOptions = { + rowHeight?: number; + headerHeight?: number; + gap?: number; +}; export class AssetStore { // --- public ---- isInitialized = $state(false); @@ -596,7 +603,7 @@ export class AssetStore { #unsubscribers: Unsubscriber[] = []; #rowHeight = $state(235); - #headerHeight = $state(49); + #headerHeight = $state(48); #gap = $state(12); #options: AssetStoreOptions = AssetStore.#INIT_OPTIONS; @@ -608,36 +615,46 @@ export class AssetStore { constructor() {} - set headerHeight(value) { + setLayoutOptions({ headerHeight = 48, rowHeight = 235, gap = 12 }: AssetStoreLayoutOptions) { + let changed = false; + changed ||= this.#setHeaderHeight(headerHeight); + changed ||= this.#setGap(gap); + changed ||= this.#setRowHeight(rowHeight); + if (changed) { + this.refreshLayout(); + } + } + + #setHeaderHeight(value: number) { if (this.#headerHeight == value) { - return; + return false; } this.#headerHeight = value; - this.refreshLayout(); + return true; } get headerHeight() { return this.#headerHeight; } - set gap(value) { + #setGap(value: number) { if (this.#gap == value) { - return; + return false; } this.#gap = value; - this.refreshLayout(); + return true; } get gap() { return this.#gap; } - set rowHeight(value) { + #setRowHeight(value: number) { if (this.#rowHeight == value) { - return; + return false; } this.#rowHeight = value; - this.refreshLayout(); + return true; } get rowHeight() { @@ -815,6 +832,15 @@ export class AssetStore { } bucket.intersecting = actuallyIntersecting || preIntersecting; bucket.actuallyIntersecting = actuallyIntersecting; + if (preIntersecting || actuallyIntersecting) { + const hasDeferred = bucket.dateGroups.some((group) => group.deferredLayout); + if (hasDeferred) { + this.#updateGeometry(bucket, true); + for (const group of bucket.dateGroups) { + group.deferredLayout = false; + } + } + } } #processPendingChanges = throttle(() => { @@ -839,7 +865,7 @@ export class AssetStore { const timebuckets = await getTimeBuckets({ ...this.#options, size: TimeBucketSize.Month, - key: getKey(), + key: authManager.key, }); this.buckets = timebuckets.map((bucket) => { @@ -1047,7 +1073,7 @@ export class AssetStore { ...this.#options, timeBucket: bucketDate, size: TimeBucketSize.Month, - key: getKey(), + key: authManager.key, }, { signal }, ); @@ -1058,7 +1084,7 @@ export class AssetStore { albumId: this.#options.timelineAlbumId, timeBucket: bucketDate, size: TimeBucketSize.Month, - key: getKey(), + key: authManager.key, }, { signal }, ); diff --git a/web/src/lib/stores/folders.svelte.ts b/web/src/lib/stores/folders.svelte.ts index fb59687a38..6f3eb8b66a 100644 --- a/web/src/lib/stores/folders.svelte.ts +++ b/web/src/lib/stores/folders.svelte.ts @@ -1,3 +1,4 @@ +import { eventManager } from '$lib/managers/event-manager.svelte'; import { getAssetsByOriginalPath, getUniqueOriginalPaths, @@ -16,6 +17,10 @@ class FoldersStore { uniquePaths = $state([]); assets = $state({}); + constructor() { + eventManager.on('auth.logout', () => this.clearCache()); + } + async fetchUniquePaths() { if (this.initialized) { return; diff --git a/web/src/lib/stores/memory.store.svelte.ts b/web/src/lib/stores/memory.store.svelte.ts index 7173b43d06..9ef3de4328 100644 --- a/web/src/lib/stores/memory.store.svelte.ts +++ b/web/src/lib/stores/memory.store.svelte.ts @@ -1,3 +1,4 @@ +import { eventManager } from '$lib/managers/event-manager.svelte'; import { asLocalTimeISO } from '$lib/utils/date-time'; import { type AssetResponseDto, @@ -24,6 +25,10 @@ export type MemoryAsset = MemoryIndex & { }; class MemoryStoreSvelte { + constructor() { + eventManager.on('auth.logout', () => this.clearCache()); + } + memories = $state([]); private initialized = false; private memoryAssets = $derived.by(() => { diff --git a/web/src/lib/stores/notification-manager.svelte.ts b/web/src/lib/stores/notification-manager.svelte.ts new file mode 100644 index 0000000000..3eba15deed --- /dev/null +++ b/web/src/lib/stores/notification-manager.svelte.ts @@ -0,0 +1,41 @@ +import { eventManager } from '$lib/managers/event-manager.svelte'; +import { handlePromiseError } from '$lib/utils'; +import { handleError } from '$lib/utils/handle-error'; +import { getNotifications, updateNotification, updateNotifications, type NotificationDto } from '@immich/sdk'; +import { t } from 'svelte-i18n'; +import { get } from 'svelte/store'; + +class NotificationStore { + notifications = $state([]); + + constructor() { + eventManager.on('auth.login', () => handlePromiseError(this.refresh())); + eventManager.on('auth.logout', () => this.clear()); + } + + async refresh() { + try { + this.notifications = await getNotifications({ unread: true }); + } catch (error) { + const translate = get(t); + handleError(error, translate('errors.failed_to_load_notifications')); + } + } + + markAsRead = async (id: string) => { + this.notifications = this.notifications.filter((notification) => notification.id !== id); + await updateNotification({ id, notificationUpdateDto: { readAt: new Date().toISOString() } }); + }; + + markAllAsRead = async () => { + const ids = this.notifications.map(({ id }) => id); + this.notifications = []; + await updateNotifications({ notificationUpdateAllDto: { ids, readAt: new Date().toISOString() } }); + }; + + clear = () => { + this.notifications = []; + }; +} + +export const notificationManager = new NotificationStore(); diff --git a/web/src/lib/stores/preferences.store.ts b/web/src/lib/stores/preferences.store.ts index e268e8817d..e7f38eb6d0 100644 --- a/web/src/lib/stores/preferences.store.ts +++ b/web/src/lib/stores/preferences.store.ts @@ -2,39 +2,12 @@ import { browser } from '$app/environment'; import { Theme, defaultLang } from '$lib/constants'; import { getPreferredLocale } from '$lib/utils/i18n'; import { persisted } from 'svelte-persisted-store'; -import { get } from 'svelte/store'; export interface ThemeSetting { value: Theme; system: boolean; } -export const handleToggleTheme = () => { - const theme = get(colorTheme); - theme.value = theme.value === Theme.DARK ? Theme.LIGHT : Theme.DARK; - colorTheme.set(theme); -}; - -const initTheme = (): ThemeSetting => { - if (browser && globalThis.matchMedia && !globalThis.matchMedia('(prefers-color-scheme: dark)').matches) { - return { value: Theme.LIGHT, system: false }; - } - return { value: Theme.DARK, system: false }; -}; - -const initialTheme = initTheme(); - -// The 'color-theme' key is also used by app.html to prevent FOUC on page load. -export const colorTheme = persisted('color-theme', initialTheme, { - serializer: { - parse: (text: string): ThemeSetting => { - const parsedText: ThemeSetting = JSON.parse(text); - return Object.values(Theme).includes(parsedText.value) ? parsedText : initTheme(); - }, - stringify: (object) => JSON.stringify(object), - }, -}); - // Locale to use for formatting dates, numbers, etc. export const locale = persisted('locale', undefined, { serializer: { diff --git a/web/src/lib/stores/search.svelte.ts b/web/src/lib/stores/search.svelte.ts index 7d012922ca..32f2741955 100644 --- a/web/src/lib/stores/search.svelte.ts +++ b/web/src/lib/stores/search.svelte.ts @@ -1,7 +1,13 @@ +import { eventManager } from '$lib/managers/event-manager.svelte'; + class SearchStore { savedSearchTerms = $state([]); isSearchEnabled = $state(false); + constructor() { + eventManager.on('auth.logout', () => this.clearCache()); + } + clearCache() { this.savedSearchTerms = []; this.isSearchEnabled = false; diff --git a/web/src/lib/stores/user.store.ts b/web/src/lib/stores/user.store.ts index 5bffc08b80..0790788278 100644 --- a/web/src/lib/stores/user.store.ts +++ b/web/src/lib/stores/user.store.ts @@ -1,3 +1,4 @@ +import { eventManager } from '$lib/managers/event-manager.svelte'; import { purchaseStore } from '$lib/stores/purchase.store'; import { type UserAdminResponseDto, type UserPreferencesResponseDto } from '@immich/sdk'; import { writable } from 'svelte/store'; @@ -14,3 +15,5 @@ export const resetSavedUser = () => { preferences.set(undefined as unknown as UserPreferencesResponseDto); purchaseStore.setPurchaseStatus(false); }; + +eventManager.on('auth.logout', () => resetSavedUser()); diff --git a/web/src/lib/stores/user.svelte.ts b/web/src/lib/stores/user.svelte.ts index 71b2cdd847..94d73efb9c 100644 --- a/web/src/lib/stores/user.svelte.ts +++ b/web/src/lib/stores/user.svelte.ts @@ -1,3 +1,4 @@ +import { eventManager } from '$lib/managers/event-manager.svelte'; import type { AlbumResponseDto, ServerAboutResponseDto, @@ -19,8 +20,10 @@ const defaultUserInteraction: UserInteractions = { serverInfo: undefined, }; -export const resetUserInteraction = () => { +export const userInteraction = $state(defaultUserInteraction); + +const reset = () => { Object.assign(userInteraction, defaultUserInteraction); }; -export const userInteraction = $state(defaultUserInteraction); +eventManager.on('auth.logout', () => reset()); diff --git a/web/src/lib/stores/websocket.ts b/web/src/lib/stores/websocket.ts index d398ca52a9..6e896e8000 100644 --- a/web/src/lib/stores/websocket.ts +++ b/web/src/lib/stores/websocket.ts @@ -1,7 +1,7 @@ -import { AppRoute } from '$lib/constants'; -import { handleLogout } from '$lib/utils/auth'; +import { authManager } from '$lib/managers/auth-manager.svelte'; +import { notificationManager } from '$lib/stores/notification-manager.svelte'; import { createEventEmitter } from '$lib/utils/eventemitter'; -import type { AssetResponseDto, ServerVersionResponseDto } from '@immich/sdk'; +import { type AssetResponseDto, type NotificationDto, type ServerVersionResponseDto } from '@immich/sdk'; import { io, type Socket } from 'socket.io-client'; import { get, writable } from 'svelte/store'; import { user } from './user.store'; @@ -27,6 +27,7 @@ export interface Events { on_config_update: () => void; on_new_release: (newRelase: ReleaseEvent) => void; on_session_delete: (sessionId: string) => void; + on_notification: (notification: NotificationDto) => void; } const websocket: Socket = io({ @@ -50,7 +51,8 @@ websocket .on('disconnect', () => websocketStore.connected.set(false)) .on('on_server_version', (serverVersion) => websocketStore.serverVersion.set(serverVersion)) .on('on_new_release', (releaseVersion) => websocketStore.release.set(releaseVersion)) - .on('on_session_delete', () => handleLogout(AppRoute.AUTH_LOGIN)) + .on('on_session_delete', () => authManager.logout()) + .on('on_notification', () => notificationManager.refresh()) .on('connect_error', (e) => console.log('Websocket Connect Error', e)); export const openWebsocketConnection = () => { diff --git a/web/src/lib/utils.ts b/web/src/lib/utils.ts index 7d542a940a..b7466b5812 100644 --- a/web/src/lib/utils.ts +++ b/web/src/lib/utils.ts @@ -1,5 +1,6 @@ import { NotificationType, notificationController } from '$lib/components/shared-components/notification/notification'; import { defaultLang, langs, locales } from '$lib/constants'; +import { authManager } from '$lib/managers/auth-manager.svelte'; import { lang } from '$lib/stores/preferences.store'; import { handleError } from '$lib/utils/handle-error'; import { @@ -155,18 +156,11 @@ export const getJobName = derived(t, ($t) => { }; }); -let _key: string | undefined; let _sharedLink: SharedLinkResponseDto | undefined; -export const setKey = (key?: string) => (_key = key); -export const getKey = (): string | undefined => _key; export const setSharedLink = (sharedLink: SharedLinkResponseDto) => (_sharedLink = sharedLink); export const getSharedLink = (): SharedLinkResponseDto | undefined => _sharedLink; -export const isSharedLink = () => { - return !!_key; -}; - const createUrl = (path: string, parameters?: Record) => { const searchParameters = new URLSearchParams(); for (const key in parameters) { @@ -189,7 +183,7 @@ export const getAssetOriginalUrl = (options: string | AssetUrlOptions) => { options = { id: options }; } const { id, cacheKey } = options; - return createUrl(getAssetOriginalPath(id), { key: getKey(), c: cacheKey }); + return createUrl(getAssetOriginalPath(id), { key: authManager.key, c: cacheKey }); }; export const getAssetThumbnailUrl = (options: string | (AssetUrlOptions & { size?: AssetMediaSize })) => { @@ -197,7 +191,7 @@ export const getAssetThumbnailUrl = (options: string | (AssetUrlOptions & { size options = { id: options }; } const { id, size, cacheKey } = options; - return createUrl(getAssetThumbnailPath(id), { size, key: getKey(), c: cacheKey }); + return createUrl(getAssetThumbnailPath(id), { size, key: authManager.key, c: cacheKey }); }; export const getAssetPlaybackUrl = (options: string | AssetUrlOptions) => { @@ -205,7 +199,7 @@ export const getAssetPlaybackUrl = (options: string | AssetUrlOptions) => { options = { id: options }; } const { id, cacheKey } = options; - return createUrl(getAssetPlaybackPath(id), { key: getKey(), c: cacheKey }); + return createUrl(getAssetPlaybackPath(id), { key: authManager.key, c: cacheKey }); }; export const getProfileImageUrl = (user: UserResponseDto) => diff --git a/web/src/lib/utils/album-utils.ts b/web/src/lib/utils/album-utils.ts index 74a2e3c5e9..a5b830774c 100644 --- a/web/src/lib/utils/album-utils.ts +++ b/web/src/lib/utils/album-utils.ts @@ -59,7 +59,7 @@ export const sortOptionsMetadata: AlbumSortOptionMetadata[] = [ { id: AlbumSortBy.Title, defaultOrder: SortOrder.Asc, - columnStyle: 'text-left w-8/12 sm:w-4/12 md:w-4/12 md:w-4/12 xl:w-[30%] 2xl:w-[40%]', + columnStyle: 'text-start w-8/12 sm:w-4/12 md:w-4/12 xl:w-[30%] 2xl:w-[40%]', }, { id: AlbumSortBy.ItemCount, diff --git a/web/src/lib/utils/asset-utils.ts b/web/src/lib/utils/asset-utils.ts index bd3cb416b5..254b90f08d 100644 --- a/web/src/lib/utils/asset-utils.ts +++ b/web/src/lib/utils/asset-utils.ts @@ -3,11 +3,12 @@ import FormatBoldMessage from '$lib/components/i18n/format-bold-message.svelte'; import type { InterpolationValues } from '$lib/components/i18n/format-message'; import { NotificationType, notificationController } from '$lib/components/shared-components/notification/notification'; import { AppRoute } from '$lib/constants'; +import { authManager } from '$lib/managers/auth-manager.svelte'; +import { downloadManager } from '$lib/managers/download-manager.svelte'; import type { AssetInteraction } from '$lib/stores/asset-interaction.svelte'; import { assetsSnapshot, isSelectingAllAssets, type AssetStore } from '$lib/stores/assets-store.svelte'; -import { downloadManager } from '$lib/stores/download-store.svelte'; import { preferences } from '$lib/stores/user.store'; -import { downloadRequest, getKey, withError } from '$lib/utils'; +import { downloadRequest, withError } from '$lib/utils'; import { createAlbum } from '$lib/utils/album-utils'; import { getByteUnitString } from '$lib/utils/byte-units'; import { getFormatter } from '$lib/utils/i18n'; @@ -44,7 +45,7 @@ export const addAssetsToAlbum = async (albumId: string, assetIds: string[], show bulkIdsDto: { ids: assetIds, }, - key: getKey(), + key: authManager.key, }); const count = result.filter(({ success }) => success).length; const $t = get(t); @@ -178,7 +179,7 @@ export const downloadArchive = async (fileName: string, options: Omit(preferences); const dto = { ...options, archiveSize: $preferences?.download.archiveSize }; - const [error, downloadInfo] = await withError(() => getDownloadInfo({ downloadInfoDto: dto, key: getKey() })); + const [error, downloadInfo] = await withError(() => getDownloadInfo({ downloadInfoDto: dto, key: authManager.key })); if (error) { const $t = get(t); handleError(error, $t('errors.unable_to_download_files')); @@ -193,7 +194,7 @@ export const downloadArchive = async (fileName: string, options: Omit 1 ? `+${index + 1}` : ''; const archiveName = fileName.replace('.zip', `${suffix}-${DateTime.now().toFormat('yyyyLLdd_HHmmss')}.zip`); - const key = getKey(); + const key = authManager.key; let downloadKey = `${archiveName} `; if (downloadInfo.archives.length > 1) { @@ -240,7 +241,7 @@ export const downloadFile = async (asset: AssetResponseDto) => { }; if (asset.livePhotoVideoId) { - const motionAsset = await getAssetInfo({ id: asset.livePhotoVideoId, key: getKey() }); + const motionAsset = await getAssetInfo({ id: asset.livePhotoVideoId, key: authManager.key }); if (!isAndroidMotionVideo(motionAsset) || get(preferences)?.download.includeEmbeddedVideos) { assets.push({ filename: motionAsset.originalFileName, @@ -252,7 +253,7 @@ export const downloadFile = async (asset: AssetResponseDto) => { for (const { filename, id } of assets) { try { - const key = getKey(); + const key = authManager.key; notificationController.show({ type: NotificationType.Info, diff --git a/web/src/lib/utils/auth.ts b/web/src/lib/utils/auth.ts index 22b92dd988..9b78c345e2 100644 --- a/web/src/lib/utils/auth.ts +++ b/web/src/lib/utils/auth.ts @@ -1,11 +1,7 @@ import { browser } from '$app/environment'; -import { goto } from '$app/navigation'; -import { foldersStore } from '$lib/stores/folders.svelte'; -import { memoryStore } from '$lib/stores/memory.store.svelte'; import { purchaseStore } from '$lib/stores/purchase.store'; -import { searchStore } from '$lib/stores/search.svelte'; -import { preferences as preferences$, resetSavedUser, user as user$ } from '$lib/stores/user.store'; -import { resetUserInteraction, userInteraction } from '$lib/stores/user.svelte'; +import { preferences as preferences$, user as user$ } from '$lib/stores/user.store'; +import { userInteraction } from '$lib/stores/user.svelte'; import { getAboutInfo, getMyPreferences, getMyUser, getStorage } from '@immich/sdk'; import { redirect } from '@sveltejs/kit'; import { DateTime } from 'luxon'; @@ -91,19 +87,3 @@ export const getAccountAge = (): number => { return Number(accountAge); }; - -export const handleLogout = async (redirectUri: string) => { - try { - if (redirectUri.startsWith('/')) { - await goto(redirectUri); - } else { - globalThis.location.href = redirectUri; - } - } finally { - resetSavedUser(); - resetUserInteraction(); - foldersStore.clearCache(); - memoryStore.clearCache(); - searchStore.clearCache(); - } -}; diff --git a/web/src/lib/utils/byte-units.ts b/web/src/lib/utils/byte-units.ts index dae44009e2..218e22f671 100644 --- a/web/src/lib/utils/byte-units.ts +++ b/web/src/lib/utils/byte-units.ts @@ -34,6 +34,7 @@ export function getBytesWithUnit(bytes: number, maxPrecision = 1): [number, Byte * * de: `1,5 KiB` * * @param bytes number of bytes + * @param locale locale to use, default is `navigator.language` * @param maxPrecision maximum number of decimal places, default is `1` * @returns localized bytes with unit as string */ diff --git a/web/src/lib/utils/file-uploader.ts b/web/src/lib/utils/file-uploader.ts index 04d4d78810..db43e92f94 100644 --- a/web/src/lib/utils/file-uploader.ts +++ b/web/src/lib/utils/file-uploader.ts @@ -1,6 +1,7 @@ +import { authManager } from '$lib/managers/auth-manager.svelte'; import { UploadState } from '$lib/models/upload-asset'; import { uploadAssetsStore } from '$lib/stores/upload'; -import { getKey, uploadRequest } from '$lib/utils'; +import { uploadRequest } from '$lib/utils'; import { addAssetsToAlbum } from '$lib/utils/asset-utils'; import { ExecutorQueue } from '$lib/utils/executor-queue'; import { @@ -134,7 +135,7 @@ async function fileUploader( } let responseData: { id: string; status: AssetMediaStatus; isTrashed?: boolean } | undefined; - const key = getKey(); + const key = authManager.key; if (crypto?.subtle?.digest && !key) { uploadAssetsStore.updateItem(deviceAssetId, { message: $t('asset_hashing') }); await tick(); diff --git a/web/src/lib/utils/focus-util.ts b/web/src/lib/utils/focus-util.ts index 8ad774f7ac..c95ed3f31d 100644 --- a/web/src/lib/utils/focus-util.ts +++ b/web/src/lib/utils/focus-util.ts @@ -1,4 +1,39 @@ -const selectors = - 'button:not([disabled], .hidden), [href]:not(.hidden), input:not([disabled], .hidden), select:not([disabled], .hidden), textarea:not([disabled], .hidden), [tabindex]:not([tabindex="-1"], .hidden)'; +import { focusable, isTabbable, tabbable, type CheckOptions, type TabbableOptions } from 'tabbable'; -export const getFocusable = (container: ParentNode) => [...container.querySelectorAll(selectors)]; +type TabbableOpts = TabbableOptions & CheckOptions; +let defaultOpts: TabbableOpts = { + includeContainer: false, +}; + +export const setDefaultTabbleOptions = (options: TabbableOpts) => { + defaultOpts = options; +}; + +export const getTabbable = (container: Element, includeContainer: boolean = false) => + tabbable(container, { ...defaultOpts, includeContainer }); + +export const focusNext = (selector: (element: HTMLElement | SVGElement) => boolean, forwardDirection: boolean) => { + const focusElements = focusable(document.body, { includeContainer: true }); + const current = document.activeElement as HTMLElement; + const index = focusElements.indexOf(current); + if (index === -1) { + for (const element of focusElements) { + if (selector(element)) { + element.focus(); + return; + } + } + focusElements[0].focus(); + return; + } + const totalElements = focusElements.length; + let i = index; + do { + i = (i + (forwardDirection ? 1 : -1) + totalElements) % totalElements; + const next = focusElements[i]; + if (isTabbable(next) && selector(next)) { + next.focus(); + break; + } + } while (i !== index); +}; diff --git a/web/src/lib/utils/persisted.ts b/web/src/lib/utils/persisted.ts new file mode 100644 index 0000000000..73eb4de5db --- /dev/null +++ b/web/src/lib/utils/persisted.ts @@ -0,0 +1,81 @@ +import { browser } from '$app/environment'; +import { createSubscriber } from 'svelte/reactivity'; + +type PersistedBaseOptions = { + read: (key: string) => T | undefined; + write: (key: string, value: T) => void; +}; + +class PersistedBase { + #value: T; + #subscribe: () => void; + #update = () => {}; + + #write: (value: T) => void; + + get current() { + this.#subscribe(); + return this.#value as T; + } + + set current(value: T) { + this.#write(value); + this.#update(); + this.#value = value; + } + + constructor(key: string, defaultValue: T, options: PersistedBaseOptions) { + const value = options.read(key); + + this.#value = value === undefined ? defaultValue : value; + this.#write = (value: T) => options.write(key, value); + + this.#subscribe = createSubscriber((update) => { + this.#update = update; + + return () => { + this.#update = () => {}; + }; + }); + } +} + +type PersistedLocalStorageOptions = { + serializer?: { + stringify(value: T): string; + parse(text: string): T; + }; + valid?: (value: T | unknown) => value is T; +}; + +export class PersistedLocalStorage extends PersistedBase { + constructor(key: string, defaultValue: T, options: PersistedLocalStorageOptions = {}) { + const valid = options.valid || (() => true); + const serializer = options.serializer || JSON; + + super(key, defaultValue, { + read: (key: string) => { + if (!browser) { + return; + } + + const item = localStorage.getItem(key) ?? undefined; + if (item === undefined) { + return; + } + + const parsed = serializer.parse(item); + if (!valid(parsed)) { + return; + } + + return parsed; + }, + write: (key: string, value: T) => { + if (browser) { + localStorage.setItem(key, serializer.stringify(value)); + } + }, + }); + } +} diff --git a/web/src/lib/utils/sw-messaging.ts b/web/src/lib/utils/sw-messaging.ts new file mode 100644 index 0000000000..1a19d3c134 --- /dev/null +++ b/web/src/lib/utils/sw-messaging.ts @@ -0,0 +1,8 @@ +const broadcast = new BroadcastChannel('immich'); + +export function cancelImageUrl(url: string) { + broadcast.postMessage({ type: 'cancel', url }); +} +export function preloadImageUrl(url: string) { + broadcast.postMessage({ type: 'preload', url }); +} diff --git a/web/src/lib/utils/thumbnail-util.ts b/web/src/lib/utils/thumbnail-util.ts index a53691e716..f0043790ea 100644 --- a/web/src/lib/utils/thumbnail-util.ts +++ b/web/src/lib/utils/thumbnail-util.ts @@ -1,6 +1,7 @@ +import { locale } from '$lib/stores/preferences.store'; import { AssetTypeEnum, type AssetResponseDto } from '@immich/sdk'; import { t } from 'svelte-i18n'; -import { derived } from 'svelte/store'; +import { derived, get } from 'svelte/store'; import { fromLocalDateTime } from './timeline-util'; /** @@ -43,7 +44,7 @@ export const getAltText = derived(t, ($t) => { return asset.exifInfo.description; } - const date = fromLocalDateTime(asset.localDateTime).toLocaleString({ dateStyle: 'long' }); + const date = fromLocalDateTime(asset.localDateTime).toLocaleString({ dateStyle: 'long' }, { locale: get(locale) }); const hasPlace = !!asset.exifInfo?.city && !!asset.exifInfo?.country; const names = asset.people?.filter((p) => p.name).map((p) => p.name) ?? []; const peopleCount = names.length; diff --git a/web/src/lib/utils/timeline-util.ts b/web/src/lib/utils/timeline-util.ts index f40e2bc3eb..21a7d23953 100644 --- a/web/src/lib/utils/timeline-util.ts +++ b/web/src/lib/utils/timeline-util.ts @@ -1,41 +1,13 @@ -import type { AssetBucket } from '$lib/stores/assets-store.svelte'; import { locale } from '$lib/stores/preferences.store'; -import { type CommonJustifiedLayout } from '$lib/utils/layout-utils'; - -import type { AssetResponseDto } from '@immich/sdk'; import { memoize } from 'lodash-es'; import { DateTime, type LocaleOptions } from 'luxon'; import { get } from 'svelte/store'; -export type DateGroup = { - bucket: AssetBucket; - index: number; - row: number; - col: number; - date: DateTime; - groupTitle: string; - assets: AssetResponseDto[]; - assetsIntersecting: boolean[]; - height: number; - intersecting: boolean; - geometry: CommonJustifiedLayout; -}; export type ScrubberListener = ( bucketDate: string | undefined, overallScrollPercent: number, bucketScrollPercent: number, ) => void | Promise; -export type ScrollTargetListener = ({ - bucket, - dateGroup, - asset, - offset, -}: { - bucket: AssetBucket; - dateGroup: DateGroup; - asset: AssetResponseDto; - offset: number; -}) => void; export const fromLocalDateTime = (localDateTime: string) => DateTime.fromISO(localDateTime, { zone: 'UTC', locale: get(locale) }); @@ -43,31 +15,6 @@ export const fromLocalDateTime = (localDateTime: string) => export const fromDateTimeOriginal = (dateTimeOriginal: string, timeZone: string) => DateTime.fromISO(dateTimeOriginal, { zone: timeZone }); -export type LayoutBox = { - aspectRatio: number; - top: number; - width: number; - height: number; - left: number; - forcedAspectRatio?: boolean; -}; - -export function findTotalOffset(element: HTMLElement, stop: HTMLElement) { - let offset = 0; - while (element.offsetParent && element !== stop) { - offset += element.offsetTop; - element = element.offsetParent as HTMLElement; - } - return offset; -} - -export const groupDateFormat: Intl.DateTimeFormatOptions = { - weekday: 'short', - month: 'short', - day: 'numeric', - year: 'numeric', -}; - export function formatGroupTitle(_date: DateTime): string { if (!_date.isValid) { return _date.toString(); @@ -87,20 +34,24 @@ export function formatGroupTitle(_date: DateTime): string { // Last week if (date >= today.minus({ days: 6 }) && date < today) { - return date.toLocaleString({ weekday: 'long' }); + return date.toLocaleString({ weekday: 'long' }, { locale: get(locale) }); } // This year if (today.hasSame(date, 'year')) { - return date.toLocaleString({ - weekday: 'short', - month: 'short', - day: 'numeric', - }); + return date.toLocaleString( + { + weekday: 'short', + month: 'short', + day: 'numeric', + }, + { locale: get(locale) }, + ); } - return getDateLocaleString(date); + return getDateLocaleString(date, { locale: get(locale) }); } + export const getDateLocaleString = (date: DateTime, opts?: LocaleOptions): string => date.toLocaleString(DateTime.DATE_MED_WITH_WEEKDAY, opts); diff --git a/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte index 818f48fe4a..e10fbae139 100644 --- a/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -22,9 +22,10 @@ import FavoriteAction from '$lib/components/photos-page/actions/favorite-action.svelte'; import RemoveFromAlbum from '$lib/components/photos-page/actions/remove-from-album.svelte'; import SelectAllAssets from '$lib/components/photos-page/actions/select-all-assets.svelte'; + import TagAction from '$lib/components/photos-page/actions/tag-action.svelte'; import AssetGrid from '$lib/components/photos-page/asset-grid.svelte'; - import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte'; import AssetSelectControlBar from '$lib/components/photos-page/asset-select-control-bar.svelte'; + import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte'; import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte'; import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte'; import CreateSharedLinkModal from '$lib/components/shared-components/create-share-link-modal/create-shared-link-modal.svelte'; @@ -33,14 +34,16 @@ notificationController, } from '$lib/components/shared-components/notification/notification'; import UserAvatar from '$lib/components/shared-components/user-avatar.svelte'; - import { AppRoute, AlbumPageViewMode } from '$lib/constants'; - import { numberOfComments, setNumberOfComments, updateNumberOfComments } from '$lib/stores/activity.store'; + import { AlbumPageViewMode, AppRoute } from '$lib/constants'; + import { activityManager } from '$lib/managers/activity-manager.svelte'; + import { AssetInteraction } from '$lib/stores/asset-interaction.svelte'; import { assetViewingStore } from '$lib/stores/asset-viewing.store'; import { AssetStore } from '$lib/stores/assets-store.svelte'; import { SlideshowNavigation, SlideshowState, slideshowStore } from '$lib/stores/slideshow.store'; import { preferences, user } from '$lib/stores/user.store'; import { handlePromiseError } from '$lib/utils'; - import { downloadAlbum, cancelMultiselect } from '$lib/utils/asset-utils'; + import { confirmAlbumDelete } from '$lib/utils/album-utils'; + import { cancelMultiselect, downloadAlbum } from '$lib/utils/asset-utils'; import { openFileUploadDialog } from '$lib/utils/file-uploader'; import { handleError } from '$lib/utils/handle-error'; import { @@ -53,18 +56,11 @@ import { AlbumUserRole, AssetOrder, - ReactionLevel, - ReactionType, addAssetsToAlbum, addUsersToAlbum, - createActivity, - deleteActivity, deleteAlbum, - getActivities, - getActivityStatistics, getAlbumInfo, updateAlbumInfo, - type ActivityResponseDto, type AlbumUserAddDto, } from '@immich/sdk'; import { @@ -80,13 +76,10 @@ mdiPresentationPlay, mdiShareVariantOutline, } from '@mdi/js'; + import { onDestroy } from 'svelte'; + import { t } from 'svelte-i18n'; import { fly } from 'svelte/transition'; import type { PageData } from './$types'; - import { t } from 'svelte-i18n'; - import { onDestroy } from 'svelte'; - import { confirmAlbumDelete } from '$lib/utils/album-utils'; - import TagAction from '$lib/components/photos-page/actions/tag-action.svelte'; - import { AssetInteraction } from '$lib/stores/asset-interaction.svelte'; interface Props { data: PageData; @@ -103,8 +96,6 @@ let viewMode: AlbumPageViewMode = $state(AlbumPageViewMode.VIEW); let isCreatingSharedAlbum = $state(false); let isShowActivity = $state(false); - let isLiked: ActivityResponseDto | null = $state(null); - let reactions: ActivityResponseDto[] = $state([]); let albumOrder: AssetOrder | undefined = $state(data.album.order); const assetInteraction = new AssetInteraction(); @@ -154,44 +145,15 @@ const handleFavorite = async () => { try { - if (isLiked) { - const activityId = isLiked.id; - await deleteActivity({ id: activityId }); - reactions = reactions.filter((reaction) => reaction.id !== activityId); - isLiked = null; - } else { - isLiked = await createActivity({ - activityCreateDto: { albumId: album.id, type: ReactionType.Like }, - }); - reactions = [...reactions, isLiked]; - } + await activityManager.toggleLike(); } catch (error) { handleError(error, $t('errors.cant_change_asset_favorite')); } }; - const getFavorite = async () => { - if ($user) { - try { - const data = await getActivities({ - userId: $user.id, - albumId: album.id, - $type: ReactionType.Like, - level: ReactionLevel.Album, - }); - if (data.length > 0) { - isLiked = data[0]; - } - } catch (error) { - handleError(error, $t('errors.unable_to_load_liked_status')); - } - } - }; - - const getNumberOfComments = async () => { + const updateComments = async () => { try { - const { comments } = await getActivityStatistics({ albumId: album.id }); - setNumberOfComments(comments); + await activityManager.refreshActivities(album.id); } catch (error) { handleError(error, $t('errors.cant_get_number_of_comments')); } @@ -398,7 +360,7 @@ let albumId = $derived(album.id); $effect(() => { - if (!album.isActivityEnabled && $numberOfComments === 0) { + if (!album.isActivityEnabled && activityManager.commentCount === 0) { isShowActivity = false; } }); @@ -412,7 +374,16 @@ void assetStore.updateOptions({ isArchived: false, withPartners: true, timelineAlbumId: albumId }); } }); - onDestroy(() => assetStore.destroy()); + + $effect(() => { + activityManager.reset(); + activityManager.init(album.id); + }); + + onDestroy(() => { + activityManager.reset(); + assetStore.destroy(); + }); // let timelineStore = new AssetStore(); // $effect(() => void timelineStore.updateOptions({ isArchived: false, withPartners: true, timelineAlbumId: albumId })); // onDestroy(() => timelineStore.destroy()); @@ -420,7 +391,7 @@ let isOwned = $derived($user.id == album.ownerId); let showActivityStatus = $derived( - album.albumUsers.length > 0 && !$showAssetViewer && (album.isActivityEnabled || $numberOfComments > 0), + album.albumUsers.length > 0 && !$showAssetViewer && (album.isActivityEnabled || activityManager.commentCount > 0), ); let isEditor = $derived( album.albumUsers.find(({ user: { id } }) => id === $user.id)?.role === AlbumUserRole.Editor || @@ -430,8 +401,7 @@ let albumHasViewers = $derived(album.albumUsers.some(({ role }) => role === AlbumUserRole.Viewer)); $effect(() => { if (album.albumUsers.length > 0) { - handlePromiseError(getFavorite()); - handlePromiseError(getNumberOfComments()); + handlePromiseError(updateComments()); } }); const isShared = $derived(viewMode === AlbumPageViewMode.SELECT_ASSETS ? false : album.albumUsers.length > 0); @@ -708,11 +678,11 @@ {#if showActivityStatus} -
+
@@ -725,7 +695,7 @@
updateNumberOfComments(1)} - onDeleteComment={() => updateNumberOfComments(-1)} - onDeleteLike={() => (isLiked = null)} onClose={handleOpenAndCloseActivityTab} />
diff --git a/web/src/routes/(user)/explore/+page.svelte b/web/src/routes/(user)/explore/+page.svelte index ec62d5e869..49d38d0815 100644 --- a/web/src/routes/(user)/explore/+page.svelte +++ b/web/src/routes/(user)/explore/+page.svelte @@ -48,7 +48,7 @@

{$t('people')}

{$t('view_all')}
@@ -64,7 +64,7 @@ widthStyle="100%" /> {#if person.isFavorite} -
+
{/if} @@ -82,7 +82,7 @@

{$t('places')}

{$t('view_all')}
diff --git a/web/src/routes/(user)/folders/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/folders/[[photos=photos]]/[[assetId=id]]/+page.svelte index f5a4f6cd09..d1fc0bcd90 100644 --- a/web/src/routes/(user)/folders/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/folders/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -87,7 +87,7 @@ {#if assetInteraction.selectionActive} -
+
cancelMultiselect(assetInteraction)} @@ -133,7 +133,7 @@
-
{$t('explorer').toUpperCase()}
+
{$t('explorer').toUpperCase()}
{ @@ -542,7 +542,7 @@ heightStyle="3.375rem" />

{person.name || $t('add_a_name')}

@@ -598,7 +598,7 @@ widthStyle="2rem" heightStyle="2rem" /> -

{person.name}

+

{person.name}

{/each}
diff --git a/web/src/routes/(user)/search/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/search/[[photos=photos]]/[[assetId=id]]/+page.svelte index c985104e3c..9d427e1ea7 100644 --- a/web/src/routes/(user)/search/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/search/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -251,7 +251,7 @@
{#if assetInteraction.selectionActive} -
+
cancelMultiselect(assetInteraction)} @@ -289,13 +289,13 @@
{:else} -
+
goto(previousRoute)} backIcon={mdiArrowLeft}>
-
+
@@ -313,13 +313,13 @@
{getHumanReadableSearchKey(key as keyof SearchTerms)}
{#if value !== true} -
+
{#if (key === 'takenAfter' || key === 'takenBefore') && typeof value === 'string'} {getHumanReadableDate(value)} {:else if key === 'personIds' && Array.isArray(value)} @@ -349,7 +349,7 @@ > {#if searchResultAlbums.length > 0}
-
{$t('albums').toUpperCase()}
+
{$t('albums').toUpperCase()}
diff --git a/web/src/routes/(user)/sharing/+page.svelte b/web/src/routes/(user)/sharing/+page.svelte index e3d6ac1ced..a55452b5d1 100644 --- a/web/src/routes/(user)/sharing/+page.svelte +++ b/web/src/routes/(user)/sharing/+page.svelte @@ -68,7 +68,7 @@ class="flex gap-4 rounded-lg px-5 py-4 transition-all hover:bg-gray-200 dark:hover:bg-gray-700" > -
+

{partner.name}

diff --git a/web/src/routes/(user)/tags/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/tags/[[photos=photos]]/[[assetId=id]]/+page.svelte index 8bb43676e8..8d33a2eb6e 100644 --- a/web/src/routes/(user)/tags/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/tags/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -146,7 +146,7 @@
-
{$t('explorer').toUpperCase()}
+
{$t('explorer').toUpperCase()}
{ - if (theme.system) { - theme.value = globalThis.matchMedia('(prefers-color-scheme: dark)').matches ? Theme.DARK : Theme.LIGHT; - } - - if (theme.value === Theme.LIGHT) { - document.documentElement.classList.remove('dark'); - } else { - document.documentElement.classList.add('dark'); - } - }; - - const handleChangeTheme = () => { - if ($colorTheme.system) { - handleToggleTheme(); - } - }; - const getMyImmichLink = () => { return new URL(page.url.pathname + page.url.search, 'https://my.immich.app'); }; @@ -65,20 +46,11 @@ const element = document.querySelector('#stencil'); element?.remove(); // if the browser theme changes, changes the Immich theme too - globalThis.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', handleChangeTheme); }); - onDestroy(() => { - document.removeEventListener('change', handleChangeTheme); - }); - - if (isSharedLinkRoute(page.route?.id)) { - setKey(page.params.key); - } + eventManager.emit('app.init'); beforeNavigate(({ from, to }) => { - setKey(isSharedLinkRoute(to?.route.id) ? to?.params?.key : undefined); - if (isAssetViewerRoute(from) && isAssetViewerRoute(to)) { return; } @@ -88,9 +60,6 @@ afterNavigate(() => { showNavigationLoadingBar = false; }); - run(() => { - changeTheme($colorTheme); - }); run(() => { if ($user) { openWebsocketConnection(); diff --git a/web/src/routes/admin/jobs-status/+page.svelte b/web/src/routes/admin/jobs-status/+page.svelte index 21381081e0..07757614e5 100644 --- a/web/src/routes/admin/jobs-status/+page.svelte +++ b/web/src/routes/admin/jobs-status/+page.svelte @@ -107,7 +107,7 @@ > {#snippet promptSnippet()} -
+
{#if libraries.length > 0} -
+
@@ -369,7 +369,7 @@ {/if} {#if editScanSettings === index} -
+
- import empty4Url from '$lib/assets/empty-4.svg'; - import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte'; - import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte'; - import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte'; - import { - NotificationType, - notificationController, - } from '$lib/components/shared-components/notification/notification'; - import { downloadManager } from '$lib/stores/download-store.svelte'; - import { locale } from '$lib/stores/preferences.store'; - import { copyToClipboard } from '$lib/utils'; - import { downloadBlob } from '$lib/utils/asset-utils'; - import { handleError } from '$lib/utils/handle-error'; - import { fixAuditFiles, getAuditFiles, getFileChecksums, type FileReportItemDto } from '@immich/sdk'; - import { Button, HStack, Text } from '@immich/ui'; - import { mdiCheckAll, mdiContentCopy, mdiDownload, mdiRefresh, mdiWrench } from '@mdi/js'; - import { t } from 'svelte-i18n'; - import type { PageData } from './$types'; - - interface Props { - data: PageData; - } - - let { data }: Props = $props(); - - interface UntrackedFile { - filename: string; - checksum: string | null; - } - - interface Match { - orphan: FileReportItemDto; - extra: UntrackedFile; - } - - const normalize = (filenames: string[]) => filenames.map((filename) => ({ filename, checksum: null })); - - let checking = $state(false); - let repairing = $state(false); - - let orphans: FileReportItemDto[] = $state(data.orphans); - let extras: UntrackedFile[] = $state(normalize(data.extras)); - let matches: Match[] = $state([]); - - const handleDownload = () => { - if (extras.length > 0) { - const blob = new Blob([extras.map(({ filename }) => filename).join('\n')], { type: 'text/plain' }); - const downloadKey = 'untracked.txt'; - downloadManager.add(downloadKey, blob.size); - downloadManager.update(downloadKey, blob.size); - downloadBlob(blob, downloadKey); - setTimeout(() => downloadManager.clear(downloadKey), 5000); - } - - if (orphans.length > 0) { - const blob = new Blob([JSON.stringify(orphans, null, 4)], { type: 'application/json' }); - const downloadKey = 'orphans.json'; - downloadManager.add(downloadKey, blob.size); - downloadManager.update(downloadKey, blob.size); - downloadBlob(blob, downloadKey); - setTimeout(() => downloadManager.clear(downloadKey), 5000); - } - }; - - const handleRepair = async () => { - if (matches.length === 0) { - return; - } - - repairing = true; - - try { - await fixAuditFiles({ - fileReportFixDto: { - items: matches.map(({ orphan, extra }) => ({ - entityId: orphan.entityId, - entityType: orphan.entityType, - pathType: orphan.pathType, - pathValue: extra.filename, - })), - }, - }); - - notificationController.show({ - type: NotificationType.Info, - message: $t('admin.repaired_items', { values: { count: matches.length } }), - }); - - matches = []; - } catch (error) { - handleError(error, $t('errors.unable_to_repair_items')); - } finally { - repairing = false; - } - }; - - const handleSplit = (match: Match) => { - matches = matches.filter((_match) => _match !== match); - orphans = [match.orphan, ...orphans]; - extras = [match.extra, ...extras]; - }; - - const handleRefresh = async () => { - matches = []; - orphans = []; - extras = []; - - try { - const report = await getAuditFiles(); - - orphans = report.orphans; - extras = normalize(report.extras); - - notificationController.show({ message: $t('refreshed'), type: NotificationType.Info }); - } catch (error) { - handleError(error, $t('errors.unable_to_load_items')); - } - }; - - const handleCheckOne = async (filename: string) => { - try { - const matched = await loadAndMatch([filename]); - if (matched) { - notificationController.show({ - message: $t('admin.repair_matched_items', { values: { count: 1 } }), - type: NotificationType.Info, - }); - } - } catch (error) { - handleError(error, $t('errors.repair_unable_to_check_items', { values: { count: 'one' } })); - } - }; - - const handleCheckAll = async () => { - checking = true; - - let count = 0; - - try { - const chunkSize = 10; - const filenames = extras.filter(({ checksum }) => !checksum).map(({ filename }) => filename); - for (let index = 0; index < filenames.length; index += chunkSize) { - count += await loadAndMatch(filenames.slice(index, index + chunkSize)); - } - } catch (error) { - handleError(error, $t('errors.repair_unable_to_check_items', { values: { count: 'other' } })); - } finally { - checking = false; - } - - notificationController.show({ - message: $t('admin.repair_matched_items', { values: { count } }), - type: NotificationType.Info, - }); - }; - - const loadAndMatch = async (filenames: string[]) => { - const items = await getFileChecksums({ - fileChecksumDto: { filenames }, - }); - - let count = 0; - - for (const { checksum, filename } of items) { - const extra = extras.find((extra) => extra.filename === filename); - if (extra) { - extra.checksum = checksum; - extras = [...extras]; - } - - const orphan = orphans.find((orphan) => orphan.checksum === checksum); - if (orphan) { - count++; - matches = [...matches, { orphan, extra: { filename, checksum } }]; - orphans = orphans.filter((_orphan) => _orphan !== orphan); - extras = extras.filter((extra) => extra.filename !== filename); - } - } - - return count; - }; - - - - {#snippet buttons()} - - - - - - - {/snippet} -
-
- {#if matches.length + extras.length + orphans.length === 0} -
- -
- {:else} -
-
- - - - - - - {#each matches as match (match.extra.filename)} - handleSplit(match)} - > - - - - {/each} - -
-
-

- {$t('matches').toUpperCase()} - {matches.length > 0 ? `(${matches.length.toLocaleString($locale)})` : ''} -

-

{$t('admin.these_files_matched_by_checksum')}

-
-
- {match.orphan.pathValue} => - {match.extra.filename} - - ({match.orphan.entityType}/{match.orphan.pathType}) -
- - - - - - - - - {#each orphans as orphan, index (index)} - - - - - - {/each} - -
-
-

- {$t('admin.offline_paths').toUpperCase()} - {orphans.length > 0 ? `(${orphans.length.toLocaleString($locale)})` : ''} -

-

- {$t('admin.offline_paths_description')} -

-
-
copyToClipboard(orphan.pathValue)}> - {}} /> - - {orphan.pathValue} - - ({orphan.entityType}) -
- - - - - - - - - {#each extras as extra (extra.filename)} - handleCheckOne(extra.filename)} - title={extra.filename} - > - - - - {/each} - -
-
-

- {$t('admin.untracked_files').toUpperCase()} - {extras.length > 0 ? `(${extras.length.toLocaleString($locale)})` : ''} -

-

- {$t('admin.untracked_files_description')} -

-
-
copyToClipboard(extra.filename)}> - {}} /> - - {extra.filename} - - {#if extra.checksum} - [sha1:{extra.checksum}] - {/if} - -
- - {/if} - - - diff --git a/web/src/routes/admin/repair/+page.ts b/web/src/routes/admin/repair/+page.ts deleted file mode 100644 index 9e52abb573..0000000000 --- a/web/src/routes/admin/repair/+page.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { authenticate } from '$lib/utils/auth'; -import { getFormatter } from '$lib/utils/i18n'; -import { getAuditFiles } from '@immich/sdk'; -import type { PageLoad } from './$types'; - -export const load = (async () => { - await authenticate({ admin: true }); - const { orphans, extras } = await getAuditFiles(); - const $t = await getFormatter(); - - return { - orphans, - extras, - meta: { - title: $t('repair'), - }, - }; -}) satisfies PageLoad; diff --git a/web/src/routes/admin/system-settings/+page.svelte b/web/src/routes/admin/system-settings/+page.svelte index 6512461ee9..1ac9f0b6fd 100644 --- a/web/src/routes/admin/system-settings/+page.svelte +++ b/web/src/routes/admin/system-settings/+page.svelte @@ -1,15 +1,16 @@ diff --git a/web/src/routes/auth/login/+page.svelte b/web/src/routes/auth/login/+page.svelte index c3d01b3c56..fdad88e1ff 100644 --- a/web/src/routes/auth/login/+page.svelte +++ b/web/src/routes/auth/login/+page.svelte @@ -2,10 +2,11 @@ import { goto } from '$app/navigation'; import AuthPageLayout from '$lib/components/layouts/AuthPageLayout.svelte'; import { AppRoute } from '$lib/constants'; + import { eventManager } from '$lib/managers/event-manager.svelte'; import { featureFlags, serverConfig } from '$lib/stores/server-config.store'; import { oauth } from '$lib/utils'; import { getServerErrorMessage, handleError } from '$lib/utils/handle-error'; - import { login } from '@immich/sdk'; + import { login, type LoginResponseDto } from '@immich/sdk'; import { Alert, Button, Field, Input, PasswordInput, Stack } from '@immich/ui'; import { onMount } from 'svelte'; import { t } from 'svelte-i18n'; @@ -24,7 +25,11 @@ let loading = $state(false); let oauthLoading = $state(true); - const onSuccess = async () => await goto(AppRoute.PHOTOS, { invalidateAll: true }); + const onSuccess = async (user: LoginResponseDto) => { + await goto(AppRoute.PHOTOS, { invalidateAll: true }); + eventManager.emit('auth.login', user); + }; + const onFirstLogin = async () => await goto(AppRoute.AUTH_CHANGE_PASSWORD); const onOnboarding = async () => await goto(AppRoute.AUTH_ONBOARDING); @@ -36,8 +41,8 @@ if (oauth.isCallback(globalThis.location)) { try { - await oauth.login(globalThis.location); - await onSuccess(); + const user = await oauth.login(globalThis.location); + await onSuccess(user); return; } catch (error) { console.error('Error [login-form] [oauth.callback]', error); @@ -74,7 +79,7 @@ await onFirstLogin(); return; } - await onSuccess(); + await onSuccess(user); return; } catch (error) { errorMessage = getServerErrorMessage(error) || $t('errors.incorrect_email_or_password'); @@ -132,7 +137,7 @@

{$t('or').toUpperCase()} diff --git a/web/src/service-worker/index.ts b/web/src/service-worker/index.ts new file mode 100644 index 0000000000..797f4754b6 --- /dev/null +++ b/web/src/service-worker/index.ts @@ -0,0 +1,86 @@ +/// +/// +/// +/// +import { version } from '$service-worker'; + +const useCache = true; +const sw = globalThis as unknown as ServiceWorkerGlobalScope; +const pendingLoads = new Map(); + +// Create a unique cache name for this deployment +const CACHE = `cache-${version}`; + +sw.addEventListener('install', (event) => { + event.waitUntil(sw.skipWaiting()); +}); + +sw.addEventListener('activate', (event) => { + event.waitUntil(sw.clients.claim()); + // Remove previous cached data from disk + event.waitUntil(deleteOldCaches()); +}); + +sw.addEventListener('fetch', (event) => { + if (event.request.method !== 'GET') { + return; + } + const url = new URL(event.request.url); + if (/^\/api\/assets\/[a-f0-9-]+\/(original|thumbnail)/.test(url.pathname)) { + event.respondWith(immichAsset(url)); + } +}); + +async function deleteOldCaches() { + for (const key of await caches.keys()) { + if (key !== CACHE) { + await caches.delete(key); + } + } +} + +async function immichAsset(url: URL) { + const cache = await caches.open(CACHE); + let response = useCache ? await cache.match(url) : undefined; + if (response) { + return response; + } + try { + const cancelToken = new AbortController(); + const request = fetch(url, { + signal: cancelToken.signal, + }); + pendingLoads.set(url.toString(), cancelToken); + response = await request; + if (!(response instanceof Response)) { + throw new TypeError('invalid response from fetch'); + } + if (response.status === 200) { + cache.put(url, response.clone()); + } + return response; + } catch { + return Response.error(); + } finally { + pendingLoads.delete(url.toString()); + } +} + +const broadcast = new BroadcastChannel('immich'); +// eslint-disable-next-line unicorn/prefer-add-event-listener +broadcast.onmessage = (event) => { + if (!event.data) { + return; + } + const urlstring = event.data.url; + const url = new URL(urlstring, event.origin); + if (event.data.type === 'cancel') { + const pending = pendingLoads.get(url.toString()); + if (pending) { + pending.abort(); + pendingLoads.delete(url.toString()); + } + } else if (event.data.type === 'preload') { + immichAsset(url); + } +}; diff --git a/web/src/test-data/setup.ts b/web/src/test-data/setup.ts index 6709bd5b80..f2cfac3c36 100644 --- a/web/src/test-data/setup.ts +++ b/web/src/test-data/setup.ts @@ -4,3 +4,15 @@ import { init } from 'svelte-i18n'; beforeAll(async () => { await init({ fallbackLocale: 'dev' }); }); + +Object.defineProperty(globalThis, 'matchMedia', { + writable: true, + value: vi.fn().mockImplementation((query) => ({ + matches: false, + media: query, + onchange: null, + addEventListener: vi.fn(), + removeEventListener: vi.fn(), + dispatchEvent: vi.fn(), + })), +}); diff --git a/web/static/.well-known/security.txt b/web/static/.well-known/security.txt new file mode 100644 index 0000000000..1cd9daa56a --- /dev/null +++ b/web/static/.well-known/security.txt @@ -0,0 +1,7 @@ +# This site is running an Immich instance. +# Immich-related security problems should be reported to the Immich security team. +# Security problems related to this instance should be reported to its administration. +Policy: https://github.com/immich-app/immich/blob/main/SECURITY.md +Contact: mailto:security@immich.app +Preferred-Languages: en +Expires: 2026-05-01T23:59:00.000Z