diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 9563be6125..79126fd658 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -5,8 +5,7 @@ "immich-server", "redis", "database", - "immich-machine-learning", - "init" + "immich-machine-learning" ], "dockerComposeFile": [ "../docker/docker-compose.dev.yml", diff --git a/.devcontainer/mobile/container-compose-overrides.yml b/.devcontainer/mobile/container-compose-overrides.yml index c0655e50e7..99e41cbece 100644 --- a/.devcontainer/mobile/container-compose-overrides.yml +++ b/.devcontainer/mobile/container-compose-overrides.yml @@ -6,29 +6,35 @@ services: - IMMICH_SERVER_URL=http://127.0.0.1:2283/ volumes: !override # bind mount host to /workspaces/immich - ..:/workspaces/immich - - cli_node_modules:/workspaces/immich/cli/node_modules - - e2e_node_modules:/workspaces/immich/e2e/node_modules - - open_api_node_modules:/workspaces/immich/open-api/typescript-sdk/node_modules - - server_node_modules:/workspaces/immich/server/node_modules - - web_node_modules:/workspaces/immich/web/node_modules - - ${UPLOAD_LOCATION}/photos:/data - - ${UPLOAD_LOCATION}/photos/upload:/data/upload + - ${UPLOAD_LOCATION:-upload-devcontainer-volume}${UPLOAD_LOCATION:+/photos}:/data + - pnpm-store:/usr/src/app/.pnpm-store + - server-node_modules:/usr/src/app/server/node_modules + - web-node_modules:/usr/src/app/web/node_modules + - github-node_modules:/usr/src/app/.github/node_modules + - cli-node_modules:/usr/src/app/cli/node_modules + - docs-node_modules:/usr/src/app/docs/node_modules + - e2e-node_modules:/usr/src/app/e2e/node_modules + - sdk-node_modules:/usr/src/app/open-api/typescript-sdk/node_modules + - app-node_modules:/usr/src/app/node_modules + - sveltekit:/usr/src/app/web/.svelte-kit + - coverage:/usr/src/app/web/coverage - /etc/localtime:/etc/localtime:ro - + immich-web: + env_file: !reset [] + immich-machine-learning: + env_file: !reset [] database: + env_file: !reset [] + environment: !override + POSTGRES_PASSWORD: ${DB_PASSWORD-postgres} + POSTGRES_USER: ${DB_USERNAME-postgres} + POSTGRES_DB: ${DB_DATABASE_NAME-immich} + POSTGRES_INITDB_ARGS: '--data-checksums' + POSTGRES_HOST_AUTH_METHOD: md5 volumes: - - ${UPLOAD_LOCATION}/postgres:/var/lib/postgresql/data - + - ${UPLOAD_LOCATION:-postgres-devcontainer-volume}${UPLOAD_LOCATION:+/postgres}:/var/lib/postgresql/data + redis: + env_file: !reset [] volumes: - # Node modules for each service to avoid conflicts and ensure consistent dependencies - cli_node_modules: - e2e_node_modules: - open_api_node_modules: - server_node_modules: - web_node_modules: - - # UPLOAD_LOCATION must be set to a absolute path or vol-upload - vol-upload: - - # DB_DATA_LOCATION must be set to a absolute path or vol-database - vol-database: + upload-devcontainer-volume: + postgres-devcontainer-volume: diff --git a/.devcontainer/mobile/devcontainer.json b/.devcontainer/mobile/devcontainer.json index 0dbcc8e9c8..140a2ecac3 100644 --- a/.devcontainer/mobile/devcontainer.json +++ b/.devcontainer/mobile/devcontainer.json @@ -40,7 +40,7 @@ "userEnvProbe": "loginInteractiveShell", "remoteEnv": { // The location where your uploaded files are stored - "UPLOAD_LOCATION": "${localEnv:UPLOAD_LOCATION:./Library}", + "UPLOAD_LOCATION": "${localEnv:UPLOAD_LOCATION:./library}", // Connection secret for postgres. You should change it to a random password // Please use only the characters `A-Za-z0-9`, without special characters or spaces "DB_PASSWORD": "${localEnv:DB_PASSWORD:postgres}", diff --git a/.devcontainer/server/container-compose-overrides.yml b/.devcontainer/server/container-compose-overrides.yml index abf34ad68c..3be5cd8f3f 100644 --- a/.devcontainer/server/container-compose-overrides.yml +++ b/.devcontainer/server/container-compose-overrides.yml @@ -8,8 +8,7 @@ services: - IMMICH_SERVER_URL=http://127.0.0.1:2283/ volumes: !override - ..:/workspaces/immich - - ${UPLOAD_LOCATION:-upload1-devcontainer-volume}${UPLOAD_LOCATION:+/photos}:/data - - ${UPLOAD_LOCATION:-upload2-devcontainer-volume}${UPLOAD_LOCATION:+/photos/upload}:/data/upload + - ${UPLOAD_LOCATION:-upload-devcontainer-volume}${UPLOAD_LOCATION:+/photos}:/data - /etc/localtime:/etc/localtime:ro - pnpm-store:/usr/src/app/.pnpm-store - server-node_modules:/usr/src/app/server/node_modules @@ -24,9 +23,6 @@ services: - coverage:/usr/src/app/web/coverage immich-web: env_file: !reset [] - init: - env_file: !reset [] - command: sh -c 'find /data -maxdepth 1 ! -path "/data/postgres" -type d -exec chown ${UID:-1000}:${GID:-1000} {} + 2>/dev/null || true; for path in /usr/src/app/.pnpm-store /usr/src/app/server/node_modules /usr/src/app/server/dist /usr/src/app/.github/node_modules /usr/src/app/cli/node_modules /usr/src/app/docs/node_modules /usr/src/app/e2e/node_modules /usr/src/app/open-api/typescript-sdk/node_modules /usr/src/app/web/.svelte-kit /usr/src/app/web/coverage /usr/src/app/node_modules /usr/src/app/web/node_modules; do [ -e "$$path" ] && chown -R ${UID:-1000}:${GID:-1000} "$$path" || true; done' immich-machine-learning: env_file: !reset [] database: @@ -42,7 +38,5 @@ services: redis: env_file: !reset [] volumes: - # Node modules for each service to avoid conflicts and ensure consistent dependencies - upload1-devcontainer-volume: - upload2-devcontainer-volume: + upload-devcontainer-volume: postgres-devcontainer-volume: diff --git a/.github/.nvmrc b/.github/.nvmrc index e2228113dd..442c7587a9 100644 --- a/.github/.nvmrc +++ b/.github/.nvmrc @@ -1 +1 @@ -22.19.0 +22.20.0 diff --git a/.github/labeler.yml b/.github/labeler.yml index c0c52f1d7e..d8923a3035 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -6,7 +6,6 @@ cli: documentation: - changed-files: - any-glob-to-any-file: - - docs/blob/** - docs/docs/** - docs/src/** - docs/static/** diff --git a/.github/workflows/build-mobile.yml b/.github/workflows/build-mobile.yml index 71fa358942..f7e9ad5731 100644 --- a/.github/workflows/build-mobile.yml +++ b/.github/workflows/build-mobile.yml @@ -32,24 +32,18 @@ jobs: permissions: contents: read outputs: - should_run: ${{ steps.found_paths.outputs.mobile == 'true' || steps.should_force.outputs.should_force == 'true' }} + should_run: ${{ steps.check.outputs.should_run }} steps: - - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - with: - persist-credentials: false - - - id: found_paths - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + - name: Check what should run + id: check + uses: immich-app/devtools/actions/pre-job@5f91b52dfbb92b8d96ca411ab59c896cd59714ca # pre-job-action-v1.1.0 with: filters: | mobile: - 'mobile/**' - workflow: - - '.github/workflows/build-mobile.yml' - - name: Check if we should force jobs to run - id: should_force - run: echo "should_force=${{ steps.found_paths.outputs.workflow == 'true' || github.event_name == 'workflow_call' || github.event_name == 'workflow_dispatch' }}" >> "$GITHUB_OUTPUT" + force-filters: | + - '.github/workflows/build-mobile.yml' + force-events: 'workflow_call,workflow_dispatch' build-sign-android: name: Build and sign Android @@ -57,11 +51,11 @@ jobs: permissions: contents: read # Skip when PR from a fork - if: ${{ !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' && needs.pre-job.outputs.should_run == 'true' }} + if: ${{ !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' && fromJSON(needs.pre-job.outputs.should_run).mobile == true }} runs-on: mich steps: - - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: ref: ${{ inputs.ref || github.sha }} persist-credentials: false @@ -72,14 +66,14 @@ jobs: working-directory: ./mobile run: printf "%s" $KEY_JKS | base64 -d > android/key.jks - - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: 'zulu' java-version: '17' - name: Restore Gradle Cache id: cache-gradle-restore - uses: actions/cache/restore@0400d5f644dc74513175e3cd8d07132dd4860809 # v4 + uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: | ~/.gradle/caches @@ -136,7 +130,7 @@ jobs: - name: Save Gradle Cache id: cache-gradle-save - uses: actions/cache/save@0400d5f644dc74513175e3cd8d07132dd4860809 # v4 + uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 if: github.ref == 'refs/heads/main' with: path: | diff --git a/.github/workflows/cache-cleanup.yml b/.github/workflows/cache-cleanup.yml index cdff8ed931..0b4366ba04 100644 --- a/.github/workflows/cache-cleanup.yml +++ b/.github/workflows/cache-cleanup.yml @@ -19,7 +19,7 @@ jobs: actions: write steps: - name: Check out code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml index 777f1898ec..1483b4312b 100644 --- a/.github/workflows/cli.yml +++ b/.github/workflows/cli.yml @@ -29,7 +29,7 @@ jobs: working-directory: ./cli steps: - - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false @@ -37,7 +37,7 @@ jobs: uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: './cli/.nvmrc' registry-url: 'https://registry.npmjs.org' @@ -50,7 +50,7 @@ jobs: - run: pnpm install --frozen-lockfile - run: pnpm build - - run: pnpm publish + - run: pnpm publish --no-git-checks if: ${{ github.event_name == 'release' }} env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} @@ -65,7 +65,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false @@ -76,7 +76,7 @@ jobs: uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 - name: Login to GitHub Container Registry - uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0 + uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 if: ${{ !github.event.pull_request.head.repo.fork }} with: registry: ghcr.io diff --git a/.github/workflows/close-duplicates.yml b/.github/workflows/close-duplicates.yml index b3411351a3..8470e0e18c 100644 --- a/.github/workflows/close-duplicates.yml +++ b/.github/workflows/close-duplicates.yml @@ -35,22 +35,21 @@ jobs: needs: [get_body, should_run] if: ${{ needs.should_run.outputs.should_run == 'true' }} container: - image: yshavit/mdq:0.8.0@sha256:c69224d34224a0043d9a3ee46679ba4a2a25afaac445f293d92afe13cd47fcea + image: ghcr.io/immich-app/mdq:main@sha256:d8ae47cf2e6cf4e2559bd57a60b73674fe44f897cba2c2bddff2987a05be10a4 outputs: - json: ${{ steps.get_checkbox.outputs.json }} + checked: ${{ steps.get_checkbox.outputs.checked }} steps: - id: get_checkbox env: BODY: ${{ needs.get_body.outputs.body }} - # TODO: We should detect if the checkbox is missing entirely and also close_and_comment in that case. run: | - JSON=$(echo "$BODY" | base64 -d | /mdq --output json '# I have searched | - [?] Yes') - echo "json=$JSON" >> $GITHUB_OUTPUT + CHECKED=$(echo "$BODY" | base64 -d | /mdq --output json '# I have searched | - [?] Yes' | jq '.items[0].list[0].checked // false') + echo "checked=$CHECKED" >> $GITHUB_OUTPUT close_and_comment: runs-on: ubuntu-latest needs: [get_checkbox_json, should_run] - if: ${{ needs.should_run.outputs.should_run == 'true' && !fromJSON(needs.get_checkbox_json.outputs.json).items[0].list[0].checked }} + if: ${{ needs.should_run.outputs.should_run == 'true' && needs.get_checkbox_json.outputs.checked != 'true' }} permissions: issues: write discussions: write diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index fac8afd8ae..2946f33783 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -44,13 +44,13 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@df559355d593797519d70b90fc8edd5db049e7a2 # v3.29.9 + uses: github/codeql-action/init@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # v3.30.6 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@df559355d593797519d70b90fc8edd5db049e7a2 # v3.29.9 + uses: github/codeql-action/autobuild@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # v3.30.6 # â„šī¸ 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@df559355d593797519d70b90fc8edd5db049e7a2 # v3.29.9 + uses: github/codeql-action/analyze@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # v3.30.6 with: category: '/language:${{matrix.language}}' diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 6e2bcdb84d..7175dc0a89 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -20,15 +20,11 @@ jobs: permissions: contents: read outputs: - should_run_server: ${{ steps.found_paths.outputs.server == 'true' || steps.should_force.outputs.should_force == 'true' }} - should_run_ml: ${{ steps.found_paths.outputs.machine-learning == 'true' || steps.should_force.outputs.should_force == 'true' }} + should_run: ${{ steps.check.outputs.should_run }} steps: - - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - with: - persist-credentials: false - - id: found_paths - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + - name: Check what should run + id: check + uses: immich-app/devtools/actions/pre-job@5f91b52dfbb92b8d96ca411ab59c896cd59714ca # pre-job-action-v1.1.0 with: filters: | server: @@ -38,14 +34,11 @@ jobs: - 'i18n/**' machine-learning: - 'machine-learning/**' - workflow: - - '.github/workflows/docker.yml' - - '.github/workflows/multi-runner-build.yml' - - '.github/actions/image-build' - - - name: Check if we should force jobs to run - id: should_force - run: echo "should_force=${{ steps.found_paths.outputs.workflow == 'true' || github.event_name == 'workflow_dispatch' || github.event_name == 'release' }}" >> "$GITHUB_OUTPUT" + force-filters: | + - '.github/workflows/docker.yml' + - '.github/workflows/multi-runner-build.yml' + - '.github/actions/image-build' + force-events: 'workflow_dispatch,release' retag_ml: name: Re-Tag ML @@ -53,14 +46,14 @@ jobs: permissions: contents: read packages: write - if: ${{ needs.pre-job.outputs.should_run_ml == 'false' && !github.event.pull_request.head.repo.fork }} + if: ${{ fromJSON(needs.pre-job.outputs.should_run).machine-learning == false && !github.event.pull_request.head.repo.fork }} runs-on: ubuntu-latest strategy: matrix: suffix: ['', '-cuda', '-rocm', '-openvino', '-armnn', '-rknn'] steps: - name: Login to GitHub Container Registry - uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0 + uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: registry: ghcr.io username: ${{ github.repository_owner }} @@ -82,14 +75,14 @@ jobs: permissions: contents: read packages: write - if: ${{ needs.pre-job.outputs.should_run_server == 'false' && !github.event.pull_request.head.repo.fork }} + if: ${{ fromJSON(needs.pre-job.outputs.should_run).server == false && !github.event.pull_request.head.repo.fork }} runs-on: ubuntu-latest strategy: matrix: suffix: [''] steps: - name: Login to GitHub Container Registry - uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0 + uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: registry: ghcr.io username: ${{ github.repository_owner }} @@ -108,7 +101,7 @@ jobs: machine-learning: name: Build and Push ML needs: pre-job - if: ${{ needs.pre-job.outputs.should_run_ml == 'true' }} + if: ${{ fromJSON(needs.pre-job.outputs.should_run).machine-learning == true }} strategy: fail-fast: false matrix: @@ -131,7 +124,7 @@ jobs: tag-suffix: '-rocm' platforms: linux/amd64 runner-mapping: '{"linux/amd64": "mich"}' - uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@129aeda75a450666ce96e8bc8126652e717917a7 # multi-runner-build-workflow-0.1.1 + uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@946acac326940f8badf09ccf591d9cb345d6a689 # multi-runner-build-workflow-v0.2.1 permissions: contents: read actions: read @@ -153,8 +146,8 @@ jobs: server: name: Build and Push Server needs: pre-job - if: ${{ needs.pre-job.outputs.should_run_server == 'true' }} - uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@129aeda75a450666ce96e8bc8126652e717917a7 # multi-runner-build-workflow-0.1.1 + if: ${{ fromJSON(needs.pre-job.outputs.should_run).server == true }} + uses: immich-app/devtools/.github/workflows/multi-runner-build.yml@946acac326940f8badf09ccf591d9cb345d6a689 # multi-runner-build-workflow-v0.2.1 permissions: contents: read actions: read diff --git a/.github/workflows/docs-build.yml b/.github/workflows/docs-build.yml index 2514ee8639..1a29bebe47 100644 --- a/.github/workflows/docs-build.yml +++ b/.github/workflows/docs-build.yml @@ -18,32 +18,28 @@ jobs: permissions: contents: read outputs: - should_run: ${{ steps.found_paths.outputs.docs == 'true' || steps.found_paths.outputs.open-api == 'true' || steps.should_force.outputs.should_force == 'true' }} + should_run: ${{ steps.check.outputs.should_run }} steps: - - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - with: - persist-credentials: false - - id: found_paths - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + - name: Check what should run + id: check + uses: immich-app/devtools/actions/pre-job@5f91b52dfbb92b8d96ca411ab59c896cd59714ca # pre-job-action-v1.1.0 with: filters: | docs: - 'docs/**' - workflow: - - '.github/workflows/docs-build.yml' open-api: - 'open-api/immich-openapi-specs.json' - - name: Check if we should force jobs to run - id: should_force - run: echo "should_force=${{ steps.found_paths.outputs.workflow == 'true' || github.event_name == 'release' || github.ref_name == 'main' }}" >> "$GITHUB_OUTPUT" + force-filters: | + - '.github/workflows/docs-build.yml' + force-events: 'release' + force-branches: 'main' build: name: Docs Build needs: pre-job permissions: contents: read - if: ${{ needs.pre-job.outputs.should_run == 'true' }} + if: ${{ fromJSON(needs.pre-job.outputs.should_run).docs == true }} runs-on: ubuntu-latest defaults: run: @@ -51,7 +47,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false @@ -59,7 +55,7 @@ jobs: uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: './docs/.nvmrc' cache: 'pnpm' diff --git a/.github/workflows/docs-deploy.yml b/.github/workflows/docs-deploy.yml index c05121ad70..6643c5abfd 100644 --- a/.github/workflows/docs-deploy.yml +++ b/.github/workflows/docs-deploy.yml @@ -20,7 +20,7 @@ jobs: run: echo 'The triggering workflow did not succeed' && exit 1 - name: Get artifact id: get-artifact - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: | let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ @@ -38,7 +38,7 @@ jobs: return { found: true, id: matchArtifact.id }; - name: Determine deploy parameters id: parameters - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: HEAD_SHA: ${{ github.event.workflow_run.head_sha }} with: @@ -108,13 +108,13 @@ jobs: if: ${{ fromJson(needs.checks.outputs.artifact).found && fromJson(needs.checks.outputs.parameters).shouldDeploy }} steps: - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - name: Load parameters id: parameters - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: PARAM_JSON: ${{ needs.checks.outputs.parameters }} with: @@ -125,7 +125,7 @@ jobs: core.setOutput("shouldDeploy", parameters.shouldDeploy); - name: Download artifact - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: ARTIFACT_JSON: ${{ needs.checks.outputs.artifact }} with: diff --git a/.github/workflows/docs-destroy.yml b/.github/workflows/docs-destroy.yml index 37653c0990..c4b9a9fff3 100644 --- a/.github/workflows/docs-destroy.yml +++ b/.github/workflows/docs-destroy.yml @@ -14,7 +14,7 @@ jobs: pull-requests: write steps: - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false diff --git a/.github/workflows/fix-format.yml b/.github/workflows/fix-format.yml index 4c7c57e4f0..1c57828b0c 100644 --- a/.github/workflows/fix-format.yml +++ b/.github/workflows/fix-format.yml @@ -16,20 +16,23 @@ jobs: steps: - name: Generate a token id: generate-token - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 with: app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }} private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }} - name: 'Checkout' - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: ref: ${{ github.event.pull_request.head.ref }} token: ${{ steps.generate-token.outputs.token }} persist-credentials: true + - name: Setup pnpm + uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 + - name: Setup Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: './server/.nvmrc' cache: 'pnpm' @@ -45,7 +48,7 @@ jobs: message: 'chore: fix formatting' - name: Remove label - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 if: always() with: script: | diff --git a/.github/workflows/merge-translations.yml b/.github/workflows/merge-translations.yml index c4167efa8a..d494460320 100644 --- a/.github/workflows/merge-translations.yml +++ b/.github/workflows/merge-translations.yml @@ -1,8 +1,20 @@ name: Merge translations on: - workflow_call: workflow_dispatch: + workflow_call: + secrets: + PUSH_O_MATIC_APP_ID: + required: true + PUSH_O_MATIC_APP_KEY: + required: true + WEBLATE_TOKEN: + required: true + inputs: + skip: + description: 'Skip translations' + required: false + type: boolean permissions: {} @@ -18,65 +30,80 @@ jobs: steps: - name: Find translation PR id: find_pr + if: ${{ inputs.skip != true }} env: GH_TOKEN: ${{ github.token }} run: | set -euo pipefail - gh pr list --repo $GITHUB_REPOSITORY --author weblate --json number,mergeable | read PR + PR=$(gh pr list --repo $GITHUB_REPOSITORY --author weblate --json number,mergeable) echo "$PR" - echo "$PR" | jq ' + PR_NUMBER=$(echo "$PR" | jq ' if length == 1 then .[0].number else error("Expected exactly 1 entry, got \(length)") end - ' 2>&1 | read PR_NUMBER || exit 1 + ' 2>&1) || exit 1 echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT echo "Selected PR $PR_NUMBER" - echo "$PR" | jq -e '.[0].mergeable == "MERGEABLE"' || { echo "PR is not mergeable" ; exit 1 } + if ! echo "$PR" | jq -e '.[0].mergeable == "MERGEABLE"'; then + echo "PR is not mergeable" + exit 1 + fi - name: Generate a token id: generate_token - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + if: ${{ inputs.skip != true }} + uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 with: app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }} private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }} - name: Lock weblate + if: ${{ inputs.skip != true }} env: WEBLATE_TOKEN: ${{ secrets.WEBLATE_TOKEN }} run: | - curl -X POST -H "Authorization: Token $WEBLATE_TOKEN" "$WEBLATE_HOST/api/components/$WEBLATE_COMPONENT/lock/" -d lock=true + curl --fail-with-body -X POST -H "Authorization: Token $WEBLATE_TOKEN" "$WEBLATE_HOST/api/components/$WEBLATE_COMPONENT/lock/" -d lock=true - name: Commit translations + if: ${{ inputs.skip != true }} env: WEBLATE_TOKEN: ${{ secrets.WEBLATE_TOKEN }} run: | - curl -X POST -H "Authorization: Token $WEBLATE_TOKEN" "$WEBLATE_HOST/api/components/$WEBLATE_COMPONENT/repository/" -d operation=commit - curl -X POST -H "Authorization: Token $WEBLATE_TOKEN" "$WEBLATE_HOST/api/components/$WEBLATE_COMPONENT/repository/" -d operation=push + curl --fail-with-body -X POST -H "Authorization: Token $WEBLATE_TOKEN" "$WEBLATE_HOST/api/components/$WEBLATE_COMPONENT/repository/" -d operation=commit + curl --fail-with-body -X POST -H "Authorization: Token $WEBLATE_TOKEN" "$WEBLATE_HOST/api/components/$WEBLATE_COMPONENT/repository/" -d operation=push - name: Merge PR + id: merge_pr + if: ${{ inputs.skip != true }} env: GH_TOKEN: ${{ steps.generate_token.outputs.token }} PR_NUMBER: ${{ steps.find_pr.outputs.PR_NUMBER }} run: | - gh api -X POST "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/reviews" --field event='APPROVE' --field body='Automatically merging translations PR' \ - | jq '.id' | read REVIEW_ID + set -euo pipefail + + REVIEW_ID=$(gh api -X POST "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/reviews" --field event='APPROVE' --field body='Automatically merging translations PR' \ + | jq '.id') echo "REVIEW_ID=$REVIEW_ID" >> $GITHUB_OUTPUT gh pr merge "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --auto --squash - name: Wait for PR to merge + if: ${{ inputs.skip != true }} env: GH_TOKEN: ${{ steps.generate_token.outputs.token }} PR_NUMBER: ${{ steps.find_pr.outputs.PR_NUMBER }} REVIEW_ID: ${{ steps.merge_pr.outputs.REVIEW_ID }} run: | - for i in {1..10}; do - if gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --json merged | jq -e '.merged == true'; then + # So we clean up no matter what + set +e + + for i in {1..100}; do + if gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --json state | jq -e '.state == "MERGED"'; then echo "PR merged" exit 0 else @@ -90,7 +117,12 @@ jobs: exit 1 - name: Unlock weblate + if: ${{ inputs.skip != true }} env: WEBLATE_TOKEN: ${{ secrets.WEBLATE_TOKEN }} run: | - curl -X POST -H "Authorization: Token $WEBLATE_TOKEN" "$WEBLATE_HOST/api/components/$WEBLATE_COMPONENT/lock/" -d lock=false + curl --fail-with-body -X POST -H "Authorization: Token $WEBLATE_TOKEN" "$WEBLATE_HOST/api/components/$WEBLATE_COMPONENT/lock/" -d lock=false + + - name: Report success + run: | + echo "Workflow completed successfully (or was skipped)" diff --git a/.github/workflows/org-checks.yml b/.github/workflows/org-checks.yml deleted file mode 100644 index 9781dc3b83..0000000000 --- a/.github/workflows/org-checks.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: Org Checks - -on: - pull_request_review: - pull_request: - -jobs: - check-approvals: - name: Check for Team/Admin Review - uses: immich-app/devtools/.github/workflows/required-approval.yml@main - permissions: - pull-requests: read - contents: read diff --git a/.github/workflows/org-pr-require-conventional-commit.yml b/.github/workflows/org-pr-require-conventional-commit.yml new file mode 100644 index 0000000000..5e5f84ef39 --- /dev/null +++ b/.github/workflows/org-pr-require-conventional-commit.yml @@ -0,0 +1,12 @@ +name: PR Conventional Commit + +on: + pull_request: + types: [opened, synchronize, reopened, edited] + +jobs: + validate-pr-title: + name: Validate PR Title (conventional commit) + uses: immich-app/devtools/.github/workflows/shared-pr-require-conventional-commit.yml@main + permissions: + pull-requests: write diff --git a/.github/workflows/org-zizmor.yml b/.github/workflows/org-zizmor.yml new file mode 100644 index 0000000000..8510fd85b4 --- /dev/null +++ b/.github/workflows/org-zizmor.yml @@ -0,0 +1,15 @@ +name: Zizmor + +on: + pull_request: + push: + branches: [main] + +jobs: + zizmor: + name: Zizmor + uses: immich-app/devtools/.github/workflows/shared-zizmor.yml@main + permissions: + actions: read + contents: read + security-events: write diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml index ad73c78cf8..af92a3e215 100644 --- a/.github/workflows/pr-labeler.yml +++ b/.github/workflows/pr-labeler.yml @@ -11,4 +11,4 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5.0.0 + - uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1 diff --git a/.github/workflows/pr-require-conventional-commit.yml b/.github/workflows/pr-require-conventional-commit.yml deleted file mode 100644 index 78ba77495c..0000000000 --- a/.github/workflows/pr-require-conventional-commit.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: PR Conventional Commit Validation - -on: - pull_request: - types: [opened, synchronize, reopened, edited] - -permissions: {} - -jobs: - validate-pr-title: - runs-on: ubuntu-latest - permissions: - pull-requests: write - steps: - - name: PR Conventional Commit Validation - uses: ytanikin/PRConventionalCommits@b628c5a234cc32513014b7bfdd1e47b532124d98 # 1.3.0 - with: - task_types: '["feat","fix","docs","test","ci","refactor","perf","chore","revert"]' - add_label: 'false' diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index add0ba7ae4..a6fa5c802f 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -10,12 +10,17 @@ on: type: choice options: - 'false' + - major - minor - patch mobileBump: description: 'Bump mobile build number' required: false type: boolean + skipTranslations: + description: 'Skip translations' + required: false + type: boolean concurrency: group: ${{ github.workflow }}-${{ github.ref }}-root @@ -26,6 +31,8 @@ permissions: {} jobs: merge_translations: uses: ./.github/workflows/merge-translations.yml + with: + skip: ${{ inputs.skipTranslations }} permissions: pull-requests: write secrets: @@ -35,31 +42,33 @@ jobs: bump_version: runs-on: ubuntu-latest + needs: [merge_translations] outputs: ref: ${{ steps.push-tag.outputs.commit_long_sha }} permissions: {} # No job-level permissions are needed because it uses the app-token steps: - name: Generate a token id: generate-token - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 with: app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }} private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }} - name: Checkout - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: token: ${{ steps.generate-token.outputs.token }} persist-credentials: true + ref: main - name: Install uv - uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 + uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0 - name: Setup pnpm uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: './server/.nvmrc' cache: 'pnpm' @@ -102,24 +111,24 @@ jobs: steps: - name: Generate a token id: generate-token - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 with: app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }} private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }} - name: Checkout - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: token: ${{ steps.generate-token.outputs.token }} persist-credentials: false - name: Download APK - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 with: name: release-apk-signed - name: Create draft release - uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8 # v2.3.2 + uses: softprops/action-gh-release@aec2ec56f94eb8180ceec724245f64ef008b89f5 # v2.4.0 with: draft: true tag_name: ${{ env.IMMICH_VERSION }} diff --git a/.github/workflows/preview-label.yaml b/.github/workflows/preview-label.yaml index 3ab9fd267f..594214f820 100644 --- a/.github/workflows/preview-label.yaml +++ b/.github/workflows/preview-label.yaml @@ -24,7 +24,7 @@ jobs: permissions: pull-requests: write steps: - - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: | github.rest.issues.removeLabel({ diff --git a/.github/workflows/sdk.yml b/.github/workflows/sdk.yml index 460e7da4a7..a0d89be598 100644 --- a/.github/workflows/sdk.yml +++ b/.github/workflows/sdk.yml @@ -16,7 +16,7 @@ jobs: run: working-directory: ./open-api/typescript-sdk steps: - - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false @@ -24,7 +24,7 @@ jobs: uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 # Setup .npmrc file to publish to npm - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: './open-api/typescript-sdk/.nvmrc' registry-url: 'https://registry.npmjs.org' @@ -35,6 +35,6 @@ jobs: - name: Build run: pnpm build - name: Publish - run: pnpm publish + run: pnpm publish --no-git-checks env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml index d9b8c1fc0d..3e7223be74 100644 --- a/.github/workflows/static_analysis.yml +++ b/.github/workflows/static_analysis.yml @@ -17,28 +17,23 @@ jobs: permissions: contents: read outputs: - should_run: ${{ steps.found_paths.outputs.mobile == 'true' || steps.should_force.outputs.should_force == 'true' }} + should_run: ${{ steps.check.outputs.should_run }} steps: - - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - with: - persist-credentials: false - - id: found_paths - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + - name: Check what should run + id: check + uses: immich-app/devtools/actions/pre-job@5f91b52dfbb92b8d96ca411ab59c896cd59714ca # pre-job-action-v1.1.0 with: filters: | mobile: - 'mobile/**' - workflow: - - '.github/workflows/static_analysis.yml' - - name: Check if we should force jobs to run - id: should_force - run: echo "should_force=${{ steps.found_paths.outputs.workflow == 'true' || github.event_name == 'release' }}" >> "$GITHUB_OUTPUT" + force-filters: | + - '.github/workflows/static_analysis.yml' + force-events: 'workflow_dispatch,release' mobile-dart-analyze: name: Run Dart Code Analysis needs: pre-job - if: ${{ needs.pre-job.outputs.should_run == 'true' }} + if: ${{ fromJSON(needs.pre-job.outputs.should_run).mobile == true }} runs-on: ubuntu-latest permissions: contents: read @@ -47,7 +42,7 @@ jobs: working-directory: ./mobile steps: - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false @@ -100,36 +95,10 @@ jobs: - name: Run dart format run: make format - - name: Run dart custom_lint - run: dart run custom_lint + # TODO: Re-enable after upgrading custom_lint + # - name: Run dart custom_lint + # run: dart run custom_lint # TODO: Use https://github.com/CQLabs/dcm-action - name: Run DCM run: dcm analyze lib --fatal-style --fatal-warnings - - zizmor: - name: zizmor - runs-on: ubuntu-latest - permissions: - security-events: write - contents: read - actions: read - steps: - - name: Checkout repository - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - with: - persist-credentials: false - - - name: Install the latest version of uv - uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - - - 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@df559355d593797519d70b90fc8edd5db049e7a2 # v3.29.9 - with: - sarif_file: results.sarif - category: zizmor diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e3d2c9b0dc..3ed57a59ba 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,23 +14,11 @@ jobs: permissions: contents: read outputs: - should_run_i18n: ${{ steps.found_paths.outputs.i18n == 'true' || steps.should_force.outputs.should_force == 'true' }} - should_run_web: ${{ steps.found_paths.outputs.web == 'true' || steps.should_force.outputs.should_force == 'true' }} - should_run_server: ${{ steps.found_paths.outputs.server == 'true' || steps.should_force.outputs.should_force == 'true' }} - should_run_cli: ${{ steps.found_paths.outputs.cli == 'true' || steps.should_force.outputs.should_force == 'true' }} - should_run_e2e: ${{ steps.found_paths.outputs.e2e == 'true' || steps.should_force.outputs.should_force == 'true' }} - should_run_mobile: ${{ steps.found_paths.outputs.mobile == 'true' || steps.should_force.outputs.should_force == 'true' }} - should_run_ml: ${{ steps.found_paths.outputs.machine-learning == 'true' || steps.should_force.outputs.should_force == 'true' }} - should_run_e2e_web: ${{ steps.found_paths.outputs.e2e == 'true' || steps.found_paths.outputs.web == 'true' || steps.should_force.outputs.should_force == 'true' }} - should_run_e2e_server_cli: ${{ steps.found_paths.outputs.e2e == 'true' || steps.found_paths.outputs.server == 'true' || steps.found_paths.outputs.cli == 'true' || steps.should_force.outputs.should_force == 'true' }} - should_run_.github: ${{ steps.found_paths.outputs['.github'] == 'true' || steps.should_force.outputs.should_force == 'true' }} # redundant to have should_force but if someone changes the trigger then this won't have to be changed + should_run: ${{ steps.check.outputs.should_run }} steps: - - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - with: - persist-credentials: false - - id: found_paths - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + - name: Check what should run + id: check + uses: immich-app/devtools/actions/pre-job@5f91b52dfbb92b8d96ca411ab59c896cd59714ca # pre-job-action-v1.1.0 with: filters: | i18n: @@ -50,17 +38,16 @@ jobs: - 'mobile/**' machine-learning: - 'machine-learning/**' - workflow: - - '.github/workflows/test.yml' .github: - '.github/**' - - name: Check if we should force jobs to run - id: should_force - run: echo "should_force=${{ steps.found_paths.outputs.workflow == 'true' || github.event_name == 'workflow_dispatch' }}" >> "$GITHUB_OUTPUT" + force-filters: | + - '.github/workflows/test.yml' + force-events: 'workflow_dispatch' + server-unit-tests: name: Test & Lint Server needs: pre-job - if: ${{ needs.pre-job.outputs.should_run_server == 'true' }} + if: ${{ fromJSON(needs.pre-job.outputs.should_run).server == true }} runs-on: ubuntu-latest permissions: contents: read @@ -69,13 +56,13 @@ jobs: working-directory: ./server steps: - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - name: Setup pnpm uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: './server/.nvmrc' cache: 'pnpm' @@ -97,7 +84,7 @@ jobs: cli-unit-tests: name: Unit Test CLI needs: pre-job - if: ${{ needs.pre-job.outputs.should_run_cli == 'true' }} + if: ${{ fromJSON(needs.pre-job.outputs.should_run).cli == true }} runs-on: ubuntu-latest permissions: contents: read @@ -106,13 +93,13 @@ jobs: working-directory: ./cli steps: - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - name: Setup pnpm uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: './cli/.nvmrc' cache: 'pnpm' @@ -137,7 +124,7 @@ jobs: cli-unit-tests-win: name: Unit Test CLI (Windows) needs: pre-job - if: ${{ needs.pre-job.outputs.should_run_cli == 'true' }} + if: ${{ fromJSON(needs.pre-job.outputs.should_run).cli == true }} runs-on: windows-latest permissions: contents: read @@ -146,13 +133,13 @@ jobs: working-directory: ./cli steps: - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - name: Setup pnpm uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: './cli/.nvmrc' cache: 'pnpm' @@ -172,7 +159,7 @@ jobs: web-lint: name: Lint Web needs: pre-job - if: ${{ needs.pre-job.outputs.should_run_web == 'true' }} + if: ${{ fromJSON(needs.pre-job.outputs.should_run).web == true }} runs-on: mich permissions: contents: read @@ -181,13 +168,13 @@ jobs: working-directory: ./web steps: - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - name: Setup pnpm uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: './web/.nvmrc' cache: 'pnpm' @@ -198,7 +185,7 @@ jobs: - name: Run pnpm install run: pnpm rebuild && pnpm install --frozen-lockfile - name: Run linter - run: pnpm lint:p + run: pnpm lint if: ${{ !cancelled() }} - name: Run formatter run: pnpm format @@ -209,7 +196,7 @@ jobs: web-unit-tests: name: Test Web needs: pre-job - if: ${{ needs.pre-job.outputs.should_run_web == 'true' }} + if: ${{ fromJSON(needs.pre-job.outputs.should_run).web == true }} runs-on: ubuntu-latest permissions: contents: read @@ -218,13 +205,13 @@ jobs: working-directory: ./web steps: - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - name: Setup pnpm uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: './web/.nvmrc' cache: 'pnpm' @@ -243,19 +230,19 @@ jobs: i18n-tests: name: Test i18n needs: pre-job - if: ${{ needs.pre-job.outputs.should_run_i18n == 'true' }} + if: ${{ fromJSON(needs.pre-job.outputs.should_run).i18n == true }} runs-on: ubuntu-latest permissions: contents: read steps: - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - name: Setup pnpm uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: './web/.nvmrc' cache: 'pnpm' @@ -281,7 +268,7 @@ jobs: e2e-tests-lint: name: End-to-End Lint needs: pre-job - if: ${{ needs.pre-job.outputs.should_run_e2e == 'true' }} + if: ${{ fromJSON(needs.pre-job.outputs.should_run).e2e == true }} runs-on: ubuntu-latest permissions: contents: read @@ -290,13 +277,13 @@ jobs: working-directory: ./e2e steps: - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - name: Setup pnpm uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: './e2e/.nvmrc' cache: 'pnpm' @@ -320,7 +307,7 @@ jobs: server-medium-tests: name: Medium Tests (Server) needs: pre-job - if: ${{ needs.pre-job.outputs.should_run_server == 'true' }} + if: ${{ fromJSON(needs.pre-job.outputs.should_run).server == true }} runs-on: ubuntu-latest permissions: contents: read @@ -329,13 +316,13 @@ jobs: working-directory: ./server steps: - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - name: Setup pnpm uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: './server/.nvmrc' cache: 'pnpm' @@ -348,7 +335,7 @@ jobs: e2e-tests-server-cli: name: End-to-End Tests (Server & CLI) needs: pre-job - if: ${{ needs.pre-job.outputs.should_run_e2e_server_cli == 'true' }} + if: ${{ fromJSON(needs.pre-job.outputs.should_run).e2e == true || fromJSON(needs.pre-job.outputs.should_run).server == true || fromJSON(needs.pre-job.outputs.should_run).cli == true }} runs-on: ${{ matrix.runner }} permissions: contents: read @@ -360,14 +347,14 @@ jobs: runner: [ubuntu-latest, ubuntu-24.04-arm] steps: - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false submodules: 'recursive' - name: Setup pnpm uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: './e2e/.nvmrc' cache: 'pnpm' @@ -396,7 +383,7 @@ jobs: e2e-tests-web: name: End-to-End Tests (Web) needs: pre-job - if: ${{ needs.pre-job.outputs.should_run_e2e_web == 'true' }} + if: ${{ fromJSON(needs.pre-job.outputs.should_run).e2e == true || fromJSON(needs.pre-job.outputs.should_run).web == true }} runs-on: ${{ matrix.runner }} permissions: contents: read @@ -408,14 +395,14 @@ jobs: runner: [ubuntu-latest, ubuntu-24.04-arm] steps: - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false submodules: 'recursive' - name: Setup pnpm uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: './e2e/.nvmrc' cache: 'pnpm' @@ -449,12 +436,12 @@ jobs: mobile-unit-tests: name: Unit Test Mobile needs: pre-job - if: ${{ needs.pre-job.outputs.should_run_mobile == 'true' }} + if: ${{ fromJSON(needs.pre-job.outputs.should_run).mobile == true }} runs-on: ubuntu-latest permissions: contents: read steps: - - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - name: Setup Flutter SDK @@ -471,7 +458,7 @@ jobs: ml-unit-tests: name: Unit Test ML needs: pre-job - if: ${{ needs.pre-job.outputs.should_run_ml == 'true' }} + if: ${{ fromJSON(needs.pre-job.outputs.should_run).machine-learning == true }} runs-on: ubuntu-latest permissions: contents: read @@ -479,12 +466,12 @@ jobs: run: working-directory: ./machine-learning steps: - - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - name: Install uv - uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0 + - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 # TODO: add caching when supported (https://github.com/actions/setup-python/pull/818) # with: # python-version: 3.11 @@ -507,7 +494,7 @@ jobs: github-files-formatting: name: .github Files Formatting needs: pre-job - if: ${{ needs.pre-job.outputs['should_run_.github'] == 'true' }} + if: ${{ fromJSON(needs.pre-job.outputs.should_run)['.github'] == true }} runs-on: ubuntu-latest permissions: contents: read @@ -516,13 +503,13 @@ jobs: working-directory: ./.github steps: - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - name: Setup pnpm uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: './.github/.nvmrc' cache: 'pnpm' @@ -538,7 +525,7 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - name: Run ShellCheck @@ -553,13 +540,13 @@ jobs: contents: read steps: - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - name: Setup pnpm uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: './server/.nvmrc' cache: 'pnpm' @@ -594,7 +581,7 @@ jobs: contents: read services: postgres: - image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3@sha256:ec713143dca1a426eba2e03707c319e2ec3cc9d304ef767f777f8e297dee820c + image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3@sha256:dbf18b3ffea4a81434c65b71e20d27203baf903a0275f4341e4c16dfd901fd67 env: POSTGRES_PASSWORD: postgres POSTGRES_USER: postgres @@ -608,13 +595,13 @@ jobs: working-directory: ./server steps: - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - name: Setup pnpm uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 - name: Setup Node - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: './server/.nvmrc' cache: 'pnpm' diff --git a/.github/workflows/weblate-lock.yml b/.github/workflows/weblate-lock.yml index 58b11e00cf..d7deb244f9 100644 --- a/.github/workflows/weblate-lock.yml +++ b/.github/workflows/weblate-lock.yml @@ -1,37 +1,44 @@ name: Weblate checks on: - pull_request_review: pull_request: branches: [main] + types: + - opened + - synchronize + - ready_for_review + - auto_merge_enabled + - auto_merge_disabled permissions: {} +env: + BOT_NAME: immich-push-o-matic + jobs: pre-job: runs-on: ubuntu-latest permissions: contents: read outputs: - should_run: ${{ steps.found_paths.outputs.i18n == 'true' }} + should_run: ${{ steps.check.outputs.should_run }} steps: - - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - with: - persist-credentials: false - - id: found_paths - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + - name: Check what should run + id: check + uses: immich-app/devtools/actions/pre-job@5f91b52dfbb92b8d96ca411ab59c896cd59714ca # pre-job-action-v1.1.0 with: filters: | i18n: - 'i18n/!(en)**\.json' + exclude-branches: 'chore/translations' + skip-force-logic: 'true' enforce-lock: name: Check Weblate Lock needs: [pre-job] runs-on: ubuntu-latest permissions: {} - if: ${{ needs.pre-job.outputs.should_run == 'true' }} + if: ${{ fromJSON(needs.pre-job.outputs.should_run).i18n == true }} steps: - name: Bot review status env: @@ -39,7 +46,7 @@ jobs: GH_TOKEN: ${{ github.token }} run: | # Then check for APPROVED by the bot, if absent fail - gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --json reviews | jq -e '.reviews | map(select(.author.login == "github-actions[bot]" and .state == "APPROVED")) | length > 0' \ + gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --json reviews | jq -e '.reviews | map(select(.author.login == env.BOT_NAME and .state == "APPROVED")) | length > 0' \ || (echo "The push-o-matic bot has not approved this PR yet" && exit 1) success-check-lock: diff --git a/.gitignore b/.gitignore index af85d96c02..3220701cc6 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ mobile/libisar.dylib mobile/openapi/test mobile/openapi/doc mobile/openapi/.openapi-generator/FILES +mobile/ios/build open-api/typescript-sdk/build mobile/android/fastlane/report.xml @@ -25,3 +26,5 @@ mobile/ios/fastlane/report.xml vite.config.js.timestamp-* .pnpm-store +.devcontainer/library +.devcontainer/.env* diff --git a/.vscode/launch.json b/.vscode/launch.json index 0cc9b256ca..9ed2bb77b8 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -18,6 +18,20 @@ "name": "Immich Workers", "remoteRoot": "/usr/src/app/server", "localRoot": "${workspaceFolder}/server" + }, + { + "type": "node", + "request": "launch", + "name": "Immich CLI", + "program": "${workspaceFolder}/cli/dist/index.js", + "args": ["upload", "--help"], + "runtimeArgs": ["--enable-source-maps"], + "console": "integratedTerminal", + "resolveSourceMapLocations": ["${workspaceFolder}/cli/dist/**/*.js.map"], + "sourceMaps": true, + "outFiles": ["${workspaceFolder}/cli/dist/**/*.js"], + "skipFiles": ["/**"], + "preLaunchTask": "Build Immich CLI" } ] } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 119d6a961b..478a46b4bd 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -5,6 +5,7 @@ "label": "Fix Permissions, Install Dependencies", "type": "shell", "command": "[ -f /immich-devcontainer/container-start.sh ] && /immich-devcontainer/container-start.sh || exit 0", + "isBackground": true, "presentation": { "echo": true, "reveal": "always", @@ -25,6 +26,7 @@ "dependsOn": ["Fix Permissions, Install Dependencies"], "type": "shell", "command": "[ -f /immich-devcontainer/container-start-backend.sh ] && /immich-devcontainer/container-start-backend.sh || exit 0", + "isBackground": true, "presentation": { "echo": true, "reveal": "always", @@ -45,6 +47,7 @@ "dependsOn": ["Fix Permissions, Install Dependencies"], "type": "shell", "command": "[ -f /immich-devcontainer/container-start-frontend.sh ] && /immich-devcontainer/container-start-frontend.sh || exit 0", + "isBackground": true, "presentation": { "echo": true, "reveal": "always", @@ -67,6 +70,11 @@ "runOn": "folderOpen" }, "problemMatcher": [] + }, + { + "label": "Build Immich CLI", + "type": "shell", + "command": "pnpm --filter cli build:dev" } ] } diff --git a/CODEOWNERS b/CODEOWNERS index cd61814ff8..8759cf2357 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,5 +1,7 @@ /.github/ @bo0tzz /docker/ @bo0tzz /server/ @danieldietzler +/web/ @danieldietzler /machine-learning/ @mertalev /e2e/ @danieldietzler +/mobile/ @shenlong-tanwen diff --git a/Makefile b/Makefile index 517e8d7523..fc99170676 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,13 @@ -dev: prepare-volumes +dev: @trap 'make dev-down' EXIT; COMPOSE_BAKE=true docker compose -f ./docker/docker-compose.dev.yml up --remove-orphans dev-down: docker compose -f ./docker/docker-compose.dev.yml down --remove-orphans -dev-update: prepare-volumes +dev-update: @trap 'make dev-down' EXIT; COMPOSE_BAKE=true docker compose -f ./docker/docker-compose.dev.yml up --build -V --remove-orphans -dev-scale: prepare-volumes +dev-scale: @trap 'make dev-down' EXIT; COMPOSE_BAKE=true docker compose -f ./docker/docker-compose.dev.yml up --build -V --scale immich-server=3 --remove-orphans dev-docs: @@ -23,7 +23,7 @@ e2e-update: e2e-down: docker compose -f ./e2e/docker-compose.yml down --remove-orphans -prod: +prod: @trap 'make prod-down' EXIT; COMPOSE_BAKE=true docker compose -f ./docker/docker-compose.prod.yml up --build -V --remove-orphans prod-down: @@ -33,16 +33,16 @@ prod-scale: @trap 'make prod-down' EXIT; COMPOSE_BAKE=true docker compose -f ./docker/docker-compose.prod.yml up --build -V --scale immich-server=3 --scale immich-microservices=3 --remove-orphans .PHONY: open-api -open-api: prepare-volumes +open-api: cd ./open-api && bash ./bin/generate-open-api.sh -open-api-dart: prepare-volumes +open-api-dart: cd ./open-api && bash ./bin/generate-open-api.sh dart -open-api-typescript: prepare-volumes +open-api-typescript: cd ./open-api && bash ./bin/generate-open-api.sh typescript -sql: prepare-volumes +sql: pnpm --filter immich run sync:sql attach-server: @@ -68,34 +68,6 @@ VOLUME_DIRS = \ # Include .env file if it exists -include docker/.env -# Helper function to chown, on error suggest remediation and exit -define safe_chown - if chown $(2) $(or $(UID),1000):$(or $(GID),1000) "$(1)" 2>/dev/null; then \ - true; \ - else \ - STATUS=$$?; echo "Exit code: $$STATUS $(1)"; \ - echo "$$STATUS $(1)"; \ - echo "Permission denied when changing owner of volumes and upload location. Try running 'sudo make prepare-volumes' first."; \ - exit 1; \ - fi; -endef -# create empty directories and chown -prepare-volumes: - @$(foreach dir,$(VOLUME_DIRS),mkdir -p $(dir);) - @$(foreach dir,$(VOLUME_DIRS),$(call safe_chown,$(dir),-R)) -ifneq ($(UPLOAD_LOCATION),) -ifeq ($(filter /%,$(UPLOAD_LOCATION)),) - @mkdir -p "docker/$(UPLOAD_LOCATION)/photos/upload" - @$(call safe_chown,docker/$(UPLOAD_LOCATION),) - @$(call safe_chown,docker/$(UPLOAD_LOCATION)/photos,-R) -else - @mkdir -p "$(UPLOAD_LOCATION)/photos/upload" - @$(call safe_chown,$(UPLOAD_LOCATION),) - @$(call safe_chown,$(UPLOAD_LOCATION)/photos,-R) -endif -endif - - MODULES = e2e server web cli sdk docs .github # directory to package name mapping function @@ -119,8 +91,6 @@ format-%: pnpm --filter $(call map-package,$*) run format:fix lint-%: pnpm --filter $(call map-package,$*) run lint:fix -lint-web: - pnpm --filter $(call map-package,$*) run lint:p check-%: pnpm --filter $(call map-package,$*) run check check-web: diff --git a/README.md b/README.md index 459cda481c..b540408475 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,8 @@ Deutsch Nederlands TÃŧrkçe - 中文 + įŽ€äŊ“中文 + æ­ŖéĢ”ä¸­æ–‡ ĐŖĐēŅ€Đ°Ņ—ĐŊҁҌĐēа Đ ŅƒŅŅĐēиК PortuguÃĒs Brasileiro @@ -38,26 +39,25 @@ ā¸ ā¸˛ā¸Šā¸˛āš„ā¸—ā¸ĸ

-## Disclaimer -- âš ī¸ The project is under **very active** development. -- âš ī¸ Expect bugs and breaking changes. -- âš ī¸ **Do not use the app as the only way to store your photos and videos.** -- âš ī¸ Always follow [3-2-1](https://www.backblaze.com/blog/the-3-2-1-backup-strategy/) backup plan for your precious photos and videos! +> [!WARNING] +> âš ī¸ Always follow [3-2-1](https://www.backblaze.com/blog/the-3-2-1-backup-strategy/) backup plan for your precious photos and videos! +> + > [!NOTE] > You can find the main documentation, including installation guides, at https://immich.app/. ## Links -- [Documentation](https://immich.app/docs) -- [About](https://immich.app/docs/overview/introduction) -- [Installation](https://immich.app/docs/install/requirements) +- [Documentation](https://docs.immich.app/) +- [About](https://docs.immich.app/overview/introduction) +- [Installation](https://docs.immich.app/install/requirements) - [Roadmap](https://immich.app/roadmap) - [Demo](#demo) - [Features](#features) -- [Translations](https://immich.app/docs/developer/translations) -- [Contributing](https://immich.app/docs/overview/support-the-project) +- [Translations](https://docs.immich.app/developer/translations) +- [Contributing](https://docs.immich.app/overview/support-the-project) ## Demo @@ -106,7 +106,7 @@ Access the demo [here](https://demo.immich.app). For the mobile app, you can use ## Translations -Read more about translations [here](https://immich.app/docs/developer/translations). +Read more about translations [here](https://docs.immich.app/developer/translations). Translation status diff --git a/cli/.nvmrc b/cli/.nvmrc index e2228113dd..442c7587a9 100644 --- a/cli/.nvmrc +++ b/cli/.nvmrc @@ -1 +1 @@ -22.19.0 +22.20.0 diff --git a/cli/README.md b/cli/README.md index 8fa2ace483..b9d61fce09 100644 --- a/cli/README.md +++ b/cli/README.md @@ -1,30 +1,38 @@ A command-line interface for interfacing with the self-hosted photo manager [Immich](https://immich.app/). -Please see the [Immich CLI documentation](https://immich.app/docs/features/command-line-interface). +Please see the [Immich CLI documentation](https://docs.immich.app/features/command-line-interface). # For developers Before building the CLI, you must build the immich server and the open-api client. To build the server run the following in the server folder: - $ npm install - $ npm run build + $ pnpm install + $ pnpm run build Then, to build the open-api client run the following in the open-api folder: $ ./bin/generate-open-api.sh -To run the Immich CLI from source, run the following in the cli folder: +## Run from build - $ npm install - $ npm run build - $ ts-node . +Go to the cli folder and build it: -You'll need ts-node, the easiest way to install it is to use npm: + $ pnpm install + $ pnpm run build + $ node dist/index.js - $ npm i -g ts-node +## Run and Debug from source (VSCode) + +With VScode you can run and debug the Immich CLI. Go to the launch.json file, find the Immich CLI config and change this with the command you need to debug + +`"args": ["upload", "--help"],` + +replace that for the command of your choice. + +## Install from build You can also build and install the CLI using - $ npm run build - $ npm install -g . + $ pnpm run build + $ pnpm install -g . **** diff --git a/cli/package.json b/cli/package.json index f67d6bc212..f0b5bd5cd1 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,6 +1,6 @@ { "name": "@immich/cli", - "version": "2.2.88", + "version": "2.2.97", "description": "Command Line Interface (CLI) for Immich", "type": "module", "exports": "./dist/index.js", @@ -13,7 +13,6 @@ "cli" ], "devDependencies": { - "@eslint/eslintrc": "^3.1.0", "@eslint/js": "^9.8.0", "@immich/sdk": "file:../open-api/typescript-sdk", "@types/byte-size": "^8.1.0", @@ -21,7 +20,7 @@ "@types/lodash-es": "^4.17.12", "@types/micromatch": "^4.0.9", "@types/mock-fs": "^4.13.1", - "@types/node": "^22.18.0", + "@types/node": "^22.18.8", "@vitest/coverage-v8": "^3.0.0", "byte-size": "^9.0.0", "cli-progress": "^3.12.0", @@ -44,6 +43,7 @@ }, "scripts": { "build": "vite build", + "build:dev": "vite build --sourcemap true", "lint": "eslint \"src/**/*.ts\" --max-warnings 0", "lint:fix": "npm run lint -- --fix", "prepack": "npm run build", @@ -69,6 +69,6 @@ "micromatch": "^4.0.8" }, "volta": { - "node": "22.19.0" + "node": "22.20.0" } } diff --git a/deployment/.env b/deployment/.env new file mode 100644 index 0000000000..f6ce050d29 --- /dev/null +++ b/deployment/.env @@ -0,0 +1,4 @@ +export CLOUDFLARE_ACCOUNT_ID="op://tf/cloudflare/account_id" +export CLOUDFLARE_API_TOKEN="op://tf/cloudflare/api_token" +export TF_STATE_POSTGRES_CONN_STR="op://tf/tf_state/postgres_conn_str" +export TF_VAR_env=$ENVIRONMENT diff --git a/deployment/modules/cloudflare/docs-release/.terraform.lock.hcl b/deployment/modules/cloudflare/docs-release/.terraform.lock.hcl index 90a7bd6259..0869dd28bc 100644 --- a/deployment/modules/cloudflare/docs-release/.terraform.lock.hcl +++ b/deployment/modules/cloudflare/docs-release/.terraform.lock.hcl @@ -2,37 +2,37 @@ # Manual edits may be lost in future updates. provider "registry.opentofu.org/cloudflare/cloudflare" { - version = "4.52.1" - constraints = "4.52.1" + version = "4.52.5" + constraints = "4.52.5" hashes = [ - "h1:2lHvafwGbLdmc9lYkuJFw3nsInaQjRpjX/JfIRKmq/M=", - "h1:596JomwjrtUrOSreq9NNCS+rj70+jOV+0pfja5MXiTI=", - "h1:7mBOA5TVAIt3qAwPXKCtE0RSYeqij9v30mnksuBbpEg=", - "h1:ELVgzh4kHKBCYdL+2A8JjWS0E1snLUN3Mmz3Vo6qSfw=", - "h1:FGGM5yLFf72g3kSXM3LAN64Gf/AkXr5WCmhixgnP+l4=", - "h1:JupkJbQALcIVoMhHImrLeLDsQR1ET7VJLGC7ONxjqGU=", - "h1:KsaE4JNq+1uV1nJsuTcYar/8lyY6zKS5UBEpfYg3wvc=", - "h1:NHZ5RJIzQDLhie/ykl3uI6UPfNQR9Lu5Ti7JPR6X904=", - "h1:NfAuMbn6LQPLDtJhbzO1MX9JMIGLMa8K6CpekvtsuX8=", - "h1:e+vNKokamDsp/kJvFr2pRudzwEz2r49iZ/oSggw+1LY=", - "h1:jnb4VdfNZ79I3yj7Q8x+JmOT+FxbfjjRfrF0dL0yCW8=", - "h1:kmF//O539d7NuHU7qIxDj7Wz4eJmLKFiI5glwQivldU=", - "h1:s6XriaKwOgV4jvKAGPXkrxhhOQxpNU5dceZwi9Z/1k8=", - "h1:wt3WBEBAeSGTlC9OlnTlAALxRiK4SQgLy0KgBIS7qzs=", - "zh:2fb95e1d3229b9b6c704e1a413c7481c60f139780d9641f657b6eb9b633b90f2", - "zh:379c7680983383862236e9e6e720c3114195c40526172188e88d0ffcf50dfe2e", - "zh:55533beb6cfc02d22ffda8cba8027bc2c841bb172cd637ed0d28323d41395f8f", - "zh:5abd70760e4eb1f37a1c307cbd2989ea7c9ba0afb93818c67c1d363a31f75703", - "zh:699f1c8cd66129176fe659ebf0e6337632a8967a28d2630b6ae5948665c0c2ae", - "zh:69c15acd73c451e89de6477059cda2f3ec200b48ae4b9ff3646c4d389fd3205e", - "zh:6e02b687de21b844f8266dff99e93e7c61fc8eb688f4bbb23803caceb251839e", - "zh:7a51d17b87ed87b7bebf2ad9fc7c3a74f16a1b44eee92c779c08eb89258c0496", - "zh:88ad84436837b0f55302f22748505972634e87400d6902260fd6b7ba1610f937", + "h1:+rfzF+16ZcWZWnTyW/p1HHTzYbPKX8Zt2nIFtR/+f+E=", + "h1:18bXaaOSq8MWKuMxo/4y7EB7/i7G90y5QsKHZRmkoDo=", + "h1:4vZVOpKeEQZsF2VrARRZFeL37Ed/gD4rRMtfnvWQres=", + "h1:BZOsTF83QPKXTAaYqxPKzdl1KRjk/L2qbPpFjM0w28A=", + "h1:CDuC+HXLvc1z6wkCRsSDcc/+QENIHEtssYshiWg3opA=", + "h1:DE+YFzLnqSe79pI2R4idRGx5QzLdrA7RXvngTkGfZ30=", + "h1:DfaJwH3Ml4yrRbdAY4AcDVy0QTQk5T3A622TXzS/u2E=", + "h1:EIDXP0W3kgIv2pecrFmqtK/DnlqkyckzBzhxKaXU+4A=", + "h1:EV4kYyaOnwGA0bh/3hU6Ezqnt1PFDxopH7i85e48IzY=", + "h1:M0iXabfzamU+MPDi0G9XACpbacFKMakmM+Z9HZ8HrsM=", + "h1:YWmCbGF/KbsrUzcYVBLscwLizidbp95TDQa0N2qpmVo=", + "h1:cxPcCB5gbrpUO1+IXkQYs1YTY50/0IlApCzGea0cwuQ=", + "h1:g6DldikTV2HXUu9uoeNY5FuLufgaYWF4ufgZg7wq62s=", + "h1:oi/Hrx9pwoQ+Z52CBC+rrowVH387EIj0qvnxQgDeI+0=", + "zh:1a3400cb38863b2585968d1876706bcfc67a148e1318a1d325c6c7704adc999b", + "zh:4c5062cb9e9da1676f06ae92b8370186d98976cc4c7030d3cd76df12af54282a", + "zh:52110f493b5f0587ef77a1cfd1a67001fd4c617b14c6502d732ab47352bdc2f7", + "zh:5aa536f9eaeb43823aaf2aa80e7d39b25ef2b383405ed034aa16a28b446a9238", + "zh:5cc39459a1c6be8a918f17054e4fbba573825ed5597dcada588fe99614d98a5b", + "zh:629ae6a7ba298815131da826474d199312d21cec53a4d5ded4fa56a692e6f072", + "zh:719cc7c75dc1d3eb30c22ff5102a017996d9788b948078c7e1c5b3446aeca661", + "zh:8698635a3ca04383c1e93b21d6963346bdae54d27177a48e4b1435b7f731731c", "zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f", - "zh:8d46c3d9f4f7ad20ac6ef01daa63f4e30a2d16dcb1bb5c7c7ee3dc6be38e9ca1", - "zh:913d64e72a4929dae1d4793e2004f4f9a58b138ea337d9d94fa35cafbf06550a", - "zh:c8d93cf86e2e49f6cec665cfe78b82c144cce15a8b2e30f343385fadd1251849", - "zh:cc4f69397d9bc34a528a5609a024c3a48f54f21616c0008792dd417297add955", - "zh:df99cdb8b064aad35ffea77e645cf6541d0b1b2ebc51b6d26c42031de60ab69e", + "zh:8a9993f1dcadf1dd6ca43b23348abe374605d29945a2fafc07fb3457644e6a54", + "zh:b1b9a1e6bcc24d5863a664a411d2dc906373ae7a2399d2d65548ce7377057852", + "zh:b270184cdeec277218e84b94cb136fead753da717f9b9dc378e51907f3f00bb0", + "zh:dff2bc10071210181726ce270f954995fe42c696e61e2e8f874021fed02521e5", + "zh:e8e87b40b6a87dc097b0fdc20d3f725cec0d82abc9cc3755c1f89f8f6e8b0036", + "zh:ee964a6573d399a5dd22ce328fb38ca1207797a02248f14b2e4913ee390e7803", ] } diff --git a/deployment/modules/cloudflare/docs-release/config.tf b/deployment/modules/cloudflare/docs-release/config.tf index 9dd16d5982..63347cf67e 100644 --- a/deployment/modules/cloudflare/docs-release/config.tf +++ b/deployment/modules/cloudflare/docs-release/config.tf @@ -5,7 +5,7 @@ terraform { required_providers { cloudflare = { source = "cloudflare/cloudflare" - version = "4.52.1" + version = "4.52.5" } } } diff --git a/deployment/modules/cloudflare/docs-release/domain.tf b/deployment/modules/cloudflare/docs-release/domain.tf index 0602045f71..3a6f479a74 100644 --- a/deployment/modules/cloudflare/docs-release/domain.tf +++ b/deployment/modules/cloudflare/docs-release/domain.tf @@ -1,11 +1,11 @@ resource "cloudflare_pages_domain" "immich_app_release_domain" { account_id = var.cloudflare_account_id project_name = data.terraform_remote_state.cloudflare_account.outputs.immich_app_archive_pages_project_name - domain = "immich.app" + domain = "docs.immich.app" } resource "cloudflare_record" "immich_app_release_domain" { - name = "immich.app" + name = "docs.immich.app" proxied = true ttl = 1 type = "CNAME" diff --git a/deployment/modules/cloudflare/docs/.terraform.lock.hcl b/deployment/modules/cloudflare/docs/.terraform.lock.hcl index 90a7bd6259..0869dd28bc 100644 --- a/deployment/modules/cloudflare/docs/.terraform.lock.hcl +++ b/deployment/modules/cloudflare/docs/.terraform.lock.hcl @@ -2,37 +2,37 @@ # Manual edits may be lost in future updates. provider "registry.opentofu.org/cloudflare/cloudflare" { - version = "4.52.1" - constraints = "4.52.1" + version = "4.52.5" + constraints = "4.52.5" hashes = [ - "h1:2lHvafwGbLdmc9lYkuJFw3nsInaQjRpjX/JfIRKmq/M=", - "h1:596JomwjrtUrOSreq9NNCS+rj70+jOV+0pfja5MXiTI=", - "h1:7mBOA5TVAIt3qAwPXKCtE0RSYeqij9v30mnksuBbpEg=", - "h1:ELVgzh4kHKBCYdL+2A8JjWS0E1snLUN3Mmz3Vo6qSfw=", - "h1:FGGM5yLFf72g3kSXM3LAN64Gf/AkXr5WCmhixgnP+l4=", - "h1:JupkJbQALcIVoMhHImrLeLDsQR1ET7VJLGC7ONxjqGU=", - "h1:KsaE4JNq+1uV1nJsuTcYar/8lyY6zKS5UBEpfYg3wvc=", - "h1:NHZ5RJIzQDLhie/ykl3uI6UPfNQR9Lu5Ti7JPR6X904=", - "h1:NfAuMbn6LQPLDtJhbzO1MX9JMIGLMa8K6CpekvtsuX8=", - "h1:e+vNKokamDsp/kJvFr2pRudzwEz2r49iZ/oSggw+1LY=", - "h1:jnb4VdfNZ79I3yj7Q8x+JmOT+FxbfjjRfrF0dL0yCW8=", - "h1:kmF//O539d7NuHU7qIxDj7Wz4eJmLKFiI5glwQivldU=", - "h1:s6XriaKwOgV4jvKAGPXkrxhhOQxpNU5dceZwi9Z/1k8=", - "h1:wt3WBEBAeSGTlC9OlnTlAALxRiK4SQgLy0KgBIS7qzs=", - "zh:2fb95e1d3229b9b6c704e1a413c7481c60f139780d9641f657b6eb9b633b90f2", - "zh:379c7680983383862236e9e6e720c3114195c40526172188e88d0ffcf50dfe2e", - "zh:55533beb6cfc02d22ffda8cba8027bc2c841bb172cd637ed0d28323d41395f8f", - "zh:5abd70760e4eb1f37a1c307cbd2989ea7c9ba0afb93818c67c1d363a31f75703", - "zh:699f1c8cd66129176fe659ebf0e6337632a8967a28d2630b6ae5948665c0c2ae", - "zh:69c15acd73c451e89de6477059cda2f3ec200b48ae4b9ff3646c4d389fd3205e", - "zh:6e02b687de21b844f8266dff99e93e7c61fc8eb688f4bbb23803caceb251839e", - "zh:7a51d17b87ed87b7bebf2ad9fc7c3a74f16a1b44eee92c779c08eb89258c0496", - "zh:88ad84436837b0f55302f22748505972634e87400d6902260fd6b7ba1610f937", + "h1:+rfzF+16ZcWZWnTyW/p1HHTzYbPKX8Zt2nIFtR/+f+E=", + "h1:18bXaaOSq8MWKuMxo/4y7EB7/i7G90y5QsKHZRmkoDo=", + "h1:4vZVOpKeEQZsF2VrARRZFeL37Ed/gD4rRMtfnvWQres=", + "h1:BZOsTF83QPKXTAaYqxPKzdl1KRjk/L2qbPpFjM0w28A=", + "h1:CDuC+HXLvc1z6wkCRsSDcc/+QENIHEtssYshiWg3opA=", + "h1:DE+YFzLnqSe79pI2R4idRGx5QzLdrA7RXvngTkGfZ30=", + "h1:DfaJwH3Ml4yrRbdAY4AcDVy0QTQk5T3A622TXzS/u2E=", + "h1:EIDXP0W3kgIv2pecrFmqtK/DnlqkyckzBzhxKaXU+4A=", + "h1:EV4kYyaOnwGA0bh/3hU6Ezqnt1PFDxopH7i85e48IzY=", + "h1:M0iXabfzamU+MPDi0G9XACpbacFKMakmM+Z9HZ8HrsM=", + "h1:YWmCbGF/KbsrUzcYVBLscwLizidbp95TDQa0N2qpmVo=", + "h1:cxPcCB5gbrpUO1+IXkQYs1YTY50/0IlApCzGea0cwuQ=", + "h1:g6DldikTV2HXUu9uoeNY5FuLufgaYWF4ufgZg7wq62s=", + "h1:oi/Hrx9pwoQ+Z52CBC+rrowVH387EIj0qvnxQgDeI+0=", + "zh:1a3400cb38863b2585968d1876706bcfc67a148e1318a1d325c6c7704adc999b", + "zh:4c5062cb9e9da1676f06ae92b8370186d98976cc4c7030d3cd76df12af54282a", + "zh:52110f493b5f0587ef77a1cfd1a67001fd4c617b14c6502d732ab47352bdc2f7", + "zh:5aa536f9eaeb43823aaf2aa80e7d39b25ef2b383405ed034aa16a28b446a9238", + "zh:5cc39459a1c6be8a918f17054e4fbba573825ed5597dcada588fe99614d98a5b", + "zh:629ae6a7ba298815131da826474d199312d21cec53a4d5ded4fa56a692e6f072", + "zh:719cc7c75dc1d3eb30c22ff5102a017996d9788b948078c7e1c5b3446aeca661", + "zh:8698635a3ca04383c1e93b21d6963346bdae54d27177a48e4b1435b7f731731c", "zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f", - "zh:8d46c3d9f4f7ad20ac6ef01daa63f4e30a2d16dcb1bb5c7c7ee3dc6be38e9ca1", - "zh:913d64e72a4929dae1d4793e2004f4f9a58b138ea337d9d94fa35cafbf06550a", - "zh:c8d93cf86e2e49f6cec665cfe78b82c144cce15a8b2e30f343385fadd1251849", - "zh:cc4f69397d9bc34a528a5609a024c3a48f54f21616c0008792dd417297add955", - "zh:df99cdb8b064aad35ffea77e645cf6541d0b1b2ebc51b6d26c42031de60ab69e", + "zh:8a9993f1dcadf1dd6ca43b23348abe374605d29945a2fafc07fb3457644e6a54", + "zh:b1b9a1e6bcc24d5863a664a411d2dc906373ae7a2399d2d65548ce7377057852", + "zh:b270184cdeec277218e84b94cb136fead753da717f9b9dc378e51907f3f00bb0", + "zh:dff2bc10071210181726ce270f954995fe42c696e61e2e8f874021fed02521e5", + "zh:e8e87b40b6a87dc097b0fdc20d3f725cec0d82abc9cc3755c1f89f8f6e8b0036", + "zh:ee964a6573d399a5dd22ce328fb38ca1207797a02248f14b2e4913ee390e7803", ] } diff --git a/deployment/modules/cloudflare/docs/config.tf b/deployment/modules/cloudflare/docs/config.tf index 9dd16d5982..63347cf67e 100644 --- a/deployment/modules/cloudflare/docs/config.tf +++ b/deployment/modules/cloudflare/docs/config.tf @@ -5,7 +5,7 @@ terraform { required_providers { cloudflare = { source = "cloudflare/cloudflare" - version = "4.52.1" + version = "4.52.5" } } } diff --git a/deployment/modules/cloudflare/docs/domain.tf b/deployment/modules/cloudflare/docs/domain.tf index a28fb4c0f8..c5f77de6b4 100644 --- a/deployment/modules/cloudflare/docs/domain.tf +++ b/deployment/modules/cloudflare/docs/domain.tf @@ -1,11 +1,11 @@ resource "cloudflare_pages_domain" "immich_app_branch_domain" { account_id = var.cloudflare_account_id project_name = local.is_release ? data.terraform_remote_state.cloudflare_account.outputs.immich_app_archive_pages_project_name : data.terraform_remote_state.cloudflare_account.outputs.immich_app_preview_pages_project_name - domain = "${var.prefix_name}.${local.deploy_domain_prefix}.immich.app" + domain = "docs.${var.prefix_name}.${local.deploy_domain_prefix}.immich.app" } resource "cloudflare_record" "immich_app_branch_subdomain" { - name = "${var.prefix_name}.${local.deploy_domain_prefix}.immich.app" + name = "docs.${var.prefix_name}.${local.deploy_domain_prefix}.immich.app" proxied = true ttl = 1 type = "CNAME" diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml index 372352d12a..53d64dd0c8 100644 --- a/docker/docker-compose.dev.yml +++ b/docker/docker-compose.dev.yml @@ -1,5 +1,5 @@ # -# WARNING: To install Immich, follow our guide: https://immich.app/docs/install/docker-compose +# WARNING: To install Immich, follow our guide: https://docs.immich.app/install/docker-compose # # Make sure to use the docker-compose.yml of the current release: # @@ -8,8 +8,8 @@ # The compose file on main may not be compatible with the latest release. # For development see: -# - https://immich.app/docs/developer/setup -# - https://immich.app/docs/developer/troubleshooting +# - https://docs.immich.app/developer/setup +# - https://docs.immich.app/developer/troubleshooting name: immich-dev @@ -21,16 +21,14 @@ services: # extends: # file: hwaccel.transcoding.yml # service: cpu # set to one of [nvenc, quicksync, rkmpp, vaapi, vaapi-wsl] for accelerated transcoding - user: '${UID:-1000}:${GID:-1000}' build: context: ../ - dockerfile: server/Dockerfile + dockerfile: server/Dockerfile.dev target: dev restart: unless-stopped volumes: - ..:/usr/src/app - ${UPLOAD_LOCATION}/photos:/data - - ${UPLOAD_LOCATION}/photos/upload:/data/upload - /etc/localtime:/etc/localtime:ro - pnpm-store:/usr/src/app/.pnpm-store - server-node_modules:/usr/src/app/server/node_modules @@ -57,8 +55,8 @@ services: IMMICH_BUILD_IMAGE_URL: https://github.com/immich-app/immich/pkgs/container/immich-server IMMICH_THIRD_PARTY_SOURCE_URL: https://github.com/immich-app/immich/ IMMICH_THIRD_PARTY_BUG_FEATURE_URL: https://github.com/immich-app/immich/issues - IMMICH_THIRD_PARTY_DOCUMENTATION_URL: https://immich.app/docs - IMMICH_THIRD_PARTY_SUPPORT_URL: https://immich.app/docs/community-guides + IMMICH_THIRD_PARTY_DOCUMENTATION_URL: https://docs.immich.app + IMMICH_THIRD_PARTY_SUPPORT_URL: https://docs.immich.app/community-guides ulimits: nofile: soft: 1048576 @@ -72,20 +70,15 @@ services: condition: service_started database: condition: service_started - init: - condition: service_completed_successfully healthcheck: disable: false immich-web: container_name: immich_web image: immich-web-dev:latest - # Needed for rootless docker setup, see https://github.com/moby/moby/issues/45919 - # user: 0:0 - user: '${UID:-1000}:${GID:-1000}' build: context: ../ - dockerfile: server/Dockerfile + dockerfile: server/Dockerfile.dev target: dev command: ['immich-web'] env_file: @@ -114,8 +107,6 @@ services: depends_on: immich-server: condition: service_started - init: - condition: service_completed_successfully immich-machine-learning: container_name: immich_machine_learning @@ -143,13 +134,13 @@ services: redis: container_name: immich_redis - image: docker.io/valkey/valkey:8-bookworm@sha256:a137a2b60aca1a75130022d6bb96af423fefae4eb55faf395732db3544803280 + image: docker.io/valkey/valkey:8@sha256:81db6d39e1bba3b3ff32bd3a1b19a6d69690f94a3954ec131277b9a26b95b3aa healthcheck: test: redis-cli ping || exit 1 database: container_name: immich_postgres - image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:32324a2f41df5de9efe1af166b7008c3f55646f8d0e00d9550c16c9822366b4a + image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:bcf63357191b76a916ae5eb93464d65c07511da41e3bf7a8416db519b40b1c23 env_file: - .env environment: @@ -183,25 +174,6 @@ services: # volumes: # - grafana-data:/var/lib/grafana - init: - container_name: init - image: busybox@sha256:ab33eacc8251e3807b85bb6dba570e4698c3998eca6f0fc2ccb60575a563ea74 - env_file: - - .env - user: 0:0 - command: sh -c 'find /data -maxdepth 1 -type d -exec chown ${UID:-1000}:${GID:-1000} {} + 2>/dev/null || true; for path in /usr/src/app/.pnpm-store /usr/src/app/server/node_modules /usr/src/app/server/dist /usr/src/app/.github/node_modules /usr/src/app/cli/node_modules /usr/src/app/docs/node_modules /usr/src/app/e2e/node_modules /usr/src/app/open-api/typescript-sdk/node_modules /usr/src/app/web/.svelte-kit /usr/src/app/web/coverage /usr/src/app/node_modules /usr/src/app/web/node_modules; do [ -e "$$path" ] && chown -R ${UID:-1000}:${GID:-1000} "$$path" || true; done' - volumes: - - pnpm-store:/usr/src/app/.pnpm-store - - server-node_modules:/usr/src/app/server/node_modules - - web-node_modules:/usr/src/app/web/node_modules - - github-node_modules:/usr/src/app/.github/node_modules - - cli-node_modules:/usr/src/app/cli/node_modules - - docs-node_modules:/usr/src/app/docs/node_modules - - e2e-node_modules:/usr/src/app/e2e/node_modules - - sdk-node_modules:/usr/src/app/open-api/typescript-sdk/node_modules - - app-node_modules:/usr/src/app/node_modules - - sveltekit:/usr/src/app/web/.svelte-kit - - coverage:/usr/src/app/web/coverage volumes: model-cache: prometheus-data: diff --git a/docker/docker-compose.prod.yml b/docker/docker-compose.prod.yml index 7c658de336..78ba0653ac 100644 --- a/docker/docker-compose.prod.yml +++ b/docker/docker-compose.prod.yml @@ -1,5 +1,5 @@ # -# WARNING: To install Immich, follow our guide: https://immich.app/docs/install/docker-compose +# WARNING: To install Immich, follow our guide: https://docs.immich.app/install/docker-compose # # Make sure to use the docker-compose.yml of the current release: # @@ -56,14 +56,14 @@ services: redis: container_name: immich_redis - image: docker.io/valkey/valkey:8-bookworm@sha256:a137a2b60aca1a75130022d6bb96af423fefae4eb55faf395732db3544803280 + image: docker.io/valkey/valkey:8@sha256:81db6d39e1bba3b3ff32bd3a1b19a6d69690f94a3954ec131277b9a26b95b3aa healthcheck: test: redis-cli ping || exit 1 restart: always database: container_name: immich_postgres - image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:32324a2f41df5de9efe1af166b7008c3f55646f8d0e00d9550c16c9822366b4a + image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:bcf63357191b76a916ae5eb93464d65c07511da41e3bf7a8416db519b40b1c23 env_file: - .env environment: diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 052ae8b334..e4e0f964d3 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,5 +1,5 @@ # -# WARNING: To install Immich, follow our guide: https://immich.app/docs/install/docker-compose +# WARNING: To install Immich, follow our guide: https://docs.immich.app/install/docker-compose # # Make sure to use the docker-compose.yml of the current release: # @@ -36,7 +36,7 @@ services: # For hardware acceleration, add one of -[armnn, cuda, rocm, openvino, rknn] to the image tag. # Example tag: ${IMMICH_VERSION:-release}-cuda image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release} - # extends: # uncomment this section for hardware acceleration - see https://immich.app/docs/features/ml-hardware-acceleration + # extends: # uncomment this section for hardware acceleration - see https://docs.immich.app/features/ml-hardware-acceleration # file: hwaccel.ml.yml # service: cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn] for accelerated inference - use the `-wsl` version for WSL2 where applicable volumes: @@ -49,14 +49,14 @@ services: redis: container_name: immich_redis - image: docker.io/valkey/valkey:8-bookworm@sha256:a137a2b60aca1a75130022d6bb96af423fefae4eb55faf395732db3544803280 + image: docker.io/valkey/valkey:8@sha256:81db6d39e1bba3b3ff32bd3a1b19a6d69690f94a3954ec131277b9a26b95b3aa healthcheck: test: redis-cli ping || exit 1 restart: always database: container_name: immich_postgres - image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:32324a2f41df5de9efe1af166b7008c3f55646f8d0e00d9550c16c9822366b4a + image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:bcf63357191b76a916ae5eb93464d65c07511da41e3bf7a8416db519b40b1c23 environment: POSTGRES_PASSWORD: ${DB_PASSWORD} POSTGRES_USER: ${DB_USERNAME} diff --git a/docker/example.env b/docker/example.env index 0450dc0805..6d6fd1e3fe 100644 --- a/docker/example.env +++ b/docker/example.env @@ -1,4 +1,4 @@ -# You can find documentation for all the supported env variables at https://immich.app/docs/install/environment-variables +# You can find documentation for all the supported env variables at https://docs.immich.app/install/environment-variables # The location where your uploaded files are stored UPLOAD_LOCATION=./library diff --git a/docker/hwaccel.ml.yml b/docker/hwaccel.ml.yml index 111202d022..c95ac7ee4c 100644 --- a/docker/hwaccel.ml.yml +++ b/docker/hwaccel.ml.yml @@ -4,7 +4,7 @@ # you can inline the config for a backend by copying its contents # into the immich-machine-learning service in the docker-compose.yml file. -# See https://immich.app/docs/features/ml-hardware-acceleration for info on usage. +# See https://docs.immich.app/features/ml-hardware-acceleration for info on usage. services: armnn: diff --git a/docker/hwaccel.transcoding.yml b/docker/hwaccel.transcoding.yml index 60ee7e8fa3..0857faf465 100644 --- a/docker/hwaccel.transcoding.yml +++ b/docker/hwaccel.transcoding.yml @@ -4,7 +4,7 @@ # you can inline the config for a backend by copying its contents # into the immich-microservices service in the docker-compose.yml file. -# See https://immich.app/docs/features/hardware-transcoding for more info on using hardware transcoding. +# See https://docs.immich.app/features/hardware-transcoding for more info on using hardware transcoding. services: cpu: {} diff --git a/docs/.nvmrc b/docs/.nvmrc index e2228113dd..442c7587a9 100644 --- a/docs/.nvmrc +++ b/docs/.nvmrc @@ -1 +1 @@ -22.19.0 +22.20.0 diff --git a/docs/blog/2022/11-10/release-1.36.mdx b/docs/blog/2022/11-10/release-1.36.mdx deleted file mode 100644 index 5f5643196c..0000000000 --- a/docs/blog/2022/11-10/release-1.36.mdx +++ /dev/null @@ -1,110 +0,0 @@ ---- -slug: release-1-36 -title: Release v1.36.0 -authors: [alextran] -tags: [release] -date: 2022-11-10 ---- - -Hello everyone, it is my pleasure to deliver the new release of Immich to you. The team has been working hard to bring you the new features and improvements. This release includes some big features that the community has been asking since the beginning of Immich. We hope you will enjoy it. - -Some notable features are: - -- OAuth integration -- LivePhoto support on iOS -- User config system - - - -## LivePhoto iOS Support 🎉 - -LivePhoto on iOS is now supported in Immich. - -The motion part will now be uploaded and can be played on the mobile app and the web. - -:::caution - -- The server and the app has to be on version **1.36.x** for the application to work correctly. -- Previous uploaded photos will not be updated automatically, you will have to remove and reupload them if you want to keep the LivePhoto functionality. - -::: - - - -## OAuth Integration 🎉 - -I want to borrow this chance to express my gratitude to [@EnricoBilla](https://github.com/EnricoBilla), who has been the trailblazer for this feature since the beginning days of Immich. His PR has sparked ideas, suggestions, and discussion among the team member on how to integrate this feature successfully into the app. Thank you so much for your work and your time. - -OAuth is now integrated into the system. Please follow the guide [here](https://immich.app/docs/usage/oauth) to set up your OAuth integration - -After setting up the correct environment variables in the `.env` file, as shown below - -| Key | Type | Default | Description | -| ------------------- | ------- | -------------------- | ------------------------------------------------------------------------- | -| OAUTH_ENABLED | boolean | false | Enable/disable OAuth2 | -| OAUTH_ISSUER_URL | URL | (required) | Required. Self-discovery URL for client | -| OAUTH_CLIENT_ID | string | (required) | Required. Client ID | -| OAUTH_CLIENT_SECRET | string | (required) | Required. Client Secret | -| OAUTH_SCOPE | string | openid email profile | Full list of scopes to send with the request (space delimited) | -| OAUTH_AUTO_REGISTER | boolean | true | When true, will automatically register a user the first time they sign in | -| OAUTH_BUTTON_TEXT | string | Login with OAuth | Text for the OAuth button on the web | - -```bash title="Authentik Example" -OAUTH_ENABLED=true -OAUTH_ISSUER_URL=http://10.1.15.216:9000/application/o/immich-test/ -OAUTH_CLIENT_ID=30596v8f78a4b6a97d5985c3076b6b4c4d12ddc33 -OAUTH_CLIENT_SECRET=50f1eafdec353b95b1c638db390db4ab67ef035a51212dbec2f56175e2eb272b5d572c099176e6fe116ecf47ffdd544bgdb9e2edc588307ee0339d25eeccd88 -OAUTH_BUTTON_TEXT=Login with Authentik -``` - -The web will have the option to sign in with OAuth. - - - -The mobile app will check if the server has OAuth enabled before displaying the OAuth -sign-in button. - - - -## Support - - - -If you find the project helpful and it helps you in some ways, you can support the project [one time](https://github.com/sponsors/alextran1502?frequency=one-time&sponsor=alextran1502) or [monthly](https://github.com/sponsors/alextran1502) from GitHub Sponsor - -It is a great way to let me know that you want me to continue developing and working on this project for years to come. - -## Details - -For more details, please check out the [release note](https://github.com/immich-app/immich/releases/tag/v1.36.0_55-dev) diff --git a/docs/blog/2023/06-24/update.mdx b/docs/blog/2023/06-24/update.mdx deleted file mode 100644 index 464d3e44d9..0000000000 --- a/docs/blog/2023/06-24/update.mdx +++ /dev/null @@ -1,103 +0,0 @@ ---- -title: Immich Update - June 2023 -authors: [alextran] -tags: [update] ---- - -Hello everybody, Alex here! - -I am back with another update on Immich. It has been only a month since my last update (May 18th, 2023), but it seems forever. I think the rapid releases of Immich and the amount of work make the perspective of time change in Immich’s world. We have some exciting updates that I think you will like. - -Before going into detail, on behalf of the core team, I would like to thank all of you for loving Immich and contributing to the project. Thank you for helping me make Immich an enjoyable alternative solution to Google Photos so that you have complete control of your data and privacy. I know we are still young and have a lot of work to do, but I am confident we will get there with help from the community. I appreciate all of you from the bottom of my heart! - - - -And now, to the exciting part, what is new in Immich’s world? - -- Initial support for existing gallery. -- Memory feature. -- Support XMP sidecar. -- Support more raw formats. -- Justified layout for web timeline and blurred thumbnail hash. -- Mechanism to host machine learning on a completely different machine. - -## Support for existing gallery - -I know this is the most controversial feature when it comes to Immich’s way of ingesting photos and videos. For many users, having to upload photos and videos to Immich is simply not working. We listen, discuss, and digest this feature internally more than you imagine because it is not a simple feature to tackle while keeping the performance and the user experience at the top level, which is Immich’s primary goal. - -Thankfully, we have many great contributors and developers that want to make this come true. So we came up with an initial implementation of this feature in the form of a supporting read-only gallery. - -To be concise, Immich can now read in the gallery files, register the path into the database, and then generate necessary files and put them through Immich’s machine learning pipeline so you can use all the goodness of Immich without the need to upload them. Since this is the initial implementation, some actions/behavior are not yet supported, and we aim to build toward them in future releases, namely: - -- Assets are not automatically synced and must instead be manually synced with the CLI tool. -- Only new files that are added to the gallery will be detected. -- Deleted and moved files will not be detected. - -## Memory feature - -This is considered a fun feature that the team and I wanted to build for so long, but we had to put it off because of the refactoring of the code base. The code base is now in a good enough form to circle back and add more exciting features. - -This memory feature is very much similar to GPhotos' implementation of “x years sinceâ€Ļ”. We are aiming to add more categories of memories in the future, such as “Spotlight of the day” or “Day of the Week highlights” - - - -This feature is now available on the web and will be ported to the mobile app in the near future. - -## Support XMP Sidecar - -Immich can now import/upload XMP sidecars from the CLI and use the information as the metadata of assets. - -## Support more raw formats. - -With the recent updates on the dependencies of Immich, we are now extending and hardening support for multiple raw formats. So users with DSLR or mirrorless cameras can now upload their original files to Immich and have them displayed in high-quality thumbnails on the web and mobile view. - -## Justified layout for web timeline and blurred thumbnail hash - -This is an aesthetic improvement in user experience when browsing the timeline. Photos and videos are now displayed correctly with perspective orientation, making the browsing experience more pleasurable. - -To further improve the browsing experience, we now added a blur hash to the thumbnail, so the transition is more natural with a dreamy fade in effect, similar to how our brain goes from faded to vivid memory - - - -## Hosting machine learning container on a different machine - -With more capabilities Immich is building toward, machine learning will get more powerful and therefore require more resources to run effectively. However, we understand that users might not have the best server resources where they host the Immich instance. Therefore, we changed how machine learning interacts and receives the photos and videos to run through its inference pipeline. - -The machine learning container is now a headless system that can run on any machine. As long as your Immich instance can communicate with the system running the machine learning container, it can send the files and receive the required information to make Immich powerful in terms of searching and intelligence. This helps you to utilize a more powerful machine in your home/infrastructure to perform the CPU-intensive tasks while letting Immich only handle the I/O operations for a pleasant and smooth experience. - ---- - -So, those are the highlights for the team and the community after a busy month. There are a lot more changes and improvements. I encourage you to read some release notes, starting from version [v1.57.0](https://github.com/immich-app/immich/releases/tag/v1.57.0) to now. - -Thank you, and I am asking for your support for the project. I hope to be a full-time maintainer of Immich one day to dedicate myself to the project as my life works for the community and my family. You can find the support channels below: - -- Monthly donation via [GitHub Sponsors](https://github.com/sponsors/alextran1502) -- One-time donation via [GitHub Sponsors](https://github.com/sponsors/alextran1502?frequency=one-time&sponsor=alextran1502) -- [Liberapay](https://liberapay.com/alex.tran1502/) -- [buymeacoffee](https://www.buymeacoffee.com/altran1502) -- Bitcoin: 3QVAb9dCHutquVejeNXitPqZX26Yg5kxb7 -- Give a project a star - the contributors love gazing at the stars and seeing their creations shining in the sky. - -Join our friendly [Discord](https://discord.immich.app) to talk and discuss Immich, tech, or anything - -Cheer! - -Until next time! - -Alex diff --git a/docs/blog/2023/07-29/images/web-shortcuts-panel.png b/docs/blog/2023/07-29/images/web-shortcuts-panel.png deleted file mode 100644 index 5a16c9f289..0000000000 Binary files a/docs/blog/2023/07-29/images/web-shortcuts-panel.png and /dev/null differ diff --git a/docs/blog/2023/07-29/update.mdx b/docs/blog/2023/07-29/update.mdx deleted file mode 100644 index 6d50ddfdc0..0000000000 --- a/docs/blog/2023/07-29/update.mdx +++ /dev/null @@ -1,151 +0,0 @@ ---- -title: Immich Update - July 2023 -authors: [alextran] -tags: [update, v1.64.0-v1.71.0] ---- - -Hello, Immich fans, another month, another milestone. We hope you are staying cool and safe in this scorching hot summer across the globe. - -Immich recently got some good recognition when getting to the front page of HackerNews, which helped to let more people know about the project's existence. The project will help more and more people find a solution to control the privacy of their most precious moments. And with the gain in popularity and recognition, we have gotten new users and more questions from the community than ever. - -I want to express my gratitude to all the contributors and the community who have been tremendously helpful to new users' questions and provided technical support. - -Below are the highlights of new features we added to the application over the past month, along with countless bug fixes and improvements across the board, from developer experience to resource optimization and UI/UX improvement. I hope you find these topics as exciting as I am. - -## Highlights - -- Memories feature. -- Facial recognition improvements. -- Improvements on multi selection behavior on the web. -- Shortcuts for common actions on the web. -- Support viewer for 360-panorama photos. - - - ---- - -### Memories feature - -We've added the memory feature on the mobile app, so you can reminisce about your past memories. - - - -### Facial recognition improvements - -Over the past few releases, we have added many UI improvements to the facial recognition feature to help you manage the recognized people better. Some of the highlights: - -#### Choose a new feature photo for a person. - - - -#### Hide and show faces. - -You can now select irrelevant faces to hide them. The hidden faces won’t be displayed in search results and the people section in the info panel. - -#### Merge faces. - -This is useful when you have multiple faces of the same person in your photos, and you want to merge them into one. - - - -We also added a nifty mechanism that when naming a face, similar names will prompt you a merge face option for the convenience. - - - -### Improvements on multi selection behavior on the web - -We have added a new multi selection behavior on the web to help you select multiple items easier. You can now select a range of photos and videos by holding the `Shift` key. - - - -### Shortcuts for common actions on the web. - -Some of us only navigate the world and the web with a keyboard (looking at you, Vim and Emacs users). So it would take away the sacred weapon of choice to require many clicks to perform repetitive actions. So we added quick shortcuts for the following action on the web. - -Dot Env Example - -### Support viewer for 360-panorama photos. - -Photos with the EXIF property of `ProjectionType` will now have a special viewer on the web to view all the angles of the panorama. - -The thumbnail of the 360 degrees panoramas will have a special icon on the top right of the thumbnail - -Dot Env Example - -Panorama in the detail view - -Dot Env Example - ---- - -Thank you, and I am asking for your support for the project. I hope to be a full-time maintainer of Immich one day to dedicate myself to the project as my life's work for the community and my family. You can find the support channels below: - -- Monthly donation via [GitHub Sponsors](https://github.com/sponsors/alextran1502) -- One-time donation via [GitHub Sponsors](https://github.com/sponsors/alextran1502?frequency=one-time&sponsor=alextran1502) -- [Liberapay](https://liberapay.com/alex.tran1502/) -- [buymeacoffee](https://www.buymeacoffee.com/altran1502) -- Bitcoin: 3QVAb9dCHutquVejeNXitPqZX26Yg5kxb7 -- Give a project a star - the contributors love gazing at the stars and seeing their creations shining in the sky. - -Join our friendly [Discord](https://discord.immich.app) to talk and discuss Immich, tech, or anything - -Cheer! - -Until next time! - -Alex diff --git a/docs/blog/2023/2023-recap.mdx b/docs/blog/2023/2023-recap.mdx deleted file mode 100644 index e9d93a52be..0000000000 --- a/docs/blog/2023/2023-recap.mdx +++ /dev/null @@ -1,71 +0,0 @@ ---- -title: Immich Recap 2023 -authors: [alextran] -tags: [update, recap-2023] -date: 2023-12-30T00:00 ---- - -Hi everyone, - -Alex from Immich here. - -We are entering the last few weeks of 2023, and it has been quite a year for Immich. The project has grown so much in terms of users, developers, features, maturity, and the community around it. When I started working on Immich, it was simply a challenge for myself and an opportunity to learn new technologies, crafting something fun and useful for my wife during my free time to satisfy my urge to build and create things. I never thought it would become so popular and help so many people. At the end of the day, all we have is memory. I am proud that the team and I have created something to make storing and viewing those precious memories easier without restrictions and without sacrificing our privacy. As the year closes, here’s a recap of everything the project accomplished in 2023. - -# Milestones - -- Public shared links -- Favorites page -- Immich turned 1 -- Material Design 3 on the mobile app -- Auto-link LivePhotos server-side -- iOS background backup -- Explore page -- CLIP search -- Search by metadata -- Responsive web app -- Archive page -- Asset descriptions -- 10,000 stars on GitHub -- Manage auth devices -- Map view -- Facial recognition, clustering, searching, renaming, and person management -- Partner sharing and unifying timeline between partners' users -- Custom storage label -- XMP sidecar reading -- RAW file formats -- Justified layout on the web -- Memories -- Multi-select via SHIFT -- Android Motion Photos -- 360° Photos -- Album description -- Album performance improvements (time buckets) -- Video hardware transcoding -- Slideshow mode on the web -- Configuration file -- External libraries -- Trash page -- Custom theme -- Asset Stacking -- 20,000 stars on GitHub -- Shared album activity and comments -- CLI v2 -- Down to 5 containers (from 8) - -# Fun Statistics - -- We have gone from the release version `1.41.0` to `1.90.0` at the time of writing. On average, we see a release every 7 days. -- According to GitHub's metrics, the `immich-server` container image has been pulled almost _4 million_ times. -- According to mobile app store metrics, we have 22,000 installations on Android and 6700 installation units on iOS (opt-in only). -- Immich is making around $1200/month on average from donations. (Thank you all so much!) -- We were guests on two podcasts: - - [Self-hosted](https://selfhosted.show/110) - - [The Vergecast](https://www.theverge.com/23938533/self-hosting-local-first-software-vergecast) -- There are over 4,500 members on the Discord server. -- We have over 22,000 stars on the main GitHub repository, gaining 15,000 stars since January 2023. - -Diving into the next year, the team will continue to build on the foundation we have laid out over the past year, implementing more advanced features for searching, organizing, and sharing between users. Bugs will continue to be squashed and conquered. “Shit Alex wrote'' code will continue to be replaced by beautiful, clean code from Jason, Zack, Boet, Daniel, Osorin, Mert, Fynn, Marty, Martin, and Jonathan. The team has my eternal gratitude for creating a welcoming environment for new contributors, helping, teaching, and learning from each other. I’ve realized that hardly a day has gone by where the team hasn’t been in communication about Immich related topics over the past year. - -My long-term goal is to help hone Immich into a diamond in the FOSS space, where the UI, UX, development experiences, documentation, and quality are at a high standard while remaining free for everybody to use. - -I hope you enjoy Immich and have a happy and peaceful holiday. diff --git a/docs/blog/2024/immich-core-team-goes-fulltime.mdx b/docs/blog/2024/immich-core-team-goes-fulltime.mdx deleted file mode 100644 index 0cba2b467c..0000000000 --- a/docs/blog/2024/immich-core-team-goes-fulltime.mdx +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: The Immich core team goes full-time -authors: [alextran] -tags: [update, announcement, FUTO] -date: 2024-05-01T00:00 ---- - -**Immich is joining [FUTO](https://futo.org/)!** - -Since the beginning of this adventure, my goal has always been to create a better world for my children. Memories are priceless, and privacy should not be a luxury. However, building quality open source has its challenges. Over the past two years, it has taken significant dedication, time, and effort. - -Recently, a company in Austin, Texas, called FUTO contacted the team. FUTO strives to develop quality and sustainable open software. They build software alternatives that focus on giving control to users. From their mission statement: - -“Computers should belong to you, the people. We develop and fund technology to give them back.” - -FUTO loved Immich and wanted to see if we’d consider working with them to take the project to the next level. In short, FUTO offered to: - -- Pay the core team to work on Immich full-time -- Let us keep full autonomy about the project’s direction and leadership -- Continue to license Immich under AGPL -- Keep Immich’s development direction with no paywalled features -- Keep Immich “built for the people” (no ads, data mining/selling, or alternative motives) -- Provide us with financial, technical, legal, and administrative support - -After careful deliberation, the team decided that FUTO’s vision closely aligns with our own: to build a better future by providing a polished, performant, and privacy-preserving open-source software solution for photo and video management delivered in a sustainable way. - -Immich’s future has never looked brighter, and we look forward to realizing our vision for Immich as part of FUTO. - -If you have more questions, we’ll host a Q&A live stream on May 9th at 3PM UTC (10AM CST). [You can ask questions here](https://www.live-ask.com/event/01HWP2SB99A1K8EXFBDKZ5Z9CF), and the stream will be live [here on our YouTube channel](https://youtube.com/live/cwz2iZwYpgg). - -Cheers, - -The Immich Team - ---- - -## FAQs - -### What is FUTO? - -[https://futo.org/what-is-futo/](https://futo.org/what-is-futo/) - -### Will the license change? - -No. Immich will continue to be licensed under AGPL without a CLA. - -### Will Immich continue to be free? - -Yes. The Immich source code will remain freely available under the AGPL license. - -### Is Immich getting VC funding? - -No. Venture capital implies investment in a business, often with the expectation of a future payout (exit plan). Immich is neither a business that can be acquired nor comes with a money-making exit plan. - -### I am currently supporting Immich through GitHub sponsors. What will happen to my donation? - -Effective immediately, all donations to the Immich organization will be canceled. In the future, we will offer an optional, modest payment option instead. Thank you to everyone who donated to help us get this far! - -### How is funding sustainable? - -Immich and FUTO believe a sustainable future requires a model that does not rely on users-as-a-product. To this end, FUTO advocates that users pay for good, open software. In keeping with this model, we will adopt a purchase price. This means we no longer accept donations, but — _without limiting features for those who do not pay_ — we will soon allow you to purchase Immich through a modest payment. We encourage you to pay for the high-quality software you use to foster a healthy software culture where developers build great applications without hidden motives for their users. - -### When does this change take effect? - -This change takes effect immediately. - -### What will change? - -The following things will change as Immich joins FUTO: - -- The brand, logo, and other Immich trademarks will be transferred to FUTO. -- We will stop all donations to the project. -- The core team can now dedicate our full attention to Immich -- Before the end of the year, we plan to have a roadmap for what it will take to get Immich to a stable release. -- Bugs will be squashed, and features will be delivered faster. diff --git a/docs/blog/2024/immich-licensing.mdx b/docs/blog/2024/immich-licensing.mdx deleted file mode 100644 index 773abcb666..0000000000 --- a/docs/blog/2024/immich-licensing.mdx +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: Licensing announcement - Purchase a license to support Immich -authors: [alextran] -tags: [update, announcement, FUTO] -date: 2024-07-18T00:00 ---- - -Hello everybody, - -Firstly, on behalf of the Immich team, I'd like to thank everybody for your continuous support of Immich since the very first day! Your contributions, encouragement, and community engagement have helped bring Immich to its current state. The team and I are forever grateful for that. - -Since our [last announcement of the core team joining FUTO to work on Immich full-time](https://immich.app/blog/2024/immich-core-team-goes-fulltime), one of the goals of our new position is to foster a healthy relationship between the developers and the users. We believe that this enables us to create great software, establish transparent policies and build trust. - -We want to build a great software application that brings value to you and your loved ones' lives. We are not using you as a product, i.e., selling or tracking your data. We are not putting annoying ads into our software. We respect your privacy. We want to be compensated for the hard work we put in to build Immich for you. - -With those notes, we have enabled a way for you to financially support the continued development of Immich, ensuring the software can move forward and will be maintained, by offering a lifetime license of the software. We think if you like and use software, you should pay for it, but _we're never going to force anyone to pay or try to limit Immich for those who don't._ - -There are two types of license that you can choose to purchase: **Server License** and **Individual License**. - -### Server License - -This is a lifetime license costing **$99.99**. The license is applied to the whole server. You and all users that use your server are licensed. - -### Individual License - -This is a lifetime license costing **$24.99**. The license is applied to a single user, and can be used on any server they choose to connect to. - -license-social-gh - -You can purchase the license on [our page - https://buy.immich.app](https://buy.immich.app). - -Starting with release `v1.109.0` you can purchase and enter your purchased license key directly in the app. - -license-page-gh - -## Thank you - -Thank you again for your support, this will help create a strong foundation and stability for the Immich team to continue developing and maintaining the project that you love to use. - -

- -

- -
-
- -Cheers! 🎉 - -Immich team - -# FAQ - -### 1. Where can I purchase a license? - -There are several places where you can purchase the license from - -- [https://buy.immich.app](https://buy.immich.app) -- [https://pay.futo.org](https://pay.futo.org/) -- or directly from the app. - -### 2. Do I need both _Individual License_ and _Server License_? - -No, - -If you are the admin and the sole user, or your instance has less than a total of 4 users, you can buy the **Individual License** for each user. - -If your instance has more than 4 users, it is more cost-effective to buy the **Server License**, which will license all the users on your instance. - -### 3. What do I do if I don't pay? - -You can continue using Immich without any restriction. - -### 4. Will there be any paywalled features? - -No, there will never be any paywalled features. - -### 5. Where can I get support regarding payment issues? - -You can email us with your `orderId` and your email address `billing@futo.org` or on our Discord server. diff --git a/docs/blog/2024/update-july-2024.mdx b/docs/blog/2024/update-july-2024.mdx deleted file mode 100644 index cbe99177e7..0000000000 --- a/docs/blog/2024/update-july-2024.mdx +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: Immich Update - July 2024 -authors: [alextran] -date: 2024-07-01T00:00 -tags: [update, v1.106.0] ---- - -Hello everybody! Alex from Immich here and I am back with another development progress update for the project. - -Summer has returned once again, and the night sky is filled with stars, thank you for **38_000 shining stars** you have sent to our [GitHub repo](https://github.com/immich-app/immich)! Since the last announcement several core contributors have started full time. Everything is going great with development, PRs get merged with _brrrrrrr_ rate, conversation exchange between team members is on a new high, we met and are working with the great engineers at FUTO. The spirit is high and we have a lot of things brewing that we think you will like. - -Let's go over some of the updates we had since the last post. - -### Container consolidation - -Reduced the number of total containers from 5 to 4 by making the microservices thread get spawned directly in the server container. Woohoo, remember when Immich had 7 containers? - -### Email notifications - -![smtp](https://github.com/immich-app/immich/assets/27055614/949cba85-d3f1-4cd3-b246-a6f5fb5d3ae8) - -We added email notifications to the app with SMTP settings that you can configure for the following events - -- A new account is created for you. -- You are added to a shared album. -- New media is added to an album. - -### Versioned docs - -You can now jump back into the past or take a peek at the unreleased version of the documentation by selecting the version on the website. - -![version-doc](https://github.com/immich-app/immich/assets/27055614/6d22898a-5093-41ad-b416-4573d7ce6e03) - -### Similarity deduplication - -With more machine learning and CLIP magic, we now have similarity deduplication built into the application where it will search for closely similar images and let you decide what to do with them; i.e keep or trash. - -![similarity-deduplication](https://github.com/immich-app/immich/assets/27055614/3cac8478-fbf7-47ea-acb6-0146901dc67e) - -### Permanent URL for asset on the web - -The detail view for an asset now has a permanent URL so you can easily share them with your loved ones. - -### Web app translations - -We now have a public Weblate project which the community can use to translate the webapp to their native languages. We are planning to port the mobile app translation to this platform as well. If you would like to contribute, you can take a look [here](https://hosted.weblate.org/projects/immich/immich/). We're already close to 50% translations -- we really appreciate everyone contributing to that! - -![web-translation](https://github.com/immich-app/immich/assets/27055614/363df2ed-656c-4584-bd82-0708a693c5bc) - -### Read-only/Editor mode on shared album - -As the owner of the album, you can choose if the shared user can edit the album or to only view the content of the album without any modification. - -![read-only-album](https://github.com/immich-app/immich/assets/27055614/c6f66375-b869-495a-9a86-3e87b316d109) - -### Better video thumbnails - -Immich now tries to find a descriptive video thumbnail instead of simply using the first frame. No more black images for thumbnails! - -### Public Roadmap - -We now have a [public roadmap](https://immich.app/roadmap), giving you a high-level overview of things the team is working on. The first goal of this roadmap is to bring Immich to a stable release, which is expected sometime later this year. Some of the highlights include - -- Auto stacking - Auto stacking of burst photos -- Basic editor - Basic photo editing capabilities -- Workflows - Automate tasks with workflows -- Fine grained access controls - Granular access controls for users and api keys -- Better background backups - Rework background backups to be more reliable -- Private/locked photos - Private assets with extra protections - -Beyond the items in the roadmap, we have _many many_ more ideas for Immich. The team and I hope that you are enjoying the application, find it helpful in your life and we have nothing but the intention of building out great software for you all! - -Have an amazing Summer or Winter for those in the southern hemisphere! :D - -Until next time, - -Cheers! -Alex diff --git a/docs/blog/authors.yml b/docs/blog/authors.yml deleted file mode 100644 index f331efa927..0000000000 --- a/docs/blog/authors.yml +++ /dev/null @@ -1,5 +0,0 @@ -alextran: - name: Alex Tran - title: Maintainer of Immich - url: https://github.com/alextran1502 - image_url: https://github.com/alextran1502.png diff --git a/docs/docs/FAQ.mdx b/docs/docs/FAQ.mdx index b2f2e85775..e3df672d35 100644 --- a/docs/docs/FAQ.mdx +++ b/docs/docs/FAQ.mdx @@ -22,7 +22,7 @@ For organizations seeking to resell Immich, we have established the following gu - Do not misrepresent your reseller site or services as being officially affiliated with or endorsed by Immich or our development team. -- For small resellers who wish to contribute financially to Immich's development, we recommend directing your customers to purchase licenses directy from us rather than attempting to broker revenue-sharing arrangements. We ask that you refrain from misrepresenting reseller activities as directly supporting our development work. +- For small resellers who wish to contribute financially to Immich's development, we recommend directing your customers to purchase licenses directly from us rather than attempting to broker revenue-sharing arrangements. We ask that you refrain from misrepresenting reseller activities as directly supporting our development work. When in doubt or if you have an edge case scenario, we encourage you to contact us directly via email to discuss the use of our trademark. We can provide clear guidance on what is acceptable and what is not. You can reach out at: questions@immich.app @@ -30,11 +30,11 @@ When in doubt or if you have an edge case scenario, we encourage you to contact ### How can I reset the admin password? -The admin password can be reset by running the [reset-admin-password](/docs/administration/server-commands.md) command on the immich-server. +The admin password can be reset by running the [reset-admin-password](/administration/server-commands.md) command on the immich-server. ### How can I see a list of all users in Immich? -You can see the list of all users by running [list-users](/docs/administration/server-commands.md) Command on the Immich-server. +You can see the list of all users by running [list-users](/administration/server-commands.md) Command on the Immich-server. --- @@ -106,20 +106,20 @@ However, Immich will delete original files that have been trashed when the trash When Storage Template is off (default) Immich saves the file names in a random string (also known as random UUIDs) to prevent duplicate file names. To retrieve the original file names, you must enable the Storage Template and then run the STORAGE TEMPLATE MIGRATION job. -It is recommended to read about [Storage Template](https://immich.app/docs/administration/storage-template) before activation. +It is recommended to read about [Storage Template](/administration/storage-template) before activation. ### Can I add my existing photo library? -Yes, with an [External Library](/docs/features/libraries.md). +Yes, with an [External Library](/features/libraries.md). -### What happens to existing files after I choose a new [Storage Template](/docs/administration/storage-template.mdx)? +### What happens to existing files after I choose a new [Storage Template](/administration/storage-template.mdx)? -Template changes will only apply to _new_ assets. To retroactively apply the template to previously uploaded assets, run the Storage Migration Job, available on the [Jobs](/docs/administration/jobs-workers/#jobs) page. +Template changes will only apply to _new_ assets. To retroactively apply the template to previously uploaded assets, run the Storage Migration Job, available on the [Jobs](/administration/jobs-workers/#jobs) page. ### Why are only photos and not videos being uploaded to Immich? This often happens when using a reverse proxy in front of Immich. -Make sure to [set your reverse proxy](/docs/administration/reverse-proxy/) to allow large requests. +Make sure to [set your reverse proxy](/administration/reverse-proxy/) to allow large requests. Also, check the disk space of your reverse proxy. In some cases, proxies cache requests to disk before passing them on, and if disk space runs out, the request fails. @@ -139,7 +139,7 @@ You can _archive_ them. ### How can I backup data from Immich? -See [Backup and Restore](/docs/administration/backup-and-restore.md). +See [Backup and Restore](/administration/backup-and-restore.md). ### Does Immich support reading existing face tag metadata? @@ -225,7 +225,7 @@ volumes: ### Can I keep my existing album structure while importing assets into Immich? -Yes, by using the [Immich CLI](/docs/features/command-line-interface) along with the `--album` flag. +Yes, by using the [Immich CLI](/features/command-line-interface) along with the `--album` flag. ### Is there a way to reorder photos within an album? @@ -266,7 +266,7 @@ Immich uses CLIP models. An ML model converts each image to an "embedding", whic ### How does facial recognition work? -See [How Facial Recognition Works](/docs/features/facial-recognition#how-facial-recognition-works) for details. +See [How Facial Recognition Works](/features/facial-recognition#how-facial-recognition-works) for details. ### How can I disable machine learning? @@ -288,7 +288,7 @@ No, this is not supported. Only models listed in the [Hugging Face][huggingface] ### I want to be able to search in other languages besides English. How can I do that? -You can change to a multilingual CLIP model. See [here](/docs/features/searching#clip-models) for instructions. +You can change to a multilingual CLIP model. See [here](/features/searching#clip-models) for instructions. ### Does Immich support Facial Recognition for videos? @@ -299,7 +299,7 @@ Scanning the entire video for faces may be implemented in the future. No. :::tip -You can use [Smart Search](/docs/features/searching.md) for this to some extent. For example, if you have a Golden Retriever and a Chihuahua, type these words in the smart search and watch the results. +You can use [Smart Search](/features/searching.md) for this to some extent. For example, if you have a Golden Retriever and a Chihuahua, type these words in the smart search and watch the results. ::: ### I'm getting a lot of "faces" that aren't faces, what can I do? @@ -329,7 +329,7 @@ ls clip/ facial-recognition/ ### Why is Immich slow on low-memory systems like the Raspberry Pi? -Immich optionally uses transcoding and machine learning for several features. However, it can be too heavy to run on a Raspberry Pi. You can [mitigate](/docs/FAQ#can-i-lower-cpu-and-ram-usage) this or host Immich's machine-learning container on a [more powerful system](/docs/guides/remote-machine-learning), or [disable](/docs/FAQ#how-can-i-disable-machine-learning) machine learning entirely. +Immich optionally uses transcoding and machine learning for several features. However, it can be too heavy to run on a Raspberry Pi. You can [mitigate](/FAQ#can-i-lower-cpu-and-ram-usage) this or host Immich's machine-learning container on a [more powerful system](/guides/remote-machine-learning), or [disable](/FAQ#how-can-i-disable-machine-learning) machine learning entirely. ### Can I lower CPU and RAM usage? @@ -339,9 +339,9 @@ The initial backup is the most intensive due to the number of jobs running. The - Under Settings > Transcoding Settings > Threads, set the number of threads to a low number like 1 or 2. - Under Settings > Machine Learning Settings > Facial Recognition > Model Name, you can change the facial recognition model to `buffalo_s` instead of `buffalo_l`. The former is a smaller and faster model, albeit not as good. - For facial recognition on new images to work properly, You must re-run the Face Detection job for all images after this. -- At the container level, you can [set resource constraints](/docs/FAQ#can-i-limit-cpu-and-ram-usage) to lower usage further. +- At the container level, you can [set resource constraints](/FAQ#can-i-limit-cpu-and-ram-usage) to lower usage further. - It's recommended to only apply these constraints _after_ taking some of the measures here for best performance. -- If these changes are not enough, see [above](/docs/FAQ#how-can-i-disable-machine-learning) for instructions on how to disable machine learning. +- If these changes are not enough, see [above](/FAQ#how-can-i-disable-machine-learning) for instructions on how to disable machine learning. ### Can I limit CPU and RAM usage? @@ -383,7 +383,7 @@ Do not exaggerate with the job concurrency because you're probably thoroughly ov ### My server shows Server Status Offline | Version Unknown. What can I do? -You need to [enable WebSockets](/docs/administration/reverse-proxy/) on your reverse proxy. +You need to [enable WebSockets](/administration/reverse-proxy/) on your reverse proxy. --- @@ -391,7 +391,7 @@ You need to [enable WebSockets](/docs/administration/reverse-proxy/) on your rev ### How can I see Immich logs? -Immich components are typically deployed using docker. To see logs for deployed docker containers, you can use the [Docker CLI](https://docs.docker.com/engine/reference/commandline/cli/), specifically the `docker logs` command. For examples, see [Docker Help](/docs/guides/docker-help.md). +Immich components are typically deployed using docker. To see logs for deployed docker containers, you can use the [Docker CLI](https://docs.docker.com/engine/reference/commandline/cli/), specifically the `docker logs` command. For examples, see [Docker Help](/guides/docker-help.md). ### How can I reduce the log verbosity of Redis? @@ -435,7 +435,7 @@ cap_drop: Data for Immich comes in two forms: 1. **Metadata** stored in a Postgres database, stored in the `DB_DATA_LOCATION` folder (previously `pg_data` Docker volume). -2. **Files** (originals, thumbs, profile, etc.), stored in the `UPLOAD_LOCATION` folder, more [info](/docs/administration/backup-and-restore#asset-types-and-storage-locations). +2. **Files** (originals, thumbs, profile, etc.), stored in the `UPLOAD_LOCATION` folder, more [info](/administration/backup-and-restore#asset-types-and-storage-locations). :::warning This will destroy your database and reset your instance, meaning that you start from scratch. @@ -473,7 +473,7 @@ If it mentions SIGILL (note the lack of a K) or error code 132, it most likely m ### Why am I getting database ownership errors? If you get database errors such as `FATAL: data directory "/var/lib/postgresql/data" has wrong ownership` upon database startup, this is likely due to an issue with your filesystem. -NTFS and ex/FAT/32 filesystems are not supported. See [here](/docs/install/requirements#special-requirements-for-windows-users) for more details. +NTFS and ex/FAT/32 filesystems are not supported. See [here](/install/requirements#special-requirements-for-windows-users) for more details. ### How can I verify the integrity of my database? diff --git a/docs/docs/administration/backup-and-restore.md b/docs/docs/administration/backup-and-restore.md index deeefa5635..f9c00c7df7 100644 --- a/docs/docs/administration/backup-and-restore.md +++ b/docs/docs/administration/backup-and-restore.md @@ -3,7 +3,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -A [3-2-1 backup strategy](https://www.backblaze.com/blog/the-3-2-1-backup-strategy/) is recommended to protect your data. You should keep copies of your uploaded photos/videos as well as the Immich database for a comprehensive backup solution. This page provides an overview on how to backup the database and the location of user-uploaded pictures and videos. A template bash script that can be run as a cron job is provided [here](/docs/guides/template-backup-script.md) +A [3-2-1 backup strategy](https://www.backblaze.com/blog/the-3-2-1-backup-strategy/) is recommended to protect your data. You should keep copies of your uploaded photos/videos as well as the Immich database for a comprehensive backup solution. This page provides an overview on how to backup the database and the location of user-uploaded pictures and videos. A template bash script that can be run as a cron job is provided [here](/guides/template-backup-script.md) :::danger The instructions on this page show you how to prepare your Immich instance to be backed up, and which files to take a backup of. You still need to take care of using an actual backup tool to make a backup yourself. @@ -160,7 +160,7 @@ for more info read the [release notes](https://github.com/immich-app/immich/rele :::danger A backup of this folder does not constitute a backup of your database! - Follow the instructions listed [here](/docs/administration/backup-and-restore#database) to learn how to perform a proper backup. + Follow the instructions listed [here](/administration/backup-and-restore#database) to learn how to perform a proper backup. ::: @@ -205,7 +205,7 @@ When you turn off the storage template engine, it will leave the assets in `UPLO :::danger A backup of this folder does not constitute a backup of your database! - Follow the instructions listed [here](/docs/administration/backup-and-restore#database) to learn how to perform a proper backup. + Follow the instructions listed [here](/administration/backup-and-restore#database) to learn how to perform a proper backup. ::: diff --git a/docs/docs/administration/email-notification.mdx b/docs/docs/administration/email-notification.mdx index 2ad4fba2be..0da132161f 100644 --- a/docs/docs/administration/email-notification.mdx +++ b/docs/docs/administration/email-notification.mdx @@ -12,7 +12,7 @@ You can access the settings panel from the web at `Administration -> Settings -> Under Email, enter the required details to connect with an SMTP server. -You can use [this guide](/docs/guides/smtp-gmail) to use Gmail's SMTP server. +You can use [this guide](/guides/smtp-gmail) to use Gmail's SMTP server. ## User's notifications settings diff --git a/docs/docs/administration/jobs-workers.md b/docs/docs/administration/jobs-workers.md index 4634151b9a..8ed3ba2694 100644 --- a/docs/docs/administration/jobs-workers.md +++ b/docs/docs/administration/jobs-workers.md @@ -11,7 +11,7 @@ The `immich-server` container contains multiple workers: ## Split workers -If you prefer to throttle or distribute the workers, you can do this using the [environment variables](/docs/install/environment-variables) to specify which container should pick up which tasks. +If you prefer to throttle or distribute the workers, you can do this using the [environment variables](/install/environment-variables) to specify which container should pick up which tasks. For example, for a simple setup with one container for the Web/API and one for all other microservices, you can do the following: @@ -53,5 +53,21 @@ Additionally, some jobs (such as memories generation) run on a schedule, which i :::note -Some jobs ([External Libraries](/docs/features/libraries) scanning, Database Dump) are configured in their own sections in System Settings. +Some jobs ([External Libraries](/features/libraries) scanning, Database Dump) are configured in their own sections in System Settings. ::: + +## Job processing order + +The below diagram shows the job run order for newly uploaded files + +```mermaid +graph TD + A[Asset Upload] --> B[Metadata Extraction] + B --> C[Storage Template Migration] + C --> D["Thumbnail Generation (Large, small, blurred and person)"] + D --> E[Smart Search] + D --> F[Face Detection] + D --> G[Video Transcoding] + E --> H[Duplicate Detection] + F --> I[Facial Recognition] +``` diff --git a/docs/docs/administration/oauth.md b/docs/docs/administration/oauth.md index 55a0ce9469..47f4a96c6a 100644 --- a/docs/docs/administration/oauth.md +++ b/docs/docs/administration/oauth.md @@ -28,7 +28,7 @@ Before enabling OAuth in Immich, a new client application needs to be configured 2. Configure Redirect URIs/Origins The **Sign-in redirect URIs** should include: - - `app.immich:///oauth-callback` - for logging in with OAuth from the [Mobile App](/docs/features/mobile-app.mdx) + - `app.immich:///oauth-callback` - for logging in with OAuth from the [Mobile App](/features/mobile-app.mdx) - `http://DOMAIN:PORT/auth/login` - for logging in with OAuth from the Web Client - `http://DOMAIN:PORT/user-settings` - for manually linking OAuth in the Web Client @@ -98,7 +98,7 @@ The redirect URI for the mobile app is `app.immich:///oauth-callback`, which is 2. Whitelist the new endpoint as a valid redirect URI with your provider. 3. Specify the new endpoint as the `Mobile Redirect URI Override`, in the OAuth settings. -With these steps in place, you should be able to use OAuth from the [Mobile App](/docs/features/mobile-app.mdx) without a custom scheme redirect URI. +With these steps in place, you should be able to use OAuth from the [Mobile App](/features/mobile-app.mdx) without a custom scheme redirect URI. :::info Immich has a route (`/api/oauth/mobile-redirect`) that is already configured to forward requests to `app.immich:///oauth-callback`, and can be used for step 1. diff --git a/docs/docs/administration/server-commands.md b/docs/docs/administration/server-commands.md index a25673abf2..3838635c24 100644 --- a/docs/docs/administration/server-commands.md +++ b/docs/docs/administration/server-commands.md @@ -16,7 +16,7 @@ The `immich-server` docker image comes preinstalled with an administrative CLI ( ## How to run a command -To run a command, [connect](/docs/guides/docker-help.md#attach-to-a-container) to the `immich_server` container and then execute the command via `immich-admin `. +To run a command, [connect](/guides/docker-help.md#attach-to-a-container) to the `immich_server` container and then execute the command via `immich-admin `. ## Examples diff --git a/docs/docs/administration/system-settings.md b/docs/docs/administration/system-settings.md index f241050136..fdfdad29ea 100644 --- a/docs/docs/administration/system-settings.md +++ b/docs/docs/administration/system-settings.md @@ -12,14 +12,14 @@ Manage password, OAuth, and other authentication settings ### OAuth Authentication -Immich supports OAuth Authentication. Read more about this feature and its configuration [here](/docs/administration/oauth). +Immich supports OAuth Authentication. Read more about this feature and its configuration [here](/administration/oauth). ### Password Authentication -The administrator can choose to disable login with username and password for the entire instance. This means that **no one**, including the system administrator, will be able to log using this method. If [OAuth Authentication](/docs/administration/oauth) is also disabled, no users will be able to login using **any** method. Changing this setting does not affect existing sessions, just new login attempts. +The administrator can choose to disable login with username and password for the entire instance. This means that **no one**, including the system administrator, will be able to log using this method. If [OAuth Authentication](/administration/oauth) is also disabled, no users will be able to login using **any** method. Changing this setting does not affect existing sessions, just new login attempts. :::tip -You can always use the [Server CLI](/docs/administration/server-commands) to re-enable password login. +You can always use the [Server CLI](/administration/server-commands) to re-enable password login. ::: ## Image Settings (thumbnails and previews) @@ -108,7 +108,7 @@ If more than one URL is provided, each server will be attempted one-at-a-time un ### Smart Search -The [smart search](/docs/features/searching) settings allow you to change the [CLIP model](https://openai.com/research/clip). Larger models will typically provide [more accurate search results](https://github.com/immich-app/immich/discussions/11862) but consume more processing power and RAM. When [changing the CLIP model](/docs/FAQ#can-i-use-a-custom-clip-model) it is mandatory to re-run the Smart Search job on all images to fully apply the change. +The [smart search](/features/searching) settings allow you to change the [CLIP model](https://openai.com/research/clip). Larger models will typically provide [more accurate search results](https://github.com/immich-app/immich/discussions/11862) but consume more processing power and RAM. When [changing the CLIP model](/FAQ#can-i-use-a-custom-clip-model) it is mandatory to re-run the Smart Search job on all images to fully apply the change. :::info Internet connection Changing models requires a connection to the Internet to download the model. @@ -132,7 +132,7 @@ Editable settings: - **Max Recognition Distance** - **Min Recognized Faces** -You can learn more about these options on the [Facial Recognition page](/docs/features/facial-recognition#how-face-detection-works) +You can learn more about these options on the [Facial Recognition page](/features/facial-recognition#how-face-detection-works) :::info When changing the values in Min Detection Score, Max Recognition Distance, and Min Recognized Faces. @@ -154,15 +154,15 @@ The map can be adjusted via [OpenMapTiles](https://openmaptiles.org/styles/) for ### Reverse Geocoding Settings -Immich supports [Reverse Geocoding](/docs/features/reverse-geocoding) using data from the [GeoNames](https://www.geonames.org/) geographical database. +Immich supports [Reverse Geocoding](/features/reverse-geocoding) using data from the [GeoNames](https://www.geonames.org/) geographical database. ## Notification Settings -SMTP server setup, for user creation notifications, new albums, etc. More information can be found [here](/docs/administration/email-notification) +SMTP server setup, for user creation notifications, new albums, etc. More information can be found [here](/administration/email-notification) ## Notification Templates -Override the default notifications text with notification templates. More information can be found [here](/docs/administration/email-notification) +Override the default notifications text with notification templates. More information can be found [here](/administration/email-notification) ## Server Settings @@ -176,7 +176,7 @@ The administrator can set a custom message on the login screen (the message will ## Storage Template -Immich supports a custom [Storage Template](/docs/administration/storage-template). Learn more about this feature and its configuration [here](/docs/administration/storage-template). +Immich supports a custom [Storage Template](/administration/storage-template). Learn more about this feature and its configuration [here](/administration/storage-template). ## Theme Settings diff --git a/docs/docs/developer/architecture.mdx b/docs/docs/developer/architecture.mdx index a8d38ba5c1..42d9c1b974 100644 --- a/docs/docs/developer/architecture.mdx +++ b/docs/docs/developer/architecture.mdx @@ -44,7 +44,7 @@ The web app is a [TypeScript](https://www.typescriptlang.org/) project that uses ### CLI -The Immich CLI is an [npm](https://www.npmjs.com/) package that lets users control their Immich instance from the command line. It uses the API to perform various tasks, especially uploading assets. See the [CLI documentation](/docs/features/command-line-interface.md) for more information. +The Immich CLI is an [npm](https://www.npmjs.com/) package that lets users control their Immich instance from the command line. It uses the API to perform various tasks, especially uploading assets. See the [CLI documentation](/features/command-line-interface.md) for more information. ## Server @@ -83,11 +83,11 @@ Immich uses a [worker](https://github.com/immich-app/immich/blob/main/server/src - Smart Search - Facial Recognition - Storage Template Migration -- Sidecar (see [XMP Sidecars](/docs/features/xmp-sidecars.md)) +- Sidecar (see [XMP Sidecars](/features/xmp-sidecars.md)) - Background jobs (file deletion, user deletion) :::info -This list closely matches what is available on the [Administration > Jobs](/docs/administration/jobs-workers/#jobs) page, which provides some remote queue management capabilities. +This list closely matches what is available on the [Administration > Jobs](/administration/jobs-workers/#jobs) page, which provides some remote queue management capabilities. ::: ### Machine Learning diff --git a/docs/docs/developer/devcontainers.md b/docs/docs/developer/devcontainers.md index c7c48acf2b..0a1946e6c1 100644 --- a/docs/docs/developer/devcontainers.md +++ b/docs/docs/developer/devcontainers.md @@ -431,7 +431,7 @@ While the Dev Container focuses on server and web development, you can connect m - Server URL: `http://YOUR_IP:2283/api` - Ensure firewall allows port 2283 -3. **For full mobile development**, see the [mobile development guide](/docs/developer/setup) which covers: +3. **For full mobile development**, see the [mobile development guide](/developer/setup) which covers: - Flutter setup - Running on simulators/devices - Mobile-specific debugging @@ -474,7 +474,7 @@ Recommended minimums: ## Next Steps -- Read the [architecture overview](/docs/developer/architecture) -- Learn about [database migrations](/docs/developer/database-migrations) -- Explore [API documentation](/docs/api) +- Read the [architecture overview](/developer/architecture) +- Learn about [database migrations](/developer/database-migrations) +- Explore [API documentation](https://api.immich.app/) - Join `#immich` on [Discord](https://discord.immich.app) diff --git a/docs/docs/developer/open-api.md b/docs/docs/developer/open-api.md index 2c29c7365b..f627b2c459 100644 --- a/docs/docs/developer/open-api.md +++ b/docs/docs/developer/open-api.md @@ -1,6 +1,6 @@ # OpenAPI -Immich uses the [OpenAPI](https://swagger.io/specification/) standard to generate API documentation. To view the published docs see [here](/docs/api). +Immich uses the [OpenAPI](https://swagger.io/specification/) standard to generate API documentation. To view the published docs see [here](https://api.immich.app/). ## Generator diff --git a/docs/docs/developer/pr-checklist.md b/docs/docs/developer/pr-checklist.md index ea44367742..f855e854c4 100644 --- a/docs/docs/developer/pr-checklist.md +++ b/docs/docs/developer/pr-checklist.md @@ -53,8 +53,8 @@ You can use `dart fix --apply` and `dcm fix lib` to potentially correct some iss ## OpenAPI -The OpenAPI client libraries need to be regenerated whenever there are changes to the `immich-openapi-specs.json` file. Note that you should not modify this file directly as it is auto-generated. See [OpenAPI](/docs/developer/open-api.md) for more details. +The OpenAPI client libraries need to be regenerated whenever there are changes to the `immich-openapi-specs.json` file. Note that you should not modify this file directly as it is auto-generated. See [OpenAPI](/developer/open-api.md) for more details. ## Database Migrations -A database migration needs to be generated whenever there are changes to `server/src/infra/src/entities`. See [Database Migration](/docs/developer/database-migrations.md) for more details. +A database migration needs to be generated whenever there are changes to `server/src/infra/src/entities`. See [Database Migration](/developer/database-migrations.md) for more details. diff --git a/docs/docs/features/automatic-backup.md b/docs/docs/features/automatic-backup.md index 8fcbedaa6e..30d132cef8 100644 --- a/docs/docs/features/automatic-backup.md +++ b/docs/docs/features/automatic-backup.md @@ -16,7 +16,7 @@ If foreground backup is enabled: whenever the app is opened or resumed, it will ## Background backup -This feature is intended for everyday use. For initial bulk uploading, please use the foreground upload feature. For more information on why background upload is not working as expected, please refer to the [FAQ](/docs/FAQ#why-does-foreground-backup-stop-when-i-navigate-away-from-the-app-shouldnt-it-transfer-the-job-to-background-backup). +This feature is intended for everyday use. For initial bulk uploading, please use the foreground upload feature. For more information on why background upload is not working as expected, please refer to the [FAQ](/FAQ#why-does-foreground-backup-stop-when-i-navigate-away-from-the-app-shouldnt-it-transfer-the-job-to-background-backup). If background backup is enabled. The app will periodically check if there are any new photos or videos in the selected album(s) to be uploaded to the server. If there are, it will upload them to the cloud in the background. diff --git a/docs/docs/features/casting.md b/docs/docs/features/casting.md index bca85cb28c..2a6785dc6c 100644 --- a/docs/docs/features/casting.md +++ b/docs/docs/features/casting.md @@ -4,7 +4,7 @@ Immich supports the Google's Cast protocol so that photos and videos can be cast ## Enable Google Cast Support -Google Cast support is disabled by default. The web UI uses Google-provided scripts and must retreive them from Google servers when the page loads. This is a privacy concern for some and is thus opt-in. +Google Cast support is disabled by default. The web UI uses Google-provided scripts and must retrieve them from Google servers when the page loads. This is a privacy concern for some and is thus opt-in. You can enable Google Cast support through `Account Settings > Features > Cast > Google Cast` diff --git a/docs/docs/features/facial-recognition.md b/docs/docs/features/facial-recognition.md index f0dec55484..85712ef5f6 100644 --- a/docs/docs/features/facial-recognition.md +++ b/docs/docs/features/facial-recognition.md @@ -70,7 +70,7 @@ Navigating to Administration > Settings > Machine Learning Settings > Facial Rec :::tip It's better to only tweak the parameters here than to set them to something very different unless you're ready to test a variety of options. If you do need to set a parameter to a strict setting, relaxing other settings can be a good option to compensate, and vice versa. -You can learn how the tune the result in this [Guide](/docs/guides/better-facial-clusters) +You can learn how the tune the result in this [Guide](/guides/better-facial-clusters) ::: ### Facial recognition model diff --git a/docs/docs/features/img/xmp-sidecars.webp b/docs/docs/features/img/xmp-sidecars.webp deleted file mode 100644 index f00b32c730..0000000000 Binary files a/docs/docs/features/img/xmp-sidecars.webp and /dev/null differ diff --git a/docs/docs/features/libraries.md b/docs/docs/features/libraries.md index e68bcdc272..9f1cef0bc4 100644 --- a/docs/docs/features/libraries.md +++ b/docs/docs/features/libraries.md @@ -1,5 +1,9 @@ # External Libraries +:::info +Currently an external library can only belong to a single user which is selected when the library is initially created. +::: + External libraries track assets stored in the filesystem outside of Immich. When the external library is scanned, Immich will load videos and photos from disk and create the corresponding assets. These assets will then be shown in the main timeline, and they will look and behave like any other asset, including viewing on the map, adding to albums, etc. Later, if a file is modified outside of Immich, you need to scan the library for the changes to show up. If an external asset is deleted from disk, Immich will move it to trash on rescan. To restore the asset, you need to restore the original file. After 30 days the file will be removed from trash, and any changes to metadata within Immich will be lost. @@ -103,7 +107,7 @@ The `immich-server` container will need access to the gallery. Modify your docke :::tip The `ro` flag at the end only gives read-only access to the volumes. -This will disallow the images from being deleted in the web UI, or adding metadata to the library ([XMP sidecars](/docs/features/xmp-sidecars)). +This will disallow the images from being deleted in the web UI, or adding metadata to the library ([XMP sidecars](/features/xmp-sidecars)). ::: :::info diff --git a/docs/docs/features/ml-hardware-acceleration.md b/docs/docs/features/ml-hardware-acceleration.md index a94f8c8c64..7f92c25449 100644 --- a/docs/docs/features/ml-hardware-acceleration.md +++ b/docs/docs/features/ml-hardware-acceleration.md @@ -35,7 +35,7 @@ You do not need to redo any machine learning jobs after enabling hardware accele - Where and how you can get this file depends on device and vendor, but typically, the device vendor also supplies these - The `hwaccel.ml.yml` file assumes the path to it is `/usr/lib/libmali.so`, so update accordingly if it is elsewhere - The `hwaccel.ml.yml` file assumes an additional file `/lib/firmware/mali_csffw.bin`, so update accordingly if your device's driver does not require this file -- Optional: Configure your `.env` file, see [environment variables](/docs/install/environment-variables) for ARM NN specific settings +- Optional: Configure your `.env` file, see [environment variables](/install/environment-variables) for ARM NN specific settings - In particular, the `MACHINE_LEARNING_ANN_FP16_TURBO` can significantly improve performance at the cost of very slightly lower accuracy #### CUDA @@ -49,12 +49,12 @@ You do not need to redo any machine learning jobs after enabling hardware accele - The GPU must be supported by ROCm. If it isn't officially supported, you can attempt to use the `HSA_OVERRIDE_GFX_VERSION` environmental variable: `HSA_OVERRIDE_GFX_VERSION=
`. If this doesn't work, you might need to also set `HSA_USE_SVM=0`. - The ROCm image is quite large and requires at least 35GiB of free disk space. However, pulling later updates to the service through Docker will generally only amount to a few hundred megabytes as the rest will be cached. -- This backend is new and may experience some issues. For example, GPU power consumption can be higher than usual after running inference, even if the machine learning service is idle. In this case, it will only go back to normal after being idle for 5 minutes (configurable with the [MACHINE_LEARNING_MODEL_TTL](/docs/install/environment-variables) setting). +- This backend is new and may experience some issues. For example, GPU power consumption can be higher than usual after running inference, even if the machine learning service is idle. In this case, it will only go back to normal after being idle for 5 minutes (configurable with the [MACHINE_LEARNING_MODEL_TTL](/install/environment-variables) setting). #### OpenVINO - Integrated GPUs are more likely to experience issues than discrete GPUs, especially for older processors or servers with low RAM. -- Ensure the server's kernel version is new enough to use the device for hardware accceleration. +- Ensure the server's kernel version is new enough to use the device for hardware acceleration. - Expect higher RAM usage when using OpenVINO compared to CPU processing. #### RKNN @@ -64,7 +64,7 @@ You do not need to redo any machine learning jobs after enabling hardware accele - This is usually pre-installed on the device vendor's Linux images - RKNPU driver V0.9.8 or later must be available in the host server - You may confirm this by running `cat /sys/kernel/debug/rknpu/version` to check the version -- Optional: Configure your `.env` file, see [environment variables](/docs/install/environment-variables) for RKNN specific settings +- Optional: Configure your `.env` file, see [environment variables](/install/environment-variables) for RKNN specific settings - In particular, setting `MACHINE_LEARNING_RKNN_THREADS` to 2 or 3 can _dramatically_ improve performance for RK3576 and RK3588 compared to the default of 1, at the expense of multiplying the amount of RAM each model uses by that amount. ## Setup diff --git a/docs/docs/features/mobile-app.mdx b/docs/docs/features/mobile-app.mdx index cd837741f1..82a2976b41 100644 --- a/docs/docs/features/mobile-app.mdx +++ b/docs/docs/features/mobile-app.mdx @@ -28,7 +28,7 @@ The beta release channel allows users to test upcoming changes before they are o :::info -You can enable automatic backup on supported devices. For more information see [Automatic Backup](/docs/features/automatic-backup.md). +You can enable automatic backup on supported devices. For more information see [Automatic Backup](/features/automatic-backup.md). ::: ## Sync only selected photos @@ -75,7 +75,7 @@ You can sync or mirror an album from your phone to the Immich server on your acc - **User-Specific Sync:** Album synchronization is unique to each server user and does not sync between different users or partners. -- **Mobile-Only Feature:** Album synchronization is currently only available on mobile. For similar options on a computer, refer to [Libraries](/docs/features/libraries) for further details. +- **Mobile-Only Feature:** Album synchronization is currently only available on mobile. For similar options on a computer, refer to [Libraries](/features/libraries) for further details. ### Synchronizing albums from the past diff --git a/docs/docs/features/monitoring.md b/docs/docs/features/monitoring.md index 64377ec073..f087a3306f 100644 --- a/docs/docs/features/monitoring.md +++ b/docs/docs/features/monitoring.md @@ -28,7 +28,7 @@ The metrics in immich are grouped into API (endpoint calls and response times), Immich will not expose an endpoint for metrics by default. To enable this endpoint, you can add the `IMMICH_TELEMETRY_INCLUDE=all` environmental variable to your `.env` file. Note that only the server container currently use this variable. :::tip -`IMMICH_TELEMETRY_INCLUDE=all` enables all metrics. For a more granular configuration you can enumerate the telemetry metrics that should be included as a comma separated list (e.g. `IMMICH_TELEMETRY_INCLUDE=repo,api`). Alternatively, you can also exclude specific metrics with `IMMICH_TELEMETRY_EXCLUDE`. For more information refer to the [environment section](/docs/install/environment-variables.md#prometheus). +`IMMICH_TELEMETRY_INCLUDE=all` enables all metrics. For a more granular configuration you can enumerate the telemetry metrics that should be included as a comma separated list (e.g. `IMMICH_TELEMETRY_INCLUDE=repo,api`). Alternatively, you can also exclude specific metrics with `IMMICH_TELEMETRY_EXCLUDE`. For more information refer to the [environment section](/install/environment-variables.md#prometheus). ::: The next step is to configure a new or existing Prometheus instance to scrape this endpoint. The following steps assume that you do not have an existing Prometheus instance, but the steps will be similar either way. @@ -66,9 +66,9 @@ The provided file is just a starting point. There are a ton of ways to configure After bringing down the containers with `docker compose down` and back up with `docker compose up -d`, a Prometheus instance will now collect metrics from the immich server and microservices containers. Note that we didn't need to expose any new ports for these containers - the communication is handled in the internal Docker network. :::note -To see exactly what metrics are made available, you can additionally add `8081:8081` to the server container's ports and `8082:8082` to the microservices container's ports. +To see exactly what metrics are made available, you can additionally add `8081:8081` (API metrics) and `8082:8082` (microservices metrics) to the immich_server container's ports. Visiting the `/metrics` endpoint for these services will show the same raw data that Prometheus collects. -To configure these ports see [`IMMICH_API_METRICS_PORT` & `IMMICH_MICROSERVICES_METRICS_PORT`](/docs/install/environment-variables/#general). +To configure these ports see [`IMMICH_API_METRICS_PORT` & `IMMICH_MICROSERVICES_METRICS_PORT`](/install/environment-variables/#general). ::: ### Usage diff --git a/docs/docs/features/reverse-geocoding.md b/docs/docs/features/reverse-geocoding.md index 399bdd9b48..b1aee74a99 100644 --- a/docs/docs/features/reverse-geocoding.md +++ b/docs/docs/features/reverse-geocoding.md @@ -8,7 +8,7 @@ During Exif Extraction, assets with latitudes and longitudes are reverse geocode ## Usage -Data from a reverse geocode is displayed in the image details, and used in [Smart Search](/docs/features/searching.md). +Data from a reverse geocode is displayed in the image details, and used in [Smart Search](/features/searching.md). diff --git a/docs/docs/features/sharing.md b/docs/docs/features/sharing.md index ff0a03beea..c19b4f48e1 100644 --- a/docs/docs/features/sharing.md +++ b/docs/docs/features/sharing.md @@ -24,11 +24,11 @@ After creating an album, you can access the sharing options by clicking on the s Partner sharing allows you to share your _entire_ library with other users of your choice. They can then view your library and download the assets. -You can read this guide to learn more about [partner sharing](/docs/features/partner-sharing). +You can read this guide to learn more about [partner sharing](/features/partner-sharing). ## Public sharing -You can create a public link to share a group of photos or videos, or an album, with anyone. The public link can be shared via email, social media, or any other method. There are a varierity of options to customize the public link, such as setting an expiration date, password protection, and more. Public shared link is handy when you want to share a group of photos or videos with someone who doesn't have an Immich account and allow the shared user to upload their photos or videos to your account. +You can create a public link to share a group of photos or videos, or an album, with anyone. The public link can be shared via email, social media, or any other method. There are a variety of options to customize the public link, such as setting an expiration date, password protection, and more. Public shared link is handy when you want to share a group of photos or videos with someone who doesn't have an Immich account and allow the shared user to upload their photos or videos to your account. The public shared link is generated with a random URL, which acts as as a secret to avoid the link being guessed by unwanted parties, for instance. diff --git a/docs/docs/features/tags.md b/docs/docs/features/tags.md index ca663e9edd..79a9696d9a 100644 --- a/docs/docs/features/tags.md +++ b/docs/docs/features/tags.md @@ -1,6 +1,6 @@ # Tags -Immich supports hierarchical tags, with the ability to read existing tags from the `TagList` and `Keywords` EXIF properties. Any changes to tags made through Immich are also written back to a [sidecar](/docs/features/xmp-sidecars) file. You can re-run the metadata extraction jobs for all assets to import your existing tags. +Immich supports hierarchical tags, with the ability to read existing tags from the XMP `TagsList` field and IPTC `Keywords` field. Any changes to tags made through Immich are also written back to a [sidecar](/features/xmp-sidecars) file. You can re-run the metadata extraction jobs for all assets to import your existing tags. ## Enable tags feature diff --git a/docs/docs/features/user-settings.md b/docs/docs/features/user-settings.md index a2d0308541..402105cd43 100644 --- a/docs/docs/features/user-settings.md +++ b/docs/docs/features/user-settings.md @@ -15,9 +15,9 @@ You can access the [user settings](https://my.immich.app/user-settings) by click --- :::tip Reset Password -The admin can reset a user password through the [User Management](/docs/administration/user-management.mdx) screen. +The admin can reset a user password through the [User Management](/administration/user-management.mdx) screen. ::: :::tip Reset Admin Password -The admin password can be reset using a [Server Command](/docs/administration/server-commands.md) +The admin password can be reset using a [Server Command](/administration/server-commands.md) ::: diff --git a/docs/docs/features/xmp-sidecars.md b/docs/docs/features/xmp-sidecars.md index 98ce8782e6..3536777d8a 100644 --- a/docs/docs/features/xmp-sidecars.md +++ b/docs/docs/features/xmp-sidecars.md @@ -1,13 +1,68 @@ # XMP Sidecars -Immich can ingest XMP sidecars on file upload (via the CLI) as well as detect new sidecars that are placed in the filesystem for existing images. +Immich supports XMP sidecar files — external `.xmp` files that store metadata for an image or video in XML format. During the metadata extraction job Immich will read & import metadata from `.xmp` files, and during the Sidecar Write job it will _write_ metadata back to `.xmp`. - +:::tip +Tools like Lightroom, Darktable, digiKam and other applications can also be configured to write changes to `.xmp` files, in order to avoid modifying the original file. +::: -XMP sidecars are external XML files that contain metadata related to media files. Many applications read and write these files either exclusively or in addition to the metadata written to image files. They can be a powerful tool for editing and storing metadata of a media file without modifying the media file itself. When Immich receives or detects an XMP sidecar for a media file, it will attempt to extract the metadata from both the sidecar as well as the media file. It will prioritize the metadata for fields in the sidecar but will fall back and use the metadata in the media file if necessary. +## Metadata Fields -When importing files via the CLI bulk uploader or parsing photo metadata for external libraries, Immich will automatically detect XMP sidecar files as files that exist next to the original media file. Immich will look files that have the same name as the photo, but with the `.xmp` file extension. The same name can either include the photo's file extension or without the photo's file extension. For example, for a photo named `PXL_20230401_203352928.MP.jpg`, Immich will look for an XMP file named either `PXL_20230401_203352928.MP.jpg.xmp` or `PXL_20230401_203352928.MP.xmp`. If both `PXL_20230401_203352928.MP.jpg.xmp` and `PXL_20230401_203352928.MP.xmp` are present, Immich will prefer `PXL_20230401_203352928.MP.jpg.xmp`. +Immich does not support _all_ metadata fields. Below is a table showing what fields Immich can _read_ and _write_. It's important to note that writes do not replace the entire file contents, but are merged together with any existing fields. -There are 2 administrator jobs associated with sidecar files: `SYNC` and `DISCOVER`. The sync job will re-scan all media with existing sidecar files and queue them for a metadata refresh. This is a great use case when third-party applications are used to modify the metadata of media. The discover job will attempt to scan the filesystem for new sidecar files for all media that does not currently have a sidecar file associated with it. +:::info +Immich automatically queues a Sidecar Write job after editing the description, rating, or updating tags. +::: - +| Metadata | Immich writes to XMP | Immich reads from XMP | +| --------------- | ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Description** | `dc:description`, `tiff:ImageDescription` | `dc:description`, `tiff:ImageDescription` | +| **Rating** | `xmp:Rating` | `xmp:Rating` | +| **DateTime** | `exif:DateTimeOriginal`, `photoshop:DateCreated` | In prioritized order:
`exif:SubSecDateTimeOriginal`
`exif:DateTimeOriginal`
`xmp:SubSecCreateDate`
`xmp:CreateDate`
`xmp:CreationDate`
`xmp:MediaCreateDate`
`xmp:SubSecMediaCreateDate`
`xmp:DateTimeCreated` | +| **Location** | `exif:GPSLatitude`, `exif:GPSLongitude` | `exif:GPSLatitude`, `exif:GPSLongitude` | +| **Tags** | `digiKam:TagsList` | In prioritized order:
`digiKam:TagsList`
`lr:HierarchicalSubject`
`IPTC:Keywords` | + +:::note +All other fields (e.g. `Creator`, `Source`, IPTC, Lightroom edits) remain in the `.xmp` file and are **not searchable** in Immich. +::: + +## File Naming Rules + +A sidecar must share the base name of the media file: + +- ✅ `IMG_0001.jpg.xmp` ← preferred +- ✅ `IMG_0001.xmp` ← fallback +- ❌ `myphoto_meta.xmp` ← not recognized + +If both `.jpg.xmp` and `.xmp` are present, Immich uses the **`.jpg.xmp`** file. + +## CLI Support + +1. **Detect** – Immich looks for a `.xmp` file placed next to each media file during upload. +2. **Copy** – Both the media and the sidecar file are copied into Immich’s internal library folder. + The sidecar is renamed to match the internal filename template, e.g.: + `upload/library//YYYY/YYYY-MM-DD/IMG_0001.jpg` + `upload/library//YYYY/YYYY-MM-DD/IMG_0001.jpg.xmp` +3. **Extract** – Selected metadata (title, description, date, rating, tags) is parsed from the sidecar and saved to the database. +4. **Write-back** – If you later update tags, rating, or description in the web UI, Immich will update **both** the database _and_ the copied `.xmp` file to stay in sync. + +## External Library (Mounted Folder) Support + +1. **Detect** – The `DISCOVER` job automatically associates `.xmp` files that sit next to existing media files in your mounted folder. No files are moved or renamed. +2. **Extract** – Immich reads and saves the same metadata fields from the sidecar to the database. +3. **Write-back** – If Immich has **write access** to the mount, any future metadata edits (e.g., rating or tags) are also written back to the original `.xmp` file on disk. + +:::danger +If the mount is **read-only**, Immich cannot update either the sidecar **or** the database — **metadata edits will silently fail** with no warning see issue [#10538](https://github.com/immich-app/immich/issues/10538) for more details. +::: + +## Admin Jobs + +Immich provides two admin jobs for managing sidecars: + +| Job | What it does | +| ---------- | ------------------------------------------------------------------------------------------------- | +| `DISCOVER` | Finds new `.xmp` files next to media that don’t already have one linked | +| `SYNC` | Re-reads existing `.xmp` files and refreshes metadata in the database (e.g. after external edits) | + +![Sidecar Admin Jobs](./img/sidecar-jobs.webp) diff --git a/docs/docs/guides/better-facial-clusters.md b/docs/docs/guides/better-facial-clusters.md index f4409b441c..40796983a5 100644 --- a/docs/docs/guides/better-facial-clusters.md +++ b/docs/docs/guides/better-facial-clusters.md @@ -10,7 +10,7 @@ This guide explains how to optimize facial recognition in systems with large ima - **Best Suited For:** Large image libraries after importing a significant number of images. - **Warning:** This method deletes all previously assigned names. -- **Tip:** **Always take a [backup](/docs/administration/backup-and-restore#database) before proceeding!** +- **Tip:** **Always take a [backup](/administration/backup-and-restore#database) before proceeding!** --- diff --git a/docs/docs/guides/custom-locations.md b/docs/docs/guides/custom-locations.md index af8ca438e7..e0274d3bd9 100644 --- a/docs/docs/guides/custom-locations.md +++ b/docs/docs/guides/custom-locations.md @@ -9,7 +9,7 @@ It is important to remember to update the backup settings after following the gu In our `.env` file, we will define the paths we want to use. Note that you don't have to define all of these: UPLOAD_LOCATION will be the base folder that files are stored in by default, with the other paths acting as overrides. ```diff title=".env" -# You can find documentation for all the supported environment variables [here](/docs/install/environment-variables) +# You can find documentation for all the supported environment variables [here](/install/environment-variables) # Custom location where your uploaded, thumbnails, and transcoded video files are stored - UPLOAD_LOCATION=./library diff --git a/docs/docs/guides/database-queries.md b/docs/docs/guides/database-queries.md index 267e7bf2ad..5cdcdc04c4 100644 --- a/docs/docs/guides/database-queries.md +++ b/docs/docs/guides/database-queries.md @@ -7,7 +7,7 @@ Keep in mind that mucking around in the database might set the Moon on fire. Avo :::tip Run `docker exec -it immich_postgres psql --dbname= --username=` to connect to the database via the container directly. -(Replace `` and `` with the values from your [`.env` file](/docs/install/environment-variables#database)). +(Replace `` and `` with the values from your [`.env` file](/install/environment-variables#database)). ::: ## Assets @@ -142,12 +142,15 @@ DELETE FROM "person" WHERE "name" = 'PersonNameHere'; SELECT "key", "value" FROM "system_metadata" WHERE "key" = 'system-config'; ``` -(Only used when not using the [config file](/docs/install/config-file)) +(Only used when not using the [config file](/install/config-file)) ### File properties ```sql title="Without thumbnails" -SELECT * FROM "asset" WHERE "asset"."previewPath" IS NULL OR "asset"."thumbnailPath" IS NULL; +SELECT * FROM "asset" +WHERE (NOT EXISTS (SELECT 1 FROM "asset_file" WHERE "asset"."id" = "asset_file"."assetId" AND "asset_file"."type" = 'thumbnail') + OR NOT EXISTS (SELECT 1 FROM "asset_file" WHERE "asset"."id" = "asset_file"."assetId" AND "asset_file"."type" = 'preview')) +AND "asset"."visibility" = 'timeline'; ``` ```sql title="Failed file movements" diff --git a/docs/docs/guides/external-library.md b/docs/docs/guides/external-library.md index 7921843297..3f366bb0d4 100644 --- a/docs/docs/guides/external-library.md +++ b/docs/docs/guides/external-library.md @@ -1,13 +1,13 @@ # External Library -This guide walks you through adding an [External Library](/docs/features/libraries). +This guide walks you through adding an [External Library](/features/libraries). This guide assumes you are running Immich in Docker and that the files you wish to access are stored in a directory on the same machine. # Mount the directory into the containers. Edit `docker-compose.yml` to add one or more new mount points in the section `immich-server:` under `volumes:`. -If you want Immich to be able to delete the images in the external library or add metadata ([XMP sidecars](/docs/features/xmp-sidecars)), remove `:ro` from the end of the mount point. +If you want Immich to be able to delete the images in the external library or add metadata ([XMP sidecars](/features/xmp-sidecars)), remove `:ro` from the end of the mount point. ```diff immich-server: @@ -21,6 +21,10 @@ Restart Immich by running `docker compose up -d`. # Create the library +:::info +External library management requires administrator access and the steps below assume you are using an admin account. +::: + In the Immich web UI: - click the **Administration** link in the upper right corner. @@ -33,7 +37,7 @@ In the Immich web UI: - In the dialog, select which user should own the new library - + - Click the three-dots menu and select **Edit Import Paths** diff --git a/docs/docs/guides/remote-access.md b/docs/docs/guides/remote-access.md index 6f401dfc5a..518b003c3a 100644 --- a/docs/docs/guides/remote-access.md +++ b/docs/docs/guides/remote-access.md @@ -46,7 +46,7 @@ You can learn how to set up Tailscale together with Immich with the [tutorial vi A reverse proxy is a service that sits between web servers and clients. A reverse proxy can either be hosted on the server itself or remotely. Clients can connect to the reverse proxy via https, and the proxy relays data to Immich. This setup makes most sense if you have your own domain and want to access your Immich instance just like any other website, from outside your LAN. You can also use a DDNS provider like DuckDNS or no-ip if you don't have a domain. This configuration allows the Immich Android and iphone apps to connect to your server without a VPN or tailscale app on the client side. -If you're hosting your own reverse proxy, [Nginx](https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/) is a great option. An example configuration for Nginx is provided [here](/docs/administration/reverse-proxy.md). +If you're hosting your own reverse proxy, [Nginx](https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/) is a great option. An example configuration for Nginx is provided [here](/administration/reverse-proxy.md). You'll also need your own certificate to authenticate https connections. If you're making Immich publicly accessible, [Let's Encrypt](https://letsencrypt.org/) can provide a free certificate for your domain and is the recommended option. Alternatively, a [self-signed certificate](https://en.wikipedia.org/wiki/Self-signed_certificate) allows you to encrypt your connection to Immich, but it raises a security warning on the client's browser. diff --git a/docs/docs/guides/remote-machine-learning.md b/docs/docs/guides/remote-machine-learning.md index 72ae0e3fa1..0a8ddf2577 100644 --- a/docs/docs/guides/remote-machine-learning.md +++ b/docs/docs/guides/remote-machine-learning.md @@ -1,6 +1,6 @@ # Remote Machine Learning -To alleviate [performance issues on low-memory systems](/docs/FAQ.mdx#why-is-immich-slow-on-low-memory-systems-like-the-raspberry-pi) like the Raspberry Pi, you may also host Immich's machine learning container on a more powerful system, such as your laptop or desktop computer. The server container will send requests containing the image preview to the remote machine learning container for processing. The machine learning container does not persist this data or associate it with a particular user. +To alleviate [performance issues on low-memory systems](/FAQ.mdx#why-is-immich-slow-on-low-memory-systems-like-the-raspberry-pi) like the Raspberry Pi, you may also host Immich's machine learning container on a more powerful system, such as your laptop or desktop computer. The server container will send requests containing the image preview to the remote machine learning container for processing. The machine learning container does not persist this data or associate it with a particular user. :::info Smart Search and Face Detection will use this feature, but Facial Recognition will not. This is because Facial Recognition uses the _outputs_ of these models that have already been saved to the database. As such, its processing is between the server container and the database. @@ -14,7 +14,7 @@ Image previews are sent to the remote machine learning container. Use this optio 2. Copy the following `docker-compose.yml` to the remote server :::info -If using hardware acceleration, the [hwaccel.ml.yml](https://github.com/immich-app/immich/releases/latest/download/hwaccel.ml.yml) file also needs to be added and the `docker-compose.yml` needs to be configured as described in the [hardware acceleration documentation](/docs/features/ml-hardware-acceleration) +If using hardware acceleration, the [hwaccel.ml.yml](https://github.com/immich-app/immich/releases/latest/download/hwaccel.ml.yml) file also needs to be added and the `docker-compose.yml` needs to be configured as described in the [hardware acceleration documentation](/features/ml-hardware-acceleration) ::: ```yaml diff --git a/docs/docs/guides/template-backup-script.md b/docs/docs/guides/template-backup-script.md index 34381dd0ee..19647d4ae1 100644 --- a/docs/docs/guides/template-backup-script.md +++ b/docs/docs/guides/template-backup-script.md @@ -7,7 +7,7 @@ This script assumes you have a second hard drive connected to your server for on The database is saved to your Immich upload folder in the `database-backup` subdirectory. The database is then backed up and versioned with your assets by Borg. This ensures that the database backup is in sync with your assets in every snapshot. :::info -This script makes backups of your database along with your photo/video library. This is redundant with the [automatic database backup tool](https://immich.app/docs/administration/backup-and-restore#automatic-database-backups) built into Immich. Using this script to backup your database has two advantages over the built-in backup tool: +This script makes backups of your database along with your photo/video library. This is redundant with the [automatic database backup tool](/administration/backup-and-restore#automatic-database-dumps) built into Immich. Using this script to backup your database has two advantages over the built-in backup tool: - This script uses storage more efficiently by versioning your backups instead of making multiple copies. - The database backups are performed at the same time as the library backup, ensuring that the backups of your database and the library are always in sync. diff --git a/docs/docs/install/config-file.md b/docs/docs/install/config-file.md index 54d7c61bb3..3fb0687e4a 100644 --- a/docs/docs/install/config-file.md +++ b/docs/docs/install/config-file.md @@ -209,7 +209,7 @@ So you can just grab it from there, paste it into a file and you're pretty much ### Step 2 - Specify the file location In your `.env` file, set the variable `IMMICH_CONFIG_FILE` to the path of your config. -For more information, refer to the [Environment Variables](/docs/install/environment-variables.md) section. +For more information, refer to the [Environment Variables](/install/environment-variables.md) section. :::tip YAML-formatted config files are also supported. diff --git a/docs/docs/install/docker-compose.mdx b/docs/docs/install/docker-compose.mdx index 7a0b566f5d..46b144eb4a 100644 --- a/docs/docs/install/docker-compose.mdx +++ b/docs/docs/install/docker-compose.mdx @@ -29,4 +29,4 @@ If you get an error `can't set healthcheck.start_interval as feature require Doc ## Next Steps -Read the [Post Installation](/docs/install/post-install.mdx) steps and [upgrade instructions](/docs/install/upgrading.md). +Read the [Post Installation](/install/post-install.mdx) steps and [upgrade instructions](/install/upgrading.md). diff --git a/docs/docs/install/environment-variables.md b/docs/docs/install/environment-variables.md index 928e0b26e5..78a5289bf4 100644 --- a/docs/docs/install/environment-variables.md +++ b/docs/docs/install/environment-variables.md @@ -42,7 +42,7 @@ These environment variables are used by the `docker-compose.yml` file and do **N | `IMMICH_MICROSERVICES_METRICS_PORT` | Port for the OTEL metrics | `8082` | server | microservices | | `IMMICH_PROCESS_INVALID_IMAGES` | When `true`, generate thumbnails for invalid images | | server | microservices | | `IMMICH_TRUSTED_PROXIES` | List of comma-separated IPs set as trusted proxies | | server | api | -| `IMMICH_IGNORE_MOUNT_CHECK_ERRORS` | See [System Integrity](/docs/administration/system-integrity) | | server | api, microservices | +| `IMMICH_IGNORE_MOUNT_CHECK_ERRORS` | See [System Integrity](/administration/system-integrity) | | server | api, microservices | \*1: `TZ` should be set to a `TZ identifier` from [this list][tz-list]. For example, `TZ="Etc/UTC"`. `TZ` is used by `exiftool` as a fallback in case the timezone cannot be determined from the image metadata. It is also used for logfile timestamps and cron job execution. @@ -57,7 +57,7 @@ These environment variables are used by the `docker-compose.yml` file and do **N | `IMMICH_WORKERS_EXCLUDE` | Do not run these workers. Matches against default workers, or `IMMICH_WORKERS_INCLUDE` if specified. | | server | :::info -Information on the current workers can be found [here](/docs/administration/jobs-workers). +Information on the current workers can be found [here](/administration/jobs-workers). ::: ## Ports @@ -169,10 +169,9 @@ Redis (Sentinel) URL example JSON before encoding: | `MACHINE_LEARNING_ANN_TUNING_LEVEL` | ARM-NN GPU tuning level (1: rapid, 2: normal, 3: exhaustive) | `2` | machine learning | | `MACHINE_LEARNING_DEVICE_IDS`\*4 | Device IDs to use in multi-GPU environments | `0` | machine learning | | `MACHINE_LEARNING_MAX_BATCH_SIZE__FACIAL_RECOGNITION` | Set the maximum number of faces that will be processed at once by the facial recognition model | None (`1` if using OpenVINO) | machine learning | -| `MACHINE_LEARNING_PING_TIMEOUT` | How long (ms) to wait for a PING response when checking if an ML server is available | `2000` | server | -| `MACHINE_LEARNING_AVAILABILITY_BACKOFF_TIME` | How long to ignore ML servers that are offline before trying again | `30000` | server | | `MACHINE_LEARNING_RKNN` | Enable RKNN hardware acceleration if supported | `True` | machine learning | | `MACHINE_LEARNING_RKNN_THREADS` | How many threads of RKNN runtime should be spinned up while inferencing. | `1` | machine learning | +| `MACHINE_LEARNING_MODEL_ARENA` | Pre-allocates CPU memory to avoid memory fragmentation | true | machine learning | \*1: It is recommended to begin with this parameter when changing the concurrency levels of the machine learning service and then tune the other ones. diff --git a/docs/docs/install/one-click.md b/docs/docs/install/one-click.md new file mode 100644 index 0000000000..53fcb20d21 --- /dev/null +++ b/docs/docs/install/one-click.md @@ -0,0 +1,32 @@ +--- +sidebar_position: 65 +--- + +# One-Click [Cloud Service] + +:::note +This version of Immich is provided via cloud service providers' one-click marketplaces. Hosting costs are set by the cloud service providers. +Support for these are provided by the individual cloud service providers. + +**Please report issues to the corresponding [Github Repository][github].** +::: + +## Installation + +Go to the provider's marketplace and choose Immich, then follow the provided instructions. + +## One-Click Immich marketplace providers + +### DigitalOcean + +https://marketplace.digitalocean.com/apps/immich + +### Vultr + +https://www.vultr.com/marketplace/apps/immich + +## Issues + +For issues, open an issue on the associated [GitHub Repository][github]. + +[github]: https://github.com/immich-app/immich/ diff --git a/docs/docs/install/portainer.md b/docs/docs/install/portainer.md index 916d89a0d5..07fd255292 100644 --- a/docs/docs/install/portainer.md +++ b/docs/docs/install/portainer.md @@ -45,5 +45,5 @@ alt="Dot Env Example" 11. Click on "**Deploy the stack**". :::tip -For more information on how to use the application, please refer to the [Post Installation](/docs/install/post-install.mdx) guide. +For more information on how to use the application, please refer to the [Post Installation](/install/post-install.mdx) guide. ::: diff --git a/docs/docs/install/post-install.mdx b/docs/docs/install/post-install.mdx index 636274aaea..b30e91f3cd 100644 --- a/docs/docs/install/post-install.mdx +++ b/docs/docs/install/post-install.mdx @@ -44,6 +44,6 @@ A list of common steps to take after installing Immich include: ## Setting up optional features -- [External Libraries](/docs/features/libraries.md): Adding your existing photo library to Immich -- [Hardware Transcoding](/docs/features/hardware-transcoding.md): Speeding up video transcoding -- [Hardware-Accelerated Machine Learning](/docs/features/ml-hardware-acceleration.md): Speeding up various machine learning tasks in Immich +- [External Libraries](/features/libraries.md): Adding your existing photo library to Immich +- [Hardware Transcoding](/features/hardware-transcoding.md): Speeding up video transcoding +- [Hardware-Accelerated Machine Learning](/features/ml-hardware-acceleration.md): Speeding up various machine learning tasks in Immich diff --git a/docs/docs/install/script.md b/docs/docs/install/script.md index 93d1fb166c..ce05dc82d9 100644 --- a/docs/docs/install/script.md +++ b/docs/docs/install/script.md @@ -5,12 +5,12 @@ sidebar_position: 20 # Install script [Experimental] :::caution -This method is experimental and not currently recommended for production use. For production, please refer to installing with [Docker Compose](/docs/install/docker-compose.mdx). +This method is experimental and not currently recommended for production use. For production, please refer to installing with [Docker Compose](/install/docker-compose.mdx). ::: ## Requirements -Follow the [requirements page](/docs/install/requirements) to get started. +Follow the [requirements page](/install/requirements) to get started. The install script only supports Linux operating systems and requires Docker to be already installed on the system. @@ -32,5 +32,5 @@ The web application and mobile app will be available at `http:// + Updating Immich using Container Manager +Check the post installation and upgrade instructions at the links above before proceeding with this section. + +## Step 1. Backup + +Ensure your photos and videos are backed up. Your `.env` settings will define where they are stored. There is no need to delete any files or folders within the `docker` folder when doing a release upgrade unless instructed in the release notes. + +## Step 2. Check release notes + +Always check the [release notes](https://github.com/immich-app/immich/releases) before proceeding with an update! + +## Step 3. Stop containers & clean up + +Open **Container Manager**. Select **Project** then your Immich app + +![Select project](../../static/img/synology-select-proj.png) + +Select **Stop** + +![Stop project](../../static/img/synology-project-stop.png) + +Select **Action** then **Clean**. This removes the containers. + +![Clean project](../../static/img/synology-action-clean.png) + +Go to **Image** and select **Remove Unused Images**. + +![Remove unused](../../static/img/synology-remove-unused.png) + +## Step 4. Build + +Go to **Project**, select **Action** then **Build**. This will download, unpack, install and start the containers. + +![Build](../../static/img/synology-build.png) + +## Step 5. Update firewall rule + +The default behavior is to automatically start the containers once installed. If `immich_server` runs for a few seconds and then stops, it may be because the firewall rule no longer matches the server IP address. + +Go to the **Container** section. Click on `immich_server` and scroll down on **General** to find the IP address. +![Container IP](../../static/img/synology-container-ip.png) + +Go to Synology **Control Panel**. Select **Security** and **Firewall**. + +![Firewall](../../static/img/synology-fw-rules.png) + +In this example, the IP addresses mismatch and the firewall rule needs to be edited to match above. + +![Edit IP](../../static/img/synology-fw-ipedit.png) + + diff --git a/docs/docs/install/truenas.md b/docs/docs/install/truenas.md index a13147a1be..9135b72fe6 100644 --- a/docs/docs/install/truenas.md +++ b/docs/docs/install/truenas.md @@ -60,13 +60,13 @@ For an easy setup: :::tip To improve performance, Immich recommends using SSDs for the database. If you have a pool made of SSDs, you can create the `pgData` dataset on that pool. -Thumbnails can also be stored on the SSDs for faster access. This is an advanced option and not required for Immich to run. More information on how you can use multiple datasets to manage Immich storage in a finer-grained manner can be found in the [Advanced: Multiple Datasets for Immich Storage](#advanced-multiple-datasets-for-immich-storage) section below. +Thumbnails can also be stored on the SSDs for faster access. This is an advanced option and not required for Immich to run. More information on how you can use multiple datasets to manage Immich storage in a finer-grained manner can be found in the [Additional Storage: Multiple Datasets for Immich Storage](#additional-storage-advanced-users) section below. ::: :::warning If you just created the datasets using the **Apps** preset, you can skip this warning section. -If the **data** dataset uses ACL it must have [ACL mode](https://www.truenas.com/docs/scale/scaletutorials/datasets/permissionsscale/) set to `Passthrough` if you plan on using a [storage template](/docs/administration/storage-template.mdx) and the dataset is configured for network sharing (its ACL type is set to `SMB/NFSv4`). When the template is applied and files need to be moved from **upload** to **library** (internal folder created by Immich within the **data** dataset), Immich performs `chmod` internally and must be allowed to execute the command. [More info.](https://github.com/immich-app/immich/pull/13017) +If the **data** dataset uses ACL it must have [ACL mode](https://www.truenas.com/docs/scale/scaletutorials/datasets/permissionsscale/) set to `Passthrough` if you plan on using a [storage template](/administration/storage-template.mdx) and the dataset is configured for network sharing (its ACL type is set to `SMB/NFSv4`). When the template is applied and files need to be moved from **upload** to **library** (internal folder created by Immich within the **data** dataset), Immich performs `chmod` internally and must be allowed to execute the command. [More info.](https://github.com/immich-app/immich/pull/13017) To change or verify the ACL mode, go to the **Datasets** screen, select the **library** dataset, click on the **Edit** button next to **Dataset Details**, then click on the **Advanced Options** tab, scroll down to the **ACL Mode** section, and select `Passthrough` from the dropdown menu. Click **Save** to apply the changes. If the option is greyed out, set the **ACL Type** to `SMB/NFSv4` first, then you can change the **ACL Mode** to `Passthrough`. ::: @@ -129,7 +129,7 @@ The **Timezone** is set to the system default, which usually matches your local **Enable Machine Learning** is enabled by default. It allows Immich to use machine learning features such as face recognition, image search, and smart duplicate detection. Untick this option if you do not want to use these features. -Select the **Machine Learning Image Type** based on the hardware you have. More details here: [Hardware-Accelerated Machine Learning](/docs/features/ml-hardware-acceleration.md) +Select the **Machine Learning Image Type** based on the hardware you have. More details here: [Hardware-Accelerated Machine Learning](/features/ml-hardware-acceleration.md) **Database Password** should be set to a custom value using only the characters `A-Za-z0-9`. This password is used to secure the Postgres database. @@ -156,7 +156,7 @@ className="border rounded-xl" /> These are used to add custom configuration options or to enable specific features. -More information on available environment variables can be found in the **[environment variables documentation](/docs/install/environment-variables/)**. +More information on available environment variables can be found in the **[environment variables documentation](/install/environment-variables/)**. :::info Some environment variables are not available for the TrueNAS Community Edition app as they can be configured through GUI options in the [Edit Immich screen](#edit-app-settings). @@ -242,7 +242,7 @@ alt="Add External Libraries with Additional Storage" className="border rounded-xl" /> -You may configure [external libraries](/docs/features/libraries) by mounting them using **Additional Storage**. +You may configure [external libraries](/features/libraries) by mounting them using **Additional Storage**. The dataset that contains your external library files must at least give **read** access to the user running Immich (Default: `apps` (UID 568), `apps` (GID 568)). If you want to be able to delete files or edit metadata in the external library using Immich, you will need to give the **modify** permission to the user running Immich. @@ -266,7 +266,7 @@ A general recommendation is to mount any external libraries to a path beginning This feature should only be used by advanced users. ::: -Immich can use multiple datasets for its storage, allowing you to manage your data more granularly, similar to the old storage configuration. This is useful if you want to separate your data into different datasets for performance or organizational reasons. There is a general guide for this [here](/docs/guides/custom-locations), but read on for the TrueNAS guide. +Immich can use multiple datasets for its storage, allowing you to manage your data more granularly, similar to the old storage configuration. This is useful if you want to separate your data into different datasets for performance or organizational reasons. There is a general guide for this [here](/guides/custom-locations), but read on for the TrueNAS guide. Each additional dataset has to give the permission **_modify_** to the user who will run Immich (Default: `apps` (UID 568), `apps` (GID 568)) As described in the [Setting up Storage Datasets](#setting-up-storage-datasets) section above, you have to create the datasets with the **Apps** preset to ensure the correct permissions are set, or you can set the permissions manually after creating the datasets. @@ -309,7 +309,7 @@ className="border rounded-xl" Both **CPU** and **Memory** are limits, not reservations. This means that Immich can use up to the specified amount of CPU threads and RAM, but it will not reserve that amount of resources at all times. The system will allocate resources as needed, and Immich will use less than the specified amount most of the time. -- Enable **GPU Configuration** options if you have a GPU or CPU with integrated graphics that you will use for [Hardware Transcoding](/docs/features/hardware-transcoding) and/or [Hardware-Accelerated Machine Learning](/docs/features/ml-hardware-acceleration.md). +- Enable **GPU Configuration** options if you have a GPU or CPU with integrated graphics that you will use for [Hardware Transcoding](/features/hardware-transcoding) and/or [Hardware-Accelerated Machine Learning](/features/ml-hardware-acceleration.md). The process for NVIDIA GPU passthrough requires additional steps. More details here: [GPU Passthrough Docs for TrueNAS Apps](https://apps.truenas.com/managing-apps/installing-apps/#gpu-passthrough) @@ -332,7 +332,7 @@ Click **Web Portal** on the **Application Info** widget, or go to the URL `http: After that, you can start using Immich to upload and manage your photos and videos. :::tip -For more information on how to use the application once installed, please refer to the [Post Install](/docs/install/post-install.mdx) guide. +For more information on how to use the application once installed, please refer to the [Post Install](/install/post-install.mdx) guide. ::: ## Edit App Settings @@ -347,7 +347,7 @@ For more information on how to use the application once installed, please refer ## Updating the App :::danger -Make sure to read the general [upgrade instructions](/docs/install/upgrading.md). +Make sure to read the general [upgrade instructions](/install/upgrading.md). ::: When updates become available, TrueNAS alerts and provides easy updates. @@ -387,27 +387,35 @@ To migrate from the old storage configuration to the new one, you will need to c 3. **Copy the data** from the old datasets to the new dataset. We advise using the `rsync` command to copy the data, as it will preserve the permissions and ownership of the files. The following commands are examples: ```bash -rsync -av /mnt/tank/immich/library/ /mnt/tank/immich/data/library/ -rsync -av /mnt/tank/immich/upload/ /mnt/tank/immich/data/upload/ -rsync -av /mnt/tank/immich/thumbs/ /mnt/tank/immich/data/thumbs/ -rsync -av /mnt/tank/immich/profile/ /mnt/tank/immich/data/profile/ -rsync -av /mnt/tank/immich/video/ /mnt/tank/immich/data/encoded-video/ -rsync -av /mnt/tank/immich/backups/ /mnt/tank/immich/data/backups/ +sudo rsync -av /mnt/tank/immich/library/ /mnt/tank/immich/data/library/ +sudo rsync -av /mnt/tank/immich/upload/ /mnt/tank/immich/data/upload/ +sudo rsync -av /mnt/tank/immich/thumbs/ /mnt/tank/immich/data/thumbs/ +sudo rsync -av /mnt/tank/immich/profile/ /mnt/tank/immich/data/profile/ +sudo rsync -av /mnt/tank/immich/video/ /mnt/tank/immich/data/encoded-video/ +sudo rsync -av /mnt/tank/immich/backups/ /mnt/tank/immich/data/backups/ ``` Make sure to replace `/mnt/tank/immich/` with the correct path to your old datasets and `/mnt/tank/immich/data/` with the correct path to your new dataset. :::tip -If you were using **ixVolume (dataset created automatically by the system)** for Immich data storage, the path to the data should be `/mnt/.ix-apps/app_mounts/immich/`. You have to use this path instead of `/mnt/tank/immich/` in the `rsync` command above, for example: +If you were using **ixVolume (dataset created automatically by the system)** for some of Immich data storage, the path to the data should be `/mnt/.ix-apps/app_mounts/immich/`. You have to use this path instead of `/mnt/tank/immich/` in the `rsync` command above, for example: ```bash -rsync -av /mnt/.ix-apps/app_mounts/immich/library/ /mnt/tank/immich/data/library/ +sudo rsync -av /mnt/.ix-apps/app_mounts/immich/library/ /mnt/tank/immich/data/library/ ``` +If you also were storing your files in the **ixVolume**, the **_upload_** folder is named `uploads` instead of `upload`, so the command to run should be: + +```bash +sudo rsync -av /mnt/.ix-apps/app_mounts/immich/uploads/ /mnt/tank/immich/data/upload/ +``` + +This means that depending on your old storage configuration, you might have to use a mix of paths in the `rsync` commands above. + If you were also using an ixVolume for Postgres data storage, you also should, first create the pgData dataset, as described in the [Setting up Storage Datasets](#setting-up-storage-datasets) section above, and then you can use the following command to copy the Postgres data: ```bash -rsync -av /mnt/.ix-apps/app_mounts/immich/pgData/ /mnt/tank/immich/pgData/ +sudo rsync -av /mnt/.ix-apps/app_mounts/immich/pgData/ /mnt/tank/immich/pgData/ ``` ::: @@ -416,7 +424,7 @@ rsync -av /mnt/.ix-apps/app_mounts/immich/pgData/ /mnt/tank/immich/pgData/ Make sure that for each folder, the `.immich` file is copied as well, as it contains important metadata for Immich. If for some reason the `.immich` file is not copied, you can copy it manually with the `rsync` command, for example: ```bash -rsync -av /mnt/tank/immich/library/.immich /mnt/tank/immich/data/library/ +sudo rsync -av /mnt/tank/immich/library/.immich /mnt/tank/immich/data/library/ ``` Replace `library` with the name of the folder where you are copying the file. @@ -437,38 +445,37 @@ This will recreate the Immich container with the new storage configuration and s If everything went well, you should now be able to access Immich with the new storage configuration. You can verify that the data has been copied correctly by checking the Immich web interface and ensuring that all your photos and videos are still available. You may delete the old datasets, if you no longer need them, using the TrueNAS web interface. +:::tip If you were using **ixVolume (dataset created automatically by the system)** or folders for Immich data storage, you can delete the old datasets using the following commands: ```bash -rm -r /mnt/.ix-apps/app_mounts/immich/library -rm -r /mnt/.ix-apps/app_mounts/immich/uploads -rm -r /mnt/.ix-apps/app_mounts/immich/thumbs -rm -r /mnt/.ix-apps/app_mounts/immich/profile -rm -r /mnt/.ix-apps/app_mounts/immich/video -rm -r /mnt/.ix-apps/app_mounts/immich/backups +sudo rm -r /mnt/.ix-apps/app_mounts/immich/* ``` +::: + - + To migrate from the old storage configuration to the new one without creating new datasets. + 1. **Stop the Immich app** from the TrueNAS web interface to ensure no data is being written while you are updating the app. -2. **Update the datasets permissions**: Ensure that the datasets used for Immich data storage (`library`, `upload`, `thumbs`, `profile`, `video`, `backups`) have the correct permissions set for the user who will run Immich. The user should have ***modify*** permissions on these datasets. The default user for Immich is `apps` (UID 568) and the default group is `apps` (GID 568). If you are using a different user, make sure to set the permissions accordingly. You can do this from the TrueNAS web interface by going to the **Datasets** screen, selecting each dataset, clicking on the **Edit** button next to **Permissions**, and adding the user with ***modify*** permissions. +2. **Update the datasets permissions**: Ensure that the datasets used for Immich data storage (`library`, `upload`, `thumbs`, `profile`, `video`, `backups`) have the correct permissions set for the user who will run Immich. The user should have **_modify_** permissions on these datasets. The default user for Immich is `apps` (UID 568) and the default group is `apps` (GID 568). If you are using a different user, make sure to set the permissions accordingly. You can do this from the TrueNAS web interface by going to the **Datasets** screen, selecting each dataset, clicking on the **Edit** button next to **Permissions**, and adding the user with **_modify_** permissions. 3. **Update the Immich app** to use the existing datasets: - - Go to the **Installed Applications** screen and select Immich from the list of installed applications. - - Click **Edit** on the **Application Info** widget. - - In the **Storage Configuration** section, untick the **Use Old Storage Configuration (Deprecated)** checkbox. - - For the **Data Storage**, you can keep the **ixVolume (dataset created automatically by the system)** as no data will be directly written to it. We recommend selecting **Host Path (Path that already exists on the system)** and then select a **new** dataset you created for Immich data storage, for example, `data`. - - For the **Postgres Data Storage**, keep **Host Path (Path that already exists on the system)** and then select the existing dataset you used for Postgres data storage, for example, `pgData`. - - Following the instructions in the [Multiple Datasets for Immich Storage](#additional-storage-advanced-users) section, you can add, **for each old dataset**, a new Additional Storage with the following settings: - - **Type**: `Host Path (Path that already exists on the system)` - - **Mount Path**: `/data/` (e.g. `/data/library`) - - **Host Path**: `/mnt//` (e.g. `/mnt/tank/immich/library`) - :::danger Ensure using the correct paths names - Make sure to replace `` with the actual name of the folder used by Immich: `library`, `upload`, `thumbs`, `profile`, `encoded-video`, and `backups`. Also, replace `` and `` with the actual names of your pool and dataset. - ::: - - **Read Only**: Keep it unticked as Immich needs to write to these datasets. - - Click **Update** at the bottom of the page to save changes. + - Go to the **Installed Applications** screen and select Immich from the list of installed applications. + - Click **Edit** on the **Application Info** widget. + - In the **Storage Configuration** section, untick the **Use Old Storage Configuration (Deprecated)** checkbox. + - For the **Data Storage**, you can keep the **ixVolume (dataset created automatically by the system)** as no data will be directly written to it. We recommend selecting **Host Path (Path that already exists on the system)** and then select a **new** dataset you created for Immich data storage, for example, `data`. + - For the **Postgres Data Storage**, keep **Host Path (Path that already exists on the system)** and then select the existing dataset you used for Postgres data storage, for example, `pgData`. + - Following the instructions in the [Multiple Datasets for Immich Storage](#additional-storage-advanced-users) section, you can add, **for each old dataset**, a new Additional Storage with the following settings: + - **Type**: `Host Path (Path that already exists on the system)` + - **Mount Path**: `/data/` (e.g. `/data/library`) + - **Host Path**: `/mnt//` (e.g. `/mnt/tank/immich/library`) + :::danger Ensure using the correct paths names + Make sure to replace `` with the actual name of the folder used by Immich: `library`, `upload`, `thumbs`, `profile`, `encoded-video`, and `backups`. Also, replace `` and `` with the actual names of your pool and dataset. + ::: + - **Read Only**: Keep it unticked as Immich needs to write to these datasets. + - Click **Update** at the bottom of the page to save changes. 4. **Start the Immich app** from the TrueNAS web interface. This will recreate the Immich container with the new storage configuration and start the app. If everything went well, you should now be able to access Immich with the new storage configuration. You can verify that the data is still available by checking the Immich web interface and ensuring that all your photos and videos are still accessible. diff --git a/docs/docs/install/unraid.md b/docs/docs/install/unraid.md index efb493f267..ca7263a1e8 100644 --- a/docs/docs/install/unraid.md +++ b/docs/docs/install/unraid.md @@ -125,13 +125,13 @@ alt="Go to Docker Tab and visit the address listed next to immich-web" :::tip -For more information on how to use the application once installed, please refer to the [Post Install](/docs/install/post-install.mdx) guide. +For more information on how to use the application once installed, please refer to the [Post Install](/install/post-install.mdx) guide. ::: ## Updating Steps :::danger -Make sure to read the general [upgrade instructions](/docs/install/upgrading.md). +Make sure to read the general [upgrade instructions](/install/upgrading.md). ::: Updating is extremely easy however it's important to be aware that containers managed via the Docker Compose Manager plugin do not integrate with Unraid's native dockerman UI, the label "_update ready_" will always be present on containers installed via the Docker Compose Manager. diff --git a/docs/docs/install/upgrading.md b/docs/docs/install/upgrading.md index d638a6f7d1..bf788cb680 100644 --- a/docs/docs/install/upgrading.md +++ b/docs/docs/install/upgrading.md @@ -4,9 +4,7 @@ sidebar_position: 95 # Upgrading -:::danger Read the release notes -Immich is currently under heavy development, which means you can expect [breaking changes][breaking] and bugs. You should read the release notes prior to updating and take special care when using automated tools like [Watchtower][watchtower]. - +:::tip Breaking changes You can see versions that had breaking changes [here][breaking]. ::: @@ -40,7 +38,7 @@ If you do not deploy Immich using Docker Compose and see a deprecation warning f Immich has migrated off of the deprecated pgvecto.rs database extension to its successor, [VectorChord](https://github.com/tensorchord/VectorChord), which comes with performance improvements in almost every aspect. This section will guide you on how to make this change in a Docker Compose setup. -Before making any changes, please [back up your database](/docs/administration/backup-and-restore). While every effort has been made to make this migration as smooth as possible, there’s always a chance that something can go wrong. +Before making any changes, please [back up your database](/administration/backup-and-restore). While every effort has been made to make this migration as smooth as possible, there’s always a chance that something can go wrong. After making a backup, please modify your `docker-compose.yml` file with the following information. @@ -89,7 +87,7 @@ After making a backup, please modify your `docker-compose.yml` file with the fol If you deviated from the defaults of pg14 or pgvectors0.2.0, you must adjust the pg major version and pgvecto.rs version. If you are still using the default `docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0` image, you can just follow the changes above. For example, if the previous image is `docker.io/tensorchord/pgvecto-rs:pg16-v0.3.0`, the new image should be `ghcr.io/immich-app/postgres:16-vectorchord0.3.0-pgvectors0.3.0` instead of the image specified in the diff. ::: -After making these changes, you can start Immich as normal. Immich will make some changes to the DB during startup, which can take seconds to minutes to finish, depending on hardware and library size. In particular, it’s normal for the server logs to be seemingly stuck at `Reindexing clip_index` and `Reindexing face_index`for some time if you have over 100k assets in Immich and/or Immich is on a relatively weak server. If you see these logs and there are no errors, just give it time. +After making these changes, you can start Immich as normal. Immich will make some changes to the DB during startup, which can take seconds to minutes to finish, depending on hardware and library size. In particular, it’s normal for the server logs to be seemingly stuck at `Reindexing clip_index` and `Reindexing face_index` for some time if you have over 100k assets in Immich and/or Immich is on a relatively weak server. If you see these logs and there are no errors, just give it time. :::danger After switching to VectorChord, you should not downgrade Immich below 1.133.0. @@ -101,7 +99,7 @@ Please don’t hesitate to contact us on [GitHub](https://github.com/immich-app/ #### I have a separate PostgreSQL instance shared with multiple services. How can I switch to VectorChord? -Please see the [standalone PostgreSQL documentation](/docs/administration/postgres-standalone#migrating-to-vectorchord) for migration instructions. The migration path will be different depending on whether you’re currently using pgvecto.rs or pgvector, as well as whether Immich has superuser DB permissions. +Please see the [standalone PostgreSQL documentation](/administration/postgres-standalone#migrating-to-vectorchord) for migration instructions. The migration path will be different depending on whether you’re currently using pgvecto.rs or pgvector, as well as whether Immich has superuser DB permissions. #### Why are so many lines removed from the `docker-compose.yml` file? Does this mean the health check is removed? diff --git a/docs/docs/overview/help.md b/docs/docs/overview/help.md index f38ecde168..e6523547fa 100644 --- a/docs/docs/overview/help.md +++ b/docs/docs/overview/help.md @@ -6,7 +6,7 @@ sidebar_position: 6 Running into an issue or have a question? Try the following: -1. Check the [FAQs](/docs/FAQ.mdx). +1. Check the [FAQs](/FAQ.mdx). 2. Read through the [Release Notes][github-releases]. 3. Search through existing [GitHub Issues][github-issues]. 4. Open a help ticket on [Discord][discord-link]. diff --git a/docs/docs/overview/img/social-preview-light.webp b/docs/docs/overview/img/social-preview-light.webp deleted file mode 100644 index 3d088f6522..0000000000 Binary files a/docs/docs/overview/img/social-preview-light.webp and /dev/null differ diff --git a/docs/docs/overview/quick-start.mdx b/docs/docs/overview/quick-start.mdx index 28cee15007..d80a194ad2 100644 --- a/docs/docs/overview/quick-start.mdx +++ b/docs/docs/overview/quick-start.mdx @@ -13,7 +13,7 @@ to install and use it. - A system with at least 4GB of RAM and 2 CPU cores. - [Docker](https://docs.docker.com/engine/install/) -> For a more detailed list of requirements, see the [requirements page](/docs/install/requirements). +> For a more detailed list of requirements, see the [requirements page](/install/requirements). --- @@ -61,7 +61,7 @@ import MobileAppBackup from '/docs/partials/_mobile-app-backup.md'; The backup time differs depending on how many photos are on your mobile device. Large uploads may take quite a while. -To quickly get going, you can selectively upload few photos first, by following this [guide](/docs/features/mobile-app#sync-only-selected-photos). +To quickly get going, you can selectively upload few photos first, by following this [guide](/features/mobile-app#sync-only-selected-photos). You can select the **Jobs** tab to see Immich processing your photos. @@ -72,7 +72,7 @@ You can select the **Jobs** tab to see Immich processing your photos. ## Review the database backup and restore process Immich has built-in database backups. You can refer to the -[database backup](/docs/administration/backup-and-restore) for more information. +[database backup](/administration/backup-and-restore) for more information. :::danger The database only contains metadata and user information. You must setup manual backups of the images and videos stored in `UPLOAD_LOCATION`. @@ -86,8 +86,8 @@ You may decide you'd like to install the server a different way; the Install cat You may decide you'd like to add the _rest_ of your photos from Google Photos, even those not on your mobile device, via Google Takeout. You can use [immich-go](https://github.com/simulot/immich-go) for this. -You may want to [upload photos from your own archive](/docs/features/command-line-interface). +You may want to [upload photos from your own archive](/features/command-line-interface). -You may want to incorporate a pre-existing archive of photos from an [External Library](/docs/features/libraries); there's a [guide](/docs/guides/external-library) for that. +You may want to incorporate a pre-existing archive of photos from an [External Library](/features/libraries); there's a [guide](/guides/external-library) for that. -You may want your mobile device to [back photos up to your server automatically](/docs/features/automatic-backup). +You may want your mobile device to [back photos up to your server automatically](/features/automatic-backup). diff --git a/docs/docs/overview/support-the-project.md b/docs/docs/overview/support-the-project.md index a439893a7e..ae24a3f1ce 100644 --- a/docs/docs/overview/support-the-project.md +++ b/docs/docs/overview/support-the-project.md @@ -10,11 +10,11 @@ By far the easiest way to help make Immich better it to use it and report issues ## Translations -Support the project by localizing on [Weblate](https://hosted.weblate.org/projects/immich/immich/). For more information, see the [Translations](/docs/developer/translations) section. +Support the project by localizing on [Weblate](https://hosted.weblate.org/projects/immich/immich/). For more information, see the [Translations](/developer/translations) section. ## Development -If you are a programmer or developer, take a look at Immich's [technology stack](/docs/developer/architecture.mdx) and consider fixing bugs or building new features. The team and I are always looking for new contributors. For information about how to contribute as a developer, see the [Developer](/docs/developer/architecture.mdx) section. +If you are a programmer or developer, take a look at Immich's [technology stack](/developer/architecture.mdx) and consider fixing bugs or building new features. The team and I are always looking for new contributors. For information about how to contribute as a developer, see the [Developer](/developer/architecture.mdx) section. ## Purchase Immich diff --git a/docs/docs/overview/welcome.mdx b/docs/docs/overview/welcome.mdx deleted file mode 100644 index 93ce705369..0000000000 --- a/docs/docs/overview/welcome.mdx +++ /dev/null @@ -1,27 +0,0 @@ ---- -sidebar_position: 1 ---- - -# Welcome to Immich - -Immich - Self-hosted photos and videos backup tool - -## Welcome! - -Hello, I am glad you are here. - -My name is Alex. I am an Electrical Engineer by schooling, then turned into a Software Engineer by trade and the pure love of problem solving. - -We were lying in bed with our newborn, and my wife said, "We are starting to accumulate a lot of photos and videos of our baby, and I don't want to pay for **_App-Which-Must-Not-Be-Named_** anymore. You always want to build something for me, so why don't you build me an app which can do that?" - -That was how the idea started to grow in my head. After that, I began to find existing solutions in the self-hosting space with similar backup functionality and the performance level of the **_App-Which-Must-Not-Be-Named_**. I found that the current solutions mainly focus on the gallery-type application. However, I want a simple-to-use backup tool with a native mobile app that can view photos and videos efficiently. So I set sail on this journey as a hungry engineer on the hunt. - -Another motivation that pushed me to deliver my execution of the **_App-Which-Must-Not-Be-Named_** alternative or replacement is for contributing back to the open source community that I have greatly benefited from over the years. - -I'm proud to share this creation with you, which values privacy, memories, and the joy of looking back at those moments in an easy-to-use and friendly interface. - -If you like the application or it helps you in some way, please consider [supporting](./support-the-project.md) the project. It will help me to continue to develop and maintain the application. diff --git a/docs/docs/partials/_server-backup.md b/docs/docs/partials/_server-backup.md index b9479600aa..34e09670e9 100644 --- a/docs/docs/partials/_server-backup.md +++ b/docs/docs/partials/_server-backup.md @@ -1,7 +1,6 @@ Now that you have imported some pictures, you should setup server backups to preserve your memories. -You can do so by following our [backup guide](/docs/administration/backup-and-restore.md). +You can do so by following our [backup guide](/administration/backup-and-restore.md). -:::danger -Immich is still under heavy development _and_ handles very important data. -It is essential that you set up good backups, and test them. +:::info +A 3-2-1 backup strategy is still crucial. The team has the responsibility to ensure that the application doesn’t cause loss of your precious memories; however, we cannot guarantee that hard drives will not fail, or an electrical event causes unexpected shutdown of your server/system, leading to data loss. Therefore, we still encourage users to follow best practices when safeguarding their data. Keep multiple copies of your most precious data: at least two local copies and one copy offsite in cold storage. ::: diff --git a/docs/docs/partials/_storage-template.md b/docs/docs/partials/_storage-template.md index 20e9caac43..84236e0ac1 100644 --- a/docs/docs/partials/_storage-template.md +++ b/docs/docs/partials/_storage-template.md @@ -1,7 +1,7 @@ -Immich allows the admin user to set the uploaded filename pattern at the directory and filename level as well as the [storage label for a user](/docs/administration/user-management/#set-storage-label-for-user). +Immich allows the admin user to set the uploaded filename pattern at the directory and filename level as well as the [storage label for a user](/administration/user-management/#set-storage-label-for-user). :::tip -You can read more about the differences between storage template engine on and off [here](/docs/administration/backup-and-restore#asset-types-and-storage-locations) +You can read more about the differences between storage template engine on and off [here](/administration/backup-and-restore#asset-types-and-storage-locations) ::: The admin user can set the template by using the template builder in the `Administration -> Settings -> Storage Template`. Immich provides a set of variables that you can use in constructing the template, along with additional custom text. If the template produces [multiple files with the same filename, they won't be overwritten](https://github.com/immich-app/immich/discussions/3324) as a sequence number is appended to the filename. diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index d612dda253..70e0189a00 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -7,7 +7,7 @@ const prism = require('prism-react-renderer'); const config = { title: 'Immich', tagline: 'High performance self-hosted photo and video backup solution directly from your mobile phone', - url: 'https://immich.app', + url: 'https://docs.immich.app', baseUrl: '/', onBrokenLinks: 'throw', onBrokenMarkdownLinks: 'warn', @@ -42,26 +42,19 @@ const config = { ], presets: [ [ - 'docusaurus-preset-openapi', - /** @type {import('docusaurus-preset-openapi').Options} */ + 'classic', + /** @type {import('@docusaurus/preset-classic').Options} */ ({ docs: { showLastUpdateAuthor: true, showLastUpdateTime: true, + routeBasePath: '/', sidebarPath: require.resolve('./sidebars.js'), // Please change this to your repo. // Remove this to remove the "edit this page" links. editUrl: 'https://github.com/immich-app/immich/tree/main/docs/', }, - api: { - path: '../open-api/immich-openapi-specs.json', - routeBasePath: '/docs/api', - }, - // blog: { - // showReadingTime: true, - // editUrl: "https://github.com/immich-app/immich/tree/main/docs/", - // }, theme: { customCss: require.resolve('./src/css/custom.css'), }, @@ -72,11 +65,6 @@ const config = { themeConfig: /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ ({ - announcementBar: { - id: 'site_announcement_immich', - content: `âš ī¸ The project is under very active development. Expect bugs and changes. Do not use it as the only way to store your photos and videos!`, - isCloseable: false, - }, docs: { sidebar: { autoCollapseCategories: false, @@ -95,17 +83,17 @@ const config = { position: 'right', }, { - to: '/docs/overview/welcome', + to: '/overview/quick-start', position: 'right', label: 'Docs', }, { - to: '/roadmap', + href: 'https://immich.app/roadmap', position: 'right', label: 'Roadmap', }, { - to: '/docs/api', + href: 'https://api.immich.app/', position: 'right', label: 'API', }, @@ -139,16 +127,16 @@ const config = { title: 'Overview', items: [ { - label: 'Welcome', - to: '/docs/overview/welcome', + label: 'Quick start', + to: '/overview/quick-start', }, { label: 'Installation', - to: '/docs/install/requirements', + to: '/install/requirements', }, { label: 'Contributing', - to: '/docs/overview/support-the-project', + to: '/overview/support-the-project', }, { label: 'Privacy Policy', @@ -161,15 +149,15 @@ const config = { items: [ { label: 'Roadmap', - to: '/roadmap', + href: 'https://immich.app/roadmap', }, { label: 'API', - to: '/docs/api', + href: 'https://api.immich.app/', }, { label: 'Cursed Knowledge', - to: '/cursed-knowledge', + href: 'https://immich.app/cursed-knowledge', }, ], }, diff --git a/docs/package.json b/docs/package.json index fdf1da447c..f45a4ec256 100644 --- a/docs/package.json +++ b/docs/package.json @@ -17,17 +17,14 @@ "write-heading-ids": "docusaurus write-heading-ids" }, "dependencies": { - "@docusaurus/core": "~3.8.0", - "@docusaurus/preset-classic": "~3.8.0", - "@docusaurus/theme-common": "~3.8.0", + "@docusaurus/core": "~3.9.0", + "@docusaurus/preset-classic": "~3.9.0", + "@docusaurus/theme-common": "~3.9.0", "@mdi/js": "^7.3.67", "@mdi/react": "^1.6.1", "@mdx-js/react": "^3.0.0", "autoprefixer": "^10.4.17", - "classnames": "^2.3.2", - "clsx": "^2.0.0", "docusaurus-lunr-search": "^3.3.2", - "docusaurus-preset-openapi": "^0.7.5", "lunr": "^2.3.9", "postcss": "^8.4.25", "prism-react-renderer": "^2.3.1", @@ -38,7 +35,7 @@ "url": "^0.11.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "~3.8.0", + "@docusaurus/module-type-aliases": "~3.9.0", "@docusaurus/tsconfig": "^3.7.0", "@docusaurus/types": "^3.7.0", "prettier": "^3.2.4", @@ -60,6 +57,6 @@ "node": ">=20" }, "volta": { - "node": "22.19.0" + "node": "22.20.0" } } diff --git a/docs/src/components/community-guides.tsx b/docs/src/components/community-guides.tsx index 49ba7a8a08..08c8e096d9 100644 --- a/docs/src/components/community-guides.tsx +++ b/docs/src/components/community-guides.tsx @@ -28,6 +28,12 @@ const guides: CommunityGuidesProps[] = [ description: `synchronize folders in imported library with albums having the folders name.`, url: 'https://github.com/immich-app/immich/discussions/3382', }, + { + title: 'Immich Podman Quadlets Handbook', + description: + 'A rewrite of the original Immich Docker Compose file using Podman Quadlets, with a set of extra guides in the repository’s wiki.', + url: 'https://github.com/linux-universe/immich-podman-quadlets/blob/main/README.md', + }, { title: 'Podman/Quadlets Install', description: 'Documentation for simple podman setup using quadlets.', diff --git a/docs/src/components/community-projects.tsx b/docs/src/components/community-projects.tsx index 46e28b3b76..6b74ae7ad8 100644 --- a/docs/src/components/community-projects.tsx +++ b/docs/src/components/community-projects.tsx @@ -23,11 +23,6 @@ const projects: CommunityProjectProps[] = [ description: 'A Python script to sync folders as albums.', url: 'https://git.orenit.solutions/open/immichalbumpull', }, - { - title: 'Remove offline files', - description: 'A simple way to remove orphaned offline assets from the Immich database', - url: 'https://github.com/Thoroslives/immich_remove_offline_files', - }, { title: 'Immich-Tools', description: 'Provides scripts for handling problems on the repair page.', @@ -105,6 +100,26 @@ const projects: CommunityProjectProps[] = [ description: 'Speed up your machine learning by load balancing your requests to multiple computers', url: 'https://github.com/apetersson/immich_ml_balancer', }, + { + title: 'Immich Drop Uploader', + description: 'A tiny, zero-login web app for collecting photos/videos from anyone into your Immich server.', + url: 'https://github.com/Nasogaa/immich-drop', + }, + { + title: 'Immich Birthday Sync', + description: 'Bulk-upload and -download birthdays, with CardDAV sync support', + url: 'https://github.com/sid3windr/immich-birthday', + }, + { + title: 'Immich Stack', + description: 'Auto-stack photos with identical filenames and differing extensions (i.e. JPG+RAW)', + url: 'https://github.com/sid3windr/immich-stack', + }, + { + title: 'Immich Stack', + description: 'Automatically groups similar photos into stacks within the Immich photo management system.', + url: 'https://github.com/Majorfi/immich-stack/', + }, ]; function CommunityProject({ title, description, url }: CommunityProjectProps): JSX.Element { diff --git a/docs/src/components/version-switcher.tsx b/docs/src/components/version-switcher.tsx index 5cb23891aa..739d7bd001 100644 --- a/docs/src/components/version-switcher.tsx +++ b/docs/src/components/version-switcher.tsx @@ -11,7 +11,7 @@ export default function VersionSwitcher(): JSX.Element { useEffect(() => { async function getVersions() { try { - let baseUrl = 'https://immich.app'; + let baseUrl = 'https://docs.immich.app'; if (window.location.origin === 'http://localhost:3005') { baseUrl = window.location.origin; } @@ -21,12 +21,13 @@ export default function VersionSwitcher(): JSX.Element { const archiveVersions = await response.json(); const allVersions = [ - { label: 'Next', url: 'https://main.preview.immich.app' }, - { label: 'Latest', url: 'https://immich.app' }, + { label: 'Next', url: 'https://docs.main.preview.immich.app' }, + { label: 'Latest', url: 'https://docs.immich.app' }, ...archiveVersions, - ].map(({ label, url }) => ({ + ].map(({ label, url, rootPath }) => ({ label, url: new URL(url), + rootPath, })); setVersions(allVersions); @@ -50,12 +51,18 @@ export default function VersionSwitcher(): JSX.Element { className="version-switcher-34ab39" label={activeLabel} mobile={windowSize === 'mobile'} - items={versions.map(({ label, url }) => ({ - label, - to: new URL(location.pathname + location.search + location.hash, url).href, - target: '_self', - className: label === activeLabel ? 'dropdown__link--active menu__link--active' : '', // workaround because React Router `` only supports using URL path for checking if active: https://v5.reactrouter.com/web/api/NavLink/isactive-func - }))} + items={versions.map(({ label, url, rootPath }) => { + let path = location.pathname + location.search + location.hash; + if (rootPath && !path.startsWith(rootPath)) { + path = rootPath + path; + } + return { + label, + to: new URL(path, url).href, + target: '_self', + className: label === activeLabel ? 'dropdown__link--active menu__link--active' : '', // workaround because React Router `` only supports using URL path for checking if active: https://v5.reactrouter.com/web/api/NavLink/isactive-func + }; + })} /> ) ); diff --git a/docs/src/pages/cursed-knowledge.tsx b/docs/src/pages/cursed-knowledge.tsx deleted file mode 100644 index f3dacc2ce6..0000000000 --- a/docs/src/pages/cursed-knowledge.tsx +++ /dev/null @@ -1,273 +0,0 @@ -import { - mdiBug, - mdiCalendarToday, - mdiCrosshairsOff, - mdiCrop, - mdiDatabase, - mdiLeadPencil, - mdiLockOff, - mdiLockOutline, - mdiMicrosoftWindows, - mdiSecurity, - mdiSpeedometerSlow, - mdiTrashCan, - mdiWeb, - mdiWrap, - mdiCloudKeyOutline, - mdiRegex, - mdiCodeJson, - mdiClockOutline, - mdiAccountOutline, - mdiRestart, -} from '@mdi/js'; -import Layout from '@theme/Layout'; -import React from 'react'; -import { Timeline, Item as TimelineItem } from '../components/timeline'; - -const withLanguage = (date: Date) => (language: string) => date.toLocaleDateString(language); - -type Item = Omit & { date: Date }; - -const items: Item[] = [ - { - icon: mdiClockOutline, - iconColor: 'gray', - title: 'setTimeout is cursed', - description: - 'The setTimeout method in JavaScript is cursed when used with small values because the implementation may or may not actually wait the specified time.', - link: { - url: 'https://github.com/immich-app/immich/pull/20655', - text: '#20655', - }, - date: new Date(2025, 7, 4), - }, - { - icon: mdiAccountOutline, - iconColor: '#DAB1DA', - title: 'PostgreSQL USER is cursed', - description: - 'The USER keyword in PostgreSQL is cursed because you can select from it like a table, which leads to confusion if you have a table name user as well.', - link: { - url: 'https://github.com/immich-app/immich/pull/19891', - text: '#19891', - }, - date: new Date(2025, 7, 4), - }, - { - icon: mdiRestart, - iconColor: '#8395e3', - title: 'PostgreSQL RESET is cursed', - description: - 'PostgreSQL RESET is cursed because it is impossible to RESET a PostgreSQL extension parameter if the extension has been uninstalled.', - link: { - url: 'https://github.com/immich-app/immich/pull/19363', - text: '#19363', - }, - date: new Date(2025, 5, 20), - }, - { - icon: mdiRegex, - iconColor: 'purple', - title: 'Zitadel Actions are cursed', - description: - "Zitadel is cursed because its custom scripting feature is executed with a JS engine that doesn't support regex named capture groups.", - link: { - url: 'https://github.com/dop251/goja', - text: 'Go JS engine', - }, - date: new Date(2025, 5, 4), - }, - { - icon: mdiCloudKeyOutline, - iconColor: '#0078d4', - title: 'Entra is cursed', - description: - "Microsoft Entra supports PKCE, but doesn't include it in its OpenID discovery document. This leads to clients thinking PKCE isn't available.", - link: { - url: 'https://github.com/immich-app/immich/pull/18725', - text: '#18725', - }, - date: new Date(2025, 4, 30), - }, - { - icon: mdiCrop, - iconColor: 'tomato', - title: 'Image dimensions in EXIF metadata are cursed', - description: - 'The dimensions in EXIF metadata can be different from the actual dimensions of the image, causing issues with cropping and resizing.', - link: { - url: 'https://github.com/immich-app/immich/pull/17974', - text: '#17974', - }, - date: new Date(2025, 4, 5), - }, - { - icon: mdiCodeJson, - iconColor: 'yellow', - title: 'YAML whitespace is cursed', - description: 'YAML whitespaces are often handled in unintuitive ways.', - link: { - url: 'https://github.com/immich-app/immich/pull/17309', - text: '#17309', - }, - date: new Date(2025, 3, 1), - }, - { - icon: mdiMicrosoftWindows, - iconColor: '#357EC7', - title: 'Hidden files in Windows are cursed', - description: - 'Hidden files in Windows cannot be opened with the "w" flag. That, combined with SMB option "hide dot files" leads to a lot of confusion.', - link: { - url: 'https://github.com/immich-app/immich/pull/12812', - text: '#12812', - }, - date: new Date(2024, 8, 20), - }, - { - icon: mdiWrap, - iconColor: 'gray', - title: 'Carriage returns in bash scripts are cursed', - description: 'Git can be configured to automatically convert LF to CRLF on checkout and CRLF breaks bash scripts.', - link: { - url: 'https://github.com/immich-app/immich/pull/11613', - text: '#11613', - }, - date: new Date(2024, 7, 7), - }, - { - icon: mdiLockOff, - iconColor: 'red', - title: 'Fetch inside Cloudflare Workers is cursed', - description: - 'Fetch requests in Cloudflare Workers use http by default, even if you explicitly specify https, which can often cause redirect loops.', - link: { - url: 'https://community.cloudflare.com/t/does-cloudflare-worker-allow-secure-https-connection-to-fetch-even-on-flexible-ssl/68051/5', - text: 'Cloudflare', - }, - date: new Date(2024, 7, 7), - }, - { - icon: mdiCrosshairsOff, - iconColor: 'gray', - title: 'GPS sharing on mobile is cursed', - description: - 'Some phones will silently strip GPS data from images when apps without location permission try to access them.', - link: { - url: 'https://github.com/immich-app/immich/discussions/11268', - text: '#11268', - }, - date: new Date(2024, 6, 21), - }, - { - icon: mdiLeadPencil, - iconColor: 'gold', - title: 'PostgreSQL NOTIFY is cursed', - description: - 'PostgreSQL does everything in a transaction, including NOTIFY. This means using the socket.io postgres-adapter writes to WAL every 5 seconds.', - link: { url: 'https://github.com/immich-app/immich/pull/10801', text: '#10801' }, - date: new Date(2024, 6, 3), - }, - { - icon: mdiWeb, - iconColor: 'lightskyblue', - title: 'npm scripts are cursed', - description: - 'npm scripts make a http call to the npm registry each time they run, which means they are a terrible way to execute a health check.', - link: { url: 'https://github.com/immich-app/immich/issues/10796', text: '#10796' }, - date: new Date(2024, 6, 3), - }, - { - icon: mdiSpeedometerSlow, - iconColor: 'brown', - title: '50 extra packages are cursed', - description: - 'There is a user in the JavaScript community who goes around adding "backwards compatibility" to projects. They do this by adding 50 extra package dependencies to your project, which are maintained by them.', - link: { url: 'https://github.com/immich-app/immich/pull/10690', text: '#10690' }, - date: new Date(2024, 5, 28), - }, - { - icon: mdiLockOutline, - iconColor: 'gold', - title: 'Long passwords are cursed', - description: - 'The bcrypt implementation only uses the first 72 bytes of a string. Any characters after that are ignored.', - // link: GHSA-4p64-9f7h-3432 - date: new Date(2024, 5, 25), - }, - { - icon: mdiCalendarToday, - iconColor: 'greenyellow', - title: 'JavaScript Date objects are cursed', - description: 'JavaScript date objects are 1 indexed for years and days, but 0 indexed for months.', - link: { url: 'https://github.com/immich-app/immich/pull/6787', text: '#6787' }, - date: new Date(2024, 0, 31), - }, - { - icon: mdiBug, - iconColor: 'green', - title: 'ESM imports are cursed', - description: - 'Prior to Node.js v20.8 using --experimental-vm-modules in a CommonJS project that imported an ES module that imported a CommonJS modules would create a segfault and crash Node.js', - link: { - url: 'https://github.com/immich-app/immich/pull/6719', - text: '#6179', - }, - date: new Date(2024, 0, 9), - }, - { - icon: mdiDatabase, - iconColor: 'gray', - title: 'PostgreSQL parameters are cursed', - description: `PostgresSQL has a limit of ${Number(65535).toLocaleString()} parameters, so bulk inserts can fail with large datasets.`, - link: { - url: 'https://github.com/immich-app/immich/pull/6034', - text: '#6034', - }, - date: new Date(2023, 11, 28), - }, - { - icon: mdiSecurity, - iconColor: 'gold', - title: 'Secure contexts are cursed', - description: `Some web features like the clipboard API only work in "secure contexts" (ie. https or localhost)`, - link: { - url: 'https://github.com/immich-app/immich/issues/2981', - text: '#2981', - }, - date: new Date(2023, 5, 26), - }, - { - icon: mdiTrashCan, - iconColor: 'gray', - title: 'TypeORM deletes are cursed', - description: `The remove implementation in TypeORM mutates the input, deleting the id property from the original object.`, - link: { - url: 'https://github.com/typeorm/typeorm/issues/7024#issuecomment-948519328', - text: 'typeorm#6034', - }, - date: new Date(2023, 1, 23), - }, -]; - -export default function CursedKnowledgePage(): JSX.Element { - return ( - -
-

- Cursed Knowledge -

-

- Cursed knowledge we have learned as a result of building Immich that we wish we never knew. -

-
- b.date.getTime() - a.date.getTime()) - .map((item) => ({ ...item, getDateLabel: withLanguage(item.date) }))} - /> -
-
-
- ); -} diff --git a/docs/src/pages/errors.md b/docs/src/pages/errors.md index 5f73162a61..fed72f21c7 100644 --- a/docs/src/pages/errors.md +++ b/docs/src/pages/errors.md @@ -2,7 +2,17 @@ ## TypeORM Upgrade -In order to update to Immich to `v1.137.0` (or above), the application must be started at least once on a version in the range between `1.132.0` and `1.136.0`. Doing so will complete database schema upgrades that are required for `v1.137.0` (and above). After Immich has successfully updated to a version in this range, you can now attempt to update to v1.137.0 (or above). We recommend users upgrade to `1.132.0` since it does not have any other breaking changes. +If you encountered "Migrations failed: Error: Invalid upgrade path" then perform an intermediate upgrade to `v1.132.3` first. + +:::tip +We recommend users upgrade to `v1.132.3` since it does not have any breaking changes or bugs on this upgrade path. +::: + +In order to update to Immich `v1.137.0` or above, the application must be started at least once on a version in the range between `1.132.0` and `1.136.0`. Doing so will complete database schema upgrades that are required for `v1.137.0` (and above). After Immich has successfully updated to a version in this range, you can now attempt to update to `v1.137.0` (or above). + +:::caution +Avoid `v1.136.0` if upgrading from `v1.131.0` (or earlier) due to a bug blocking this upgrade in some installations. +::: ## Inconsistent Media Location diff --git a/docs/src/pages/index.tsx b/docs/src/pages/index.tsx index 277a1d0b46..37455cde16 100644 --- a/docs/src/pages/index.tsx +++ b/docs/src/pages/index.tsx @@ -1,123 +1,5 @@ -import React from 'react'; -import Link from '@docusaurus/Link'; -import Layout from '@theme/Layout'; -import { discordPath, discordViewBox } from '@site/src/components/svg-paths'; -import ThemedImage from '@theme/ThemedImage'; -import Icon from '@mdi/react'; - -function HomepageHeader() { - return ( -
-
- Immich logo -
-
-
- - - - -
-

- Self-hosted{' '} - - photo and - video management{' '} - - solution -

- -

- Easily back up, organize, and manage your photos on your own server. Immich helps you - browse, search and organize your photos and videos with ease, without - sacrificing your privacy. -

-
-
- - Get Started - - - - Open Demo - -
- -
- - Join our Discord -
- -
-
-
- -
-

Download the mobile app

-

- Download the Immich app and start backing up your photos and videos securely to your own server -

-
-
-
- - Get it on Google Play - -
- -
- - Download on the App Store - -
- -
- - Download APK - -
-
- -
-
- ); -} +import { Redirect } from '@docusaurus/router'; export default function Home(): JSX.Element { - return ( - - -
-

This project is available under GNU AGPL v3 license.

-

Privacy should not be a luxury

-
-
- ); + return ; } diff --git a/docs/src/pages/roadmap.tsx b/docs/src/pages/roadmap.tsx deleted file mode 100644 index e002c4d032..0000000000 --- a/docs/src/pages/roadmap.tsx +++ /dev/null @@ -1,944 +0,0 @@ -import { - mdiAccountGroup, - mdiAccountGroupOutline, - mdiAndroid, - mdiAppleIos, - mdiArchiveOutline, - mdiBash, - mdiBookSearchOutline, - mdiBookmark, - mdiCakeVariant, - mdiCameraBurst, - mdiChartBoxMultipleOutline, - mdiCheckAll, - mdiCheckboxMarked, - mdiCloudUploadOutline, - mdiCollage, - mdiContentDuplicate, - mdiCrop, - mdiDevices, - mdiEmailOutline, - mdiExpansionCard, - mdiEyeOutline, - mdiEyeRefreshOutline, - mdiFaceMan, - mdiFaceManOutline, - mdiFile, - mdiFileSearch, - mdiFlash, - mdiFolder, - mdiFolderMultiple, - mdiForum, - mdiHandshakeOutline, - mdiHeart, - mdiHistory, - mdiImage, - mdiImageAlbum, - mdiImageEdit, - mdiImageMultipleOutline, - mdiImageSearch, - mdiKeyboardSettingsOutline, - mdiLicense, - mdiLockOutline, - mdiMagnify, - mdiMagnifyScan, - mdiMap, - mdiMaterialDesign, - mdiMatrix, - mdiMerge, - mdiMonitor, - mdiMotionPlayOutline, - mdiPalette, - mdiPanVertical, - mdiPartyPopper, - mdiPencil, - mdiRaw, - mdiRocketLaunch, - mdiRotate360, - mdiScaleBalance, - mdiSecurity, - mdiServer, - mdiShare, - mdiShareAll, - mdiShareCircle, - mdiStar, - mdiStarOutline, - mdiTableKey, - mdiTag, - mdiTagMultiple, - mdiText, - mdiThemeLightDark, - mdiTrashCanOutline, - mdiVectorCombine, - mdiFolderSync, - mdiFaceRecognition, - mdiVideo, - mdiWeb, - mdiDatabaseOutline, - mdiLinkEdit, - mdiTagFaces, - mdiMovieOpenPlayOutline, - mdiCast, -} from '@mdi/js'; -import Layout from '@theme/Layout'; -import React from 'react'; -import { Item, Timeline } from '../components/timeline'; - -const releases = { - 'v1.135.0': new Date(2025, 5, 18), - 'v1.133.0': new Date(2025, 4, 21), - 'v1.130.0': new Date(2025, 2, 25), - 'v1.127.0': new Date(2025, 1, 26), - 'v1.122.0': new Date(2024, 11, 5), - 'v1.120.0': new Date(2024, 10, 6), - 'v1.114.0': new Date(2024, 8, 6), - 'v1.113.0': new Date(2024, 7, 30), - 'v1.112.0': new Date(2024, 7, 14), - 'v1.111.0': new Date(2024, 6, 26), - 'v1.110.0': new Date(2024, 5, 11), - 'v1.109.0': new Date(2024, 6, 18), - 'v1.106.1': new Date(2024, 5, 11), - 'v1.104.0': new Date(2024, 4, 13), - 'v1.103.0': new Date(2024, 3, 29), - 'v1.102.0': new Date(2024, 3, 15), - 'v1.99.0': new Date(2024, 2, 20), - 'v1.98.0': new Date(2024, 2, 7), - 'v1.95.0': new Date(2024, 1, 20), - 'v1.94.0': new Date(2024, 0, 31), - 'v1.93.0': new Date(2024, 0, 19), - 'v1.91.0': new Date(2023, 11, 15), - 'v1.90.0': new Date(2023, 11, 7), - 'v1.88.0': new Date(2023, 10, 20), - 'v1.84.0': new Date(2023, 10, 1), - 'v1.83.0': new Date(2023, 9, 28), - 'v1.82.0': new Date(2023, 9, 17), - 'v1.79.0': new Date(2023, 8, 21), - 'v1.76.0': new Date(2023, 7, 29), - 'v1.75.0': new Date(2023, 7, 26), - 'v1.72.0': new Date(2023, 7, 6), - 'v1.71.0': new Date(2023, 6, 29), - 'v1.69.0': new Date(2023, 6, 23), - 'v1.68.0': new Date(2023, 6, 20), - 'v1.67.0': new Date(2023, 6, 14), - 'v1.66.0': new Date(2023, 6, 4), - 'v1.65.0': new Date(2023, 5, 30), - 'v1.63.0': new Date(2023, 5, 24), - 'v1.61.0': new Date(2023, 5, 16), - 'v1.58.0': new Date(2023, 4, 28), - 'v1.57.0': new Date(2023, 4, 23), - 'v1.56.0': new Date(2023, 4, 18), - 'v1.55.0': new Date(2023, 4, 9), - 'v1.54.0': new Date(2023, 3, 18), - 'v1.52.0': new Date(2023, 2, 29), - 'v1.51.0': new Date(2023, 2, 20), - 'v1.48.0': new Date(2023, 1, 21), - 'v1.47.0': new Date(2023, 1, 13), - 'v1.46.0': new Date(2023, 1, 9), - 'v1.43.0': new Date(2023, 1, 3), - 'v1.41.0': new Date(2023, 0, 10), - 'v1.39.0': new Date(2022, 11, 19), - 'v1.36.0': new Date(2022, 10, 20), - 'v1.33.1': new Date(2022, 9, 26), - 'v1.32.0': new Date(2022, 9, 14), - 'v1.27.0': new Date(2022, 8, 6), - 'v1.24.0': new Date(2022, 7, 19), - 'v1.10.0': new Date(2022, 4, 29), - 'v1.7.0': new Date(2022, 3, 24), - 'v1.3.0': new Date(2022, 2, 22), - 'v1.2.0': new Date(2022, 1, 8), -} as const; - -const weirdTags = { - 'v1.41.0': 'v1.41.1_64-dev', - 'v1.39.0': 'v1.39.0_61-dev', - 'v1.36.0': 'v1.36.0_55-dev', - 'v1.33.1': 'v1.33.0_52-dev', - 'v1.32.0': 'v1.32.0_50-dev', - 'v1.27.0': 'v1.27.0_37-dev', - 'v1.24.0': 'v1.24.0_34-dev', - 'v1.10.0': 'v1.10.0_15-dev', - 'v1.7.0': 'v1.7.0_11-dev ', - 'v1.3.0': 'v1.3.0-dev ', - 'v1.2.0': 'v0.2-dev ', -}; - -const title = 'Roadmap'; -const description = 'A list of future plans and goals, as well as past achievements and milestones.'; - -const withLanguage = (date: Date) => (language: string) => date.toLocaleDateString(language); - -type Base = { icon: string; iconColor?: React.CSSProperties['color']; title: string; description: string }; -const withRelease = ({ - icon, - iconColor, - title, - description, - release: version, -}: Base & { release: keyof typeof releases }) => { - return { - icon, - iconColor: iconColor ?? 'gray', - title, - description, - link: { - url: `https://github.com/immich-app/immich/releases/tag/${weirdTags[version] ?? version}`, - text: version, - }, - getDateLabel: withLanguage(releases[version]), - }; -}; - -const roadmap: Item[] = [ - { - done: false, - icon: mdiFlash, - iconColor: 'gold', - title: 'Workflows', - description: 'Automate tasks with workflows', - getDateLabel: () => 'Planned for 2025', - }, - { - done: false, - icon: mdiImageEdit, - iconColor: 'rebeccapurple', - title: 'Basic editor', - description: 'Basic photo editing capabilities', - getDateLabel: () => 'Planned for 2025', - }, - { - done: false, - icon: mdiRocketLaunch, - iconColor: 'indianred', - title: 'Stable release', - description: 'Immich goes stable', - getDateLabel: () => 'Planned for 2025', - }, - { - done: false, - icon: mdiCloudUploadOutline, - iconColor: 'cornflowerblue', - title: 'Better background backups', - description: 'Rework background backups to be more reliable', - getDateLabel: () => 'Planned for 2025', - }, - { - done: false, - icon: mdiCameraBurst, - iconColor: 'rebeccapurple', - title: 'Auto stacking', - description: 'Auto stack burst photos', - getDateLabel: () => 'Planned for 2025', - }, -]; - -const milestones: Item[] = [ - { - icon: mdiStar, - iconColor: 'gold', - title: '70,000 Stars', - description: 'Reached 70K Stars on GitHub!', - getDateLabel: withLanguage(new Date(2025, 6, 9)), - }, - withRelease({ - icon: mdiTableKey, - iconColor: 'gray', - title: 'Fine grained access controls', - description: 'Granular access controls for api keys', - release: 'v1.135.0', - }), - withRelease({ - icon: mdiCast, - iconColor: 'aqua', - title: 'Google Cast (web and mobile)', - description: 'Cast assets to Google Cast/Chromecast compatible devices', - release: 'v1.135.0', - }), - withRelease({ - icon: mdiLockOutline, - iconColor: 'sandybrown', - title: 'Private/locked photos', - description: 'Private assets with extra protections', - release: 'v1.133.0', - }), - withRelease({ - icon: mdiFolderMultiple, - iconColor: 'brown', - title: 'Folders view in the mobile app', - description: 'Browse your photos and videos in their folder structure inside the mobile app', - release: 'v1.130.0', - }), - { - icon: mdiStar, - iconColor: 'gold', - title: '60,000 Stars', - description: 'Reached 60K Stars on GitHub!', - getDateLabel: withLanguage(new Date(2025, 2, 4)), - }, - withRelease({ - icon: mdiTagFaces, - iconColor: 'teal', - title: 'Manual face tagging', - description: - 'Manually tag or remove faces in photos and videos, even when automatic detection misses or misidentifies them.', - release: 'v1.127.0', - }), - withRelease({ - icon: mdiLinkEdit, - iconColor: 'crimson', - title: 'Automatic URL switching', - description: 'The mobile app now supports automatic switching between different server URLs', - release: 'v1.122.0', - }), - withRelease({ - icon: mdiMovieOpenPlayOutline, - iconColor: 'darksalmon', - title: 'Native video player', - description: 'HDR videos are now fully supported using the Immich native video player', - release: 'v1.122.0', - }), - withRelease({ - icon: mdiDatabaseOutline, - iconColor: 'brown', - title: 'Automatic database dumps', - description: 'Database dumps are now integrated into the Immich server', - release: 'v1.120.0', - }), - { - icon: mdiStar, - iconColor: 'gold', - title: '50,000 Stars', - description: 'Reached 50K Stars on GitHub!', - getDateLabel: withLanguage(new Date(2024, 10, 1)), - }, - withRelease({ - icon: mdiFaceRecognition, - title: 'Metadata Face Import', - description: 'Read face metadata in Digikam format during import', - release: 'v1.114.0', - }), - withRelease({ - icon: mdiTagMultiple, - iconColor: 'orange', - title: 'Tags', - description: 'Tag your photos and videos', - release: 'v1.113.0', - }), - withRelease({ - icon: mdiFolderSync, - iconColor: 'green', - title: 'Album sync (mobile)', - description: 'Sync or mirror an album from your phone to the Immich server', - release: 'v1.113.0', - }), - withRelease({ - icon: mdiFolderMultiple, - iconColor: 'brown', - title: 'Folders view', - description: 'Browse your photos and videos in their folder structure', - release: 'v1.113.0', - }), - withRelease({ - icon: mdiPalette, - title: 'Theming (mobile)', - description: 'Pick a primary color for the mobile app', - release: 'v1.112.0', - }), - withRelease({ - icon: mdiStarOutline, - iconColor: 'gold', - title: 'Star rating', - description: 'Rate your photos and videos', - release: 'v1.112.0', - }), - withRelease({ - icon: mdiCrop, - iconColor: 'royalblue', - title: 'Editor (mobile)', - description: 'Crop and rotate on mobile', - release: 'v1.111.0', - }), - withRelease({ - icon: mdiMap, - iconColor: 'green', - title: 'Deploy tiles.immich.cloud', - description: 'Dedicated tile server for Immich', - release: 'v1.111.0', - }), - { - icon: mdiStar, - iconColor: 'gold', - title: '40,000 Stars', - description: 'Reached 40K Stars on GitHub!', - getDateLabel: withLanguage(new Date(2024, 6, 21)), - }, - withRelease({ - icon: mdiShare, - title: 'Deploy my.immich.app', - description: 'Url router for immich links', - release: 'v1.109.0', - }), - withRelease({ - icon: mdiLicense, - iconColor: 'gold', - title: 'Supporter Badge', - description: 'The option to buy Immich to support its development!', - release: 'v1.109.0', - }), - withRelease({ - icon: mdiHistory, - title: 'Versioned documentation', - description: 'View documentation as it was at the time of past releases', - release: 'v1.106.1', - }), - withRelease({ - icon: mdiWeb, - iconColor: 'royalblue', - title: 'Web translations', - description: 'Translate the web application to multiple languages', - release: 'v1.106.1', - }), - withRelease({ - icon: mdiContentDuplicate, - title: 'Similar image detection', - description: "Detect duplicate assets that aren't exactly identical", - release: 'v1.106.1', - }), - withRelease({ - icon: mdiVectorCombine, - title: 'Container consolidation', - description: - 'The microservices container can be run as a worker within the server image, allowing us to remove it from the default stack.', - release: 'v1.106.1', - }), - withRelease({ - icon: mdiPencil, - iconColor: 'saddlebrown', - title: 'Read-write external libraries', - description: 'Edit, update, and delete files in external libraries', - release: 'v1.104.0', - }), - withRelease({ - icon: mdiEmailOutline, - iconColor: 'crimson', - title: 'Email notifications', - description: 'Send emails for important events', - release: 'v1.104.0', - }), - { - icon: mdiHandshakeOutline, - iconColor: 'magenta', - title: 'Immich joins FUTO!', - description: 'Joined Futo and Immich core team goes full-time', - getDateLabel: withLanguage(new Date(2024, 4, 1)), - }, - withRelease({ - icon: mdiEyeOutline, - iconColor: 'darkslategray', - title: 'Read-only albums', - description: 'Share albums with other users as read-only', - release: 'v1.103.0', - }), - withRelease({ - icon: mdiBookmark, - iconColor: 'orangered', - title: 'Permanent URLs (Web)', - description: 'Assets on the web now have permanent URLs', - release: 'v1.103.0', - }), - withRelease({ - icon: mdiStar, - iconColor: 'gold', - title: '30,000 Stars', - description: 'Reached 30K Stars on GitHub!', - release: 'v1.102.0', - }), - withRelease({ - icon: mdiChartBoxMultipleOutline, - iconColor: 'mediumvioletred', - title: 'OpenTelemetry metrics', - description: 'OpenTelemetry metrics for local evaluation and advanced debugging', - release: 'v1.99.0', - }), - withRelease({ - icon: 'immich', - title: 'New logo', - description: 'Immich got its new logo', - release: 'v1.98.0', - }), - withRelease({ - icon: mdiMagnifyScan, - title: 'Search enhancement with advanced filters', - description: 'Advanced search with filters by date, location and more', - release: 'v1.95.0', - }), - withRelease({ - icon: mdiScaleBalance, - iconColor: 'gold', - title: 'AGPL License', - description: 'Immich switches to AGPLv3 license', - release: 'v1.95.0', - }), - withRelease({ - icon: mdiEyeRefreshOutline, - title: 'Library watching', - description: 'Automatically import files in external libraries when the operating system detects changes.', - release: 'v1.94.0', - }), - withRelease({ - icon: mdiExpansionCard, - iconColor: 'green', - title: 'GPU acceleration for machine-learning', - description: 'Hardware acceleration support for Nvidia and Intel devices through CUDA and OpenVINO.', - release: 'v1.94.0', - }), - withRelease({ - icon: mdiAccountGroupOutline, - iconColor: 'gray', - title: '250 unique contributors', - description: '250 amazing people contributed to Immich', - release: 'v1.93.0', - }), - withRelease({ - icon: mdiMatrix, - title: 'Search improvement with pgvecto.rs', - description: 'Moved the search from typesense to pgvecto.rs', - release: 'v1.91.0', - }), - withRelease({ - icon: mdiPencil, - iconColor: 'saddlebrown', - title: 'Edit metadata', - description: "Edit a photo or video's date, time, hours, timezone, and GPS information", - release: 'v1.90.0', - }), - withRelease({ - icon: mdiVectorCombine, - title: 'Container consolidation', - description: - 'The serving of the web app is merged into the server image, allowing us to remove two containers from the stack.', - release: 'v1.88.0', - }), - withRelease({ - icon: mdiBash, - iconColor: 'gray', - title: 'CLI v2', - description: 'Version 2 of the Immich CLI is released, replacing the legacy v1 CLI.', - release: 'v1.88.0', - }), - withRelease({ - icon: mdiForum, - iconColor: 'dodgerblue', - title: 'Activity', - description: 'Comment a photo or a video in a shared album', - release: 'v1.84.0', - }), - withRelease({ - icon: mdiStar, - iconColor: 'gold', - title: '20,000 Stars', - description: 'Reached 20K Stars on GitHub!', - release: 'v1.83.0', - }), - withRelease({ - icon: mdiCameraBurst, - iconColor: 'rebeccapurple', - title: 'Stack assets', - description: 'Manual asset stacking for grouping and hiding related assets in the main timeline.', - release: 'v1.83.0', - }), - withRelease({ - icon: mdiPalette, - iconColor: 'magenta', - title: 'Custom theme', - description: 'Apply your custom CSS for modifying fonts, colors, and styles in the web application.', - release: 'v1.83.0', - }), - withRelease({ - icon: mdiTrashCanOutline, - iconColor: 'brown', - title: 'Trash feature', - description: 'Trash, restore from trash, and automatically empty the recycle bin after 30 days.', - release: 'v1.82.0', - }), - withRelease({ - icon: mdiBookSearchOutline, - title: 'External libraries', - description: 'Automatically import media into Immich based on imports paths and ignore patterns.', - release: 'v1.79.0', - }), - withRelease({ - icon: mdiMap, - iconColor: 'darksalmon', - title: 'Map view (mobile)', - description: 'Heat map implementation in the mobile app.', - release: 'v1.76.0', - }), - withRelease({ - icon: mdiFile, - iconColor: 'lightblue', - title: 'Configuration file', - description: 'Auto-configure an Immich installation via a configuration file.', - release: 'v1.75.0', - }), - withRelease({ - icon: mdiMonitor, - iconColor: 'darkcyan', - title: 'Slideshow mode (web)', - description: 'Start a full-screen slideshow from an Album on the web.', - release: 'v1.75.0', - }), - withRelease({ - icon: mdiServer, - iconColor: 'lightskyblue', - title: 'Hardware transcoding', - description: 'Support hardware acceleration (QuickSync, VAAPI, and Nvidia) for video transcoding.', - release: 'v1.72.0', - }), - withRelease({ - icon: mdiImageAlbum, - iconColor: 'olivedrab', - title: 'View albums via time buckets', - description: 'Upgrade albums to use time buckets, an optimized virtual viewport.', - release: 'v1.72.0', - }), - withRelease({ - icon: mdiImageAlbum, - iconColor: 'olivedrab', - title: 'Album description', - description: 'Save an album description.', - release: 'v1.72.0', - }), - withRelease({ - icon: mdiRotate360, - title: '360° Photos (web)', - description: 'View 360° Photos on the web.', - release: 'v1.71.0', - }), - withRelease({ - icon: mdiMotionPlayOutline, - title: 'Android motion photos', - description: 'Add support for Android Motion Photos.', - release: 'v1.69.0', - }), - withRelease({ - icon: mdiFaceManOutline, - iconColor: 'mistyrose', - title: 'Show/hide faces', - description: 'Add the options to show or hide faces.', - release: 'v1.68.0', - }), - withRelease({ - icon: mdiMerge, - iconColor: 'forestgreen', - title: 'Merge faces', - description: 'Add the ability to merge multiple faces together.', - release: 'v1.67.0', - }), - withRelease({ - icon: mdiImage, - iconColor: 'rebeccapurple', - title: 'Feature photo', - description: 'Add the option to change the feature photo for a person.', - release: 'v1.66.0', - }), - withRelease({ - icon: mdiKeyboardSettingsOutline, - iconColor: 'darkslategray', - title: 'Multi-select via SHIFT', - description: 'Add the option to multi-select while holding SHIFT.', - release: 'v1.66.0', - }), - withRelease({ - icon: mdiImageMultipleOutline, - iconColor: 'rebeccapurple', - title: 'Memories (mobile)', - description: 'View "On this day..." memories in the mobile app.', - release: 'v1.65.0', - }), - withRelease({ - icon: mdiFaceMan, - iconColor: 'mistyrose', - title: 'Facial recognition (mobile)', - description: 'View detected faces in the mobile app.', - release: 'v1.63.0', - }), - withRelease({ - icon: mdiImageMultipleOutline, - iconColor: 'rebeccapurple', - title: 'Memories (web)', - description: 'View pictures taken in past years on this day on the web.', - release: 'v1.61.0', - }), - withRelease({ - icon: mdiCollage, - iconColor: 'deeppink', - title: 'Justified layout (web)', - description: 'Implement justified layout (collage) on the web.', - release: 'v1.61.0', - }), - withRelease({ - icon: mdiRaw, - title: 'RAW file formats', - description: 'Support for RAW file formats.', - release: 'v1.61.0', - }), - withRelease({ - icon: mdiShareAll, - iconColor: 'darkturquoise', - title: 'Partner sharing (mobile)', - description: 'View shared partner photos in the mobile app.', - release: 'v1.58.0', - }), - withRelease({ - icon: mdiFile, - iconColor: 'lightblue', - title: 'XMP sidecar', - description: 'Attach XMP sidecar files to assets.', - release: 'v1.58.0', - }), - withRelease({ - icon: mdiFolder, - iconColor: 'brown', - title: 'Custom storage label', - description: 'Replace the user UUID in the storage template with a custom label.', - release: 'v1.57.0', - }), - withRelease({ - icon: mdiShareCircle, - title: 'Partner sharing', - description: 'Share your entire collection with another user.', - release: 'v1.56.0', - }), - withRelease({ - icon: mdiFaceMan, - iconColor: 'mistyrose', - title: 'Facial recognition', - description: 'Detect faces in pictures and cluster them together as people, which can be named.', - release: 'v1.56.0', - }), - withRelease({ - icon: mdiMap, - iconColor: 'darksalmon', - title: 'Map view (web)', - description: 'View a global map, with clusters of photos based on corresponding GPS data.', - release: 'v1.55.0', - }), - withRelease({ - icon: mdiDevices, - iconColor: 'slategray', - title: 'Manage auth devices', - description: 'Manage logged-in devices and revoke access from User Settings.', - release: 'v1.55.0', - }), - withRelease({ - icon: mdiStar, - iconColor: 'gold', - title: '10,000 Stars', - description: 'Reached 10K stars on GitHub!', - release: 'v1.54.0', - }), - withRelease({ - icon: mdiText, - title: 'Asset descriptions', - description: 'Save an asset description', - release: 'v1.54.0', - }), - withRelease({ - icon: mdiArchiveOutline, - title: 'Archiving', - description: 'Remove assets from the main timeline by archiving them.', - release: 'v1.54.0', - }), - withRelease({ - icon: mdiDevices, - iconColor: 'slategray', - title: 'Responsive web app', - description: 'Optimize the web app for small screen.', - release: 'v1.54.0', - }), - withRelease({ - icon: mdiFileSearch, - iconColor: 'brown', - title: 'Search by metadata', - description: 'Search images by filename, description, tagged people, make, model, and other metadata.', - release: 'v1.52.0', - }), - withRelease({ - icon: mdiImageSearch, - iconColor: 'rebeccapurple', - title: 'CLIP search', - description: 'Search images with free-form text like "Sunset at the beach".', - release: 'v1.51.0', - }), - withRelease({ - icon: mdiMagnify, - iconColor: 'lightblue', - title: 'Explore page', - description: 'View tagged places, object, and people.', - release: 'v1.51.0', - }), - withRelease({ - icon: mdiAppleIos, - title: 'iOS background uploads', - description: 'Automatically backup pictures in the background on iOS.', - release: 'v1.48.0', - }), - withRelease({ - icon: mdiMotionPlayOutline, - title: 'Auto-Link live photos', - description: 'Automatically link live photos, even when uploaded as separate files.', - release: 'v1.48.0', - }), - withRelease({ - icon: mdiMaterialDesign, - iconColor: 'blue', - title: 'Material design 3 (mobile)', - description: 'Upgrade the mobile app to Material Design 3.', - release: 'v1.47.0', - }), - withRelease({ - icon: mdiHeart, - iconColor: 'red', - title: 'Favorites (mobile)', - description: 'Show favorites on the mobile app.', - release: 'v1.46.0', - }), - withRelease({ - icon: mdiCakeVariant, - iconColor: 'deeppink', - title: 'Immich turns 1', - description: 'Immich is officially one year old.', - release: 'v1.43.0', - }), - withRelease({ - icon: mdiHeart, - iconColor: 'red', - title: 'Favorites page (web)', - description: 'Favorite and view favorites on the web.', - release: 'v1.43.0', - }), - withRelease({ - icon: mdiShareCircle, - title: 'Public share links', - description: 'Share photos and albums publicly via a shared link.', - release: 'v1.41.0', - }), - withRelease({ - icon: mdiFolder, - iconColor: 'lightblue', - title: 'User-defined storage structure', - description: 'Support custom storage structures.', - release: 'v1.39.0', - }), - withRelease({ - icon: mdiMotionPlayOutline, - title: 'iOS live photos', - description: 'Backup and display iOS Live Photos.', - release: 'v1.36.0', - }), - withRelease({ - icon: mdiSecurity, - iconColor: 'green', - title: 'OAuth integration', - description: 'Support OAuth2 and OIDC capable identity providers.', - release: 'v1.36.0', - }), - withRelease({ - icon: mdiWeb, - iconColor: 'royalblue', - title: 'Documentation site', - description: 'Release an official documentation website.', - release: 'v1.33.1', - }), - withRelease({ - icon: mdiThemeLightDark, - iconColor: 'slategray', - title: 'Dark mode (web)', - description: 'Dark mode on the web.', - release: 'v1.32.0', - }), - withRelease({ - icon: mdiPanVertical, - title: 'Virtual scrollbar (web)', - description: 'View the main timeline with a virtual scrollbar, allowing to jump to any point in time, instantly.', - release: 'v1.27.0', - }), - withRelease({ - icon: mdiCheckAll, - iconColor: 'green', - title: 'Checksum duplication check', - description: 'Enforce per user sha1 checksum uniqueness.', - release: 'v1.27.0', - }), - withRelease({ - icon: mdiAndroid, - iconColor: 'greenyellow', - title: 'Android background backup', - description: 'Automatic backup in the background on Android.', - release: 'v1.24.0', - }), - withRelease({ - icon: mdiAccountGroup, - iconColor: 'gray', - title: 'Admin portal', - description: 'Manage users and admin settings from the web.', - release: 'v1.10.0', - }), - withRelease({ - icon: mdiShareCircle, - title: 'Album sharing', - description: 'Share albums with other users.', - release: 'v1.7.0', - }), - withRelease({ - icon: mdiTag, - iconColor: 'coral', - title: 'Image tagging', - description: 'Tag images with custom values.', - release: 'v1.7.0', - }), - withRelease({ - icon: mdiImage, - iconColor: 'rebeccapurple', - title: 'View exif', - description: 'View metadata about assets.', - release: 'v1.3.0', - }), - withRelease({ - icon: mdiCheckboxMarked, - iconColor: 'green', - title: 'Multi select', - description: 'Select and execute actions on multiple assets at the same time.', - release: 'v1.2.0', - }), - withRelease({ - icon: mdiVideo, - iconColor: 'slategray', - title: 'Video player', - description: 'Play videos in the web and on mobile.', - release: 'v1.2.0', - }), - { - icon: mdiPartyPopper, - iconColor: 'deeppink', - title: 'First commit', - description: 'First commit on GitHub, Immich is born.', - getDateLabel: withLanguage(new Date(2022, 1, 3)), - }, -]; - -export default function MilestonePage(): JSX.Element { - return ( - -
-

- {title} -

-

{description}

-
- -
-
-
- ); -} diff --git a/docs/static/.well-known/security.txt b/docs/static/.well-known/security.txt deleted file mode 100644 index 5a8414c3e2..0000000000 --- a/docs/static/.well-known/security.txt +++ /dev/null @@ -1,5 +0,0 @@ -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 -Canonical: https://immich.app/.well-known/security.txt diff --git a/docs/static/_redirects b/docs/static/_redirects index 7b01d1e3bb..ecbdf19303 100644 --- a/docs/static/_redirects +++ b/docs/static/_redirects @@ -1,34 +1,34 @@ -/docs /docs/overview/welcome 307 -/docs/ /docs/overview/welcome 307 -/docs/mobile-app-beta-program /docs/features/mobile-app 307 -/docs/contribution-guidelines /docs/overview/support-the-project#contributing 307 -/docs/install /docs/install/docker-compose 307 -/docs/installation/one-step-installation /docs/install/script 307 -/docs/installation/portainer-installation /docs/install/portainer 307 -/docs/installation/recommended-installation /docs/install/docker-compose 307 -/docs/installation/unraid /docs/install/unraid 307 -/docs/installation/requirements /docs/install/requirements 307 -/docs/overview/logo-meaning /docs/overview/logo 307 -/docs/overview/technology-stack /docs/developer/architecture 307 -/docs/usage/automatic-backup /docs/features/automatic-backup 307 -/docs/usage/bulk-upload /docs/features/command-line-interface 307 -/docs/features/bulk-upload /docs/features/command-line-interface 307 -/docs/usage/oauth /docs/administration/oauth 307 -/docs/usage/post-installation /docs/install/post-install 307 -/docs/usage/update /docs/install/docker-compose#step-4---upgrading 307 -/docs/usage/server-commands /docs/administration/server-commands 307 -/docs/features/jobs /docs/administration/jobs 307 -/docs/features/oauth /docs/administration/oauth 307 -/docs/features/password-login /docs/administration/password-login 307 -/docs/features/server-commands /docs/administration/server-commands 307 -/docs/features/storage-template /docs/administration/storage-template 307 -/docs/features/user-management /docs/administration/user-management 307 -/docs/developer/contributing /docs/developer/pr-checklist 307 -/docs/guides/machine-learning /docs/guides/remote-machine-learning 307 -/docs/administration/password-login /docs/administration/system-settings 307 -/docs/features/search /docs/features/searching 307 -/docs/features/smart-search /docs/features/searching 307 -/docs/guides/api-album-sync /docs/community-projects 307 -/docs/guides/remove-offline-files /docs/community-projects 307 -/milestones /roadmap 307 -/docs/overview/introduction /docs/overview/welcome 307 +/ /overview/quick-start 307 +/mobile-app-beta-program /features/mobile-app 307 +/contribution-guidelines /overview/support-the-project#contributing 307 +/install /install/docker-compose 307 +/installation/one-step-installation /install/script 307 +/installation/portainer-installation /install/portainer 307 +/installation/recommended-installation /install/docker-compose 307 +/installation/unraid /install/unraid 307 +/installation/requirements /install/requirements 307 +/overview/logo-meaning /overview/logo 307 +/overview/technology-stack /developer/architecture 307 +/usage/automatic-backup /features/automatic-backup 307 +/usage/bulk-upload /features/command-line-interface 307 +/features/bulk-upload /features/command-line-interface 307 +/usage/oauth /administration/oauth 307 +/usage/post-installation /install/post-install 307 +/usage/update /install/docker-compose#step-4---upgrading 307 +/usage/server-commands /administration/server-commands 307 +/features/jobs /administration/jobs 307 +/features/oauth /administration/oauth 307 +/features/password-login /administration/password-login 307 +/features/server-commands /administration/server-commands 307 +/features/storage-template /administration/storage-template 307 +/features/user-management /administration/user-management 307 +/developer/contributing /developer/pr-checklist 307 +/guides/machine-learning /guides/remote-machine-learning 307 +/administration/password-login /administration/system-settings 307 +/features/search /features/searching 307 +/features/smart-search /features/searching 307 +/guides/api-album-sync /community-projects 307 +/guides/remove-offline-files /community-projects 307 +/overview/introduction /overview/quick-start 307 +/overview/welcome /overview/quick-start 307 +/docs/* /:splat 307 diff --git a/docs/static/archived-versions.json b/docs/static/archived-versions.json index 5b7d3a9507..58f3d67cd2 100644 --- a/docs/static/archived-versions.json +++ b/docs/static/archived-versions.json @@ -1,218 +1,241 @@ [ { - "label": "v1.141.1", - "url": "https://v1.141.1.archive.immich.app" + "label": "v2.1.0", + "url": "https://docs.v2.1.0.archive.immich.app" }, { - "label": "v1.141.0", - "url": "https://v1.141.0.archive.immich.app" + "label": "v2.0.1", + "url": "https://docs.v2.0.1.archive.immich.app" + }, + { + "label": "v2.0.0", + "url": "https://docs.v2.0.0.archive.immich.app" + }, + { + "label": "v1.144.1", + "url": "https://docs.v1.144.1.archive.immich.app" + }, + { + "label": "v1.144.0", + "url": "https://docs.v1.144.0.archive.immich.app" + }, + { + "label": "v1.143.1", + "url": "https://docs.v1.143.1.archive.immich.app" + }, + { + "label": "v1.142.1", + "url": "https://v1.142.1.archive.immich.app", + "rootPath": "/docs" + }, + { + "label": "v1.141.1", + "url": "https://v1.141.1.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.140.1", - "url": "https://v1.140.1.archive.immich.app" - }, - { - "label": "v1.140.0", - "url": "https://v1.140.0.archive.immich.app" + "url": "https://v1.140.1.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.139.4", - "url": "https://v1.139.4.archive.immich.app" - }, - { - "label": "v1.139.3", - "url": "https://v1.139.3.archive.immich.app" - }, - { - "label": "v1.139.2", - "url": "https://v1.139.2.archive.immich.app" + "url": "https://v1.139.4.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.138.1", - "url": "https://v1.138.1.archive.immich.app" - }, - { - "label": "v1.138.0", - "url": "https://v1.138.0.archive.immich.app" + "url": "https://v1.138.1.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.137.3", - "url": "https://v1.137.3.archive.immich.app" - }, - { - "label": "v1.137.2", - "url": "https://v1.137.2.archive.immich.app" - }, - { - "label": "v1.137.1", - "url": "https://v1.137.1.archive.immich.app" - }, - { - "label": "v1.137.0", - "url": "https://v1.137.0.archive.immich.app" + "url": "https://v1.137.3.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.136.0", - "url": "https://v1.136.0.archive.immich.app" + "url": "https://v1.136.0.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.135.3", - "url": "https://v1.135.3.archive.immich.app" - }, - { - "label": "v1.135.2", - "url": "https://v1.135.2.archive.immich.app" - }, - { - "label": "v1.135.1", - "url": "https://v1.135.1.archive.immich.app" - }, - { - "label": "v1.135.0", - "url": "https://v1.135.0.archive.immich.app" + "url": "https://v1.135.3.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.134.0", - "url": "https://v1.134.0.archive.immich.app" + "url": "https://v1.134.0.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.133.1", - "url": "https://v1.133.1.archive.immich.app" - }, - { - "label": "v1.133.0", - "url": "https://v1.133.0.archive.immich.app" + "url": "https://v1.133.1.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.132.3", - "url": "https://v1.132.3.archive.immich.app" + "url": "https://v1.132.3.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.131.3", - "url": "https://v1.131.3.archive.immich.app" + "url": "https://v1.131.3.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.130.3", - "url": "https://v1.130.3.archive.immich.app" + "url": "https://v1.130.3.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.129.0", - "url": "https://v1.129.0.archive.immich.app" + "url": "https://v1.129.0.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.128.0", - "url": "https://v1.128.0.archive.immich.app" + "url": "https://v1.128.0.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.127.0", - "url": "https://v1.127.0.archive.immich.app" + "url": "https://v1.127.0.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.126.1", - "url": "https://v1.126.1.archive.immich.app" + "url": "https://v1.126.1.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.125.7", - "url": "https://v1.125.7.archive.immich.app" + "url": "https://v1.125.7.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.124.2", - "url": "https://v1.124.2.archive.immich.app" + "url": "https://v1.124.2.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.123.0", - "url": "https://v1.123.0.archive.immich.app" + "url": "https://v1.123.0.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.122.3", - "url": "https://v1.122.3.archive.immich.app" + "url": "https://v1.122.3.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.121.0", - "url": "https://v1.121.0.archive.immich.app" + "url": "https://v1.121.0.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.120.2", - "url": "https://v1.120.2.archive.immich.app" + "url": "https://v1.120.2.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.119.1", - "url": "https://v1.119.1.archive.immich.app" + "url": "https://v1.119.1.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.118.2", - "url": "https://v1.118.2.archive.immich.app" + "url": "https://v1.118.2.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.117.0", - "url": "https://v1.117.0.archive.immich.app" + "url": "https://v1.117.0.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.116.2", - "url": "https://v1.116.2.archive.immich.app" + "url": "https://v1.116.2.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.115.0", - "url": "https://v1.115.0.archive.immich.app" + "url": "https://v1.115.0.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.114.0", - "url": "https://v1.114.0.archive.immich.app" + "url": "https://v1.114.0.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.113.1", - "url": "https://v1.113.1.archive.immich.app" + "url": "https://v1.113.1.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.112.1", - "url": "https://v1.112.1.archive.immich.app" + "url": "https://v1.112.1.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.111.0", - "url": "https://v1.111.0.archive.immich.app" + "url": "https://v1.111.0.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.110.0", - "url": "https://v1.110.0.archive.immich.app" + "url": "https://v1.110.0.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.109.2", - "url": "https://v1.109.2.archive.immich.app" + "url": "https://v1.109.2.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.108.0", - "url": "https://v1.108.0.archive.immich.app" + "url": "https://v1.108.0.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.107.2", - "url": "https://v1.107.2.archive.immich.app" + "url": "https://v1.107.2.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.106.4", - "url": "https://v1.106.4.archive.immich.app" + "url": "https://v1.106.4.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.105.1", - "url": "https://v1.105.1.archive.immich.app" + "url": "https://v1.105.1.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.104.0", - "url": "https://v1.104.0.archive.immich.app" + "url": "https://v1.104.0.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.103.1", - "url": "https://v1.103.1.archive.immich.app" + "url": "https://v1.103.1.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.102.3", - "url": "https://v1.102.3.archive.immich.app" + "url": "https://v1.102.3.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.101.0", - "url": "https://v1.101.0.archive.immich.app" + "url": "https://v1.101.0.archive.immich.app", + "rootPath": "/docs" }, { "label": "v1.100.0", - "url": "https://v1.100.0.archive.immich.app" + "url": "https://v1.100.0.archive.immich.app", + "rootPath": "/docs" } ] diff --git a/docs/static/img/synology-action-clean.png b/docs/static/img/synology-action-clean.png new file mode 100644 index 0000000000..4d168b0bd8 Binary files /dev/null and b/docs/static/img/synology-action-clean.png differ diff --git a/docs/static/img/synology-build.png b/docs/static/img/synology-build.png new file mode 100644 index 0000000000..50c4d0fc98 Binary files /dev/null and b/docs/static/img/synology-build.png differ diff --git a/docs/static/img/synology-container-ip.png b/docs/static/img/synology-container-ip.png new file mode 100644 index 0000000000..21617d8c72 Binary files /dev/null and b/docs/static/img/synology-container-ip.png differ diff --git a/docs/static/img/synology-container-manager-customize-docker-compose.png b/docs/static/img/synology-container-manager-customize-docker-compose.png index 558557487a..2c0a40def0 100644 Binary files a/docs/static/img/synology-container-manager-customize-docker-compose.png and b/docs/static/img/synology-container-manager-customize-docker-compose.png differ diff --git a/docs/static/img/synology-custom-port-firewall-rule.png b/docs/static/img/synology-custom-port-firewall-rule.png new file mode 100644 index 0000000000..26ee17785c Binary files /dev/null and b/docs/static/img/synology-custom-port-firewall-rule.png differ diff --git a/docs/static/img/synology-fw-ipedit.png b/docs/static/img/synology-fw-ipedit.png new file mode 100644 index 0000000000..7f4e561395 Binary files /dev/null and b/docs/static/img/synology-fw-ipedit.png differ diff --git a/docs/static/img/synology-fw-rules.png b/docs/static/img/synology-fw-rules.png new file mode 100644 index 0000000000..2ec43a682f Binary files /dev/null and b/docs/static/img/synology-fw-rules.png differ diff --git a/docs/static/img/synology-ipaddress-firewall-rule.png b/docs/static/img/synology-ipaddress-firewall-rule.png new file mode 100644 index 0000000000..d1982b053d Binary files /dev/null and b/docs/static/img/synology-ipaddress-firewall-rule.png differ diff --git a/docs/static/img/synology-project-stop.png b/docs/static/img/synology-project-stop.png new file mode 100644 index 0000000000..8a77446dc2 Binary files /dev/null and b/docs/static/img/synology-project-stop.png differ diff --git a/docs/static/img/synology-remove-unused.png b/docs/static/img/synology-remove-unused.png new file mode 100644 index 0000000000..9b1a217902 Binary files /dev/null and b/docs/static/img/synology-remove-unused.png differ diff --git a/docs/static/img/synology-select-proj.png b/docs/static/img/synology-select-proj.png new file mode 100644 index 0000000000..21642d8713 Binary files /dev/null and b/docs/static/img/synology-select-proj.png differ diff --git a/e2e/.nvmrc b/e2e/.nvmrc index e2228113dd..442c7587a9 100644 --- a/e2e/.nvmrc +++ b/e2e/.nvmrc @@ -1 +1 @@ -22.19.0 +22.20.0 diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml index 983125e4ad..9aef2288f6 100644 --- a/e2e/docker-compose.yml +++ b/e2e/docker-compose.yml @@ -35,10 +35,10 @@ services: - 2285:2285 redis: - image: redis:6.2-alpine@sha256:7fe72c486b910f6b1a9769c937dad5d63648ddee82e056f47417542dd40825bb + image: redis:6.2-alpine@sha256:77697a75da9f94e9357b61fcaf8345f69e3d9d32e9d15032c8415c21263977dc database: - image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0@sha256:7a4469b9484e37bf2630a60bc2f02f086dae898143b599ecc1c93f619849ef6b + image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0@sha256:6f3e9d2c2177af16c2988ff71425d79d89ca630ec2f9c8db03209ab716542338 command: -c fsync=off -c shared_preload_libraries=vchord.so -c config_file=/var/lib/postgresql/data/postgresql.conf environment: POSTGRES_PASSWORD: postgres diff --git a/e2e/package.json b/e2e/package.json index 2cf1b79f86..67aeb00c1b 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -1,6 +1,6 @@ { "name": "immich-e2e", - "version": "1.141.1", + "version": "2.1.0", "description": "", "main": "index.js", "type": "module", @@ -19,19 +19,17 @@ "author": "", "license": "GNU Affero General Public License version 3", "devDependencies": { - "@eslint/eslintrc": "^3.1.0", "@eslint/js": "^9.8.0", "@immich/cli": "file:../cli", "@immich/sdk": "file:../open-api/typescript-sdk", "@playwright/test": "^1.44.1", "@socket.io/component-emitter": "^3.1.2", "@types/luxon": "^3.4.2", - "@types/node": "^22.18.0", + "@types/node": "^22.18.8", "@types/oidc-provider": "^9.0.0", "@types/pg": "^8.15.1", "@types/pngjs": "^6.0.4", "@types/supertest": "^6.0.2", - "@vitest/coverage-v8": "^3.0.0", "eslint": "^9.14.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-prettier": "^5.1.3", @@ -45,7 +43,7 @@ "pngjs": "^7.0.0", "prettier": "^3.2.5", "prettier-plugin-organize-imports": "^4.0.0", - "sharp": "^0.34.3", + "sharp": "^0.34.4", "socket.io-client": "^4.7.4", "supertest": "^7.0.0", "typescript": "^5.3.3", @@ -54,6 +52,6 @@ "vitest": "^3.0.0" }, "volta": { - "node": "22.19.0" + "node": "22.20.0" } } diff --git a/e2e/src/api/specs/album.e2e-spec.ts b/e2e/src/api/specs/album.e2e-spec.ts index 5615a312f2..c4f06edd93 100644 --- a/e2e/src/api/specs/album.e2e-spec.ts +++ b/e2e/src/api/specs/album.e2e-spec.ts @@ -136,6 +136,7 @@ describe('/albums', () => { expect(body).toEqual({ ...user1Albums[0], assets: [expect.objectContaining({ isFavorite: false })], + contributorCounts: [{ userId: user1.userId, assetCount: 1 }], lastModifiedAssetTimestamp: expect.any(String), startDate: expect.any(String), endDate: expect.any(String), @@ -310,6 +311,7 @@ describe('/albums', () => { expect(body).toEqual({ ...user1Albums[0], assets: [expect.objectContaining({ id: user1Albums[0].assets[0].id })], + contributorCounts: [{ userId: user1.userId, assetCount: 1 }], lastModifiedAssetTimestamp: expect.any(String), startDate: expect.any(String), endDate: expect.any(String), @@ -345,6 +347,7 @@ describe('/albums', () => { expect(body).toEqual({ ...user1Albums[0], assets: [expect.objectContaining({ id: user1Albums[0].assets[0].id })], + contributorCounts: [{ userId: user1.userId, assetCount: 1 }], lastModifiedAssetTimestamp: expect.any(String), startDate: expect.any(String), endDate: expect.any(String), @@ -362,6 +365,7 @@ describe('/albums', () => { expect(body).toEqual({ ...user1Albums[0], assets: [], + contributorCounts: [{ userId: user1.userId, assetCount: 1 }], assetCount: 1, lastModifiedAssetTimestamp: expect.any(String), endDate: expect.any(String), @@ -382,6 +386,7 @@ describe('/albums', () => { expect(body).toEqual({ ...user2Albums[0], assets: [], + contributorCounts: [{ userId: user1.userId, assetCount: 1 }], assetCount: 1, lastModifiedAssetTimestamp: expect.any(String), endDate: expect.any(String), diff --git a/e2e/src/api/specs/asset.e2e-spec.ts b/e2e/src/api/specs/asset.e2e-spec.ts index 9c8b893075..5c30ff5cbe 100644 --- a/e2e/src/api/specs/asset.e2e-spec.ts +++ b/e2e/src/api/specs/asset.e2e-spec.ts @@ -1466,10 +1466,10 @@ describe('/asset', () => { expectedDate: '2023-04-04T04:00:00.000Z', }, { - name: 'CreateDate when DateTimeOriginal missing', + name: 'CreationDate when DateTimeOriginal missing', exifData: { - CreateDate: '2023:05:05 05:00:00', // TESTABLE - CreationDate: '2023:07:07 07:00:00', // TESTABLE + CreationDate: '2023:05:05 05:00:00', // TESTABLE + CreateDate: '2023:07:07 07:00:00', // TESTABLE GPSDateTime: '2023:10:10 10:00:00', // TESTABLE }, expectedDate: '2023-05-05T05:00:00.000Z', diff --git a/i18n/af.json b/i18n/af.json index b3729903ec..fce944504b 100644 --- a/i18n/af.json +++ b/i18n/af.json @@ -14,6 +14,7 @@ "add_a_location": "Voeg 'n ligging by", "add_a_name": "Voeg 'n naam by", "add_a_title": "Voeg 'n titel by", + "add_birthday": "Voeg 'n verjaarsdag by", "add_endpoint": "Voeg Koppelvlakpunt by", "add_exclusion_pattern": "Voeg uitsgluitingspatrone by", "add_import_path": "Voeg invoerpad by", @@ -27,6 +28,8 @@ "add_to_album": "Voeg na album", "add_to_album_bottom_sheet_added": "By {album} bygevoeg", "add_to_album_bottom_sheet_already_exists": "Reeds in {album}", + "add_to_albums": "Voeg by albums", + "add_to_albums_count": "Voeg by ({count}) albums", "add_to_shared_album": "Voeg toe aan gedeelde album", "add_url": "Voeg URL by", "added_to_archive": "By argief toegevoegd", @@ -44,6 +47,11 @@ "backup_database": "Skep DatastortlÃĒer", "backup_database_enable_description": "Aktiveer databasisrugsteun", "backup_keep_last_amount": "Aantal vorige rugsteune om te hou", + "backup_onboarding_3_description": "totale kopieÃĢ van jou data, insluitende die oorspronklikke lÃĒers. Dit sluit in 1 kopie op 'n ander perseel en 2 kopieÃĢ om die huidige rekenaar.", + "backup_onboarding_description": "'N 3-2-1 rugsteun strategie word sterk aanbeveel om jou data veilig te hou. Hou kopieÃĢ van jou fotos/videos so wel as die Immich databasis vir 'n volledige rugsteun oplossing.", + "backup_onboarding_footer": "Vir meer inligting oor hoe om 'n rugsteun kopie van Immich te maak, gaan lees asseblief hierdie dokument.", + "backup_onboarding_parts_title": "'N 3-2-1 rugsteun sluit in:", + "backup_onboarding_title": "Rugsteun kopieÃĢ", "backup_settings": "Rugsteun instellings", "backup_settings_description": "Bestuur databasis rugsteun instellings.", "cleared_jobs": "Poste gevee vir: {job}", @@ -62,8 +70,8 @@ "duplicate_detection_job_description": "Begin masjienleer op bates om soortgelyke beelde op te spoor. Maak staat op Smart Search", "exclusion_pattern_description": "Met uitsluitingspatrone kan jy lÃĒers en vouers ignoreer wanneer jy jou biblioteek skandeer. Dit is nuttig as jy vouers het wat lÃĒers bevat wat jy nie wil invoer nie, soos RAW-lÃĒers.", "external_library_management": "Eksterne Biblioteekbestuur", - "face_detection": "Gesig deteksie", - "face_detection_description": "Detecteer die gesigte in media deur middel van masjienleer. Vir videos word slegs die duimnaelskets oorweeg. “Herlaai” (ver)werk al die media weer. “Stel terug” verwyder boonop alle huidige gesigdata. “Onverwerk” plaas bates in die tou wat nog nie verwerk is nie. Gedekte gesigte sal nÃĄ voltooiing van Gesigdetectie vir Gesigherkenning in die tou geplaas word, om hulle in bestaande of nuwe persone te groepeer.", + "face_detection": "Gesig herkenning", + "face_detection_description": "Identifiseer die gesigte in media deur middel van masjienleer. Vir videos word slegs die duimnaelskets oorweeg. “Herlaai” (ver)werk al die media weer. “Stel terug” verwyder alle huidige gesigdata. “Onverwerk” plaas bates in die tou wat nog nie verwerk is nie. Geidentifiseerde gesigte sal nÃĄ voltooiing van Gesigidentifikasie vir Gesigherkenning in die tou geplaas word, om hulle in bestaande of nuwe persone te groepeer.", "facial_recognition_job_description": "Groepeer gesigte in mense in. Die stap is vinniger nadat Gesig Deteksie klaar is. \"Herstel\" (her-)groepeer alle gesigte. \"Vermiste\" plaas gesigte in ry wat nie 'n persoon gekoppel het nie.", "failed_job_command": "Opdrag {command} het misluk vir werk: {job}", "force_delete_user_warning": "WAARSKUWING: Dit sal onmiddellik die gebruiker en alle bates verwyder. Dit kan nie ontdoen word nie en die lÃĒers kan nie herstel word nie.", @@ -93,15 +101,33 @@ "job_status": "Werkstatus", "library_created": "Biblioteek geskep: {library}", "library_deleted": "Biblioteek verwyder", - "library_import_path_description": "Spesifiseer 'n leer om in te neem. Hierdie leer, en al die sub leers, gaan geskandeer for vir prente en videos.", - "library_scanning": "Periodieke Skandering", - "library_scanning_description": "Stel periodieke skandering van biblioteek in", + "library_import_path_description": "Spesifiseer 'n leer om in te neem. Hierdie leer, en al die sub leers, gaan deursoek word vir prente en videos.", + "library_scanning": "Periodieke Soek", + "library_scanning_description": "Stel periodieke deursoek van biblioteek in", "library_scanning_enable_description": "Aktiveer periodieke biblioteekskandering", "library_settings": "Eksterne Biblioteek", + "library_settings_description": "Eksterne biblioteek verstellings", + "library_tasks_description": "Deursoek eksterne biblioteke vir nuwe of veranderde bates", + "library_watching_enable_description": "Hou eksterne biblioteke dop vir leer veranderinge", + "library_watching_settings": "Biblioteek dop hou (EKSPERIMENTEEL)", + "library_watching_settings_description": "Hou automaties dop vir veranderinge", + "logging_enable_description": "Aktifeer \"logging\"", + "logging_level_description": "Wanneer aktief, watter vlak van \"logs\" om te skep.", + "logging_settings": "\"Logs\"", + "machine_learning_clip_model": "CLIP model", + "machine_learning_duplicate_detection": "Duplikaat herkenning", + "machine_learning_duplicate_detection_enabled": "Aktifeer duplikaat herkenning", + "machine_learning_enabled": "Aktifeer masjienleer", + "machine_learning_facial_recognition": "Gesigsherkenning", + "machine_learning_facial_recognition_description": "Herken, identifiseer en groepeer gesigte in fotos", + "machine_learning_facial_recognition_model": "Gesigsherkennings model", + "machine_learning_facial_recognition_setting": "Aktifeer gesigsherkenning", + "machine_learning_max_detection_distance": "Maksimum herkennings afstand", "map_settings": "Kaart", "migration_job": "Migrasie", "oauth_settings": "OAuth", - "transcoding_acceleration_vaapi": "VAAPI" + "transcoding_acceleration_vaapi": "VAAPI", + "transcoding_preferred_hardware_device": "Verkiesde hardeware" }, "administration": "Administrasie", "advanced": "Gevorderde", diff --git a/i18n/ar.json b/i18n/ar.json index 10e7da5f33..5d94846c52 100644 --- a/i18n/ar.json +++ b/i18n/ar.json @@ -28,10 +28,12 @@ "add_to_album": "ØĨØļØ§ŲØŠ ØĨŲ„Ų‰ ØŖŲ„Ø¨ŲˆŲ…", "add_to_album_bottom_sheet_added": "ØĒŲ…ØĒ Ø§Ų„Ø§ØļØ§ŲØŠ Ø§Ų„Ų‰ {album}", "add_to_album_bottom_sheet_already_exists": "Ų…ŲˆØŦŲˆØ¯ Ų…ØŗØ¨Ų‚Ø§ ؁؊ {album}", + "add_to_album_bottom_sheet_some_local_assets": "Ų„Ø§ ŲŠŲ…ŲƒŲ† ØĨØļØ§ŲØŠ بؚØļ Ø§Ų„ØŖØĩŲˆŲ„ Ø§Ų„Ų…Ø­Ų„ŲŠØŠ ØĨŲ„Ų‰ Ø§Ų„ØŖŲ„Ø¨ŲˆŲ…", "add_to_album_toggle": "ØĒØ¨Ø¯ŲŠŲ„ Ø§Ų„ØĒØ­Ø¯ŲŠØ¯ Ų„Ų€{album}", "add_to_albums": "ØĨØļØ§ŲØŠ Ø§Ų„Ų‰ Ø§Ų„Ø¨ŲˆŲ…Ø§ØĒ", "add_to_albums_count": "ØĨØļØ§ŲŲ‡ ØĨŲ„Ų‰ Ø§Ų„Ø¨ŲˆŲ…Ø§ØĒ ({count})", "add_to_shared_album": "ØĨØļØ§ŲØŠ ØĨŲ„Ų‰ ØŖŲ„Ø¨ŲˆŲ… Ų…Ø´Ø§ØąŲƒ", + "add_upload_to_stack": "اØļ؁ ØąŲØš Ø§Ų„Ų‰ Ø­Ø˛Ų…ØŠ", "add_url": "ØĨØļØ§ŲØŠ ØąØ§Ø¨Øˇ", "added_to_archive": "ØŖŲØļ؊؁ØĒ Ų„Ų„ØŖØąØ´ŲŠŲ", "added_to_favorites": "ØŖŲØļ؊؁ØĒ ؄؄؅؁ØļŲ„Ø§ØĒ", @@ -123,6 +125,13 @@ "logging_enable_description": "ØĒŲØšŲŠŲ„ ØĒØŗØŦŲŠŲ„ Ø§Ų„ØŖØ­Ø¯Ø§ØĢ", "logging_level_description": "ØšŲ†Ø¯ Ø§Ų„ØĒŲØšŲŠŲ„ØŒ ØŖŲŠ Ų…ØŗØĒŲˆŲ‰ ØĒØŗØŦŲŠŲ„ ØŗŲŠØŗØĒØŽØ¯Ų….", "logging_settings": "ØĒØŗØŦŲŠŲ„ Ø§Ų„Ø§Ø­Ø¯Ø§ØĢ", + "machine_learning_availability_checks": "ØĒØ­Ų‚Ų‚ Ų…Ų† Ø§Ų„ØĒŲˆŲØą", + "machine_learning_availability_checks_description": "ØĒØ­Ø¯ŲŠØ¯ ØŽŲˆØ§Ø¯Ų… Ø§Ų„ØĒØšŲ„Ų… Ø§Ų„ØĸŲ„ŲŠ Ø§Ų„Ų…ØĒاح؊ ØĒŲ„Ų‚Ø§ØĻŲŠŲ‹Ø§ ؈ØĨØšØˇØ§ØĄŲ‡Ø§ Ø§Ų„ØŖŲˆŲ„ŲˆŲŠØŠ", + "machine_learning_availability_checks_enabled": "ØĒŲØšŲŠŲ„ ØšŲ…Ų„ŲŠØ§ØĒ ŲØ­Øĩ Ø§Ų„ØĒŲˆŲØą", + "machine_learning_availability_checks_interval": "؁ØĒØąØŠ Ø§Ų„ØĒØ­Ų‚Ų‚", + "machine_learning_availability_checks_interval_description": "Ø§Ų„ŲØĒØąØŠ Ø§Ų„Ø˛Ų…Ų†ŲŠØŠ Ø¨Ø§Ų„Ų…Ų„Ų„ŲŠ ØĢØ§Ų†ŲŠØŠ Ø¨ŲŠŲ† ØšŲ…Ų„ŲŠØ§ØĒ ŲØ­Øĩ Ø§Ų„ØĒŲˆŲØą", + "machine_learning_availability_checks_timeout": "Ø§Ų†ØĒŲ‡ØĒ Ų…Ø¯ØŠ Ø§Ų†ØĒØ¸Ø§Øą Ø§Ų„ØˇŲ„Ø¨", + "machine_learning_availability_checks_timeout_description": "Ų…Ø¯ØŠ Ø§Ų†ØĒØ¸Ø§Øą (Ø¨Ø§Ų„Ų…Ų„Ų„ŲŠ ØĢØ§Ų†ŲŠØŠ) Ų„Ø§ØŽØĒØ¨Ø§ØąØ§ØĒ ØĒŲˆŲØą Ø§Ų„ØŽØ¯Ų…ØŠ", "machine_learning_clip_model": "Ų†Ų…ŲˆØ°ØŦ CLIP", "machine_learning_clip_model_description": "Ø§ØŗŲ… Ų†Ų…ŲˆØ°ØŦ CLIP Ų…Ø¯ØąØŦ، Ų‡Ų†Ø§. ŲŠØąØŦŲ‰ Ų…Ų„Ø§Ø­Ø¸ØŠ ØŖŲ†Ų‡ ؊ØŦب ØĨؚاد؊ ØĒØ´ØēŲŠŲ„ ŲˆØ¸ŲŠŲØŠ \"Ø§Ų„Ø¨Ø­ØĢ Ø§Ų„Ø°ŲƒŲŠ\" Ų„ØŦŲ…ŲŠØš Ø§Ų„ØĩŲˆØą بؚد ØĒØēŲŠŲŠØą Ø§Ų„Ų†Ų…ŲˆØ°ØŦ.", "machine_learning_duplicate_detection": "ŲƒØ´Ų Ø§Ų„ØĒŲƒØąØ§Øą", @@ -387,8 +396,6 @@ "admin_password": "ŲƒŲ„Ų…ØŠ ØŗØą Ø§Ų„Ų…Ø´ØąŲ", "administration": "Ø§Ų„ØĨØ¯Ø§ØąØŠ", "advanced": "Ų…ØĒŲ‚Ø¯Ų…", - "advanced_settings_beta_timeline_subtitle": "ØŦØąØ¨ ØĒØŦØąØ¨ØŠ Ø§Ų„ØĒØˇØ¨ŲŠŲ‚ Ø§Ų„ØŦØ¯ŲŠØ¯ØŠ", - "advanced_settings_beta_timeline_title": "Ø§Ų„ØŦØ¯ŲˆŲ„ Ø§Ų„Ø˛Ų…Ų†ŲŠ Ø§Ų„ØĒØŦØąŲŠØ¨ŲŠ", "advanced_settings_enable_alternate_media_filter_subtitle": "Ø§ØŗØĒØŽØ¯Ų… Ų‡Ø°Ø§ Ø§Ų„ØŽŲŠØ§Øą Ų„ØĒØĩŲŲŠØŠ Ø§Ų„ŲˆØŗØ§ØĻØˇ اØĢŲ†Ø§ØĄ Ø§Ų„Ų…Ø˛Ø§Ų…Ų†Ų‡ Ø¨Ų†Ø§ØĄ ØšŲ„Ų‰ Ų…ØšØ§ŲŠŲŠØą Ø¨Ø¯ŲŠŲ„ØŠ. ØŦØąØ¨ Ų‡Ø°Ø§ Ø§Ų„ØŽŲŠØ§Øą ŲŲ‚Øˇ ŲƒØ§Ų† Ų„Ø¯ŲŠŲƒ Ų…Ø´Ø§ŲƒŲ„ Ų…Øš Ø§Ų„ØĒØˇØ¨ŲŠŲ‚ Ø¨Ø§Ų„ŲƒØ´Ų ØšŲ† ØŦŲ…ŲŠØš Ø§Ų„Ø§Ų„Ø¨ŲˆŲ…Ø§ØĒ.", "advanced_settings_enable_alternate_media_filter_title": "[ØĒØŦØąŲŠØ¨ŲŠ] Ø§ØŗØĒØŽØ¯Ų… ØŦŲ‡Ø§Ø˛ ØĒØĩŲŲŠØŠ Ų…Ø˛Ø§Ų…Ų†Ų‡ Ø§Ų„Ø¨ŲˆŲ…Ø§ØĒ Ø¨Ø¯ŲŠŲ„", "advanced_settings_log_level_title": "Ų…ØŗØĒŲˆŲ‰ Ø§Ų„ØŗØŦŲ„: {level}", @@ -396,6 +403,7 @@ "advanced_settings_prefer_remote_title": "ØĒ؁ØļŲ„ Ø§Ų„ØĩŲˆØą Ø§Ų„Ø¨ØšŲŠØ¯ØŠ", "advanced_settings_proxy_headers_subtitle": "ØšØąŲ ØšŲ†Ø§ŲˆŲŠŲ† Ø§Ų„ŲˆŲƒŲŠŲ„ Ø§Ų„ØĒ؊ ŲŠØŗØĒØŽØ¯Ų…Ų‡Ø§ Immich Ų„Ø§ØąØŗØ§Ų„ ŲƒŲ„ ØˇŲ„Ø¨ Ø´Ø¨ŲƒŲŠ", "advanced_settings_proxy_headers_title": "ØšŲ†Ø§ŲˆŲŠŲ† Ø§Ų„ŲˆŲƒŲŠŲ„", + "advanced_settings_readonly_mode_subtitle": "ØĒØĒŲŠØ­ Ų‡Ø°Ų‡ Ø§Ų„Ų…ŲŠØ˛ØŠ ؈ØļØš Ø§Ų„ØšØąØļ ŲŲ‚ØˇØŒ Ø­ŲŠØĢ ŲŠŲ…ŲƒŲ† Ų„Ų„Ų…ØŗØĒØŽØ¯Ų… Ų…ØšØ§ŲŠŲ†ØŠ Ø§Ų„ØĩŲˆØą ŲŲ‚ØˇØŒ Ø¨ŲŠŲ†Ų…Ø§ ؊ØĒŲ… ØĒØšØˇŲŠŲ„ ØŦŲ…ŲŠØš Ø§Ų„ØŽŲŠØ§ØąØ§ØĒ Ø§Ų„ØŖØŽØąŲ‰ Ų…ØĢŲ„ ØĒØ­Ø¯ŲŠØ¯ ؚد؊ ØĩŲˆØąØŒ ØŖŲˆ Ų…Ø´Ø§ØąŲƒØĒŲ‡Ø§ØŒ ØŖŲˆ بØĢŲ‡Ø§ØŒ ØŖŲˆ Ø­Ø°ŲŲ‡Ø§. ŲŠŲ…ŲƒŲ† ØĒŲØšŲŠŲ„/ØĒØšØˇŲŠŲ„ ؈ØļØš Ø§Ų„ØšØąØļ ŲŲ‚Øˇ Ų…Ų† ØŽŲ„Ø§Ų„ ØĩŲˆØąØŠ Ø§Ų„Ų…ØŗØĒØŽØ¯Ų… ؁؊ Ø§Ų„Ø´Ø§Ø´ØŠ Ø§Ų„ØąØĻŲŠØŗŲŠØŠ", "advanced_settings_readonly_mode_title": "؈ØļØš Ø§Ų„Ų‚ØąØ§ØĄØŠ ŲŲ‚Øˇ", "advanced_settings_self_signed_ssl_subtitle": "ØĒØŽØˇŲŠ Ø§Ų„ØĒØ­Ų‚Ų‚ Ų…Ų† Ø´Ų‡Ø§Ø¯ØŠ SSL Ų„ØŽØ§Ø¯Ų… Ø§Ų„Ų†Ų‚ØˇØŠ Ø§Ų„Ų†Ų‡Ø§ØĻ؊. Ų…ŲƒŲ„ŲˆØ¨ Ų„Ų„Ø´Ų‡Ø§Ø¯Ø§ØĒ Ø§Ų„Ų…ŲˆŲ‚ØšØŠ ذاØĒŲŠØ§.", "advanced_settings_self_signed_ssl_title": "Ø§Ų„ØŗŲ…Ø§Ø­ Ø¨Ø´Ų‡Ø§Ø¯Ø§ØĒ SSL Ø§Ų„Ų…ŲˆŲ‚ØšØŠ ذاØĒŲŠŲ‹Ø§", @@ -424,6 +432,7 @@ "album_remove_user_confirmation": "Ų‡Ų„ ØŖŲ†ØĒ Ų…ØĒØŖŲƒØ¯ ØŖŲ†Ųƒ ØĒØąŲŠØ¯ ØĨØ˛Ø§Ų„ØŠ {user}؟", "album_search_not_found": "Ų„Ų… ؊ØĒŲ… Ø§ŲŠØŦاد Ø§Ų„Ø¨ŲˆŲ… Ų…ØˇØ§Ø¨Ų‚ Ų„Ø¨Ø­ØĢ؃", "album_share_no_users": "ŲŠØ¨Ø¯Ųˆ ØŖŲ†Ųƒ Ų‚Ų…ØĒ Ø¨Ų…Ø´Ø§ØąŲƒØŠ Ų‡Ø°Ø§ Ø§Ų„ØŖŲ„Ø¨ŲˆŲ… Ų…Øš ØŦŲ…ŲŠØš Ø§Ų„Ų…ØŗØĒØŽØ¯Ų…ŲŠŲ† ØŖŲˆ Ų„ŲŠØŗ Ų„Ø¯ŲŠŲƒ ØŖŲŠ Ų…ØŗØĒØŽØ¯Ų… Ų„Ų„Ų…Ø´Ø§ØąŲƒØŠ Ų…ØšŲ‡.", + "album_summary": "Ų…Ų„ØŽØĩ Ø§Ų„ØŖŲ„Ø¨ŲˆŲ…", "album_updated": "ØĒŲ… ØĒØ­Ø¯ŲŠØĢ Ø§Ų„ØŖŲ„Ø¨ŲˆŲ…", "album_updated_setting_description": "ØĒŲ„Ų‚ŲŠ ØĨØ´ØšØ§ØąŲ‹Ø§ ØšØ¨Øą Ø§Ų„Ø¨ØąŲŠØ¯ Ø§Ų„ØĨŲ„ŲƒØĒØąŲˆŲ†ŲŠ ØšŲ†Ø¯Ų…Ø§ ŲŠØ­ØĒ؈؊ Ø§Ų„ØŖŲ„Ø¨ŲˆŲ… Ø§Ų„Ų…Ø´ØĒØąŲƒ ØšŲ„Ų‰ Ų…Ø­ØĒŲˆŲŠØ§ØĒ ØŦØ¯ŲŠØ¯ØŠ", "album_user_left": "ØĒŲ… ØĒØąŲƒ {album}", @@ -462,6 +471,7 @@ "app_bar_signout_dialog_title": "ØŽØąŲˆØŦ", "app_settings": "ØĨؚداداØĒ Ø§Ų„ØĒØˇØ¨ŲŠŲ‚", "appears_in": "ŲŠØ¸Ų‡Øą ؁؊", + "apply_count": "ØĒØˇØ¨ŲŠŲ‚ ({count, number})", "archive": "Ø§Ų„ØŖØąØ´ŲŠŲ", "archive_action_prompt": "{count} اØļ؊؁ ØĨŲ„Ų‰ Ø§Ų„Ø§ØąØ´ŲŠŲ", "archive_or_unarchive_photo": "ØŖØąØ´ŲØŠ Ø§Ų„ØĩŲˆØąØŠ ØŖŲˆ ØĨŲ„ØēØ§ØĄ ØŖØąØ´ŲØĒŲ‡Ø§", @@ -494,6 +504,8 @@ "asset_restored_successfully": "ØĒŲ… Ø§ØŗØĒؚاد؊ Ø§Ų„Ø§ØĩŲ„ Ø¨Ų†ØŦاح", "asset_skipped": "ØĒŲ… ØĒØŽØˇŲŠŲ‡", "asset_skipped_in_trash": "؁؊ ØŗŲ„ØŠ Ø§Ų„Ų…Ų‡Ų…Ų„Ø§ØĒ", + "asset_trashed": "اØĩŲˆŲ„ Ų…Ø­Ø°ŲˆŲØŠ", + "asset_troubleshoot": "Ø§ØŗØĒŲƒØ´Ø§Ų Ų…Ø´Ø§ŲƒŲ„ Ø§Ų„ØŖØĩŲˆŲ„", "asset_uploaded": "ØĒŲ… Ø§Ų„ØąŲØš", "asset_uploading": "ØŦØ§ØąŲ Ø§Ų„ØąŲØšâ€Ļ", "asset_viewer_settings_subtitle": "ØĨØ¯Ø§ØąØŠ ØĨؚداداØĒ ØšØ§ØąØļ Ø§Ų„Ų…ØšØąØļ Ø§Ų„ØŽØ§Øĩ Ø¨Ųƒ", @@ -501,7 +513,9 @@ "assets": "Ø§Ų„Ų…Ø­ØĒŲˆŲŠØ§ØĒ", "assets_added_count": "ØĒŲ…ØĒ ØĨØļØ§ŲØŠ {count, plural, one {# Ų…Ø­ØĒŲˆŲ‰} other {# Ų…Ø­ØĒŲˆŲŠØ§ØĒ}}", "assets_added_to_album_count": "ØĒŲ…ØĒ ØĨØļØ§ŲØŠ {count, plural, one {# Ø§Ų„ØŖØĩŲ„} other {# Ø§Ų„ØŖØĩŲˆŲ„}} ØĨŲ„Ų‰ Ø§Ų„ØŖŲ„Ø¨ŲˆŲ…", + "assets_added_to_albums_count": "ØĒŲ…ØĒ اØļØ§ŲØŠ {assetTotal, plural, one {# اØĩŲ„} other {# اØĩŲˆŲ„}} to {albumTotal, plural, one {# Ø§Ų„Ø¨ŲˆŲ…} other {# Ø§Ų„Ø¨ŲˆŲ…Ø§ØĒ}}", "assets_cannot_be_added_to_album_count": "{count, plural, one {Asset} other {Assets}} Ų„Ø§ŲŠŲ…ŲƒŲ† اØļØ§ŲØĒŲ‡ Ø§Ų„Ų‰ Ø§Ų„Ø§Ų„Ø¨ŲˆŲ…", + "assets_cannot_be_added_to_albums": "{count, plural, one {اØĩŲ„} other {اØĩŲˆŲ„}} Ų„Ø§ ŲŠŲ…ŲƒŲ† ØĨØļØ§ŲØĒŲ‡ ØĨŲ„Ų‰ ØŖŲŠ Ų…Ų† Ø§Ų„ØŖŲ„Ø¨ŲˆŲ…Ø§ØĒ", "assets_count": "{count, plural, one {# Ų…Ø­ØĒŲˆŲ‰} other {# Ų…Ø­ØĒŲˆŲŠØ§ØĒ}}", "assets_deleted_permanently": "{count} Ø§Ų„Ø§Øĩ(؈)Ų„ Ø§Ų„Ų…Ø­Ø°ŲˆŲ(Ų‡) Ø¨Ø´ŲƒŲ„ داØĻŲ…", "assets_deleted_permanently_from_server": "{count} Ø§Ų„Ø§Øĩ(؈)Ų„ Ø§Ų„Ų…Ø­Ø°ŲˆŲ(Ų‡) Ø¨Ø´ŲƒŲ„ داØĻŲ…ŲŠ Ų…Ų† ØŽØ§Ø¯Ų… Immich", @@ -518,14 +532,17 @@ "assets_trashed_count": "ØĒŲ… ØĨØąØŗØ§Ų„ {count, plural, one {# Ų…Ø­ØĒŲˆŲ‰} other {# Ų…Ø­ØĒŲˆŲŠØ§ØĒ}} ØĨŲ„Ų‰ ØŗŲ„ØŠ Ø§Ų„Ų…Ų‡Ų…Ų„Ø§ØĒ", "assets_trashed_from_server": "{count} Ø§Ų„Ø§Øĩ(؈)Ų„ Ø§Ų„Ų…Ų†Ų‚ŲˆŲ„ØŠ Ø§Ų„Ų‰ ØŗŲ„ØŠ Ø§Ų„Ų…Ų‡Ų…Ų„Ø§ØĒ Ų…Ų† ØŽØ§Ø¯Ų… Immich", "assets_were_part_of_album_count": "{count, plural, one {Ų‡Ø°Ø§ Ø§Ų„Ų…Ø­ØĒŲˆŲ‰} other {Ų‡Ø°Ų‡ Ø§Ų„Ų…Ø­ØĒŲˆŲŠØ§ØĒ}} ؁؊ Ø§Ų„ØŖŲ„Ø¨ŲˆŲ… Ø¨Ø§Ų„ŲØšŲ„", + "assets_were_part_of_albums_count": "{count, plural, one {اØĩŲ„ Ų‡Ųˆ} other {اØĩŲˆŲ„ Ų‡ŲŠ}}Ø¨Ø§Ų„ŲØšŲ„ ØŦØ˛ØĄ Ų…Ų† Ø§Ų„ØŖŲ„Ø¨ŲˆŲ…Ø§ØĒ", "authorized_devices": "Ø§Ų„ØŖØŦŲ‡Ø˛Ų‡ Ø§Ų„Ų…ØŽŲˆŲ„ØŠ", "automatic_endpoint_switching_subtitle": "اØĒØĩŲ„ Ų…Ø­Ų„ŲŠØ§ Ų…Ų† ØŽŲ„Ø§Ų„ Ø´Ø¨ŲƒŲ‡ Wi-Fi ØšŲ†Ø¯ ØĒŲˆŲØąŲ‡Ø§ ؈ Ø§ØŗØĒØŽØ¯Ų… اØĒØĩØ§Ų„Ø§ØĒ Ø¨Ø¯ŲŠŲ„Ų‡ ؁؊ Ø§Ų„Ø§Ų…Ø§ŲƒŲ† Ø§Ų„Ø§ØŽØąŲ‰", "automatic_endpoint_switching_title": "ØĒØ¨Ø¯ŲŠŲ„ URL ØĒŲ„Ų‚Ø§ØĻ؊", "autoplay_slideshow": "ØĒØ´ØēŲŠŲ„ ØĒŲ„Ų‚Ø§ØĻ؊ Ų„ØšØąØļ Ø§Ų„Ø´ØąØ§ØĻØ­", "back": "ØŽŲ„Ų", "back_close_deselect": "Ø§Ų„ØąØŦŲˆØš ØŖŲˆ Ø§Ų„ØĨØēŲ„Ø§Ų‚ ØŖŲˆ ØĨŲ„ØēØ§ØĄ Ø§Ų„ØĒØ­Ø¯ŲŠØ¯", + "background_backup_running_error": "؊ØĒŲ… ØĒØ´ØēŲŠŲ„ Ø§Ų„Ų†ØŗØŽ Ø§Ų„Ø§Ø­ØĒŲŠØ§ØˇŲŠ ؁؊ Ø§Ų„ØŽŲ„ŲŲŠØŠ Ø­Ø§Ų„ŲŠŲ‹Ø§ØŒ ŲˆŲ„Ø§ ŲŠŲ…ŲƒŲ† Ø¨Ø¯ØĄ Ø§Ų„Ų†ØŗØŽ Ø§Ų„Ø§Ø­ØĒŲŠØ§ØˇŲŠ Ø§Ų„ŲŠØ¯ŲˆŲŠ", "background_location_permission": "Ø§Ø°Ų† Ø§Ų„ŲˆØĩŲˆŲ„ Ų„Ų„Ų…ŲˆŲ‚Øš ؁؊ Ø§Ų„ØŽŲ„ŲŲŠØŠ", "background_location_permission_content": "Ų„Ų„ØĒŲ…ŲƒŲ† Ų…Ų† ØĒØ¨Ø¯ŲŠŲ„ Ø§Ų„Ø´Ø¨ŲƒŲ‡ Ø¨Ø§Ų„ØŽŲ„ŲŲŠØŠØŒ Immich ŲŠØ­ØĒاØŦ*داØĻŲ…Ø§* Ų„Ų„Ø­ØĩŲˆŲ„ ØšŲ„Ų‰ Ų…ŲˆŲ‚Øš Ø¯Ų‚ŲŠŲ‚ Ų„ŲŠØĒŲ…ŲƒŲ† Ø§Ų„ØĒØˇØ¨ŲŠŲ‚ Ų…Ų† Ų‚ØąØ§ØĻØŠ Ø§ØŗŲ… Ø´Ø¨ŲƒØŠ Ø§Ų„Wi-Fi", + "background_options": "ØŽŲŠØ§ØąØ§ØĒ Ø§Ų„ØŽŲ„ŲŲŠØŠ", "backup": "Ų†ØŗØŽ احØĒŲŠØ§ØˇŲŠ", "backup_album_selection_page_albums_device": "Ø§Ų„Ø§Ų„Ø¨ŲˆŲ…Ø§ØĒ ØšŲ„Ų‰ Ø§Ų„ØŦŲ‡Ø§Ø˛ ({count})", "backup_album_selection_page_albums_tap": "Ø§Ų†Ų‚Øą Ų„Ų„ØĒØļŲ…ŲŠŲ†ØŒ ŲˆØ§Ų†Ų‚Øą Ų†Ų‚ØąŲ‹Ø§ Ų…Ø˛Ø¯ŲˆØŦŲ‹Ø§ Ų„Ų„Ø§ØŗØĒØĢŲ†Ø§ØĄ", @@ -533,6 +550,7 @@ "backup_album_selection_page_select_albums": "حدد Ø§Ų„ØŖŲ„Ø¨ŲˆŲ…Ø§ØĒ", "backup_album_selection_page_selection_info": "Ų…ØšŲ„ŲˆŲ…Ø§ØĒ Ø§Ų„Ø§ØŽØĒŲŠØ§Øą", "backup_album_selection_page_total_assets": "ØĨØŦŲ…Ø§Ų„ŲŠ Ø§Ų„ØŖØĩŲˆŲ„ Ø§Ų„ŲØąŲŠØ¯ØŠ", + "backup_albums_sync": "Ų…Ø˛Ø§Ų…Ų†ØŠ ØŖŲ„Ø¨ŲˆŲ…Ø§ØĒ Ø§Ų„Ų†ØŗØŽ Ø§Ų„Ø§Ø­ØĒŲŠØ§ØˇŲŠ", "backup_all": "Ø§Ų„ØŦŲ…ŲŠØš", "backup_background_service_backup_failed_message": "ŲØ´Ų„ ؁؊ Ø§Ų„Ų†ØŗØŽ Ø§Ų„Ø§Ø­ØĒŲŠØ§ØˇŲŠ Ų„Ų„ØŖØĩŲˆŲ„. ØŦØ§ØąŲ ØĨؚاد؊ Ø§Ų„Ų…Ø­Ø§ŲˆŲ„ØŠâ€Ļ", "backup_background_service_connection_failed_message": "ŲØ´Ų„ ؁؊ Ø§Ų„Ø§ØĒØĩØ§Ų„ Ø¨Ø§Ų„ØŽØ§Ø¯Ų…. ØŦØ§ØąŲ ØĨؚاد؊ Ø§Ų„Ų…Ø­Ø§ŲˆŲ„ØŠâ€Ļ", @@ -582,6 +600,7 @@ "backup_controller_page_turn_on": "Ų‚Ų… بØĒØ´ØēŲŠŲ„ Ø§Ų„Ų†ØŗØŽ Ø§Ų„Ø§Ø­ØĒŲŠØ§ØˇŲŠ Ø§Ų„Ų…Ų‚Ø¯Ų…ØŠ", "backup_controller_page_uploading_file_info": "ØĒØ­Ų…ŲŠŲ„ Ų…ØšŲ„ŲˆŲ…Ø§ØĒ Ø§Ų„Ų…Ų„Ų", "backup_err_only_album": "Ų„Ø§ ŲŠŲ…ŲƒŲ† ØĨØ˛Ø§Ų„ØŠ Ø§Ų„ØŖŲ„Ø¨ŲˆŲ… Ø§Ų„ŲˆØ­ŲŠØ¯", + "backup_error_sync_failed": "ŲØ´Ų„ Ø§Ų„Ų…Ø˛Ø§Ų…Ų†ØŠ. Ų„Ø§ ŲŠŲ…ŲƒŲ† Ų…ØšØ§Ų„ØŦØŠ Ø§Ų„Ų†ØŗØŽ Ø§Ų„Ø§Ø­ØĒŲŠØ§ØˇŲŠ.", "backup_info_card_assets": "ØŖØĩŲˆŲ„", "backup_manual_cancelled": "Ų…Ų„Øē؊", "backup_manual_in_progress": "Ų‚ŲŠØ¯ Ø§Ų„ØĒØ­Ų…ŲŠŲ„ Ø­Ø§ŲˆŲ„ Ų…ØąŲ‡ Ø§ØŽØąŲ‰", @@ -592,8 +611,6 @@ "backup_setting_subtitle": "Ø§Ø¯Ø§ØąØŠ اؚداداØĒ Ø§Ų„ØĒØ­Ų…ŲŠŲ„ ؁؊ Ø§Ų„ØŽŲ„ŲŲŠØŠ ŲˆØ§Ų„Ų…Ų‚Ø¯Ų…ØŠ", "backup_settings_subtitle": "ØĨØ¯Ø§ØąØŠ ØĨؚداداØĒ Ø§Ų„ØĒØ­Ų…ŲŠŲ„", "backward": "Ø§Ų„Ų‰ Ø§Ų„ŲˆØąØ§ØĄ", - "beta_sync": "Ø­Ø§Ų„ØŠ Ø§Ų„Ų…Ø˛Ø§Ų…Ų†ØŠ Ø§Ų„ØĒØŦØąŲŠØ¨ŲŠØŠ", - "beta_sync_subtitle": "Ø§Ø¯Ø§ØąØŠ Ų†Ø¸Ø§Ų… Ø§Ų„Ų…Ø˛Ø§Ų…Ų†ØŠ Ø§Ų„ØŦØ¯ŲŠØ¯", "biometric_auth_enabled": "Ø§Ų„Ų…ØĩØ§Ø¯Ų‚ØŠ Ø§Ų„Ø¨Ø§ŲŠŲˆŲ…ØĒØąŲŠØŠ Ų…ŲØšŲ„Ų‡", "biometric_locked_out": "Ų„Ų‚Ø¯ ؂؁؄ØĒ ØšŲ†Ųƒ Ø§Ų„Ų…ØĩØ§Ø¯Ų‚ØŠ Ø§Ų„Ø¨ŲŠŲˆŲ…ØĒØąŲŠØŠ", "biometric_no_options": "Ų„Ø§ ØĒ؈ØŦد ØŽŲŠØ§ØąØ§ØĒ Ø¨Ø§ŲŠŲˆŲ…ØĒØąŲŠØŠ Ų…ØĒŲˆŲØąØŠ", @@ -651,6 +668,8 @@ "change_pin_code": "ØĒØēŲŠŲŠØą ØąŲ…Ø˛ PIN", "change_your_password": "ØēŲŠØą ŲƒŲ„Ų…ØŠ Ø§Ų„Ų…ØąŲˆØą Ø§Ų„ØŽØ§ØĩØŠ Ø¨Ųƒ", "changed_visibility_successfully": "ØĒŲ… ØĒØēŲŠŲŠØą Ø§Ų„ØąØ¤ŲŠØŠ Ø¨Ų†ØŦاح", + "charging": "Ø§Ų„Ø´Ø­Ų†", + "charging_requirement_mobile_backup": "؊ØĒØˇŲ„Ø¨ Ø§Ų„Ų†ØŗØŽ Ø§Ų„Ø§Ø­ØĒŲŠØ§ØˇŲŠ ؁؊ Ø§Ų„ØŽŲ„ŲŲŠØŠ ØŖŲ† ŲŠŲƒŲˆŲ† Ø§Ų„ØŦŲ‡Ø§Ø˛ Ų‚ŲŠØ¯ Ø§Ų„Ø´Ø­Ų†", "check_corrupt_asset_backup": "Ø§Ų„ØĒØ­Ų‚Ų‚ Ų…Ų† ؈ØŦŲˆØ¯ Ų†ØŗØŽ احØĒŲŠØ§ØˇŲŠØŠ ŲØ§ØŗØ¯ØŠ Ų„Ų„Ø§ØĩŲˆŲ„", "check_corrupt_asset_backup_button": "اØŦØąØ§ØĄ ŲØ­Øĩ", "check_corrupt_asset_backup_description": "Ų‚Ų… بØĨØŦØąØ§ØĄ Ų‡Ø°Ø§ Ø§Ų„ŲØ­Øĩ ŲŲ‚Øˇ ØšØ¨Øą Ø´Ø¨ŲƒØŠ Wi-Fi ŲˆØ¨ØšØ¯ Ų†ØŗØŽ ØŦŲ…ŲŠØš Ø§Ų„ØŖØĩŲˆŲ„ احØĒŲŠØ§ØˇŲŠŲ‹Ø§. Ų‚Ø¯ ŲŠØŗØĒØēØąŲ‚ Ø§Ų„ØĨØŦØąØ§ØĄ بØļØš Ø¯Ų‚Ø§ØĻŲ‚.", @@ -737,6 +756,7 @@ "create_user": "ØĨŲ†Ø´Ø§ØĄ Ų…ØŗØĒØŽØ¯Ų…", "created": "ØĒŲ… Ø§Ų„ØĨŲ†Ø´Ø§ØĄ", "created_at": "Ų…ØŽŲ„ŲˆŲ‚", + "creating_linked_albums": "ØŦØ§ØąŲŠ ØĨŲ†Ø´Ø§ØĄ Ø§Ų„ØŖŲ„Ø¨ŲˆŲ…Ø§ØĒ Ø§Ų„Ų…ØąØĒØ¨ØˇØŠ...", "crop": "Ų‚Øĩ", "curated_object_page_title": "ØŖØ´ŲŠØ§ØĄ", "current_device": "Ø§Ų„ØŦŲ‡Ø§Ø˛ Ø§Ų„Ø­Ø§Ų„ŲŠ", @@ -886,7 +906,9 @@ "error": "ØŽØˇØŖ", "error_change_sort_album": "ŲØ´Ų„ ؁؊ ØĒØēŲŠŲŠØą ØĒØąØĒŲŠØ¨ Ø§Ų„ØŖŲ„Ø¨ŲˆŲ…", "error_delete_face": "حدØĢ ØŽØˇØŖ ؁؊ Ø­Ø°Ų Ø§Ų„ŲˆØŦŲ‡ Ų…Ų† Ø§Ų„ØŖØĩŲˆŲ„", + "error_getting_places": "ØŽØˇØŖ ØŖØĢŲ†Ø§ØĄ Ø§ØŗØĒØąØŦاؚ Ø¨ŲŠØ§Ų†Ø§ØĒ Ø§Ų„Ų…ŲˆØ§Ų‚Øš", "error_loading_image": "حدØĢ ØŽØˇØŖ ØŖØĢŲ†Ø§ØĄ ØĒØ­Ų…ŲŠŲ„ Ø§Ų„ØĩŲˆØąØŠ", + "error_loading_partners": "ØŽØˇØŖ بØĒØ­Ų…ŲŠŲ„ Ø¨ŲŠØ§Ų†Ø§ØĒ Ø§Ų„Ø´ØąŲƒØ§ØĄ: {error}", "error_saving_image": "ØŽØˇØŖ: {error}", "error_tag_face_bounding_box": "ØŽØˇØŖ ؁؊ ؈ØļØš ØšŲ„Ø§Ų…ØŠ ØšŲ„Ų‰ Ø§Ų„ŲˆØŦŲ‡ - Ų„Ø§ ŲŠŲ…ŲƒŲ† Ø§Ų„Ø­ØĩŲˆŲ„ ØšŲ„Ų‰ ØĨحداØĢŲŠØ§ØĒ Ø§Ų„Ų…ØąØ¨Øš Ø§Ų„Ų…Ø­ŲŠØˇ", "error_title": "ØŽØˇØŖ - حدØĢ ØŽŲ„Ų„ŲŒ Ų…Ø§", @@ -1051,6 +1073,7 @@ "favorites_page_no_favorites": "Ų„Ų… ؊ØĒŲ… Ø§Ų„ØšØĢŲˆØą ØšŲ„Ų‰ Ø§Ų„ØŖØĩŲˆŲ„ Ø§Ų„Ų…ŲØļŲ„ØŠ", "feature_photo_updated": "ØĒŲ… ØĒØ­Ø¯ŲŠØĢ Ø§Ų„ØĩŲˆØąØŠ Ø§Ų„Ų…Ų…ŲŠØ˛ØŠ", "features": "Ø§Ų„Ų…ŲŠØ˛Ø§ØĒ", + "features_in_development": "Ø§Ų„Ų…ŲŠØ˛Ø§ØĒ Ų‚ŲŠØ¯ Ø§Ų„ØĒØˇŲˆŲŠØą", "features_setting_description": "ØĨØ¯Ø§ØąØŠ Ų…ŲŠØ˛Ø§ØĒ Ø§Ų„ØĒØˇØ¨ŲŠŲ‚", "file_name": "ØĨØŗŲ… Ø§Ų„Ų…Ų„Ų", "file_name_or_extension": "Ø§ØŗŲ… Ø§Ų„Ų…Ų„Ų ØŖŲˆ Ø§Ų…ØĒØ¯Ø§Ø¯Ų‡", @@ -1071,12 +1094,15 @@ "gcast_enabled": "ŲƒŲˆŲƒŲ„ ŲƒØ§ØŗØĒ", "gcast_enabled_description": "ØĒŲ‚ŲˆŲ… Ų‡Ø°Ų‡ Ø§Ų„Ų…ŲŠØ˛ØŠ بØĒØ­Ų…ŲŠŲ„ Ø§Ų„Ų…ŲˆØ§ØąØ¯ Ø§Ų„ØŽØ§ØąØŦŲŠØŠ Ų…Ų† Google Ø­ØĒŲ‰ ØĒØšŲ…Ų„.", "general": "ØšØ§Ų…", + "geolocation_instruction_location": "Ø§Ų†Ų‚Øą ØšŲ„Ų‰ Ø§Ų„Ø§ØĩŲ„ Ø§Ų„Ø°ŲŠ ŲŠØ­ØĒ؈؊ ØšŲ„Ų‰ ØĨحداØĢŲŠØ§ØĒ Ų†Ø¸Ø§Ų… ØĒØ­Ø¯ŲŠØ¯ Ø§Ų„Ų…ŲˆØ§Ų‚Øš Ų„Ø§ØŗØĒØŽØ¯Ø§Ų… Ų…ŲˆŲ‚ØšŲ‡ØŒ ØŖŲˆ ا؎ØĒØą Ø§Ų„Ų…ŲˆŲ‚Øš Ų…Ø¨Ø§Ø´ØąØŠ Ų…Ų† Ø§Ų„ØŽØąŲŠØˇØŠ", "get_help": "Ø§Ų„Ø­ØĩŲˆŲ„ ØšŲ„Ų‰ Ø§Ų„Ų…ØŗØ§ØšØ¯ØŠ", "get_wifiname_error": "ØĒØšØ°Øą Ø§Ų„Ø­ØĩŲˆŲ„ ØšŲ„Ų‰ Ø§ØŗŲ… Ø´Ø¨ŲƒØŠ Wi-Fi. ØĒØŖŲƒØ¯ Ų…Ų† Ų…Ų†Ø­ Ø§Ų„ØŖØ°ŲˆŲ†Ø§ØĒ Ø§Ų„Ų„Ø§Ø˛Ų…ØŠ ŲˆØ§ØĒØĩØ§Ų„Ųƒ Ø¨Ø´Ø¨ŲƒØŠ Wi-Fi", "getting_started": "Ø§Ų„Ø¨Ø¯ØĄ", "go_back": "Ø§Ų„ØąØŦŲˆØš Ų„Ų„ØŽŲ„Ų", "go_to_folder": "Ø§Ø°Ų‡Ø¨ ØĨŲ„Ų‰ Ø§Ų„Ų…ØŦŲ„Ø¯", "go_to_search": "Ø§Ø°Ų‡Ø¨ ØĨŲ„Ų‰ Ø§Ų„Ø¨Ø­ØĢ", + "gps": "Ų†Ø¸Ø§Ų… ØĒØ­Ø¯ŲŠØ¯ Ø§Ų„Ų…ŲˆØ§Ų‚Øš", + "gps_missing": "Ų„Ø§ ؊؈ØŦد Ų†Ø¸Ø§Ų… ØĒØ­Ø¯ŲŠØ¯ Ø§Ų„Ų…ŲˆØ§Ų‚Øš", "grant_permission": "Ų…Ų†Ø­ Ø§Ų„Ø§Ø°Ų†", "group_albums_by": "ØĒØŦŲ…ŲŠØš Ø§Ų„ØŖŲ„Ø¨ŲˆŲ…Ø§ØĒ Ø­ØŗØ¨...", "group_country": "Ų…ØŦŲ…ŲˆØšØŠ Ø§Ų„Ø¨Ų„Ø¯", @@ -1212,6 +1238,7 @@ "local": "Ų…Ø­Ų„Ų‘ŲŠ", "local_asset_cast_failed": "ØēŲŠØą Ų‚Ø§Ø¯Øą ØšŲ„Ų‰ بØĢ ØŖØĩŲ„ Ų„Ų… ؊ØĒŲ… ØĒØ­Ų…ŲŠŲ„Ų‡ ØĨŲ„Ų‰ Ø§Ų„ØŽØ§Ø¯Ų…", "local_assets": "ØŖŲØĩŲˆŲ„ (Ų…Ų„ŲØ§ØĒ) Ų…Ø­Ų„ŲŠØŠ", + "local_media_summary": "Ų…Ų„ØŽØĩ Ø§Ų„Ų…Ų„ŲØ§ØĒ Ø§Ų„Ų…Ø­Ų„ŲŠØŠ", "local_network": "Ø´Ø¨ŲƒØŠ Ų…Ø­Ų„ŲŠØŠ", "local_network_sheet_info": "ØŗŲŠØĒØĩŲ„ Ø§Ų„ØĒØˇØ¨ŲŠŲ‚ Ø¨Ø§Ų„ØŽØ§Ø¯Ų… Ų…Ų† ØŽŲ„Ø§Ų„ ØšŲ†ŲˆØ§Ų† URL Ų‡Ø°Ø§ ØšŲ†Ø¯ Ø§ØŗØĒØŽØ¯Ø§Ų… Ø´Ø¨ŲƒØŠ Wi-Fi Ø§Ų„Ų…Ø­Ø¯Ø¯ØŠ", "location_permission": "Ø§Ø°Ų† Ø§Ų„Ų…ŲˆŲ‚Øš", @@ -1223,6 +1250,7 @@ "location_picker_longitude_hint": "ØŖØ¯ØŽŲ„ ØŽØˇ Ø§Ų„ØˇŲˆŲ„ Ų‡Ų†Ø§", "lock": "؂؁؄", "locked_folder": "Ų…ØŦŲ„Ø¯ Ų…Ų‚ŲŲˆŲ„", + "log_detail_title": "ØĒŲØ§ØĩŲŠŲ„ Ø§Ų„ØŗØŦŲ„", "log_out": "ØĒØŗØŦŲŠŲ„ ØŽØąŲˆØŦ", "log_out_all_devices": "ØĒØŗØŦŲŠŲ„ Ø§Ų„ØŽØąŲˆØŦ Ų…Ų† ŲƒØ§ŲØŠ Ø§Ų„ØŖØŦŲ‡Ø˛ØŠ", "logged_in_as": "ØĒŲ… ØĒØŗØŦŲŠŲ„ Ø§Ų„Ø¯ØŽŲˆŲ„ Ø¨Ø§ØŗŲ… {user}", @@ -1253,6 +1281,7 @@ "login_password_changed_success": "ØĒŲ… ØĒØ­Ø¯ŲŠØĢ ŲƒŲ„Ų…ØŠ Ø§Ų„ØŗØą Ø¨Ų†ØŦاح", "logout_all_device_confirmation": "Ų‡Ų„ ØŖŲ†ØĒ Ų…ØĒØŖŲƒØ¯ ØŖŲ†Ųƒ ØĒØąŲŠØ¯ ØĒØŗØŦŲŠŲ„ Ø§Ų„ØŽØąŲˆØŦ Ų…Ų† ØŦŲ…ŲŠØš Ø§Ų„ØŖØŦŲ‡Ø˛ØŠØŸ", "logout_this_device_confirmation": "Ų‡Ų„ ØŖŲ†ØĒ Ų…ØĒØŖŲƒØ¯ ØŖŲ†Ųƒ ØĒØąŲŠØ¯ ØĒØŗØŦŲŠŲ„ Ø§Ų„ØŽØąŲˆØŦ Ų…Ų† Ų‡Ø°Ø§ Ø§Ų„ØŦŲ‡Ø§Ø˛ØŸ", + "logs": "Ø§Ų„ØŗØŦŲ„Ø§ØĒ", "longitude": "ØŽØˇ Ø§Ų„ØˇŲˆŲ„", "look": "Ø§Ų„Ø´ŲƒŲ„", "loop_videos": "ØĒŲƒØąØ§Øą Ų…Ų‚Ø§ØˇØš Ø§Ų„ŲŲŠØ¯ŲŠŲˆ", @@ -1260,6 +1289,7 @@ "main_branch_warning": "ØŖŲ†ØĒ ØĒØŗØĒØŽØ¯Ų… ØĨØĩØ¯Ø§ØąØ§Ų‹ Ų‚ŲŠØ¯ Ø§Ų„ØĒØˇŲˆŲŠØąØ› ŲˆŲ†Ø­Ų† Ų†ŲˆØĩ؊ بشد؊ Ø¨Ø§ØŗØĒØŽØ¯Ø§Ų… ØĨØĩØ¯Ø§Øą Ø§Ų„Ų†Ø´Øą!", "main_menu": "Ø§Ų„Ų‚Ø§ØĻŲ…ØŠ Ø§Ų„ØąØĻŲŠØŗŲŠØŠ", "make": "ØĩŲ†Øš", + "manage_geolocation": "ØĨØ¯Ø§ØąØŠ Ø§Ų„Ų…ŲˆŲ‚Øš", "manage_shared_links": "ØĨØ¯Ø§ØąØŠ Ø§Ų„ØąŲˆØ§Ø¨Øˇ Ø§Ų„Ų…Ø´ØĒØąŲƒØŠ", "manage_sharing_with_partners": "ØĨØ¯Ø§ØąØŠ Ø§Ų„Ų…Ø´Ø§ØąŲƒØŠ Ų…Øš Ø§Ų„Ø´ØąŲƒØ§ØĄ", "manage_the_app_settings": "ØĨØ¯Ø§ØąØŠ ØĨؚداداØĒ Ø§Ų„ØĒØˇØ¨ŲŠŲ‚", @@ -1294,6 +1324,7 @@ "mark_as_read": "ØĒØ­Ø¯ŲŠØ¯ ŲƒŲ…Ų‚ØąŲˆØĄ", "marked_all_as_read": "ØĒŲ… ØĒØ­Ø¯ŲŠØ¯ Ø§Ų„ŲƒŲ„ ŲƒŲ…Ų‚ØąŲˆØĄ", "matches": "ØĒØˇØ§Ø¨Ų‚Ø§ØĒ", + "matching_assets": "â€Ø§Ų„Ø§ØĩŲˆŲ„ Ø§Ų„Ų…ØˇØ§Ø¨Ų‚ØŠ", "media_type": "Ų†ŲˆØš Ø§Ų„ŲˆØŗØ§ØĻØˇ", "memories": "Ø§Ų„Ø°ŲƒØąŲŠØ§ØĒ", "memories_all_caught_up": "ŲƒŲ„ Ø´ŲŠØĄ Ų…Ø­Ø¯ØĢ", @@ -1334,6 +1365,7 @@ "name_or_nickname": "Ø§Ų„Ø§ØŗŲ… ØŖŲˆ Ø§Ų„Ų„Ų‚Ø¨", "network_requirement_photos_upload": "Ø§ØŗØĒØŽØ¯Ø§Ų… Ø¨ŲŠØ§Ų†Ø§ØĒ Ø§Ų„Ų‡Ø§ØĒ؁ Ø§Ų„Ų…Ø­Ų…ŲˆŲ„ Ų„ØšŲ…Ų„ Ų†ØŗØŽØŠ احØĒŲŠØ§ØˇŲŠØŠ Ų„Ų„ØĩŲˆØą", "network_requirement_videos_upload": "Ø§ØŗØĒØŽØ¯Ø§Ų… Ø¨ŲŠØ§Ų†Ø§ØĒ Ø§Ų„Ų‡Ø§ØĒ؁ Ø§Ų„Ų…Ø­Ų…ŲˆŲ„ Ų„ØšŲ…Ų„ Ų†ØŗØŽØŠ احØĒŲŠØ§ØˇŲŠØŠ Ų„Ų…Ų‚Ø§ØˇØš Ø§Ų„ŲŲŠØ¯ŲŠŲˆ", + "network_requirements": "Ų…ØĒØˇŲ„Ø¨Ø§ØĒ Ø§Ų„Ø´Ø¨ŲƒØŠ", "network_requirements_updated": "ØĒŲ… ØĒØēŲŠŲŠØą Ų…ØĒØˇŲ„Ø¨Ø§ØĒ Ø§Ų„Ø´Ø¨ŲƒØŠØŒ ؊ØĒŲ… ØĨؚاد؊ ØĒØšŲŠŲŠŲ† Ų‚Ø§ØĻŲ…ØŠ Ø§Ų†ØĒØ¸Ø§Øą Ø§Ų„Ų†ØŗØŽ Ø§Ų„Ø§Ø­ØĒŲŠØ§ØˇŲŠ", "networking_settings": "Ø§Ų„Ø´Ø¨ŲƒØ§ØĒ", "networking_subtitle": "ØĨØ¯Ø§ØąØŠ ØĨؚداداØĒ Ų†Ų‚ØˇØŠ Ø§Ų„ØŽØ§Ø¯Ų… Ø§Ų„Ų†Ų‡Ø§ØĻŲŠØŠ", @@ -1344,6 +1376,7 @@ "new_person": "Ø´ØŽØĩ ØŦØ¯ŲŠØ¯", "new_pin_code": "ØąŲ…Ø˛ PIN Ø§Ų„ØŦØ¯ŲŠØ¯", "new_pin_code_subtitle": "Ų‡Ø°Ų‡ ØŖŲˆŲ„ Ų…ØąØŠ ØĒØ¯ØŽŲ„ ŲŲŠŲ‡Ø§ ØĨŲ„Ų‰ Ø§Ų„Ų…ØŦŲ„Ø¯ Ø§Ų„Ų…Ų‚ŲŲ„. ØŖŲ†Ø´ØĻ ØąŲ…Ø˛Ų‹Ø§ PIN Ų„Ų„ŲˆØĩŲˆŲ„ Ø¨Ø§Ų…Ø§Ų† ØĨŲ„Ų‰ Ų‡Ø°Ų‡ Ø§Ų„ØĩŲØ­ØŠ", + "new_timeline": "Ø§Ų„ØŽØˇ Ø§Ų„Ø˛Ų…Ų†ŲŠ Ø§Ų„ØŦØ¯ŲŠØ¯", "new_user_created": "ØĒŲ… ØĨŲ†Ø´Ø§ØĄ Ų…ØŗØĒØŽØ¯Ų… ØŦØ¯ŲŠØ¯", "new_version_available": "ØĨØĩØ¯Ø§Øą ØŦØ¯ŲŠØ¯ Ų…ØĒاح", "newest_first": "Ø§Ų„ØŖØ­Ø¯ØĢ ØŖŲˆŲ„Ø§Ų‹", @@ -1357,20 +1390,25 @@ "no_assets_message": "Ø§Ų†Ų‚Øą Ų„ØĒØ­Ų…ŲŠŲ„ ØĩŲˆØąØĒ؃ Ø§Ų„ØŖŲˆŲ„Ų‰", "no_assets_to_show": "Ų„Ø§ ØĒ؈ØŦد ØŖØĩŲˆŲ„ Ų„ØšØąØļŲ‡Ø§", "no_cast_devices_found": "Ų„Ų… ؊ØĒŲ… Ø§ŲŠØŦاد ØŦŲ‡Ø§Ø˛ بØĢ", + "no_checksum_local": "Ų„Ø§ ØĒ؈ØŦد Ø¨ŲŠØ§Ų†Ø§ØĒ ØĒØ­Ų‚Ų‚ Ų…ØĒاح؊ - ؊ØĒØšØ°Øą ØĒØ­Ų…ŲŠŲ„ Ø§Ų„Ø§ØĩŲˆŲ„ Ø§Ų„Ų…Ø­Ų„ŲŠØŠ", + "no_checksum_remote": "Ų„Ø§ ؊؈ØŦد ØąŲ…Ø˛ ØĒØ­Ų‚Ų‚ Ų…ØĒاح - ؊ØĒØšØ°Øą ØĒØ­Ų…ŲŠŲ„ Ø§Ų„Ø§ØĩŲ„ Ų…Ų† Ø§Ų„Ų…ŲˆŲ‚Øš Ø§Ų„Ø¨ØšŲŠØ¯", "no_duplicates_found": "Ų„Ų… ؊ØĒŲ… Ø§Ų„ØšØĢŲˆØą ØšŲ„Ų‰ ØŖŲŠ ØĒŲƒØąØ§ØąØ§ØĒ.", "no_exif_info_available": "Ų„Ø§ ØĒØĒŲˆŲØą Ų…ØšŲ„ŲˆŲ…Ø§ØĒ exif", "no_explore_results_message": "Ų‚Ų… Ø¨ØąŲØš Ø§Ų„Ų…Ø˛ŲŠØ¯ Ų…Ų† Ø§Ų„ØĩŲˆØą Ų„Ø§ØŗØĒŲƒØ´Ø§Ų Ų…ØŦŲ…ŲˆØšØĒ؃.", "no_favorites_message": "ØŖØļ؁ Ø§Ų„Ų…ŲØļŲ„ØŠ Ų„Ų„ØšØĢŲˆØą Ø¨ØŗØąØšØŠ ØšŲ„Ų‰ ØŖŲØļŲ„ Ø§Ų„ØĩŲˆØą ŲˆŲ…Ų‚Ø§ØˇØš Ø§Ų„ŲŲŠØ¯ŲŠŲˆ", "no_libraries_message": "ØĨŲ†Ø´Ø§ØĄ Ų…ŲƒØĒب؊ ØŽØ§ØąØŦŲŠØŠ Ų„ØšØąØļ Ø§Ų„ØĩŲˆØą ŲˆŲ…Ų‚Ø§ØˇØš Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ø§Ų„ØŽØ§ØĩØŠ Ø¨Ųƒ", + "no_local_assets_found": "Ų„Ų… ؊ØĒŲ… Ø§Ų„ØšØĢŲˆØą ØšŲ„Ų‰ ØŖŲŠ اØĩŲˆŲ„ Ų…Ø­Ų„ŲŠØŠ ØĒØĒØˇØ§Ø¨Ų‚ Ų…Øš Ų‚ŲŠŲ…ØŠ Ø§Ų„ØĒØ­Ų‚Ų‚ Ų‡Ø°Ų‡", "no_locked_photos_message": "Ø§Ų„ØĩŲˆØą ŲˆØ§Ų„ŲØ¯ŲŠŲˆŲ‡Ø§ØĒ ؁؊ Ø§Ų„Ų…ØŦŲ„Ø¯ Ø§Ų„Ų…Ų‚ŲŲ„ Ų…ØŽŲŲŠØŠ ŲˆŲ„Ų† ØĒØĩŲ‡Øą ؁؊ Ø§Ų„ØĒØĩŲØ­ Ø§Ųˆ Ø§Ų„Ø¨Ø­ØĢ ؁؊ Ų…ŲƒØĒبØĒ؃.", "no_name": "Ų„Ø§ Ø§ØŗŲ…", "no_notifications": "Ų„Ø§ ØĒ؈ØŦد ØĒŲ†Ø¨ŲŠŲ‡Ø§ØĒ", "no_people_found": "Ų„Ų… ؊ØĒŲ… Ø§Ų„ØšØĢŲˆØą ØšŲ„Ų‰ اش؎اØĩ Ų…ØˇØ§Ø¨Ų‚ŲŠŲ†", "no_places": "Ų„Ø§ ØŖŲ…Ø§ŲƒŲ†", + "no_remote_assets_found": "Ų„Ų… ؊ØĒŲ… Ø§Ų„ØšØĢŲˆØą ØšŲ„Ų‰ ØŖŲŠ اØĩŲˆŲ„ Ø¨ØšŲŠØ¯ØŠ ØĒØĒØˇØ§Ø¨Ų‚ Ų…Øš ØąŲ…Ø˛ Ø§Ų„ØĒØ­Ų‚Ų‚ Ų‡Ø°Ų„", "no_results": "Ų„Ø§ ؊؈ØŦد Ų†ØĒاØĻØŦ", "no_results_description": "ØŦØąØ¨ ŲƒŲ„Ų…ØŠ ØąØĻŲŠØŗŲŠØŠ Ų…ØąØ§Ø¯ŲØŠ ØŖŲˆ ØŖŲƒØĢØą ØšŲ…ŲˆŲ…ŲŠØŠ", "no_shared_albums_message": "Ų‚Ų… بØĨŲ†Ø´Ø§ØĄ ØŖŲ„Ø¨ŲˆŲ… Ų„Ų…Ø´Ø§ØąŲƒØŠ Ø§Ų„ØĩŲˆØą ŲˆŲ…Ų‚Ø§ØˇØš Ø§Ų„ŲŲŠØ¯ŲŠŲˆ Ų…Øš Ø§Ų„ØŖØ´ØŽØ§Øĩ ؁؊ Ø´Ø¨ŲƒØĒ؃", "no_uploads_in_progress": "Ų„Ø§ ؊؈ØŦد Ø§ŲŠ Ų…Ų„ŲØ§ØĒ Ų‚ŲŠØ¯ Ø§Ų„ØąŲØš", + "not_available": "ØēŲŠØą Ų…ØĒاح", "not_in_any_album": "Ų„ŲŠØŗØĒ ؁؊ ØŖŲŠ ØŖŲ„Ø¨ŲˆŲ…", "not_selected": "Ų„Ų… ŲŠØŽØĒØ§Øą", "note_apply_storage_label_to_previously_uploaded assets": "Ų…Ų„Ø§Ø­Ø¸ØŠ: Ų„ØĒØˇØ¨ŲŠŲ‚ ØŗŲ…ØŠ Ø§Ų„ØĒØŽØ˛ŲŠŲ† ØšŲ„Ų‰ Ø§Ų„Ų…Ø­ØĒŲˆŲŠØ§ØĒ Ø§Ų„ØĒ؊ ØĒŲ… ØąŲØšŲ‡Ø§ Ų…ØŗØ¨Ų‚Ų‹Ø§ØŒ Ų‚Ų… بØĒØ´ØēŲŠŲ„", @@ -1405,6 +1443,8 @@ "open_the_search_filters": "Ø§ŲØĒØ­ Ų…ØąØ´Ø­Ø§ØĒ Ø§Ų„Ø¨Ø­ØĢ", "options": "ØŽŲŠØ§ØąØ§ØĒ", "or": "ØŖŲˆ", + "organize_into_albums": "ØĒØąØĒŲŠØ¨ ؁؊ ØŖŲ„Ø¨ŲˆŲ…Ø§ØĒ", + "organize_into_albums_description": "ØŖØļ؁ Ø§Ų„ØĩŲˆØą Ø§Ų„Ų…ŲˆØŦŲˆØ¯ØŠ ØĨŲ„Ų‰ Ø§Ų„ØŖŲ„Ø¨ŲˆŲ…Ø§ØĒ Ø¨Ø§ØŗØĒØŽØ¯Ø§Ų… ØĨؚداداØĒ Ø§Ų„Ų†ØŗØŽ Ø§Ų„Ų…ØĒØ˛Ø§Ų…Ų† Ø§Ų„Ø­Ø§Ų„ŲŠØŠ", "organize_your_library": "ØĒŲ†Ø¸ŲŠŲ… Ų…ŲƒØĒبØĒ؃", "original": "ØŖØĩŲ„ŲŠ", "other": "ØŖØŽØąŲ‰", @@ -1490,6 +1530,7 @@ "port": "Ø§Ų„Ų…Ų†ŲØ°", "preferences_settings_subtitle": "Ø§Ø¯Ø§ØąØŠ ØĒ؁ØļŲŠŲ„Ø§ØĒ Ø§Ų„ØĒØˇØ¨ŲŠŲ‚", "preferences_settings_title": "Ø§Ų„ØĒ؁ØļŲŠŲ„Ø§ØĒ", + "preparing": "Ų‚ŲŠØ¯ Ø§Ų„ØĒØ­ØļŲŠØą", "preset": "Ø§Ų„ØĨؚداد Ø§Ų„Ų…ØŗØ¨Ų‚", "preview": "Ų…ØšØ§ŲŠŲ†ØŠ", "previous": "Ø§Ų„ØŗØ§Ø¨Ų‚", @@ -1506,6 +1547,7 @@ "profile_drawer_client_out_of_date_minor": "ØĒØˇØ¨ŲŠŲ‚ Ø§Ų„Ų‡Ø§ØĒ؁ Ø§Ų„Ų…Ø­Ų…ŲˆŲ„ Ų‚Ø¯ŲŠŲ….ŲŠØąØŦŲ‰ Ø§Ų„ØĒØ­Ø¯ŲŠØĢ ØĨŲ„Ų‰ ØŖØ­Ø¯ØĢ ØĨØĩØ¯Ø§Øą ØĩØēŲŠØą.", "profile_drawer_client_server_up_to_date": "Ø§Ų„ØšŲ…ŲŠŲ„ ŲˆØ§Ų„ØŽØ§Ø¯Ų… Ų…Ø­Ø¯ØĢØ§Ų†", "profile_drawer_github": "Github", + "profile_drawer_readonly_mode": "ØĒŲ… ØĒŲØšŲŠŲ„ ؈ØļØš Ø§Ų„Ų‚ØąØ§ØĄØŠ ŲŲ‚Øˇ. اØļØēØˇ Ų…ØˇŲˆŲ„Ø§ ØšŲ„Ų‰ ØąŲ…Ø˛ ØĩŲˆØąØŠ Ø§Ų„Ų…ØŗØĒØŽØ¯Ų… Ų„Ų„ØŽØąŲˆØŦ.", "profile_drawer_server_out_of_date_major": "Ø§Ų„ØŽØ§Ø¯Ų… Ų‚Ø¯ŲŠŲ….ŲŠØąØŦŲ‰ Ø§Ų„ØĒØ­Ø¯ŲŠØĢ ØĨŲ„Ų‰ ØŖØ­Ø¯ØĢ ØĨØĩØ¯Ø§Øą ØąØĻŲŠØŗŲŠ.", "profile_drawer_server_out_of_date_minor": "Ø§Ų„ØŽØ§Ø¯Ų… Ų‚Ø¯ŲŠŲ….ŲŠØąØŦŲ‰ Ø§Ų„ØĒØ­Ø¯ŲŠØĢ ØĨŲ„Ų‰ ØŖØ­Ø¯ØĢ ØĨØĩØ¯Ø§Øą ØĩØēŲŠØą.", "profile_image_of_user": "ØĩŲˆØąØŠ Ø§Ų„Ų…Ų„Ų Ø§Ų„Ø´ØŽØĩ؊ Ų„Ų€ {user}", @@ -1544,6 +1586,7 @@ "purchase_server_description_2": "Ø­Ø§Ų„ØŠ Ø§Ų„Ø¯Ø§ØšŲ…", "purchase_server_title": "Ø§Ų„ØŽØ§Ø¯Ų…", "purchase_settings_server_activated": "؊ØĒŲ… ØĨØ¯Ø§ØąØŠ ؅؁ØĒاح Ų…Ų†ØĒØŦ Ø§Ų„ØŽØ§Ø¯Ų… Ų…Ų† Ų‚Ø¨Ų„ Ų…Ø¯ŲŠØą Ø§Ų„Ų†Ø¸Ø§Ų…", + "query_asset_id": "Ø§ØŗØĒØšŲ„Ø§Ų… ØšŲ† Ų…ØšØąŲ Ø§Ų„ØŖØĩŲ„", "queue_status": "؊ØĒŲ… Ø§Ų„Ø§ØļØ§ŲØŠ Ø§Ų„Ų‰ Ų‚Ø§ØĻŲ…ØŠ Ø§Ų†ØĒØ¸Ø§Øą Ø§Ų„Ų†ØŗØŽ Ø§Ų„Ø§Ø­ØĒŲŠØ§ØˇŲŠ {count}/{total}", "rating": "ØĒŲ‚ŲŠŲŠŲ… Ų†ØŦŲ…ŲŠ", "rating_clear": "Ų…ØŗØ­ Ø§Ų„ØĒŲ‚ŲŠŲŠŲ…", @@ -1551,6 +1594,9 @@ "rating_description": "â€Ģâ€ŒØ§ØšØąØļ ØĒŲ‚ŲŠŲŠŲ… EXIF ؁؊ Ų„ŲˆØ­ØŠ Ø§Ų„Ų…ØšŲ„ŲˆŲ…Ø§ØĒ", "reaction_options": "ØŽŲŠØ§ØąØ§ØĒ ØąØ¯ Ø§Ų„ŲØšŲ„", "read_changelog": "Ų‚ØąØ§ØĄØŠ ØŗØŦŲ„ Ø§Ų„ØĒØēŲŠŲŠØą", + "readonly_mode_disabled": "ØĒŲ… ØĒØšØˇŲŠŲ„ ؈ØļØš Ø§Ų„Ų‚ØąØ§ØĄØŠ ŲŲ‚Øˇ", + "readonly_mode_enabled": "ØĒŲ… ØĒŲØšŲŠŲ„ ؈ØļØš Ø§Ų„Ų‚ØąØ§ØĄØŠ ŲŲ‚Øˇ", + "ready_for_upload": "ØŦØ§Ų‡Ø˛ Ų„Ų„ØąŲØš", "reassign": "ØĨؚاد؊ Ø§Ų„ØĒØšŲŠŲŠŲ†", "reassigned_assets_to_existing_person": "ØĒŲ…ØĒ ØĨؚاد؊ ØĒØšŲŠŲŠŲ† {count, plural, one {# Ø§Ų„ØŖØĩŲ„} other {# Ø§Ų„Ø§ØĩŲˆŲ„}} ØĨŲ„Ų‰ {name, select, null {Ø´ØŽØĩ Ų…ŲˆØŦŲˆØ¯ } other {{name}}}", "reassigned_assets_to_new_person": "ØĒŲ…ØĒ ØĨؚاد؊ ØĒØšŲŠŲŠŲ† {count, plural, one {# Ø§Ų„Ų…Ø­ØĒŲˆŲ‰} other {# Ø§Ų„Ų…Ø­ØĒŲˆŲŠØ§ØĒ}} ØĨŲ„Ų‰ Ø´ØŽØĩ ØŦØ¯ŲŠØ¯", @@ -1575,6 +1621,7 @@ "regenerating_thumbnails": "ØŦØ§ØąŲ ØĒØŦØ¯ŲŠØ¯ Ø§Ų„ØĩŲˆØą Ø§Ų„Ų…ØĩØēØąØŠ", "remote": "Ø¨ØšŲŠØ¯", "remote_assets": "Ø§Ų„ØŖŲØĩŲˆŲ„ Ø§Ų„Ø¨ØšŲŠØ¯ØŠ", + "remote_media_summary": "Ų…Ų„ØŽØĩ Ø§Ų„Ų…Ų„ŲØ§ØĒ Ø§Ų„Ø¨ØšŲŠØ¯ØŠ", "remove": "ØĨØ˛Ø§Ų„ØŠ", "remove_assets_album_confirmation": "Ų‡Ų„ ØŖŲ†ØĒ Ų…ØĒØŖŲƒØ¯ ØŖŲ†Ųƒ ØĒØąŲŠØ¯ ØĨØ˛Ø§Ų„ØŠ {count, plural, one {# Ø§Ų„Ų…Ø­ØĒŲˆŲ‰} other {# Ø§Ų„Ų…Ø­ØĒŲˆŲŠØ§ØĒ}} Ų…Ų† Ø§Ų„ØŖŲ„Ø¨ŲˆŲ… ؟", "remove_assets_shared_link_confirmation": "Ų‡Ų„ ØŖŲ†ØĒ Ų…ØĒØŖŲƒØ¯ ØŖŲ†Ųƒ ØĒØąŲŠØ¯ ØĨØ˛Ø§Ų„ØŠ {count, plural, one {# Ø§Ų„Ų…Ø­ØĒŲˆŲ‰} other {# Ø§Ų„Ų…Ø­ØĒŲˆŲŠØ§ØĒ}} Ų…Ų† ØąØ§Ø¨Øˇ Ø§Ų„Ų…Ø´Ø§ØąŲƒØŠ Ų‡Ø°Ø§ØŸ", @@ -1627,6 +1674,7 @@ "restore_user": "Ø§ØŗØĒؚاد؊ Ø§Ų„Ų…ØŗØĒØŽØ¯Ų…", "restored_asset": "Ø§Ų„Ų…Ø­ØĒŲˆŲŠØ§ØĒ Ø§Ų„Ų…ØŗØĒؚاد؊", "resume": "Ø§ØŗØĒØĻŲ†Ø§Ų", + "resume_paused_jobs": "Ø§ØŗØĒŲƒŲ…Ø§Ų„ {count, plural, one {# ŲˆØ¸ŲŠŲØŠ Ų…ØšŲ„Ų‚ØŠ} other {# ŲˆØ¸Ø§ØĻ؁ Ų…ØšŲ„Ų‚ØŠ}}", "retry_upload": "ØŖØšØ¯ Ų…Ø­Ø§ŲˆŲ„ØŠ Ø§Ų„ØąŲØš", "review_duplicates": "Ų…ØąØ§ØŦؚ؊ Ø§Ų„ØĒŲƒØąØ§ØąØ§ØĒ", "review_large_files": "Ų…ØąØ§ØŦؚ؊ Ø§Ų„Ų…Ų„ŲØ§ØĒ Ø§Ų„ŲƒØ¨ŲŠØąØŠ", @@ -1720,6 +1768,7 @@ "select_user_for_sharing_page_err_album": "ŲØ´Ų„ ؁؊ ØĨŲ†Ø´Ø§ØĄ ØŖŲ„Ø¨ŲˆŲ…", "selected": "Ø§Ų„ØĒØ­Ø¯ŲŠØ¯", "selected_count": "{count, plural, other {# Ų…Ø­Ø¯Ø¯ØŠ }}", + "selected_gps_coordinates": "ØĨحداØĢŲŠØ§ØĒ Ų†Ø¸Ø§Ų… ØĒØ­Ø¯ŲŠØ¯ Ø§Ų„Ų…ŲˆØ§Ų‚Øš Ø§Ų„Ų…ØŽØĒØ§ØąØŠ", "send_message": "‏ØĨØąØŗØ§Ų„ ØąØŗØ§Ų„ØŠ", "send_welcome_email": "ØĨØąØŗØ§Ų„ Ø¨ØąŲŠØ¯Ų‹Ø§ ØĨŲ„ŲƒØĒØąŲˆŲ†ŲŠŲ‹Ø§ ØĒØąØ­ŲŠØ¨ŲŠŲ‹Ø§", "server_endpoint": "Ų†Ų‚ØˇØŠ Ų†Ų‡Ø§ŲŠØŠ Ø§Ų„ØŽØ§Ø¯Ų…", @@ -1848,6 +1897,7 @@ "show_slideshow_transition": "ØĨØ¸Ų‡Ø§Øą Ø§Ų†ØĒŲ‚Ø§Ų„ ØšØąØļ Ø§Ų„Ø´ØąØ§ØĻØ­", "show_supporter_badge": "Ø´Ø§ØąØŠ Ø§Ų„Ų…Ø¤ŲŠØ¯", "show_supporter_badge_description": "ØĨØ¸Ų‡Ø§Øą Ø´Ø§ØąØŠ Ø§Ų„Ų…Ø¤ŲŠØ¯", + "show_text_search_menu": "ØšØąØļ Ų‚Ø§ØĻŲ…ØŠ ØŽŲŠØ§ØąØ§ØĒ Ø§Ų„Ø¨Ø­ØĢ ؁؊ Ø§Ų„Ų†Øĩ", "shuffle": "ØŽŲ„Øˇ", "sidebar": "Ø§Ų„Ø´ØąŲŠØˇ Ø§Ų„ØŦØ§Ų†Ø¨ŲŠ", "sidebar_display_description": "ØšØąØļ ØąØ§Ø¨Øˇ Ų„Ų„ØšØąØļ ؁؊ Ø§Ų„Ø´ØąŲŠØˇ Ø§Ų„ØŦØ§Ų†Ø¨ŲŠ", @@ -1878,6 +1928,7 @@ "stacktrace": "ØĒØĒŲ‘Ø¨ŲØš Ø§Ų„ØĒŲƒØ¯ŲŠØŗ", "start": "Ø§Ø¨Ø¯ØŖ", "start_date": "ØĒØ§ØąŲŠØŽ Ø§Ų„Ø¨Ø¯ØĄ", + "start_date_before_end_date": "؊ØŦب ØŖŲ† ŲŠŲƒŲˆŲ† ØĒØ§ØąŲŠØŽ Ø¨Ø¯ØĄ Ø§Ų„ŲØĒØąØŠ Ų‚Ø¨Ų„ ØĒØ§ØąŲŠØŽ Ų†Ų‡Ø§ŲŠØĒŲ‡Ø§", "state": "Ø§Ų„ŲˆŲ„Ø§ŲŠØŠ", "status": "Ø§Ų„Ø­Ø§Ų„ØŠ", "stop_casting": "Ø§ŲŠŲ‚Ø§Ų Ø§Ų„Ø¨ØĢ", @@ -1902,6 +1953,8 @@ "sync_albums_manual_subtitle": "Ų…Ø˛Ø§Ų…Ų†ØŠ ØŦŲ…ŲŠØš Ø§Ų„ŲØ¯ŲŠŲˆŲ‡Ø§ØĒ ŲˆØ§Ų„ØĩŲˆØą Ø§Ų„Ų…ØąŲŲˆØšØŠ Ø§Ų„Ų‰ Ø§Ų„Ø¨ŲˆŲ…Ø§ØĒ Ø§Ų„ØŽØ˛Ų† Ø§Ų„Ø§Ø­ØĒŲŠØ§ØˇŲŠ Ø§Ų„Ų…ØŽØĒØ§ØąØŠ", "sync_local": "Ų…Ø˛Ø§Ų…Ų†ØŠ Ø§Ų„Ų…Ų„ŲØ§ØĒ Ø§Ų„Ų…Ø­Ų„ŲŠØŠ", "sync_remote": "Ų…Ø˛Ø§Ų…Ų†ØŠ Ø§Ų„Ų…Ų„ŲØ§ØĒ Ø§Ų„Ø¨ØšŲŠØ¯ØŠ", + "sync_status": "Ø­Ø§Ų„ØŠ Ø§Ų„Ų†ØŗØŽ Ø§Ų„Ų…ØĒØ˛Ø§Ų…Ų†", + "sync_status_subtitle": "ØšØąØļ ؈ØĨØ¯Ø§ØąØŠ Ų†Ø¸Ø§Ų… Ø§Ų„Ų†ØŗØŽ Ø§Ų„Ų…ØĒØ˛Ø§Ų…Ų†", "sync_upload_album_setting_subtitle": "Ø§Ų†Ø´ØĻ ؈ Ø§ØąŲØš ØĩŲˆØąŲƒ ؈ ŲØ¯ŲŠŲˆŲ‡Ø§ØĒ؃ Ø§Ų„Ø§Ų„Ø¨ŲˆŲ…Ø§ØĒ Ø§Ų„Ų…ØŽØĒØ§ØąØŠ ؁؊ Immich", "tag": "Ø§Ų„ØšŲ„Ø§Ų…ØŠ", "tag_assets": "ØŖØĩŲˆŲ„ Ø§Ų„ØšŲ„Ø§Ų…ØŠ", @@ -1939,7 +1992,9 @@ "to_change_password": "ØĒØēŲŠŲŠØą ŲƒŲ„Ų…ØŠ Ø§Ų„Ų…ØąŲˆØą", "to_favorite": "ØĒ؁ØļŲŠŲ„", "to_login": "ØĒØŗØŦŲŠŲ„ Ø§Ų„Ø¯ØŽŲˆŲ„", + "to_multi_select": "Ų„Ų„ØĒØ­Ø¯ŲŠØ¯ Ø§Ų„Ų…ØĒؚدد", "to_parent": "Ø§Ų†ØĒŲ‚Ų„ ØĨŲ„Ų‰ Ø§Ų„ŲˆØ§Ų„Ø¯", + "to_select": "Ų„Ų„ØĒØ­Ø¯ŲŠØ¯", "to_trash": "Ø­Ø°Ų", "toggle_settings": "Ø§Ų„ØĨؚداداØĒ", "total": "Ø§Ų„ØĨØŦŲ…Ø§Ų„ŲŠ", @@ -1959,6 +2014,7 @@ "trash_page_select_assets_btn": "ا؎ØĒØą Ø§Ų„ØŖØĩŲˆŲ„", "trash_page_title": "ØŗŲ„ØŠ Ø§Ų„Ų…Ų‡Ų…Ų„Ø§ØĒ ({count})", "trashed_items_will_be_permanently_deleted_after": "ØŗŲŠØĒŲ… Ø­Ø°ŲŲ Ø§Ų„ØšŲ†Ø§ØĩØą Ø§Ų„Ų…Ø­Ø°ŲˆŲØŠ Ų†ŲŲ‡Ø§ØĻŲŠŲ‹Ø§ بؚد {days, plural, one {# ŲŠŲˆŲ…} other {# ØŖŲŠØ§Ų… }}.", + "troubleshoot": "Ø§ØŗØĒŲƒØ´Ø§Ų Ø§Ų„Ų…Ø´Ø§ŲƒŲ„", "type": "Ø§Ų„Ų†ŲˆØš", "unable_to_change_pin_code": "ØĒŲŲŠŲŠØą ØąŲ…Ø˛ PIN ØēŲŠØą Ų…Ų…ŲƒŲ†", "unable_to_setup_pin_code": "Ø§Ų†Ø´Ø§ØĄ ØąŲ…Ø˛ PIN ØēŲŠØą Ų…Ų…ŲƒŲ†", @@ -1989,6 +2045,7 @@ "unstacked_assets_count": "ØĒŲ… ØĨØŽØąØ§ØŦ {count, plural, one {# Ø§Ų„ØŖØĩŲ„} other {# Ø§Ų„ØŖØĩŲˆŲ„}} Ų…Ų† Ø§Ų„ØĒŲƒØ¯ŲŠØŗ", "untagged": "ØēŲŠØą Ų…ŲØšŲŽŲ„ŲŽŲ‘Ų…", "up_next": "Ø§Ų„ØĒØ§Ų„ŲŠ", + "update_location_action_prompt": "ØĒØ­Ø¯ŲŠØĢ Ų…ŲˆŲ‚Øš {count} ØšŲ†Ø§ØĩØą Ų…Ø­Ø¯Ø¯ØŠ ØšŲ„Ų‰ Ø§Ų„Ų†Ø­Ųˆ Ø§Ų„ØĒØ§Ų„ŲŠ:", "updated_at": "ØĒŲ… Ø§Ų„ØĒØ­Ø¯ŲŠØĢ", "updated_password": "ØĒŲ… ØĒØ­Ø¯ŲŠØĢ ŲƒŲ„Ų…ØŠ Ø§Ų„Ų…ØąŲˆØą", "upload": "ØąŲØš", @@ -2055,6 +2112,7 @@ "view_next_asset": "ØšØąØļ Ø§Ų„Ų…Ø­ØĒŲˆŲ‰ Ø§Ų„ØĒØ§Ų„ŲŠ", "view_previous_asset": "ØšØąØļ Ø§Ų„Ų…Ø­ØĒŲˆŲ‰ Ø§Ų„ØŗØ§Ø¨Ų‚", "view_qr_code": "Â­ØšØąØļ ØąŲ…Ø˛ Ø§Ų„Ø§ØŗØĒØŦاب؊ Ø§Ų„ØŗØąŲŠØšØŠ", + "view_similar_photos": "ØšØąØļ ØĩŲˆØą Ų…Ø´Ø§Ø¨Ų‡ØŠ", "view_stack": "ØšØąØļ Ø§Ų„ØĒŲƒØ¯ŲŠØŗ", "view_user": "ØšØąØļ Ø§Ų„Ų…ØŗØĒØŽØ¯Ų…", "viewer_remove_from_stack": "Ø­Ø°Ų Ų…Ų† Ø§Ų„ŲƒŲˆŲ…Ų‡ ØŖŲˆ Ø§Ų„Ų…ØŦŲ…ŲˆØšØŠ", @@ -2073,5 +2131,6 @@ "yes": "Ų†ØšŲ…", "you_dont_have_any_shared_links": "Ų„ŲŠØŗ Ų„Ø¯ŲŠŲƒ ØŖŲŠ ØąŲˆØ§Ø¨Øˇ Ų…Ø´ØĒØąŲƒØŠ", "your_wifi_name": "Ø§ØŗŲ… Ø´Ø¨ŲƒØŠ Wi-Fi Ø§Ų„ØŽØ§Øĩ Ø¨Ųƒ", - "zoom_image": "ØĒŲƒØ¨ŲŠØą Ø§Ų„ØĩŲˆØąØŠ" + "zoom_image": "ØĒŲƒØ¨ŲŠØą Ø§Ų„ØĩŲˆØąØŠ", + "zoom_to_bounds": "ØĒŲƒØ¨ŲŠØą Ø­ØĒŲ‰ Ø­Ø¯ŲˆØ¯ Ø§Ų„Ų…Ų†ØˇŲ‚ØŠ" } diff --git a/i18n/az.json b/i18n/az.json index 0449289735..53e7f55db6 100644 --- a/i18n/az.json +++ b/i18n/az.json @@ -1,7 +1,7 @@ { "about": "HaqqÄąnda", "account": "Hesab", - "account_settings": "Hesab parametrləri", + "account_settings": "Hesab Parametrləri", "acknowledge": "Təsdiq et", "action": "Əməliyyat", "action_common_update": "Yenilə", @@ -16,8 +16,8 @@ "add_a_title": "BaşlÄąq əlavə et", "add_birthday": "Doğum gÃŧnÃŧ əlavə et", "add_endpoint": "Son nÃļqtə əlavə et", - "add_exclusion_pattern": "İstisna nÃŧmunəsi əlavə et", - "add_import_path": "Import yolunu əlavə et", + "add_exclusion_pattern": "Ã‡Äąxarma nÃŧmunəsi əlavə et", + "add_import_path": "İdxal yolu əlavə et", "add_location": "Məkan əlavə et", "add_more_users": "Daha çox istifadəçi əlavə et", "add_partner": "Partnyor əlavə et", @@ -25,20 +25,21 @@ "add_photos": "Şəkillər əlavə et", "add_tag": "Etiket əlavə et", "add_to": "Bura əlavə etâ€Ļ", - "add_to_album": "Albom əlavə et", + "add_to_album": "Alboma əlavə et", "add_to_album_bottom_sheet_added": "{album} albomuna əlavə edildi", "add_to_album_bottom_sheet_already_exists": "ArtÄąq {album} albomunda var", + "add_to_album_bottom_sheet_some_local_assets": "Bəzi lokal resurslar alboma əlavə edilə bilmədi", "add_to_album_toggle": "{album} ÃŧçÃŧn seçimi dəyişin", "add_to_albums": "Albomlara əlavə et", - "add_to_albums_count": "Albomlara əlavə et ({count})", + "add_to_albums_count": "({count}) albomlarÄąna əlavə et", "add_to_shared_album": "PaylaÅŸÄąlan alboma əlavə et", "add_url": "URL əlavə et", "added_to_archive": "Arxivə əlavə edildi", "added_to_favorites": "Sevimlilələrə əlavə edildi", "added_to_favorites_count": "{count, number} şəkil sevimlilələrə əlavə edildi", "admin": { - "add_exclusion_pattern_description": "İstisna şablonlarÄąnÄą əlavə edin. *, ** və ? ilə Globbing dəstəklənir. Məs.: \"Raw\" adlanan hər hansÄąsa bir qovluqda bÃŧtÃŧn fayllarÄą saymamaq ÃŧçÃŧn \"**/Raw/**\"-dan istifadə edin. \".tif\" ilə bitən bÃŧtÃŧn fayllarÄą saymamaq ÃŧçÃŧn \"**/*.tif\"-dən istifadə edin. FaylÄą mÃŧtləq yoldan istifadə etməklə saymamaq istəyirsinizsə \"/path/to/ignore/**\"-dan istifadə edin.", - "admin_user": "Admin İstifadəçi", + "add_exclusion_pattern_description": "Ã‡Äąxarma nÃŧmunələri əlavə et. *, ** və ? istifadə edilərək globbing dəstəklənir. Hər hansÄą bir \"Raw\" adlÄą qovluqdakÄą bÃŧtÃŧn fayllarÄą gÃļrməməzlikdən gəlmək ÃŧçÃŧn **/Raw/** istifadə et. “.tif” ilə bitən bÃŧtÃŧn fayllarÄą gÃļrməməzlikdən gəlmək ÃŧçÃŧn **/*.tif istifadə et. Tam yolu gÃļrməməzlikdən gəlmək ÃŧçÃŧn /path/to/ignore/** istifadə et.", + "admin_user": "İdarəçi İstifadəçi", "asset_offline_description": "Bu xarici kitabxana varlığı diskdə artÄąq tapÄąlmadÄą və zibil qutusuna kÃļçÃŧrÃŧldÃŧ. Əgər fayl kitabxana içərisində kÃļçÃŧrÃŧlÃŧbsə, zaman şkalanÄązÄą yeni uyğun gələn varlÄąq ÃŧçÃŧn yoxlayÄąn. Varlığı yenidən qaytarmaq ÃŧçÃŧn aşağıda verilmiş fayl yolunun Immich tərəfindən əlçatan olduğundan əmin olduqdan sonra kitabxananÄą skan edin.", "authentication_settings": "Səlahiyyətləndirmə parametrləri", "authentication_settings_description": "Şifrə, OAuth və digər səlahiyyətləndirmə parametrləri", @@ -48,8 +49,15 @@ "backup_database": "Verilənlər bazasÄąnÄąn dump-ÄąnÄą yaradÄąn", "backup_database_enable_description": "Verilənlər bazasÄąnÄąn artÄąq nÃŧsxələrini aktiv et", "backup_keep_last_amount": "TutulmasÄą gərəkən nÃŧsxələrin sayÄą", - "backup_settings": "Ehtiyat NÃŧsxə Parametrləri", + "backup_onboarding_1_description": "buludda və ya başqa fiziki yerdə saytdan kənar surət.", + "backup_onboarding_2_description": "mÃŧxtəlif cihazlarda yerli nÃŧsxələr. Bura əsas fayllar və həmin fayllarÄąn ehtiyat lokal nÃŧsxəsi daxildir.", + "backup_onboarding_3_description": "orijinal fayllar da daxil olmaqla məlumatlarÄąnÄązÄąn Ãŧmumi surətləri. Buraya 1 kənar nÃŧsxə və 2 lokal nÃŧsxə daxildir.", + "backup_onboarding_footer": "Immich-in ehtiyat nÃŧsxəsini Ã§Äąxarmaq haqqÄąnda ətraflÄą məlumat ÃŧçÃŧn sənədlərə mÃŧraciət edin.", + "backup_onboarding_parts_title": "3-2-1 ehtiyat nÃŧsxəsinə aşağıdakÄąlar daxildir:", + "backup_onboarding_title": "Ehtiyat surətlər", + "backup_settings": "BazanÄąn Dump Parametrləri", "backup_settings_description": "Verilənlər bazasÄąnÄąn ehtiyat nÃŧsxə parametrlərini idarə et", + "cleared_jobs": "{job} ÃŧçÃŧn tapÅŸÄąrÄąqlar silindi", "config_set_by_file": "Konfiqurasiya hal-hazÄąrda konfiqurasiya faylÄą ilə təyin olunub", "confirm_delete_library": "{library} kitabxanasÄąnÄą silmək istədiyinizdən əminmisiniz?", "confirm_email_below": "Təsdiqləmək ÃŧçÃŧn aşağıya {email} yazÄąn", @@ -69,7 +77,7 @@ "image_thumbnail_title": "Önizləmə parametrləri", "job_concurrency": "{job}paralellik", "job_created": "TapÅŸÄąrÄąq yaradÄąldÄą", - "job_not_concurrency_safe": "Bu tapÅŸÄąrÄąq parallel fəaliyyət ÃŧçÃŧn uyğun deyil", + "job_not_concurrency_safe": "Bu iş eyni vaxtda icra ÃŧçÃŧn təhlÃŧkəsiz deyil.", "job_settings": "TapÅŸÄąrÄąq parametrləri", "job_settings_description": "Parallel şəkildə fəaliyyət gÃļstərən tapÅŸÄąrÄąqlarÄą idarə et", "job_status": "TapÅŸÄąrÄąq statusu", diff --git a/i18n/be.json b/i18n/be.json index 0ee0eb9806..98c02cae53 100644 --- a/i18n/be.json +++ b/i18n/be.json @@ -28,6 +28,10 @@ "add_to_album": "Đ”Đ°Đ´Đ°Ņ†ŅŒ ҃ аĐģŅŒĐąĐžĐŧ", "add_to_album_bottom_sheet_added": "ДададзĐĩĐŊа да {album}", "add_to_album_bottom_sheet_already_exists": "ĐŖĐļĐž СĐŊĐ°Ņ…ĐžĐ´ĐˇŅ–Ņ†Ņ†Đ° Ņž {album}", + "add_to_album_bottom_sheet_some_local_assets": "НĐĩĐēĐ°Ņ‚ĐžŅ€Ņ‹Ņ ĐģаĐēаĐģҌĐŊŅ‹Ņ аĐēŅ‚Ņ‹Đ˛Ņ‹ ĐŊĐĩ ĐŧĐžĐŗŅƒŅ†ŅŒ ĐąŅ‹Ņ†ŅŒ дададСĐĩĐŊŅ‹ Ņž аĐģŅŒĐąĐžĐŧ", + "add_to_album_toggle": "ПĐĩŅ€Đ°ĐēĐģŅŽŅ‡Ņ‹Ņ†ŅŒ Đ˛Ņ‹ĐąĐ°Ņ€ Đ´ĐģŅ {album}", + "add_to_albums": "Đ”Đ°Đ´Đ°Ņ†ŅŒ ҃ аĐģŅŒĐąĐžĐŧŅ‹", + "add_to_albums_count": "Đ”Đ°Đ´Đ°Ņ†ŅŒ ҃ аĐģŅŒĐąĐžĐŧŅ‹ ({count})", "add_to_shared_album": "Đ”Đ°Đ´Đ°Ņ†ŅŒ ҃ Đ°ĐŗŅƒĐģҌĐŊŅ‹ аĐģŅŒĐąĐžĐŧ", "add_url": "Đ”Đ°Đ´Đ°Ņ†ŅŒ URL", "added_to_archive": "ДададзĐĩĐŊа Ņž Đ°Ņ€Ņ…Ņ–Ņž", @@ -47,6 +51,9 @@ "backup_keep_last_amount": "КоĐģҌĐēĐ°ŅŅ†ŅŒ ĐŋаĐŋŅŅ€ŅĐ´ĐŊŅ–Ņ… Ņ€ŅĐˇĐĩŅ€Đ˛ĐžĐ˛Ņ‹Ņ… ĐēĐžĐŋŅ–Đš Đ´ĐģŅ ĐˇĐ°Ņ…Đ°Đ˛Đ°ĐŊĐŊŅ", "backup_onboarding_1_description": "СĐŊŅŅˆĐŊŅŅ ĐēĐžĐŋŅ–Ņ Ņž вОйĐģаĐē҃ айО Ņž Ņ–ĐŊŅˆŅ‹Đŧ Ņ„Ņ–ĐˇŅ–Ņ‡ĐŊŅ‹Đŧ ĐŧĐĩҁ҆ҋ.", "backup_onboarding_2_description": "ĐģаĐēаĐģҌĐŊŅ‹Ņ ĐēĐžĐŋŅ–Ņ– ĐŊа Ņ–ĐŊŅˆŅ‹Ņ… ĐŋҀҋĐģĐ°Đ´Đ°Ņ…. Đ“ŅŅ‚Đ° ŅžĐēĐģŅŽŅ‡Đ°Đĩ Ņž ŅŅĐąĐĩ Đ°ŅĐŊĐžŅžĐŊŅ‹Ņ Ņ„Đ°ĐšĐģŅ‹ Ņ– ĐģаĐēаĐģҌĐŊŅƒŅŽ Ņ€ŅĐˇĐĩŅ€Đ˛ĐžĐ˛ŅƒŅŽ ĐēĐžĐŋŅ–ŅŽ ĐŗŅŅ‚Ņ‹Ņ… Ņ„Đ°ĐšĐģĐ°Ņž.", + "backup_onboarding_3_description": "ĐŋĐžŅžĐŊĐ°Ņ ĐēĐžĐģҌĐēĐ°ŅŅ†ŅŒ ĐēĐžĐŋŅ–Đš Đ˛Đ°ŅˆŅ‹Ņ… даĐŊĐŊҋ҅, ҃ ҂ҋĐŧ ĐģŅ–Đē҃ ĐˇŅ‹Ņ…ĐžĐ´ĐŊҋ҅ Ņ„Đ°ĐšĐģĐ°Ņž. Đ“ŅŅ‚Đ° ŅžĐēĐģŅŽŅ‡Đ°Đĩ 1 ĐŋĐ°ĐˇĐ°ŅˆŅ‚Đ°Ņ‚ĐŊŅƒŅŽ ĐēĐžĐŋŅ–ŅŽ Ņ– 2 ĐģаĐēаĐģҌĐŊŅ‹Ņ ĐēĐžĐŋŅ–Ņ–.", + "backup_onboarding_description": " ŅŅ‚Ņ€Đ°Ņ‚ŅĐŗŅ–Ņ Ņ€ŅĐˇĐĩŅ€Đ˛Đ°Đ˛Đ°ĐŊĐŊŅ 3-2-1 Ņ€ŅĐēаĐŧĐĩĐŊдаваĐŊа Đ´ĐģŅ Đ°Ņ…ĐžĐ˛Ņ‹ Đ˛Đ°ŅˆŅ‹Ņ… даĐŊĐŊҋ҅. Đ’Ņ‹ ĐŋĐ°Đ˛Ņ–ĐŊĐŊŅ‹ ĐˇĐ°Ņ…ĐžŅžĐ˛Đ°Ņ†ŅŒ ĐēĐžĐŋŅ–Ņ– Đ˛Đ°ŅˆŅ‹Ņ… ĐˇĐ°ĐŗŅ€ŅƒĐļаĐŊҋ҅ Ņ„ĐžŅ‚Đ° / Đ˛Ņ–Đ´ŅĐ° ĐŗŅŅ‚Đ°Đē Đļа Đ´ĐžĐąŅ€Đ°, ŅĐē ĐąĐ°ĐˇŅƒ даĐŊĐŊҋ҅ Immich Đ´ĐģŅ Đ˛Ņ‹Ņ‡Đ°Ņ€ĐŋаĐģҌĐŊа ĐŋĐžŅžĐŊĐ°ĐŗĐ° Ņ€ŅĐˇĐĩŅ€Đ˛ĐžĐ˛Đ°ĐŗĐ° ĐēаĐŋŅ–ŅĐ˛Đ°ĐŊĐŊŅ.", + "backup_onboarding_footer": "Каб Đ°Ņ‚Ņ€Ņ‹ĐŧĐ°Ņ†ŅŒ Đ´Đ°Đ´Đ°Ņ‚ĐēĐžĐ˛ŅƒŅŽ Ņ–ĐŊŅ„Đ°Ņ€ĐŧĐ°Ņ†Ņ‹ŅŽ ĐŋŅ€Đ° Ņ€ŅĐˇĐĩŅ€Đ˛ĐžĐ˛Đ°Đĩ ĐēаĐŋŅ–Ņ€Đ°Đ˛Đ°ĐŊĐŊĐĩ Immich, ĐˇĐ˛ŅŅ€ĐŊҖ҆ĐĩŅŅ да даĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ‹Ņ–.", "backup_onboarding_parts_title": "Đ ŅĐˇĐĩŅ€Đ˛ĐžĐ˛Đ°Ņ ĐēĐžĐŋŅ–Ņ ÂĢ3-2-1Âģ ҃ĐēĐģŅŽŅ‡Đ°Đĩ Ņž ŅŅĐąĐĩ:", "backup_onboarding_title": "Đ ŅĐˇĐĩŅ€Đ˛ĐžĐ˛Ņ‹Ņ ĐēĐžĐŋŅ–Ņ–", "backup_settings": "НаĐģĐ°Đ´Ņ‹ Ņ€ŅĐˇĐĩŅ€Đ˛ĐžĐ˛Đ°ĐŗĐ° ĐēаĐŋŅ–ŅĐ˛Đ°ĐŊĐŊŅ", @@ -89,6 +96,8 @@ "image_resolution": "Đ Đ°ĐˇĐ´ĐˇŅĐģŅĐģҌĐŊĐ°ŅŅ†ŅŒ", "image_settings": "НаĐģĐ°Đ´Ņ‹ Đ˛Ņ–Đ´Đ°Ņ€Ņ‹ŅĐ°", "image_settings_description": "ĐšŅ–Ņ€ŅƒĐšŅ†Đĩ ŅĐēĐ°ŅŅ†ŅŽ Ņ– Ņ€Đ°ĐˇĐ´ĐˇŅĐģŅĐģҌĐŊĐ°ŅŅ†ŅŽ ŅĐŗĐĩĐŊĐĩŅ€Ņ‹Ņ€Đ°Đ˛Đ°ĐŊҋ҅ Đ˛Ņ–Đ´Đ°Ņ€Ņ‹ŅĐ°Ņž", + "image_thumbnail_description": "МаĐģĐĩĐŊҌĐēĐ°Ņ ĐŧŅ–ĐŊŅ–ŅŅ†ŅŽŅ€Đ° С Đ˛Ņ‹Đ´Đ°ĐģĐĩĐŊŅ‹ĐŧŅ– ĐŧĐĩŅ‚Đ°Đ´Đ°Đ´ĐˇĐĩĐŊŅ‹ĐŧŅ–, ŅĐēĐ°Ņ Đ˛Ņ‹ĐēĐ°Ņ€Ņ‹ŅŅ‚ĐžŅžĐ˛Đ°ĐĩŅ†Ņ†Đ° ĐŋҀҋ ĐŋŅ€Đ°ĐŗĐģŅĐ´ĐˇĐĩ ĐŗŅ€ŅƒĐŋ Ņ„Đ°Ņ‚Đ°ĐŗŅ€Đ°Ņ„Ņ–Đš, Ņ‚Đ°ĐēŅ–Ņ… ŅĐē Đ°ŅĐŊĐžŅžĐŊĐ°Ņ Ņ…Ņ€ĐžĐŊŅ–Đēа", + "image_thumbnail_quality_description": "Đ¯ĐēĐ°ŅŅ†ŅŒ ĐŧŅ–ĐŊŅ–ŅŅ†ŅŽŅ€ ад 1 да 100. Đ§Ņ‹Đŧ Đ˛Ņ‹ŅˆŅĐš ŅĐēĐ°ŅŅ†ŅŒ, ҂ҋĐŧ ĐģĐĩĐŋ҈, аĐģĐĩ ĐŋҀҋ ĐŗŅŅ‚Ņ‹Đŧ ŅŅ‚Đ˛Đ°Ņ€Đ°ŅŽŅ†Ņ†Đ° Ņ„Đ°ĐšĐģŅ‹ йОĐģŅŒŅˆĐ°ĐŗĐ° ĐŋаĐŧĐĩŅ€Ņƒ Ņ– ĐŧĐžĐļа СĐŊŅ–ĐˇŅ–Ņ†Ņ†Đ° Ņ…ŅƒŅ‚ĐēĐ°ŅŅ†ŅŒ Đ˛ĐžĐ´ĐŗŅƒĐē҃ ĐŋҀҋĐēĐģадаĐŊĐŊŅ.", "image_thumbnail_title": "НаĐģĐ°Đ´Ņ‹ ĐŧŅ–ĐŊŅ–ŅŅ†ŅŽŅ€", "job_concurrency": "{job} ĐēаĐŊĐēŅƒŅ€ŅĐŊŅ‚ĐŊĐ°ŅŅ†ŅŒ", "job_created": "ЗадаĐŊĐŊĐĩ ŅŅ‚Đ˛ĐžŅ€Đ°ĐŊа", @@ -96,6 +105,8 @@ "job_settings": "НаĐģĐ°Đ´Ņ‹ СадаĐŊĐŊŅŅž", "job_settings_description": "ĐšŅ–Ņ€Đ°Đ˛Đ°Ņ†ŅŒ ĐŊаĐģадаĐŧŅ– адĐŊĐ°Ņ‡Đ°ŅĐžĐ˛Đ°ĐŗĐ° (ĐŋĐ°Ņ€Đ°ĐģĐĩĐģҌĐŊĐ°ĐŗĐ°) Đ˛Ņ‹ĐēаĐŊаĐŊĐŊŅ СадаĐŊĐŊŅ", "job_status": "ĐĄŅ‚Đ°ĐŊĐžĐ˛Ņ–ŅˆŅ‡Đ° СадаĐŊĐŊŅ", + "jobs_delayed": "{jobCount, plural, other {# адĐēĐģадСĐĩĐŊа}}", + "jobs_failed": "{jobCount, plural, other {# ĐŊĐĩ Đ˛Ņ‹ĐēаĐŊаĐģĐ°ŅŅ}}", "library_created": "ĐĄŅ‚Đ˛ĐžŅ€Đ°ĐŊа ĐąŅ–ĐąĐģŅ–ŅŅ‚ŅĐēа: {library}", "library_deleted": "Đ‘Ņ–ĐąĐģŅ–ŅŅ‚ŅĐēа Đ˛Ņ‹Đ´Đ°ĐģĐĩĐŊа", "library_scanning": "ĐĄĐēаĐŊаваĐŊĐŊĐĩ Đŋа Ņ€Đ°ŅĐēĐģадСĐĩ", @@ -152,6 +163,9 @@ "trash_settings": "НаĐģĐ°Đ´Ņ‹ ҁĐŧĐĩŅ‚ĐŊҖ҆ҋ", "trash_settings_description": "ĐšŅ–Ņ€Đ°Đ˛Đ°ĐŊĐŊĐĩ ĐŊаĐģадаĐŧŅ– ҁĐŧĐĩŅ‚ĐŊҖ҆ҋ", "user_cleanup_job": "ĐŅ‡Ņ‹ŅŅ‚Đēа ĐēĐ°Ņ€Ņ‹ŅŅ‚Đ°ĐģҌĐŊŅ–Đēа", + "user_delete_delay": "ĐŖĐģŅ–ĐēĐžĐ˛Ņ‹ СаĐŋҖҁ {user} Ņ– аĐēŅ‚Ņ‹Đ˛Ņ‹ ĐąŅƒĐ´ŅƒŅ†ŅŒ СаĐŋĐģаĐŊаваĐŊŅ‹ Đ´ĐģŅ ĐēаĐŊŅ‡Đ°Ņ‚ĐēĐžĐ˛Đ°ĐŗĐ° Đ˛Ņ‹Đ´Đ°ĐģĐĩĐŊĐŊŅ ĐŋŅ€Đ°Đˇ {delay, plural, one {# дСĐĩĐŊҌ} few {# Đ´ĐŊŅ–} many {# Đ´ĐˇŅ‘ĐŊ} other {# Đ´ĐˇŅ‘ĐŊ}}.", + "user_delete_delay_settings_description": "КоĐģҌĐēĐ°ŅŅ†ŅŒ Đ´ĐˇŅ‘ĐŊ ĐŋĐ°ŅĐģŅ Đ˛Ņ‹Đ´Đ°ĐģĐĩĐŊĐŊŅ, Đŋа СаĐēаĐŊŅ‡ŅĐŊĐŊŅ– ŅĐēŅ–Ņ… ҃ĐģŅ–ĐēĐžĐ˛Ņ‹ СаĐŋҖҁ ĐēĐ°Ņ€Ņ‹ŅŅ‚Đ°ĐģҌĐŊŅ–Đēа Ņ– ŅĐŗĐž аĐēŅ‚Ņ‹Đ˛Ņ‹ ĐąŅƒĐ´ŅƒŅ†ŅŒ Đ˛Ņ‹Đ´Đ°ĐģĐĩĐŊŅ‹Ņ ĐŊĐĩĐˇĐ˛Đ°Ņ€ĐžŅ‚ĐŊа. ЗадаĐŊĐŊĐĩ ĐŊа Đ˛Ņ‹Đ´Đ°ĐģĐĩĐŊĐŊĐĩ ĐēĐ°Ņ€Ņ‹ŅŅ‚Đ°ĐģҌĐŊŅ–Đēа СаĐŋ҃ҁĐēаĐĩŅ†Ņ†Đ° аĐŋĐžŅžĐŊĐ°Ņ‡Ņ‹ Đ´ĐģŅ ĐŋŅ€Đ°Đ˛ĐĩŅ€ĐēŅ– ĐŗĐ°Ņ‚ĐžŅžĐŊĐ°ŅŅ†Ņ– ĐēĐ°Ņ€Ņ‹ŅŅ‚Đ°ĐģҌĐŊŅ–ĐēĐ°Ņž да Đ˛Ņ‹Đ´Đ°ĐģĐĩĐŊĐŊŅ. ЗĐŧĐĩĐŊŅ‹ Ņž ĐŗŅŅ‚Ņ‹Đŧ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁҋ ĐąŅƒĐ´ŅƒŅ†ŅŒ ҃ĐģŅ–Ņ‡Đ°ĐŊŅ‹Ņ ĐŋҀҋ ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊŅ‹Đŧ Đ˛Ņ‹ĐēаĐŊаĐŊĐŊŅ–.", + "user_delete_immediately": "ĐŖĐģŅ–ĐēĐžĐ˛Ņ‹ СаĐŋҖҁ {user} Ņ– аĐēŅ‚Ņ‹Đ˛Ņ‹ ĐąŅƒĐ´ŅƒŅ†ŅŒ ĐŊĐĩадĐēĐģадĐŊа СĐŧĐĩŅˆŅ‡Đ°ĐŊŅ‹ Ņž Ņ‡Đ°Ņ€ĐŗŅƒ ĐŊа ĐēаĐŊŅ‡Đ°Ņ‚ĐēОваĐĩ Đ˛Ņ‹Đ´Đ°ĐģĐĩĐŊĐŊĐĩ.", "user_management": "ĐšŅ–Ņ€Đ°Đ˛Đ°ĐŊĐŊĐĩ ĐēĐ°Ņ€Ņ‹ŅŅ‚Đ°ĐģҌĐŊŅ–ĐēаĐŧŅ–", "user_password_has_been_reset": "ĐŸĐ°Ņ€ĐžĐģҌ ĐēĐ°Ņ€Ņ‹ŅŅ‚Đ°ĐģҌĐŊŅ–Đēа ĐąŅ‹Ņž ҁĐēŅ–ĐŊŅƒŅ‚Ņ‹:", "user_password_reset_description": "Đ—Đ°Đ´Đ°ĐšŅ†Đĩ ĐēĐ°Ņ€Ņ‹ŅŅ‚Đ°ĐģҌĐŊŅ–Đē҃ Ņ‡Đ°ŅĐžĐ˛Ņ‹ ĐŋĐ°Ņ€ĐžĐģҌ Ņ– ĐŋавĐĩдаĐŧҖ҆Đĩ ŅĐŧ҃, ŅˆŅ‚Đž ĐŋҀҋ ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊŅ‹Đŧ ŅƒĐ˛Đ°Ņ…ĐžĐ´ĐˇĐĩ Ņž ŅŅ–ŅŅ‚ŅĐŧ҃ ŅĐŧ҃ Ņ‚Ņ€ŅĐąĐ° ĐąŅƒĐ´ĐˇĐĩ СĐŧŅĐŊŅ–Ņ†ŅŒ ĐŋĐ°Ņ€ĐžĐģҌ.", @@ -399,8 +413,15 @@ "purchase_button_buy": "ĐšŅƒĐŋŅ–Ņ†ŅŒ", "purchase_button_buy_immich": "ĐšŅƒĐŋŅ–Ņ†ŅŒ Immich", "purchase_button_select": "Đ’Ņ‹ĐąŅ€Đ°Ņ†ŅŒ", + "readonly_mode_disabled": "Đ’Ņ‹ĐēĐģŅŽŅ‡Đ°ĐŊŅ‹ Ņ€ŅĐļŅ‹Đŧ Ņ‚ĐžĐģҌĐēŅ– Đ´ĐģŅ Ņ‡Ņ‹Ņ‚Đ°ĐŊĐŊŅ", "readonly_mode_enabled": "ĐŖĐēĐģŅŽŅ‡Đ°ĐŊŅ‹ Ņ€ŅĐļŅ‹Đŧ Ņ‚ĐžĐģҌĐēŅ– Đ´ĐģŅ Ņ‡Ņ‹Ņ‚Đ°ĐŊĐŊŅ", "reassign": "ПĐĩŅ€Đ°ĐŋŅ€Ņ‹ĐˇĐŊĐ°Ņ‡Ņ‹Ņ†ŅŒ", + "reassing_hint": "ĐŸŅ€Ņ‹ĐŋŅ–ŅĐ°Ņ†ŅŒ Đ˛Ņ‹ĐąŅ€Đ°ĐŊŅ‹Ņ аĐēŅ‚Ņ‹Đ˛Ņ‹ ҖҁĐŊŅƒŅŽŅ‡Đ°Đš Đ°ŅĐžĐąĐĩ", + "recent": "ĐŅĐ´Đ°ŅžĐŊŅ–", + "recent-albums": "ĐŅĐ´Đ°ŅžĐŊŅ–Ņ аĐģŅŒĐąĐžĐŧŅ‹", + "recent_searches": "ĐŅĐ´Đ°ŅžĐŊŅ–Ņ ĐŋĐžŅˆŅƒĐēŅ–", + "recently_added": "ĐŅĐ´Đ°ŅžĐŊа дададСĐĩĐŊа", + "refresh_faces": "АйĐŊĐ°Đ˛Ņ–Ņ†ŅŒ Ņ‚Đ˛Đ°Ņ€Ņ‹", "remove": "Đ’Ņ‹Đ´Đ°ĐģŅ–Ņ†ŅŒ", "remove_from_album": "Đ’Ņ‹Đ´Đ°ĐģŅ–Ņ†ŅŒ С аĐģŅŒĐąĐžĐŧа", "remove_from_favorites": "Đ’Ņ‹Đ´Đ°ĐģŅ–Ņ†ŅŒ С Đ°ĐąŅ€Đ°ĐŊҋ҅", diff --git a/i18n/bg.json b/i18n/bg.json index 27bd6cc78e..a0ab4d0a80 100644 --- a/i18n/bg.json +++ b/i18n/bg.json @@ -28,6 +28,7 @@ "add_to_album": "Добави ĐēҊĐŧ аĐģĐąŅƒĐŧ", "add_to_album_bottom_sheet_added": "ДобавĐĩĐŊĐž в {album}", "add_to_album_bottom_sheet_already_exists": "ВĐĩ҇Đĩ Đĩ в {album}", + "add_to_album_bottom_sheet_some_local_assets": "ĐŅĐēОи ĐģĐžĐēаĐģĐŊи Ņ„Đ°ĐšĐģОвĐĩ ĐŊĐĩ ҃ҁĐŋŅŅ…Đ° да ҁĐĩ Đ´ĐžĐąĐ°Đ˛ŅŅ‚ ĐēҊĐŧ аĐģĐąŅƒĐŧа", "add_to_album_toggle": "ĐĄĐŧĐĩĐŊĐĩŅ‚Đĩ Đ¸ĐˇĐąĐžŅ€Đ° Са {album}", "add_to_albums": "Đ”ĐžĐąĐ°Đ˛ŅĐŊĐĩ в аĐģĐąŅƒĐŧи", "add_to_albums_count": "Đ”ĐžĐąĐ°Đ˛ŅĐŊĐĩ в аĐģĐąŅƒĐŧи ({count})", @@ -123,6 +124,13 @@ "logging_enable_description": "ВĐēĐģŅŽŅ‡Đ˛Đ°ĐŊĐĩ ĐŊа СаĐŋĐ¸Ņ (ĐģĐžĐŗĐžĐ˛Đĩ)", "logging_level_description": "ĐšĐžĐŗĐ°Ņ‚Đž Đĩ вĐēĐģŅŽŅ‡ĐĩĐŊĐž, ĐēаĐēвО ĐŊивО ĐŊа СаĐŋĐ¸ŅĐ˛Đ°ĐŊĐĩ да ҁĐĩ иСĐŋĐžĐģСва.", "logging_settings": "ЗаĐŋĐ¸ŅĐ˛Đ°ĐŊĐĩ", + "machine_learning_availability_checks": "ĐŸŅ€ĐžĐ˛ĐĩŅ€Đēи Са ĐŊаĐģĐ¸Ņ‡ĐŊĐžŅŅ‚", + "machine_learning_availability_checks_description": "ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ĐžŅ‚ĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ и ĐŋŅ€ĐĩĐ´ĐŋĐžŅ‡Đ¸Ņ‚Đ°ĐŊĐĩ ĐŊа ĐŊаĐģĐ¸Ņ‡ĐŊи ŅŅŠŅ€Đ˛ŅŠŅ€Đ¸ Са ĐŧĐ°ŅˆĐ¸ĐŊĐŊĐž ĐžĐąŅƒŅ‡ĐĩĐŊиĐĩ", + "machine_learning_availability_checks_enabled": "АĐēŅ‚Đ¸Đ˛Đ¸Ņ€Đ°ĐŊĐĩ ĐŊа ĐŋŅ€ĐžĐ˛ĐĩŅ€Đēи Са ĐŊаĐģĐ¸Ņ‡ĐŊĐžŅŅ‚", + "machine_learning_availability_checks_interval": "ИĐŊŅ‚ĐĩŅ€Đ˛Đ°Đģ ĐŊа ĐŋŅ€ĐžĐ˛ĐĩŅ€ŅĐ˛Đ°ĐŊĐĩ", + "machine_learning_availability_checks_interval_description": "Đ’Ņ€ĐĩĐŧĐĩ в ĐŧиĐģĐ¸ŅĐĩĐē҃ĐŊди ĐŧĐĩĐļĐ´Ņƒ ĐŋŅ€ĐžĐ˛ĐĩŅ€ĐēĐ¸Ņ‚Đĩ Са ĐŊаĐģĐ¸Ņ‡ĐŊĐžŅŅ‚", + "machine_learning_availability_checks_timeout": "Đ’Ņ€ĐĩĐŧĐĩ Са Đ¸ĐˇŅ‡Đ°ĐēваĐŊĐĩ ĐŊа ĐžŅ‚ĐŗĐžĐ˛ĐžŅ€", + "machine_learning_availability_checks_timeout_description": "Đ’Ņ€ĐĩĐŧĐĩ Са Đ¸ĐˇŅ‡Đ°ĐēваĐŊĐĩ ĐŊа ĐžŅ‚ĐŗĐžĐ˛ĐžŅ€ в ĐŧиĐģĐ¸ŅĐĩĐē҃ĐŊди ĐŋŅ€Đ¸ ĐŋŅ€ĐžĐ˛ĐĩŅ€Đēа ĐŊа ĐŊаĐģĐ¸Ņ‡ĐŊĐžŅŅ‚", "machine_learning_clip_model": "CLIP ĐŧОдĐĩĐģ", "machine_learning_clip_model_description": "ИĐŧĐĩŅ‚Đž ĐŊа CLIP ĐŧОдĐĩĐģа, ĐŋĐžŅĐžŅ‡ĐĩĐŊ Ņ‚ŅƒĐē. ИĐŧĐ°ĐšŅ‚Đĩ ĐŋŅ€Đĩдвид, ҇Đĩ ĐŋŅ€Đ¸ ĐŋŅ€ĐžĐŧŅĐŊа ĐŊа ĐŧОдĐĩĐģа Ņ‚Ņ€ŅĐąĐ˛Đ° да ŅŅ‚Đ°Ņ€Ņ‚Đ¸Ņ€Đ°Ņ‚Đĩ ĐžŅ‚ĐŊОвО ĐˇĐ°Đ´Đ°Ņ‡Đ°Ņ‚Đ° \"ИĐŊŅ‚ĐĩĐģĐ¸ĐŗĐĩĐŊŅ‚ĐŊĐž ĐĸŅŠŅ€ŅĐĩĐŊĐĩ\" Са Đ˛ŅĐ¸Ņ‡Đēи Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ.", "machine_learning_duplicate_detection": "ĐžŅ‚ĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа Đ´ŅƒĐąĐģиĐēĐ°Ņ‚Đ¸", @@ -387,8 +395,6 @@ "admin_password": "АдĐŧиĐŊĐ¸ŅŅ‚Ņ€Đ°Ņ‚ĐžŅ€ŅĐēа ĐŋĐ°Ņ€ĐžĐģа", "administration": "АдĐŧиĐŊĐ¸ŅŅ‚Ņ€Đ°Ņ†Đ¸Ņ", "advanced": "Đ Đ°ĐˇŅˆĐ¸Ņ€ĐĩĐŊĐž", - "advanced_settings_beta_timeline_subtitle": "ОĐŋĐ¸Ņ‚Đ°ĐšŅ‚Đĩ ĐŊĐžĐ˛Đ¸Ņ‚Đĩ Ņ„ŅƒĐŊĐēŅ†Đ¸Đ¸ ĐŊа ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩŅ‚Đž", - "advanced_settings_beta_timeline_title": "БĐĩŅ‚Đ° вĐĩŅ€ŅĐ¸Ņ ĐŊа Đ˛Ņ€ĐĩĐŧĐĩĐ˛Đ°Ņ‚Đ° ĐģиĐŊĐ¸Ņ", "advanced_settings_enable_alternate_media_filter_subtitle": "ĐŸŅ€Đ¸ ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Ņ, иСĐŋĐžĐģĐˇĐ˛Đ°ĐšŅ‚Đĩ Ņ‚Đ°ĐˇĐ¸ ĐžĐŋŅ†Đ¸Ņ ĐēĐ°Ņ‚Đž Ņ„Đ¸ĐģŅ‚ŅŠŅ€, ĐžŅĐŊОваĐŊ ĐŊа ĐŋŅ€ĐžĐŧŅĐŊа ĐŊа дадĐĩĐŊ ĐēŅ€Đ¸Ņ‚ĐĩŅ€Đ¸Đ¸. ОĐŋĐ¸Ņ‚Đ°ĐšŅ‚Đĩ ŅĐ°ĐŧĐž в ҁĐģŅƒŅ‡Đ°Đš, ҇Đĩ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩŅ‚Đž иĐŧа ĐŋŅ€ĐžĐąĐģĐĩĐŧ ҁ ĐžŅ‚ĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа Đ˛ŅĐ¸Ņ‡Đēи аĐģĐąŅƒĐŧи.", "advanced_settings_enable_alternate_media_filter_title": "[ЕКСПЕРИМЕНĐĸАЛНО] ИСĐŋĐžĐģСваК Ņ„Đ¸ĐģŅ‚ŅŠŅ€Đ° ĐŊа аĐģŅ‚ĐĩŅ€ĐŊĐ°Ņ‚Đ¸Đ˛ĐŊĐžŅ‚Đž ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đž Са ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Ņ ĐŊа аĐģĐąŅƒĐŧи", "advanced_settings_log_level_title": "Ниво ĐŊа СаĐŋĐ¸Ņ в Đ´ĐŊĐĩвĐŊиĐēа: {level}", @@ -404,7 +410,7 @@ "advanced_settings_sync_remote_deletions_title": "ХиĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Ņ ĐŊа Đ´Đ¸ŅŅ‚Đ°ĐŊŅ†Đ¸ĐžĐŊĐŊи Đ¸ĐˇŅ‚Ņ€Đ¸Đ˛Đ°ĐŊĐ¸Ņ [ЕКСПЕРИМЕНĐĸАЛНО]", "advanced_settings_tile_subtitle": "Đ Đ°ĐˇŅˆĐ¸Ņ€ĐĩĐŊи ĐŋĐžŅ‚Ņ€ĐĩĐąĐ¸Ņ‚ĐĩĐģҁĐēи ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēи", "advanced_settings_troubleshooting_subtitle": "Đ Đ°ĐˇŅ€ĐĩŅˆĐ¸ Đ´ĐžĐŋҊĐģĐŊĐ¸Ņ‚ĐĩĐģĐŊи Đ˛ŅŠĐˇĐŧĐžĐļĐŊĐžŅŅ‚Đ¸ Са ĐžŅ‚ŅŅ‚Ņ€Đ°ĐŊŅĐ˛Đ°ĐŊĐĩ ĐŊа ĐŋŅ€ĐžĐąĐģĐĩĐŧи", - "advanced_settings_troubleshooting_title": "ĐžŅ‚ŅŅ‚Ņ€Đ°ĐŊŅĐ˛Đ°ĐŊĐĩ ĐŊа ĐŋŅ€ĐžĐąĐģĐĩĐŧи", + "advanced_settings_troubleshooting_title": "ĐžŅ‚ŅŅ‚Ņ€Đ°ĐŊŅĐ˛Đ°ĐŊe ĐŊа ĐŋŅ€ĐžĐąĐģĐĩĐŧи", "age_months": "Đ’ŅŠĐˇŅ€Đ°ŅŅ‚ {months, plural, one {# ĐŧĐĩҁĐĩ҆} other {# ĐŧĐĩҁĐĩŅ†Đ¸}}", "age_year_months": "Đ’ŅŠĐˇŅ€Đ°ŅŅ‚ 1 ĐŗĐžĐ´Đ¸ĐŊа, {months, plural, one {# ĐŧĐĩҁĐĩ҆} other {# ĐŧĐĩҁĐĩŅ†Đ¸}}", "age_years": "{years, plural, other {ГодиĐŊа #}}", @@ -425,6 +431,7 @@ "album_remove_user_confirmation": "ĐĄĐ¸ĐŗŅƒŅ€ĐŊи Đģи ҁ҂Đĩ, ҇Đĩ Đ¸ŅĐēĐ°Ņ‚Đĩ да ĐŋŅ€ĐĩĐŧĐ°Ņ…ĐŊĐĩŅ‚Đĩ {user}?", "album_search_not_found": "ĐŅĐŧа ĐŊаĐŧĐĩŅ€ĐĩĐŊи аĐģĐąŅƒĐŧи, ĐžŅ‚ĐŗĐžĐ˛Đ°Ņ€ŅŅ‰Đ¸ ĐŊа Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩŅ‚Đž ви", "album_share_no_users": "Đ˜ĐˇĐŗĐģĐĩĐļда, ҇Đĩ ҁ҂Đĩ ҁĐŋОдĐĩĐģиĐģи Ņ‚ĐžĐˇĐ¸ аĐģĐąŅƒĐŧ ҁ Đ˛ŅĐ¸Ņ‡Đēи ĐŋĐžŅ‚Ņ€ĐĩĐąĐ¸Ņ‚ĐĩĐģи иĐģи ĐŊŅĐŧĐ°Ņ‚Đĩ Đ´Ņ€ŅƒĐŗ ĐŋĐžŅ‚Ņ€ĐĩĐąĐ¸Ņ‚ĐĩĐģ, ҁ ĐēĐžĐŗĐžŅ‚Đž да ĐŗĐž ҁĐŋОдĐĩĐģĐ¸Ņ‚Đĩ.", + "album_summary": "ĐžĐąĐžĐąŅ‰ĐĩĐŊиĐĩ ĐŊа аĐģĐąŅƒĐŧа", "album_updated": "АĐģĐąŅƒĐŧŅŠŅ‚ Đĩ аĐēŅ‚ŅƒĐ°ĐģĐ¸ĐˇĐ¸Ņ€Đ°ĐŊ", "album_updated_setting_description": "ПоĐģŅƒŅ‡Đ°Đ˛Đ°ĐšŅ‚Đĩ иСвĐĩŅŅ‚Đ¸Đĩ ĐŋĐž иĐŧĐĩĐšĐģ, ĐēĐžĐŗĐ°Ņ‚Đž ҁĐŋОдĐĩĐģĐĩĐŊ аĐģĐąŅƒĐŧ иĐŧа ĐŊОви Ņ„Đ°ĐšĐģОвĐĩ", "album_user_left": "НаĐŋ҃ҁĐŊа {album}", @@ -496,6 +503,8 @@ "asset_restored_successfully": "ĐŖŅĐŋĐĩ҈ĐŊĐž Đ˛ŅŠĐˇŅŅ‚Đ°ĐŊОвĐĩĐŊ ОйĐĩĐēŅ‚", "asset_skipped": "ĐŸŅ€ĐžĐŋ҃ҁĐŊĐ°Ņ‚Đž", "asset_skipped_in_trash": "В ĐēĐžŅˆŅ‡ĐĩŅ‚Đž", + "asset_trashed": "ОбĐĩĐēŅ‚ŅŠŅ‚ Đĩ Đ¸ĐˇŅ…Đ˛ŅŠŅ€ĐģĐĩĐŊ", + "asset_troubleshoot": "ПоĐŋŅ€Đ°Đ˛Đēа ĐŊа ĐŗŅ€Đĩ҈Đēи ҁ ОйĐĩĐēŅ‚Đ°", "asset_uploaded": "ĐšĐ°Ņ‡ĐĩĐŊĐž", "asset_uploading": "ĐšĐ°Ņ‡Đ˛Đ°ĐŊĐĩâ€Ļ", "asset_viewer_settings_subtitle": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ĐŊа ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēĐ¸Ņ‚Đĩ Са Đ¸ĐˇĐŗĐģĐĩĐ´", @@ -529,8 +538,10 @@ "autoplay_slideshow": "ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊа ҁĐŧŅĐŊа ĐŊа ҁĐģаКдОвĐĩŅ‚Đĩ", "back": "Назад", "back_close_deselect": "Назад, ĐˇĐ°Ņ‚Đ˛Đ°Ņ€ŅĐŊĐĩ иĐģи ĐŋŅ€ĐĩĐŧĐ°Ņ…Đ˛Đ°ĐŊĐĩ ĐŊа Đ¸ĐˇĐąĐžŅ€Đ°", + "background_backup_running_error": "ĐĄŅ‚Đ°Ņ€Ņ‚Đ¸Ņ€Đ°ĐŊĐž Đĩ Ņ„ĐžĐŊОвО Đ°Ņ€Ņ…Đ¸Đ˛Đ¸Ņ€Đ°ĐŊĐĩ, ĐŊĐĩ ĐŧĐžĐļĐĩ да ҁĐĩ Đŋ҃ҁĐŊĐĩ Ņ€ŅŠŅ‡ĐŊĐž Đ°Ņ€Ņ…Đ¸Đ˛Đ¸Ņ€Đ°ĐŊĐĩ", "background_location_permission": "Đ Đ°ĐˇŅ€Đĩ҈ĐĩĐŊиĐĩ Са Đ´ĐžŅŅ‚ŅŠĐŋ Đ´Đž ĐŧĐĩŅŅ‚ĐžĐŋĐžĐģĐžĐļĐĩĐŊиĐĩŅ‚Đž Đ˛ŅŠĐ˛ Ņ„ĐžĐŊОв Ņ€ĐĩĐļиĐŧ", "background_location_permission_content": "За да ĐŧĐžĐļĐĩ да ҇ĐĩŅ‚Đĩ иĐŧĐĩĐŊĐ°Ņ‚Đ° ĐŊа Wi-Fi ĐŧŅ€ĐĩĐļĐ¸Ņ‚Đĩ и да ĐŗĐ¸ ĐŋŅ€ĐĩвĐēĐģŅŽŅ‡Đ˛Đ° ĐŋŅ€Đ¸ Ņ€Đ°ĐąĐžŅ‚Đ° Đ˛ŅŠĐ˛ Ņ„ĐžĐŊОв Ņ€ĐĩĐļиĐŧ, Immich Ņ‚Ņ€ŅĐąĐ˛Đ° *виĐŊĐ°ĐŗĐ¸* да иĐŧа Đ´ĐžŅŅ‚ŅŠĐŋ Đ´Đž Ņ‚ĐžŅ‡ĐŊĐžŅ‚Đž ĐŧĐĩŅŅ‚ĐžĐŋĐžĐģĐžĐļĐĩĐŊиĐĩ", + "background_options": "ОĐŋŅ†Đ¸Đ¸ Са Ņ„ĐžĐŊĐžĐ˛Đ¸Ņ‚Đĩ ĐˇĐ°Đ´Đ°Ņ‡Đ¸", "backup": "ĐŅ€Ņ…Đ¸Đ˛Đ¸Ņ€Đ°ĐŊĐĩ", "backup_album_selection_page_albums_device": "АĐģĐąŅƒĐŧи ĐŊа ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛ĐžŅ‚Đž ({count})", "backup_album_selection_page_albums_tap": "ĐĐ°Ņ‚Đ¸ŅĐŊи Са да вĐēĐģŅŽŅ‡Đ¸Ņˆ, двОКĐŊĐž Са да иСĐēĐģŅŽŅ‡Đ¸Ņˆ", @@ -538,6 +549,7 @@ "backup_album_selection_page_select_albums": "Đ˜ĐˇĐąĐžŅ€ ĐŊа аĐģĐąŅƒĐŧи", "backup_album_selection_page_selection_info": "ИĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Ņ Са Đ¸ĐˇĐąŅ€Đ°ĐŊĐžŅ‚Đž", "backup_album_selection_page_total_assets": "ĐŖĐŊиĐēаĐģĐŊи ОйĐĩĐēŅ‚Đ¸ ĐžĐąŅ‰Đž", + "backup_albums_sync": "ХиĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ¸Ņ€Đ°ĐŊĐĩ ĐŊа Đ°Ņ€Ņ…Đ¸Đ˛Đ¸Ņ‚Đĩ", "backup_all": "Đ’ŅĐ¸Ņ‡ĐēĐž", "backup_background_service_backup_failed_message": "НĐĩ҃ҁĐŋĐĩ҈ĐŊĐž Đ°Ņ€Ņ…Đ¸Đ˛Đ¸Ņ€Đ°ĐŊĐĩ. Нов ĐžĐŋĐ¸Ņ‚â€Ļ", "backup_background_service_connection_failed_message": "НĐĩ҃ҁĐŋĐĩ҈ĐŊĐž ŅĐ˛ŅŠŅ€ĐˇĐ˛Đ°ĐŊĐĩ ĐēҊĐŧ ŅŅŠŅ€Đ˛ŅŠŅ€Đ°. Нов ĐžĐŋĐ¸Ņ‚â€Ļ", @@ -587,7 +599,8 @@ "backup_controller_page_turn_on": "ВĐēĐģŅŽŅ‡Đ¸ Đ°Ņ€Ņ…Đ¸Đ˛Đ¸Ņ€Đ°ĐŊĐĩ в аĐēŅ‚Đ¸Đ˛ĐĩĐŊ Ņ€ĐĩĐļиĐŧ", "backup_controller_page_uploading_file_info": "ИĐŊŅ„Đž Са Đ°Ņ€Ņ…Đ¸Đ˛Đ¸Ņ€Đ°ĐŊĐ¸Ņ Ņ„Đ°ĐšĐģ", "backup_err_only_album": "НĐĩ ĐŧĐžĐļĐĩ да ҁĐĩ ĐŋŅ€ĐĩĐŧĐ°Ņ…ĐŊĐĩ ĐĩдиĐŊŅŅ‚Đ˛ĐĩĐŊĐ¸Ņ аĐģĐąŅƒĐŧ", - "backup_info_card_assets": "ОйĐĩĐēŅ‚Đ¸", + "backup_error_sync_failed": "ХиĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸ŅŅ‚Đ° Đĩ ĐŊĐĩ҃ҁĐŋĐĩ҈ĐŊа. Đ ĐĩСĐĩŅ€Đ˛ĐŊĐžŅ‚Đž ĐēĐžĐŋиĐĩ ĐŊĐĩ ĐŧĐžĐļĐĩ да ҁĐĩ ĐžĐąŅ€Đ°ĐąĐžŅ‚Đ¸.", + "backup_info_card_assets": "ОйĐĩĐēŅ‚Đ°", "backup_manual_cancelled": "ĐžŅ‚ĐŧĐĩĐŊĐĩĐŊĐž", "backup_manual_in_progress": "Đ’ŅŠŅ€Đ˛Đ¸ Đ°Ņ€Ņ…Đ¸Đ˛Đ¸Ņ€Đ°ĐŊĐĩ. ОĐŋĐ¸Ņ‚Đ°Đš ҁĐģĐĩĐ´ ĐŧаĐģĐēĐž", "backup_manual_success": "ĐŖŅĐŋĐĩ҈ĐŊĐž", @@ -597,8 +610,6 @@ "backup_setting_subtitle": "ĐŖĐŋŅ€Đ°Đ˛ĐģŅĐ˛Đ°Đš ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēĐ¸Ņ‚Đĩ Са Đ°Ņ€Ņ…Đ¸Đ˛Đ¸Ņ€Đ°ĐŊĐĩ в аĐēŅ‚Đ¸Đ˛ĐĩĐŊ и Ņ„ĐžĐŊОв Ņ€ĐĩĐļиĐŧ", "backup_settings_subtitle": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ĐŊа ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēĐ¸Ņ‚Đĩ Са ĐēĐ°Ņ‡Đ˛Đ°ĐŊĐĩ", "backward": "Назад", - "beta_sync": "ĐĄŅ‚Đ°Ņ‚ŅƒŅ ĐŊа ĐąĐĩŅ‚Đ° ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸ŅŅ‚Đ°", - "beta_sync_subtitle": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ĐŊа ĐŊĐžĐ˛Đ°Ņ‚Đ° ŅĐ¸ŅŅ‚ĐĩĐŧа Са ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Ņ", "biometric_auth_enabled": "ВĐēĐģŅŽŅ‡ĐĩĐŊа йиОĐŧĐĩŅ‚Ņ€Đ¸Ņ‡ĐŊĐž ŅƒĐ´ĐžŅŅ‚ĐžĐ˛ĐĩŅ€ŅĐ˛Đ°ĐŊĐĩ", "biometric_locked_out": "ĐŅĐŧа Đ´ĐžŅŅ‚ŅŠĐŋ Đ´Đž йиОĐŧĐĩŅ‚Ņ€Đ¸Ņ‡ĐŊĐž ŅƒĐ´ĐžŅŅ‚ĐžĐ˛ĐĩŅ€ŅĐ˛Đ°ĐŊĐĩ", "biometric_no_options": "ĐŅĐŧа йиОĐŧĐĩŅ‚Ņ€Đ¸Ņ‡ĐŊа Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸ĐēĐ°Ņ†Đ¸Ņ", @@ -656,6 +667,8 @@ "change_pin_code": "ĐĄĐŧĐĩĐŊи PIN ĐēОда", "change_your_password": "ĐŸŅ€ĐžĐŧĐĩĐŊĐĩŅ‚Đĩ ĐŋĐ°Ņ€ĐžĐģĐ°Ņ‚Đ° ŅĐ¸", "changed_visibility_successfully": "ВидиĐŧĐžŅŅ‚Ņ‚Đ° Đĩ ĐŋŅ€ĐžĐŧĐĩĐŊĐĩĐŊа ҃ҁĐŋĐĩ҈ĐŊĐž", + "charging": "ĐŸŅ€Đ¸ ĐˇĐ°Ņ€ĐĩĐļдаĐŊĐĩ", + "charging_requirement_mobile_backup": "ФОĐŊОвО Đ°Ņ€Ņ…Đ¸Đ˛Đ¸Ņ€Đ°ĐŊĐĩ ŅĐ°ĐŧĐž ĐŋŅ€Đ¸ ĐˇĐ°Ņ€ĐĩĐļдаĐŊĐĩ ĐŊа ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛ĐžŅ‚Đž", "check_corrupt_asset_backup": "ĐŸŅ€ĐžĐ˛ĐĩŅ€Đ¸ Са ĐŋĐžĐ˛Ņ€ĐĩĐ´ĐĩĐŊи Đ°Ņ€Ņ…Đ¸Đ˛ĐŊи ĐēĐžĐŋĐ¸Ņ", "check_corrupt_asset_backup_button": "ĐŸŅ€ĐžĐ˛ĐĩŅ€Đ¸", "check_corrupt_asset_backup_description": "ИСĐŋҊĐģĐŊи Ņ‚Đ°ĐˇĐ¸ ĐŋŅ€ĐžĐ˛ĐĩŅ€Đēа ŅĐ°ĐŧĐž ĐŋŅ€Đ¸ Wi-Fi и ҁĐģĐĩĐ´ Đ°Ņ€Ņ…Đ¸Đ˛Đ¸Ņ€Đ°ĐŊĐĩ ĐŊа Đ˛ŅĐ¸Ņ‡Đēи ОйĐĩĐēŅ‚Đ¸. ĐŸŅ€ĐžŅ†ĐĩĐ´ŅƒŅ€Đ°Ņ‚Đ° ĐŧĐžĐļĐĩ да ĐŋŅ€ĐžĐ´ŅŠĐģĐļи ĐŊŅĐēĐžĐģĐēĐž ĐŧиĐŊŅƒŅ‚Đ¸.", @@ -742,6 +755,7 @@ "create_user": "ĐĄŅŠĐˇĐ´Đ°Đš ĐŋĐžŅ‚Ņ€ĐĩĐąĐ¸Ņ‚ĐĩĐģ", "created": "ĐĄŅŠĐˇĐ´Đ°Đ´ĐĩĐŊĐž", "created_at": "ĐĄŅŠĐˇĐ´Đ°Đ´ĐĩĐŊ", + "creating_linked_albums": "ĐĄŅŠĐˇĐ´Đ°Đ˛Đ°ĐŊĐĩ ĐŊа ŅĐ˛ŅŠŅ€ĐˇĐ°ĐŊи аĐģĐąŅƒĐŧи...", "crop": "Đ˜ĐˇŅ€ĐĩĐļи", "curated_object_page_title": "НĐĩŅ‰Đ°", "current_device": "ĐĸĐĩĐēŅƒŅ‰Đž ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đž", @@ -891,7 +905,9 @@ "error": "Đ“Ņ€Đĩ҈Đēа", "error_change_sort_album": "НĐĩ҃ҁĐŋĐĩ҈ĐŊа ĐŋŅ€ĐžĐŧŅĐŊа ĐŊа Ņ€Đĩда ĐŊа ŅĐžŅ€Ņ‚Đ¸Ņ€Đ°ĐŊĐĩ ĐŊа аĐģĐąŅƒĐŧ", "error_delete_face": "Đ“Ņ€Đĩ҈Đēа ĐŋŅ€Đ¸ Đ¸ĐˇŅ‚Ņ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа ĐģĐ¸Ņ†Đĩ ĐžŅ‚ аĐēŅ‚Đ¸Đ˛Đ°", + "error_getting_places": "Đ“Ņ€Đĩ҈Đēа ĐŋŅ€Đ¸ ŅŅŠĐąĐ¸Ņ€Đ°ĐŊĐĩ ĐŊа ĐŧĐĩŅŅ‚Đ°Ņ‚Đ°", "error_loading_image": "Đ“Ņ€Đĩ҈Đēа ĐŋŅ€Đ¸ ĐˇĐ°Ņ€ĐĩĐļдаĐŊĐĩ ĐŊа Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиĐĩŅ‚Đž", + "error_loading_partners": "Đ“Ņ€Đĩ҈Đēа ĐŋŅ€Đ¸ ĐˇĐ°Ņ€ĐĩĐļдаĐŊĐĩ ĐŊа ĐŋĐ°Ņ€Ņ‚ĐŊŅŒĐžŅ€Đ¸: {error}", "error_saving_image": "Đ“Ņ€Đĩ҈Đēа: {error}", "error_tag_face_bounding_box": "Đ“Ņ€Đĩ҈Đēа ĐŋŅ€Đ¸ ĐžŅ‚ĐąĐĩĐģŅĐˇĐ˛Đ°ĐŊĐĩ ĐŊа ĐģĐ¸Ņ†Đĩ - ĐŊĐĩ҃ҁĐŋĐĩ҈ĐŊĐž ĐŋĐžĐģŅƒŅ‡Đ°Đ˛Đ°ĐŊĐĩ ĐŊа ĐēĐžĐžŅ€Đ´Đ¸ĐŊĐ°Ņ‚Đ¸ ĐŊа Ņ€Đ°ĐŧĐēĐ°Ņ‚Đ°", "error_title": "Đ“Ņ€Đĩ҈Đēа - ĐŊĐĩŅ‰Đž ҁĐĩ ĐžĐąŅŠŅ€Đēа", @@ -1056,6 +1072,7 @@ "favorites_page_no_favorites": "НĐĩ ŅĐ° ĐŊаĐŧĐĩŅ€ĐĩĐŊи ĐģŅŽĐąĐ¸Đŧи ОйĐĩĐēŅ‚Đ¸", "feature_photo_updated": "ĐŸŅ€ĐĩĐ´ŅŅ‚Đ°Đ˛Đ¸Ņ‚ĐĩĐģĐŊĐ°Ņ‚Đ° ҁĐŊиĐŧĐēа Đĩ ĐŋŅ€ĐžĐŧĐĩĐŊĐĩĐŊа", "features": "Đ¤ŅƒĐŊĐēŅ†Đ¸Đ¸", + "features_in_development": "Đ¤ŅƒĐŊĐēŅ†Đ¸Đ¸ в ĐŋŅ€ĐžŅ†Đĩҁ ĐŊа Ņ€Đ°ĐˇŅ€Đ°ĐąĐžŅ‚Đēа", "features_setting_description": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ĐŊа Ņ„ŅƒĐŊĐēŅ†Đ¸Đ¸Ņ‚Đĩ ĐŊа ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩŅ‚Đž", "file_name": "ИĐŧĐĩ ĐŊа Ņ„Đ°ĐšĐģа", "file_name_or_extension": "ИĐŧĐĩ ĐŊа Ņ„Đ°ĐšĐģ иĐģи Ņ€Đ°ĐˇŅˆĐ¸Ņ€ĐĩĐŊиĐĩ", @@ -1076,10 +1093,7 @@ "gcast_enabled": "Google Cast", "gcast_enabled_description": "За да Ņ€Đ°ĐąĐžŅ‚Đ¸ Ņ‚Đ°ĐˇĐ¸ Ņ„ŅƒĐŊĐēŅ†Đ¸Ņ ĐˇĐ°Ņ€ĐĩĐļда Đ˛ŅŠĐŊ҈ĐŊи Ņ€ĐĩŅŅƒŅ€ŅĐ¸ ĐžŅ‚ Google.", "general": "ĐžĐąŅ‰Đ¸", - "geolocation_instruction_all_have_location": "Đ’ŅĐ¸Ņ‡Đēи ОйĐĩĐēŅ‚Đ¸ ĐžŅ‚ Ņ‚Đ°ĐˇĐ¸ Đ´Đ°Ņ‚Đ° вĐĩ҇Đĩ иĐŧĐ°Ņ‚ даĐŊĐŊи Са ĐŧĐĩŅŅ‚ĐžĐŋĐžĐģĐžĐļĐĩĐŊиĐĩ. ОĐŋĐ¸Ņ‚Đ°ĐšŅ‚Đĩ да вĐēĐģŅŽŅ‡Đ¸Ņ‚Đĩ ĐŋĐžĐēаСваĐŊĐĩ ĐŊа Đ˛ŅĐ¸Ņ‡Đēи ОйĐĩĐēŅ‚Đ¸ иĐģи иСйĐĩŅ€ĐĩŅ‚Đĩ Đ´Ņ€ŅƒĐŗĐ° Đ´Đ°Ņ‚Đ°", "geolocation_instruction_location": "ИСйĐĩŅ€ĐĩŅ‚Đĩ ОйĐĩĐēŅ‚ ҁ GPS ĐēĐžĐžŅ€Đ´Đ¸ĐŊĐ°Ņ‚Đ¸ Са да иСĐŋĐžĐģĐˇĐ˛Đ°Ņ‚Đĩ Ņ‚ŅŅ… иĐģи иСйĐĩŅ€ĐĩŅ‚Đĩ ĐŧŅŅŅ‚Đž Đ´Đ¸Ņ€ĐĩĐēŅ‚ĐŊĐž ĐžŅ‚ ĐēĐ°Ņ€Ņ‚Đ°Ņ‚Đ°", - "geolocation_instruction_no_date": "ИСйĐĩŅ€ĐĩŅ‚Đĩ Đ´Đ°Ņ‚Đ° Са да ҃ĐŋŅ€Đ°Đ˛ĐģŅĐ˛Đ°Ņ‚Đĩ даĐŊĐŊĐ¸Ņ‚Đĩ Са ĐģĐžĐēĐ°Ņ†Đ¸Ņ ĐŊа ҁĐŊиĐŧĐēĐ¸Ņ‚Đĩ и видĐĩĐ°Ņ‚Đ° ĐžŅ‚ Ņ‚Đ°ĐˇĐ¸ Đ´Đ°Ņ‚Đ°", - "geolocation_instruction_no_photos": "НĐĩ ŅĐ° ĐŊаĐŧĐĩŅ€ĐĩĐŊи ҁĐŊиĐŧĐēи иĐģи видĐĩа ĐžŅ‚ Ņ‚Đ°ĐˇĐ¸ Đ´Đ°Ņ‚Đ°. ИСйĐĩŅ€ĐĩŅ‚Đĩ Đ´Ņ€ŅƒĐŗĐ° Đ´Đ°Ņ‚Đ°", "get_help": "ПоĐŧĐžŅ‰", "get_wifiname_error": "НĐĩ҃ҁĐŋĐĩ҈ĐŊĐž ĐŋĐžĐģŅƒŅ‡Đ°Đ˛Đ°ĐŊĐĩ иĐŧĐĩŅ‚Đž ĐŊа Wi-Fi ĐŧŅ€ĐĩĐļĐ°Ņ‚Đ°. МоĐģŅ, ŅƒĐąĐĩĐ´ĐĩŅ‚Đĩ ҁĐĩ, ҇Đĩ ŅĐ° ĐŋŅ€ĐĩĐ´ĐžŅŅ‚Đ°Đ˛ĐĩĐŊи ĐŊ҃ĐļĐŊĐ¸Ņ‚Đĩ Ņ€Đ°ĐˇŅ€Đĩ҈ĐĩĐŊĐ¸Ņ ĐŊа ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩŅ‚Đž и иĐŧа Đ˛Ņ€ŅŠĐˇĐēа ҁ Wi-Fi", "getting_started": "КаĐē да СаĐŋĐžŅ‡ĐŊĐĩĐŧ", @@ -1223,6 +1237,7 @@ "local": "ЛоĐēаĐģĐŊĐž", "local_asset_cast_failed": "НĐĩ ĐŧĐžĐļĐĩ да ҁĐĩ ĐŋŅ€Đĩдава ОйĐĩĐēŅ‚, ĐēĐžĐšŅ‚Đž ĐžŅ‰Đĩ ĐŊĐĩ Đĩ ĐēĐ°Ņ‡ĐĩĐŊ ĐŊа ŅŅŠŅ€Đ˛ŅŠŅ€Đ°", "local_assets": "ЛоĐēаĐģĐŊи ОйĐĩĐēŅ‚Đ¸", + "local_media_summary": "ĐžĐąĐžĐąŅ‰ĐĩĐŊиĐĩ ĐŊа ĐģĐžĐēаĐģĐŊĐ¸Ņ‚Đĩ Ņ„Đ°ĐšĐģОвĐĩ", "local_network": "ЛоĐēаĐģĐŊа ĐŧŅ€ĐĩĐļа", "local_network_sheet_info": "ĐŸŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩŅ‚Đž ҉Đĩ ҁĐĩ ŅĐ˛ŅŠŅ€ĐļĐĩ ҁҊҁ ŅŅŠŅ€Đ˛ŅŠŅ€Đ° ĐŊа Ņ‚ĐžĐˇĐ¸ URL, ĐēĐžĐŗĐ°Ņ‚Đž ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛ĐžŅ‚Đž Đĩ ŅĐ˛ŅŠŅ€ĐˇĐ°ĐŊĐž ĐēҊĐŧ СададĐĩĐŊĐ°Ņ‚Đ° Wi-Fi ĐŧŅ€ĐĩĐļа", "location_permission": "Đ Đ°ĐˇŅ€Đĩ҈ĐĩĐŊиĐĩ Са ĐŧĐĩŅŅ‚ĐžĐŋĐžĐģĐžĐļĐĩĐŊиĐĩ", @@ -1234,6 +1249,7 @@ "location_picker_longitude_hint": "Đ’ŅŠĐ˛ĐĩĐ´ĐĩŅ‚Đĩ ĐŗĐĩĐžĐŗŅ€Đ°Ņ„ŅĐēа Đ´ŅŠĐģĐļиĐŊа Ņ‚ŅƒĐē", "lock": "ЗаĐēĐģŅŽŅ‡Đ¸", "locked_folder": "ЗаĐēĐģŅŽŅ‡ĐĩĐŊа ĐŋаĐŋĐēа", + "log_detail_title": "ĐŸĐžĐ´Ņ€ĐžĐąĐŊĐžŅŅ‚Đ¸ ĐžŅ‚ Đ´ĐŊĐĩвĐŊиĐēа", "log_out": "ИСĐģиСаĐŊĐĩ", "log_out_all_devices": "ИСĐģиСаĐŊĐĩ ҁ Đ˛ŅĐ¸Ņ‡Đēи ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đ°", "logged_in_as": "ВĐŋĐ¸ŅĐ°ĐŊ ĐēĐ°Ņ‚Đž {user}", @@ -1264,6 +1280,7 @@ "login_password_changed_success": "ĐŖŅĐŋĐĩ҈ĐŊĐž ОйĐŊОвĐĩĐŊа ĐŋĐ°Ņ€ĐžĐģа", "logout_all_device_confirmation": "ĐĄĐ¸ĐŗŅƒŅ€ĐŊи Đģи ҁ҂Đĩ, ҇Đĩ Đ¸ŅĐēĐ°Ņ‚Đĩ да иСĐģĐĩСĐĩŅ‚Đĩ ĐžŅ‚ Đ˛ŅĐ¸Ņ‡Đēи ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đ°?", "logout_this_device_confirmation": "ĐĄĐ¸ĐŗŅƒŅ€ĐŊи Đģи ҁ҂Đĩ, ҇Đĩ Đ¸ŅĐēĐ°Ņ‚Đĩ да иСĐģĐĩСĐĩŅ‚Đĩ ĐžŅ‚ Ņ‚ĐžĐ˛Đ° ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đž?", + "logs": "ДĐŊĐĩвĐŊиĐē", "longitude": "Đ”ŅŠĐģĐļиĐŊа", "look": "Đ˜ĐˇĐŗĐģĐĩĐ´", "loop_videos": "ĐŸĐžĐ˛Ņ‚Đ°Ņ€ŅĐŊĐĩ ĐŊа видĐĩĐ°Ņ‚Đ°", @@ -1306,6 +1323,7 @@ "mark_as_read": "ĐœĐ°Ņ€ĐēĐ¸Ņ€Đ°Đš ĐēĐ°Ņ‚Đž ҇ĐĩŅ‚ĐĩĐŊĐž", "marked_all_as_read": "Đ’ŅĐ¸Ņ‡Đēи ĐŧĐ°Ņ€ĐēĐ¸Ņ€Đ°ĐŊи ĐēĐ°Ņ‚Đž ĐŋŅ€ĐžŅ‡ĐĩŅ‚ĐĩĐŊи", "matches": "ĐĄŅŠĐ˛ĐŋадĐĩĐŊĐ¸Ņ", + "matching_assets": "ĐĄŅŠĐ˛ĐŋĐ°Đ´Đ°Ņ‰Đ¸ ОйĐĩĐēŅ‚Đ¸", "media_type": "Вид ĐŧĐĩĐ´Đ¸Ņ", "memories": "ĐĄĐŋĐžĐŧĐĩĐŊи", "memories_all_caught_up": "ĐĸОва Đĩ Đ˛ŅĐ¸Ņ‡ĐēĐž Са Đ´ĐŊĐĩҁ", @@ -1328,7 +1346,7 @@ "missing": "ЛиĐŋŅĐ˛Đ°Ņ‰Đ¸", "model": "МодĐĩĐģ", "month": "МĐĩҁĐĩ҆", - "monthly_title_text_date_format": "MMMM y", + "monthly_title_text_date_format": "MMMM Đŗ", "more": "ĐžŅ‰Đĩ", "move": "ĐŸŅ€ĐĩĐŧĐĩŅŅ‚Đ¸", "move_off_locked_folder": "ИСвади ĐžŅ‚ СаĐēĐģŅŽŅ‡ĐĩĐŊĐ°Ņ‚Đ° ĐŋаĐŋĐēа", @@ -1346,6 +1364,7 @@ "name_or_nickname": "ИĐŧĐĩ иĐģи ĐŋŅ€ŅĐēĐžŅ€", "network_requirement_photos_upload": "ИСĐŋĐžĐģСваК ĐŧОйиĐģĐŊи даĐŊĐŊи Са Đ°Ņ€Ņ…Đ¸Đ˛Đ¸Ņ€Đ°ĐŊĐĩ ĐŊа ҁĐŊиĐŧĐēи", "network_requirement_videos_upload": "ИСĐŋĐžĐģСваК ĐŧОйиĐģĐŊи даĐŊĐŊи Са Đ°Ņ€Ņ…Đ¸Đ˛Đ¸Ņ€Đ°ĐŊĐĩ ĐŊа видĐĩĐž", + "network_requirements": "Đ˜ĐˇĐ¸ŅĐēваĐŊĐ¸Ņ ĐēҊĐŧ ĐŧŅ€ĐĩĐļĐ°Ņ‚Đ°", "network_requirements_updated": "ĐœŅ€ĐĩĐļĐžĐ˛Đ¸Ņ‚Đĩ ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēи ŅĐ° ĐŋŅ€ĐžĐŧĐĩĐŊĐĩĐŊи, ĐŊ҃ĐģĐ¸Ņ€Đ°ĐŊĐĩ ĐŊа ĐžĐŋĐ°ŅˆĐēĐ°Ņ‚Đ° Са Đ°Ņ€Ņ…Đ¸Đ˛Đ¸Ņ€Đ°ĐŊĐĩ", "networking_settings": "ĐœŅ€ĐĩĐļа", "networking_subtitle": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ĐŊа ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēĐ¸Ņ‚Đĩ Са Đ˛Ņ€ŅŠĐˇĐēа ҁҊҁ ŅŅŠŅ€Đ˛ŅŠŅ€Đ°", @@ -1356,6 +1375,7 @@ "new_person": "Нов Ņ‡ĐžĐ˛ĐĩĐē", "new_pin_code": "Нов PIN ĐēОд", "new_pin_code_subtitle": "ĐĸОва Đĩ ĐŋŅŠŅ€Đ˛Đ¸ Đ´ĐžŅŅ‚ŅŠĐŋ Đ´Đž СаĐēĐģŅŽŅ‡ĐĩĐŊа ĐŋаĐŋĐēа. ĐĄŅŠĐˇĐ´Đ°ĐšŅ‚Đĩ PIN ĐēОд Са ĐˇĐ°Ņ‰Đ¸Ņ‚ĐĩĐŊ Đ´ĐžŅŅ‚ŅŠĐŋ Đ´Đž Ņ‚Đ°ĐˇĐ¸ ŅŅ‚Ņ€Đ°ĐŊĐ¸Ņ†Đ°", + "new_timeline": "Нова Đ˛Ņ€ĐĩĐŧĐĩва ĐģиĐŊĐ¸Ņ", "new_user_created": "ĐĄŅŠĐˇĐ´Đ°Đ´ĐĩĐŊ ĐŊОв ĐŋĐžŅ‚Ņ€ĐĩĐąĐ¸Ņ‚ĐĩĐģ", "new_version_available": "НАЛИЧНА НОВА Đ’Đ•Đ ĐĄĐ˜Đ¯", "newest_first": "Най-ĐŊĐžĐ˛Đ¸Ņ‚Đĩ ĐŋŅŠŅ€Đ˛Đ¸", @@ -1369,20 +1389,25 @@ "no_assets_message": "КЛИКНЕĐĸЕ, ЗА ДА КАЧИĐĸЕ ПĐĒРВАĐĸА ХИ СНИМКА", "no_assets_to_show": "ĐŅĐŧа ОйĐĩĐēŅ‚Đ¸ Са ĐŋĐžĐēаСваĐŊĐĩ", "no_cast_devices_found": "ĐŅĐŧа ĐŊаĐŧĐĩŅ€ĐĩĐŊи ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đ° Са ĐŋŅ€ĐĩдаваĐŊĐĩ", + "no_checksum_local": "ЛиĐŋŅĐ˛Đ°Ņ‚ ĐēĐžĐŊŅ‚Ņ€ĐžĐģĐŊи ҁ҃Đŧи - ĐŊĐĩ ĐŧĐžĐļĐĩ да ҁĐĩ ĐŋĐžĐģŅƒŅ‡Đ°Ņ‚ ĐģĐžĐēаĐģĐŊи ОйĐĩĐēŅ‚Đ¸", + "no_checksum_remote": "ЛиĐŋŅĐ˛Đ°Ņ‚ ĐēĐžĐŊŅ‚Ņ€ĐžĐģĐŊи ҁ҃Đŧи - ĐŊĐĩ ĐŧĐžĐļĐĩ да ҁĐĩ ĐŋĐžĐģŅƒŅ‡Đ°Ņ‚ ОйĐĩĐēŅ‚Đ¸ ĐžŅ‚ ŅŅŠŅ€Đ˛ŅŠŅ€Đ°", "no_duplicates_found": "НĐĩ ĐąŅŅ…Đ° ĐžŅ‚ĐēŅ€Đ¸Ņ‚Đ¸ Đ´ŅƒĐąĐģиĐēĐ°Ņ‚Đ¸.", "no_exif_info_available": "ĐŅĐŧа exif иĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Ņ", "no_explore_results_message": "ĐšĐ°Ņ‡ĐĩŅ‚Đĩ ĐžŅ‰Đĩ ҁĐŊиĐŧĐēи, Са да Ņ€Đ°ĐˇĐŗĐģĐĩĐ´Đ°Ņ‚Đĩ ĐēĐžĐģĐĩĐēŅ†Đ¸ŅŅ‚Đ° ŅĐ¸.", "no_favorites_message": "ДобавĐĩŅ‚Đĩ в ĐģŅŽĐąĐ¸Đŧи, Са да ĐŊаĐŧĐ¸Ņ€Đ°Ņ‚Đĩ ĐąŅŠŅ€ĐˇĐž ĐŊаК-Đ´ĐžĐąŅ€Đ¸Ņ‚Đĩ ŅĐ¸ ҁĐŊиĐŧĐēи и видĐĩĐžĐēĐģиĐŋОвĐĩ", "no_libraries_message": "ĐĄŅŠĐˇĐ´Đ°ĐšŅ‚Đĩ Đ˛ŅŠĐŊ҈ĐŊа йийĐģĐ¸ĐžŅ‚ĐĩĐēа Са да Ņ€Đ°ĐˇĐŗĐģĐĩĐļĐ´Đ°Ņ‚Đĩ ҁĐŊиĐŧĐēи и видĐĩĐžĐēĐģиĐŋОвĐĩ", + "no_local_assets_found": "НĐĩ Đĩ ĐŊаĐŧĐĩŅ€ĐĩĐŊ ĐģĐžĐēаĐģĐĩĐŊ ОйĐĩĐēŅ‚ ҁ Ņ‚Đ°Đēава ĐēĐžĐŊŅ‚Ņ€ĐžĐģĐŊа ҁ҃Đŧа", "no_locked_photos_message": "ĐĄĐŊиĐŧĐēĐ¸Ņ‚Đĩ и видĐĩĐ°Ņ‚Đ° в СаĐēĐģŅŽŅ‡ĐĩĐŊĐ°Ņ‚Đ° ĐŋаĐŋĐēа ŅĐ° ҁĐēŅ€Đ¸Ņ‚Đ¸ и ĐŊĐĩ ҁĐĩ ĐŋĐžĐēĐ°ĐˇĐ˛Đ°Ņ‚ ĐŋŅ€Đ¸ Ņ€Đ°ĐˇĐŗĐģĐĩĐļдаĐŊĐĩ ĐŊа йийĐģĐ¸ĐžŅ‚ĐĩĐēĐ°Ņ‚Đ°.", "no_name": "БĐĩС иĐŧĐĩ", "no_notifications": "ĐŅĐŧа иСвĐĩŅŅ‚Đ¸Ņ", "no_people_found": "НĐĩ ŅĐ° ĐŊаĐŧĐĩŅ€ĐĩĐŊи ŅŅŠĐžŅ‚Đ˛ĐĩŅ‚ŅŅ‚Đ˛Đ°Ņ‰Đ¸ Ņ…ĐžŅ€Đ°", "no_places": "ĐŅĐŧа ĐŧĐĩŅŅ‚Đ°", + "no_remote_assets_found": "НĐĩ Đĩ ĐŊаĐŧĐĩŅ€ĐĩĐŊ ОйĐĩĐēŅ‚ ĐŊа ŅŅŠŅ€Đ˛ŅŠŅ€Đ° ҁ Ņ‚Đ°Đēава ĐēĐžĐŊŅ‚Ņ€ĐžĐģĐŊа ҁ҃Đŧа", "no_results": "ĐŅĐŧа Ņ€ĐĩĐˇŅƒĐģŅ‚Đ°Ņ‚Đ¸", "no_results_description": "ОĐŋĐ¸Ņ‚Đ°ĐšŅ‚Đĩ ҁҊҁ ŅĐ¸ĐŊĐžĐŊиĐŧ иĐģи ĐŋĐž-ĐžĐąŅ‰Đ° ĐēĐģŅŽŅ‡ĐžĐ˛Đ° Đ´ŅƒĐŧа", "no_shared_albums_message": "ĐĄŅŠĐˇĐ´Đ°ĐšŅ‚Đĩ аĐģĐąŅƒĐŧ, Са да ҁĐŋОдĐĩĐģŅŅ‚Đĩ ҁĐŊиĐŧĐēи и видĐĩĐžĐēĐģиĐŋОвĐĩ ҁ Ņ…ĐžŅ€Đ°Ņ‚Đ° в ĐŧŅ€ĐĩĐļĐ°Ņ‚Đ° ŅĐ¸", "no_uploads_in_progress": "ĐŅĐŧа ĐēĐ°Ņ‡Đ˛Đ°ĐŊĐĩ в ĐŧĐžĐŧĐĩĐŊŅ‚Đ°", + "not_available": "НĐĩĐŊаĐģĐ¸Ņ‡ĐŊĐž", "not_in_any_album": "НĐĩ Đĩ в ĐŊиĐēОК аĐģĐąŅƒĐŧ", "not_selected": "НĐĩ Đĩ Đ¸ĐˇĐąŅ€Đ°ĐŊĐž", "note_apply_storage_label_to_previously_uploaded assets": "ЗабĐĩĐģĐĩĐļĐēа: За да ĐŋŅ€Đ¸ĐģĐžĐļĐ¸Ņ‚Đĩ ĐĩŅ‚Đ¸ĐēĐĩŅ‚Đ° Са ŅŅŠŅ…Ņ€Đ°ĐŊĐĩĐŊиĐĩ ĐēҊĐŧ ĐŋŅ€ĐĩĐ´Đ˛Đ°Ņ€Đ¸Ņ‚ĐĩĐģĐŊĐž ĐēĐ°Ņ‡ĐĩĐŊи аĐēŅ‚Đ¸Đ˛Đ¸, ŅŅ‚Đ°Ņ€Ņ‚Đ¸Ņ€Đ°ĐšŅ‚Đĩ", @@ -1417,6 +1442,8 @@ "open_the_search_filters": "ĐžŅ‚Đ˛Đ°Ņ€Đ¸ Ņ„Đ¸ĐģŅ‚Ņ€Đ¸Ņ‚Đĩ Са Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩ", "options": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи", "or": "иĐģи", + "organize_into_albums": "Organitzar per àlbums", + "organize_into_albums_description": "Posar les fotos existents dins dels àlbums fent servir la configuraciÃŗ de sincronitzaciÃŗ", "organize_your_library": "ĐžŅ€ĐŗĐ°ĐŊĐ¸ĐˇĐ¸Ņ€Đ°ĐŊĐĩ ĐŊа Đ˛Đ°ŅˆĐ°Ņ‚Đ° йийĐģĐ¸ĐžŅ‚ĐĩĐēа", "original": "ĐžŅ€Đ¸ĐŗĐ¸ĐŊаĐģ", "other": "Đ”Ņ€ŅƒĐŗĐ¸", @@ -1502,6 +1529,7 @@ "port": "ĐŸĐžŅ€Ņ‚", "preferences_settings_subtitle": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ĐŊа ĐŋŅ€ĐĩĐ´ĐŋĐžŅ‡Đ¸Ņ‚Đ°ĐŊĐ¸ŅŅ‚Đ° ĐŊа ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩŅ‚Đž", "preferences_settings_title": "ĐŸŅ€ĐĩĐ´ĐŋĐžŅ‡Đ¸Ņ‚Đ°ĐŊĐ¸Ņ", + "preparing": "ĐŸĐžĐ´ĐŗĐžŅ‚ĐžĐ˛Đēа", "preset": "ШайĐģĐžĐŊ", "preview": "ĐŸŅ€ĐĩĐŗĐģĐĩди", "previous": "ĐŸŅ€ĐĩĐ´Đ¸ŅˆĐŊĐž", @@ -1514,13 +1542,13 @@ "privacy": "ПовĐĩŅ€Đ¸Ņ‚ĐĩĐģĐŊĐžŅŅ‚", "profile": "ĐŸŅ€ĐžŅ„Đ¸Đģ", "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_readonly_mode": "Đ ĐĩĐļиĐŧа ŅĐ°ĐŧĐž Са ҇ĐĩŅ‚ĐĩĐŊĐĩ Đĩ аĐēŅ‚Đ¸Đ˛Đ¸Ņ€Đ°ĐŊ. ĐĄ двОĐĩĐŊ ĐēĐģиĐē Đ˛ŅŠŅ€Ņ…Ņƒ ĐēĐ°Ņ€Ņ‚Đ¸ĐēĐ°Ņ‚Đ°-Đ°Đ˛Đ°Ņ‚Đ°Ņ€ ĐŊа ĐŋĐžŅ‚Ņ€ĐĩĐąĐ¸Ņ‚ĐĩĐģŅ ҉Đĩ Đ´ĐĩаĐēŅ‚Đ¸Đ˛Đ¸Ņ€Đ°Ņ‚Đĩ ŅĐ°ĐŧĐž Са ҇ĐĩŅ‚ĐĩĐŊĐĩ.", - "profile_drawer_server_out_of_date_major": "ВĐĩŅ€ŅĐ¸ŅŅ‚Đ° ĐŊа ŅŅŠŅ€Đ˛ŅŠŅ€Đ° Đĩ ĐžŅŅ‚Đ°Ņ€ŅĐģа. МоĐģŅ, аĐēŅ‚ŅƒĐ°ĐģĐ¸ĐˇĐ¸Ņ€Đ°Đš ĐŋĐžĐŊĐĩ Đ´Đž ĐŋĐžŅĐģĐĩĐ´ĐŊĐ°Ņ‚Đ° ĐŗĐģавĐŊа вĐĩŅ€ŅĐ¸Ņ.", - "profile_drawer_server_out_of_date_minor": "ВĐĩŅ€ŅĐ¸ŅŅ‚Đ° ĐŊа ŅŅŠŅ€Đ˛ŅŠŅ€Đ° Đĩ ĐžŅŅ‚Đ°Ņ€ŅĐģа. МоĐģŅ, аĐēŅ‚ŅƒĐ°ĐģĐ¸ĐˇĐ¸Ņ€Đ°Đš Đ´Đž ĐŋĐžŅĐģĐĩĐ´ĐŊĐ°Ņ‚Đ° вĐĩŅ€ŅĐ¸Ņ.", + "profile_drawer_readonly_mode": "Đ ĐĩĐļиĐŧа ŅĐ°ĐŧĐž Са ҇ĐĩŅ‚ĐĩĐŊĐĩ Đĩ аĐēŅ‚Đ¸Đ˛Đ¸Ņ€Đ°ĐŊ. ĐĄ Đ´ŅŠĐģĐŗĐž ĐŊĐ°Ņ‚Đ¸ŅĐēаĐŊĐĩ Đ˛ŅŠŅ€Ņ…Ņƒ ĐēĐ°Ņ€Ņ‚Đ¸ĐēĐ°Ņ‚Đ°-Đ°Đ˛Đ°Ņ‚Đ°Ņ€ ĐŊа ĐŋĐžŅ‚Ņ€ĐĩĐąĐ¸Ņ‚ĐĩĐģŅ ҉Đĩ Đ´ĐĩаĐēŅ‚Đ¸Đ˛Đ¸Ņ€Đ°Ņ‚Đĩ ŅĐ°ĐŧĐž Са ҇ĐĩŅ‚ĐĩĐŊĐĩ.", + "profile_drawer_server_out_of_date_major": "ВĐĩŅ€ŅĐ¸ŅŅ‚Đ° ĐŊа ŅŅŠŅ€Đ˛ŅŠŅ€Đ° Đĩ ĐžŅŅ‚Đ°Ņ€ŅĐģа. МоĐģŅ, аĐēŅ‚ŅƒĐ°ĐģĐ¸ĐˇĐ¸Ņ€Đ°ĐšŅ‚Đĩ ĐŋĐžĐŊĐĩ Đ´Đž ĐŋĐžŅĐģĐĩĐ´ĐŊĐ°Ņ‚Đ° ĐŗĐģавĐŊа вĐĩŅ€ŅĐ¸Ņ.", + "profile_drawer_server_out_of_date_minor": "ВĐĩŅ€ŅĐ¸ŅŅ‚Đ° ĐŊа ŅŅŠŅ€Đ˛ŅŠŅ€Đ° Đĩ ĐžŅŅ‚Đ°Ņ€ŅĐģа. МоĐģŅ, аĐēŅ‚ŅƒĐ°ĐģĐ¸ĐˇĐ¸Ņ€Đ°ĐšŅ‚Đĩ Đ´Đž ĐŋĐžŅĐģĐĩĐ´ĐŊĐ°Ņ‚Đ° вĐĩŅ€ŅĐ¸Ņ.", "profile_image_of_user": "ĐŸŅ€ĐžŅ„Đ¸ĐģĐŊа ҁĐŊиĐŧĐēа ĐŊа {user}", "profile_picture_set": "ĐŸŅ€ĐžŅ„Đ¸ĐģĐŊĐ°Ņ‚Đ° ҁĐŊиĐŧĐēа Đĩ ҁĐģĐžĐļĐĩĐŊа.", "public_album": "ĐŸŅƒĐąĐģĐ¸Ņ‡ĐĩĐŊ аĐģĐąŅƒĐŧ", @@ -1557,6 +1585,7 @@ "purchase_server_description_2": "ĐĄŅ‚Đ°Ņ‚ŅƒŅ ĐŊа ĐŋĐžĐ´Đ´Ņ€ŅŠĐļĐŊиĐē", "purchase_server_title": "ĐĄŅŠŅ€Đ˛ŅŠŅ€", "purchase_settings_server_activated": "ĐŸŅ€ĐžĐ´ŅƒĐēŅ‚ĐžĐ˛Đ¸ŅŅ‚ ĐēĐģŅŽŅ‡ ĐŊа ŅŅŠŅ€Đ˛ŅŠŅ€Đ° ҁĐĩ ҃ĐŋŅ€Đ°Đ˛ĐģŅĐ˛Đ° ĐžŅ‚ адĐŧиĐŊĐ¸ŅŅ‚Ņ€Đ°Ņ‚ĐžŅ€Đ°", + "query_asset_id": "Buscar item per ID", "queue_status": "В ĐžĐŋĐ°ŅˆĐēа {count} ĐžŅ‚ {total}", "rating": "ĐžŅ†ĐĩĐŊĐēа ҁҊҁ СвĐĩСди", "rating_clear": "Đ˜ĐˇŅ‡Đ¸ŅŅ‚Đ¸ ĐžŅ†ĐĩĐŊĐēĐ°Ņ‚Đ°", @@ -1566,6 +1595,7 @@ "read_changelog": "ĐŸŅ€ĐžŅ‡ĐĩŅ‚Đ¸ ĐŋŅ€ĐžĐŧĐĩĐŊĐ¸Ņ‚Đĩ", "readonly_mode_disabled": "Đ ĐĩĐļиĐŧа ŅĐ°ĐŧĐž Са ҇ĐĩŅ‚ĐĩĐŊĐĩ Đĩ Đ´ĐĩаĐēŅ‚Đ¸Đ˛Đ¸Ņ€Đ°ĐŊ", "readonly_mode_enabled": "Đ ĐĩĐļиĐŧа ŅĐ°ĐŧĐž Са ҇ĐĩŅ‚ĐĩĐŊĐĩ Đĩ аĐēŅ‚Đ¸Đ˛Đ¸Ņ€Đ°ĐŊ", + "ready_for_upload": "Đ“ĐžŅ‚ĐžĐ˛Đž Са ĐēĐ°Ņ‡Đ˛Đ°ĐŊĐĩ", "reassign": "ĐŸŅ€ĐĩĐŊаСĐŊĐ°Ņ‡Đ°Đ˛Đ°ĐŊĐĩ", "reassigned_assets_to_existing_person": "ĐŸŅ€ĐĩĐŊаСĐŊĐ°Ņ‡ĐĩĐŊи {count, plural, one {# ĐĩĐģĐĩĐŧĐĩĐŊŅ‚} other {# ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ°}} ĐŊа {name, select, null {ŅŅŠŅ‰ĐĩŅŅ‚Đ˛ŅƒĐ˛Đ°Ņ‰ Ņ‡ĐžĐ˛ĐĩĐē} other {{name}}}", "reassigned_assets_to_new_person": "ĐŸŅ€ĐĩĐŊаСĐŊĐ°Ņ‡ĐĩĐŊи {count, plural, one {# ĐĩĐģĐĩĐŧĐĩĐŊŅ‚} other {# ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ°}} ĐŊа ĐŊОв Ņ‡ĐžĐ˛ĐĩĐē", @@ -1590,6 +1620,7 @@ "regenerating_thumbnails": "ĐŸŅ€ĐĩŅŅŠĐˇĐ´Đ°Đ˛Đ°ĐŊĐĩ ĐŊа ĐŧиĐŊĐ¸Đ°Ņ‚ŅŽŅ€Đ¸Ņ‚Đĩ", "remote": "На ŅŅŠŅ€Đ˛ŅŠŅ€Đ°", "remote_assets": "ОбĐĩĐēŅ‚Đ¸ ĐŊа ŅŅŠŅ€Đ˛ŅŠŅ€Đ°", + "remote_media_summary": "ĐžĐąĐžĐąŅ‰ĐĩĐŊиĐĩ ĐŊа ĐŧĐĩдиКĐŊĐ¸Ņ‚Đĩ Ņ„Đ°ĐšĐģОвĐĩ ĐŊа ŅŅŠŅ€Đ˛ŅŠŅ€Đ°", "remove": "ĐŸŅ€ĐĩĐŧĐ°Ņ…ĐŊи", "remove_assets_album_confirmation": "ĐĄĐ¸ĐŗŅƒŅ€ĐŊи Đģи ҁ҂Đĩ, ҇Đĩ Đ¸ŅĐēĐ°Ņ‚Đĩ да ĐŋŅ€ĐĩĐŧĐ°Ņ…ĐŊĐĩŅ‚Đĩ {count, plural, one {# ĐĩĐģĐĩĐŧĐĩĐŊŅ‚} other {# ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ°}} ĐžŅ‚ аĐģĐąŅƒĐŧа?", "remove_assets_shared_link_confirmation": "ĐĄĐ¸ĐŗŅƒŅ€ĐŊи Đģи ҁ҂Đĩ, ҇Đĩ Đ¸ŅĐēĐ°Ņ‚Đĩ да ĐŋŅ€ĐĩĐŧĐ°Ņ…ĐŊĐĩŅ‚Đĩ {count, plural, one {# ĐĩĐģĐĩĐŧĐĩĐŊŅ‚} other {# ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ°}} ĐžŅ‚ Ņ‚ĐžĐˇĐ¸ ҁĐŋĐžĐĩĐ´ĐĩĐģĐĩĐŊ ĐģиĐŊĐē?", @@ -1642,6 +1673,7 @@ "restore_user": "Đ’ŅŠĐˇŅŅ‚Đ°ĐŊОви ĐŋĐžŅ‚Ņ€ĐĩĐąĐ¸Ņ‚ĐĩĐģ", "restored_asset": "Đ’ŅŠĐˇŅŅ‚Đ°ĐŊОвĐĩĐŊ ĐĩĐģĐĩĐŧĐĩĐŊŅ‚", "resume": "ĐŸŅ€ĐžĐ´ŅŠĐģĐļаваĐŊĐĩ", + "resume_paused_jobs": "ĐŸŅ€ĐžĐ´ŅŠĐģĐļи иСĐŋҊĐģĐŊĐĩĐŊиĐĩŅ‚Đž ĐŊа {count, plural, one {# ĐˇĐ°Đ´Đ°Ņ‡Đ°} other {# ĐˇĐ°Đ´Đ°Ņ‡Đ¸}}", "retry_upload": "ОĐŋĐ¸Ņ‚Đ°Đš ĐēĐ°Ņ‡Đ˛Đ°ĐŊĐĩŅ‚Đž ĐžŅ‚ĐŊОвО", "review_duplicates": "Đ Đ°ĐˇĐŗĐģĐĩдаК Đ´ŅƒĐąĐģиĐēĐ°Ņ‚Đ¸Ņ‚Đĩ", "review_large_files": "ĐŸŅ€ĐĩĐŗĐģĐĩĐ´ ĐŊа ĐŗĐžĐģĐĩĐŧи Ņ„Đ°ĐšĐģОвĐĩ", @@ -1735,7 +1767,7 @@ "select_user_for_sharing_page_err_album": "ĐĄŅŠĐˇĐ´Đ°Đ˛Đ°ĐŊĐĩŅ‚Đž ĐŊа аĐģĐąŅƒĐŧ ĐŊĐĩ ĐąĐĩ ҃ҁĐŋĐĩ҈ĐŊĐž", "selected": "Đ˜ĐˇĐąŅ€Đ°ĐŊĐž", "selected_count": "{count, plural, other {# Đ¸ĐˇĐąŅ€Đ°ĐŊи}}", - "selected_gps_coordinates": "Đ¸ĐˇĐąŅ€Đ°ĐŊи GPS ĐēĐžĐžŅ€Đ´Đ¸ĐŊĐ°Ņ‚Đ¸", + "selected_gps_coordinates": "Đ˜ĐˇĐąŅ€Đ°ĐŊи GPS ĐēĐžĐžŅ€Đ´Đ¸ĐŊĐ°Ņ‚Đ¸", "send_message": "ИСĐŋŅ€Đ°Ņ‚ĐĩŅ‚Đĩ ŅŅŠĐžĐąŅ‰ĐĩĐŊиĐĩ", "send_welcome_email": "ИСĐŋŅ€Đ°Ņ‚ĐĩŅ‚Đĩ иĐŧĐĩĐšĐģ Са Đ´ĐžĐąŅ€Đĩ Đ´ĐžŅˆĐģи", "server_endpoint": "ĐĐ´Ņ€Đĩҁ ĐŊа ŅŅŠŅ€Đ˛ŅŠŅ€Đ°", @@ -1846,10 +1878,8 @@ "shift_to_permanent_delete": "ĐĐ°Ņ‚Đ¸ŅĐŊĐĩŅ‚Đĩ ⇧, Са да Đ¸ĐˇŅ‚Ņ€Đ¸ĐĩŅ‚Đĩ СавиĐŊĐ°ĐŗĐ¸ ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ°", "show_album_options": "ПоĐēаСваĐŊĐĩ ĐžĐŋŅ†Đ¸Đ¸ Са аĐģĐąŅƒĐŧ", "show_albums": "ПоĐēаĐļи аĐģĐąŅƒĐŧи", - "show_all_assets": "ПоĐēаĐļи Đ˛ŅĐ¸Ņ‡ĐēĐž", "show_all_people": "ПоĐēаĐļи Đ˛ŅĐ¸Ņ‡Đēи Ņ…ĐžŅ€Đ°", "show_and_hide_people": "ПоĐēаСваĐŊĐĩ и ҁĐēŅ€Đ¸Đ˛Đ°ĐŊĐĩ ĐŊа Ņ…ĐžŅ€Đ°", - "show_assets_without_location": "ПоĐēаĐļи ОйĐĩĐēŅ‚Đ¸ ĐąĐĩС ĐēĐžĐžŅ€Đ´Đ¸ĐŊĐ°Ņ‚Đ¸", "show_file_location": "ПоĐēаĐļи ĐŧĐĩŅŅ‚ĐžĐŋĐžĐģĐžĐļĐĩĐŊиĐĩŅ‚Đž ĐŊа Ņ„Đ°ĐšĐģа", "show_gallery": "ПоĐēаĐļи ĐŗĐ°ĐģĐĩŅ€Đ¸Ņ", "show_hidden_people": "ПоĐēаСваĐŊĐĩ ĐŊа ҁĐēŅ€Đ¸Ņ‚Đ¸Ņ‚Đĩ Ņ…ĐžŅ€Đ°", @@ -1866,6 +1896,7 @@ "show_slideshow_transition": "ПоĐēаĐļи ĐŋŅ€ĐĩŅ…ĐžĐ´Đ° ĐŊа ҁĐģĐ°ĐšĐ´ŅˆĐžŅƒŅ‚Đž", "show_supporter_badge": "ЗĐŊĐ°Ņ‡Đēа ĐŋĐžĐ´Đ´Ņ€ŅŠĐļĐŊиĐē", "show_supporter_badge_description": "ПоĐēаĐļи СĐŊĐ°Ņ‡Đēа ĐŋĐžĐ´Đ´Ņ€ŅŠĐļĐŊиĐē", + "show_text_search_menu": "ПоĐēаĐļи ĐŧĐĩĐŊŅŽŅ‚Đž Са Ņ‚ŅŠŅ€ŅĐĩĐŊĐĩ ĐŊа Ņ‚ĐĩĐēҁ҂", "shuffle": "Đ Đ°ĐˇĐąŅŠŅ€ĐēваĐŊĐĩ", "sidebar": "ĐĄŅ‚Ņ€Đ°ĐŊĐ¸Ņ‡ĐŊа ĐģĐĩĐŊŅ‚Đ°", "sidebar_display_description": "ПоĐēаСваĐŊĐĩ ĐŊа Đ˛Ņ€ŅŠĐˇĐēа ĐēҊĐŧ Đ¸ĐˇĐŗĐģĐĩда в ŅŅ‚Ņ€Đ°ĐŊĐ¸Ņ‡ĐŊĐ°Ņ‚Đ° ĐģĐĩĐŊŅ‚Đ°", @@ -1896,6 +1927,7 @@ "stacktrace": "ĐĄĐģĐĩда ĐŊа ŅŅŠĐąŅ€Đ°ĐŊĐ¸Ņ‚Đĩ", "start": "ĐĄŅ‚Đ°Ņ€Ņ‚", "start_date": "ĐĐ°Ņ‡Đ°ĐģĐŊа Đ´Đ°Ņ‚Đ°", + "start_date_before_end_date": "ĐĐ°Ņ‡Đ°ĐģĐŊĐ°Ņ‚Đ° Đ´Đ°Ņ‚Đ° Ņ‚Ņ€ŅĐąĐ˛Đ° да ĐąŅŠĐ´Đĩ ĐŋŅ€Đĩди ĐēŅ€Đ°ĐšĐŊĐ°Ņ‚Đ° Đ´Đ°Ņ‚Đ°", "state": "ĐŠĐ°Ņ‚", "status": "ĐĄŅ‚Đ°Ņ‚ŅƒŅ", "stop_casting": "ĐĄĐŋŅ€Đ¸ ĐŋŅ€ĐĩдаваĐŊĐĩŅ‚Đž", @@ -1920,6 +1952,8 @@ "sync_albums_manual_subtitle": "ХиĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ¸Ņ€Đ°Đš Đ˛ŅĐ¸Ņ‡Đēи ĐˇĐ°Ņ€ĐĩĐ´ĐĩĐŊи видĐĩа и ҁĐŊиĐŧĐēи в Đ¸ĐˇĐąŅ€Đ°ĐŊĐ¸Ņ‚Đĩ Đ°Ņ€Ņ…Đ¸Đ˛ĐŊи аĐģĐąŅƒĐŧи", "sync_local": "ЛоĐēаĐģĐŊа ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Ņ", "sync_remote": "ХиĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Ņ ҁҊҁ ŅŅŠŅ€Đ˛ŅŠŅ€Đ°", + "sync_status": "ĐĄŅŠŅŅ‚ĐžŅĐŊиĐĩ ĐŊа ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸ŅŅ‚Đ°", + "sync_status_subtitle": "ĐŸŅ€ĐĩĐŗĐģĐĩĐ´ и ҃ĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ĐŊа ŅĐ¸ŅŅ‚ĐĩĐŧĐ°Ņ‚Đ° Са ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Ņ", "sync_upload_album_setting_subtitle": "ĐĄŅŠĐˇĐ´Đ°Đ˛Đ°ĐšŅ‚Đĩ и ĐˇĐ°Ņ€ĐĩĐļĐ´Đ°ĐšŅ‚Đĩ ҁĐŊиĐŧĐēи и видĐĩа в Đ¸ĐˇĐąŅ€Đ°ĐŊи аĐģĐąŅƒĐŧи в Immich", "tag": "ĐĸĐ°Đŗ", "tag_assets": "ĐĸĐ°ĐŗĐŊи ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸", @@ -1979,6 +2013,7 @@ "trash_page_select_assets_btn": "ИСйĐĩŅ€Đ¸ ОйĐĩĐēŅ‚Đ¸", "trash_page_title": "В ĐēĐžŅˆĐ° ({count})", "trashed_items_will_be_permanently_deleted_after": "Đ˜ĐˇŅ…Đ˛ŅŠŅ€ĐģĐĩĐŊĐ¸Ņ‚Đĩ в ĐēĐžŅˆŅ‡ĐĩŅ‚Đž ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ ҉Đĩ ĐąŅŠĐ´Đ°Ņ‚ Đ¸ĐˇŅ‚Ņ€Đ¸Ņ‚Đ¸ Са ĐŋĐžŅŅ‚ĐžŅĐŊĐŊĐž ҁĐģĐĩĐ´ {days, plural, one {# Đ´ĐĩĐŊ} other {# Đ´ĐŊи}}.", + "troubleshoot": "ĐžŅ‚ŅŅ‚Ņ€Đ°ĐŊŅĐ˛Đ°ĐŊĐĩ ĐŊа ĐŋŅ€ĐžĐąĐģĐĩĐŧи", "type": "ĐĸиĐŋ", "unable_to_change_pin_code": "НĐĩĐ˛ŅŠĐˇĐŧĐžĐļĐŊа ĐŋŅ€ĐžĐŧŅĐŊа ĐŊа PIN ĐēОда", "unable_to_setup_pin_code": "НĐĩ҃ҁĐŋĐĩ҈ĐŊĐž СадаваĐŊĐĩ ĐŊа PIN ĐēОда", @@ -2034,7 +2069,6 @@ "use_biometric": "ИСĐŋĐžĐģСваК йиОĐŧĐĩŅ‚Ņ€Đ¸Ņ", "use_current_connection": "иСĐŋĐžĐģСваК Ņ‚ĐĩĐēŅƒŅ‰Đ°Ņ‚Đ° Đ˛Ņ€ŅŠĐˇĐēа", "use_custom_date_range": "ИСĐŋĐžĐģĐˇĐ˛Đ°ĐšŅ‚Đĩ ŅĐžĐąŅŅ‚Đ˛ĐĩĐŊ диаĐŋаСОĐŊ ĐžŅ‚ Đ´Đ°Ņ‚Đ¸ вĐŧĐĩŅŅ‚Đž Ņ‚ĐžĐ˛Đ°", - "use_this_location": "ИСйĐĩŅ€Đ¸ Ņ‚ĐžĐ˛Đ° ĐŧŅŅŅ‚Đž", "user": "ĐŸĐžŅ‚Ņ€ĐĩĐąĐ¸Ņ‚ĐĩĐģ", "user_has_been_deleted": "ĐĸОСи ĐŋĐžŅ‚Ņ€ĐĩĐąĐ¸Ņ‚ĐĩĐģ Đĩ ĐŋŅ€ĐĩĐŧĐ°Ņ…ĐŊĐ°Ņ‚.", "user_id": "ĐŸĐžŅ‚Ņ€ĐĩĐąĐ¸Ņ‚ĐĩĐģ ИД", @@ -2077,6 +2111,7 @@ "view_next_asset": "ĐŸŅ€ĐĩĐŗĐģĐĩĐ´ ĐŊа ҁĐģĐĩĐ´Đ˛Đ°Ņ‰Đ¸Ņ Ņ„Đ°ĐšĐģ", "view_previous_asset": "ĐŸŅ€ĐĩĐŗĐģĐĩĐ´ ĐŊа ĐŋŅ€ĐĩĐ´Đ¸ŅˆĐŊĐ¸Ņ Ņ„Đ°ĐšĐģ", "view_qr_code": "ВиĐļ QR ĐēОда", + "view_similar_photos": "ВиĐļ ĐŋОдОйĐŊи ҁĐŊиĐŧĐēи", "view_stack": "ПоĐēаĐļи в ҁ҂ĐĩĐē", "view_user": "ВиĐļ ĐŋĐžŅ‚Ņ€ĐĩĐąĐ¸Ņ‚ĐĩĐģŅ", "viewer_remove_from_stack": "ĐŸŅ€ĐĩĐŧĐ°Ņ…Đ˛Đ°ĐŊĐĩ ĐžŅ‚ ĐžĐŋĐ°ŅˆĐēĐ°Ņ‚Đ°", @@ -2095,5 +2130,6 @@ "yes": "Да", "you_dont_have_any_shared_links": "ĐŅĐŧĐ°Ņ‚Đĩ ҁĐŋОдĐĩĐģĐĩĐŊи Đ˛Ņ€ŅŠĐˇĐēи", "your_wifi_name": "Đ’Đ°ŅˆĐ°Ņ‚Đ° Wi-Fi ĐŧŅ€ĐĩĐļа", - "zoom_image": "ĐŖĐ˛ĐĩĐģĐ¸Ņ‡Đ°Đ˛Đ°ĐŊĐĩ ĐŊа Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиĐĩŅ‚Đž" + "zoom_image": "ĐŖĐ˛ĐĩĐģĐ¸Ņ‡Đ°Đ˛Đ°ĐŊĐĩ ĐŊа Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиĐĩŅ‚Đž", + "zoom_to_bounds": "ĐŸŅ€Đ¸ĐąĐģиĐļи Đ´Đž ŅŅŠĐąĐ¸Ņ€Đ°ĐŊĐĩ в ĐŗŅ€Đ°ĐŊĐ¸Ņ†Đ¸Ņ‚Đĩ" } diff --git a/i18n/bn.json b/i18n/bn.json index 004b584d3c..813aadea7e 100644 --- a/i18n/bn.json +++ b/i18n/bn.json @@ -28,6 +28,7 @@ "add_to_album": "āĻāϞāĻŦāĻžāĻŽ āĻ āϝ⧋āĻ— āĻ•āϰ⧁āύ", "add_to_album_bottom_sheet_added": "{album} āĻ āϝ⧋āĻ— āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇", "add_to_album_bottom_sheet_already_exists": "{album} āĻ āφāϗ⧇ āĻĨ⧇āϕ⧇āχ āφāϛ⧇", + "add_to_album_bottom_sheet_some_local_assets": "āĻ•āĻŋāϛ⧁ āĻ¸ā§āĻĨāĻžāύ⧀āϝāĻŧ āĻ›āĻŦāĻŋ āĻŦāĻž āĻ­āĻŋāĻĄāĻŋāĻ“ āĻ…ā§āϝāĻžāϞāĻŦāĻžāĻŽā§‡ āϝ⧋āĻ— āĻ•āϰāĻž āϝāĻžāϝāĻŧāύāĻŋ", "add_to_album_toggle": "{album} - āĻāϰ āύāĻŋāĻ°ā§āĻŦāĻžāϚāύ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ āĻ•āϰ⧁āύ", "add_to_albums": "āĻ…ā§āϝāĻžāϞāĻŦāĻžāĻŽā§‡ āϝ⧋āĻ— āĻ•āϰ⧁āύ", "add_to_albums_count": "āĻ…ā§āϝāĻžāϞāĻŦāĻžāĻŽā§‡ āϝ⧋āĻ— āĻ•āϰ⧁āύ ({count})", @@ -123,6 +124,11 @@ "logging_enable_description": "āϞāĻ—āĻŋāĻ‚ āĻāύāĻžāĻŦāϞ/āϏāĻ•ā§āώāĻŽ āĻ•āϰ⧁āύ", "logging_level_description": "āϏāĻ•ā§āϰāĻŋāϝāĻŧ āĻĨāĻžāĻ•āĻžāĻ•āĻžāϞ⧀āύ, āϕ⧋āύ āϞāĻ— āĻ¸ā§āϤāϰ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻšāĻŦ⧇āĨ¤", "logging_settings": "āϞāĻ—āĻŋāĻ‚", + "machine_learning_availability_checks": "āĻĒā§āϰāĻžāĻĒā§āϝāϤāĻž āĻĒāϰ⧀āĻ•ā§āώāĻž", + "machine_learning_availability_checks_description": "āĻ¸ā§āĻŦāϝāĻŧāĻ‚āĻ•ā§āϰāĻŋāϝāĻŧāĻ­āĻžāĻŦ⧇ āωāĻĒāϞāĻŦā§āϧ āĻŽā§‡āĻļāĻŋāύ āϞāĻžāĻ°ā§āύāĻŋāĻ‚ āϏāĻžāĻ°ā§āĻ­āĻžāϰāϗ⧁āϞāĻŋ āϏāύāĻžāĻ•ā§āϤ āĻ•āϰ⧁āύ āĻāĻŦāĻ‚ āĻĒāĻ›āĻ¨ā§āĻĻ āĻ•āϰ⧁āύ", + "machine_learning_availability_checks_enabled": "āĻĒā§āϰāĻžāĻĒā§āϝāϤāĻž āĻĒāϰ⧀āĻ•ā§āώāĻž āϏāĻ•ā§āώāĻŽ āĻ•āϰ⧁āύ", + "machine_learning_availability_checks_interval": "āĻšā§‡āĻ• āĻŦā§āϝāĻŦāϧāĻžāύ", + "machine_learning_availability_checks_interval_description": "āĻĒā§āϰāĻžāĻĒā§āϝāϤāĻž āĻĒāϰ⧀āĻ•ā§āώāĻžāϗ⧁āϞāĻŋāϰ āĻŽāĻ§ā§āϝ⧇ āĻŦā§āϝāĻŦāϧāĻžāύ āĻŽāĻŋāϞāĻŋāϏ⧇āϕ⧇āĻ¨ā§āĻĄā§‡", "machine_learning_clip_model": "CLIP āĻŽāĻĄā§‡āϞ", "machine_learning_clip_model_description": "āĻāĻ–āĻžāύ⧇ āϤāĻžāϞāĻŋāĻ•āĻžāϭ⧁āĻ•ā§āϤ āĻāĻ•āϟāĻŋ CLIP āĻŽāĻĄā§‡āϞ⧇āϰ āύāĻžāĻŽāĨ¤ āĻŽāύ⧇ āϰāĻžāĻ–āĻŦ⧇āύ, āĻŽāĻĄā§‡āϞ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ⧇āϰ āĻĒāϰ āϏāĻŦ āĻ›āĻŦāĻŋāϰ āϜāĻ¨ā§āϝ āĻ…āĻŦāĻļā§āϝāχ ‘Smart Search’ āĻ•āĻžāϜāϟāĻŋ āφāĻŦāĻžāϰ āϚāĻžāϞāĻžāϤ⧇ āĻšāĻŦ⧇āĨ¤", "machine_learning_duplicate_detection": "āĻĒ⧁āύāϰāĻžāĻŦ⧃āĻ¤ā§āϤāĻŋ āϏāύāĻžāĻ•ā§āϤāĻ•āϰāĻŖ", diff --git a/i18n/ca.json b/i18n/ca.json index 11b9157f56..cd55641f64 100644 --- a/i18n/ca.json +++ b/i18n/ca.json @@ -28,12 +28,14 @@ "add_to_album": "Afegir a un l'àlbum", "add_to_album_bottom_sheet_added": "Afegit a {album}", "add_to_album_bottom_sheet_already_exists": "Ja està a {album}", + "add_to_album_bottom_sheet_some_local_assets": "Alguns recursos locals no s'han pogut afegir a l'àlbum", "add_to_album_toggle": "Commutar selecciÃŗ de {album}", "add_to_albums": "Afegir als àlbums", "add_to_albums_count": "Afegir als àlbums ({count})", "add_to_shared_album": "Afegir a un àlbum compartit", + "add_upload_to_stack": "Afegeix la càrrega a la pila", "add_url": "Afegir URL", - "added_to_archive": "Afegit als arxivats", + "added_to_archive": "Afegir a l'arxiu", "added_to_favorites": "Afegit als preferits", "added_to_favorites_count": "{count, number} afegits als preferits", "admin": { @@ -84,10 +86,10 @@ "image_fullsize_enabled": "Activa la generaciÃŗ d'imatges a tamany complet", "image_fullsize_enabled_description": "Genera imatges a tamany complet per formats no compatibles amb la web. Quan \"Prefereix vista prèvia incrustada\" està activat, les vistes prèvies incrustades s'utilitzen directament sense conversiÃŗ. No afecta els formats compatibles amb la web com JPEG.", "image_fullsize_quality_description": "De 1 a 100, qualitat de l'imatge a tamany complet. Un valor mÊs alt Ês millor, perÃ˛ resulta en fitxers de major tamany.", - "image_fullsize_title": "ConfiguraciÃŗ d'imatges a tamany complet", + "image_fullsize_title": "ConfiguraciÃŗ de les imatges a tamany complet", "image_prefer_embedded_preview": "Prefereix vista prèvia incrustada", "image_prefer_embedded_preview_setting_description": "Empra vista prèvia incrustada en les fotografies RAW com a entrada per al processament d'imatge, quan sigui possible. Aquesta acciÃŗ pot produir colors mÊs acurats en algunes imatges, perÃ˛ la qualitat de la vista prèvia depèn de la càmera i la imatge pot tenir mÊs artefactes de compressiÃŗ.", - "image_prefer_wide_gamut": "Prefereix àmplia gamma", + "image_prefer_wide_gamut": "Prefereix la gamma àmplia", "image_prefer_wide_gamut_setting_description": "Uitlitza Display P3 per a les miniatures. AixÃ˛ preserva mÊs bÊ la vitalitat de les imatges amb espais de color àmplis, perÃ˛ les imatges es poden veure diferent en aparells antics amb una versiÃŗ antiga del navegador. Les imatges sRGB romandran com a sRGB per a evitar canvis de color.", "image_preview_description": "Imatge de mida mitjana amb metadades eliminades, que s'utilitza quan es visualitza un sol recurs i per a l'aprenentatge automàtic", "image_preview_quality_description": "Vista prèvia de la qualitat de l'1 al 100. MÊs alt Ês millor, perÃ˛ produeix fitxers mÊs grans i pot reduir la capacitat de resposta de l'aplicaciÃŗ. Establir un valor baix pot afectar la qualitat de l'aprenentatge automàtic.", @@ -95,11 +97,11 @@ "image_quality": "Qualitat", "image_resolution": "ResoluciÃŗ", "image_resolution_description": "Les resolucions mÊs altes poden conservar mÊs detalls perÃ˛ triguen mÊs a codificar-se, tenen mides de fitxer mÊs grans i poden reduir la capacitat de resposta de l'aplicaciÃŗ.", - "image_settings": "ConfiguraciÃŗ d'imatges", + "image_settings": "ConfiguraciÃŗ de les imatges", "image_settings_description": "Gestiona la qualitat i resoluciÃŗ de les imatges generades", "image_thumbnail_description": "Miniatura petita amb metadades eliminades, que s'utilitza quan es visualitzen grups de fotos com la línia de temps principal", "image_thumbnail_quality_description": "Qualitat de miniatura d'1 a 100. MÊs alt Ês millor, perÃ˛ produeix fitxers mÊs grans i pot reduir la capacitat de resposta de l'aplicaciÃŗ.", - "image_thumbnail_title": "ConfiguraciÃŗ de miniatures", + "image_thumbnail_title": "ConfiguraciÃŗ de les miniatures", "job_concurrency": "{job} simultàniament", "job_created": "Tasca creada", "job_not_concurrency_safe": "Aquesta tasca no Ês segura per a la conconcurrència.", @@ -123,6 +125,13 @@ "logging_enable_description": "Habilitar el registrament", "logging_level_description": "Quan està habilitat, quin nivell de registre es vol emprar.", "logging_settings": "Registre", + "machine_learning_availability_checks": "Comprovacions de disponibilitat", + "machine_learning_availability_checks_description": "Detectar i preferir automàticament els servidors d'aprenentatge automàtic disponibles", + "machine_learning_availability_checks_enabled": "Habilita les comprovacions de disponibilitat", + "machine_learning_availability_checks_interval": "Interval de comprovaciÃŗ", + "machine_learning_availability_checks_interval_description": "Interval en mil¡lisegons entre comprovacions de disponibilitat", + "machine_learning_availability_checks_timeout": "Temps d'espera de la sol¡licitud", + "machine_learning_availability_checks_timeout_description": "Temps d'espera en mil¡lisegons per a les comprovacions de disponibilitat", "machine_learning_clip_model": "Model CLIP", "machine_learning_clip_model_description": "El nom d'un model CLIP que apareix a aquí. Tingues en compte que has de tornar a executar la cerca intel¡ligent per a totes les imatges quan es canvia de model.", "machine_learning_duplicate_detection": "DetecciÃŗ de duplicats", @@ -387,8 +396,6 @@ "admin_password": "Contrasenya de l'administrador", "administration": "AdministraciÃŗ", "advanced": "Avançat", - "advanced_settings_beta_timeline_subtitle": "Prova la nova experiència de l'aplicaciÃŗ", - "advanced_settings_beta_timeline_title": "Cronologia beta", "advanced_settings_enable_alternate_media_filter_subtitle": "Feu servir aquesta opciÃŗ per filtrar els continguts multimèdia durant la sincronitzaciÃŗ segons criteris alternatius. NomÊs proveu-ho si teniu problemes amb l'aplicaciÃŗ per detectar tots els àlbums.", "advanced_settings_enable_alternate_media_filter_title": "Utilitza el filtre de sincronitzaciÃŗ d'àlbums de dispositius alternatius", "advanced_settings_log_level_title": "Nivell de registre: {level}", @@ -425,6 +432,7 @@ "album_remove_user_confirmation": "Esteu segurs que voleu eliminar {user}?", "album_search_not_found": "No s'ha trobat cap àlbum que coincideixi amb la teva cerca", "album_share_no_users": "Sembla que has compartit aquest àlbum amb tots els usuaris o no tens cap usuari amb qui compartir-ho.", + "album_summary": "Resum de l'àlbum", "album_updated": "Àlbum actualitzat", "album_updated_setting_description": "Rep una notificaciÃŗ per correu electrÃ˛nic quan un àlbum compartit tingui recursos nous", "album_user_left": "Surt de {album}", @@ -496,6 +504,8 @@ "asset_restored_successfully": "Element recuperat correctament", "asset_skipped": "Saltat", "asset_skipped_in_trash": "A la paperera", + "asset_trashed": "Recurs a la paperera", + "asset_troubleshoot": "DiagnÃ˛stic de l'element", "asset_uploaded": "Carregat", "asset_uploading": "S'està carregantâ€Ļ", "asset_viewer_settings_subtitle": "Gestiona la configuraciÃŗ del visualitzador de la galeria", @@ -529,8 +539,10 @@ "autoplay_slideshow": "Reprodueix automàticament les diapositives", "back": "Enrere", "back_close_deselect": "Tornar, tancar o anul¡lar la selecciÃŗ", + "background_backup_running_error": "La cÃ˛pia de seguretat en segon pla s'està executant actualment, no es pot iniciar la cÃ˛pia de seguretat manual", "background_location_permission": "Permís d'ubicaciÃŗ en segon pla", "background_location_permission_content": "Per canviar de xarxa quan s'executa en segon pla, Immich ha de *sempre* tenir accÊs a la ubicaciÃŗ precisa perquè l'aplicaciÃŗ pugui llegir el nom de la xarxa Wi-Fi", + "background_options": "Opcions en segon pla", "backup": "CÃ˛pia", "backup_album_selection_page_albums_device": "Àlbums al dispositiu ({count})", "backup_album_selection_page_albums_tap": "Un toc per incloure, doble toc per excloure", @@ -538,6 +550,7 @@ "backup_album_selection_page_select_albums": "Selecciona àlbums", "backup_album_selection_page_selection_info": "InformaciÃŗ de la selecciÃŗ", "backup_album_selection_page_total_assets": "Total d'elements Ãēnics", + "backup_albums_sync": "SincronitzaciÃŗ d'àlbums de cÃ˛pia de seguretat", "backup_all": "Tots", "backup_background_service_backup_failed_message": "No s'ha pogut copiar els elements. Tornant a intentarâ€Ļ", "backup_background_service_connection_failed_message": "No s'ha pogut connectar al servidor. Tornant a intentarâ€Ļ", @@ -587,6 +600,7 @@ "backup_controller_page_turn_on": "Activa la cÃ˛pia de seguretat", "backup_controller_page_uploading_file_info": "S'està pujant la informaciÃŗ del fitxer", "backup_err_only_album": "No es pot eliminar l'Ãēnic àlbum", + "backup_error_sync_failed": "SincronitzaciÃŗ malament, No es pot fer backup.", "backup_info_card_assets": "elements", "backup_manual_cancelled": "Cancel¡lat", "backup_manual_in_progress": "La pujada ja està en curs. Torneu-ho a provar mÊs tard", @@ -597,8 +611,6 @@ "backup_setting_subtitle": "Gestiona la configuraciÃŗ de càrrega en segon pla i en primer pla", "backup_settings_subtitle": "Administra la configuraciÃŗ de pujada", "backward": "Enrere", - "beta_sync": "Estat de la sincronitzaciÃŗ beta", - "beta_sync_subtitle": "Administra el nou sistema de sincronitzaciÃŗ", "biometric_auth_enabled": "AutentificaciÃŗ biomètrica activada", "biometric_locked_out": "Esteu bloquejats fora de l'autenticaciÃŗ biomètrica", "biometric_no_options": "No hi ha opcions biomètriques disponibles", @@ -656,6 +668,8 @@ "change_pin_code": "Canviar el codi PIN", "change_your_password": "Canvia la teva contrasenya", "changed_visibility_successfully": "Visibilitat canviada amb èxit", + "charging": "Carregant", + "charging_requirement_mobile_backup": "La cÃ˛pia de seguretat en segon pla requereix que el dispositiu estigui carregant", "check_corrupt_asset_backup": "Comprovar les cÃ˛pies de seguretat corruptes", "check_corrupt_asset_backup_button": "Realitzar comprovaciÃŗ", "check_corrupt_asset_backup_description": "Executeu aquesta comprovaciÃŗ nomÊs mitjançant Wi-Fi i un cop s'hagi fet una cÃ˛pia de seguretat de tots els actius. El procediment pot trigar uns minuts.", @@ -742,6 +756,7 @@ "create_user": "Crea un usuari", "created": "Creat", "created_at": "Creat", + "creating_linked_albums": "Creant àlbums enllaçats...", "crop": "Retalla", "curated_object_page_title": "Coses", "current_device": "Dispositiu actual", @@ -880,7 +895,7 @@ "empty_trash": "Buidar la paperera", "empty_trash_confirmation": "Esteu segur que voleu buidar la paperera? AixÃ˛ eliminarà tots els recursos a la paperera permanentment d'Immich.\nNo podeu desfer aquesta acciÃŗ!", "enable": "Activar", - "enable_backup": "Habilitar CÃ˛pia de Seguretat", + "enable_backup": "CÃ˛pia de Seguretat", "enable_biometric_auth_description": "Introduïu el codi PIN per a habilitar l'autenticaciÃŗ biomètrica", "enabled": "Activat", "end_date": "Data final", @@ -891,7 +906,9 @@ "error": "Error", "error_change_sort_album": "No s'ha pogut canviar l'ordre d'ordenaciÃŗ dels àlbums", "error_delete_face": "Error esborrant cara de les cares reconegudes", + "error_getting_places": "S'ha produït un error en obtenir els llocs", "error_loading_image": "Error carregant la imatge", + "error_loading_partners": "No s'han pogut carregar les parelles: {error}", "error_saving_image": "Error: {error}", "error_tag_face_bounding_box": "Error a l'etiquetar la cara - no s'han pogut obtenir les coordenades de l'àrea", "error_title": "Error - Quelcom ha anat malament", @@ -1056,6 +1073,7 @@ "favorites_page_no_favorites": "No s'han trobat preferits", "feature_photo_updated": "Foto destacada actualitzada", "features": "Característiques", + "features_in_development": "Funcions en desenvolupament", "features_setting_description": "Administrar les funcions de l'aplicaciÃŗ", "file_name": "Nom de l'arxiu", "file_name_or_extension": "Nom de l'arxiu o extensiÃŗ", @@ -1076,10 +1094,7 @@ "gcast_enabled": "Google Cast", "gcast_enabled_description": "Aquesta funciÃŗ carrega recursos externs de Google per funcionar.", "general": "General", - "geolocation_instruction_all_have_location": "Tots els actius d'aquesta data ja tenen dades d'ubicaciÃŗ. Prova de mostrar tots els actius o selecciona una data diferent", "geolocation_instruction_location": "Fes click en un element amb coordinades GPS per utilitzar la seva ubicaciÃŗ o selecciona una ubicaciÃŗ des del mapa", - "geolocation_instruction_no_date": "Seleccioneu una data per gestionar dades d'ubicaciÃŗ per a fotos i vídeos d'aquest dia", - "geolocation_instruction_no_photos": "Cap foto o vídeo trobats per a aquesta data. Selecciona una data diferent", "get_help": "Aconseguir ajuda", "get_wifiname_error": "No s'ha pogut obtenir el nom de la Wi-Fi. Assegureu-vos que heu concedit els permisos necessaris i que esteu connectat a una xarxa Wi-Fi", "getting_started": "Començant", @@ -1100,7 +1115,7 @@ "has_quota": "Quota", "hash_asset": "Hash del recurs", "hashed_assets": "Recursos amb hash", - "hashing": "Hashing", + "hashing": "Generant el hash", "header_settings_add_header_tip": "Afegeix Capçalera", "header_settings_field_validator_msg": "El valor no pot estar buit", "header_settings_header_name_input": "Nom de la capçalera", @@ -1206,7 +1221,7 @@ "library_options": "Opcions de biblioteca", "library_page_device_albums": "Àlbums al Dispositiu", "library_page_new_album": "Nou àlbum", - "library_page_sort_asset_count": "Nombre d'elements", + "library_page_sort_asset_count": "Quantitat d'elements", "library_page_sort_created": "Creat mÊs recentment", "library_page_sort_last_modified": "Darrera modificaciÃŗ", "library_page_sort_title": "Títol de l'àlbum", @@ -1223,6 +1238,7 @@ "local": "Local", "local_asset_cast_failed": "No es pot convertir un actiu que no s'ha penjat al servidor", "local_assets": "Recursos Locals", + "local_media_summary": "Resum de Mitjans Locals", "local_network": "Xarxa local", "local_network_sheet_info": "L'aplicaciÃŗ es connectarà al servidor mitjançant aquest URL quan utilitzeu la xarxa Wi-Fi especificada", "location_permission": "Permís d'ubicaciÃŗ", @@ -1234,6 +1250,7 @@ "location_picker_longitude_hint": "Introdueix aquí la longitud", "lock": "Bloqueja", "locked_folder": "Carpeta bloquejada", + "log_detail_title": "Detall de Registres", "log_out": "Tanca la sessiÃŗ", "log_out_all_devices": "Tanqueu la sessiÃŗ de tots els dispositius", "logged_in_as": "SessiÃŗ iniciada com a {user}", @@ -1264,6 +1281,7 @@ "login_password_changed_success": "La contrasenya s'ha canviat correctament", "logout_all_device_confirmation": "Esteu segur que voleu tancar la sessiÃŗ de tots els dispositius?", "logout_this_device_confirmation": "Esteu segur que voleu tancar la sessiÃŗ d'aquest dispositiu?", + "logs": "Registres", "longitude": "Longitud", "look": "Aspecte", "loop_videos": "Vídeos en bucle", @@ -1306,6 +1324,7 @@ "mark_as_read": "Marcar com ha llegit", "marked_all_as_read": "Marcat tot com a llegit", "matches": "Coincidències", + "matching_assets": "Recursos Coincidents", "media_type": "Tipus de mitjà", "memories": "Records", "memories_all_caught_up": "Posat al dia", @@ -1346,6 +1365,7 @@ "name_or_nickname": "Nom o sobrenom", "network_requirement_photos_upload": "Fes servir dades mÃ˛bils per a cÃ˛pies de seguretat de fotos", "network_requirement_videos_upload": "Fes servir dades mÃ˛bils per a cÃ˛pies de seguretat de videos", + "network_requirements": "Requeriments de Xarxa", "network_requirements_updated": "Han canviat els requeriments de xarxa, reiniciant la cua", "networking_settings": "Xarxes", "networking_subtitle": "Gestiona la configuraciÃŗ del endpoint del servidor", @@ -1356,6 +1376,7 @@ "new_person": "Persona nova", "new_pin_code": "Nou codi PIN", "new_pin_code_subtitle": "Aquesta Ês la primera vegada que accedeixes a la carpeta bloquejada. Crea una codi PIN i accedeix de manera segura a aquesta pàgina", + "new_timeline": "Nova Línia de Temps", "new_user_created": "Nou usuari creat", "new_version_available": "NOVA VERSIÓ DISPONIBLE", "newest_first": "El mÊs nou primer", @@ -1369,20 +1390,25 @@ "no_assets_message": "FEU CLIC PER PUJAR LA VOSTRA PRIMERA FOTO", "no_assets_to_show": "No hi ha elements per mostrar", "no_cast_devices_found": "No s'han trobat dispositius per transmetre", + "no_checksum_local": "Cap checksum disponible - no s'han pogut carregar els recursos locals", + "no_checksum_remote": "Cap checksum disponible - no s'ha pogut obtenir el recurs remot", "no_duplicates_found": "No s'han trobat duplicats.", "no_exif_info_available": "No hi ha informaciÃŗ d'exif disponible", "no_explore_results_message": "Penja mÊs fotos per explorar la teva col¡lecciÃŗ.", "no_favorites_message": "Afegiu preferits per trobar les millors fotos i vídeos a l'instant", "no_libraries_message": "Creeu una llibreria externa per veure les vostres fotos i vídeos", + "no_local_assets_found": "No s'ha trobat cap recurs local amb aquest checksum", "no_locked_photos_message": "Les fotos i vídeos d'aquesta carpeta estan ocultes, i no es mostraran a mesura que navegues o cerques a la teva biblioteca.", "no_name": "Sense nom", "no_notifications": "No hi ha notificacions", "no_people_found": "No s'han trobat coincidències de persones", "no_places": "No hi ha llocs", + "no_remote_assets_found": "No s'ha trobat cap recurs remot amb aquest checksum", "no_results": "Sense resultats", "no_results_description": "Proveu un sinÃ˛nim o una paraula clau mÊs general", "no_shared_albums_message": "Creeu un àlbum per compartir fotos i vídeos amb persones a la vostra xarxa", "no_uploads_in_progress": "Cap pujada en progrÊs", + "not_available": "N/A", "not_in_any_album": "En cap àlbum", "not_selected": "No seleccionat", "note_apply_storage_label_to_previously_uploaded assets": "Nota: per aplicar l'etiqueta d'emmagatzematge als actius penjats anteriorment, executeu el", @@ -1417,6 +1443,8 @@ "open_the_search_filters": "Obriu els filtres de cerca", "options": "Opcions", "or": "o", + "organize_into_albums": "Organitzar en àlbums", + "organize_into_albums_description": "Posar fotos existents en àlbums utilitzant la configuraciÃŗ de sincronitzaciÃŗ actual", "organize_your_library": "Organitzeu la llibreria", "original": "original", "other": "Altres", @@ -1502,6 +1530,7 @@ "port": "Port", "preferences_settings_subtitle": "Gestiona les preferències de l'aplicaciÃŗ", "preferences_settings_title": "Preferències", + "preparing": "Preparant", "preset": "Preestablert", "preview": "PrevisualitzaciÃŗ", "previous": "Anterior", @@ -1516,9 +1545,9 @@ "profile_drawer_app_logs": "Registres", "profile_drawer_client_out_of_date_major": "L'aplicaciÃŗ mÃ˛bil està desactualitzada. Si us plau, actualitzeu a l'Ãēltima versiÃŗ major.", "profile_drawer_client_out_of_date_minor": "L'aplicaciÃŗ mÃ˛bil està desactualitzada. Si us plau, actualitzeu a l'Ãēltima versiÃŗ menor.", - "profile_drawer_client_server_up_to_date": "El Client i el Servidor estan actualitzats", + "profile_drawer_client_server_up_to_date": "El client i el servidor estan actualitzats", "profile_drawer_github": "GitHub", - "profile_drawer_readonly_mode": "Manera de nomÊs lectura activada. Feu doble click a la icona de l'avatar de l'usuari per sortir.", + "profile_drawer_readonly_mode": "Mode nomÊs lectura. Feu pulsaciÃŗ llarga a la icona de l'avatar d'usuari per sortir.", "profile_drawer_server_out_of_date_major": "El servidor està desactualitzat. Si us plau, actualitzeu a l'Ãēltima versiÃŗ major.", "profile_drawer_server_out_of_date_minor": "El servidor està desactualitzat. Si us plau, actualitzeu a l'Ãēltima versiÃŗ menor.", "profile_image_of_user": "Imatge de perfil de {user}", @@ -1557,6 +1586,7 @@ "purchase_server_description_2": "Estat del contribuent", "purchase_server_title": "Servidor", "purchase_settings_server_activated": "La clau de producte del servidor la gestiona l'administrador", + "query_asset_id": "Consulta d'identificaciÃŗ d'actius", "queue_status": "En cua {count}/{total}", "rating": "ValoraciÃŗ", "rating_clear": "Esborrar valoraciÃŗ", @@ -1566,6 +1596,7 @@ "read_changelog": "Llegeix el registre de canvis", "readonly_mode_disabled": "Mode de nomÊs lectura desactivat", "readonly_mode_enabled": "Mode de nomÊs lectura activat", + "ready_for_upload": "Llest per a pujar", "reassign": "Reassignar", "reassigned_assets_to_existing_person": "{count, plural, one {S'ha reassignat # recurs} other {S'han reassignat # recursos}} a {name, select, null {una persona existent} other {{name}}}", "reassigned_assets_to_new_person": "{count, plural, one {S'ha reassignat # recurs} other {S'han reassignat # recursos}} a una persona nova", @@ -1590,6 +1621,7 @@ "regenerating_thumbnails": "Regenerant les miniatures", "remote": "Remot", "remote_assets": "Recursos Remots", + "remote_media_summary": "Resum de Mitjans Remots", "remove": "Eliminar", "remove_assets_album_confirmation": "Confirmes que vols eliminar {count, plural, one {# recurs} other {# recursos}} de l'àlbum?", "remove_assets_shared_link_confirmation": "Esteu segur que voleu eliminar {count, plural, one {# recurs} other {# recursos}} d'aquest enllaç compartit?", @@ -1642,6 +1674,7 @@ "restore_user": "Restaurar l'usuari", "restored_asset": "Element restaurat", "resume": "Reprendre", + "resume_paused_jobs": "Reprèn {count, plural, one {# treball pausat} other {# treballs pausats}}", "retry_upload": "Torna a provar de pujar", "review_duplicates": "Revisar duplicats", "review_large_files": "Revisar fitxers grans", @@ -1735,7 +1768,7 @@ "select_user_for_sharing_page_err_album": "Error al crear l'àlbum", "selected": "Seleccionat", "selected_count": "{count, plural, one {# seleccionat} other {# seleccionats}}", - "selected_gps_coordinates": "seleccio de coordinades GPS", + "selected_gps_coordinates": "Seleccio de coordinades GPS", "send_message": "Envia missatge", "send_welcome_email": "Envia correu de benvinguda", "server_endpoint": "Endpoint de Servidor", @@ -1846,10 +1879,8 @@ "shift_to_permanent_delete": "premeu ⇧ per suprimir el recurs permanentment", "show_album_options": "Mostra les opcions d'àlbum", "show_albums": "Mostrar àlbums", - "show_all_assets": "Mostrar tots els elements", "show_all_people": "Veure totes les persones", "show_and_hide_people": "Mostra i amaga persones", - "show_assets_without_location": "Mostra els elements sense ubicaciÃŗ", "show_file_location": "Mostra l'ubicaciÃŗ del fitxer", "show_gallery": "Mostra la galeria", "show_hidden_people": "Mostra persones ocultes", @@ -1866,6 +1897,7 @@ "show_slideshow_transition": "Mostra la transiciÃŗ de la presentaciÃŗ de diapositives", "show_supporter_badge": "Insígnia de contribuent", "show_supporter_badge_description": "Mostra una insígnia de contributor", + "show_text_search_menu": "Mostra el menÃē de cerca amb text", "shuffle": "Mescla", "sidebar": "Barra lateral", "sidebar_display_description": "Mostra un enllaç a la vista a la barra lateral", @@ -1879,7 +1911,7 @@ "slideshow_settings": "ConfiguraciÃŗ de diapositives", "sort_albums_by": "Ordena àlbums per...", "sort_created": "Data de creaciÃŗ", - "sort_items": "Nombre d'elements", + "sort_items": "Quantitat d'elements", "sort_modified": "Data de modificaciÃŗ", "sort_newest": "Foto mÊs nova", "sort_oldest": "Foto mÊs antiga", @@ -1896,6 +1928,7 @@ "stacktrace": "Traça de pila", "start": "Inicia", "start_date": "Data inicial", + "start_date_before_end_date": "La data d'inici ha de ser abans de la data de fi", "state": "RegiÃŗ", "status": "Estat", "stop_casting": "Atura la transmisiÃŗ", @@ -1920,6 +1953,8 @@ "sync_albums_manual_subtitle": "Sincronitza tots els vídeos i fotos penjats amb els àlbums de cÃ˛pia de seguretat seleccionats", "sync_local": "Sincronitza Local", "sync_remote": "Sincronitza Remot", + "sync_status": "Estat de sincronitzaciÃŗ", + "sync_status_subtitle": "Observa i administra el sistema de sincronitzaciÃŗ", "sync_upload_album_setting_subtitle": "Creeu i pugeu les seves fotos i vídeos als àlbums seleccionats a Immich", "tag": "Etiqueta", "tag_assets": "Etiquetar actius", @@ -1979,6 +2014,7 @@ "trash_page_select_assets_btn": "Selecciona elements", "trash_page_title": "Paperera ({count})", "trashed_items_will_be_permanently_deleted_after": "Els elements que s'enviïn a la paperera s'eliminaran permanentment desprÊs de {days, plural, one {# dia} other {# dies}}.", + "troubleshoot": "SoluciÃŗ de problemes", "type": "Tipus", "unable_to_change_pin_code": "No es pot canviar el codi PIN", "unable_to_setup_pin_code": "No s'ha pogut configurar el codi PIN", @@ -2034,7 +2070,6 @@ "use_biometric": "Empra biometria", "use_current_connection": "utilitzar la connexiÃŗ actual", "use_custom_date_range": "Fes servir un rang de dates personalitzat", - "use_this_location": "Fes clic per utilitzar la ubicaciÃŗ", "user": "Usuari", "user_has_been_deleted": "Aquest usuari ha sigut eliminat.", "user_id": "ID d'usuari", @@ -2077,6 +2112,7 @@ "view_next_asset": "Mostra el segÃŧent element", "view_previous_asset": "Mostra l'element anterior", "view_qr_code": "Veure codi QR", + "view_similar_photos": "Veure fotos similars", "view_stack": "Veure la pila", "view_user": "Veure Usuari", "viewer_remove_from_stack": "Elimina de la pila", @@ -2095,5 +2131,6 @@ "yes": "Sí", "you_dont_have_any_shared_links": "No tens cap enllaç compartit", "your_wifi_name": "Nom del teu Wi-Fi", - "zoom_image": "Ampliar Imatge" + "zoom_image": "Ampliar Imatge", + "zoom_to_bounds": "Amplia als límits" } diff --git a/i18n/cs.json b/i18n/cs.json index e600fc1348..e6fe1a3589 100644 --- a/i18n/cs.json +++ b/i18n/cs.json @@ -28,10 +28,12 @@ "add_to_album": "Přidat do alba", "add_to_album_bottom_sheet_added": "PřidÃĄno do {album}", "add_to_album_bottom_sheet_already_exists": "Je jiÅž v {album}", + "add_to_album_bottom_sheet_some_local_assets": "NěkterÊ místní poloÅžky nebylo moÅžnÊ přidat do alba", "add_to_album_toggle": "Přepnout vÃŊběr pro {album}", "add_to_albums": "Přidat do alb", "add_to_albums_count": "Přidat do alb ({count})", "add_to_shared_album": "Přidat do sdílenÊho alba", + "add_upload_to_stack": "Přidat nahranÊ do zÃĄsobníku", "add_url": "Přidat URL", "added_to_archive": "PřidÃĄno do archivu", "added_to_favorites": "PřidÃĄno do oblíbenÃŊch", @@ -123,6 +125,13 @@ "logging_enable_description": "Povolit protokolovÃĄní", "logging_level_description": "KdyÅž je povoleno, jakou Ãēroveň protokolu pouŞít.", "logging_settings": "ProtokolovÃĄní", + "machine_learning_availability_checks": "Kontroly dostupnosti", + "machine_learning_availability_checks_description": "Automaticky zvolit a preferovat dostupnÊ servery strojovÊho učení", + "machine_learning_availability_checks_enabled": "Povolit kontroly dostupnosti", + "machine_learning_availability_checks_interval": "Interval kontrol", + "machine_learning_availability_checks_interval_description": "Interval v milisekundÃĄch mezi kontrolami dostupnosti", + "machine_learning_availability_checks_timeout": "ČasovÃŊ limit poÅžadavku", + "machine_learning_availability_checks_timeout_description": "ČasovÃŊ limit v milisekundÃĄch pro kontrolu dostupnosti", "machine_learning_clip_model": "Model CLIP", "machine_learning_clip_model_description": "NÃĄzev CLIP modelu je uvedenÃŊ zde. Pamatujte, Åže při změně modelu je nutnÊ znovu spustit Ãēlohu 'ChytrÊ vyhledÃĄvÃĄní' pro vÅĄechny obrÃĄzky.", "machine_learning_duplicate_detection": "Kontrola duplicit", @@ -387,8 +396,6 @@ "admin_password": "Heslo sprÃĄvce", "administration": "Administrace", "advanced": "PokročilÊ", - "advanced_settings_beta_timeline_subtitle": "VyzkouÅĄejte novÊ prostředí aplikace", - "advanced_settings_beta_timeline_title": "ČasovÃĄ osa (beta)", "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í: {level}", @@ -425,6 +432,7 @@ "album_remove_user_confirmation": "Opravdu chcete odebrat uÅživatele {user}?", "album_search_not_found": "Nebyla nalezena ÅžÃĄdnÃĄ alba odpovídající vaÅĄemu hledÃĄní", "album_share_no_users": "Zřejmě jste toto album sdíleli se vÅĄemi uÅživateli, nebo nemÃĄte ÅžÃĄdnÊho uÅživatele, se kterÃŊm byste ho mohli sdílet.", + "album_summary": "Souhrn alba", "album_updated": "Album aktualizovÃĄno", "album_updated_setting_description": "DostÃĄvat e-mailovÃĄ oznÃĄmení o novÃŊch poloÅžkÃĄch sdílenÊho alba", "album_user_left": "Opustil {album}", @@ -496,6 +504,8 @@ "asset_restored_successfully": "PoloÅžka ÃēspÄ›ÅĄně obnovena", "asset_skipped": "Přeskočeno", "asset_skipped_in_trash": "V koÅĄi", + "asset_trashed": "PoloÅžka vyhozena", + "asset_troubleshoot": "ŘeÅĄení problÊmů s poloÅžkami", "asset_uploaded": "NahrÃĄno", "asset_uploading": "NahrÃĄvÃĄníâ€Ļ", "asset_viewer_settings_subtitle": "SprÃĄva nastavení prohlíŞeče galerie", @@ -529,8 +539,10 @@ "autoplay_slideshow": "AutomatickÊ přehrÃĄvÃĄní prezentace", "back": "Zpět", "back_close_deselect": "Zpět, zavřít nebo zruÅĄit vÃŊběr", + "background_backup_running_error": "PrÃĄvě probíhÃĄ zÃĄlohovÃĄní na pozadí, nelze spustit ruční zÃĄlohovÃĄní", "background_location_permission": "Povolení polohy na pozadí", "background_location_permission_content": "Aby bylo moÅžnÊ přepínat sítě při běhu na pozadí, musí mít Immich *vÅždy* přístup k přesnÊ poloze, aby mohl zjistit nÃĄzev Wi-Fi sítě", + "background_options": "MoÅžnosti běhu na pozadí", "backup": "ZÃĄloha", "backup_album_selection_page_albums_device": "Alba v zařízení ({count})", "backup_album_selection_page_albums_tap": "Klepnutím na poloÅžku ji zahrnete, opětovnÃŊm klepnutím ji vyloučíte", @@ -538,6 +550,7 @@ "backup_album_selection_page_select_albums": "VybranÃĄ alba", "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_albums_sync": "Synchronizace zÃĄlohovanÃŊch alb", "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â€Ļ", @@ -587,6 +600,7 @@ "backup_controller_page_turn_on": "Povolit zÃĄlohovÃĄní na popředí", "backup_controller_page_uploading_file_info": "Informace o nahranÊm souboru", "backup_err_only_album": "Nelze odstranit jedinÊ vybranÊ album", + "backup_error_sync_failed": "Synchronizace selhala. Nelze zpracovat zÃĄlohu.", "backup_info_card_assets": "poloÅžek", "backup_manual_cancelled": "ZruÅĄeno", "backup_manual_in_progress": "NahrÃĄvÃĄní jiÅž probíhÃĄ. Zkuste to znovu později", @@ -597,8 +611,6 @@ "backup_setting_subtitle": "SprÃĄva nastavení zÃĄlohovÃĄní na pozadí a na popředí", "backup_settings_subtitle": "SprÃĄva nastavení nahrÃĄvÃĄní", "backward": "PozpÃĄtku", - "beta_sync": "Stav synchronizace (beta)", - "beta_sync_subtitle": "SprÃĄva novÊho systÊmu synchronizace", "biometric_auth_enabled": "BiometrickÊ ověřovÃĄní je povoleno", "biometric_locked_out": "Jste vyloučeni z biometrickÊho ověřovÃĄní", "biometric_no_options": "BiometrickÊ moÅžnosti nejsou k dispozici", @@ -656,6 +668,8 @@ "change_pin_code": "Změnit PIN kÃŗd", "change_your_password": "Změna vaÅĄeho hesla", "changed_visibility_successfully": "Změna viditelnosti proběhla ÃēspÄ›ÅĄně", + "charging": "Nabíjení", + "charging_requirement_mobile_backup": "ZÃĄlohovÃĄní na pozadí vyÅžaduje, aby bylo zařízení nabíjeno", "check_corrupt_asset_backup": "Kontrola poÅĄkozenÃŊch zÃĄloh poloÅžek", "check_corrupt_asset_backup_button": "ProvÊst kontrolu", "check_corrupt_asset_backup_description": "Tuto kontrolu provÃĄdějte pouze přes Wi-Fi a po zÃĄlohovÃĄní vÅĄech prostředků. Takto operace můŞe trvat několik minut.", @@ -742,6 +756,7 @@ "create_user": "Vytvořit uÅživatele", "created": "Vytvořeno", "created_at": "Vytvořeno", + "creating_linked_albums": "VytvÃĄÅ™ení propojenÃŊch alb...", "crop": "Oříznout", "curated_object_page_title": "Věci", "current_device": "SoučasnÊ zařízení", @@ -891,7 +906,9 @@ "error": "Chyba", "error_change_sort_album": "Nepodařilo se změnit pořadí alba", "error_delete_face": "Chyba při odstraňovÃĄní obličeje z poloÅžky", + "error_getting_places": "Chyba při zjiÅĄÅĨovÃĄní míst", "error_loading_image": "Chyba při načítÃĄní obrÃĄzku", + "error_loading_partners": "Chyba při načítÃĄní partnerů: {error}", "error_saving_image": "Chyba: {error}", "error_tag_face_bounding_box": "Chyba při označovÃĄní obličeje - nelze získat souřadnice ohraničujícího rÃĄmečku", "error_title": "Chyba - Něco se pokazilo", @@ -1056,6 +1073,7 @@ "favorites_page_no_favorites": "Nebyla nalezena ÅžÃĄdnÃĄ oblíbenÃĄ mÊdia", "feature_photo_updated": "Hlavní fotka aktualizovÃĄna", "features": "Funkce", + "features_in_development": "Funkce ve vÃŊvoji", "features_setting_description": "SprÃĄva funkcí aplikace", "file_name": "NÃĄzev souboru", "file_name_or_extension": "NÃĄzev nebo přípona souboru", @@ -1076,10 +1094,7 @@ "gcast_enabled": "Google Cast", "gcast_enabled_description": "Tato funkce načítÃĄ externí zdroje z Googlu, aby mohla fungovat.", "general": "ObecnÊ", - "geolocation_instruction_all_have_location": "VÅĄechny poloÅžky k tomuto datu jiÅž mají Ãēdaje o poloze. Zkuste zobrazit vÅĄechny poloÅžky nebo vyberte jinÊ datum", "geolocation_instruction_location": "Klikněte na poloÅžku s GPS souřadnicemi, abyste mohli pouŞít její polohu, nebo vyberte polohu přímo z mapy", - "geolocation_instruction_no_date": "Vyberte datum, abyste mohli spravovat Ãēdaje o poloze pro fotografie a videa z danÊho dne", - "geolocation_instruction_no_photos": "Pro tento den nebyly nalezeny ÅžÃĄdnÊ fotografie ani videa. Vyberte jinÊ datum pro jejich zobrazení", "get_help": "Získat pomoc", "get_wifiname_error": "Nepodařilo se získat nÃĄzev Wi-Fi. Zkontrolujte, zda jste udělili potřebnÃĄ oprÃĄvnění a zda jste připojeni k Wi-Fi síti", "getting_started": "ZačínÃĄme", @@ -1223,6 +1238,7 @@ "local": "Místní", "local_asset_cast_failed": "Nelze odeslat poloÅžku, kterÃĄ není nahranÃĄ na serveru", "local_assets": "Místní poloÅžky", + "local_media_summary": "Souhrn místních mÊdií", "local_network": "Místní síÅĨ", "local_network_sheet_info": "Aplikace se při pouÅžití zadanÊ sítě Wi-Fi připojí k serveru prostřednictvím tohoto URL", "location_permission": "OprÃĄvnění polohy", @@ -1234,6 +1250,7 @@ "location_picker_longitude_hint": "Zadejte vlastní zeměpisnou dÊlku", "lock": "Zamknout", "locked_folder": "UzamčenÃĄ sloÅžka", + "log_detail_title": "Podrobnosti protokolu", "log_out": "OdhlÃĄsit", "log_out_all_devices": "OdhlÃĄsit vÅĄechna zařízení", "logged_in_as": "PřihlÃĄÅĄen jako {user}", @@ -1264,6 +1281,7 @@ "login_password_changed_success": "Heslo bylo ÃēspÄ›ÅĄně aktualizovÃĄno", "logout_all_device_confirmation": "Opravdu chcete odhlÃĄsit vÅĄechna zařízení?", "logout_this_device_confirmation": "Opravdu chcete odhlÃĄsit toto zařízení?", + "logs": "Protokoly", "longitude": "ZeměpisnÃĄ dÊlka", "look": "Zobrazení", "loop_videos": "Videa ve smyčce", @@ -1306,6 +1324,7 @@ "mark_as_read": "Označit jako přečtenÊ", "marked_all_as_read": "VÅĄe označeno jako přečtenÊ", "matches": "Shody", + "matching_assets": "Odpovídající poloÅžky", "media_type": "Typ mÊdia", "memories": "Vzpomínky", "memories_all_caught_up": "To je vÅĄechno", @@ -1346,6 +1365,7 @@ "name_or_nickname": "JmÊno nebo přezdívka", "network_requirement_photos_upload": "Pro zÃĄlohovÃĄní fotografií pouŞívat mobilní data", "network_requirement_videos_upload": "Pro zÃĄlohovÃĄní videí pouŞívat mobilní data", + "network_requirements": "PoÅžadavky na síÅĨ", "network_requirements_updated": "PoÅžadavky na síÅĨ se změnily, fronta zÃĄlohovÃĄní se vytvoří znovu", "networking_settings": "SíÅĨ", "networking_subtitle": "SprÃĄva nastavení koncovÊho bodu serveru", @@ -1356,6 +1376,7 @@ "new_person": "NovÃĄ osoba", "new_pin_code": "NovÃŊ PIN kÃŗd", "new_pin_code_subtitle": "PoprvÊ přistupujete k uzamčenÊ sloÅžce. Vytvořte si kÃŗd PIN pro bezpečnÃŊ přístup na tuto strÃĄnku", + "new_timeline": "NovÃĄ časovÃĄ osa", "new_user_created": "Vytvořen novÃŊ uÅživatel", "new_version_available": "NOVÁ VERZE K DISPOZICI", "newest_first": "NejnovějÅĄÃ­ první", @@ -1369,20 +1390,25 @@ "no_assets_message": "KLIKNĚTE PRO NAHRÁNÍ PRVNÍ FOTOGRAFIE", "no_assets_to_show": "ÅŊÃĄdnÊ poloÅžky k zobrazení", "no_cast_devices_found": "Nebyla nalezena ÅžÃĄdnÃĄ zařízení", + "no_checksum_local": "Není k dispozici kontrolní součet - nelze načíst místní poloÅžky", + "no_checksum_remote": "Není k dispozici kontrolní součet - nelze načíst vzdÃĄlenou poloÅžku", "no_duplicates_found": "Nebyly nalezeny ÅžÃĄdnÊ duplicity.", "no_exif_info_available": "Exif není k dispozici", "no_explore_results_message": "Nahrajte dalÅĄÃ­ fotografie a prozkoumejte svou sbírku.", "no_favorites_message": "Přidejte si oblíbenÊ poloÅžky a rychle najděte svÊ nejlepÅĄÃ­ obrÃĄzky a videa", "no_libraries_message": "Vytvořte si externí knihovnu pro zobrazení fotografií a videí", + "no_local_assets_found": "Nebyly nalezeny ÅžÃĄdnÊ místní poloÅžky s tímto kontrolním součtem", "no_locked_photos_message": "Fotky a videa v uzamčenÊ sloÅžce jsou skrytÊ a při prochÃĄzení nebo vyhledÃĄvÃĄní v knihovně se nezobrazují.", "no_name": "Bez jmÊna", "no_notifications": "ÅŊÃĄdnÃĄ oznÃĄmení", "no_people_found": "Nebyli nalezeni ÅžÃĄdní odpovídající lidÊ", "no_places": "ÅŊÃĄdnÃĄ místa", + "no_remote_assets_found": "Nebyly nalezeny ÅžÃĄdnÊ vzdÃĄlenÊ poloÅžky s tímto kontrolním součtem", "no_results": "ÅŊÃĄdnÊ vÃŊsledky", "no_results_description": "Zkuste pouŞít synonymum nebo obecnějÅĄÃ­ klíčovÊ slovo", "no_shared_albums_message": "Vytvořte si album a sdílejte fotografie a videa s lidmi ve svÊ síti", "no_uploads_in_progress": "NeprobíhÃĄ ÅžÃĄdnÊ nahrÃĄvÃĄní", + "not_available": "Není k dispozici", "not_in_any_album": "Bez alba", "not_selected": "Není vybrÃĄno", "note_apply_storage_label_to_previously_uploaded assets": "Upozornění: Chcete-li pouŞít ÅĄtítek ÃēloÅžiÅĄtě na dříve nahranÊ poloÅžky, spusÅĨte příkaz", @@ -1504,6 +1530,7 @@ "port": "Port", "preferences_settings_subtitle": "SprÃĄva předvoleb aplikace", "preferences_settings_title": "Předvolby", + "preparing": "Příprava", "preset": "Přednastavení", "preview": "NÃĄhled", "previous": "Předchozí", @@ -1520,7 +1547,7 @@ "profile_drawer_client_out_of_date_minor": "Mobilní aplikace je zastaralÃĄ. Aktualizujte ji na nejnovějÅĄÃ­ verzi.", "profile_drawer_client_server_up_to_date": "Klient a server jsou aktuÃĄlní", "profile_drawer_github": "GitHub", - "profile_drawer_readonly_mode": "ReÅžim pouze pro čtení je aktivovÃĄn. DvojitÃŊm klepnutím na ikonu avatara uÅživatele reÅžim ukončíte.", + "profile_drawer_readonly_mode": "ReÅžim jen pro čtení. Ukončíte ho dlouhÃŊm podrÅžením ikony avataru.", "profile_drawer_server_out_of_date_major": "Server je zastaralÃŊ. Aktualizujte na nejnovějÅĄÃ­ hlavní verzi.", "profile_drawer_server_out_of_date_minor": "Server je zastaralÃŊ. Aktualizujte je na nejnovějÅĄÃ­ verzi.", "profile_image_of_user": "ProfilovÃŊ obrÃĄzek uÅživatele {user}", @@ -1569,6 +1596,7 @@ "read_changelog": "Přečtěte si seznam změn", "readonly_mode_disabled": "ReÅžim pouze pro čtení je deaktivovÃĄn", "readonly_mode_enabled": "ReÅžim pouze pro čtení povolen", + "ready_for_upload": "Připraveno k nahrÃĄní", "reassign": "Přeřadit", "reassigned_assets_to_existing_person": "Přeřadit {count, plural, one {# poloÅžku} few {# poloÅžky} other {# poloÅžek}} na {name, select, null {existující osobu} other {{name}}}", "reassigned_assets_to_new_person": "{count, plural, one {Přeřazena # poloÅžka} few {Přeřazeny # poloÅžky} other {Přeřazeno # poloÅžek}} na novou osobu", @@ -1593,6 +1621,7 @@ "regenerating_thumbnails": "Regenerace miniatur", "remote": "VzdÃĄlenÃŊ", "remote_assets": "VzdÃĄlenÊ poloÅžky", + "remote_media_summary": "Souhrn vzdÃĄlenÃŊch mÊdií", "remove": "Odstranit", "remove_assets_album_confirmation": "Opravdu chcete z alba odstranit {count, plural, one {# poloÅžku} few {# poloÅžky} other {# poloÅžek}}?", "remove_assets_shared_link_confirmation": "Opravdu chcete ze sdílenÊho odkazu odstranit {count, plural, one {# poloÅžku} few {# poloÅžky} other {# poloÅžek}}?", @@ -1645,6 +1674,7 @@ "restore_user": "Obnovit uÅživatele", "restored_asset": "PoloÅžka obnovena", "resume": "Pokračovat", + "resume_paused_jobs": "Pokračovat {count, plural, one {v # pozastavenÊ Ãēloze} few {ve # pozastavenÃŊch ÃēlohÃĄch} other {v # pozastavenÃŊch ÃēlohÃĄch}}", "retry_upload": "OpakovÃĄní nahrÃĄvÃĄní", "review_duplicates": "Kontrola duplicit", "review_large_files": "Kontrola velkÃŊch souborů", @@ -1657,7 +1687,7 @@ "saved_api_key": "API klíč uloÅžen", "saved_profile": "Profil uloÅžen", "saved_settings": "Nastavení uloÅženo", - "say_something": "Řekněte něco", + "say_something": "NapiÅĄte něco", "scaffold_body_error_occurred": "DoÅĄlo k chybě", "scan_all_libraries": "Prohledat vÅĄechny knihovny", "scan_library": "Prohledat", @@ -1849,10 +1879,8 @@ "shift_to_permanent_delete": "stiskněte ⇧ pro trvalÊ odstranění poloÅžky", "show_album_options": "Zobrazit moÅžnosti alba", "show_albums": "Zobrazit alba", - "show_all_assets": "Zobrazit vÅĄechny poloÅžky", "show_all_people": "Zobrazit vÅĄechny lidi", "show_and_hide_people": "Zobrazit a skrÃŊt osoby", - "show_assets_without_location": "Zobrazit poloÅžky bez polohy", "show_file_location": "Zobrazit umístění souboru", "show_gallery": "Zobrazit galerii", "show_hidden_people": "Zobrazit skrytÊ lidi", @@ -1869,6 +1897,7 @@ "show_slideshow_transition": "Zobrazit přechod prezentace", "show_supporter_badge": "Odznak podporovatele", "show_supporter_badge_description": "Zobrazit odznak podporovatele", + "show_text_search_menu": "Zobrazit nabídku pro vyhledÃĄvÃĄní textu", "shuffle": "NÃĄhodnÃŊ vÃŊběr", "sidebar": "Postranní panel", "sidebar_display_description": "Zobrazení odkazu na zobrazení v postranním panelu", @@ -1899,6 +1928,7 @@ "stacktrace": "VÃŊpis zÃĄsobníku", "start": "Start", "start_date": "PoÄÃĄteční datum", + "start_date_before_end_date": "PoÄÃĄteční datum se musí nachÃĄzet před konečnÃŊm datem", "state": "StÃĄt", "status": "Stav", "stop_casting": "Zastavit odesílÃĄní", @@ -1923,6 +1953,8 @@ "sync_albums_manual_subtitle": "Synchronizovat vÅĄechna nahranÃĄ videa a fotografie do vybranÃŊch zÃĄloÅžních alb", "sync_local": "Synchronizovat místní", "sync_remote": "Synchronizovat vzdÃĄlenÊ", + "sync_status": "Stav synchronizace", + "sync_status_subtitle": "Zobrazit a spravovat synchronizační systÊm", "sync_upload_album_setting_subtitle": "Vytvořit a nahrÃĄt fotografie a videa do vybranÃŊch alb na Immich", "tag": "Značka", "tag_assets": "Přiřadit značku", @@ -1982,6 +2014,7 @@ "trash_page_select_assets_btn": "Vybrat poloÅžky", "trash_page_title": "KoÅĄ ({count})", "trashed_items_will_be_permanently_deleted_after": "SmazanÊ poloÅžky budou trvale odstraněny po {days, plural, one {# dni} other {# dnech}}.", + "troubleshoot": "Diagnostika", "type": "Typ", "unable_to_change_pin_code": "Nelze změnit PIN kÃŗd", "unable_to_setup_pin_code": "Nelze nastavit PIN kÃŗd", @@ -2037,7 +2070,6 @@ "use_biometric": "PouŞít biometrickÊ Ãēdaje", "use_current_connection": "pouŞít aktuÃĄlní připojení", "use_custom_date_range": "PouŞít vlastní rozsah dat", - "use_this_location": "Klikněte pro pouÅžití polohy", "user": "UÅživatel", "user_has_been_deleted": "Tento uÅživatel byl smazÃĄn.", "user_id": "ID uÅživatele", @@ -2099,5 +2131,6 @@ "yes": "Ano", "you_dont_have_any_shared_links": "NemÃĄte ÅžÃĄdnÊ sdílenÊ odkazy", "your_wifi_name": "NÃĄzev vaÅĄÃ­ Wi-Fi", - "zoom_image": "ZvětÅĄit obrÃĄzek" + "zoom_image": "ZvětÅĄit obrÃĄzek", + "zoom_to_bounds": "PřiblíŞit na okraje" } diff --git a/i18n/da.json b/i18n/da.json index 847913497a..24dd99d45f 100644 --- a/i18n/da.json +++ b/i18n/da.json @@ -1,8 +1,8 @@ { - "about": "Om", + "about": "Om os", "account": "Konto", "account_settings": "Kontoindstillinger", - "acknowledge": "Godkend", + "acknowledge": "Accepter", "action": "Handling", "action_common_update": "Opdater", "actions": "Handlinger", @@ -28,6 +28,7 @@ "add_to_album": "Tilføj til album", "add_to_album_bottom_sheet_added": "Tilføjet til {album}", "add_to_album_bottom_sheet_already_exists": "Allerede i {album}", + "add_to_album_bottom_sheet_some_local_assets": "Nogle lokale elementer kunne ikke føjes til albummet", "add_to_album_toggle": "Skift selektion for {album}", "add_to_albums": "Tilføj til albummer", "add_to_albums_count": "Tilføj til albummer({count})", @@ -123,6 +124,13 @@ "logging_enable_description": "Aktiver logning", "logging_level_description": "NÃĨr slÃĨet til, hvilket logniveau, der skal bruges.", "logging_settings": "Logning", + "machine_learning_availability_checks": "TilgÃĻngelighedstjek", + "machine_learning_availability_checks_description": "Opdag og foretrÃĻk automatisk tilgÃĻngelige maskinlÃĻringsservere", + "machine_learning_availability_checks_enabled": "AktivÊr tilgÃĻngelighedstjek", + "machine_learning_availability_checks_interval": "Kontroller interval", + "machine_learning_availability_checks_interval_description": "Interval i millisekunder mellem tilgÃĻngelighedstjeks", + "machine_learning_availability_checks_timeout": "Timeout pÃĨ anmodning", + "machine_learning_availability_checks_timeout_description": "Timeout i millisekunder pÃĨ tilgÃĻngelighedstjeks", "machine_learning_clip_model": "CLIP-model", "machine_learning_clip_model_description": "Navnet pÃĨ CLIP-modellen pÃĨ listen her. BemÃĻrk at du skal genkøre \"Smart Søgning\"-jobbet for alle billeder, hvis du skifter model.", "machine_learning_duplicate_detection": "Dubletdetektion", @@ -387,8 +395,6 @@ "admin_password": "Administratoradgangskode", "administration": "Administration", "advanced": "Avanceret", - "advanced_settings_beta_timeline_subtitle": "Prøv den nye app-oplevelse", - "advanced_settings_beta_timeline_title": "Beta-tidslinje", "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_enable_alternate_media_filter_title": "[EKSPERIMENTEL] Brug alternativ enheds album synkroniserings filter", "advanced_settings_log_level_title": "Logniveau: {level}", @@ -425,6 +431,7 @@ "album_remove_user_confirmation": "Er du sikker pÃĨ at du vil fjerne {user}?", "album_search_not_found": "Ingen album fundet som matcher din søgning", "album_share_no_users": "Det ser ud til at du har delt denne album med alle brugere, eller du har ikke nogen brugere til at dele med.", + "album_summary": "Albumoversigt", "album_updated": "Album opdateret", "album_updated_setting_description": "Modtag en emailnotifikation nÃĨr et delt album fÃĨr nye mediefiler", "album_user_left": "Forlod {album}", @@ -496,6 +503,8 @@ "asset_restored_successfully": "Elementet blev gendannet succesfuldt", "asset_skipped": "Sprunget over", "asset_skipped_in_trash": "I skraldespand", + "asset_trashed": "Objekt kasseret", + "asset_troubleshoot": "Fejlsøg pÃĨ objekt", "asset_uploaded": "Uploadet", "asset_uploading": "Uploaderâ€Ļ", "asset_viewer_settings_subtitle": "Administrer indstillinger for gallerifremviser", @@ -529,8 +538,10 @@ "autoplay_slideshow": "Afspil slideshow automatisk", "back": "Tilbage", "back_close_deselect": "Tilbage, luk eller fravÃĻlg", + "background_backup_running_error": "Backup kører lige nu i baggrund; kan ikke starte manuel backup", "background_location_permission": "Tilladelse til baggrundsplacering", "background_location_permission_content": "For at skifte netvÃĻrk, nÃĨr appen kører i baggrunden, skal Immich *altid* have prÃĻcis placeringsadgang, sÃĨ appen kan lÃĻse WiFi-netvÃĻrkets navn", + "background_options": "Baggrundsmuligheder", "backup": "Sikkerhedskopier", "backup_album_selection_page_albums_device": "Albummer pÃĨ enheden ({count})", "backup_album_selection_page_albums_tap": "Tryk en gang for at inkludere, tryk to gange for at ekskludere", @@ -538,6 +549,7 @@ "backup_album_selection_page_select_albums": "VÃĻlg albummer", "backup_album_selection_page_selection_info": "Oplysninger om valgte", "backup_album_selection_page_total_assets": "Samlede unikke elementer", + "backup_albums_sync": "Synkronisering af backupalbums", "backup_all": "Alt", "backup_background_service_backup_failed_message": "Sikkerhedskopiering af elementer fejlede. Forsøger igenâ€Ļ", "backup_background_service_connection_failed_message": "Forbindelsen til serveren blev tabt. Forsøger igenâ€Ļ", @@ -587,6 +599,7 @@ "backup_controller_page_turn_on": "SlÃĨ sikkerhedskopiering til", "backup_controller_page_uploading_file_info": "Uploader filinformation", "backup_err_only_album": "Kan ikke slette det eneste album", + "backup_error_sync_failed": "Synkroniseringen mislykkedes. Sikkerhedskopieringen kunne ikke behandles.", "backup_info_card_assets": "objekter", "backup_manual_cancelled": "Annulleret", "backup_manual_in_progress": "Upload er allerede undervejs. Prøv igen efter noget tid", @@ -597,8 +610,6 @@ "backup_setting_subtitle": "Administrer indstillnger for upload i forgrund og baggrund", "backup_settings_subtitle": "HÃĨndtere upload indstillinger", "backward": "BaglÃĻns", - "beta_sync": "Beta synkroniseringsstatus", - "beta_sync_subtitle": "HÃĨndter det nye synkroniseringssystem", "biometric_auth_enabled": "Biometrisk adgangskontrol slÃĨet til", "biometric_locked_out": "Du er lÃĨst ude af biometrisk adgangskontrol", "biometric_no_options": "Ingen biometrisk adgangskontrol tilgÃĻngelig", @@ -637,10 +648,10 @@ "cannot_merge_people": "Kan ikke sammenflette personer", "cannot_undo_this_action": "Du kan ikke fortryde denne handling!", "cannot_update_the_description": "Kan ikke opdatere beskrivelsen", - "cast": "Cast", + "cast": "Caste", "cast_description": "Konfigurer tilgÃĻngelige cast destinationer", "change_date": "Ændr dato", - "change_description": "Beskrivelse af ÃĻndringer", + "change_description": "Ændr beskrivelse", "change_display_order": "Ændrer visningsrÃĻkkefølge", "change_expiration_time": "Ændr udløbstidspunkt", "change_location": "Ændr sted", @@ -656,6 +667,8 @@ "change_pin_code": "Skift PIN kode", "change_your_password": "Skift dit kodeord", "changed_visibility_successfully": "Synlighed blev ÃĻndret", + "charging": "Lader", + "charging_requirement_mobile_backup": "Baggrundsbackup krÃĻver, at enheden er tilsluttet oplader", "check_corrupt_asset_backup": "Tjek for korrupte sikkerhedskopier af elementer", "check_corrupt_asset_backup_button": "Foretag kontrol", "check_corrupt_asset_backup_description": "Kør kun denne kontrol via Wi-Fi, og nÃĨr alle elementer er blevet sikkerhedskopieret. Proceduren kan tage et par minutter.", @@ -742,6 +755,7 @@ "create_user": "Opret bruger", "created": "Oprettet", "created_at": "Oprettet", + "creating_linked_albums": "Opretter sammenkÃĻdede albums...", "crop": "BeskÃĻr", "curated_object_page_title": "Ting", "current_device": "NuvÃĻrende enhed", @@ -891,7 +905,9 @@ "error": "Fejl", "error_change_sort_album": "Ændring af sorteringsrÃĻkkefølgen mislykkedes", "error_delete_face": "Fejl ved sletning af ansigt fra mediefil", + "error_getting_places": "Fejl ved hentning af steder", "error_loading_image": "Fejl ved indlÃĻsning af billede", + "error_loading_partners": "Fejl ved indlÃĻsning af partnere: {error}", "error_saving_image": "Fejl: {error}", "error_tag_face_bounding_box": "Fejl ved tagging af ansigt - kan ikke finde koordinator for afgrÃĻnsningskasse", "error_title": "Fejl - Noget gik galt", @@ -1056,6 +1072,7 @@ "favorites_page_no_favorites": "Ingen favoritter blev fundet", "feature_photo_updated": "Forsidebillede uploadet", "features": "Funktioner", + "features_in_development": "Funktioner under udvikling", "features_setting_description": "Administrer app-funktioner", "file_name": "Filnavn", "file_name_or_extension": "Filnavn eller filtype", @@ -1076,10 +1093,7 @@ "gcast_enabled": "Google Cast", "gcast_enabled_description": "Denne funktion indlÃĻser eksterne ressourcer fra Google for at virke.", "general": "Generel", - "geolocation_instruction_all_have_location": "Alle objekter for denne dato har allerede lokations-data. Prøv at vise alle objekter eller vÃĻlg en anden dato", "geolocation_instruction_location": "Klik pÃĨ et objekt med GPS-koordinater for at bruge dettes position, eller vÃĻlg position direkte pÃĨ kortet", - "geolocation_instruction_no_date": "VÃĻlg en dato, for at administrere lokationsdata pÃĨ billeder og videoer fra den dag", - "geolocation_instruction_no_photos": "Ingen fotos eller videoer fundet for den dato. VÃĻlg en anden dato for at vise dem", "get_help": "FÃĨ hjÃĻlp", "get_wifiname_error": "Kunne ikke hente Wi-Fi-navn. Sørg for, at du har givet de nødvendige tilladelser og er forbundet til et Wi-Fi-netvÃĻrk", "getting_started": "Kom godt i gang", @@ -1223,6 +1237,7 @@ "local": "Lokal", "local_asset_cast_failed": "Kan ikke caste et aktiv, der ikke er uploadet til serveren", "local_assets": "Lokale objekter", + "local_media_summary": "Opsummering af lokale media", "local_network": "Lokalt netvÃĻrk", "local_network_sheet_info": "Appen vil oprette forbindelse til serveren via denne URL, nÃĨr du bruger det angivne WiFi-netvÃĻrk", "location_permission": "Tilladelse til placering", @@ -1234,6 +1249,7 @@ "location_picker_longitude_hint": "Indtast din lÃĻngdegrad her", "lock": "LÃĨs", "locked_folder": "LÃĨst mappe", + "log_detail_title": "Logdetaljer", "log_out": "Log ud", "log_out_all_devices": "Log ud af alle enheder", "logged_in_as": "Logget ind som {user}", @@ -1264,6 +1280,7 @@ "login_password_changed_success": "Kodeordet blev opdateret", "logout_all_device_confirmation": "Er du sikker pÃĨ, at du vil logge ud af alle enheder?", "logout_this_device_confirmation": "Er du sikker pÃĨ, at du vil logge denne enhed ud?", + "logs": "Logs", "longitude": "LÃĻngdegrad", "look": "Kig", "loop_videos": "Gentag videoer", @@ -1306,6 +1323,7 @@ "mark_as_read": "Marker som lÃĻst", "marked_all_as_read": "Markerede alle som lÃĻst", "matches": "Parringer", + "matching_assets": "Matchende objekter", "media_type": "Medietype", "memories": "Minder", "memories_all_caught_up": "Ajour", @@ -1346,6 +1364,7 @@ "name_or_nickname": "Navn eller kÃĻlenavn", "network_requirement_photos_upload": "Benyt mobildatanettet for at sikkerhedskopiere dine fotos", "network_requirement_videos_upload": "Benyt mobildatanettet for at sikkerhedskopiere dine videoer", + "network_requirements": "NetvÃĻrkskrav", "network_requirements_updated": "NetvÃĻrkskravene er ÃĻndret, backup-køen nulstilles", "networking_settings": "NetvÃĻrk", "networking_subtitle": "Administrer serverens endepunktindstillinger", @@ -1356,6 +1375,7 @@ "new_person": "Ny person", "new_pin_code": "Ny PIN kode", "new_pin_code_subtitle": "Dette er første gang du tilgÃĨr den lÃĨste mappe. Lav en PIN kode for sikkert at tilgÃĨ denne side", + "new_timeline": "Ny tidslinje", "new_user_created": "Ny bruger oprettet", "new_version_available": "NY VERSION TILGÆNGELIG", "newest_first": "Nyeste først", @@ -1365,24 +1385,29 @@ "no_albums_message": "Opret et album for at organisere dine billeder og videoer", "no_albums_with_name_yet": "Det ser ud til, at du ikke har noget album med dette navn endnu.", "no_albums_yet": "Det ser ud til, at du ikke har nogen album endnu.", - "no_archived_assets_message": "ArkivÊr billeder og videoer for at gemme dem vÃĻk fra din Billede oversigt", + "no_archived_assets_message": "ArkivÊr billeder og videoer for at gemme dem vÃĻk fra din billedoversigt", "no_assets_message": "KLIK FOR AT UPLOADE DIT FØRSTE BILLEDE", "no_assets_to_show": "Ingen elementer at vise", "no_cast_devices_found": "Ingen Cast-enheder fundet", + "no_checksum_local": "Ingen checksum tilgÃĻngelig – kan ikke hente lokale objekter", + "no_checksum_remote": "Ingen checksum tilgÃĻngelig – kan ikke hente eksterne objekter", "no_duplicates_found": "Ingen duplikater fundet.", "no_exif_info_available": "Ingen tilgÃĻngelig exif information", "no_explore_results_message": "Upload flere billeder for at udforske din samling.", "no_favorites_message": "Tilføj favoritter for hurtigt at finde dine bedst billeder og videoer", "no_libraries_message": "Opret et eksternt bibliotek for at se dine billeder og videoer", + "no_local_assets_found": "Ingen lokale objekter fundet med denne checksum", "no_locked_photos_message": "Billeder og videoer i den lÃĨste mappe er skjulte og vil ikke blive vist i dit bibliotek.", "no_name": "Intet navn", "no_notifications": "Ingen notifikationer", "no_people_found": "Ingen tilsvarende personer fundet", "no_places": "Ingen steder", + "no_remote_assets_found": "Ingen eksterne objekter fundet med denne checksum", "no_results": "Ingen resultater", "no_results_description": "Prøv et synonym eller et mere generelt søgeord", "no_shared_albums_message": "Opret et album for at dele billeder og videoer med personer i dit netvÃĻrk", "no_uploads_in_progress": "Ingen upload i gang", + "not_available": "ikke tilgÃĻngelig", "not_in_any_album": "Ikke i noget album", "not_selected": "Ikke valgt", "note_apply_storage_label_to_previously_uploaded assets": "BemÃĻrk: For at anvende LagringsmÃĻrkat pÃĨ tidligere uploadede medier, kør", @@ -1417,6 +1442,8 @@ "open_the_search_filters": "Åbn søgefiltre", "options": "Handlinger", "or": "eller", + "organize_into_albums": "Organiser i album", + "organize_into_albums_description": "SÃĻt eksisterende billeder i albummer ved hjÃĻlp af aktuelle synkroniseringsindstillinger", "organize_your_library": "OrganisÊr dit bibliotek", "original": "original", "other": "Andet", @@ -1425,7 +1452,7 @@ "other_variables": "Andre variable", "owned": "Egne", "owner": "Ejer", - "partner": "Partner", + "partner": "Partnerpartner", "partner_can_access": "{partner} kan tilgÃĨ", "partner_can_access_assets": "Alle dine billeder og videoer, bortset fra dem i Arkivet og Slettet", "partner_can_access_location": "Stedet, hvor dine billeder blev taget", @@ -1475,7 +1502,7 @@ "permission_onboarding_permission_granted": "Tilladelse givet! Du er nu klar.", "permission_onboarding_permission_limited": "Tilladelse begrÃĻnset. For at lade Immich lave sikkerhedskopi og styre hele dit galleri, skal der gives tilladelse til billeder og videoer i indstillinger.", "permission_onboarding_request": "Immich krÃĻver tilliadelse til at se dine billeder og videoer.", - "person": "Person", + "person": "Personperson", "person_age_months": "{months, plural, one {# month} other {# months}} gammel", "person_age_year_months": "1 ÃĨr, {months, plural, one {# month} other {# months}} gammel", "person_age_years": "{years, plural, other {# years}} gammel", @@ -1502,6 +1529,7 @@ "port": "Port", "preferences_settings_subtitle": "Administrer app-prÃĻferencer", "preferences_settings_title": "PrÃĻferencer", + "preparing": "Forberedelse", "preset": "Forudindstilling", "preview": "ForhÃĨndsvisning", "previous": "Forrige", @@ -1518,7 +1546,7 @@ "profile_drawer_client_out_of_date_minor": "Mobilapp er forÃĻldet. Opdater venligst til den nyeste mindre version.", "profile_drawer_client_server_up_to_date": "Klient og server er ajour", "profile_drawer_github": "GitHub", - "profile_drawer_readonly_mode": "Skrivebeskyttet tilstand aktiveret. Dobbeltklik pÃĨ bruger avatar ikonet for at afslutte.", + "profile_drawer_readonly_mode": "Skrivebeskyttet tilstand aktiveret. Lang tryk pÃĨ bruger avatar ikonet for at afslutte.", "profile_drawer_server_out_of_date_major": "Server er forÃĻldet. Opdater venligst til den nyeste større version.", "profile_drawer_server_out_of_date_minor": "Server er forÃĻldet. Opdater venligst til den nyeste mindre version.", "profile_image_of_user": "Profilbillede af {user}", @@ -1557,6 +1585,7 @@ "purchase_server_description_2": "Supporterstatus", "purchase_server_title": "Server", "purchase_settings_server_activated": "Serverens produktnøgle administreres af administratoren", + "query_asset_id": "Forespørgsels Asset ID", "queue_status": "Kø {count}/{total}", "rating": "Stjernebedømmelse", "rating_clear": "Nulstil vurdering", @@ -1566,6 +1595,7 @@ "read_changelog": "LÃĻs ÃĻndringslog", "readonly_mode_disabled": "Skrivebeskyttet tilstand deaktiveret", "readonly_mode_enabled": "Skrivebeskyttet tilstand aktiveret", + "ready_for_upload": "Klar til upload", "reassign": "Gentildel", "reassigned_assets_to_existing_person": "{count, plural, one {# mediefil} other {# mediefiler}} er blevet gentildelt til {name, select, null {en eksisterende person} other {{name}}}", "reassigned_assets_to_new_person": "Gentildelt {count, plural, one {# aktiv} other {# aktiver}} til en ny person", @@ -1590,6 +1620,7 @@ "regenerating_thumbnails": "Regenererer forhÃĨndsvisninger", "remote": "Eksternt", "remote_assets": "Eksterne objekter", + "remote_media_summary": "Oversigt over eksterne media", "remove": "Fjern", "remove_assets_album_confirmation": "Er du sikker pÃĨ, at du vil fjerne {count, plural, one {# aktiv} other {# aktiver}} fra albummet?", "remove_assets_shared_link_confirmation": "Er du sikker pÃĨ, at du vil fjerne {count, plural, one {# aktiv} other {# aktiver}} fra dette delte link?", @@ -1642,6 +1673,7 @@ "restore_user": "Gendan bruger", "restored_asset": "Gendannet mediefilen", "resume": "Genoptag", + "resume_paused_jobs": "FortsÃĻt {count, plural, one {# paused job} other {# paused jobs}}", "retry_upload": "Forsøg upload igen", "review_duplicates": "GennemgÃĨ dubletter", "review_large_files": "GennemgÃĨ store filer", @@ -1735,7 +1767,7 @@ "select_user_for_sharing_page_err_album": "Fejlede i at oprette et nyt album", "selected": "Valgt", "selected_count": "{count, plural, one {# valgt} other {# valgte}}", - "selected_gps_coordinates": "Valgte GPS-koordinater", + "selected_gps_coordinates": "Udvalgte GPS Koordinater", "send_message": "Send besked", "send_welcome_email": "Send velkomstemail", "server_endpoint": "Server endepunkt", @@ -1846,10 +1878,8 @@ "shift_to_permanent_delete": "tryk pÃĨ ⇧ for at slette aktiv permanent", "show_album_options": "Vis albumindstillinger", "show_albums": "Vis albummer", - "show_all_assets": "Vis alle objekter", "show_all_people": "Vis alle personer", "show_and_hide_people": "Vis & skjul personer", - "show_assets_without_location": "Vis objekter uden lokation", "show_file_location": "Vis filplacering", "show_gallery": "Vis galleri", "show_hidden_people": "Vis skjulte personer", @@ -1866,6 +1896,7 @@ "show_slideshow_transition": "Vis overgang til diasshow", "show_supporter_badge": "SupportermÃĻrke", "show_supporter_badge_description": "Vis et supportermÃĻrke", + "show_text_search_menu": "Vis tekstsøgningsmenu", "shuffle": "Bland", "sidebar": "SidebjÃĻlke", "sidebar_display_description": "Vis et link til visningen i sidebjÃĻlken", @@ -1896,9 +1927,10 @@ "stacktrace": "Stacktrace", "start": "Start", "start_date": "Startdato", + "start_date_before_end_date": "Startdato skal ligge før slutdato", "state": "Stat", "status": "Status", - "stop_casting": "Stop casting", + "stop_casting": "Stop støbning", "stop_motion_photo": "Stopmotionbillede", "stop_photo_sharing": "Stop med at dele dine billeder?", "stop_photo_sharing_description": "{partner} vil ikke lÃĻngere kunne tilgÃĨ dine billeder.", @@ -1920,6 +1952,8 @@ "sync_albums_manual_subtitle": "Synkroniser alle uploadet billeder og videoer til de valgte backupalbummer", "sync_local": "Synkroniser lokalt", "sync_remote": "Synkroniser eksternt", + "sync_status": "Synkroniserings Status", + "sync_status_subtitle": "Se og administrÊr synkroniseringssystemet", "sync_upload_album_setting_subtitle": "Opret og upload dine billeder og videoer til de valgte albummer i Immich", "tag": "Tag", "tag_assets": "Tag mediefiler", @@ -1979,6 +2013,7 @@ "trash_page_select_assets_btn": "VÃĻlg elementer", "trash_page_title": "Papirkurv ({count})", "trashed_items_will_be_permanently_deleted_after": "Mediefiler i skraldespanden vil blive slettet permanent efter {days, plural, one {# dag} other {# dage}}.", + "troubleshoot": "Fejlfinding", "type": "Type", "unable_to_change_pin_code": "Kunne ikke ÃĻndre PIN kode", "unable_to_setup_pin_code": "Kunne ikke sÃĻtte PIN kode", @@ -2034,7 +2069,6 @@ "use_biometric": "Brug biometrisk", "use_current_connection": "brug nuvÃĻrende forbindelse", "use_custom_date_range": "Brug tilpasset datointerval i stedet", - "use_this_location": "Klik for at benytte lokationen", "user": "Bruger", "user_has_been_deleted": "Denne bruger er slettet.", "user_id": "Bruger-ID", @@ -2077,6 +2111,7 @@ "view_next_asset": "Se nÃĻste medie", "view_previous_asset": "Se forrige medie", "view_qr_code": "Vis QR kode", + "view_similar_photos": "Se lignende billeder", "view_stack": "Vis stak", "view_user": "Vis bruger", "viewer_remove_from_stack": "Fjern fra stak", @@ -2095,5 +2130,6 @@ "yes": "Ja", "you_dont_have_any_shared_links": "Du har ikke nogen delte links", "your_wifi_name": "Dit Wi-Fi navn", - "zoom_image": "Zoom billede" + "zoom_image": "Zoom billede", + "zoom_to_bounds": "Zoom til grÃĻnserne" } diff --git a/i18n/de.json b/i18n/de.json index 7d1cfe3ed6..7f81950c29 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -28,10 +28,12 @@ "add_to_album": "Zu Album hinzufÃŧgen", "add_to_album_bottom_sheet_added": "Zu {album} hinzugefÃŧgt", "add_to_album_bottom_sheet_already_exists": "Bereits in {album}", + "add_to_album_bottom_sheet_some_local_assets": "Einige lokale Dateien konnten nicht zum Album hinzugefÃŧgt werden", "add_to_album_toggle": "Auswahl umschalten fÃŧr {album}", "add_to_albums": "Zu Alben hinzufÃŧgen", "add_to_albums_count": "Zu Alben hinzufÃŧgen ({count})", "add_to_shared_album": "Zu geteiltem Album hinzufÃŧgen", + "add_upload_to_stack": "Upload zum Stapel hinzufÃŧgen", "add_url": "URL hinzufÃŧgen", "added_to_archive": "Zum Archiv hinzugefÃŧgt", "added_to_favorites": "Zu Favoriten hinzugefÃŧgt", @@ -47,14 +49,14 @@ "background_task_job": "Hintergrundaufgaben", "backup_database": "Datenbanksicherung erstellen", "backup_database_enable_description": "Datenbank regelmäßig sichern", - "backup_keep_last_amount": "Anzahl der aufzubewahrenden frÃŧheren Backups", + "backup_keep_last_amount": "Anzahl der aufzubewahrenden frÃŧheren Sicherungen", "backup_onboarding_1_description": "Offsite-Kopie in der Cloud oder an einem anderen physischen Ort.", - "backup_onboarding_2_description": "Lokale Kopien auf verschiedenen Geräten. Dazu gehÃļren die Hauptdateien und eine lokale Sicherung dieser Dateien.", - "backup_onboarding_3_description": "3 komplette Kopien deiner Daten, inkl. der Originaldateien. Dies umfasst 1 Kopie an einem anderen Ort und 2 lokale Kopie.", - "backup_onboarding_description": "Eine 3-2-1 Backup-Strategie wird empfohlen, um deine Daten zu schÃŧtzen. Du solltest sowohl Kopien deiner hochgeladenen Fotos/Videos als auch der Immich-Datenbank aufbewahren, um eine umfassende Backup-LÃļsung zu haben.", + "backup_onboarding_2_description": "lokale Kopien auf verschiedenen Geräten. Dazu gehÃļren die Hauptdateien und eine lokale Sicherung dieser Dateien.", + "backup_onboarding_3_description": "Kopien deiner Daten inklusive Originaldateien. Dies umfasst 1 Kopie an einem anderen Ort und 2 lokale Kopien.", + "backup_onboarding_description": "Eine 3-2-1 Sicherungssrategie wird empfohlen, um deine Daten zu schÃŧtzen. Du solltest sowohl Kopien deiner hochgeladenen Fotos/Videos als auch der Immich-Datenbank aufbewahren, um eine umfassende SicherungslÃļsung zu haben.", "backup_onboarding_footer": "Weitere Informationen zum Sichern von Immich findest du in der Dokumentation.", "backup_onboarding_parts_title": "Eine 3-2-1-Sicherung umfasst:", - "backup_onboarding_title": "Backups", + "backup_onboarding_title": "Sicherungen", "backup_settings": "Einstellungen fÃŧr Datenbanksicherung", "backup_settings_description": "Einstellungen zur regelmäßigen Sicherung der Datenbank. Hinweis: Diese Jobs werden nicht Ãŧberwacht und du wirst nicht Ãŧber Fehler informiert.", "cleared_jobs": "Folgende Aufgaben zurÃŧckgesetzt: {job}", @@ -66,9 +68,9 @@ "confirm_user_password_reset": "Bist du sicher, dass du das Passwort fÃŧr {user} zurÃŧcksetzen mÃļchtest?", "confirm_user_pin_code_reset": "Bist du sicher, dass du den PIN Code von {user} zurÃŧcksetzen mÃļchtest?", "create_job": "Aufgabe erstellen", - "cron_expression": "Cron Zeitangabe", - "cron_expression_description": "Setze ein Intervall fÃŧr die Sicherung mittels cron. Hilfe mit dem Format bietet dir dabei z. B. der Crontab Guru", - "cron_expression_presets": "NÃŧtzliche Zeitangaben fÃŧr Cron", + "cron_expression": "Cron-Zeitangabe", + "cron_expression_description": "Setze das Scanintervall im Cron-Format. Hilfe mit dem Format bietet dir dabei z. B. der Crontab Guru", + "cron_expression_presets": "Vorlagen fÃŧr Cron-Zeitangabe", "disable_login": "Login deaktivieren", "duplicate_detection_job_description": "Diese Aufgabe fÃŧhrt das maschinelle Lernen fÃŧr jede Datei aus, um Duplikate zu finden. Diese Aufgabe beruht auf der intelligenten Suche", "exclusion_pattern_description": "Mit Ausschlussmustern kÃļnnen Dateien und Ordner beim Scannen Ihrer Bibliothek ignoriert werden. Dies ist nÃŧtzlich, wenn du Ordner hast, die Dateien enthalten, die du nicht importieren mÃļchtest, wie z. B. RAW-Dateien.", @@ -123,6 +125,13 @@ "logging_enable_description": "Aktiviere Logging", "logging_level_description": "Wenn aktiviert, welches Log-Level genutzt wird.", "logging_settings": "Protokollierung", + "machine_learning_availability_checks": "VerfÃŧgbarkeitschecks", + "machine_learning_availability_checks_description": "Erkenne und bevorzuge verfÃŧgbare Machine Learning Servers", + "machine_learning_availability_checks_enabled": "VerfÃŧgbarkeitschecks einschalten", + "machine_learning_availability_checks_interval": "ÜberprÃŧfungsinterval", + "machine_learning_availability_checks_interval_description": "Interval in Millisekunden zwischen VerfÃŧgbarkeitschecks", + "machine_learning_availability_checks_timeout": "AnfragenzeitÃŧberschreitung", + "machine_learning_availability_checks_timeout_description": "ZeitÃŧberschreitung in Millisekunden fÃŧr VerfÃŧgbarkeitschecks", "machine_learning_clip_model": "CLIP-Modell", "machine_learning_clip_model_description": "Der Name eines CLIP-Modells, welches hier aufgefÃŧhrt ist. Beachte, dass du die Aufgabe \"Intelligente Suche\" fÃŧr alle Bilder erneut ausfÃŧhren musst, wenn du das Modell wechselst.", "machine_learning_duplicate_detection": "Duplikaterkennung", @@ -278,13 +287,13 @@ "storage_template_user_label": "{label} is die Speicherpfadbezeichnung des Benutzers", "system_settings": "Systemeinstellungen", "tag_cleanup_job": "Tags aufräumen", - "template_email_available_tags": "In deiner Vorlage kannst du die folgenden Variablen verwenden: {tags}", - "template_email_if_empty": "Wenn die Vorlage leer ist, wird die Standard-E-Mail verwendet.", - "template_email_invite_album": "E-Mail-Vorlage: Einladung zu Album", + "template_email_available_tags": "Du kannst die folgenden Variablen in deiner Vorlage verwenden: {tags}", + "template_email_if_empty": "Wenn die Vorlage leer ist, wird die Standard-E-Mail-Vorlage verwendet.", + "template_email_invite_album": "Einladung zu Album", "template_email_preview": "Vorschau", "template_email_settings": "E-Mail-Vorlagen", - "template_email_update_album": "Album-Vorlage aktualisieren", - "template_email_welcome": "Willkommen bei den E-Mail-Vorlagen", + "template_email_update_album": "Aktualisiertes Album", + "template_email_welcome": "Willkommens-E-Mail", "template_settings": "Benachrichtigungsvorlagen", "template_settings_description": "Benutzerdefinierte Vorlagen fÃŧr Benachrichtigungen verwalten", "theme_custom_css_settings": "Benutzerdefiniertes CSS", @@ -387,8 +396,6 @@ "admin_password": "Administrator Passwort", "administration": "Verwaltung", "advanced": "Erweitert", - "advanced_settings_beta_timeline_subtitle": "Probier die neue App-Erfahrung aus", - "advanced_settings_beta_timeline_title": "Beta-Timeline", "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: {level}", @@ -425,6 +432,7 @@ "album_remove_user_confirmation": "Bist du sicher, dass du {user} entfernen willst?", "album_search_not_found": "Keine Alben gefunden, die zur Suche passen", "album_share_no_users": "Es sieht so aus, als hättest du dieses Album mit allen Benutzern geteilt oder du hast keine Benutzer, mit denen du teilen kannst.", + "album_summary": "Album Zusammenfassung", "album_updated": "Album aktualisiert", "album_updated_setting_description": "Erhalte eine E-Mail-Benachrichtigung, wenn ein freigegebenes Album neue Dateien enthält", "album_user_left": "{album} verlassen", @@ -496,6 +504,8 @@ "asset_restored_successfully": "Datei erfolgreich wiederhergestellt", "asset_skipped": "Übersprungen", "asset_skipped_in_trash": "Im Papierkorb", + "asset_trashed": "Datei GelÃļscht", + "asset_troubleshoot": "Datei Fehlerbehebung", "asset_uploaded": "Hochgeladen", "asset_uploading": "Hochladenâ€Ļ", "asset_viewer_settings_subtitle": "Verwaltung der Einstellungen fÃŧr die Fotoanzeige", @@ -529,15 +539,18 @@ "autoplay_slideshow": "Automatische Diashow", "back": "ZurÃŧck", "back_close_deselect": "ZurÃŧck, Schließen oder Abwählen", + "background_backup_running_error": "Sicherung läuft im Hintergrund. Manuelle Sicherung kann nicht gestartet werden", "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", + "background_options": "Hintergrund Optionen", "backup": "Sicherung", "backup_album_selection_page_albums_device": "Alben auf dem Gerät ({count})", - "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": "Antippen zum sichern, erneut antippen zum Ausschließen", "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_album_selection_page_selection_info": "Auswahlinformation", + "backup_album_selection_page_total_assets": "Elemente gesamt", + "backup_albums_sync": "Synchronisation der Sicherungsalben", "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â€Ļ", @@ -587,6 +600,7 @@ "backup_controller_page_turn_on": "Sicherung im Vordergrund einschalten", "backup_controller_page_uploading_file_info": "Informationen", "backup_err_only_album": "Das einzige Album kann nicht entfernt werden", + "backup_error_sync_failed": "Synchronisierung fehlgeschlagen. Sicherung kann nicht verarbeitet werden.", "backup_info_card_assets": "Elemente", "backup_manual_cancelled": "Abgebrochen", "backup_manual_in_progress": "Sicherung läuft bereits. Bitte versuche es später erneut", @@ -597,8 +611,6 @@ "backup_setting_subtitle": "Verwaltung der Upload-Einstellungen im Hintergrund und im Vordergrund", "backup_settings_subtitle": "Upload-Einstellungen verwalten", "backward": "RÃŧckwärts", - "beta_sync": "Status der Beta-Synchronisierung", - "beta_sync_subtitle": "Verwalte das neue Synchronisierungssystem", "biometric_auth_enabled": "Biometrische Authentifizierung aktiviert", "biometric_locked_out": "Du bist von der biometrischen Authentifizierung ausgeschlossen", "biometric_no_options": "Keine biometrischen Optionen verfÃŧgbar", @@ -656,6 +668,8 @@ "change_pin_code": "PIN Code ändern", "change_your_password": "Ändere dein Passwort", "changed_visibility_successfully": "Die Sichtbarkeit wurde erfolgreich geändert", + "charging": "Aufladen", + "charging_requirement_mobile_backup": "Backup im Hintergrund erfordert Aufladen des Geräts", "check_corrupt_asset_backup": "Auf beschädigte Asset-Backups ÃŧberprÃŧfen", "check_corrupt_asset_backup_button": "ÜberprÃŧfung durchfÃŧhren", "check_corrupt_asset_backup_description": "FÃŧhre diese PrÃŧfung nur mit aktivierten WLAN durch, nachdem alle Dateien gesichert worden sind. Dieser Vorgang kann ein paar Minuten dauern.", @@ -742,6 +756,7 @@ "create_user": "Nutzer erstellen", "created": "Erstellt", "created_at": "Erstellt", + "creating_linked_albums": "Erstelle verknÃŧpfte Alben...", "crop": "Zuschneiden", "curated_object_page_title": "Dinge", "current_device": "Aktuelles Gerät", @@ -891,7 +906,9 @@ "error": "Fehler", "error_change_sort_album": "Ändern der Anzeigereihenfolge fehlgeschlagen", "error_delete_face": "Fehler beim LÃļschen des Gesichts", + "error_getting_places": "Fehler beim Abrufen der Orte", "error_loading_image": "Fehler beim Laden des Bildes", + "error_loading_partners": "Fehler beim Laden der Partner: {error}", "error_saving_image": "Fehler: {error}", "error_tag_face_bounding_box": "Fehler beim Markieren des Gesichts - Begrenzungen kÃļnnen nicht abgerufen werden", "error_title": "Fehler - Etwas ist schief gelaufen", @@ -1022,6 +1039,7 @@ "exif_bottom_sheet_description_error": "Fehler bei der Aktualisierung der Beschreibung", "exif_bottom_sheet_details": "DETAILS", "exif_bottom_sheet_location": "STANDORT", + "exif_bottom_sheet_no_description": "Keine Beschreibung", "exif_bottom_sheet_people": "PERSONEN", "exif_bottom_sheet_person_add_person": "Namen hinzufÃŧgen", "exit_slideshow": "Diashow beenden", @@ -1056,6 +1074,7 @@ "favorites_page_no_favorites": "Keine favorisierten Inhalte gefunden", "feature_photo_updated": "Profilbild aktualisiert", "features": "Funktionen", + "features_in_development": "Feature in Entwicklung", "features_setting_description": "Funktionen der App verwalten", "file_name": "Dateiname", "file_name_or_extension": "Dateiname oder -erweiterung", @@ -1076,10 +1095,7 @@ "gcast_enabled": "Google Cast", "gcast_enabled_description": "Diese Funktion lädt externe Quellen von Google, um zu funktionieren.", "general": "Allgemein", - "geolocation_instruction_all_have_location": "Alle Dateien fÃŧr dieses Daten enthalten bereits Standortangaben. Versuche alle Dateien anzuzeigen oder wähle ein anderes Datum", "geolocation_instruction_location": "Klicke auf eine Datei mit GPS Koordinaten um diesen Standort zu verwenden oder wähle einen Standort direkt auf der Karte", - "geolocation_instruction_no_date": "Wähle ein Datum um die Standortangaben der Fotos und Videos dieses Datums zu verwalten", - "geolocation_instruction_no_photos": "Keine Fotos oder Videos an diesem Datum gefunden. Wähle ein anderes Datum", "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", "getting_started": "Erste Schritte", @@ -1195,7 +1211,7 @@ "large_files": "Große Dateien", "last": "Letzte", "last_seen": "Zuletzt gesehen", - "latest_version": "Aktuellste Version", + "latest_version": "Aktuelle Version", "latitude": "Breitengrad", "leave": "Verlassen", "leave_album": "Album verlassen", @@ -1223,6 +1239,7 @@ "local": "Lokal", "local_asset_cast_failed": "Eine Datei, die nicht auf den Server hochgeladen wurde, kann nicht gecastet werden", "local_assets": "Lokale Dateien", + "local_media_summary": "Zusammenfassung der lokalen Medien", "local_network": "Lokales Netzwerk", "local_network_sheet_info": "Die App stellt Ãŧber diese URL eine Verbindung zum Server her, wenn sie das angegebene WLAN-Netzwerk verwendet", "location_permission": "Standort Genehmigung", @@ -1234,6 +1251,7 @@ "location_picker_longitude_hint": "Längengrad eingeben", "lock": "Sperren", "locked_folder": "Gesperrter Ordner", + "log_detail_title": "Protokoll Details", "log_out": "Abmelden", "log_out_all_devices": "Alle Geräte abmelden", "logged_in_as": "Angemeldet als {user}", @@ -1264,6 +1282,7 @@ "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?", + "logs": "Protokolle", "longitude": "Längengrad", "look": "Erscheinungsbild", "loop_videos": "Loop-Videos", @@ -1306,6 +1325,7 @@ "mark_as_read": "Als gelesen markieren", "marked_all_as_read": "Alle als gelesen markiert", "matches": "Treffer", + "matching_assets": "Passende Dateien", "media_type": "Medientyp", "memories": "Erinnerungen", "memories_all_caught_up": "Alles aufgeholt", @@ -1344,8 +1364,9 @@ "my_albums": "Meine Alben", "name": "Name", "name_or_nickname": "Name oder Nickname", - "network_requirement_photos_upload": "Mobiles Datennetz verwenden, um Fotos zu sichern", - "network_requirement_videos_upload": "Mobiles Datennetz verwenden, um Videos zu sichern", + "network_requirement_photos_upload": "Mobile Daten verwenden, um Fotos zu sichern", + "network_requirement_videos_upload": "Mobile Daten verwenden, um Videos zu sichern", + "network_requirements": "Anforderungen ans Netzwerk", "network_requirements_updated": "Netzwerk-Abhängigkeiten haben sich geändert, Backup-Warteschlange wird zurÃŧckgesetzt", "networking_settings": "Netzwerk", "networking_subtitle": "Verwaltung von Server-Endpunkt-Einstellungen", @@ -1356,6 +1377,7 @@ "new_person": "Neue Person", "new_pin_code": "Neuer PIN Code", "new_pin_code_subtitle": "Dies ist dein erster Zugriff auf den gesperrten Ordner. Erstelle einen PIN Code fÃŧr den sicheren Zugriff auf diese Seite", + "new_timeline": "Neue Zeitleiste", "new_user_created": "Neuer Benutzer wurde erstellt", "new_version_available": "NEUE VERSION VERFÜGBAR", "newest_first": "Neueste zuerst", @@ -1369,20 +1391,25 @@ "no_assets_message": "KLICKE, UM DEIN ERSTES FOTO HOCHZULADEN", "no_assets_to_show": "Keine Vorschau vorhanden", "no_cast_devices_found": "Keine Geräte zum Übertragen gefunden", + "no_checksum_local": "PrÃŧfsumme nicht verfÃŧgbar - kann lokale Datei/en nicht laden", + "no_checksum_remote": "PrÃŧfsumme nicht verfÃŧgbar - kann entfernte Datei/en nicht laden", "no_duplicates_found": "Es wurden keine Duplikate gefunden.", "no_exif_info_available": "Keine EXIF-Informationen vorhanden", "no_explore_results_message": "Lade weitere Fotos hoch, um deine Sammlung zu erkunden.", "no_favorites_message": "FÃŧge Favoriten hinzu, um deine besten Bilder und Videos schnell zu finden", "no_libraries_message": "Eine externe Bibliothek erstellen, um deine Fotos und Videos anzusehen", + "no_local_assets_found": "Keine lokale Datei mit dieser PrÃŧfsumme gefunden", "no_locked_photos_message": "Fotos und Videos im gesperrten Ordner sind versteckt und werden nicht angezeigt, wenn du deine Bibliothek durchsuchst.", "no_name": "Kein Name", "no_notifications": "Keine Benachrichtigungen", "no_people_found": "Keine passenden Personen gefunden", "no_places": "Keine Orte", + "no_remote_assets_found": "Keine entfernten Dateien mit dieser PrÃŧfsumme gefunden", "no_results": "Keine Ergebnisse", "no_results_description": "Versuche es mit einem Synonym oder einem allgemeineren Stichwort", "no_shared_albums_message": "Erstelle ein Album, um Fotos und Videos mit Personen in deinem Netzwerk zu teilen", "no_uploads_in_progress": "Kein Upload in Bearbeitung", + "not_available": "N/A", "not_in_any_album": "In keinem Album", "not_selected": "Nicht ausgewählt", "note_apply_storage_label_to_previously_uploaded assets": "Hinweis: Um eine Speicherpfadbezeichnung anzuwenden, starte den", @@ -1480,7 +1507,7 @@ "person": "Person", "person_age_months": "{months, plural, one {# month} other {# months}} alt", "person_age_year_months": "1 Jahr, {months, plural, one {# month} other {# months}} alt", - "person_age_years": "{years, plural, other {# years}} alt", + "person_age_years": "{years, plural, one {# Jahr} other {# Jahre}} alt", "person_birthdate": "Geboren am {date}", "person_hidden": "{name}{hidden, select, true { (verborgen)} other {}}", "photo_shared_all_users": "Es sieht so aus, als hättest du deine Fotos mit allen Benutzern geteilt oder du hast keine Benutzer, mit denen du teilen kannst.", @@ -1504,6 +1531,7 @@ "port": "Port", "preferences_settings_subtitle": "App-Einstellungen verwalten", "preferences_settings_title": "Voreinstellungen", + "preparing": "Vorbereiten", "preset": "Voreinstellung", "preview": "Vorschau", "previous": "Vorherige", @@ -1520,7 +1548,7 @@ "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- und Server-Versionen sind aktuell", "profile_drawer_github": "GitHub", - "profile_drawer_readonly_mode": "SchreibgeschÃŧtzter Modus aktiviert. Tippe zweimal auf das Benutzer-Avatar-Symbol, um den Modus zu verlassen.", + "profile_drawer_readonly_mode": "SchreibgeschÃŧtzter Modus aktiviert. Halte das Benutzer-Avatar-Symbol gedrÃŧckt, um den Modus zu verlassen.", "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.", "profile_image_of_user": "Profilbild von {user}", @@ -1546,13 +1574,13 @@ "purchase_license_subtitle": "Kaufe Immich, um die fortlaufende Entwicklung zu unterstÃŧtzen", "purchase_lifetime_description": "Lebenslange GÃŧltigkeit", "purchase_option_title": "KAUFOPTIONEN", - "purchase_panel_info_1": "Die Entwicklung von Immich erfordert viel Zeit und MÃŧhe, und wir haben Vollzeit-Entwickler, die daran arbeiten es mÃļglichst perfekt zu machen. Unser Ziel ist es, dass Open-Source-Software und moralische Geschäftsmethoden zu einer nachhaltigen Einkommensquelle fÃŧr Entwickler werden und ein datenschutzfreundliches Ökosystem mit echten Alternativen zu ausbeuterischen Cloud-Diensten geschaffen wird.", + "purchase_panel_info_1": "Die Entwicklung von Immich erfordert viel Zeit und MÃŧhe und wir haben Vollzeit-Entwickler, die daran arbeiten Immich mÃļglichst perfekt zu machen. Unser Ziel ist es, Open-Source-Software und ethische Geschäftspraktiken zu einer verlässlichen Einkommensquelle fÃŧr Entwickler zu machen und ein datenschutzfreundliches Ökosystem mit echten Alternativen zu ausbeuterischen Cloud-Diensten zu schaffen.", "purchase_panel_info_2": "Weil wir uns dagegen entschieden haben, eine Bezahlschranke einzusetzen, wird dieser Kauf keine zusätzlichen Funktionen in Immich freischalten. Wir verlassen uns auf Nutzende wie dich, um die Entwicklung von Immich zu unterstÃŧtzen.", "purchase_panel_title": "Das Projekt unterstÃŧtzen", "purchase_per_server": "Pro Server", "purchase_per_user": "Pro Benutzer", "purchase_remove_product_key": "ProduktschlÃŧssel entfernen", - "purchase_remove_product_key_prompt": "Sicher, dass der ProduktschlÃŧssel entfernt werden soll?", + "purchase_remove_product_key_prompt": "Bist Du sicher, dass der ProduktschlÃŧssel entfernt werden soll?", "purchase_remove_server_product_key": "Server-ProduktschlÃŧssel entfernen", "purchase_remove_server_product_key_prompt": "Sicher, dass der Server-ProduktschlÃŧssel entfernt werden soll?", "purchase_server_description_1": "FÃŧr den gesamten Server", @@ -1569,6 +1597,7 @@ "read_changelog": "Changelog lesen", "readonly_mode_disabled": "SchreibgeschÃŧtzter Modus deaktiviert", "readonly_mode_enabled": "SchreibgeschÃŧtzter Modus aktiviert", + "ready_for_upload": "Bereit zum Hochladen", "reassign": "Neu zuweisen", "reassigned_assets_to_existing_person": "{count, plural, one {# Datei wurde} other {# Dateien wurden}} {name, select, null {einer vorhandenen Person} other {{name}}} zugewiesen", "reassigned_assets_to_new_person": "{count, plural, one {# Datei wurde} other {# Dateien wurden}} einer neuen Person zugewiesen", @@ -1593,6 +1622,7 @@ "regenerating_thumbnails": "Miniaturansichten werden neu erstellt", "remote": "Server", "remote_assets": "Server-Dateien", + "remote_media_summary": "Zusammenfassung der entfernten Medien", "remove": "Entfernen", "remove_assets_album_confirmation": "Bist du sicher, dass du {count, plural, one {# Datei} other {# Dateien}} aus dem Album entfernen willst?", "remove_assets_shared_link_confirmation": "Bist du sicher, dass du {count, plural, one {# Datei} other {# Dateien}} von diesem geteilten Link entfernen willst?", @@ -1645,6 +1675,7 @@ "restore_user": "Nutzer wiederherstellen", "restored_asset": "Datei wiederhergestellt", "resume": "Fortsetzen", + "resume_paused_jobs": "{count, plural, one {# Aufgabe fortsetzen } other {# Aufgaben fortsetzen}}", "retry_upload": "Upload wiederholen", "review_duplicates": "Duplikate ÃŧberprÃŧfen", "review_large_files": "Große Dateien ÃŧberprÃŧfen", @@ -1849,10 +1880,8 @@ "shift_to_permanent_delete": "DrÃŧcke ⇧, um die Datei endgÃŧltig zu lÃļschen", "show_album_options": "Album-Optionen anzeigen", "show_albums": "Alben anzeigen", - "show_all_assets": "Alle Dateien anzeigen", "show_all_people": "Alle Personen anzeigen", "show_and_hide_people": "Personen ein- & ausblenden", - "show_assets_without_location": "Zeige Dateien ohne Ortsangabe", "show_file_location": "Dateispeicherort anzeigen", "show_gallery": "Galerie anzeigen", "show_hidden_people": "Ausgeblendete Personen anzeigen", @@ -1869,6 +1898,7 @@ "show_slideshow_transition": "Slideshow-Übergang anzeigen", "show_supporter_badge": "UnterstÃŧtzerabzeichen", "show_supporter_badge_description": "Zeige UnterstÃŧtzerabzeichen", + "show_text_search_menu": "Zeige MenÃŧ fÃŧr Textsuche", "shuffle": "Durchmischen", "sidebar": "Seitenleiste", "sidebar_display_description": "Zeige einen Link zu der Ansicht in der Seitenleiste an", @@ -1899,6 +1929,7 @@ "stacktrace": "Stapelaufgaben", "start": "Starten", "start_date": "Anfangsdatum", + "start_date_before_end_date": "Anfangsdatum muss vor dem Enddatum liegen", "state": "Bundesland / Provinz", "status": "Status", "stop_casting": "Übertragung stoppen", @@ -1923,7 +1954,9 @@ "sync_albums_manual_subtitle": "Synchronisiere alle hochgeladenen Videos und Fotos in die ausgewählten Backup-Alben", "sync_local": "Lokal synchronisieren", "sync_remote": "mit Server synchronisieren", - "sync_upload_album_setting_subtitle": "Erstelle deine ausgewählten Alben in Immich und lade die Fotos und Videos dort hoch", + "sync_status": "Synchronisierungstatus", + "sync_status_subtitle": "Synchronisierungssystem anzeigen und bearbeiten", + "sync_upload_album_setting_subtitle": "Erstelle und lade deine ausgewählten Fotos und Videos in die ausgewählten Alben auf Immich hoch", "tag": "Tag", "tag_assets": "Dateien taggen", "tag_created": "Tag erstellt: {tag}", @@ -1982,6 +2015,7 @@ "trash_page_select_assets_btn": "Elemente auswählen", "trash_page_title": "Papierkorb ({count})", "trashed_items_will_be_permanently_deleted_after": "GelÃļschte Objekte werden nach {days, plural, one {# Tag} other {# Tagen}} endgÃŧltig gelÃļscht.", + "troubleshoot": "Fehler beheben", "type": "Typ", "unable_to_change_pin_code": "PIN Code konnte nicht geändert werden", "unable_to_setup_pin_code": "PIN Code konnte nicht festgelegt werden", @@ -2037,7 +2071,6 @@ "use_biometric": "Biometrie verwenden", "use_current_connection": "aktuelle Verbindung verwenden", "use_custom_date_range": "Stattdessen einen benutzerdefinierten Datumsbereich verwenden", - "use_this_location": "Klicken um Ort zu verwenden", "user": "Nutzer", "user_has_been_deleted": "Dieser Benutzer wurde gelÃļscht.", "user_id": "Nutzer-ID", @@ -2099,5 +2132,6 @@ "yes": "Ja", "you_dont_have_any_shared_links": "Du hast keine geteilten Links", "your_wifi_name": "Dein WLAN-Name", - "zoom_image": "Bild vergrÃļßern" + "zoom_image": "Bild vergrÃļßern", + "zoom_to_bounds": "In die Grenzen zoomen" } diff --git a/i18n/el.json b/i18n/el.json index 1394c24ec9..6f6835b441 100644 --- a/i18n/el.json +++ b/i18n/el.json @@ -28,10 +28,12 @@ "add_to_album": "Î ĪÎŋĪƒÎ¸ÎŽÎēΡ ΃Îĩ ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ", "add_to_album_bottom_sheet_added": "Î ĪÎŋĪƒĪ„Î­Î¸ÎˇÎēÎĩ ĪƒĪ„Îŋ {album}", "add_to_album_bottom_sheet_already_exists": "Ήδη ĪƒĪ„Îŋ {album}", + "add_to_album_bottom_sheet_some_local_assets": "ÎŸĪÎšĪƒÎŧέÎŊÎŋΚ Ī„ÎŋĪ€ÎšÎēÎŦ ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Îą δÎĩÎŊ ÎŧĪ€ĪŒĪÎĩĪƒÎąÎŊ ÎŊÎą ΀΁ÎŋĪƒĪ„ÎĩθÎŋĪÎŊ ĪƒĪ„Îŋ ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ", "add_to_album_toggle": "ΕÎŊÎąÎģÎģÎąÎŗÎŽ ÎĩĪ€ÎšÎģÎŋÎŗÎŽĪ‚ ÎŗÎšÎą Ī„Îŋ {album}", "add_to_albums": "Î ĪÎŋĪƒÎ¸ÎŽÎēΡ ĪƒĪ„Îą ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ", "add_to_albums_count": "Î ĪÎŋĪƒÎ¸ÎŽÎēΡ ĪƒĪ„Îą ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ ({count})", "add_to_shared_album": "Î ĪÎŋĪƒÎ¸ÎŽÎēΡ ΃Îĩ ÎēÎŋΚÎŊĪŒĪ‡ĪÎˇĪƒĪ„Îŋ ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ", + "add_upload_to_stack": "Î ĪÎŋĪƒÎ¸ÎŽÎēΡ ÎąĪĪ‡ÎĩίÎŋĪ… ĪƒĪ„ÎˇÎŊ Îŋ΅΁ÎŦ", "add_url": "Î ĪÎŋĪƒÎ¸ÎŽÎēΡ ÎŖĪ…ÎŊÎ´Î­ĪƒÎŧÎŋĪ…", "added_to_archive": "Î ĪÎŋĪƒĪ„Î­Î¸ÎˇÎēÎĩ ĪƒĪ„Îŋ ÎąĪĪ‡ÎĩίÎŋ", "added_to_favorites": "Î ĪÎŋĪƒĪ„Î­Î¸ÎˇÎēÎĩ ĪƒĪ„Îą ÎąÎŗÎąĪ€ÎˇÎŧέÎŊÎą", @@ -123,6 +125,13 @@ "logging_enable_description": "ΕÎŊÎĩĪÎŗÎŋĪ€ÎŋÎ¯ÎˇĪƒÎˇ ÎēÎąĪ„ÎąÎŗĪÎąĪ†ÎŽĪ‚ ĪƒĪ…ÎŧβÎŦÎŊ΄ΉÎŊ", "logging_level_description": "ΤÎŋ ÎĩĪ€Î¯Ī€ÎĩδÎŋ ÎēÎąĪ„ÎąÎŗĪÎąĪ†ÎŽĪ‚ ĪƒĪ…ÎŧβÎŦÎŊ΄ΉÎŊ Ī€ÎŋĪ… θι ÎĩĪ†ÎąĪÎŧÎŋĪƒĪ„Îĩί, ĪŒĪ„ÎąÎŊ ÎąĪ…Ī„ÎŽ ÎĩίÎŊιΚ ÎĩÎŊÎĩĪÎŗÎŋĪ€ÎŋΚΡÎŧέÎŊΡ.", "logging_settings": "ÎšÎąĪ„ÎąÎŗĪÎąĪ†ÎŽ ÎŖĪ…ÎŧβÎŦÎŊ΄ΉÎŊ", + "machine_learning_availability_checks": "ΈÎģÎĩÎŗĪ‡ÎŋΚ δΚιθÎĩĪƒÎšÎŧĪŒĪ„ÎˇĪ„ÎąĪ‚", + "machine_learning_availability_checks_description": "Î‘Ī…Ī„ĪŒÎŧÎąĪ„ÎŋĪ‚ ÎąÎŊÎ¯Ī‡ÎŊÎĩĪ…ĪƒÎˇ ÎēιΚ ΀΁ÎŋĪ„Î¯ÎŧÎˇĪƒÎˇ Î´ÎšÎąÎ¸Î­ĪƒÎšÎŧΉÎŊ δΚιÎēÎŋÎŧÎšĪƒĪ„ĪŽÎŊ ÎŧÎˇĪ‡ÎąÎŊΚÎēÎŽĪ‚ ÎŧÎŦÎ¸ÎˇĪƒÎˇĪ‚", + "machine_learning_availability_checks_enabled": "ΕÎŊÎĩĪÎŗÎŋĪ€ÎŋÎ¯ÎˇĪƒÎˇ ÎĩÎģÎ­ÎŗĪ‡Ī‰ÎŊ δΚιθÎĩĪƒÎšÎŧĪŒĪ„ÎˇĪ„ÎąĪ‚", + "machine_learning_availability_checks_interval": "ΔιÎŦĪƒĪ„ÎˇÎŧÎą ÎĩÎģÎ­ÎŗĪ‡ÎŋĪ…", + "machine_learning_availability_checks_interval_description": "ΔιÎŦĪƒĪ„ÎˇÎŧÎą ΃Îĩ Ī‡ÎšÎģΚÎŋĪƒĪ„ÎŦ δÎĩĪ…Ī„Îĩ΁ÎŋÎģÎ­Ī€Ī„ÎŋĪ… ÎŧÎĩĪ„ÎąÎžĪ ΄ΉÎŊ ÎĩÎģÎ­ÎŗĪ‡Ī‰ÎŊ δΚιθÎĩĪƒÎšÎŧĪŒĪ„ÎˇĪ„ÎąĪ‚", + "machine_learning_availability_checks_timeout": "Î‘Î¯Ī„ÎˇÎŧÎą ·΁ÎŋÎŊΚÎēÎŋĪ ÎŋĪÎ¯ÎŋĪ… ÎģÎŽÎžÎˇĪ‚", + "machine_learning_availability_checks_timeout_description": "Î§ĪÎŋÎŊΚÎēΌ ĪŒĪÎšÎŋ ΃Îĩ Ī‡ÎšÎģΚÎŋĪƒĪ„ÎŦ δÎĩĪ…Ī„Îĩ΁ÎŋÎģÎ­Ī€Ī„ÎŋĪ… ÎŗÎšÎą ÎĩÎģÎ­ÎŗĪ‡ÎŋĪ…Ī‚ δΚιθÎĩĪƒÎšÎŧĪŒĪ„ÎˇĪ„ÎąĪ‚", "machine_learning_clip_model": "ΜÎŋÎŊĪ„Î­ÎģÎŋ CLIP", "machine_learning_clip_model_description": "ΤÎŋ ΌÎŊÎŋÎŧÎą ÎĩÎŊĪŒĪ‚ ÎŧÎŋÎŊĪ„Î­ÎģÎŋĪ… CLIP Ī€ÎŋĪ… ÎąÎŊÎąĪ†Î­ĪÎĩĪ„ÎąÎš ÎĩÎ´ĪŽ. ÎŖÎˇÎŧÎĩÎšĪŽĪƒĪ„Îĩ ĪŒĪ„Îš Ī€ĪÎ­Ī€ÎĩΚ ÎŊÎą ÎĩĪ€ÎąÎŊÎĩÎēĪ„ÎĩÎģÎ­ĪƒÎĩĪ„Îĩ Ī„ÎˇÎŊ ÎĩĪÎŗÎąĪƒÎ¯Îą 'ÎˆÎžĪ…Ī€ÎŊΡ ΑÎŊÎąÎļÎŽĪ„ÎˇĪƒÎˇ' ÎŗÎšÎą ΌÎģÎĩĪ‚ Ī„ÎšĪ‚ ÎĩΚÎēΌÎŊÎĩĪ‚ ÎŧÎĩĪ„ÎŦ Ī„ÎˇÎŊ ÎąÎģÎģÎąÎŗÎŽ ÎŧÎŋÎŊĪ„Î­ÎģÎŋĪ….", "machine_learning_duplicate_detection": "ΕÎŊĪ„ÎŋĪ€ÎšĪƒÎŧĪŒĪ‚ Î”ÎšĪ€ÎģĪŒĪ„Ī…Ī€Ī‰ÎŊ", @@ -387,8 +396,6 @@ "admin_password": "ÎšĪ‰Î´ÎšÎēĪŒĪ‚ Ī€ĪĪŒĪƒÎ˛ÎąĪƒÎˇĪ‚ Î”ÎšÎąĪ‡ÎĩÎšĪÎšĪƒĪ„ÎŽ", "administration": "Î”ÎšÎąĪ‡ÎĩÎ¯ĪÎšĪƒÎˇ", "advanced": "Για ΀΁ÎŋĪ‡Ī‰ĪÎˇÎŧέÎŊÎŋĪ…Ī‚", - "advanced_settings_beta_timeline_subtitle": "ΔÎŋÎēίÎŧÎąĪƒÎĩ Ī„Îˇ ÎŊέι ÎĩÎŧĪ€ÎĩÎšĪÎ¯Îą Ī„ÎˇĪ‚ ÎĩĪ†ÎąĪÎŧÎŋÎŗÎŽĪ‚", - "advanced_settings_beta_timeline_title": "ΔÎŋÎēΚÎŧÎąĪƒĪ„ÎšÎēΌ ·΁ÎŋÎŊÎŋÎģĪŒÎŗÎšÎŋ", "advanced_settings_enable_alternate_media_filter_subtitle": "Î§ĪÎˇĪƒÎšÎŧÎŋĪ€ÎŋÎšÎŽĪƒĪ„Îĩ ÎąĪ…Ī„ÎŽÎŊ Ī„ÎˇÎŊ ÎĩĪ€ÎšÎģÎŋÎŗÎŽ ÎŗÎšÎą ÎŊÎą Ī†ÎšÎģ΄΁ÎŦ΁ÎĩĪ„Îĩ Ī„Îą ÎŧÎ­ĪƒÎą ÎĩÎŊΡÎŧÎ­ĪĪ‰ĪƒÎˇĪ‚ ÎēÎąĪ„ÎŦ Ī„ÎŋÎŊ ĪƒĪ…ÎŗĪ‡ĪÎŋÎŊÎšĪƒÎŧΌ ÎŧÎĩ βÎŦĪƒÎˇ ÎĩÎŊÎąÎģÎģÎąÎēĪ„ÎšÎēÎŦ ÎēĪÎšĪ„ÎŽĪÎšÎą. ΔÎŋÎēΚÎŧÎŦĪƒĪ„Îĩ ÎąĪ…Ī„ÎŽ Ī„Îˇ Î´Ī…ÎŊÎąĪ„ĪŒĪ„ÎˇĪ„Îą ÎŧΌÎŊÎŋ ÎąÎŊ Î­Ī‡ÎĩĪ„Îĩ ΀΁ÎŋβÎģÎŽÎŧÎąĪ„Îą ÎŧÎĩ Ī„ÎˇÎŊ ÎĩĪ†ÎąĪÎŧÎŋÎŗÎŽ Ī€ÎŋĪ… ÎĩÎŊĪ„ÎŋĪ€Î¯ÎļÎĩΚ ΌÎģÎą Ī„Îą ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ.", "advanced_settings_enable_alternate_media_filter_title": "[ΠΕΙΡΑΜΑΤΙΚΟ] Î§ĪÎŽĪƒÎˇ ÎĩÎŊÎąÎģÎģÎąÎēĪ„ÎšÎēÎŋĪ Ī†Î¯Îģ΄΁ÎŋĪ… ĪƒĪ…ÎŗĪ‡ĪÎŋÎŊÎšĪƒÎŧÎŋĪ ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ ĪƒĪ…ĪƒÎēÎĩĪ…ÎŽĪ‚", "advanced_settings_log_level_title": "Î•Ī€Î¯Ī€ÎĩδÎŋ ĪƒĪÎŊδÎĩĪƒÎˇĪ‚: {level}", @@ -396,6 +403,8 @@ "advanced_settings_prefer_remote_title": "Î ĪÎŋĪ„Î¯ÎŧÎˇĪƒÎˇ ÎąĪ€ÎŋÎŧÎąÎēĪĪ…ĪƒÎŧέÎŊΉÎŊ ÎĩΚÎēΌÎŊΉÎŊ", "advanced_settings_proxy_headers_subtitle": "ΚαθÎŋĪÎšĪƒÎŧĪŒĪ‚ ÎēÎĩĪ†ÎąÎģÎ¯Î´Ī‰ÎŊ δΚιÎēÎŋÎŧÎšĪƒĪ„ÎŽ ÎŧÎĩ΃ÎŋÎģÎŦÎ˛ÎˇĪƒÎˇĪ‚ Ī€ÎŋĪ… Ī„Îŋ Immich Ī€ĪÎ­Ī€ÎĩΚ ÎŊÎą ĪƒĪ„Î­ÎģÎŊÎĩΚ ÎŧÎĩ ÎēÎŦθÎĩ ÎąÎ¯Ī„ÎˇÎŧÎą δΚÎēĪ„ĪÎŋĪ…", "advanced_settings_proxy_headers_title": "ΚÎĩĪ†ÎąÎģίδÎĩĪ‚ δΚιÎēÎŋÎŧÎšĪƒĪ„ÎŽ ÎŧÎĩ΃ÎŋÎģÎŦÎ˛ÎˇĪƒÎˇĪ‚", + "advanced_settings_readonly_mode_subtitle": "ΕÎŊÎĩĪÎŗÎŋĪ€ÎŋΚÎĩί Ī„Îˇ ÎģÎĩÎšĪ„ÎŋĪ…ĪÎŗÎ¯Îą ÎŧΌÎŊÎŋ-ÎŗÎšÎą-ÎąÎŊÎŦÎŗÎŊĪ‰ĪƒÎˇ, ĪŒĪ€ÎŋĪ… ÎŋΚ ΆΉ΄ÎŋÎŗĪÎąĪ†Î¯ÎĩĪ‚ ÎŧĪ€Îŋ΁ÎŋĪÎŊ ÎŧΌÎŊÎŋ ÎŊÎą ΀΁ÎŋβÎģΡθÎŋĪÎŊ. ΕÎŊÎ­ĪÎŗÎĩΚÎĩĪ‚ ĪŒĪ€Ī‰Ī‚ ÎĩĪ€ÎšÎģÎŋÎŗÎŽ Ī€ÎŋÎģÎģĪŽÎŊ ÎĩΚÎēΌÎŊΉÎŊ, ÎēÎŋΚÎŊÎŽ Ī‡ĪÎŽĪƒÎˇ, ÎąĪ€ÎŋĪƒĪ„ÎŋÎģÎŽ (casting) ÎēιΚ Î´ÎšÎąÎŗĪÎąĪ†ÎŽ ÎĩίÎŊιΚ ÎąĪ€ÎĩÎŊÎĩĪÎŗÎŋĪ€ÎŋΚΡÎŧέÎŊÎĩĪ‚. Η ÎĩÎŊÎĩĪÎŗÎŋĪ€ÎŋÎ¯ÎˇĪƒÎˇ/ÎąĪ€ÎĩÎŊÎĩĪÎŗÎŋĪ€ÎŋÎ¯ÎˇĪƒÎˇ Ī„ÎˇĪ‚ ÎģÎĩÎšĪ„ÎŋĪ…ĪÎŗÎ¯ÎąĪ‚ ÎŧΌÎŊÎŋ-ÎŗÎšÎą-ÎąÎŊÎŦÎŗÎŊĪ‰ĪƒÎˇ ÎŗÎ¯ÎŊÎĩĪ„ÎąÎš ÎŧÎ­ĪƒĪ‰ Ī„ÎˇĪ‚ ÎĩΚÎēΌÎŊÎąĪ‚ Ī„ÎŋĪ… Ī‡ĪÎŽĪƒĪ„Îˇ ÎąĪ€ĪŒ Ī„ÎˇÎŊ ÎēÎĩÎŊĪ„ĪÎšÎēÎŽ ÎŋÎ¸ĪŒÎŊΡ", + "advanced_settings_readonly_mode_title": "ΛÎĩÎšĪ„ÎŋĪ…ĪÎŗÎ¯Îą ÎŧΌÎŊÎŋ-ÎŗÎšÎą-ÎąÎŊÎŦÎŗÎŊĪ‰ĪƒÎˇ", "advanced_settings_self_signed_ssl_subtitle": "Î ÎąĪÎąÎēÎŦÎŧ΀΄ÎĩΚ Ī„ÎŋÎŊ έÎģÎĩÎŗĪ‡Îŋ Ī€ÎšĪƒĪ„ÎŋĪ€ÎŋÎšÎˇĪ„ÎšÎēÎŋĪ SSL Ī„ÎŋĪ… δΚιÎēÎŋÎŧÎšĪƒĪ„ÎŽ. Î‘Ī€ÎąĪÎąÎ¯Ī„ÎˇĪ„Îŋ ÎŗÎšÎą ÎąĪ…Ī„Îŋ-Ī…Ī€ÎŋÎŗÎĩÎŗĪÎąÎŧÎŧέÎŊÎą Ī€ÎšĪƒĪ„ÎŋĪ€ÎŋÎšÎˇĪ„ÎšÎēÎŦ.", "advanced_settings_self_signed_ssl_title": "Να ÎĩĪ€ÎšĪ„ĪÎ­Ī€ÎŋÎŊĪ„ÎąÎš ÎąĪ…Ī„Îŋ-Ī…Ī€ÎŋÎŗÎĩÎŗĪÎąÎŧÎŧέÎŊÎą Ī€ÎšĪƒĪ„ÎŋĪ€ÎŋÎšÎˇĪ„ÎšÎēÎŦ SSL", "advanced_settings_sync_remote_deletions_subtitle": "Î‘Ī…Ī„ĪŒÎŧÎąĪ„Îˇ Î´ÎšÎąÎŗĪÎąĪ†ÎŽ ÎŽ ÎĩĪ€ÎąÎŊÎąĪ†Îŋ΁ÎŦ ÎĩÎŊĪŒĪ‚ Ī€ÎĩĪÎšÎŋĪ…ĪƒÎšÎąÎēÎŋĪ ĪƒĪ„ÎŋÎšĪ‡ÎĩίÎŋĪ… ΃Îĩ ÎąĪ…Ī„ÎŽ Ī„Îˇ ĪƒĪ…ĪƒÎēÎĩĪ…ÎŽ, ĪŒĪ„ÎąÎŊ Ρ ÎĩÎŊÎ­ĪÎŗÎĩΚι ÎąĪ…Ī„ÎŽ Ī€ĪÎąÎŗÎŧÎąĪ„ÎŋĪ€ÎŋΚÎĩÎ¯Ī„ÎąÎš ĪƒĪ„Îŋ Î´ÎšÎąÎ´Î¯Îē΄΅Îŋ", @@ -423,6 +432,7 @@ "album_remove_user_confirmation": "Î•Î¯ĪƒĪ„Îĩ ĪƒÎ¯ÎŗÎŋ΅΁ÎŋΚ ĪŒĪ„Îš θέÎģÎĩĪ„Îĩ ÎŊÎą ÎąĪ†ÎąÎšĪÎ­ĪƒÎĩĪ„Îĩ Ī„ÎŋÎŊ/Ī„ÎˇÎŊ {user};", "album_search_not_found": "ΔÎĩ Î˛ĪÎ­Î¸ÎˇÎēÎąÎŊ ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ Ī€ÎŋĪ… ÎŊÎą Ī„ÎąÎšĪÎšÎŦÎļÎŋĪ…ÎŊ ÎŧÎĩ Ī„ÎˇÎŊ ÎąÎŊÎąÎļÎŽĪ„ÎˇĪƒÎŽ ĪƒÎąĪ‚", "album_share_no_users": "ÎĻÎąÎ¯ÎŊÎĩĪ„ÎąÎš ĪŒĪ„Îš Î­Ī‡ÎĩĪ„Îĩ ÎēÎŋΚÎŊÎŋĪ€ÎŋÎšÎŽĪƒÎĩΚ ÎąĪ…Ī„ĪŒ Ī„Îŋ ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ ΃Îĩ ΌÎģÎŋĪ…Ī‚ Ī„ÎŋĪ…Ī‚ Ī‡ĪÎŽĪƒĪ„ÎĩĪ‚ ÎŽ δÎĩÎŊ Î­Ī‡ÎĩĪ„Îĩ Ī‡ĪÎŽĪƒĪ„ÎĩĪ‚ ÎŗÎšÎą ÎŊÎą Ī„Îŋ ÎēÎŋΚÎŊÎŋĪ€ÎŋÎšÎŽĪƒÎĩĪ„Îĩ.", + "album_summary": "ΠÎĩĪÎ¯ÎģÎˇĪˆÎˇ ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ", "album_updated": "ΤÎŋ ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ, ÎĩÎŊΡÎŧÎĩĪĪŽÎ¸ÎˇÎēÎĩ", "album_updated_setting_description": "ΛÎŦβÎĩĪ„Îĩ ÎĩΚδÎŋĪ€ÎŋÎ¯ÎˇĪƒÎˇ ÎŧÎ­ĪƒĪ‰ email ĪŒĪ„ÎąÎŊ έÎŊÎą ÎēÎŋΚÎŊĪŒĪ‡ĪÎˇĪƒĪ„Îŋ ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ Î­Ī‡ÎĩΚ ÎŊέι ÎąĪĪ‡ÎĩÎ¯Îą", "album_user_left": "Î‘Ī€ÎŋĪ‡Ī‰ĪÎŽĪƒÎąĪ„Îĩ ÎąĪ€ĪŒ Ī„Îŋ {album}", @@ -461,6 +471,7 @@ "app_bar_signout_dialog_title": "Î‘Ī€ÎŋĪƒĪÎŊδÎĩĪƒÎˇ", "app_settings": "ÎĄĪ…Î¸ÎŧÎ¯ĪƒÎĩÎšĪ‚ ÎĩĪ†ÎąĪÎŧÎŋÎŗÎŽĪ‚", "appears_in": "ΕÎŧĪ†ÎąÎŊίÎļÎĩĪ„ÎąÎš ΃Îĩ", + "apply_count": "Î•Ī†ÎąĪÎŧÎŋÎŗÎŽ ({count, number})", "archive": "Î‘ĪĪ‡ÎĩίÎŋ", "archive_action_prompt": "Î ĪÎŋĪƒĪ„Î­Î¸ÎˇÎēÎąÎŊ {count} ĪƒĪ„Îŋ Î‘ĪĪ‡ÎĩίÎŋ", "archive_or_unarchive_photo": "Î‘ĪĪ‡ÎĩΚÎŋÎ¸Î­Ī„ÎˇĪƒÎˇ ÎŽ ÎąĪ€ÎŋÎąĪĪ‡ÎĩΚÎŋÎ¸Î­Ī„ÎˇĪƒÎˇ ΆΉ΄ÎŋÎŗĪÎąĪ†Î¯ÎąĪ‚", @@ -493,6 +504,8 @@ "asset_restored_successfully": "ΤÎŋ ĪƒĪ„ÎŋÎšĪ‡ÎĩίÎŋ ÎąĪ€ÎŋÎēÎąĪ„ÎąĪƒĪ„ÎŦθΡÎēÎĩ ÎŧÎĩ ÎĩĪ€ÎšĪ„Ī…Ī‡Î¯Îą", "asset_skipped": "Î ÎąĪÎąÎģÎĩÎ¯Ī†Î¸ÎˇÎēÎĩ", "asset_skipped_in_trash": "ÎŖĪ„ÎŋÎŊ ÎēÎŦδÎŋ ÎąĪ€ÎŋĪĪÎšÎŧÎŧÎŦ΄ΉÎŊ", + "asset_trashed": "ΤÎŋ ĪƒĪ„ÎŋÎšĪ‡ÎĩίÎŋ Î´ÎšÎąÎŗĪÎŦĪ†ÎˇÎēÎĩ", + "asset_troubleshoot": "ΑÎŊĪ„ÎšÎŧÎĩĪ„ĪŽĪ€ÎšĪƒÎˇ ΀΁ÎŋβÎģÎŽÎŧÎąĪ„ÎŋĪ‚ ĪƒĪ„ÎŋÎšĪ‡ÎĩίÎŋĪ…", "asset_uploaded": "ΑÎŊÎĩβÎŦĪƒĪ„ÎˇÎēÎĩ", "asset_uploading": "ΑÎŊÎĩβÎŦÎļÎĩĪ„ÎąÎšâ€Ļ", "asset_viewer_settings_subtitle": "Î”ÎšÎąĪ‡ÎĩÎ¯ĪÎšĪƒÎˇ ĪĪ…Î¸ÎŧÎ¯ĪƒÎĩΉÎŊ ΀΁ÎŋβÎŋÎģÎŽĪ‚ ĪƒĪ…ÎģÎģÎŋÎŗÎŽĪ‚", @@ -526,8 +539,10 @@ "autoplay_slideshow": "Î‘Ī…Ī„ĪŒÎŧÎąĪ„Îˇ ÎąÎŊÎąĪ€ÎąĪÎąÎŗĪ‰ÎŗÎŽ Ī€ÎąĪÎŋĪ…ĪƒÎ¯ÎąĪƒÎˇĪ‚", "back": "Î Î¯ĪƒĪ‰", "back_close_deselect": "Î Î¯ĪƒĪ‰, ÎēÎģÎĩÎ¯ĪƒÎšÎŧÎŋ ÎŽ ÎąĪ€ÎŋÎĩĪ€ÎšÎģÎŋÎŗÎŽ", + "background_backup_running_error": "Η δΡÎŧΚÎŋĪ…ĪÎŗÎ¯Îą ÎąÎŊĪ„ÎšÎŗĪÎŦΆΉÎŊ ÎąĪƒĪ†ÎŦÎģÎĩÎšÎąĪ‚ ĪƒĪ„Îŋ Ī€ÎąĪÎąĪƒÎēÎŽÎŊΚÎŋ ÎĩÎēĪ„ÎĩÎģÎĩÎ¯Ī„ÎąÎš ΎδΡ, δÎĩÎŊ ÎŧĪ€Îŋ΁Îĩί ÎŊÎą ΞÎĩÎēΚÎŊÎŽĪƒÎĩĪ„Îĩ ·ÎĩÎšĪÎŋÎēίÎŊÎˇĪ„Îŋ ÎąÎŊĪ„Î¯ÎŗĪÎąĪ†Îŋ ÎąĪƒĪ†ÎŦÎģÎĩÎšÎąĪ‚", "background_location_permission": "ΆδÎĩΚι Ī„ÎŋĪ€ÎŋθÎĩĪƒÎ¯ÎąĪ‚ ĪƒĪ„Îŋ Ī€ÎąĪÎąĪƒÎēÎŽÎŊΚÎŋ", "background_location_permission_content": "ΤÎŋ Immich ÎŗÎšÎą ÎŊÎą ÎŧĪ€Îŋ΁Îĩί ÎŊÎą ÎąÎģÎģÎŦÎļÎĩΚ δίÎēĪ„Ī…Îą ĪŒĪ„ÎąÎŊ Ī„ĪÎ­Ī‡ÎĩΚ ĪƒĪ„Îŋ Ī€ÎąĪÎąĪƒÎēÎŽÎŊΚÎŋ, Ī€ĪÎ­Ī€ÎĩΚ *Ī€ÎŦÎŊĪ„Îą* ÎŊÎą Î­Ī‡ÎĩΚ Ī€ĪĪŒĪƒÎ˛ÎąĪƒÎˇ ĪƒĪ„ÎˇÎŊ ÎąÎēĪÎšÎ˛ÎŽ Ī„ÎŋĪ€ÎŋθÎĩĪƒÎ¯Îą ĪŽĪƒĪ„Îĩ Ρ ÎĩĪ†ÎąĪÎŧÎŋÎŗÎŽ ÎŊÎą ÎŧĪ€Îŋ΁Îĩί ÎŊÎą δΚιβÎŦÎļÎĩΚ Ī„Îŋ ΌÎŊÎŋÎŧÎą Ī„ÎŋĪ… δΚÎēĪ„ĪÎŋĪ… Wi-Fi", + "background_options": "Î•Ī€ÎšÎģÎŋÎŗÎ­Ī‚ Ī€ÎąĪÎąĪƒÎēΡÎŊίÎŋĪ…", "backup": "ΑÎŊĪ„Î¯ÎŗĪÎąĪ†Îŋ ÎąĪƒĪ†ÎąÎģÎĩÎ¯ÎąĪ‚", "backup_album_selection_page_albums_device": "ΆÎģÎŧĪ€ÎŋĪ…Îŧ ĪƒĪ„Îˇ ĪƒĪ…ĪƒÎēÎĩĪ…ÎŽ ({count})", "backup_album_selection_page_albums_tap": "ΠÎŦĪ„ÎˇÎŧÎą ÎŗÎšÎą ĪƒĪ…ÎŧĪ€ÎĩĪÎ¯ÎģÎˇĪˆÎˇ, Î´ÎšĪ€ÎģΌ Ī€ÎŦĪ„ÎˇÎŧÎą ÎŗÎšÎą ÎĩÎžÎąÎ¯ĪÎĩĪƒÎˇ", @@ -535,6 +550,7 @@ "backup_album_selection_page_select_albums": "Î•Ī€ÎšÎģÎŋÎŗÎŽ ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ", "backup_album_selection_page_selection_info": "ΠÎģÎˇĪÎŋΆÎŋĪÎ¯ÎĩĪ‚ ÎĩĪ€ÎšÎģÎŋÎŗÎŽĪ‚", "backup_album_selection_page_total_assets": "ÎŖĪ…ÎŊÎŋÎģΚÎēÎŦ ÎŧÎŋÎŊιδΚÎēÎŦ ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Îą", + "backup_albums_sync": "ÎŖĪ…ÎŗĪ‡ĪÎŋÎŊÎšĪƒÎŧĪŒĪ‚ ÎąÎŊĪ„ÎšÎŗĪÎŦΆΉÎŊ ÎąĪƒĪ†ÎąÎģÎĩÎ¯ÎąĪ‚ ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ", "backup_all": "ΌÎģÎą", "backup_background_service_backup_failed_message": "Î‘Ī€ÎŋĪ„Ī…Ī‡Î¯Îą δΡÎŧΚÎŋĪ…ĪÎŗÎ¯ÎąĪ‚ ÎąÎŊĪ„ÎšÎŗĪÎŦΆΉÎŊ ÎąĪƒĪ†ÎąÎģÎĩÎ¯ÎąĪ‚. Î•Ī€ÎąÎŊÎŦÎģÎˇĪˆÎˇâ€Ļ", "backup_background_service_connection_failed_message": "Î‘Ī€ÎŋĪ„Ī…Ī‡Î¯Îą ĪƒĪÎŊδÎĩĪƒÎˇĪ‚ ÎŧÎĩ Ī„Îŋ δΚιÎēÎŋÎŧÎšĪƒĪ„ÎŽ. Î•Ī€ÎąÎŊÎŦÎģÎˇĪˆÎˇâ€Ļ", @@ -584,6 +600,7 @@ "backup_controller_page_turn_on": "ΕÎŊÎĩĪÎŗÎŋĪ€ÎŋÎ¯ÎˇĪƒÎˇ δΡÎŧΚÎŋĪ…ĪÎŗÎ¯ÎąĪ‚ ÎąÎŊĪ„ÎšÎŗĪÎŦΆÎŋĪ… ÎąĪƒĪ†ÎąÎģÎĩÎ¯ÎąĪ‚ ĪƒĪ„Îŋ ΀΁Îŋ΃ÎēÎŽÎŊΚÎŋ", "backup_controller_page_uploading_file_info": "ΜÎĩĪ„ÎąĪ†ĪŒĪĪ„Ī‰ĪƒÎˇ Ī€ÎģÎˇĪÎŋΆÎŋĪÎšĪŽÎŊ ÎąĪĪ‡ÎĩίÎŋĪ…", "backup_err_only_album": "ΔÎĩÎŊ ÎĩίÎŊιΚ Î´Ī…ÎŊÎąĪ„ÎŽ Ρ ÎąĪ†ÎąÎ¯ĪÎĩĪƒÎˇ Ī„ÎŋĪ… ÎŧÎŋÎŊιδΚÎēÎŋĪ ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ", + "backup_error_sync_failed": "Ο ĪƒĪ…ÎŗĪ‡ĪÎŋÎŊÎšĪƒÎŧĪŒĪ‚ ÎąĪ€Î­Ī„Ī…Ī‡Îĩ. ΔÎĩÎŊ ÎĩίÎŊιΚ Î´Ī…ÎŊÎąĪ„ÎŽ Ρ ÎĩĪ€ÎĩΞÎĩĪÎŗÎąĪƒÎ¯Îą Ī„ÎŋĪ… ÎąÎŊĪ„ÎšÎŗĪÎŦΆÎŋĪ… ÎąĪƒĪ†ÎąÎģÎĩÎ¯ÎąĪ‚.", "backup_info_card_assets": "ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Îą", "backup_manual_cancelled": "ΑÎēĪ…ĪĪŽÎ¸ÎˇÎēÎĩ", "backup_manual_in_progress": "ΜÎĩĪ„ÎąĪ†ĪŒĪĪ„Ī‰ĪƒÎˇ ΃Îĩ ÎĩΞέÎģΚΞΡ. ΔÎŋÎēΚÎŧÎŦĪƒĪ„Îĩ ÎąĪÎŗĪŒĪ„ÎĩĪÎą", @@ -594,8 +611,6 @@ "backup_setting_subtitle": "Î”ÎšÎąĪ‡ÎĩÎ¯ĪÎšĪƒÎˇ ĪĪ…Î¸ÎŧÎ¯ĪƒÎĩΉÎŊ ÎŧÎĩĪ„ÎąĪ†ĪŒĪĪ„Ī‰ĪƒÎˇĪ‚ ĪƒĪ„Îŋ Ī€ÎąĪÎąĪƒÎēÎŽÎŊΚÎŋ ÎēιΚ ĪƒĪ„Îŋ ΀΁Îŋ΃ÎēÎŽÎŊΚÎŋ", "backup_settings_subtitle": "Î”ÎšÎąĪ‡ÎĩÎ¯ĪÎšĪƒÎˇ ΄ΉÎŊ ĪĪ…Î¸ÎŧÎ¯ĪƒÎĩΉÎŊ ÎŧÎĩĪ„ÎąĪ†ĪŒĪĪ„Ī‰ĪƒÎˇĪ‚", "backward": "Î ĪÎŋĪ‚ Ī„Îą Ī€Î¯ĪƒĪ‰", - "beta_sync": "ÎšÎąĪ„ÎŦĪƒĪ„ÎąĪƒÎˇ ÎŖĪ…ÎŗĪ‡ĪÎŋÎŊÎšĪƒÎŧÎŋĪ Beta (δÎŋÎēΚÎŧÎąĪƒĪ„ÎšÎēÎŽ)", - "beta_sync_subtitle": "Î”ÎšÎąĪ‡ÎĩÎ¯ĪÎšĪƒÎˇ Ī„ÎŋĪ… ÎŊέÎŋĪ… ĪƒĪ…ĪƒĪ„ÎŽÎŧÎąĪ„ÎŋĪ‚ ĪƒĪ…ÎŗĪ‡ĪÎŋÎŊÎšĪƒÎŧÎŋĪ", "biometric_auth_enabled": "ΒιÎŋÎŧÎĩĪ„ĪÎšÎēÎŽ Ī„ÎąĪ…Ī„ÎŋĪ€ÎŋÎ¯ÎˇĪƒÎˇ ÎĩÎŊÎĩĪÎŗÎŋĪ€ÎŋΚΎθΡÎēÎĩ", "biometric_locked_out": "Î•Î¯ĪƒĪ„Îĩ ÎēÎģÎĩÎšÎ´Ī‰ÎŧέÎŊÎŋΚ ÎĩÎēĪ„ĪŒĪ‚ Ī„ÎˇĪ‚ βΚÎŋÎŧÎĩĪ„ĪÎšÎēÎŽĪ‚ Ī„ÎąĪ…Ī„ÎŋĪ€ÎŋÎ¯ÎˇĪƒÎˇĪ‚", "biometric_no_options": "ΔÎĩÎŊ Ī…Ī€ÎŦ΁·ÎŋĪ…ÎŊ Î´ÎšÎąÎ¸Î­ĪƒÎšÎŧÎŋΚ Ī„ĪĪŒĪ€ÎŋΚ βΚÎŋÎŧÎĩĪ„ĪÎšÎēÎŽĪ‚ Ī„ÎąĪ…Ī„ÎŋĪ€ÎŋÎ¯ÎˇĪƒÎˇĪ‚", @@ -653,6 +668,8 @@ "change_pin_code": "ΑÎģÎģÎąÎŗÎŽ ÎēĪ‰Î´ÎšÎēÎŋĪ PIN", "change_your_password": "ΑÎģÎģÎŦÎžĪ„Îĩ Ī„ÎŋÎŊ ÎēĪ‰Î´ÎšÎēΌ ĪƒÎąĪ‚", "changed_visibility_successfully": "Η ΀΁ÎŋβÎŋÎģÎŽ, ÎŦÎģÎģιΞÎĩ ÎŧÎĩ ÎĩĪ€ÎšĪ„Ī…Ī‡Î¯Îą", + "charging": "ÎĻĪŒĪĪ„ÎšĪƒÎˇ", + "charging_requirement_mobile_backup": "Η δΡÎŧΚÎŋĪ…ĪÎŗÎ¯Îą ÎąÎŊĪ„ÎšÎŗĪÎŦΆΉÎŊ ÎąĪƒĪ†ÎŦÎģÎĩÎšÎąĪ‚ ĪƒĪ„Îŋ Ī€ÎąĪÎąĪƒÎēÎŽÎŊΚÎŋ ÎąĪ€ÎąÎšĪ„Îĩί Ρ ĪƒĪ…ĪƒÎēÎĩĪ…ÎŽ ÎŊÎą ΆÎŋĪĪ„Î¯ÎļÎĩΚ", "check_corrupt_asset_backup": "ΈÎģÎĩÎŗĪ‡ÎŋĪ‚ ÎŗÎšÎą ÎēÎąĪ„ÎĩĪƒĪ„ĪÎąÎŧÎŧέÎŊÎą ÎąÎŊĪ„Î¯ÎŗĪÎąĪ†Îą ÎąĪƒĪ†ÎąÎģÎĩÎ¯ÎąĪ‚ ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Ī‰ÎŊ", "check_corrupt_asset_backup_button": "ΕÎēĪ„Î­ÎģÎĩĪƒÎˇ ÎĩÎģÎ­ÎŗĪ‡ÎŋĪ…", "check_corrupt_asset_backup_description": "ΕÎēĪ„Î­ÎģÎĩ΃Îĩ ÎąĪ…Ī„ĪŒÎŊ Ī„ÎŋÎŊ έÎģÎĩÎŗĪ‡Îŋ ÎŧΌÎŊÎŋ ÎŧÎ­ĪƒĪ‰ Wi-Fi ÎēιΚ ÎąĪ†ÎŋĪ Î­Ī‡ÎŋĪ…ÎŊ ÎąĪ€ÎŋθΡÎēÎĩĪ…Ī„Îĩί ΌÎģÎą Ī„Îą ÎąÎŊĪ„Î¯ÎŗĪÎąĪ†Îą ÎąĪƒĪ†ÎąÎģÎĩÎ¯ÎąĪ‚ ΄ΉÎŊ ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Ī‰ÎŊ. Η δΚιδΚÎēÎąĪƒÎ¯Îą ÎŧĪ€Îŋ΁Îĩί ÎŊÎą Î´ÎšÎąĪÎēÎ­ĪƒÎĩΚ ÎŧÎĩĪÎšÎēÎŦ ÎģÎĩ΀΄ÎŦ.", @@ -739,6 +756,7 @@ "create_user": "ΔηÎŧΚÎŋĪ…ĪÎŗÎ¯Îą Ī‡ĪÎŽĪƒĪ„Îˇ", "created": "ΔηÎŧΚÎŋĪ…ĪÎŗÎŽÎ¸ÎˇÎēÎĩ", "created_at": "ΔηÎŧΚÎŋĪ…ĪÎŗÎŽÎ¸ÎˇÎēÎĩ", + "creating_linked_albums": "ΔηÎŧΚÎŋĪ…ĪÎŗÎ¯Îą ĪƒĪ…ÎŊδÎĩδÎĩÎŧέÎŊΉÎŊ ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ...", "crop": "Î‘Ī€ÎŋÎēÎŋĪ€ÎŽ", "curated_object_page_title": "Î ĪÎŦÎŗÎŧÎąĪ„Îą", "current_device": "Î¤ĪÎ­Ī‡ÎŋĪ…ĪƒÎą ĪƒĪ…ĪƒÎēÎĩĪ…ÎŽ", @@ -888,7 +906,9 @@ "error": "ÎŖĪ†ÎŦÎģÎŧÎą", "error_change_sort_album": "Î‘Ī€Î­Ī„Ī…Ī‡Îĩ Ρ ÎąÎģÎģÎąÎŗÎŽ ΃ÎĩÎšĪÎŦĪ‚ Ī„ÎŋĪ… ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ", "error_delete_face": "ÎŖĪ†ÎŦÎģÎŧÎą Î´ÎšÎąÎŗĪÎąĪ†ÎŽĪ‚ ΀΁ÎŋĪƒĪŽĪ€ÎŋĪ… ÎąĪ€ĪŒ Ī„Îŋ ĪƒĪ„ÎŋÎšĪ‡ÎĩίÎŋ", + "error_getting_places": "ÎŖĪ†ÎŦÎģÎŧÎą ÎēÎąĪ„ÎŦ Ī„ÎˇÎŊ ÎąÎŊÎŦÎēĪ„ÎˇĪƒÎˇ Ī„ÎŋĪ€ÎŋθÎĩĪƒÎšĪŽÎŊ", "error_loading_image": "ÎŖĪ†ÎŦÎģÎŧÎą ÎēÎąĪ„ÎŦ Ī„Îˇ Ī†ĪŒĪĪ„Ī‰ĪƒÎˇ Ī„ÎˇĪ‚ ÎĩΚÎēΌÎŊÎąĪ‚", + "error_loading_partners": "ÎŖĪ†ÎŦÎģÎŧÎą ÎēÎąĪ„ÎŦ Ī„Îˇ Ī†ĪŒĪĪ„Ī‰ĪƒÎˇ ĪƒĪ…ÎŊÎĩĪÎŗÎąĪ„ĪŽÎŊ: {error}", "error_saving_image": "ÎŖĪ†ÎŦÎģÎŧÎą: {error}", "error_tag_face_bounding_box": "ÎŖĪ†ÎŦÎģÎŧÎą ÎĩĪ€ÎšĪƒÎŽÎŧÎąÎŊĪƒÎˇĪ‚ ΀΁ÎŋĪƒĪŽĪ€ÎŋĪ… - δÎĩÎŊ ÎŧĪ€Îŋ΁ÎŋĪÎŊ ÎŊÎą ÎģÎˇĪ†Î¸ÎŋĪÎŊ ÎŋΚ ĪƒĪ…ÎŊĪ„ÎĩĪ„ÎąÎŗÎŧέÎŊÎĩĪ‚ Ī„ÎŋĪ… Ī€ÎģÎąÎšĪƒÎ¯ÎŋĪ… ÎŋĪÎšÎŋÎ¸Î­Ī„ÎˇĪƒÎˇĪ‚", "error_title": "ÎŖĪ†ÎŦÎģÎŧÎą - ΚÎŦĪ„Îš Ī€ÎŽÎŗÎĩ ĪƒĪ„ĪÎąÎ˛ÎŦ", @@ -1053,6 +1073,7 @@ "favorites_page_no_favorites": "ΔÎĩÎŊ Î˛ĪÎ­Î¸ÎˇÎēÎąÎŊ ÎąÎŗÎąĪ€ÎˇÎŧέÎŊÎą ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Îą", "feature_photo_updated": "Η ΆΉ΄ÎŋÎŗĪÎąĪ†Î¯Îą ΀΁ÎŋβÎŋÎģÎŽĪ‚ ÎĩÎŊΡÎŧÎĩĪĪŽÎ¸ÎˇÎēÎĩ", "features": "Î§ÎąĪÎąÎēĪ„ÎˇĪÎšĪƒĪ„ÎšÎēÎŦ", + "features_in_development": "ΛÎĩÎšĪ„ÎŋĪ…ĪÎŗÎ¯ÎĩĪ‚ Ī…Ī€ĪŒ ΑÎŊÎŦĪ€Ī„Ī…ÎžÎˇ", "features_setting_description": "Î”ÎšÎąĪ‡ÎĩÎšĪÎšĪƒĪ„ÎĩÎ¯Ī„Îĩ Ī„Îą Ī‡ÎąĪÎąÎēĪ„ÎˇĪÎšĪƒĪ„ÎšÎēÎŦ Ī„ÎˇĪ‚ ÎĩĪ†ÎąĪÎŧÎŋÎŗÎŽĪ‚", "file_name": "ΌÎŊÎŋÎŧÎą ÎąĪĪ‡ÎĩίÎŋĪ…", "file_name_or_extension": "ΌÎŊÎŋÎŧÎą ÎąĪĪ‡ÎĩίÎŋĪ… ÎŽ ÎĩĪ€Î­ÎēĪ„ÎąĪƒÎˇ", @@ -1073,12 +1094,15 @@ "gcast_enabled": "ΜÎĩĪ„ÎŦδÎŋĪƒÎˇ Ī€ÎĩĪÎšÎĩ·ÎŋÎŧέÎŊÎŋĪ… Google Cast", "gcast_enabled_description": "Î‘Ī…Ī„ĪŒ Ī„Îŋ Ī‡ÎąĪÎąÎēĪ„ÎˇĪÎšĪƒĪ„ÎšÎēΌ ΆÎŋĪĪ„ĪŽÎŊÎĩΚ ÎĩÎžĪ‰Ī„ÎĩĪÎšÎēÎŋĪĪ‚ Ī€ĪŒĪÎŋĪ…Ī‚ ÎąĪ€ĪŒ Ī„Îˇ Google ÎŗÎšÎą ÎŊÎą ÎģÎĩÎšĪ„ÎŋĪ…ĪÎŗÎŽĪƒÎĩΚ.", "general": "ΓÎĩÎŊΚÎēÎŦ", + "geolocation_instruction_location": "ΚÎŦÎŊÎĩ ÎēÎģΚÎē ΃Îĩ έÎŊÎą ĪƒĪ„ÎŋÎšĪ‡ÎĩίÎŋ ÎŧÎĩ ĪƒĪ…ÎŊĪ„ÎĩĪ„ÎąÎŗÎŧέÎŊÎĩĪ‚ GPS ÎŗÎšÎą ÎŊÎą Ī‡ĪÎˇĪƒÎšÎŧÎŋĪ€ÎŋÎšÎŽĪƒÎĩÎšĪ‚ Ī„ÎˇÎŊ Ī„ÎŋĪ€ÎŋθÎĩĪƒÎ¯Îą Ī„ÎŋĪ…, ÎŽ ÎĩĪ€Î¯ÎģÎĩΞÎĩ ÎąĪ€ÎĩĪ…Î¸ÎĩÎ¯ÎąĪ‚ ÎŧΚι Ī„ÎŋĪ€ÎŋθÎĩĪƒÎ¯Îą ÎąĪ€ĪŒ Ī„ÎŋÎŊ ·ÎŦĪĪ„Îˇ", "get_help": "Î–ÎˇĪ„ÎŽĪƒĪ„Îĩ βÎŋΎθÎĩΚι", "get_wifiname_error": "ΔÎĩÎŊ ÎŽĪ„ÎąÎŊ Î´Ī…ÎŊÎąĪ„ÎŽ Ρ ÎģÎŽĪˆÎˇ Ī„ÎŋĪ… ÎŋÎŊΌÎŧÎąĪ„ÎŋĪ‚ Wi-Fi. ΒÎĩÎ˛ÎąÎšĪ‰Î¸ÎĩÎ¯Ī„Îĩ ĪŒĪ„Îš Î­Ī‡ÎĩĪ„Îĩ Î´ĪŽĪƒÎĩΚ Ī„ÎšĪ‚ ÎąĪ€ÎąĪÎąÎ¯Ī„ÎˇĪ„ÎĩĪ‚ ÎŦδÎĩΚÎĩĪ‚ ÎēιΚ ĪŒĪ„Îš ÎĩÎ¯ĪƒĪ„Îĩ ĪƒĪ…ÎŊδÎĩδÎĩÎŧέÎŊÎŋΚ ΃Îĩ δίÎē΄΅Îŋ Wi-Fi", "getting_started": "ΞÎĩÎēΚÎŊĪŽÎŊĪ„ÎąĪ‚", "go_back": "Î ÎˇÎŗÎąÎ¯ÎŊÎĩĪ„Îĩ Ī€Î¯ĪƒĪ‰", "go_to_folder": "ΜÎĩĪ„ÎŦÎ˛ÎąĪƒÎˇ ĪƒĪ„Îŋ ΆÎŦÎēÎĩÎģÎŋ", "go_to_search": "Î ÎˇÎŗÎąÎ¯ÎŊÎĩĪ„Îĩ ĪƒĪ„ÎˇÎŊ ÎąÎŊÎąÎļÎŽĪ„ÎˇĪƒÎˇ", + "gps": "GPS", + "gps_missing": "Î§Ī‰ĪÎ¯Ī‚ GPS", "grant_permission": "Î•Ī€ÎšĪ„ĪÎ­ĪˆĪ„Îĩ Ī„ÎˇÎŊ ÎŦδÎĩΚι", "group_albums_by": "ΟÎŧιδÎŋĪ€ÎŋÎ¯ÎˇĪƒÎˇ ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ ÎēÎąĪ„ÎŦ...", "group_country": "ΟÎŧιδÎŋĪ€ÎŋÎ¯ÎˇĪƒÎˇ ÎēÎąĪ„ÎŦ Ī‡ĪŽĪÎą", @@ -1214,6 +1238,7 @@ "local": "ΤÎŋĪ€ÎšÎēÎŦ", "local_asset_cast_failed": "Î‘Î´Ī…ÎŊÎąÎŧÎ¯Îą ÎŧÎĩĪ„ÎŦδÎŋĪƒÎˇĪ‚ ĪƒĪ„ÎŋÎšĪ‡ÎĩίÎŋĪ… Ī€ÎŋĪ… δÎĩÎŊ Î­Ī‡ÎĩΚ ÎąÎŊέβÎĩΚ ĪƒĪ„ÎŋÎŊ δΚιÎēÎŋÎŧÎšĪƒĪ„ÎŽ", "local_assets": "ΤÎŋĪ€ÎšÎēÎŦ ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Îą", + "local_media_summary": "ΠÎĩĪÎ¯ÎģÎˇĪˆÎˇ Ī„ÎŋĪ€ÎšÎēĪŽÎŊ Ī€ÎŋÎģĪ…ÎŧÎ­ĪƒĪ‰ÎŊ", "local_network": "ΤÎŋĪ€ÎšÎēΌ δίÎē΄΅Îŋ", "local_network_sheet_info": "Η ÎĩĪ†ÎąĪÎŧÎŋÎŗÎŽ θι ĪƒĪ…ÎŊδÎĩθÎĩί ÎŧÎĩ Ī„ÎŋÎŊ δΚιÎēÎŋÎŧÎšĪƒĪ„ÎŽ ÎŧÎ­ĪƒĪ‰ ÎąĪ…Ī„ÎŋĪ Ī„ÎŋĪ… URL ĪŒĪ„ÎąÎŊ Ī‡ĪÎˇĪƒÎšÎŧÎŋĪ€ÎŋΚÎĩÎ¯Ī„ÎąÎš Ī„Îŋ ÎēιθÎŋĪÎšĪƒÎŧέÎŊÎŋ δίÎē΄΅Îŋ Wi-Fi", "location_permission": "ΆδÎĩΚι Ī„ÎŋĪ€ÎŋθÎĩĪƒÎ¯ÎąĪ‚", @@ -1225,6 +1250,7 @@ "location_picker_longitude_hint": "Î•ÎšĪƒÎąÎŗÎŦÎŗÎĩĪ„Îĩ ÎĩÎ´ĪŽ Ī„Îŋ ÎŗÎĩĪ‰ÎŗĪÎąĪ†ÎšÎēΌ ĪƒÎąĪ‚ ÎŧÎŽÎēÎŋĪ‚", "lock": "ΚÎģÎĩÎ¯Î´Ī‰ÎŧÎą", "locked_folder": "ΚÎģÎĩÎšÎ´Ī‰ÎŧέÎŊÎŋĪ‚ ΆÎŦÎēÎĩÎģÎŋĪ‚", + "log_detail_title": "ΛÎĩ΀΄ÎŋÎŧÎ­ĪÎĩΚι ÎēÎąĪ„ÎąÎŗĪÎąĪ†ÎŽĪ‚", "log_out": "Î‘Ī€ÎŋĪƒĪÎŊδÎĩĪƒÎˇ", "log_out_all_devices": "Î‘Ī€ÎŋĪƒĪÎŊδÎĩĪƒÎˇ ÎąĪ€ĪŒ ΌÎģÎĩĪ‚ Ī„ÎšĪ‚ ÎŖĪ…ĪƒÎēÎĩĪ…Î­Ī‚", "logged_in_as": "ÎŖĪ…ÎŊδÎĩδÎĩÎŧέÎŊÎŋĪ‚ Ή΂ {user}", @@ -1255,6 +1281,7 @@ "login_password_changed_success": "Ο ÎēĪ‰Î´ÎšÎēĪŒĪ‚ Ī€ĪĪŒĪƒÎ˛ÎąĪƒÎˇĪ‚ ÎĩÎŊΡÎŧÎĩĪĪŽÎ¸ÎˇÎēÎĩ ÎŧÎĩ ÎĩĪ€ÎšĪ„Ī…Ī‡Î¯Îą", "logout_all_device_confirmation": "Î•Î¯ĪƒĪ„Îĩ βέβιΚÎŋΚ ĪŒĪ„Îš θέÎģÎĩĪ„Îĩ ÎŊÎą ÎąĪ€ÎŋĪƒĪ…ÎŊδÎĩθÎĩÎ¯Ī„Îĩ ÎąĪ€ĪŒ ΌÎģÎĩĪ‚ Ī„ÎšĪ‚ ĪƒĪ…ĪƒÎēÎĩĪ…Î­Ī‚;", "logout_this_device_confirmation": "Î•Î¯ĪƒĪ„Îĩ βέβιΚÎŋΚ ĪŒĪ„Îš θέÎģÎĩĪ„Îĩ ÎŊÎą ÎąĪ€ÎŋĪƒĪ…ÎŊδÎĩθÎĩÎ¯Ī„Îĩ ÎąĪ€ĪŒ ÎąĪ…Ī„ÎŽÎŊ Ī„Îˇ ĪƒĪ…ĪƒÎēÎĩĪ…ÎŽ;", + "logs": "ÎšÎąĪ„ÎąÎŗĪÎąĪ†Î­Ī‚", "longitude": "ΓÎĩĪ‰ÎŗĪÎąĪ†ÎšÎēΌ ÎŧÎŽÎēÎŋĪ‚", "look": "ΕÎŧΆÎŦÎŊÎšĪƒÎˇ", "loop_videos": "Î•Ī€ÎąÎŊÎŦÎģÎˇĪˆÎˇ Î˛Î¯ÎŊĪ„ÎĩÎŋ", @@ -1262,6 +1289,7 @@ "main_branch_warning": "Î§ĪÎˇĪƒÎšÎŧÎŋĪ€ÎŋΚÎĩÎ¯Ī„Îĩ ÎŧΚι έÎēδÎŋĪƒÎˇ ΃Îĩ ÎąÎŊÎŦĪ€Ī„Ī…ÎžÎˇÎ‡ ĪƒĪ…ÎŊÎšĪƒĪ„ÎŋĪÎŧÎĩ ÎąÎŊÎĩĪ€ÎšĪ†ĪÎģÎąÎēĪ„Îą Ī„Îˇ Ī‡ĪÎŽĪƒÎˇ ÎŧÎšÎąĪ‚ Ī„ÎĩÎģΚÎēÎŽĪ‚ έÎēδÎŋĪƒÎˇĪ‚!", "main_menu": "ÎšĪĪÎšÎŋ ÎŧÎĩÎŊÎŋĪ", "make": "ÎšÎąĪ„ÎąĪƒÎēÎĩĪ…ÎąĪƒĪ„ÎŽĪ‚", + "manage_geolocation": "Î”ÎšÎąĪ‡ÎĩÎ¯ĪÎšĪƒÎˇ Ī„ÎŋĪ€ÎŋθÎĩĪƒÎ¯ÎąĪ‚", "manage_shared_links": "Î”ÎšÎąĪ‡ÎĩÎ¯ĪÎšĪƒÎˇ ÎēÎŋΚÎŊĪŒĪ‡ĪÎˇĪƒĪ„Ī‰ÎŊ ĪƒĪ…ÎŊÎ´Î­ĪƒÎŧΉÎŊ", "manage_sharing_with_partners": "Î”ÎšÎąĪ‡ÎĩÎšĪÎšĪƒĪ„ÎĩÎ¯Ī„Îĩ Ī„ÎˇÎŊ ÎēÎŋΚÎŊÎŽ Ī‡ĪÎŽĪƒÎˇ ÎŧÎĩ ĪƒĪ…ÎŊÎĩĪÎŗÎŦĪ„ÎĩĪ‚", "manage_the_app_settings": "Î”ÎšÎąĪ‡ÎĩÎšĪÎšĪƒĪ„ÎĩÎ¯Ī„Îĩ Ī„ÎšĪ‚ ĪĪ…Î¸ÎŧÎ¯ĪƒÎĩÎšĪ‚ Ī„ÎˇĪ‚ ÎĩĪ†ÎąĪÎŧÎŋÎŗÎŽĪ‚", @@ -1296,6 +1324,7 @@ "mark_as_read": "Î•Ī€ÎšĪƒÎŽÎŧÎąÎŊĪƒÎˇ Ή΂ ÎąÎŊÎąÎŗÎŊĪ‰ĪƒÎŧέÎŊÎŋ", "marked_all_as_read": "ΌÎģÎą ÎĩĪ€ÎšĪƒÎˇÎŧÎŦÎŊθΡÎēÎąÎŊ Ή΂ ÎąÎŊÎąÎŗÎŊĪ‰ĪƒÎŧέÎŊÎą", "matches": "ΑÎŊĪ„ÎšĪƒĪ„ÎŋÎšĪ‡Î¯ÎĩĪ‚", + "matching_assets": "ΑÎŊĪ„ÎšĪƒĪ„ÎŋÎšĪ‡Î¯Îą ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Ī‰ÎŊ", "media_type": "Î¤ĪĪ€ÎŋĪ‚ Ī€ÎŋÎģĪ…ÎŧÎ­ĪƒÎŋĪ…", "memories": "ΑÎŊÎąÎŧÎŊÎŽĪƒÎĩÎšĪ‚", "memories_all_caught_up": "ÎŖĪ…ÎŗĪ‡ĪÎŋÎŊÎšĪƒÎŧέÎŊÎą", @@ -1336,6 +1365,7 @@ "name_or_nickname": "ΌÎŊÎŋÎŧÎą ÎŽ ΈÎĩĪ…Î´ĪŽÎŊĪ…ÎŧÎŋ", "network_requirement_photos_upload": "Î§ĪÎŽĪƒÎˇ δÎĩδÎŋÎŧέÎŊΉÎŊ ÎēΚÎŊÎˇĪ„ÎŽĪ‚ Ī„ÎˇÎģÎĩΆΉÎŊÎ¯ÎąĪ‚ ÎŗÎšÎą Ī„Îˇ δΡÎŧΚÎŋĪ…ĪÎŗÎ¯Îą ÎąÎŊĪ„ÎšÎŗĪÎŦΆΉÎŊ ÎąĪƒĪ†ÎąÎģÎĩÎ¯ÎąĪ‚ ΄ΉÎŊ ΆΉ΄ÎŋÎŗĪÎąĪ†ÎšĪŽÎŊ", "network_requirement_videos_upload": "Î§ĪÎŽĪƒÎˇ δÎĩδÎŋÎŧέÎŊΉÎŊ ÎēΚÎŊÎˇĪ„ÎŽĪ‚ Ī„ÎˇÎģÎĩΆΉÎŊÎ¯ÎąĪ‚ ÎŗÎšÎą Ī„Îˇ δΡÎŧΚÎŋĪ…ĪÎŗÎ¯Îą ÎąÎŊĪ„ÎšÎŗĪÎŦΆΉÎŊ ÎąĪƒĪ†ÎąÎģÎĩÎ¯ÎąĪ‚ ΄ΉÎŊ Î˛Î¯ÎŊĪ„ÎĩÎŋ", + "network_requirements": "Î‘Ī€ÎąÎšĪ„ÎŽĪƒÎĩÎšĪ‚ Î”Ī…ÎēĪ„Î¯ÎŋĪ…", "network_requirements_updated": "Οι ÎąĪ€ÎąÎšĪ„ÎŽĪƒÎĩÎšĪ‚ δΚÎēĪ„ĪÎŋĪ… ÎŦÎģÎģιΞιÎŊ, ÎŗÎ¯ÎŊÎĩĪ„ÎąÎš ÎĩĪ€ÎąÎŊÎąĪ†Îŋ΁ÎŦ Ī„ÎˇĪ‚ Îŋ΅΁ÎŦĪ‚ ÎąÎŊĪ„ÎšÎŗĪÎŦΆΉÎŊ ÎąĪƒĪ†ÎąÎģÎĩÎ¯ÎąĪ‚", "networking_settings": "ΔιÎēĪ„ĪĪ‰ĪƒÎˇ", "networking_subtitle": "Î”ÎšÎąĪ‡ÎĩÎ¯ĪÎšĪƒÎˇ ĪĪ…Î¸ÎŧÎ¯ĪƒÎĩΉÎŊ Ī„ÎĩÎģΚÎēĪŽÎŊ ĪƒÎˇÎŧÎĩÎ¯Ī‰ÎŊ δΚιÎēÎŋÎŧÎšĪƒĪ„ÎŽ", @@ -1346,6 +1376,7 @@ "new_person": "ΝέÎŋ ÎŦĪ„ÎŋÎŧÎŋ", "new_pin_code": "ΝέÎŋĪ‚ ÎēĪ‰Î´ÎšÎēĪŒĪ‚ PIN", "new_pin_code_subtitle": "Î‘Ī…Ī„ÎŽ ÎĩίÎŊιΚ Ρ Ī€ĪĪŽĪ„Îˇ ΆÎŋ΁ÎŦ Ī€ÎŋĪ… ÎąĪ€ÎŋÎēĪ„ÎŦĪ„Îĩ Ī€ĪĪŒĪƒÎ˛ÎąĪƒÎˇ ĪƒĪ„ÎŋÎŊ ÎēÎģÎĩÎšÎ´Ī‰ÎŧέÎŊÎŋ ΆÎŦÎēÎĩÎģÎŋ. ΔηÎŧΚÎŋĪ…ĪÎŗÎŽĪƒĪ„Îĩ έÎŊÎąÎŊ ÎēĪ‰Î´ÎšÎēΌ PIN ÎŗÎšÎą ÎąĪƒĪ†ÎąÎģÎŽ Ī€ĪĪŒĪƒÎ˛ÎąĪƒÎˇ ΃Îĩ ÎąĪ…Ī„ÎŽ Ī„Îˇ ΃ÎĩÎģÎ¯Î´Îą", + "new_timeline": "ΝέÎŋ Î§ĪÎŋÎŊÎŋÎģĪŒÎŗÎšÎŋ", "new_user_created": "Ο ÎŊέÎŋĪ‚ Ī‡ĪÎŽĪƒĪ„ÎˇĪ‚ δΡÎŧΚÎŋĪ…ĪÎŗÎŽÎ¸ÎˇÎēÎĩ", "new_version_available": "Î”Î™Î‘Î˜Î•ÎŖÎ™ÎœÎ— ΝΕΑ Î•ÎšÎ”ÎŸÎŖÎ—", "newest_first": "Τι ÎŊÎĩĪŒĪ„ÎĩĪÎą Ī€ĪĪŽĪ„Îą", @@ -1359,20 +1390,25 @@ "no_assets_message": "ΚΑΝΤΕ ΚΛΙΚ ΓΙΑ ΝΑ Î‘ÎÎ•Î’Î‘ÎŖÎ•Î¤Î• ΤΗΝ ΠΡΩΤΗ ÎŖÎ‘ÎŖ ÎĻΩΤΟΓΡΑÎĻΙΑ", "no_assets_to_show": "ΔÎĩÎŊ Ī…Ī€ÎŦ΁·ÎŋĪ…ÎŊ ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Îą ΀΁ÎŋĪ‚ ÎĩÎŧΆÎŦÎŊÎšĪƒÎˇ", "no_cast_devices_found": "ΔÎĩ Î˛ĪÎ­Î¸ÎˇÎēÎąÎŊ ĪƒĪ…ĪƒÎēÎĩĪ…Î­Ī‚ ÎŧÎĩĪ„ÎŦδÎŋĪƒÎˇĪ‚", + "no_checksum_local": "ΔÎĩÎŊ Ī…Ī€ÎŦ΁·ÎĩΚ Î´ÎšÎąÎ¸Î­ĪƒÎšÎŧÎŋ checksum ÎŗÎšÎą έÎģÎĩÎŗĪ‡Îŋ ÎąÎēÎĩĪÎąÎšĪŒĪ„ÎˇĪ„ÎąĪ‚ – δÎĩÎŊ ÎŧĪ€Îŋ΁ÎŋĪÎŊ ÎŊÎą ÎąÎŊÎąÎēĪ„ÎˇÎ¸ÎŋĪÎŊ Ī„Îą Ī„ÎŋĪ€ÎšÎēÎŦ ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Îą", + "no_checksum_remote": "ΔÎĩÎŊ Ī…Ī€ÎŦ΁·ÎĩΚ Î´ÎšÎąÎ¸Î­ĪƒÎšÎŧÎŋ checksum ÎŗÎšÎą έÎģÎĩÎŗĪ‡Îŋ ÎąÎēÎĩĪÎąÎšĪŒĪ„ÎˇĪ„ÎąĪ‚ – δÎĩÎŊ ÎŧĪ€Îŋ΁ÎŋĪÎŊ ÎŊÎą ÎąÎŊÎąÎēĪ„ÎˇÎ¸ÎŋĪÎŊ Ī„Îą ÎąĪ€ÎŋÎŧÎąÎēĪĪ…ĪƒÎŧέÎŊÎą ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Îą", "no_duplicates_found": "ΔÎĩÎŊ Î˛ĪÎ­Î¸ÎˇÎēÎąÎŊ Î´ÎšĪ€ÎģĪŒĪ„Ī…Ī€Îą.", "no_exif_info_available": "ΚαÎŧÎ¯Îą Ī€ÎģÎˇĪÎŋΆÎŋĪÎ¯Îą exif Î´ÎšÎąÎ¸Î­ĪƒÎšÎŧΡ", "no_explore_results_message": "ΑÎŊÎĩβÎŦĪƒĪ„Îĩ Ī€ÎĩĪÎšĪƒĪƒĪŒĪ„Îĩ΁ÎĩĪ‚ ΆΉ΄ÎŋÎŗĪÎąĪ†Î¯ÎĩĪ‚ ÎŗÎšÎą ÎŊÎą Ī€ÎĩĪÎšÎˇÎŗÎˇÎ¸ÎĩÎ¯Ī„Îĩ ĪƒĪ„Îˇ ĪƒĪ…ÎģÎģÎŋÎŗÎŽ ĪƒÎąĪ‚.", "no_favorites_message": "Î ĪÎŋĪƒÎ¸Î­ĪƒĪ„Îĩ ÎąÎŗÎąĪ€ÎˇÎŧέÎŊÎą ÎŗÎšÎą ÎŊÎą Î˛ĪÎĩÎ¯Ī„Îĩ ÎŗĪÎŽÎŗÎŋĪÎą Ī„ÎšĪ‚ ÎēÎąÎģĪĪ„Îĩ΁ÎĩĪ‚ ΆΉ΄ÎŋÎŗĪÎąĪ†Î¯ÎĩĪ‚ ÎēιΚ Ī„Îą Î˛Î¯ÎŊĪ„ÎĩΌ ĪƒÎąĪ‚", "no_libraries_message": "ΔηÎŧΚÎŋĪ…ĪÎŗÎŽĪƒĪ„Îĩ ÎŧΚι ÎĩÎžĪ‰Ī„ÎĩĪÎšÎēÎŽ βΚβÎģΚÎŋθΎÎēΡ ÎŗÎšÎą ÎŊÎą ΀΁ÎŋβÎŦÎģÎĩĪ„Îĩ Ī„ÎšĪ‚ ΆΉ΄ÎŋÎŗĪÎąĪ†Î¯ÎĩĪ‚ ÎēιΚ Ī„Îą Î˛Î¯ÎŊĪ„ÎĩΌ ĪƒÎąĪ‚", + "no_local_assets_found": "ΔÎĩÎŊ Î˛ĪÎ­Î¸ÎˇÎēÎąÎŊ Ī„ÎŋĪ€ÎšÎēÎŦ ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Îą ÎŧÎĩ ÎąĪ…Ī„ĪŒ Ī„Îŋ checksum", "no_locked_photos_message": "Οι ΆΉ΄ÎŋÎŗĪÎąĪ†Î¯ÎĩĪ‚ ÎēιΚ Ī„Îą Î˛Î¯ÎŊĪ„ÎĩÎŋ ĪƒĪ„ÎŋÎŊ ÎēÎģÎĩÎšÎ´Ī‰ÎŧέÎŊÎŋ ΆÎŦÎēÎĩÎģÎŋ, ÎĩίÎŊιΚ Îē΁΅ÎŧÎŧέÎŊÎĩĪ‚ ÎēιΚ δÎĩÎŊ θι ÎĩÎŧĪ†ÎąÎŊίÎļÎŋÎŊĪ„ÎąÎš ÎēÎąĪ„ÎŦ Ī„ÎˇÎŊ Ī€ÎĩĪÎšÎŽÎŗÎˇĪƒÎˇ ÎŽ Ī„ÎˇÎŊ ÎąÎŊÎąÎļÎŽĪ„ÎˇĪƒÎˇ ĪƒĪ„Îˇ βΚβÎģΚÎŋθΎÎēΡ ĪƒÎąĪ‚.", "no_name": "Î§Ī‰ĪÎ¯Ī‚ ΌÎŊÎŋÎŧÎą", "no_notifications": "ΚαÎŧÎ¯Îą ÎĩΚδÎŋĪ€ÎŋÎ¯ÎˇĪƒÎˇ", "no_people_found": "ΔÎĩÎŊ Î˛ĪÎ­Î¸ÎˇÎēÎąÎŊ ÎŦĪ„ÎŋÎŧÎą Ī€ÎŋĪ… ÎŊÎą Ī„ÎąÎšĪÎšÎŦÎļÎŋĪ…ÎŊ", "no_places": "ΚαÎŧÎ¯Îą Ī„ÎŋĪ€ÎŋθÎĩĪƒÎ¯Îą", + "no_remote_assets_found": "ΔÎĩÎŊ Î˛ĪÎ­Î¸ÎˇÎēÎąÎŊ ÎąĪ€ÎŋÎŧÎąÎēĪĪ…ĪƒÎŧέÎŊÎą ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Îą ÎŧÎĩ ÎąĪ…Ī„ĪŒ Ī„Îŋ checksum", "no_results": "ΚαÎŊέÎŊÎą ÎąĪ€ÎŋĪ„Î­ÎģÎĩ΃ÎŧÎą", "no_results_description": "ΔÎŋÎēΚÎŧÎŦĪƒĪ„Îĩ έÎŊÎą ĪƒĪ…ÎŊĪŽÎŊĪ…ÎŧÎŋ ÎŽ Ī€ÎšÎŋ ÎŗÎĩÎŊΚÎēÎŽ ÎģέΞΡ-ÎēÎģÎĩΚδί", "no_shared_albums_message": "ΔηÎŧΚÎŋĪ…ĪÎŗÎŽĪƒĪ„Îĩ έÎŊÎą ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ ÎŗÎšÎą ÎŊÎą ÎŧÎŋÎšĪÎŦÎļÎĩĪƒĪ„Îĩ ΆΉ΄ÎŋÎŗĪÎąĪ†Î¯ÎĩĪ‚ ÎēιΚ Î˛Î¯ÎŊĪ„ÎĩÎŋ ÎŧÎĩ ÎŦĪ„ÎŋÎŧÎą ĪƒĪ„Îŋ δίÎēĪ„Ī…ĪŒ ĪƒÎąĪ‚", "no_uploads_in_progress": "ΚαÎŧÎ¯Îą ÎŧÎĩĪ„ÎąĪ†ĪŒĪĪ„Ī‰ĪƒÎˇ ΃Îĩ ÎĩΞέÎģΚΞΡ", + "not_available": "Μ/Δ (Μη Î”ÎšÎąÎ¸Î­ĪƒÎšÎŧÎŋ)", "not_in_any_album": "ÎŖÎĩ ÎēÎąÎŊέÎŊÎą ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ", "not_selected": "ΔÎĩÎŊ ÎĩĪ€ÎšÎģÎ­Ī‡Î¸ÎˇÎēÎĩ", "note_apply_storage_label_to_previously_uploaded assets": "ÎŖÎˇÎŧÎĩÎ¯Ī‰ĪƒÎˇ: Για ÎŊÎą ÎĩĪ†ÎąĪÎŧΌ΃ÎĩĪ„Îĩ Ī„ÎˇÎŊ Î•Ī„ÎšÎēÎ­Ī„Îą Î‘Ī€ÎŋθΎÎēÎĩĪ…ĪƒÎˇĪ‚ ΃Îĩ ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Îą Ī€ÎŋĪ… Î­Ī‡ÎŋĪ…ÎŊ ÎŧÎĩĪ„ÎąĪ†ÎŋĪĪ„Ī‰Î¸Îĩί ΀΁ÎŋÎˇÎŗÎŋĪ…ÎŧέÎŊΉ΂, ÎĩÎēĪ„ÎĩÎģÎ­ĪƒĪ„Îĩ Ī„Îŋ", @@ -1407,6 +1443,8 @@ "open_the_search_filters": "ΑÎŊÎŋÎ¯ÎžĪ„Îĩ Ī„Îą Ī†Î¯ÎģĪ„ĪÎą ÎąÎŊÎąÎļÎŽĪ„ÎˇĪƒÎˇĪ‚", "options": "Î•Ī€ÎšÎģÎŋÎŗÎ­Ī‚", "or": "ÎŽ", + "organize_into_albums": "ÎŸĪÎŗÎŦÎŊĪ‰ĪƒÎˇ ΃Îĩ ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ", + "organize_into_albums_description": "ΤÎŋĪ€ÎŋθÎĩĪ„ÎĩÎ¯ĪƒĪ„Îĩ Ī„ÎšĪ‚ Ī…Ī€ÎŦ΁·ÎŋĪ…ĪƒÎĩĪ‚ ΆΉ΄ÎŋÎŗĪÎąĪ†Î¯ÎĩĪ‚ ΃Îĩ ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ Ī‡ĪÎˇĪƒÎšÎŧÎŋĪ€ÎŋÎšĪŽÎŊĪ„ÎąĪ‚ Ī„ÎšĪ‚ Ī„ĪÎ­Ī‡ÎŋĪ…ĪƒÎĩĪ‚ ĪĪ…Î¸ÎŧÎ¯ĪƒÎĩÎšĪ‚ ĪƒĪ…ÎŗĪ‡ĪÎŋÎŊÎšĪƒÎŧÎŋĪ", "organize_your_library": "ÎŸĪÎŗÎąÎŊĪŽĪƒĪ„Îĩ Ī„Îˇ βΚβÎģΚÎŋθΎÎēΡ ĪƒÎąĪ‚", "original": "Ī€ĪĪ‰Ī„ĪŒĪ„Ī…Ī€Îŋ", "other": "ΆÎģÎģÎĩĪ‚", @@ -1492,6 +1530,7 @@ "port": "Î˜ĪĪÎą", "preferences_settings_subtitle": "Î”ÎšÎąĪ‡ÎĩÎšĪÎšĪƒĪ„ÎĩÎ¯Ī„Îĩ Ī„ÎšĪ‚ ΀΁ÎŋĪ„ÎšÎŧÎŽĪƒÎĩÎšĪ‚ Ī„ÎˇĪ‚ ÎĩĪ†ÎąĪÎŧÎŋÎŗÎŽĪ‚", "preferences_settings_title": "Î ĪÎŋĪ„ÎšÎŧÎŽĪƒÎĩÎšĪ‚", + "preparing": "Î ĪÎŋÎĩĪ„ÎŋΚÎŧÎąĪƒÎ¯Îą", "preset": "Î ĪÎŋÎēιθÎŋĪÎšĪƒÎŧέÎŊΡ ĪĪÎ¸ÎŧÎšĪƒÎˇ", "preview": "Î ĪÎŋÎĩĪ€ÎšĪƒÎēĪŒĪ€ÎˇĪƒÎˇ", "previous": "Î ĪÎŋÎˇÎŗÎŋĪÎŧÎĩÎŊÎŋ", @@ -1508,6 +1547,7 @@ "profile_drawer_client_out_of_date_minor": "Î ÎąĪÎąÎēÎąÎģĪŽ ÎĩÎŊΡÎŧÎĩĪĪŽĪƒĪ„Îĩ Ī„ÎˇÎŊ ÎĩĪ†ÎąĪÎŧÎŋÎŗÎŽ ĪƒĪ„ÎˇÎŊ Ī€ÎšÎŋ Ī€ĪĪŒĪƒĪ†ÎąĪ„Îˇ δÎĩĪ…Ī„Îĩ΁ÎĩĪÎŋĪ…ĪƒÎą έÎēδÎŋĪƒÎˇ.", "profile_drawer_client_server_up_to_date": "Ο Ī€ÎĩÎģÎŦĪ„ÎˇĪ‚ ÎēιΚ Îŋ δΚιÎēÎŋÎŧÎšĪƒĪ„ÎŽĪ‚ ÎĩίÎŊιΚ ÎĩÎŊΡÎŧÎĩ΁ΉÎŧέÎŊÎŋΚ", "profile_drawer_github": "GitHub", + "profile_drawer_readonly_mode": "Η ÎģÎĩÎšĪ„ÎŋĪ…ĪÎŗÎ¯Îą ÎŧΌÎŊÎŋ-ÎŗÎšÎą-ÎąÎŊÎŦÎŗÎŊĪ‰ĪƒÎˇ ÎĩÎŊÎĩĪÎŗÎŋĪ€ÎŋΚΎθΡÎēÎĩ. ÎšĪÎąĪ„ÎŽĪƒĪ„Îĩ Ī€ÎąĪ„ÎˇÎŧέÎŊÎŋ Ī„Îŋ ÎĩΚÎēÎŋÎŊίδΚÎŋ Ī„ÎŋĪ… Ī‡ĪÎŽĪƒĪ„Îˇ ÎŗÎšÎą ÎąĪ€ÎĩÎŊÎĩĪÎŗÎŋĪ€ÎŋÎ¯ÎˇĪƒÎˇ.", "profile_drawer_server_out_of_date_major": "Î ÎąĪÎąÎēÎąÎģĪŽ ÎĩÎŊΡÎŧÎĩĪĪŽĪƒĪ„Îĩ Ī„ÎŋÎŊ δΚιÎēÎŋÎŧÎšĪƒĪ„ÎŽ ĪƒĪ„ÎˇÎŊ Ī€ÎšÎŋ Ī€ĪĪŒĪƒĪ†ÎąĪ„Îˇ ÎēĪĪÎšÎą έÎēδÎŋĪƒÎˇ.", "profile_drawer_server_out_of_date_minor": "Î ÎąĪÎąÎēÎąÎģĪŽ ÎĩÎŊΡÎŧÎĩĪĪŽĪƒĪ„Îĩ Ī„ÎŋÎŊ δΚιÎēÎŋÎŧÎšĪƒĪ„ÎŽ ĪƒĪ„ÎˇÎŊ Ī€ÎšÎŋ Ī€ĪĪŒĪƒĪ†ÎąĪ„Îˇ δÎĩĪ…Ī„Îĩ΁ÎĩĪÎŋĪ…ĪƒÎą έÎēδÎŋĪƒÎˇ.", "profile_image_of_user": "ΕιÎēΌÎŊÎą ΀΁ÎŋĪ†Î¯Îģ Ī„ÎŋĪ… Ī‡ĪÎŽĪƒĪ„Îˇ {user}", @@ -1546,6 +1586,7 @@ "purchase_server_description_2": "ÎšÎąĪ„ÎŦĪƒĪ„ÎąĪƒÎˇ Ī…Ī€ÎŋĪƒĪ„ÎˇĪÎšÎēĪ„ÎŽ", "purchase_server_title": "ΔιαÎēÎŋÎŧÎšĪƒĪ„ÎŽĪ‚", "purchase_settings_server_activated": "Η Î´ÎšÎąĪ‡ÎĩÎ¯ĪÎšĪƒÎˇ Ī„ÎŋĪ… ÎēÎģÎĩΚδΚÎŋĪ ΀΁ÎŋΊΌÎŊĪ„ÎŋĪ‚ Ī„ÎŋĪ… δΚιÎēÎŋÎŧÎšĪƒĪ„ÎŽ ÎŗÎ¯ÎŊÎĩĪ„ÎąÎš ÎąĪ€ĪŒ Ī„ÎŋÎŊ Î´ÎšÎąĪ‡ÎĩÎšĪÎšĪƒĪ„ÎŽ", + "query_asset_id": "ΑÎŊÎąÎļÎŽĪ„ÎˇĪƒÎˇ ID ÎŖĪ„ÎŋÎšĪ‡ÎĩίÎŋĪ…", "queue_status": "ΤÎŋĪ€ÎŋÎ¸Î­Ī„ÎˇĪƒÎˇ ĪƒĪ„Îˇ Îŋ΅΁ÎŦ {count} ÎąĪ€ĪŒ {total}", "rating": "ΑξιÎŋÎģĪŒÎŗÎˇĪƒÎˇ ÎŧÎĩ ÎąĪƒĪ„Î­ĪÎšÎą", "rating_clear": "ΕÎēÎēιθÎŦĪÎšĪƒÎˇ ιΞΚÎŋÎģĪŒÎŗÎˇĪƒÎˇĪ‚", @@ -1553,6 +1594,9 @@ "rating_description": "ΕÎŧΆÎŦÎŊÎšĪƒÎˇ Ī„ÎˇĪ‚ ιΞΚÎŋÎģĪŒÎŗÎˇĪƒÎˇĪ‚ EXIF ĪƒĪ„ÎŋÎŊ Ī€Î¯ÎŊÎąÎēÎą Ī€ÎģÎˇĪÎŋΆÎŋĪÎšĪŽÎŊ", "reaction_options": "Î•Ī€ÎšÎģÎŋÎŗÎ­Ī‚ ÎąÎŊĪ„Î¯Î´ĪÎąĪƒÎˇĪ‚", "read_changelog": "ΔιαβÎŦĪƒĪ„Îĩ Ī„Îŋ Î‘ĪĪ‡ÎĩίÎŋ ÎšÎąĪ„ÎąÎŗĪÎąĪ†ÎŽĪ‚ ΑÎģÎģÎąÎŗĪŽÎŊ", + "readonly_mode_disabled": "Η ÎģÎĩÎšĪ„ÎŋĪ…ĪÎŗÎ¯Îą ÎŧΌÎŊÎŋ-ÎŗÎšÎą-ÎąÎŊÎŦÎŗÎŊĪ‰ĪƒÎˇ ÎąĪ€ÎĩÎŊÎĩĪÎŗÎŋĪ€ÎŋΚΎθΡÎēÎĩ", + "readonly_mode_enabled": "Η ÎģÎĩÎšĪ„ÎŋĪ…ĪÎŗÎ¯Îą ÎŧΌÎŊÎŋ-ÎŗÎšÎą-ÎąÎŊÎŦÎŗÎŊĪ‰ĪƒÎˇ ÎĩÎŊÎĩĪÎŗÎŋĪ€ÎŋΚΎθΡÎēÎĩ", + "ready_for_upload": "ÎˆĪ„ÎŋΚÎŧÎŋ ÎŗÎšÎą ÎŧÎĩĪ„ÎąĪ†ĪŒĪĪ„Ī‰ĪƒÎˇ", "reassign": "ΑÎŊÎŦθÎĩĪƒÎˇ", "reassigned_assets_to_existing_person": "Η ÎąÎŊÎŦθÎĩĪƒÎˇ {count, plural, one {# ÎąĪĪ‡ÎĩίÎŋĪ…} other {# ÎąĪĪ‡ÎĩÎ¯Ī‰ÎŊ}} ĪƒĪ„ÎŋÎŊ/ĪƒĪ„ÎˇÎŊ {name, select, null {έÎŊÎąÎŊ/ÎŧÎ¯Îą Ī…Ī€ÎŦ΁·ÎŋÎŊĪ„Îą/ÎŋĪ…ĪƒÎą Ī‡ĪÎŽĪƒĪ„Îˇ} other {{name}}}", "reassigned_assets_to_new_person": "Η ÎąÎŊÎŦθÎĩĪƒÎˇ {count, plural, one {# ÎąĪĪ‡ÎĩίÎŋĪ…} other {# ÎąĪĪ‡ÎĩÎ¯Ī‰ÎŊ}} ΃Îĩ ÎŊέÎŋ ÎŦĪ„ÎŋÎŧÎŋ", @@ -1577,6 +1621,7 @@ "regenerating_thumbnails": "Οι ÎŧΚÎē΁ÎŋÎŗĪÎąĪ†Î¯ÎĩĪ‚ ÎąÎŊÎąÎŗÎĩÎŊÎŊĪŽÎŊĪ„ÎąÎš", "remote": "Î‘Ī€ÎŋÎŧÎąÎēĪĪ…ĪƒÎŧέÎŊÎŋĪ‚", "remote_assets": "Î‘Ī€ÎŋÎŧÎąÎēĪĪ…ĪƒÎŧέÎŊÎą ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Îą", + "remote_media_summary": "ΠÎĩĪÎ¯ÎģÎˇĪˆÎˇ ÎąĪ€ÎŋÎŧÎąÎēĪĪ…ĪƒÎŧέÎŊΉÎŊ Ī€ÎŋÎģĪ…ÎŧÎ­ĪƒĪ‰ÎŊ", "remove": "Î‘Ī†ÎąÎ¯ĪÎĩĪƒÎˇ", "remove_assets_album_confirmation": "Î•Î¯ĪƒĪ„Îĩ ĪƒÎ¯ÎŗÎŋ΅΁ÎŋΚ ĪŒĪ„Îš θέÎģÎĩĪ„Îĩ ÎŊÎą ÎąĪ†ÎąÎšĪÎ­ĪƒÎĩĪ„Îĩ {count, plural, one {# ĪƒĪ„ÎŋÎšĪ‡ÎĩίÎŋ} other {# ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Îą}} ÎąĪ€ĪŒ Ī„Îŋ ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ;", "remove_assets_shared_link_confirmation": "Î•Î¯ĪƒĪ„Îĩ ĪƒÎ¯ÎŗÎŋ΅΁ÎŋΚ ĪŒĪ„Îš θέÎģÎĩĪ„Îĩ ÎŊÎą ÎąĪ†ÎąÎšĪÎ­ĪƒÎĩĪ„Îĩ {count, plural, one {# ĪƒĪ„ÎŋÎšĪ‡ÎĩίÎŋ} other {# ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Îą}} ÎąĪ€ĪŒ ÎąĪ…Ī„ĪŒÎŊ Ī„ÎŋÎŊ ÎēÎŋΚÎŊĪŒĪ‡ĪÎˇĪƒĪ„Îŋ ĪƒĪÎŊδÎĩ΃ÎŧÎŋ;", @@ -1629,6 +1674,7 @@ "restore_user": "Î•Ī€ÎąÎŊÎąĪ†Îŋ΁ÎŦ Ī‡ĪÎŽĪƒĪ„Îˇ", "restored_asset": "ΑÎŊÎąÎēĪ„ÎŽÎ¸ÎˇÎēÎĩ Ī„Îŋ ÎąĪĪ‡ÎĩίÎŋ", "resume": "ÎŖĪ…ÎŊÎ­Ī‡ÎšĪƒÎˇ", + "resume_paused_jobs": "ÎŖĪ…ÎŊÎ­Ī‡ÎšĪƒÎˇ {count, plural, one {# ΃Îĩ Ī€ÎąĪĪƒÎˇ ÎĩĪÎŗÎąĪƒÎ¯Îą} other {# ΃Îĩ Ī€ÎąĪĪƒÎˇ ÎĩĪÎŗÎąĪƒÎ¯ÎĩĪ‚}}", "retry_upload": "Î•Ī€ÎąÎŊÎŦÎģÎˇĪˆÎˇ ÎąÎŊÎĩβÎŦ΃ÎŧÎąĪ„ÎŋĪ‚", "review_duplicates": "Î ĪÎŋβÎŋÎģÎŽ Î´ÎšĪ€ÎģĪŒĪ„Ī…Ī€Ī‰ÎŊ", "review_large_files": "Î•Ī€ÎšĪƒÎēĪŒĪ€ÎˇĪƒÎˇ ÎŧÎĩÎŗÎŦÎģΉÎŊ ÎąĪĪ‡ÎĩÎ¯Ī‰ÎŊ", @@ -1722,6 +1768,7 @@ "select_user_for_sharing_page_err_album": "Î‘Ī€ÎŋĪ„Ī…Ī‡Î¯Îą δΡÎŧΚÎŋĪ…ĪÎŗÎ¯ÎąĪ‚ ÎŦÎģĪ€ÎŋĪ…Îŧ", "selected": "Î•Ī€ÎšÎģÎĩÎŗÎŧέÎŊÎŋΚ", "selected_count": "{count, plural, other {# ÎĩĪ€ÎšÎģÎĩÎŗÎŧέÎŊÎŋΚ}}", + "selected_gps_coordinates": "Î•Ī€ÎšÎģÎĩÎŗÎŧέÎŊÎĩĪ‚ ĪƒĪ…ÎŊĪ„ÎĩĪ„ÎąÎŗÎŧέÎŊÎĩĪ‚ GPS", "send_message": "Î‘Ī€ÎŋĪƒĪ„ÎŋÎģÎŽ ÎŧΡÎŊĪÎŧÎąĪ„ÎŋĪ‚", "send_welcome_email": "Î‘Ī€ÎŋĪƒĪ„ÎŋÎģÎŽ email ÎēÎąÎģĪ‰ĪƒÎŋĪÎ¯ĪƒÎŧÎąĪ„ÎŋĪ‚", "server_endpoint": "ΤÎĩÎģΚÎēΌ ĪƒÎˇÎŧÎĩίÎŋ ΔιαÎēÎŋÎŧÎšĪƒĪ„ÎŽ", @@ -1850,6 +1897,7 @@ "show_slideshow_transition": "ΕÎŧΆÎŦÎŊÎšĪƒÎˇ ÎŧÎĩĪ„ÎŦÎ˛ÎąĪƒÎˇĪ‚ Ī€ÎąĪÎŋĪ…ĪƒÎ¯ÎąĪƒÎˇĪ‚", "show_supporter_badge": "ÎŖÎŽÎŧÎą Ī…Ī€ÎŋĪƒĪ„ÎˇĪÎšÎēĪ„ÎŽ", "show_supporter_badge_description": "ΕÎŧΆÎŦÎŊÎšĪƒÎˇ ĪƒÎŽÎŧÎąĪ„ÎŋĪ‚ Ī…Ī€ÎŋĪƒĪ„ÎˇĪÎšÎēĪ„ÎŽ", + "show_text_search_menu": "ΕÎŧΆÎŦÎŊÎšĪƒÎˇ ÎŧÎĩÎŊÎŋĪ ÎąÎŊÎąÎļÎŽĪ„ÎˇĪƒÎˇĪ‚ ÎēÎĩΚÎŧέÎŊÎŋĪ…", "shuffle": "ΑÎŊÎŦÎŧÎĩΚΞΡ", "sidebar": "ΠÎģÎąĪŠÎŊÎŽ ÎŧĪ€ÎŦĪÎą", "sidebar_display_description": "ΕÎŧΆÎŦÎŊÎšĪƒÎˇ ĪƒĪ…ÎŊÎ´Î­ĪƒÎŧÎŋĪ… ÎŗÎšÎą ΀΁ÎŋβÎŋÎģÎŽ ĪƒĪ„ÎˇÎŊ Ī€ÎģÎąĪŠÎŊÎŽ ÎŧĪ€ÎŦĪÎą", @@ -1880,6 +1928,7 @@ "stacktrace": "ÎšÎąĪ„ÎąÎŗĪÎąĪ†ÎŽ ĪƒĪ„ÎŋÎ¯Î˛ÎąĪ‚", "start": "ΈÎŊÎąĪÎžÎˇ", "start_date": "Î‘Ī€ĪŒ", + "start_date_before_end_date": "Η ΡÎŧÎĩ΁ÎŋÎŧΡÎŊÎ¯Îą έÎŊÎąĪÎžÎˇĪ‚ Ī€ĪÎ­Ī€ÎĩΚ ÎŊÎą ÎĩίÎŊιΚ Ī€ĪÎšÎŊ ÎąĪ€ĪŒ Ī„ÎˇÎŊ ΡÎŧÎĩ΁ÎŋÎŧΡÎŊÎ¯Îą ÎģÎŽÎžÎˇĪ‚", "state": "ΝÎŋÎŧĪŒĪ‚", "status": "ÎšÎąĪ„ÎŦĪƒĪ„ÎąĪƒÎˇ", "stop_casting": "ΔιαÎēÎŋĪ€ÎŽ ÎŧÎĩĪ„ÎŦδÎŋĪƒÎˇĪ‚", @@ -1904,6 +1953,8 @@ "sync_albums_manual_subtitle": "ÎŖĪ…ÎŗĪ‡ĪÎŋÎŊÎ¯ĪƒĪ„Îĩ ΌÎģÎą Ī„Îą ÎŧÎĩĪ„ÎąĪ†Îŋ΁΄ΉÎŧέÎŊÎą Î˛Î¯ÎŊĪ„ÎĩÎŋ ÎēιΚ ΆΉ΄ÎŋÎŗĪÎąĪ†Î¯ÎĩĪ‚ ÎŧÎĩ Ī„Îą ÎĩĪ€ÎšÎģÎĩÎŗÎŧέÎŊÎą ÎĩΆÎĩÎ´ĪÎšÎēÎŦ ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ", "sync_local": "ΤÎŋĪ€ÎšÎēĪŒĪ‚ ÎŖĪ…ÎŗĪ‡ĪÎŋÎŊÎšĪƒÎŧĪŒĪ‚", "sync_remote": "Î‘Ī€ÎŋÎŧÎąÎēĪĪ…ĪƒÎŧέÎŊÎŋĪ‚ ÎŖĪ…ÎŗĪ‡ĪÎŋÎŊÎšĪƒÎŧĪŒĪ‚", + "sync_status": "ÎšÎąĪ„ÎŦĪƒĪ„ÎąĪƒÎˇ ĪƒĪ…ÎŗĪ‡ĪÎŋÎŊÎšĪƒÎŧÎŋĪ", + "sync_status_subtitle": "Î ĪÎŋβÎŋÎģÎŽ ÎēιΚ Î´ÎšÎąĪ‡ÎĩÎ¯ĪÎšĪƒÎˇ Ī„ÎŋĪ… ĪƒĪ…ĪƒĪ„ÎŽÎŧÎąĪ„ÎŋĪ‚ ĪƒĪ…ÎŗĪ‡ĪÎŋÎŊÎšĪƒÎŧÎŋĪ", "sync_upload_album_setting_subtitle": "ΔηÎŧΚÎŋĪ…ĪÎŗÎŽĪƒĪ„Îĩ ÎēιΚ ÎąÎŊÎĩβÎŦĪƒĪ„Îĩ Ī„ÎšĪ‚ ΆΉ΄ÎŋÎŗĪÎąĪ†Î¯ÎĩĪ‚ ÎēιΚ Ī„Îą Î˛Î¯ÎŊĪ„ÎĩΌ ĪƒÎąĪ‚ ĪƒĪ„Îą ÎĩĪ€ÎšÎģÎĩÎŗÎŧέÎŊÎą ÎŦÎģÎŧĪ€ÎŋĪ…Îŧ ĪƒĪ„Îŋ Immich", "tag": "Î•Ī„ÎšÎēÎ­Ī„Îą", "tag_assets": "Î•Ī„ÎšÎēÎĩĪ„ÎŋĪ€ÎŋÎ¯ÎˇĪƒÎˇ ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Ī‰ÎŊ", @@ -1941,7 +1992,9 @@ "to_change_password": "ΑÎģÎģÎąÎŗÎŽ ÎēĪ‰Î´ÎšÎēÎŋĪ Ī€ĪĪŒĪƒÎ˛ÎąĪƒÎˇĪ‚", "to_favorite": "Î‘ÎŗÎąĪ€ÎˇÎŧέÎŊÎŋ", "to_login": "Î•Î¯ĪƒÎŋδÎŋĪ‚", + "to_multi_select": "ÎŗÎšÎą Ī€ÎŋÎģÎģÎąĪ€ÎģÎŽ ÎĩĪ€ÎšÎģÎŋÎŗÎŽ", "to_parent": "ΜÎĩĪ„ÎąÎ˛ÎĩÎ¯Ī„Îĩ ĪƒĪ„Îŋ ÎŗÎŋÎŊΚÎēΌ ΆÎŦÎēÎĩÎģÎŋ", + "to_select": "ÎŗÎšÎą ÎĩĪ€ÎšÎģÎŋÎŗÎŽ", "to_trash": "ΚÎŦδÎŋĪ‚ ÎąĪ€ÎŋĪĪÎšÎŧÎŧÎŦ΄ΉÎŊ", "toggle_settings": "ΕÎŊÎąÎģÎģÎąÎŗÎŽ ĪĪ…Î¸ÎŧÎ¯ĪƒÎĩΉÎŊ", "total": "ÎŖĪÎŊÎŋÎģÎŋ", @@ -1961,6 +2014,7 @@ "trash_page_select_assets_btn": "Î•Ī€ÎšÎģÎ­ÎžĪ„Îĩ ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Îą", "trash_page_title": "ΚÎŦδÎŋĪ‚ Î‘Ī€ÎŋĪĪÎšÎŧÎŧÎŦ΄ΉÎŊ ({count})", "trashed_items_will_be_permanently_deleted_after": "Τι ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Îą Ī€ÎŋĪ… Î˛ĪÎ¯ĪƒÎēÎŋÎŊĪ„ÎąÎš ĪƒĪ„ÎŋÎŊ ÎēÎŦδÎŋ ÎąĪ€ÎŋĪĪÎšÎŧÎŧÎŦ΄ΉÎŊ θι Î´ÎšÎąÎŗĪÎąĪ†ÎŋĪÎŊ ÎŋĪÎšĪƒĪ„ÎšÎēÎŦ ÎŧÎĩĪ„ÎŦ ÎąĪ€ĪŒ {days, plural, one {# ΡÎŧÎ­ĪÎą} other {# ΡÎŧÎ­ĪÎĩĪ‚}}.", + "troubleshoot": "Î•Ī€Î¯ÎģĪ…ĪƒÎˇ ΀΁ÎŋβÎģΡÎŧÎŦ΄ΉÎŊ", "type": "Î¤ĪĪ€ÎŋĪ‚", "unable_to_change_pin_code": "Î‘Î´Ī…ÎŊÎąÎŧÎ¯Îą ÎąÎģÎģÎąÎŗÎŽĪ‚ ÎēĪ‰Î´ÎšÎēÎŋĪ PIN", "unable_to_setup_pin_code": "Î‘Î´Ī…ÎŊÎąÎŧÎ¯Îą ĪĪÎ¸ÎŧÎšĪƒÎˇĪ‚ ÎēĪ‰Î´ÎšÎēÎŋĪ PIN", @@ -1991,6 +2045,7 @@ "unstacked_assets_count": "Î‘Ī€ÎŋĪƒĪ„ÎŋΚβÎŦÎžÎąĪ„Îĩ {count, plural, one {# ĪƒĪ„ÎŋÎšĪ‡ÎĩίÎŋ} other {# ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Îą}}", "untagged": "Î§Ī‰ĪÎ¯Ī‚ ÎĩĪ„ÎšÎēÎ­Ī„Îą", "up_next": "ΑÎēÎŋÎģÎŋĪ…Î¸Îĩί", + "update_location_action_prompt": "ΕÎŊΡÎŧÎ­ĪĪ‰ĪƒÎˇ Ī„ÎŋĪ€ÎŋθÎĩĪƒÎ¯ÎąĪ‚ ÎŗÎšÎą {count} ÎĩĪ€ÎšÎģÎĩÎŗÎŧέÎŊÎą ĪƒĪ„ÎŋÎšĪ‡ÎĩÎ¯Îą ÎŧÎĩ:", "updated_at": "ΕÎŊΡÎŧÎĩ΁ΉÎŧέÎŊÎŋ", "updated_password": "Ο ÎēĪ‰Î´ÎšÎēĪŒĪ‚ Ī€ĪĪŒĪƒÎ˛ÎąĪƒÎˇĪ‚ ÎĩÎŊΡÎŧÎĩĪĪŽÎ¸ÎˇÎēÎĩ", "upload": "ΜÎĩĪ„ÎąĪ†ĪŒĪĪ„Ī‰ĪƒÎˇ", @@ -2057,6 +2112,7 @@ "view_next_asset": "Î ĪÎŋβÎŋÎģÎŽ ÎĩĪ€ĪŒÎŧÎĩÎŊÎŋĪ… ĪƒĪ„ÎŋÎšĪ‡ÎĩίÎŋĪ…", "view_previous_asset": "Î ĪÎŋβÎŋÎģÎŽ ΀΁ÎŋÎˇÎŗÎŋĪÎŧÎĩÎŊÎŋĪ… ĪƒĪ„ÎŋÎšĪ‡ÎĩίÎŋĪ…", "view_qr_code": "Î ĪÎŋβÎŋÎģÎŽ ÎēĪ‰Î´ÎšÎēÎŋĪ QR", + "view_similar_photos": "Î ĪÎŋβÎŋÎģÎŽ Ī€ÎąĪĪŒÎŧÎŋÎšĪ‰ÎŊ ΆΉ΄ÎŋÎŗĪÎąĪ†ÎšĪŽÎŊ", "view_stack": "Î ĪÎŋβÎŋÎģÎŽ Ī„ÎˇĪ‚ ĪƒĪ„ÎŋÎ¯Î˛ÎąĪ‚", "view_user": "Î ĪÎŋβÎŋÎģÎŽ Î§ĪÎŽĪƒĪ„Îˇ", "viewer_remove_from_stack": "ÎšÎąĪ„ÎŦĪÎŗÎˇĪƒÎˇ ÎąĪ€ĪŒ Ī„Îˇ ÎŖĪ„ÎŋÎ¯Î˛Îą", @@ -2075,5 +2131,6 @@ "yes": "Ναι", "you_dont_have_any_shared_links": "ΔÎĩÎŊ Î­Ī‡ÎĩĪ„Îĩ ÎēÎŋΚÎŊĪŒĪ‡ĪÎˇĪƒĪ„ÎŋĪ…Ī‚ ĪƒĪ…ÎŊÎ´Î­ĪƒÎŧÎŋĪ…Ī‚", "your_wifi_name": "ΤÎŋ ΌÎŊÎŋÎŧÎą Ī„ÎŋĪ… Wi-Fi ĪƒÎąĪ‚", - "zoom_image": "ΖÎŋĪ…Îŧ ΕιÎēΌÎŊÎąĪ‚" + "zoom_image": "ΖÎŋĪ…Îŧ ΕιÎēΌÎŊÎąĪ‚", + "zoom_to_bounds": "Î•ĪƒĪ„Î¯ÎąĪƒÎˇ ĪƒĪ„Îą ĪŒĪÎšÎą" } diff --git a/i18n/en.json b/i18n/en.json index a0cfe558b2..58e6390389 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -28,10 +28,12 @@ "add_to_album": "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_some_local_assets": "Some local assets could not be added to album", "add_to_album_toggle": "Toggle selection for {album}", "add_to_albums": "Add to albums", "add_to_albums_count": "Add to albums ({count})", "add_to_shared_album": "Add to shared album", + "add_upload_to_stack": "Add upload to stack", "add_url": "Add URL", "added_to_archive": "Added to archive", "added_to_favorites": "Added to favorites", @@ -123,6 +125,13 @@ "logging_enable_description": "Enable logging", "logging_level_description": "When enabled, what log level to use.", "logging_settings": "Logging", + "machine_learning_availability_checks": "Availability checks", + "machine_learning_availability_checks_description": "Automatically detect and prefer available machine learning servers", + "machine_learning_availability_checks_enabled": "Enable availability checks", + "machine_learning_availability_checks_interval": "Check interval", + "machine_learning_availability_checks_interval_description": "Interval in milliseconds between availability checks", + "machine_learning_availability_checks_timeout": "Request timeout", + "machine_learning_availability_checks_timeout_description": "Timeout in milliseconds for availability checks", "machine_learning_clip_model": "CLIP model", "machine_learning_clip_model_description": "The name of a CLIP model listed here. Note that you must re-run the 'Smart Search' job for all images upon changing a model.", "machine_learning_duplicate_detection": "Duplicate Detection", @@ -324,7 +333,7 @@ "transcoding_max_b_frames": "Maximum B-frames", "transcoding_max_b_frames_description": "Higher values improve compression efficiency, but slow down encoding. May not be compatible with hardware acceleration on older devices. 0 disables B-frames, while -1 sets this value automatically.", "transcoding_max_bitrate": "Maximum bitrate", - "transcoding_max_bitrate_description": "Setting a max bitrate can make file sizes more predictable at a minor cost to quality. At 720p, typical values are 2600 kbit/s for VP9 or HEVC, or 4500 kbit/s for H.264. Disabled if set to 0.", + "transcoding_max_bitrate_description": "Setting a max bitrate can make file sizes more predictable at a minor cost to quality. At 720p, typical values are 2600 kbit/s for VP9 or HEVC, or 4500 kbit/s for H.264. Disabled if set to 0. When no unit is specified, k (for kbit/s) is assumed; therefore 5000, 5000k, and 5M (for Mbit/s) are equivalent.", "transcoding_max_keyframe_interval": "Maximum keyframe interval", "transcoding_max_keyframe_interval_description": "Sets the maximum frame distance between keyframes. Lower values worsen compression efficiency, but improve seek times and may improve quality in scenes with fast movement. 0 sets this value automatically.", "transcoding_optimal_description": "Videos higher than target resolution or not in an accepted format", @@ -342,7 +351,7 @@ "transcoding_target_resolution": "Target resolution", "transcoding_target_resolution_description": "Higher resolutions can preserve more detail but take longer to encode, have larger file sizes, and can reduce app responsiveness.", "transcoding_temporal_aq": "Temporal AQ", - "transcoding_temporal_aq_description": "Applies only to NVENC. Increases quality of high-detail, low-motion scenes. May not be compatible with older devices.", + "transcoding_temporal_aq_description": "Applies only to NVENC. Temporal Adaptive Quantization increases quality of high-detail, low-motion scenes. May not be compatible with older devices.", "transcoding_threads": "Threads", "transcoding_threads_description": "Higher values lead to faster encoding, but leave less room for the server to process other tasks while active. This value should not be more than the number of CPU cores. Maximizes utilization if set to 0.", "transcoding_tone_mapping": "Tone-mapping", @@ -387,8 +396,6 @@ "admin_password": "Admin Password", "administration": "Administration", "advanced": "Advanced", - "advanced_settings_beta_timeline_subtitle": "Try the new app experience", - "advanced_settings_beta_timeline_title": "Beta Timeline", "advanced_settings_enable_alternate_media_filter_subtitle": "Use this option to filter media during sync based on alternate criteria. Only try this if you have issues with the app detecting all albums.", "advanced_settings_enable_alternate_media_filter_title": "[EXPERIMENTAL] Use alternate device album sync filter", "advanced_settings_log_level_title": "Log level: {level}", @@ -425,6 +432,7 @@ "album_remove_user_confirmation": "Are you sure you want to remove {user}?", "album_search_not_found": "No albums found matching your search", "album_share_no_users": "Looks like you have shared this album with all users or you don't have any user to share with.", + "album_summary": "Album summary", "album_updated": "Album updated", "album_updated_setting_description": "Receive an email notification when a shared album has new assets", "album_user_left": "Left {album}", @@ -496,6 +504,8 @@ "asset_restored_successfully": "Asset restored successfully", "asset_skipped": "Skipped", "asset_skipped_in_trash": "In trash", + "asset_trashed": "Asset trashed", + "asset_troubleshoot": "Asset Troubleshoot", "asset_uploaded": "Uploaded", "asset_uploading": "Uploadingâ€Ļ", "asset_viewer_settings_subtitle": "Manage your gallery viewer settings", @@ -529,8 +539,10 @@ "autoplay_slideshow": "Autoplay slideshow", "back": "Back", "back_close_deselect": "Back, close, or deselect", + "background_backup_running_error": "Background backup is currently running, cannot start manual backup", "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_options": "Background Options", "backup": "Backup", "backup_album_selection_page_albums_device": "Albums on device ({count})", "backup_album_selection_page_albums_tap": "Tap to include, double tap to exclude", @@ -538,6 +550,7 @@ "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_albums_sync": "Backup albums synchronization", "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â€Ļ", @@ -587,6 +600,7 @@ "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_error_sync_failed": "Sync failed. Cannot process backup.", "backup_info_card_assets": "assets", "backup_manual_cancelled": "Cancelled", "backup_manual_in_progress": "Upload already in progress. Try after sometime", @@ -597,8 +611,6 @@ "backup_setting_subtitle": "Manage background and foreground upload settings", "backup_settings_subtitle": "Manage upload settings", "backward": "Backward", - "beta_sync": "Beta Sync Status", - "beta_sync_subtitle": "Manage the new sync system", "biometric_auth_enabled": "Biometric authentication enabled", "biometric_locked_out": "You are locked out of biometric authentication", "biometric_no_options": "No biometric options available", @@ -656,6 +668,8 @@ "change_pin_code": "Change PIN code", "change_your_password": "Change your password", "changed_visibility_successfully": "Changed visibility successfully", + "charging": "Charging", + "charging_requirement_mobile_backup": "Background backup requires the device to be charging", "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.", @@ -742,6 +756,7 @@ "create_user": "Create user", "created": "Created", "created_at": "Created", + "creating_linked_albums": "Creating linked albums...", "crop": "Crop", "curated_object_page_title": "Things", "current_device": "Current device", @@ -891,7 +906,9 @@ "error": "Error", "error_change_sort_album": "Failed to change album sort order", "error_delete_face": "Error deleting face from asset", + "error_getting_places": "Error getting places", "error_loading_image": "Error loading image", + "error_loading_partners": "Error loading partners: {error}", "error_saving_image": "Error: {error}", "error_tag_face_bounding_box": "Error tagging face - cannot get bounding box coordinates", "error_title": "Error - Something went wrong", @@ -1022,6 +1039,7 @@ "exif_bottom_sheet_description_error": "Error updating description", "exif_bottom_sheet_details": "DETAILS", "exif_bottom_sheet_location": "LOCATION", + "exif_bottom_sheet_no_description": "No description", "exif_bottom_sheet_people": "PEOPLE", "exif_bottom_sheet_person_add_person": "Add name", "exit_slideshow": "Exit Slideshow", @@ -1056,6 +1074,7 @@ "favorites_page_no_favorites": "No favorite assets found", "feature_photo_updated": "Feature photo updated", "features": "Features", + "features_in_development": "Features in Development", "features_setting_description": "Manage the app features", "file_name": "File name", "file_name_or_extension": "File name or extension", @@ -1076,10 +1095,7 @@ "gcast_enabled": "Google Cast", "gcast_enabled_description": "This feature loads external resources from Google in order to work.", "general": "General", - "geolocation_instruction_all_have_location": "All assets for this date already have location data. Try showing all assets or select a different date", "geolocation_instruction_location": "Click on an asset with GPS coordinates to use its location, or select a location directly from the map", - "geolocation_instruction_no_date": "Select a date to manage location data for photos and videos from that day", - "geolocation_instruction_no_photos": "No photos or videos found for this date. Select a different date to show them", "get_help": "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", "getting_started": "Getting Started", @@ -1223,6 +1239,7 @@ "local": "Local", "local_asset_cast_failed": "Unable to cast an asset that is not uploaded to the server", "local_assets": "Local Assets", + "local_media_summary": "Local Media Summary", "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", @@ -1234,6 +1251,7 @@ "location_picker_longitude_hint": "Enter your longitude here", "lock": "Lock", "locked_folder": "Locked Folder", + "log_detail_title": "Log Detail", "log_out": "Log out", "log_out_all_devices": "Log Out All Devices", "logged_in_as": "Logged in as {user}", @@ -1264,6 +1282,7 @@ "login_password_changed_success": "Password updated successfully", "logout_all_device_confirmation": "Are you sure you want to log out all devices?", "logout_this_device_confirmation": "Are you sure you want to log out this device?", + "logs": "Logs", "longitude": "Longitude", "look": "Look", "loop_videos": "Loop videos", @@ -1306,6 +1325,7 @@ "mark_as_read": "Mark as read", "marked_all_as_read": "Marked all as read", "matches": "Matches", + "matching_assets": "Matching Assets", "media_type": "Media type", "memories": "Memories", "memories_all_caught_up": "All caught up", @@ -1344,18 +1364,23 @@ "my_albums": "My albums", "name": "Name", "name_or_nickname": "Name or nickname", + "navigate": "Navigate", + "navigate_to_time": "Navigate to Time", "network_requirement_photos_upload": "Use cellular data to backup photos", "network_requirement_videos_upload": "Use cellular data to backup videos", + "network_requirements": "Network Requirements", "network_requirements_updated": "Network requirements changed, resetting backup queue", "networking_settings": "Networking", "networking_subtitle": "Manage the server endpoint settings", "never": "Never", "new_album": "New Album", "new_api_key": "New API Key", + "new_date_range": "New date range", "new_password": "New password", "new_person": "New person", "new_pin_code": "New PIN code", "new_pin_code_subtitle": "This is your first time accessing the locked folder. Create a PIN code to securely access this page", + "new_timeline": "New Timeline", "new_user_created": "New user created", "new_version_available": "NEW VERSION AVAILABLE", "newest_first": "Newest first", @@ -1369,20 +1394,25 @@ "no_assets_message": "CLICK TO UPLOAD YOUR FIRST PHOTO", "no_assets_to_show": "No assets to show", "no_cast_devices_found": "No cast devices found", + "no_checksum_local": "No checksum available - cannot fetch local assets", + "no_checksum_remote": "No checksum available - cannot fetch remote asset", "no_duplicates_found": "No duplicates were found.", "no_exif_info_available": "No exif info available", "no_explore_results_message": "Upload more photos to explore your collection.", "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_local_assets_found": "No local assets found with this checksum", "no_locked_photos_message": "Photos and videos in the locked folder are hidden and won't show up as you browse or search your library.", "no_name": "No Name", "no_notifications": "No notifications", "no_people_found": "No matching people found", "no_places": "No places", + "no_remote_assets_found": "No remote assets found with this checksum", "no_results": "No results", "no_results_description": "Try a synonym or more general keyword", "no_shared_albums_message": "Create an album to share photos and videos with people in your network", "no_uploads_in_progress": "No uploads in progress", + "not_available": "N/A", "not_in_any_album": "Not in any album", "not_selected": "Not selected", "note_apply_storage_label_to_previously_uploaded assets": "Note: To apply the Storage Label to previously uploaded assets, run the", @@ -1504,6 +1534,7 @@ "port": "Port", "preferences_settings_subtitle": "Manage the app's preferences", "preferences_settings_title": "Preferences", + "preparing": "Preparing", "preset": "Preset", "preview": "Preview", "previous": "Previous", @@ -1520,7 +1551,7 @@ "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", "profile_drawer_github": "GitHub", - "profile_drawer_readonly_mode": "Read-only mode enabled. Double-tap the user avatar icon to exit.", + "profile_drawer_readonly_mode": "Read-only mode enabled. Long-press the user avatar icon to exit.", "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.", "profile_image_of_user": "Profile image of {user}", @@ -1569,6 +1600,7 @@ "read_changelog": "Read Changelog", "readonly_mode_disabled": "Read-only mode disabled", "readonly_mode_enabled": "Read-only mode enabled", + "ready_for_upload": "Ready for upload", "reassign": "Reassign", "reassigned_assets_to_existing_person": "Re-assigned {count, plural, one {# asset} other {# assets}} to {name, select, null {an existing person} other {{name}}}", "reassigned_assets_to_new_person": "Re-assigned {count, plural, one {# asset} other {# assets}} to a new person", @@ -1593,6 +1625,7 @@ "regenerating_thumbnails": "Regenerating thumbnails", "remote": "Remote", "remote_assets": "Remote Assets", + "remote_media_summary": "Remote Media Summary", "remove": "Remove", "remove_assets_album_confirmation": "Are you sure you want to remove {count, plural, one {# asset} other {# assets}} from the album?", "remove_assets_shared_link_confirmation": "Are you sure you want to remove {count, plural, one {# asset} other {# assets}} from this shared link?", @@ -1645,6 +1678,7 @@ "restore_user": "Restore user", "restored_asset": "Restored asset", "resume": "Resume", + "resume_paused_jobs": "Resume {count, plural, one {# paused job} other {# paused jobs}}", "retry_upload": "Retry upload", "review_duplicates": "Review duplicates", "review_large_files": "Review large files", @@ -1777,6 +1811,8 @@ "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_auto_play_subtitle": "Automatically start playing videos when they are opened", + "setting_video_viewer_auto_play_title": "Auto play videos", "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", @@ -1850,10 +1886,8 @@ "shift_to_permanent_delete": "press ⇧ to permanently delete asset", "show_album_options": "Show album options", "show_albums": "Show albums", - "show_all_assets": "Show all assets", "show_all_people": "Show all people", "show_and_hide_people": "Show & hide people", - "show_assets_without_location": "Show assets without location", "show_file_location": "Show file location", "show_gallery": "Show gallery", "show_hidden_people": "Show hidden people", @@ -1870,6 +1904,7 @@ "show_slideshow_transition": "Show slideshow transition", "show_supporter_badge": "Supporter badge", "show_supporter_badge_description": "Show a supporter badge", + "show_text_search_menu": "Show text search menu", "shuffle": "Shuffle", "sidebar": "Sidebar", "sidebar_display_description": "Display a link to the view in the sidebar", @@ -1900,6 +1935,7 @@ "stacktrace": "Stacktrace", "start": "Start", "start_date": "Start date", + "start_date_before_end_date": "Start date must be before end date", "state": "State", "status": "Status", "stop_casting": "Stop casting", @@ -1924,6 +1960,8 @@ "sync_albums_manual_subtitle": "Sync all uploaded videos and photos to the selected backup albums", "sync_local": "Sync Local", "sync_remote": "Sync Remote", + "sync_status": "Sync Status", + "sync_status_subtitle": "View and manage the sync system", "sync_upload_album_setting_subtitle": "Create and upload your photos and videos to the selected albums on Immich", "tag": "Tag", "tag_assets": "Tag assets", @@ -1983,6 +2021,7 @@ "trash_page_select_assets_btn": "Select assets", "trash_page_title": "Trash ({count})", "trashed_items_will_be_permanently_deleted_after": "Trashed items will be permanently deleted after {days, plural, one {# day} other {# days}}.", + "troubleshoot": "Troubleshoot", "type": "Type", "unable_to_change_pin_code": "Unable to change PIN code", "unable_to_setup_pin_code": "Unable to setup PIN code", @@ -2038,7 +2077,6 @@ "use_biometric": "Use biometric", "use_current_connection": "use current connection", "use_custom_date_range": "Use custom date range instead", - "use_this_location": "Click to use location", "user": "User", "user_has_been_deleted": "This user has been deleted.", "user_id": "User ID", @@ -2100,5 +2138,6 @@ "yes": "Yes", "you_dont_have_any_shared_links": "You don't have any shared links", "your_wifi_name": "Your Wi-Fi name", - "zoom_image": "Zoom Image" + "zoom_image": "Zoom Image", + "zoom_to_bounds": "Zoom to bounds" } diff --git a/i18n/es.json b/i18n/es.json index cffc32d5bd..c08f93da08 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -28,17 +28,19 @@ "add_to_album": "Incluir en ÃĄlbum", "add_to_album_bottom_sheet_added": "Agregado a {album}", "add_to_album_bottom_sheet_already_exists": "Ya se encuentra en {album}", + "add_to_album_bottom_sheet_some_local_assets": "Algunos recursos locales no se pudieron aÃąadir al ÃĄlbum", "add_to_album_toggle": "Alternar selecciÃŗn para el {album}", "add_to_albums": "Incluir en ÃĄlbumes", "add_to_albums_count": "Incluir en {count} ÃĄlbumes", "add_to_shared_album": "Incluir en ÃĄlbum compartido", + "add_upload_to_stack": "AÃąadir archivo y apilar", "add_url": "Agregar URL", "added_to_archive": "Agregado al Archivado", "added_to_favorites": "Agregado a favoritos", "added_to_favorites_count": "Agregado {count, number} a favoritos", "admin": { "add_exclusion_pattern_description": "Agrega patrones de exclusiÃŗn. Puedes utilizar los caracteres *, ** y ? (globbing). Ejemplos: para ignorar todos los archivos en cualquier directorio llamado \"Raw\", utiliza \"**/Raw/**\". Para ignorar todos los archivos que terminan en \".tif\", utiliza \"**/*.tif\". Para ignorar una ruta absoluta, utiliza \"/carpeta/a/ignorar/**\".", - "admin_user": "Usuario administrativo", + "admin_user": "Usuario administrador", "asset_offline_description": "Este recurso externo de la biblioteca ya no se encuentra en el disco y se ha movido a la papelera. Si el archivo se moviÃŗ dentro de la biblioteca, comprueba la línea temporal para el nuevo recurso correspondiente. Para restaurar este recurso, asegÃērate de que Immich puede acceder a la siguiente ruta de archivo y escanear la biblioteca.", "authentication_settings": "ParÃĄmetros de autenticaciÃŗn", "authentication_settings_description": "Gestionar contraseÃąas, OAuth y otros parÃĄmetros de autenticaciÃŗn", @@ -123,6 +125,13 @@ "logging_enable_description": "Habilitar registro", "logging_level_description": "Indica el nivel de registro a utilizar cuando estÃĄ habilitado.", "logging_settings": "Registro", + "machine_learning_availability_checks": "Comprobaciones de disponibilidad", + "machine_learning_availability_checks_description": "AutomÃĄticamente detectar y preferir servidores de machine learning disponibles", + "machine_learning_availability_checks_enabled": "Habilitar comprobaciones de disponibilidad", + "machine_learning_availability_checks_interval": "Intervalo de comprobaciÃŗn", + "machine_learning_availability_checks_interval_description": "Intervalo en milisegundos entre las comprobaciones de disponibilidad", + "machine_learning_availability_checks_timeout": "Tiempo de espera de solicitud", + "machine_learning_availability_checks_timeout_description": "Tiempo de espera en milisegundos para comprobaciones de disponibilidad", "machine_learning_clip_model": "Modelo CLIP (Contrastive Language-Image Pre-Training)", "machine_learning_clip_model_description": "El nombre de un modelo CLIP listado aquí. TendrÃĄs que relanzar el trabajo 'BÃēsqueda Inteligente' para todos los elementos al cambiar de modelo.", "machine_learning_duplicate_detection": "DetecciÃŗn de duplicados", @@ -387,8 +396,6 @@ "admin_password": "ContraseÃąa del administrador", "administration": "AdministraciÃŗn", "advanced": "Avanzada", - "advanced_settings_beta_timeline_subtitle": "Prueba la nueva experiencia de la aplicaciÃŗn", - "advanced_settings_beta_timeline_title": "Cronología beta", "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: {level}", @@ -425,6 +432,7 @@ "album_remove_user_confirmation": "ÂŋEstÃĄs seguro de que quieres eliminar a {user}?", "album_search_not_found": "No se encontraron ÃĄlbumes que coincidan con tu bÃēsqueda", "album_share_no_users": "Parece que has compartido este ÃĄlbum con todos los usuarios o no tienes ningÃēn usuario con quien compartirlo.", + "album_summary": "Resumen del ÃĄlbum", "album_updated": "Album actualizado", "album_updated_setting_description": "Reciba una notificaciÃŗn por correo electrÃŗnico cuando un ÃĄlbum compartido tenga nuevos archivos", "album_user_left": "Salida {album}", @@ -496,6 +504,8 @@ "asset_restored_successfully": "Elementos restaurados exitosamente", "asset_skipped": "Omitido", "asset_skipped_in_trash": "En la papelera", + "asset_trashed": "Elemento eliminado", + "asset_troubleshoot": "DiagnÃŗstico del elemento", "asset_uploaded": "Subido", "asset_uploading": "Subiendoâ€Ļ", "asset_viewer_settings_subtitle": "Administra las configuracioens de tu visor de fotos", @@ -529,8 +539,10 @@ "autoplay_slideshow": "PresentaciÃŗn con reproducciÃŗn automÃĄtica", "back": "AtrÃĄs", "back_close_deselect": "AtrÃĄs, cerrar o anular la selecciÃŗn", + "background_backup_running_error": "Ya se estÃĄ ejecutando la copia de seguridad en segundo plano, no se puede iniciar la copia de seguridad manual", "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", + "background_options": "Opciones de segundo plano", "backup": "Copia de Seguridad", "backup_album_selection_page_albums_device": "Álbumes en el dispositivo ({count})", "backup_album_selection_page_albums_tap": "Toque para incluir, doble toque para excluir", @@ -538,6 +550,7 @@ "backup_album_selection_page_select_albums": "Seleccionar ÃĄlbumes", "backup_album_selection_page_selection_info": "InformaciÃŗn sobre la SelecciÃŗn", "backup_album_selection_page_total_assets": "Total de elementos Ãēnicos", + "backup_albums_sync": "SincronizaciÃŗn de ÃĄlbumes de respaldo", "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â€Ļ", @@ -587,6 +600,7 @@ "backup_controller_page_turn_on": "Activar la copia de seguridad", "backup_controller_page_uploading_file_info": "Subiendo informaciÃŗn del archivo", "backup_err_only_album": "No se puede eliminar el Ãēnico ÃĄlbum", + "backup_error_sync_failed": "La sincronizaciÃŗn fallÃŗ. No es posible procesar la copia de seguridad.", "backup_info_card_assets": "elementos", "backup_manual_cancelled": "Cancelado", "backup_manual_in_progress": "Subida ya en progreso. Vuelve a intentarlo mÃĄs tarde", @@ -597,8 +611,6 @@ "backup_setting_subtitle": "Administra las configuraciones de respaldo en segundo y primer plano", "backup_settings_subtitle": "Configura las opciones de subida", "backward": "Retroceder", - "beta_sync": "Estado de SincronizaciÃŗn Beta", - "beta_sync_subtitle": "Administrar el nuevo sistema de sincronizaciÃŗn", "biometric_auth_enabled": "AutentificaciÃŗn biomÊtrica habilitada", "biometric_locked_out": "EstÃĄs bloqueado de la autentificaciÃŗn biomÊtrica", "biometric_no_options": "Sin opciones biomÊtricas disponibles", @@ -656,6 +668,8 @@ "change_pin_code": "Cambiar PIN", "change_your_password": "Cambia tu contraseÃąa", "changed_visibility_successfully": "Visibilidad cambiada correctamente", + "charging": "Cargando", + "charging_requirement_mobile_backup": "La copia de seguridad en segundo plano requiere que el dispositivo se estÊ cargando", "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.", @@ -687,7 +701,7 @@ "comments_and_likes": "Comentarios y me gusta", "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.", + "common_server_error": "Por favor, comprueba 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": "Completado", "confirm": "Confirmar", "confirm_admin_password": "Confirmar contraseÃąa del administrador", @@ -742,6 +756,7 @@ "create_user": "Crear usuario", "created": "Creado", "created_at": "Creado", + "creating_linked_albums": "Creando ÃĄlbumes vinculados...", "crop": "Recortar", "curated_object_page_title": "Objetos", "current_device": "Dispositivo actual", @@ -800,7 +815,7 @@ "deletes_missing_assets": "Elimina archivos que faltan en el disco duro", "description": "DescripciÃŗn", "description_input_hint_text": "Agregar descripciÃŗn...", - "description_input_submit_error": "Error al actualizar la descripciÃŗn, verifica el registro para obtener mÃĄs detalles", + "description_input_submit_error": "Error al actualizar la descripciÃŗn, comprueba el registro para obtener mÃĄs detalles", "deselect_all": "Deseleccionar Todo", "details": "Detalles", "direction": "DirecciÃŗn", @@ -891,7 +906,9 @@ "error": "Error", "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_getting_places": "Error obteniendo lugares", "error_loading_image": "Error al cargar la imagen", + "error_loading_partners": "Error al cargar compaÃąeros: {error}", "error_saving_image": "Error: {error}", "error_tag_face_bounding_box": "Error al etiquetar la cara: no se pueden obtener las coordenadas del marco", "error_title": "Error: algo saliÃŗ mal", @@ -1056,6 +1073,7 @@ "favorites_page_no_favorites": "No se encontraron elementos marcados como favoritos", "feature_photo_updated": "Foto destacada actualizada", "features": "Características", + "features_in_development": "Funciones en Desarrollo", "features_setting_description": "Administrar las funciones de la aplicaciÃŗn", "file_name": "Nombre de archivo", "file_name_or_extension": "Nombre del archivo o extensiÃŗn", @@ -1072,14 +1090,11 @@ "folders": "Carpetas", "folders_feature_description": "Explorar la vista de carpetas para las fotos y los videos en el sistema de archivos", "forgot_pin_code_question": "ÂŋOlvidaste tu cÃŗdigo PIN?", - "forward": "Reenviar", + "forward": "Avanzar", "gcast_enabled": "Google Cast", "gcast_enabled_description": "Esta funcionalidad carga recursos externos desde Google para poder funcionar.", "general": "General", - "geolocation_instruction_all_have_location": "Todos los assets de esta fecha ya tienen datos de ubicaciÃŗn. Prueba mostrando todos los assets o selecciona otra fecha", "geolocation_instruction_location": "Da click en un asset con coordenadas GPS para usar su ubicacion, o selecciona una ubicacion directamente en el mapa", - "geolocation_instruction_no_date": "Seleccione una fecha para administrar los datos de ubicaciÃŗn de las fotos y los videos de ese día", - "geolocation_instruction_no_photos": "No se encontraron fotos ni vídeos para esta fecha. Seleccione otra fecha para mostrarlos", "get_help": "Solicitar ayuda", "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", @@ -1223,6 +1238,7 @@ "local": "Local", "local_asset_cast_failed": "No es posible transmitir un recurso que no estÃĄ subido al servidor", "local_assets": "Archivos Locales", + "local_media_summary": "Resumen de Medios Locales", "local_network": "Red local", "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", @@ -1234,6 +1250,7 @@ "location_picker_longitude_hint": "Introduce tu longitud aquí", "lock": "Bloquear", "locked_folder": "Carpeta protegida", + "log_detail_title": "Detalle del registro", "log_out": "Cerrar sesiÃŗn", "log_out_all_devices": "Cerrar sesiÃŗn en todos los dispositivos", "logged_in_as": "SesiÃŗn iniciada como {user}", @@ -1241,7 +1258,7 @@ "logged_out_device": "Dispositivo desconectado", "login": "Inicio de sesiÃŗn", "login_disabled": "El inicio de sesiÃŗn ha sido desactivado", - "login_form_api_exception": "ExcepciÃŗn producida por API. Por favor, verifica el URL del servidor e intÊntalo de nuevo.", + "login_form_api_exception": "ExcepciÃŗn producida por API. Por favor, comprueba el URL del servidor e intÊntalo de nuevo.", "login_form_back_button_text": "AtrÃĄs", "login_form_email_hint": "tucorreo@correo.com", "login_form_endpoint_hint": "http://tu-ip-de-servidor:puerto", @@ -1251,7 +1268,7 @@ "login_form_err_invalid_url": "URL no vÃĄlida", "login_form_err_leading_whitespace": "Espacio en blanco inicial", "login_form_err_trailing_whitespace": "Espacio en blanco al final", - "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_config": "Error al iniciar sesiÃŗn con OAuth, comprueba 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 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.", @@ -1264,6 +1281,7 @@ "login_password_changed_success": "ContraseÃąa cambiado con Êxito", "logout_all_device_confirmation": "ÂŋEstÃĄs seguro de que quieres cerrar sesiÃŗn en todos los dispositivos?", "logout_this_device_confirmation": "ÂŋEstÃĄs seguro de que quieres cerrar sesiÃŗn en este dispositivo?", + "logs": "Registros", "longitude": "Longitud", "look": "Mirar", "loop_videos": "Vídeos en bucle", @@ -1306,6 +1324,7 @@ "mark_as_read": "Marcar como leído", "marked_all_as_read": "Todos marcados como leídos", "matches": "Coincidencias", + "matching_assets": "Elementos Coincidentes", "media_type": "Tipo de medio", "memories": "Recuerdos", "memories_all_caught_up": "Puesto al día", @@ -1346,6 +1365,7 @@ "name_or_nickname": "Nombre o apodo", "network_requirement_photos_upload": "Usar datos mÃŗviles para crear una copia de seguridad de las fotos", "network_requirement_videos_upload": "Usar datos mÃŗviles para crear una copia de seguridad de los videos", + "network_requirements": "Requisitos de red", "network_requirements_updated": "Los requisitos de red han cambiado, reiniciando la cola de copias de seguridad", "networking_settings": "Red", "networking_subtitle": "Configuraciones de acceso por URL al servidor", @@ -1356,6 +1376,7 @@ "new_person": "Nueva persona", "new_pin_code": "Nuevo PIN", "new_pin_code_subtitle": "Esta es la primera vez que accedes a la carpeta protegida. Crea un cÃŗdigo PIN seguro para acceder a esta pÃĄgina", + "new_timeline": "Nueva Línea de tiempo", "new_user_created": "Nuevo usuario creado", "new_version_available": "NUEVA VERSIÓN DISPONIBLE", "newest_first": "El mÃĄs reciente primero", @@ -1369,20 +1390,25 @@ "no_assets_message": "HAZ CLIC PARA SUBIR TU PRIMERA FOTO", "no_assets_to_show": "No hay elementos a mostrar", "no_cast_devices_found": "No se encontraron dispositivos de transmisiÃŗn", + "no_checksum_local": "Suma de verificaciÃŗn no disponible. No se pueden obtener los elementos locales", + "no_checksum_remote": "Suma de verificaciÃŗn no disponible. No se puede obtener el elemento remoto", "no_duplicates_found": "No se encontraron duplicados.", "no_exif_info_available": "No hay informaciÃŗn exif disponible", "no_explore_results_message": "Sube mÃĄs fotos para explorar tu colecciÃŗn.", "no_favorites_message": "Agregue favoritos para encontrar rÃĄpidamente sus mejores fotos y videos", "no_libraries_message": "Crea una biblioteca externa para ver tus fotos y vídeos", + "no_local_assets_found": "No se encontraron elementos locales con esta suma de comprobaciÃŗn", "no_locked_photos_message": "Las fotos y los vídeos de la carpeta protegida se mantienen ocultos; no aparecerÃĄn cuando veas o busques elementos en tu biblioteca.", "no_name": "Sin nombre", "no_notifications": "Ninguna notificaciÃŗn", "no_people_found": "No se encontraron personas coincidentes", "no_places": "Sin lugares", + "no_remote_assets_found": "No se encontraron elementos remotos con esta suma de comprobaciÃŗn", "no_results": "Sin resultados", "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", "no_uploads_in_progress": "No hay cargas en progreso", + "not_available": "N/D", "not_in_any_album": "Sin ÃĄlbum", "not_selected": "No seleccionado", "note_apply_storage_label_to_previously_uploaded assets": "Nota: Para aplicar la etiqueta de almacenamiento a los archivos que ya se subieron, ejecute la", @@ -1417,10 +1443,12 @@ "open_the_search_filters": "Abre los filtros de bÃēsqueda", "options": "Opciones", "or": "o", + "organize_into_albums": "Organizar en ÃĄlbumes", + "organize_into_albums_description": "AÃąade fotos existentes en ÃĄlbumes usando la configuraciÃŗn actual de sincronizaciÃŗn", "organize_your_library": "Organiza tu biblioteca", "original": "original", "other": "Otro", - "other_devices": "Otro dispositivo", + "other_devices": "Otros dispositivos", "other_entities": "Otras entidades", "other_variables": "Otras variables", "owned": "Propios", @@ -1502,6 +1530,7 @@ "port": "Puerto", "preferences_settings_subtitle": "Configuraciones de la aplicaciÃŗn", "preferences_settings_title": "Preferencias", + "preparing": "Preparando", "preset": "Preestablecido", "preview": "Posterior", "previous": "Anterior", @@ -1518,7 +1547,7 @@ "profile_drawer_client_out_of_date_minor": "La app estÃĄ desactualizada. Por favor actualiza a la Ãēltima versiÃŗn menor.", "profile_drawer_client_server_up_to_date": "Cliente y Servidor estÃĄn actualizados", "profile_drawer_github": "GitHub", - "profile_drawer_readonly_mode": "Modo Solo lectura habilitado. Toque dos veces el ícono del avatar del usuario para salir.", + "profile_drawer_readonly_mode": "Modo Solo lectura habilitado. MantÊn pulsado el icono del avatar del usuario para salir.", "profile_drawer_server_out_of_date_major": "El servidor estÃĄ desactualizado. Por favor actualiza a la Ãēltima versiÃŗn principal.", "profile_drawer_server_out_of_date_minor": "El servidor estÃĄ desactualizado. Por favor actualiza a la Ãēltima versiÃŗn menor.", "profile_image_of_user": "Foto de perfil de {user}", @@ -1557,6 +1586,7 @@ "purchase_server_description_2": "Estado del soporte", "purchase_server_title": "Servidor", "purchase_settings_server_activated": "La clave del producto del servidor la administra el administrador", + "query_asset_id": "Consultar ID de elemento", "queue_status": "Poniendo en cola {count}/{total}", "rating": "ValoraciÃŗn", "rating_clear": "Borrar calificaciÃŗn", @@ -1566,6 +1596,7 @@ "read_changelog": "Leer registro de cambios", "readonly_mode_disabled": "Modo Solo lectura deshabilitado", "readonly_mode_enabled": "Modo Solo lectura habilitado", + "ready_for_upload": "Listo para subir", "reassign": "Reasignar", "reassigned_assets_to_existing_person": "Reasignado {count, plural, one {# elemento} other {# elementos}} a {name, select, null {una persona existente} other {{name}}}", "reassigned_assets_to_new_person": "Reasignado {count, plural, one {# elemento} other {# elementos}} a un nuevo usuario", @@ -1590,6 +1621,7 @@ "regenerating_thumbnails": "Recargando miniaturas", "remote": "Remoto", "remote_assets": "Elementos remotos", + "remote_media_summary": "Resumen de Medios Remotos", "remove": "Eliminar", "remove_assets_album_confirmation": "ÂŋEstÃĄs seguro que quieres eliminar {count, plural, one {# elemento} other {# elementos}} del ÃĄlbum?", "remove_assets_shared_link_confirmation": "ÂŋEstÃĄs seguro que quieres eliminar {count, plural, one {# elemento} other {# elementos}} del enlace compartido?", @@ -1623,7 +1655,7 @@ "require_password": "ContraseÃąa requerida", "require_user_to_change_password_on_first_login": "Requerir que el usuario cambie la contraseÃąa en el primer inicio de sesiÃŗn", "rescan": "Volver a escanear", - "reset": "Reiniciar", + "reset": "Restablecer", "reset_password": "Restablecer la contraseÃąa", "reset_people_visibility": "Restablecer la visibilidad de las personas", "reset_pin_code": "Restablecer PIN", @@ -1642,6 +1674,7 @@ "restore_user": "Restaurar usuario", "restored_asset": "Archivo restaurado", "resume": "Continuar", + "resume_paused_jobs": "Reanudar {count, plural, one {# tarea en pausa} other {# tareas en pausa}}", "retry_upload": "Reintentar subida", "review_duplicates": "Revisar duplicados", "review_large_files": "Revisar archivos grandes", @@ -1735,7 +1768,7 @@ "select_user_for_sharing_page_err_album": "Fallo al crear el ÃĄlbum", "selected": "Seleccionado", "selected_count": "{count, plural, one {# seleccionado} other {# seleccionados}}", - "selected_gps_coordinates": "coordenadas gps seleccionadas", + "selected_gps_coordinates": "Coordenadas GPS seleccionadas", "send_message": "Enviar mensaje", "send_welcome_email": "Enviar correo de bienvenida", "server_endpoint": "Punto final del servidor", @@ -1846,10 +1879,8 @@ "shift_to_permanent_delete": "presiona ⇧ para eliminar permanentemente el archivo", "show_album_options": "Mostrar opciones del ÃĄlbum", "show_albums": "Mostrar ÃĄlbumes", - "show_all_assets": "Mostrar todos los assets", "show_all_people": "Mostrar todas las personas", "show_and_hide_people": "Mostrar y ocultar personas", - "show_assets_without_location": "Mostrar assets sin ubicaciÃŗn", "show_file_location": "Mostrar carpeta del archivo", "show_gallery": "Ver galería", "show_hidden_people": "Mostrar personas ocultas", @@ -1866,6 +1897,7 @@ "show_slideshow_transition": "Mostrar la transiciÃŗn de las diapositivas", "show_supporter_badge": "Insignia de colaborador", "show_supporter_badge_description": "Mostrar una insignia de colaborador", + "show_text_search_menu": "Mostrar el menÃē de bÃēsqueda", "shuffle": "Modo aleatorio", "sidebar": "Barra lateral", "sidebar_display_description": "Muestra un enlace a la vista en la barra lateral", @@ -1875,7 +1907,7 @@ "skip_to_content": "Saltar al contenido", "skip_to_folders": "Ir a las carpetas", "skip_to_tags": "Ir a las etiquetas", - "slideshow": "Diapositivas", + "slideshow": "Pase de diapositivas", "slideshow_settings": "Ajustes de diapositivas", "sort_albums_by": "Ordenar ÃĄlbumes porâ€Ļ", "sort_created": "Fecha de creaciÃŗn", @@ -1896,6 +1928,7 @@ "stacktrace": "Seguimiento de pila", "start": "Inicio", "start_date": "Fecha de inicio", + "start_date_before_end_date": "Fecha de inicio debe ser antes de fecha final", "state": "Estado", "status": "Estado", "stop_casting": "Detener transmisiÃŗn", @@ -1920,6 +1953,8 @@ "sync_albums_manual_subtitle": "Sincroniza todos los videos y fotos subidos con los ÃĄlbumes seleccionados a respaldar", "sync_local": "SincronizaciÃŗn Local", "sync_remote": "SincronizaciÃŗn Remota", + "sync_status": "Estado de la sincronizaciÃŗn", + "sync_status_subtitle": "Ver y gestionar el estado de la sincronizaciÃŗn", "sync_upload_album_setting_subtitle": "Crea y sube tus fotos y videos a los ÃĄlbumes seleccionados en Immich", "tag": "Etiqueta", "tag_assets": "Etiquetar activos", @@ -1979,6 +2014,7 @@ "trash_page_select_assets_btn": "Seleccionar elementos", "trash_page_title": "Papelera ({count})", "trashed_items_will_be_permanently_deleted_after": "Los elementos en la papelera serÃĄn eliminados permanentemente tras {days, plural, one {# día} other {# días}}.", + "troubleshoot": "Solucionar problemas", "type": "Tipo", "unable_to_change_pin_code": "No se ha podido cambiar el PIN", "unable_to_setup_pin_code": "No se ha podido establecer el PIN", @@ -2034,7 +2070,6 @@ "use_biometric": "Uso biomÊtrico", "use_current_connection": "Usar conexiÃŗn actual", "use_custom_date_range": "Usa un intervalo de fechas personalizado", - "use_this_location": "Click para usar ubicaciÃŗn", "user": "Usuario", "user_has_been_deleted": "Este usuario ha sido eliminado.", "user_id": "Id. de usuario", @@ -2077,6 +2112,7 @@ "view_next_asset": "Mostrar siguiente elemento", "view_previous_asset": "Mostrar elemento anterior", "view_qr_code": "Ver cÃŗdigo QR", + "view_similar_photos": "Ver fotografías similares", "view_stack": "Ver Pila", "view_user": "Ver Usuario", "viewer_remove_from_stack": "Quitar de la pila", @@ -2095,5 +2131,6 @@ "yes": "Sí", "you_dont_have_any_shared_links": "No tienes ningÃēn enlace compartido", "your_wifi_name": "El nombre de tu Wi-Fi", - "zoom_image": "Acercar Imagen" + "zoom_image": "Acercar Imagen", + "zoom_to_bounds": "Ajustar a los límites" } diff --git a/i18n/et.json b/i18n/et.json index 2b4e94c3cd..bfd083ad4e 100644 --- a/i18n/et.json +++ b/i18n/et.json @@ -28,10 +28,12 @@ "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_album_bottom_sheet_some_local_assets": "KÃĩiki lokaalseid Ãŧksuseid ei Ãĩnnestunud albumisse lisada", "add_to_album_toggle": "Muuda albumi {album} valikut", "add_to_albums": "Lisa albumitesse", "add_to_albums_count": "Lisa albumitesse ({count})", "add_to_shared_album": "Lisa jagatud albumisse", + "add_upload_to_stack": "Virnasta Ãŧleslaaditud Ãŧksus", "add_url": "Lisa URL", "added_to_archive": "Lisatud arhiivi", "added_to_favorites": "Lisatud lemmikutesse", @@ -123,6 +125,13 @@ "logging_enable_description": "Luba logimine", "logging_level_description": "Kui lubatud, millist logimistaset kasutada.", "logging_settings": "Logimine", + "machine_learning_availability_checks": "Saadavuskontrollid", + "machine_learning_availability_checks_description": "Tuvasta ja eelista automaatselt saadavalolevaid masinÃĩppeservereid", + "machine_learning_availability_checks_enabled": "Luba saadavuskontrollid", + "machine_learning_availability_checks_interval": "Kontrolli intervall", + "machine_learning_availability_checks_interval_description": "Saadavuskontrollide intervall millisekundites", + "machine_learning_availability_checks_timeout": "Päringu ajalÃĩpp", + "machine_learning_availability_checks_timeout_description": "Saadavuskontrollide ajalÃĩpp millisekundites", "machine_learning_clip_model": "CLIP mudel", "machine_learning_clip_model_description": "CLIP mudeli nimi, mis on loetletud siin. Pane tähele, et mudeli muutmisel pead kÃĩigi piltide peal nutiotsingu tÃļÃļte uuesti käivitama.", "machine_learning_duplicate_detection": "Duplikaatide leidmine", @@ -387,8 +396,6 @@ "admin_password": "Administraatori parool", "administration": "Administratsioon", "advanced": "Täpsemad valikud", - "advanced_settings_beta_timeline_subtitle": "Koge uut rakendust", - "advanced_settings_beta_timeline_title": "Beeta ajajoon", "advanced_settings_enable_alternate_media_filter_subtitle": "Kasuta seda valikut, et filtreerida sÃŧnkroonimise ajal Ãŧksuseid alternatiivsete kriteeriumite alusel. Proovi seda ainult siis, kui rakendusel on probleeme kÃĩigi albumite tuvastamisega.", "advanced_settings_enable_alternate_media_filter_title": "[EKSPERIMENTAALNE] Kasuta alternatiivset seadme albumi sÃŧnkroonimise filtrit", "advanced_settings_log_level_title": "Logimistase: {level}", @@ -425,6 +432,7 @@ "album_remove_user_confirmation": "Kas oled kindel, et soovid kasutaja {user} eemaldada?", "album_search_not_found": "Otsingule vastavaid albumeid ei leitud", "album_share_no_users": "Paistab, et oled seda albumit kÃĩikide kasutajatega jaganud, vÃĩi pole Ãŧhtegi kasutajat, kellega jagada.", + "album_summary": "Albumi kokkuvÃĩte", "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}", @@ -496,6 +504,8 @@ "asset_restored_successfully": "Üksus edukalt taastatud", "asset_skipped": "Vahele jäetud", "asset_skipped_in_trash": "PrÃŧgikastis", + "asset_trashed": "Üksus liigutatud prÃŧgikasti", + "asset_troubleshoot": "Üksuse tÃĩrkeotsing", "asset_uploaded": "Üleslaaditud", "asset_uploading": "Üleslaadimineâ€Ļ", "asset_viewer_settings_subtitle": "Halda galeriivaaturi seadeid", @@ -529,8 +539,10 @@ "autoplay_slideshow": "Esita slaidiesitlus automaatselt", "back": "Tagasi", "back_close_deselect": "Tagasi, sulge vÃĩi tÃŧhista valik", + "background_backup_running_error": "Taustvarundus on käimas, ei saa käsitsi varundust alustada", "background_location_permission": "Taustal asukoha luba", "background_location_permission_content": "Et taustal tÃļÃļtades vÃĩrguÃŧhendust vahetada, peab Immich'il *alati* olema täpse asukoha luba, et rakendus saaks WiFi-vÃĩrgu nime lugeda", + "background_options": "Taustavalikud", "backup": "Varundamine", "backup_album_selection_page_albums_device": "Albumid seadmel ({count})", "backup_album_selection_page_albums_tap": "Puuduta kaasamiseks, topeltpuuduta välistamiseks", @@ -538,6 +550,7 @@ "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_albums_sync": "Varundusalbumite sÃŧnkroniseerimine", "backup_all": "KÃĩik", "backup_background_service_backup_failed_message": "Üksuste varundamine ebaÃĩnnestus. Uuesti proovimineâ€Ļ", "backup_background_service_connection_failed_message": "Serveriga Ãŧhendumine ebaÃĩnnestus. Uuesti proovimineâ€Ļ", @@ -587,6 +600,7 @@ "backup_controller_page_turn_on": "LÃŧlita esiplaanil varundus sisse", "backup_controller_page_uploading_file_info": "Faili info Ãŧleslaadimine", "backup_err_only_album": "Ei saa ainsat albumit eemaldada", + "backup_error_sync_failed": "SÃŧnkroonimine ebaÃĩnnestus. Varundust ei saa tÃļÃļdelda.", "backup_info_card_assets": "Ãŧksused", "backup_manual_cancelled": "TÃŧhistatud", "backup_manual_in_progress": "Üleslaadimine juba käib. Proovi hiljem uuesti", @@ -597,8 +611,6 @@ "backup_setting_subtitle": "Halda taustal ja esiplaanil Ãŧleslaadimise seadeid", "backup_settings_subtitle": "Halda Ãŧleslaadimise seadeid", "backward": "Tagasi", - "beta_sync": "Beeta sÃŧnkroonimise staatus", - "beta_sync_subtitle": "Halda uut sÃŧnkroonimissÃŧsteemi", "biometric_auth_enabled": "Biomeetriline autentimine lubatud", "biometric_locked_out": "Biomeetriline autentimine on blokeeritud", "biometric_no_options": "Biomeetrilisi valikuid ei ole", @@ -656,6 +668,8 @@ "change_pin_code": "Muuda PIN-koodi", "change_your_password": "Muuda oma parooli", "changed_visibility_successfully": "Nähtavus muudetud", + "charging": "Laadimine", + "charging_requirement_mobile_backup": "Taustal varundus vajab, et seade oleks laadimas", "check_corrupt_asset_backup": "Otsi riknenud Ãŧksuste varukoopiaid", "check_corrupt_asset_backup_button": "Teosta kontroll", "check_corrupt_asset_backup_description": "Käivita see kontroll ainult WiFi-vÃĩrgus ja siis, kui kÃĩik Ãŧksused on varundatud. See protseduur vÃĩib kesta mÃĩne minuti.", @@ -742,6 +756,7 @@ "create_user": "Lisa kasutaja", "created": "Lisatud", "created_at": "Lisatud", + "creating_linked_albums": "Lingitud albumite loomine...", "crop": "Kärpimine", "curated_object_page_title": "Asjad", "current_device": "Praegune seade", @@ -834,11 +849,11 @@ "download_settings_description": "Halda Ãŧksuste allalaadimise seadeid", "download_started": "Allalaadimine alustatud", "download_sucess": "Allalaadimine Ãĩnnestus", - "download_sucess_android": "Meediumid laaditi alla kataloogi DCIM/Immich", + "download_sucess_android": "Üksused laaditi alla kataloogi DCIM/Immich", "download_waiting_to_retry": "Uuesti proovimise ootel", "downloading": "Allalaadimine", "downloading_asset_filename": "Üksuse {filename} allalaadimine", - "downloading_media": "Meediumi allalaadimine", + "downloading_media": "Üksuste allalaadimine", "drop_files_to_upload": "Failide Ãŧleslaadimiseks sikuta need ÃŧkskÃĩik kuhu", "duplicates": "Duplikaadid", "duplicates_description": "Lahenda iga grupp, valides duplikaadid, kui neid on", @@ -891,7 +906,9 @@ "error": "Viga", "error_change_sort_album": "Albumi sorteerimisjärjestuse muutmine ebaÃĩnnestus", "error_delete_face": "Viga näo kustutamisel", + "error_getting_places": "Viga kohtade pärimisel", "error_loading_image": "Viga pildi laadimisel", + "error_loading_partners": "Viga partnerite laadimisel: {error}", "error_saving_image": "Viga: {error}", "error_tag_face_bounding_box": "Viga näo sildistamisel - Ãŧmbritseva kasti koordinaate ei Ãĩnnestunud leida", "error_title": "Viga - midagi läks valesti", @@ -1022,6 +1039,7 @@ "exif_bottom_sheet_description_error": "Viga kirjelduse muutmisel", "exif_bottom_sheet_details": "ÜKSIKASJAD", "exif_bottom_sheet_location": "ASUKOHT", + "exif_bottom_sheet_no_description": "Kirjeldus puudub", "exif_bottom_sheet_people": "ISIKUD", "exif_bottom_sheet_person_add_person": "Lisa nimi", "exit_slideshow": "Sulge slaidiesitlus", @@ -1056,6 +1074,7 @@ "favorites_page_no_favorites": "Lemmikuid Ãŧksuseid ei leitud", "feature_photo_updated": "EsiletÃĩstetud foto muudetud", "features": "Funktsioonid", + "features_in_development": "Arendusjärgus olevad funktsioonid", "features_setting_description": "Halda rakenduse funktsioone", "file_name": "Failinimi", "file_name_or_extension": "Failinimi vÃĩi -laiend", @@ -1076,10 +1095,7 @@ "gcast_enabled": "Google Cast", "gcast_enabled_description": "See funktsionaalsus laadib tÃļÃļtamiseks Google'st väliseid ressursse.", "general": "Üldine", - "geolocation_instruction_all_have_location": "KÃĩigil selle kuupäevaga Ãŧksustel on juba asukoht. Proovi kuvada kÃĩiki Ãŧksuseid vÃĩi vali teine kuupäev", "geolocation_instruction_location": "KlÃĩpsa GPS-koordinaatidega Ãŧksusel, et kasutada selle asukohta, vÃĩi vali asukoht otse kaardilt", - "geolocation_instruction_no_date": "Vali kuupäev, et kÃĩigi selle kuupäevaga fotode ja videote asukohti hallata", - "geolocation_instruction_no_photos": "Selle kuupäevaga fotosid ja videosid ei leitud. Vali mÃĩni muu kuupäev", "get_help": "KÃŧsi abi", "get_wifiname_error": "WiFi-vÃĩrgu nime ei Ãĩnnestunud lugeda. Veendu, et oled andnud vajalikud load ja oled WiFi-vÃĩrguga Ãŧhendatud", "getting_started": "Alustamine", @@ -1223,6 +1239,7 @@ "local": "Lokaalsed", "local_asset_cast_failed": "Ei saa edastada Ãŧksust, mis pole serverisse Ãŧles laaditud", "local_assets": "Lokaalsed Ãŧksused", + "local_media_summary": "Lokaalsete Ãŧksuste kokkuvÃĩte", "local_network": "Kohalik vÃĩrk", "local_network_sheet_info": "Rakendus Ãŧhendub valitud Wi-Fi vÃĩrgus olles serveriga selle URL-i kaudu", "location_permission": "Asukoha luba", @@ -1234,6 +1251,7 @@ "location_picker_longitude_hint": "Sisesta pikkuskraad siia", "lock": "Lukusta", "locked_folder": "Lukustatud kaust", + "log_detail_title": "Logi detailid", "log_out": "Logi välja", "log_out_all_devices": "Logi kÃĩigist seadmetest välja", "logged_in_as": "Logitud sisse kasutajana {user}", @@ -1264,6 +1282,7 @@ "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?", + "logs": "Logid", "longitude": "Pikkuskraad", "look": "Välimus", "loop_videos": "Taasesita videod", @@ -1306,7 +1325,8 @@ "mark_as_read": "Märgi loetuks", "marked_all_as_read": "KÃĩik märgiti loetuks", "matches": "Ühtivad failid", - "media_type": "Meediumi tÃŧÃŧp", + "matching_assets": "Ühtivad Ãŧksused", + "media_type": "Üksuse tÃŧÃŧp", "memories": "Mälestused", "memories_all_caught_up": "Ongi kÃĩik", "memories_check_back_tomorrow": "Vaata homme juba uusi mälestusi", @@ -1346,6 +1366,7 @@ "name_or_nickname": "Nimi vÃĩi hÃŧÃŧdnimi", "network_requirement_photos_upload": "Kasuta fotode varundamiseks mobiilset andmesidet", "network_requirement_videos_upload": "Kasuta videote varundamiseks mobiilset andmesidet", + "network_requirements": "VÃĩrgu nÃĩuded", "network_requirements_updated": "VÃĩrgu nÃĩuded muutusid, varundamise järjekord lähtestatakse", "networking_settings": "VÃĩrguÃŧhendus", "networking_subtitle": "Halda serveri lÃĩpp-punkti seadeid", @@ -1356,6 +1377,7 @@ "new_person": "Uus isik", "new_pin_code": "Uus PIN-kood", "new_pin_code_subtitle": "See on sul esimene kord lukustatud kausta kasutada. Turvaliseks ligipääsuks loo PIN-kood", + "new_timeline": "Uus ajajoon", "new_user_created": "Uus kasutaja lisatud", "new_version_available": "UUS VERSIOON SAADAVAL", "newest_first": "Uuemad eespool", @@ -1369,20 +1391,25 @@ "no_assets_message": "KLIKI ESIMESE FOTO ÜLESLAADIMISEKS", "no_assets_to_show": "Pole Ãŧksuseid, mida kuvada", "no_cast_devices_found": "Edastamise seadmeid ei leitud", + "no_checksum_local": "Kontrollsumma pole saadaval - lokaalse Ãŧksuse pärimine ebaÃĩnnestus", + "no_checksum_remote": "Kontrollsumma pole saadaval - kaugÃŧksuse pärimine ebaÃĩnnestus", "no_duplicates_found": "Ühtegi duplikaati ei leitud.", "no_exif_info_available": "Exif info pole saadaval", "no_explore_results_message": "Oma kogu avastamiseks laadi Ãŧles rohkem fotosid.", "no_favorites_message": "Lisa lemmikud, et oma parimaid fotosid ja videosid kiiresti leida", "no_libraries_message": "Lisa väline kogu oma fotode ja videote vaatamiseks", + "no_local_assets_found": "Selle kontrollsummaga lokaalseid Ãŧksuseid ei leitud", "no_locked_photos_message": "Lukustatud kaustas olevad fotod ja videod on peidetud ning need pole kogu sirvimisel ja otsimisel nähtavad.", "no_name": "Nimetu", "no_notifications": "Teavitusi pole", "no_people_found": "Kattuvaid isikuid ei leitud", "no_places": "Kohti ei ole", + "no_remote_assets_found": "Selle kontrollsummaga kaugÃŧksuseid ei leitud", "no_results": "Vasteid pole", "no_results_description": "Proovi sÃŧnonÃŧÃŧmi vÃĩi Ãŧldisemat märksÃĩna", "no_shared_albums_message": "Lisa album, et fotosid ja videosid teistega jagada", "no_uploads_in_progress": "Üleslaadimisi käimas ei ole", + "not_available": "Pole saadaval", "not_in_any_album": "Pole Ãŧheski albumis", "not_selected": "Ei ole valitud", "note_apply_storage_label_to_previously_uploaded assets": "Märkus: Et rakendada talletussilt varem Ãŧleslaaditud Ãŧksustele, käivita", @@ -1504,6 +1531,7 @@ "port": "Port", "preferences_settings_subtitle": "Halda rakenduse eelistusi", "preferences_settings_title": "Eelistused", + "preparing": "Ettevalmistamine", "preset": "Eelseadistus", "preview": "Eelvaade", "previous": "Eelmine", @@ -1520,7 +1548,7 @@ "profile_drawer_client_out_of_date_minor": "Mobiilirakendus on aegunud. Palun uuenda uusimale väikesele versioonile.", "profile_drawer_client_server_up_to_date": "Klient ja server on uuendatud", "profile_drawer_github": "GitHub", - "profile_drawer_readonly_mode": "KirjutuskaitsereÅžiim sisse lÃŧlitatud. Väljumiseks topeltpuuduta avatari ikooni.", + "profile_drawer_readonly_mode": "KirjutuskaitsereÅžiim sisse lÃŧlitatud. Väljumiseks puuduta pikalt avatari ikooni.", "profile_drawer_server_out_of_date_major": "Server on aegunud. Palun uuenda uusimale suurele versioonile.", "profile_drawer_server_out_of_date_minor": "Server on aegunud. Palun uuenda uusimale väikesele versioonile.", "profile_image_of_user": "Kasutaja {user} profiilipilt", @@ -1559,6 +1587,7 @@ "purchase_server_description_2": "Toetaja staatus", "purchase_server_title": "Server", "purchase_settings_server_activated": "Serveri tootevÃĩtit haldab administraator", + "query_asset_id": "Päringu Ãŧksuse ID", "queue_status": "Järjekorras {count}/{total}", "rating": "Hinnang", "rating_clear": "TÃŧhjenda hinnang", @@ -1568,6 +1597,7 @@ "read_changelog": "Vaata muudatuste Ãŧlevaadet", "readonly_mode_disabled": "KirjutuskaitsereÅžiim välja lÃŧlitatud", "readonly_mode_enabled": "KirjutuskaitsereÅžiim sisse lÃŧlitatud", + "ready_for_upload": "Valmis Ãŧleslaadimiseks", "reassign": "Määra uuesti", "reassigned_assets_to_existing_person": "{count, plural, one {# Ãŧksus} other {# Ãŧksust}} seostatud {name, select, null {olemasoleva isikuga} other {isikuga {name}}}", "reassigned_assets_to_new_person": "{count, plural, one {# Ãŧksus} other {# Ãŧksust}} seostatud uue isikuga", @@ -1592,6 +1622,7 @@ "regenerating_thumbnails": "Pisipiltide uuesti genereerimine", "remote": "Serveris", "remote_assets": "KaugÃŧksused", + "remote_media_summary": "KaugÃŧksuste kokkuvÃĩte", "remove": "Eemalda", "remove_assets_album_confirmation": "Kas oled kindel, et soovid {count, plural, one {# Ãŧksuse} other {# Ãŧksust}} albumist eemaldada?", "remove_assets_shared_link_confirmation": "Kas oled kindel, et soovid eemaldada {count, plural, one {# Ãŧksuse} other {# Ãŧksust}} sellelt jagatud lingilt?", @@ -1644,6 +1675,7 @@ "restore_user": "Taasta kasutaja", "restored_asset": "Üksus taastatud", "resume": "Jätka", + "resume_paused_jobs": "Jätka {count, plural, one {# peatatud tÃļÃļde} other {# peatatud tÃļÃļdet}}", "retry_upload": "Proovi Ãŧleslaadimist uuesti", "review_duplicates": "Vaata duplikaadid läbi", "review_large_files": "Vaata suured failid läbi", @@ -1683,8 +1715,8 @@ "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_media_type": "Üksuse tÃŧÃŧp", + "search_filter_media_type_title": "Vali Ãŧksuse tÃŧÃŧp", "search_filter_people_title": "Vali isikud", "search_for": "Otsi", "search_for_existing_person": "Otsi olemasolevat isikut", @@ -1848,10 +1880,8 @@ "shift_to_permanent_delete": "vajuta ⇧, et Ãŧksus jäädavalt kustutada", "show_album_options": "Näita albumi valikuid", "show_albums": "Näita albumeid", - "show_all_assets": "Kuva kÃĩik Ãŧksused", "show_all_people": "Näita kÃĩiki isikuid", "show_and_hide_people": "Näita ja peida isikuid", - "show_assets_without_location": "Kuva ilma asukohata Ãŧksused", "show_file_location": "Näita faili asukohta", "show_gallery": "Näita galeriid", "show_hidden_people": "Kuva peidetud inimesed", @@ -1868,6 +1898,7 @@ "show_slideshow_transition": "Kuva slaidiesitluse Ãŧleminekud", "show_supporter_badge": "Toetaja märk", "show_supporter_badge_description": "Kuva toetaja märki", + "show_text_search_menu": "Kuva tekstiotsingu menÃŧÃŧd", "shuffle": "Juhuslik", "sidebar": "KÃŧlgmenÃŧÃŧ", "sidebar_display_description": "Kuva kÃŧlgmenÃŧÃŧs linki vaatele", @@ -1898,6 +1929,7 @@ "stacktrace": "Pinujälg", "start": "Alusta", "start_date": "Alguskuupäev", + "start_date_before_end_date": "Alguskuupäev peab olema varasem kui lÃĩppkuupäev", "state": "Osariik", "status": "Staatus", "stop_casting": "LÃĩpeta edastamine", @@ -1922,6 +1954,8 @@ "sync_albums_manual_subtitle": "SÃŧnkrooni kÃĩik Ãŧleslaaditud videod ja fotod valitud varundusalbumitesse", "sync_local": "SÃŧnkrooni lokaalsed Ãŧksused", "sync_remote": "SÃŧnkrooni kaugÃŧksused", + "sync_status": "SÃŧnkroonimise staatus", + "sync_status_subtitle": "Vaata ja halda sÃŧnkroonimissÃŧsteemi", "sync_upload_album_setting_subtitle": "Loo ja laadi oma pildid ja videod Ãŧles Immich'isse valitud albumitesse", "tag": "Silt", "tag_assets": "Sildista Ãŧksuseid", @@ -1959,7 +1993,9 @@ "to_change_password": "Muuda parool", "to_favorite": "Lemmik", "to_login": "Logi sisse", + "to_multi_select": "vali mitu", "to_parent": "Tase Ãŧles", + "to_select": "vali", "to_trash": "PrÃŧgikasti", "toggle_settings": "Kuva/peida seaded", "total": "Kokku", @@ -1979,6 +2015,7 @@ "trash_page_select_assets_btn": "Vali Ãŧksused", "trash_page_title": "PrÃŧgikast ({count})", "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.", + "troubleshoot": "TÃĩrkeotsing", "type": "TÃŧÃŧp", "unable_to_change_pin_code": "PIN-koodi muutmine ebaÃĩnnestus", "unable_to_setup_pin_code": "PIN-koodi seadistamine ebaÃĩnnestus", @@ -2028,13 +2065,12 @@ "upload_success": "Üleslaadimine Ãĩnnestus, uute Ãŧksuste nägemiseks värskenda lehte.", "upload_to_immich": "Laadi Immich'isse ({count})", "uploading": "Üleslaadimine", - "uploading_media": "Meediumi Ãŧleslaadimine", + "uploading_media": "Üksuste Ãŧleslaadimine", "url": "URL", "usage": "Kasutus", "use_biometric": "Kasuta biomeetriat", "use_current_connection": "kasuta praegust Ãŧhendust", "use_custom_date_range": "Kasuta kohandatud kuupäevavahemikku", - "use_this_location": "KlÃĩpsa asukoha kasutamiseks", "user": "Kasutaja", "user_has_been_deleted": "See kasutaja on kustutatud.", "user_id": "Kasutaja ID", @@ -2096,5 +2132,6 @@ "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" + "zoom_image": "Suumi pilti", + "zoom_to_bounds": "Suumi piiridesse" } diff --git a/i18n/eu.json b/i18n/eu.json index 311619ad90..bb16f126d6 100644 --- a/i18n/eu.json +++ b/i18n/eu.json @@ -38,6 +38,68 @@ "admin": { "add_exclusion_pattern_description": "Gehitu baztertze patroiak. *, ** eta ? karakterak erabil ditzazkezu (globbing). Adibideak: \"Raw\" izeneko edozein direktorioko fitxategi guztiak baztertzeko, erabili \"**/Raw/**\". \".tif\" amaitzen diren fitxategi guztiak baztertzeko, erabili \"**/*.tif\". Bide absolutu bat baztertzeko, erabili \"/baztertu/beharreko/bidea/**\".", "admin_user": "Administradore erabiltzailea", - "image_quality": "Kalitatea" - } + "authentication_settings": "Segurtasun Ezarpenak", + "authentication_settings_description": "Kudeatu pasahitza, OAuth edo beste segurtasun konfigurazio bat", + "authentication_settings_disable_all": "Seguru zaude saioa hasteko modu guztiak desgaitu nahi dituzula? Saioa hastea guztiz desgaitua izango da.", + "authentication_settings_reenable": "Berriro gaitzeko, erabili Server Command.", + "background_task_job": "Atzealdeko Lanak", + "backup_onboarding_footer": "Immich-en babes kopiei buruzko informazio gehiago nahi baduzu, mesedez irakurri dokumentazioa.", + "backup_onboarding_title": "Babes Kopiak", + "confirm_delete_library": "Seguru zaude {library} ezabatu nahi duzula?", + "confirm_email_below": "Konfirmatzeko, idatzi \"{email}\" azpian", + "confirm_reprocess_all_faces": "Seguru zaude aurpegi guztiak berriro prozesatu nahi dituzula? Erabakiak jendearen izenak ere borratuko ditu.", + "confirm_user_password_reset": "Seguru zaude {user}-ren pasahitza berrezarri nahi duzula?", + "confirm_user_pin_code_reset": "Seguru zaude {user}-ren PIN kodea berrezarri nahi duzula?", + "create_job": "Gehitu zeregina", + "disable_login": "Desgaitu saio hastea", + "face_detection": "Aurpegi detekzioa", + "failed_job_command": "{command} komandoak hutsegin du {job} zereginerako", + "image_format": "Formatua", + "image_format_description": "WebP ereduak JPEG baino fitxategi txikiagoak sortzen ditu, baina motelagoa da kodifikatzen.", + "image_preview_title": "Aurreikusiaen Konfigurazioa", + "image_quality": "Kalitatea", + "image_settings": "Argazkien Konfigurazioa", + "image_thumbnail_title": "Argazki Txikien Konfigurazioa", + "job_created": "Zeregina sortuta", + "job_settings": "Zereginaren konfigurazioa", + "job_status": "Zereginaren Egoera", + "logging_enable_description": "Gaitu erregistroak", + "logging_level_description": "Erregistroak gaituta daudenean, nolako erregistro maila erabili.", + "logging_settings": "Erregistroak", + "machine_learning_duplicate_detection": "Bizkoizketa Detekzioa", + "machine_learning_duplicate_detection_enabled": "Gaitu bikoizketa detekezioa", + "machine_learning_facial_recognition": "Aurpegi-Ezagutza", + "machine_learning_facial_recognition_description": "Detektatu, ezagutu eta aurpegiak banatu argazkietan", + "machine_learning_facial_recognition_model": "Aurpegi-Ezagutza eredua", + "machine_learning_facial_recognition_setting": "Aurpegi-Ezagutza Gaitu", + "machine_learning_smart_search_enabled": "Gaitu bilaketa arina", + "manage_log_settings": "Kudeatu erregistroen konfigurazioa", + "map_dark_style": "Beltz estiloa", + "map_gps_settings": "Mapa eta GPS Konfigurazioa", + "map_light_style": "Zuri estiloa", + "map_settings": "Mapa", + "metadata_faces_import_setting": "Gaitu aurpegien inportazioa", + "metadata_settings": "Metadata Konfigurazioa", + "metadata_settings_description": "Kudeatu metadaten konfigurazioa", + "migration_job": "Migrazio" + }, + "advanced_settings_readonly_mode_title": "Irakurri-bakarrik Modua", + "apply_count": "Ezarri ({count, number})", + "assets_added_to_albums_count": "Gehituta {assetTotal, plural, one {# asset} other {# assets}} to {albumTotal, plural, one {# album} other {# albums}}", + "assets_cannot_be_added_to_albums": "{count, plural, one {Asset} other {Assets}} ezin izan da albumetara gehitu", + "assets_were_part_of_albums_count": "{count, plural, one {Asset was} other {Assets were}} dagoeneko albumean dago", + "first": "Lehenengo ÂĢLehenikÂģ", + "gps": "GPS", + "gps_missing": "Ez dago GPS", + "last": "Azkena", + "like": "Gustoko", + "manage_geolocation": "Kudeatu kokapena", + "organize_into_albums": "Albumetan antolatu", + "query_asset_id": "Aztertu aukeratutako ID-a", + "readonly_mode_disabled": "Irakurri-bakarrik modua desgaituta", + "readonly_mode_enabled": "Irakurri-bakarrik modua gaituta", + "selected_gps_coordinates": "GPS Koordenadak Aukeratuta", + "sort_newest": "Argazkirik berriena", + "to_select": "aukeratzeko", + "view_similar_photos": "Ikusi antzeko argazkiak" } diff --git a/i18n/fa.json b/i18n/fa.json index 3b0be9a9b1..76f8d956fc 100644 --- a/i18n/fa.json +++ b/i18n/fa.json @@ -13,6 +13,7 @@ "add_a_location": "Ø§ŲØ˛ŲˆØ¯Ų† یڊ Ų…ÚŠØ§Ų†", "add_a_name": "Ø§ŲØ˛ŲˆØ¯Ų† Ų†Ø§Ų…", "add_a_title": "Ø§ŲØ˛ŲˆØ¯Ų† ØšŲ†ŲˆØ§Ų†", + "add_birthday": "Ø§ŲØ˛ŲˆØ¯Ų† ØĒØ§ØąÛŒØŽ ØĒŲˆŲ„Ø¯", "add_exclusion_pattern": "Ø§ŲØ˛ŲˆØ¯Ų† Ø§Ų„Ú¯ŲˆÛŒ Ø§ØŗØĒØĢŲ†Ø§", "add_import_path": "Ø§ŲØ˛ŲˆØ¯Ų† Ų…ØŗÛŒØą ŲˆØąŲˆØ¯ÛŒ", "add_location": "Ø§ŲØ˛ŲˆØ¯Ų† Ų…ÚŠØ§Ų†", @@ -22,10 +23,13 @@ "add_photos": "Ø§ŲØ˛ŲˆØ¯Ų† ØšÚŠØŗ Ų‡Ø§", "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_some_local_assets": "Ø¨ØąØŽÛŒ Ø§Ø˛ Ų…Ø­ØĒŲˆØ§Ų‡Ø§ÛŒ Ų…Ø­Ų„ÛŒ ØąØ§ Ų†Ø´Ø¯ Ø¨Ų‡ ØĸŲ„Ø¨ŲˆŲ… اØļØ§ŲŲ‡ ÚŠØąØ¯", "add_to_shared_album": "Ø§ŲØ˛ŲˆØ¯Ų† Ø¨Ų‡ ØĸŲ„Ø¨ŲˆŲ… اشØĒØąØ§ÚŠÛŒ", "added_to_archive": "Ø¨Ų‡ ØĸØąØ´ÛŒŲˆ اØļØ§ŲŲ‡ شد", "added_to_favorites": "Ø¨Ų‡ ØšŲ„Ø§Ų‚Ų‡ Ų…Ų†Ø¯ÛŒ Ų‡Ø§ اØļØ§ŲŲ‡ شد", - "added_to_favorites_count": "{count} ØĒا اØļØ§ŲŲ‡ شد Ø¨Ų‡ ØšŲ„Ø§Ų‚Ų‡ Ų…Ų†Ø¯ÛŒ Ų‡Ø§", + "added_to_favorites_count": "{count, number} ØĒا Ø¨Ų‡ ØšŲ„Ø§Ų‚Ų‡ Ų…Ų†Ø¯ÛŒ Ų‡Ø§ اØļØ§ŲŲ‡ شد", "admin": { "add_exclusion_pattern_description": "Ø§Ų„Ú¯ŲˆŲ‡Ø§ÛŒ Ø§ØŗØĒØĢŲ†Ø§ ØąØ§ اØļØ§ŲŲ‡ ÚŠŲ†ÛŒØ¯. ŲžØ´ØĒÛŒØ¨Ø§Ų†ÛŒ Ø§Ø˛ Ú¯Ų„Ø§Ø¨ÛŒŲ†Ú¯ با Ø§ØŗØĒŲØ§Ø¯Ų‡ Ø§Ø˛ *, ** ؈ ? ؈ØŦŲˆØ¯ Ø¯Ø§ØąØ¯. Ø¨ØąØ§ÛŒ Ų†Ø§Ø¯ÛŒØ¯Ų‡ Ú¯ØąŲØĒŲ† ØĒŲ…Ø§Ų… ŲØ§ÛŒŲ„â€ŒŲ‡Ø§ Ø¯Øą Ų‡Øą Ø¯Ø§ÛŒØąÚŠØĒŲˆØąÛŒ با Ų†Ø§Ų… \"Raw\"، Ø§Ø˛ \"**/Raw/**\" Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ÛŒØ¯. Ø¨ØąØ§ÛŒ Ų†Ø§Ø¯ÛŒØ¯Ų‡ Ú¯ØąŲØĒŲ† ØĒŲ…Ø§Ų… ŲØ§ÛŒŲ„â€ŒŲ‡Ø§ÛŒÛŒ ÚŠŲ‡ با \".tif\" ŲžØ§ÛŒØ§Ų† Ų…ÛŒâ€ŒÛŒØ§Ø¨Ų†Ø¯ØŒ Ø§Ø˛ \"**/*.tif\" Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ÛŒØ¯. Ø¨ØąØ§ÛŒ Ų†Ø§Ø¯ÛŒØ¯Ų‡ Ú¯ØąŲØĒŲ† یڊ Ų…ØŗÛŒØą Ų…ØˇŲ„Ų‚ØŒ Ø§Ø˛ \"/path/to/ignore/**\" Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ÛŒØ¯.", "authentication_settings": "ØĒŲ†Ø¸ÛŒŲ…Ø§ØĒ Ø§Ø­ØąØ§Ø˛ Ų‡ŲˆÛŒØĒ", diff --git a/i18n/fi.json b/i18n/fi.json index 2ed504b87c..a940493d95 100644 --- a/i18n/fi.json +++ b/i18n/fi.json @@ -28,6 +28,7 @@ "add_to_album": "Lisää albumiin", "add_to_album_bottom_sheet_added": "Lisätty albumiin {album}", "add_to_album_bottom_sheet_already_exists": "Kohde on jo albumissa {album}", + "add_to_album_bottom_sheet_some_local_assets": "Joitakin osia paikallisesta sisällÃļstä ei pystytty lisämään albumiin", "add_to_album_toggle": "Vaihda albumin {album} valintaa", "add_to_albums": "Lisää albumeihin", "add_to_albums_count": "Lisää albumeihin ({count})", @@ -39,7 +40,7 @@ "admin": { "add_exclusion_pattern_description": "Lisää mallit, jonka mukaan jätetään tiedostoja pois. Jokerimerkit *, ** ja ? ovat tuettuna. Jättääksesi pois kaikki tiedostot mistä tahansa lÃļytyvästä kansiosta \"Raw\" käytä \"**/Raw/**\". Jättääksesi pois kaikki \". tif\" päätteiset tiedot, käytä \"**/*.tif\". Jättääksesi pois tarkan tiedostopolun, käytä \"/path/to/ignore/**\".", "admin_user": "Ylläpitäjä", - "asset_offline_description": "Ulkoista kirjaston resurssia ei enää lÃļydy levyltä, ja se on siirretty roskakoriin. Jos tiedosto siirrettiin kirjaston sisällä, tarkista aikajanaltasi uusi vastaava resurssi. Palautaaksesi tämän resurssin, varmista, että alla oleva tiedostopolku on Immichin käytettävissä ja skannaa kirjasto uudelleen.", + "asset_offline_description": "Ulkoista kirjaston resurssia ei enää lÃļydy levyltä, ja se on siirretty roskakoriin. Jos tiedosto siirrettiin kirjaston sisällä, tarkista aikajanaltasi uusi vastaava resurssi. Palauttaaksesi tämän resurssin, varmista, että alla oleva tiedostopolku on Immichin käytettävissä ja skannaa kirjasto uudelleen.", "authentication_settings": "Autentikointiasetukset", "authentication_settings_description": "Hallitse salasana-, OAuth- ja muut autentikoinnin asetukset", "authentication_settings_disable_all": "Haluatko varmasti poistaa kaikki kirjautumistavat käytÃļstä? Kirjautuminen on tämän jälkeen mahdotonta.", @@ -123,6 +124,13 @@ "logging_enable_description": "Ota lokikirjaus käyttÃļÃļn", "logging_level_description": "Kun käytÃļssä, mitä lokituksen tasoa käytetään.", "logging_settings": "Lokit", + "machine_learning_availability_checks": "Saatavuustarkastukset", + "machine_learning_availability_checks_description": "Automaattisesti havaitse ja suosi vapaita koneoppimisen palvelimia", + "machine_learning_availability_checks_enabled": "Laita päälle saatavuus tarkistukset", + "machine_learning_availability_checks_interval": "Tarkastusväli", + "machine_learning_availability_checks_interval_description": "Aikaväli millisekunneissa saavutettavuus tarkistuksille", + "machine_learning_availability_checks_timeout": "PyynnÃļn aikakatkaisu", + "machine_learning_availability_checks_timeout_description": "Aikakatkaisu aika millisekunneissa saatavuus tarkistuksille", "machine_learning_clip_model": "CLIP-malli", "machine_learning_clip_model_description": "Käytettävän CLIP-mallin nimi toimivien mallien listasta. Huomaa että sinun täytyy suorittaa \"Älykäs etsintä\"-tyÃļ uudelleen vaihdettuasi käytettävää mallia.", "machine_learning_duplicate_detection": "Kaksoiskappaleiden tunnistus", @@ -142,7 +150,7 @@ "machine_learning_max_recognition_distance": "Suurin kasvojen eroavaisuus", "machine_learning_max_recognition_distance_description": "Kahden kasvon suurin eroavaisuus, milloin ne vielä mielletään samaksi henkilÃļksi, välillä 0-2. Arvoa alentamalla voidaan ehkäistä kahden saman näkÃļisen henkilÃļn mieltäminen samaksi henkilÃļksi, kun taas korottamalla voidaan ehkäistä saman henkilÃļn mieltäminen kahdeksi erilliseksi henkilÃļksi. Huomaa että on helpompaa yhdistää kaksi, kuin erottaa, joten suosi mahdollisimman matalaa arvoa.", "machine_learning_min_detection_score": "Tunnistuksen vähimmäistulos", - "machine_learning_min_detection_score_description": "Pienin kasvojen tunnistamisessa saatu vahvuusarvo välillä 0-1. Matalammalla arvolla havaitaan enemmän kascoja, mutta voi lisätä virhearvioiden määrää.", + "machine_learning_min_detection_score_description": "Pienin kasvojen tunnistamisessa saatu vahvuusarvo välillä 0-1. Matalammalla arvolla havaitaan enemmän kasvoja, mutta voi lisätä virhearvioiden määrää.", "machine_learning_min_recognized_faces": "Tunnistettujen kasvojen vähimmäismäärä", "machine_learning_min_recognized_faces_description": "Luotavan käyttäjän kasvojen vähimmäismäärä. Arvoa nostamalla kasvojentunnistuksen tarkkuus paranee, mutta todennäkÃļisyys sille, että kasvoja ei osata yhdistää henkilÃļÃļn kasvaa.", "machine_learning_settings": "Koneoppimisen asetukset", @@ -176,7 +184,7 @@ "metadata_settings": "Metatietoasetukset", "metadata_settings_description": "Hallitse metatietoja", "migration_job": "Migraatio", - "migration_job_description": "Migroi aineiston pikkukuvat ja kasvot uusimpaan kansiorakenteeseen", + "migration_job_description": "Migratoi aineiston pikkukuvat ja kasvot uusimpaan kansiorakenteeseen", "nightly_tasks_cluster_faces_setting_description": "Aja kasvojen tunnistus uusiin tunnistettuihin kasvoihin", "nightly_tasks_cluster_new_faces_setting": "Kokoa uudet kasvot", "nightly_tasks_database_cleanup_setting": "Tietokannan puhdistuksen tehtävät", @@ -196,7 +204,7 @@ "note_apply_storage_label_previous_assets": "Huom: Asettaaksesi nimikkeen aiemmin ladatulle aineistolle, aja", "note_cannot_be_changed_later": "Huom: Tätä ei voi enää myÃļhemmin vaihtaa!", "notification_email_from_address": "Lähettäjän osoite", - "notification_email_from_address_description": "Lähettäjän sähkÃļpostiosoite. Esimerkiksi \"Immich-kuvapalvelin \". Varmista, että käytetystä osoiteesta on lupa lähettää sähkÃļposteja.", + "notification_email_from_address_description": "Lähettäjän sähkÃļpostiosoite. Esimerkiksi \"Immich-kuvapalvelin \". Varmista, että käytetystä osoitteesta on lupa lähettää sähkÃļposteja.", "notification_email_host_description": "SähkÃļpostipalvelin (esim. smtp.immich.app)", "notification_email_ignore_certificate_errors": "Älä huomioi varmennevirheitä", "notification_email_ignore_certificate_errors_description": "Älä huomioi TLS-varmenteiden validointivirheitä (ei suositeltu)", @@ -218,9 +226,9 @@ "oauth_button_text": "Painikkeen teksti", "oauth_client_secret_description": "Vaaditaan, jos OAuth-palveluntarjoaja ei tue PKCE:tä (Proof Key for Code Exchange)", "oauth_enable_description": "Kirjaudu käyttäen OAuthia", - "oauth_mobile_redirect_uri": "Mobiilin uudellenohjaus-URI", + "oauth_mobile_redirect_uri": "Mobiilin uudelleenohjaus-URI", "oauth_mobile_redirect_uri_override": "Ohita mobiilin uudelleenohjaus-URI", - "oauth_mobile_redirect_uri_override_description": "Ota käyttÃļÃļn kun OAuth tarjoaja ei salli mobiili URI:a, kuten ''{callback}''", + "oauth_mobile_redirect_uri_override_description": "Ota käyttÃļÃļn kun OAuth-tarjoaja ei salli mobiili-URI:a, kuten ''{callback}''", "oauth_role_claim": "Roolin vaatimus", "oauth_role_claim_description": "Salli pääkäyttäjän pääsyoikeus automaattisesti tämän vaatimuksen perusteella. Vaatimus voi sisältää, joko 'käyttäjän' tai 'pääkäyttäjän'.", "oauth_settings": "OAuth", @@ -271,7 +279,7 @@ "storage_template_migration_info": "Tallennusmalli muuntaa kaikki tiedostopäätteet pieniksi kirjaimiksi. Mallipohjan muutokset koskevat vain uusia resursseja. Jos haluat käyttää mallipohjaa takautuvasti aiemmin ladattuihin resursseihin, suorita {job}.", "storage_template_migration_job": "Tallennustilan mallin muutostyÃļ", "storage_template_more_details": "Saadaksesi lisätietoa tästä ominaisuudesta, katso Tallennustilan Mallit sekä mihin se vaikuttaa", - "storage_template_onboarding_description_v2": "Päälle kytkettynä, toiminto järjestestelee tiedostot automaattisesti käyttäjän määrittämän mallin mukaisesti. Lisätietoja dokumentaatiosta..", + "storage_template_onboarding_description_v2": "Päälle kytkettynä toiminto järjestelee tiedostot automaattisesti käyttäjän määrittämän mallin mukaisesti. Lisätietoja dokumentaatiosta..", "storage_template_path_length": "Arvioitu tiedostopolun pituusrajoitus: {length, number}/{limit, number}", "storage_template_settings": "Tallennustilan malli", "storage_template_settings_description": "Hallitse palvelimelle ladatun aineiston kansiorakennetta ja tiedostonimiä", @@ -294,17 +302,17 @@ "thumbnail_generation_job": "Luo pikkukuvat", "thumbnail_generation_job_description": "Generoi isot, pienet sekä sumeat pikkukuvat jokaisesta aineistosta, kuten myÃļs henkilÃļistä", "transcoding_acceleration_api": "Kiihdytysrajapinta", - "transcoding_acceleration_api_description": "Rajapinta, jolla keskustellaan laittesi kanssa nopeuttaaksemme koodausta. Tämä asetus on paras mahdollinen: Mikäli ongelmia ilmenee, palataan käyttämään ohjelmistopohjaista koodausta. VP9 voi toimia tai ei, riippuen laitteistosi kokoonpanosta.", + "transcoding_acceleration_api_description": "Rajapinta, jolla keskustellaan laitteesi kanssa nopeuttaaksemme koodausta. Tämä asetus on paras mahdollinen: Mikäli ongelmia ilmenee, palataan käyttämään ohjelmistopohjaista koodausta. VP9 voi toimia tai ei, riippuen laitteistosi kokoonpanosta.", "transcoding_acceleration_nvenc": "NVENC (vaatii NVIDIA:n grafiikkasuorittimen)", "transcoding_acceleration_qsv": "Quick Sync (Vaatii vähintään gen7 Intel prosessorin)", "transcoding_acceleration_rkmpp": "RKMPP (vain Rockchip SOCt)", "transcoding_acceleration_vaapi": "VAAPI", "transcoding_accepted_audio_codecs": "Sallitut äänikoodekit", - "transcoding_accepted_audio_codecs_description": "Valitse mitä äänikoodekkeja ei tarvitse muuntaa. Käytetään vain tiettyjen koodauskäytäntÃļjen kanssa.", - "transcoding_accepted_containers": "Hyväksytyt kontit", - "transcoding_accepted_containers_description": "Valitse, mitä formaatteja ei tarvitse kääntää MP4- muotoon. KäytÃļssä vain tietyille muunnos säännÃļille.", + "transcoding_accepted_audio_codecs_description": "Valitse, mitä äänikoodekkeja ei tarvitse muuntaa. Käytetään vain tiettyjen koodauskäytäntÃļjen kanssa.", + "transcoding_accepted_containers": "Sallitut säiliÃļmuodot", + "transcoding_accepted_containers_description": "Valitse, mitä säiliÃļmuotoja ei tarvitse muuntaa MP4-muotoon. Käytetään vain tiettyjen koodauskäytäntÃļjen kanssa.", "transcoding_accepted_video_codecs": "Sallitut videokoodekit", - "transcoding_accepted_video_codecs_description": "Valitse mitä videokoodekkeja ei tarvitse muuntaa. Käytetään vain tiettyjen koodauskäytäntÃļjen kanssa.", + "transcoding_accepted_video_codecs_description": "Valitse, mitä videokoodekkeja ei tarvitse muuntaa. Käytetään vain tiettyjen koodauskäytäntÃļjen kanssa.", "transcoding_advanced_options_description": "Asetukset, joita useimpien käyttäjien ei tulisi muuttaa", "transcoding_audio_codec": "Äänikoodekki", "transcoding_audio_codec_description": "Opus on paras laadultaan, mutta ei välttämättä ole yhteensopiva vanhempien laitteiden tai sovellusten kanssa.", @@ -331,7 +339,7 @@ "transcoding_policy": "TranskoodauskäytäntÃļ", "transcoding_policy_description": "Aseta milloin video transkoodataan", "transcoding_preferred_hardware_device": "Ensisijainen laite", - "transcoding_preferred_hardware_device_description": "On voimassa vain VAAPI ja QSV -määritteille. Asettaa laitteistokoodauksessa käytetyn DRI noodin.", + "transcoding_preferred_hardware_device_description": "On voimassa vain VAAPI- ja QSV-määritteille. Asettaa laitteistokoodauksessa käytetyn DRI-noodin.", "transcoding_preset_preset": "Esiasetus (-asetus)", "transcoding_preset_preset_description": "Pakkausnopeus. Hitaampi tuottaa pienempiä tiedostoja ja parantaa laatua, kun kohdistetaan tiettyyn bittinopeuteen. VP9 ei huomioi korkeampaa kuin 'faster'.", "transcoding_reference_frames": "Kehysviitteet", @@ -348,7 +356,7 @@ "transcoding_tone_mapping": "Sävykartoitus", "transcoding_tone_mapping_description": "Pyrkii säilÃļmään HDR-kuvien ulkonäÃļn, kun muunnetaan peruskuvaksi. Jokaisella algoritmilla on omat heikkoutensa värien, yksityiskohtien tai kirkkauksien kesken. Hable säilÃļÃļ yksityiskohdat, Mobius värit ja Reinhard kirkkaudet.", "transcoding_transcode_policy": "TranskoodauskäytäntÃļ", - "transcoding_transcode_policy_description": "KäytäntÃļ miten video tulisi transkoodata. HDR videot transkoodataan aina, paitsi jos transkoodaus on poistettu käytÃļstä.", + "transcoding_transcode_policy_description": "KäytäntÃļ, miten video tulisi transkoodata. HDR-videot transkoodataan aina, paitsi jos transkoodaus on poistettu käytÃļstä.", "transcoding_two_pass_encoding": "Two-pass enkoodaus", "transcoding_two_pass_encoding_setting_description": "Transkoodaa kahdessa vaiheessa tuottaaksesi paremmin koodattuja videoita. Kun maksimibittinopeus on käytÃļssä (vaaditaan H.264- ja HEVC-koodaukselle), tämä tila käyttää bittinopeusaluetta, joka perustuu maksimibittinopeuteen ja ohittaa CRF. VP9 osalta CRF:ää voidaan käyttää, jos maksimibittinopeus on poistettu käytÃļstä.", "transcoding_video_codec": "Videokoodekki", @@ -387,8 +395,6 @@ "admin_password": "Ylläpitäjän salasana", "administration": "Ylläpito", "advanced": "Edistyneet", - "advanced_settings_beta_timeline_subtitle": "Kokeile uutta sovelluskokemusta", - "advanced_settings_beta_timeline_title": "Beta-aikajana", "advanced_settings_enable_alternate_media_filter_subtitle": "Käytä tätä vaihtoehtoa suodattaaksesi mediaa synkronoinnin aikana vaihtoehtoisten kriteerien perusteella. Kokeile tätä vain, jos sovelluksessa on ongelmia kaikkien albumien tunnistamisessa.", "advanced_settings_enable_alternate_media_filter_title": "[KOKEELLINEN] Käytä vaihtoehtoisen laitteen albumin synkronointisuodatinta", "advanced_settings_log_level_title": "Kirjaustaso: {level}", @@ -396,6 +402,7 @@ "advanced_settings_prefer_remote_title": "Suosi etäkuvia", "advanced_settings_proxy_headers_subtitle": "Määritä välityspalvelimen otsikot(proxy headers), jotka Immichin tulisi lähettää jokaisen verkkopyynnÃļn mukana", "advanced_settings_proxy_headers_title": "Välityspalvelimen otsikot", + "advanced_settings_readonly_mode_subtitle": "Aktivoi vain luku -tilan, jolloin valokuvia voi ainoastaan selata. Toiminnot kuten useiden kuvien valitseminen, jakaminen, siirtäminen toistolaitteelle ja poistaminen ovat pois käytÃļstä. Laita vain luku -tila päälle tai pois päältä päävalikon käyttäjäkuvakkeesta", "advanced_settings_readonly_mode_title": "Vain luku -tila", "advanced_settings_self_signed_ssl_subtitle": "Ohita SSL sertifikaattivarmennus palvelimen päätepisteellä. Vaaditaan self-signed -sertifikaateissa.", "advanced_settings_self_signed_ssl_title": "Salli self-signed SSL -sertifikaatit", @@ -424,11 +431,12 @@ "album_remove_user_confirmation": "Oletko varma että haluat poistaa {user}?", "album_search_not_found": "Haullasi ei lÃļytynyt yhtään albumia", "album_share_no_users": "Näyttää että olet jakanut tämän albumin kaikkien kanssa, tai sinulla ei ole käyttäjiä joille jakaa.", + "album_summary": "Albumi tiivistelmä", "album_updated": "Albumi päivitetty", "album_updated_setting_description": "Saa sähkÃļpostia kun jaetussa albumissa on uutta sisältÃļä", "album_user_left": "Poistuttiin albumista {album}", "album_user_removed": "{user} poistettu", - "album_viewer_appbar_delete_confirm": "Haluatko varmast poistaa tämän albumin tililtäsi?", + "album_viewer_appbar_delete_confirm": "Haluatko varmasti poistaa tämän albumin tililtäsi?", "album_viewer_appbar_share_err_delete": "Albumin poistaminen epäonnistui", "album_viewer_appbar_share_err_leave": "Albumista poistuminen epäonnistui", "album_viewer_appbar_share_err_remove": "Ongelmia kohteiden poistamisessa albumista", @@ -462,6 +470,7 @@ "app_bar_signout_dialog_title": "Kirjaudu ulos", "app_settings": "Sovellusasetukset", "appears_in": "Esiintyy albumeissa", + "apply_count": "Aseta {count, number}", "archive": "Arkisto", "archive_action_prompt": "{count} lisätty arkistoon", "archive_or_unarchive_photo": "Arkistoi kuva tai palauta arkistosta", @@ -473,7 +482,7 @@ "archived_count": "{count, plural, other {Arkistoitu #}}", "are_these_the_same_person": "Ovatko he sama henkilÃļ?", "are_you_sure_to_do_this": "Haluatko varmasti tehdä tämän?", - "asset_action_delete_err_read_only": "Vain luku-tilassa olevia kohteita ei voitu poistaa, ohitetaan", + "asset_action_delete_err_read_only": "Vain luku -tilassa olevia kohteita ei voitu poistaa, ohitetaan", "asset_action_share_err_offline": "Verkottomassa tilassa olevia kohteita ei voitu noutaa, ohitetaan", "asset_added_to_album": "Lisätty albumiin", "asset_adding_to_album": "Lisätään albumiinâ€Ļ", @@ -494,6 +503,8 @@ "asset_restored_successfully": "Kohde palautettu onnistuneesti", "asset_skipped": "Ohitettu", "asset_skipped_in_trash": "Roskakorissa", + "asset_trashed": "Kohde poistettu", + "asset_troubleshoot": "SisällÃļn vian paikannus", "asset_uploaded": "Lähetetty", "asset_uploading": "Ladataanâ€Ļ", "asset_viewer_settings_subtitle": "Galleriakatseluohjelman asetusten hallinta", @@ -501,7 +512,7 @@ "assets": "Kohteet", "assets_added_count": "Lisätty {count, plural, one {# kohde} other {# kohdetta}}", "assets_added_to_album_count": "Albumiin lisätty {count, plural, one {# kohde} other {# kohdetta}}", - "assets_added_to_albums_count": "Lisätty {assetTotal, plural, one {# aineisto} other {# aaineistoa}} {albumTotal, plural, one {# albumiin} other {# albumeihin}}", + "assets_added_to_albums_count": "Lisätty {assetTotal, plural, one {# kohde} other {# kohdetta}} {albumTotal, plural, one {# albumiin} other {# albumiin}}", "assets_cannot_be_added_to_album_count": "{count, plural, one {Kohdetta} other {Kohdetta}} ei voida lisätä albumiin", "assets_cannot_be_added_to_albums": "{count, plural, one {Aineisto} other {Aineistoa}} ei voi lisätä mihinkään albumiin", "assets_count": "{count, plural, one {# media} other {# mediaa}}", @@ -527,8 +538,10 @@ "autoplay_slideshow": "Toista diaesitys automaattisesti", "back": "Takaisin", "back_close_deselect": "Palaa, sulje tai poista valinnat", + "background_backup_running_error": "Tausta varmuuskopiointi on aktiivinen, ei voida aloittaa manuaalista varmuuskopiointia", "background_location_permission": "Taustasijainnin käyttÃļoikeus", "background_location_permission_content": "Jotta sovellus voi vaihtaa verkkoa taustalla toimiessaan, Immichillä on *aina* oltava pääsy tarkkaan sijaintiin, jotta se voi lukea Wi-Fi-verkon nimen", + "background_options": "Tausta valinnat", "backup": "Varmuuskopiointi", "backup_album_selection_page_albums_device": "Laitteen albumit ({count})", "backup_album_selection_page_albums_tap": "Napauta sisällyttääksesi, kaksoisnapauta jättääksesi pois", @@ -536,6 +549,7 @@ "backup_album_selection_page_select_albums": "Valitse albumit", "backup_album_selection_page_selection_info": "Valintatiedot", "backup_album_selection_page_total_assets": "Ainulaatuisia kohteita yhteensä", + "backup_albums_sync": "Varmuuskopioitujen albumeiden synkronointi", "backup_all": "Kaikki", "backup_background_service_backup_failed_message": "Kohteiden varmuuskopiointi epäonnistui. Yritetään uudelleenâ€Ļ", "backup_background_service_connection_failed_message": "Palvelimeen ei saatu yhteyttä. Yritetään uudelleenâ€Ļ", @@ -585,7 +599,8 @@ "backup_controller_page_turn_on": "Varmuuskopiointi päälle", "backup_controller_page_uploading_file_info": "Tiedostojen lähetystiedot", "backup_err_only_album": "Vähintään yhden albumin tulee olla valittuna", - "backup_info_card_assets": "kohteet", + "backup_error_sync_failed": "Synkronointi epäonnistui. Varmuuskopion käsittely ei onnistu.", + "backup_info_card_assets": "kohdetta", "backup_manual_cancelled": "Peruutettu", "backup_manual_in_progress": "Lähetys palvelimelle on jo käynnissä. Kokeile myÃļhemmin uudelleen", "backup_manual_success": "Onnistui", @@ -595,8 +610,6 @@ "backup_setting_subtitle": "Hallinnoi aktiivisia ja taustalla olevia lähetysasetuksia", "backup_settings_subtitle": "Hallitse lähetysasetuksia", "backward": "Taaksepäin", - "beta_sync": "Betasynkronoinnin tila", - "beta_sync_subtitle": "Hallitse uutta synkronointijärjestelmää", "biometric_auth_enabled": "Biometrinen tunnistautuminen käytÃļssä", "biometric_locked_out": "Sinulta on evätty pääsy biometriseen tunnistautumiseen", "biometric_no_options": "Ei biometrisiä vaihtoehtoja", @@ -622,7 +635,7 @@ "cache_settings_statistics_thumbnail": "Esikatselukuvat", "cache_settings_statistics_title": "Välimuistin käyttÃļ", "cache_settings_subtitle": "Hallitse Immich-mobiilisovelluksen välimuistin käyttÃļä", - "cache_settings_tile_subtitle": "Hallitse paikallista tallenustilaa", + "cache_settings_tile_subtitle": "Hallitse paikallista tallennustilaa", "cache_settings_tile_title": "Paikallinen tallennustila", "cache_settings_title": "Välimuistin asetukset", "camera": "Kamera", @@ -654,6 +667,8 @@ "change_pin_code": "Vaihda PIN-koodi", "change_your_password": "Vaihda salasanasi", "changed_visibility_successfully": "Näkyvyys vaihdettu", + "charging": "Ladataan laitetta", + "charging_requirement_mobile_backup": "Varmuuskopiointi taustalla vaatii laitteen latautumista", "check_corrupt_asset_backup": "Vioittuneiden varmuuskopioiden tarkistaminen", "check_corrupt_asset_backup_button": "Suorita tarkistus", "check_corrupt_asset_backup_description": "Suorita tämä tarkistus vain Wi-Fi-yhteyden kautta ja vasta, kun kaikki kohteet on varmuuskopioitu. Toimenpide voi kestää muutamia minuutteja.", @@ -740,6 +755,7 @@ "create_user": "Luo käyttäjä", "created": "Luotu", "created_at": "Luotu", + "creating_linked_albums": "Luodaan linkattuja albumeita...", "crop": "Rajaa", "curated_object_page_title": "Asiat", "current_device": "Nykyinen laite", @@ -764,7 +780,7 @@ "deduplication_criteria_1": "Kuvan koko tavuina", "deduplication_criteria_2": "EXIF-datan määrä", "deduplication_info": "Deduplikaatiotieto", - "deduplication_info_description": "Jotta voimme automaattisesti esivalita aineistot ja poistaa duplikaatit suurina erinä, tarkastelemme:", + "deduplication_info_description": "Jotta voimme automaattisesti esivalita aineistot ja poistaa kaksoiskappaleet suurina erinä, tarkastelemme:", "default_locale": "Oletuskieliasetus", "default_locale_description": "Muotoile päivämäärät ja numerot selaimesi kielen mukaan", "delete": "Poista", @@ -839,7 +855,7 @@ "downloading_media": "Median lataaminen", "drop_files_to_upload": "Pudota tiedostot mihin tahansa ladataksesi ne", "duplicates": "Kaksoiskappaleet", - "duplicates_description": "Selvitä jokaisen kohdalla mitkä (jos yksikään) ovat kaksoiskappaleita", + "duplicates_description": "Selvitä jokaisen kohdalla mitkä (jos mitkään) ovat kaksoiskappaleita", "duration": "Kesto", "edit": "Muokkaa", "edit_album": "Muokkaa albumia", @@ -889,7 +905,9 @@ "error": "Virhe", "error_change_sort_album": "Albumin lajittelujärjestyksen muuttaminen epäonnistui", "error_delete_face": "Virhe kasvojen poistamisessa kohteesta", + "error_getting_places": "Ongelma paikkojen haussa", "error_loading_image": "Kuvan lataus ei onnistunut", + "error_loading_partners": "Ongelma partnerin haussa: {error}", "error_saving_image": "Virhe: {error}", "error_tag_face_bounding_box": "Kasvojen merkitseminen epäonnistui – rajausruudun koordinaatteja ei lÃļydy", "error_title": "Virhe - Jotain meni pieleen", @@ -1049,11 +1067,12 @@ "failed_to_load_folder": "Kansion lataaminen epäonnistui", "favorite": "Suosikki", "favorite_action_prompt": "{count} lisätty suosikkeihin", - "favorite_or_unfavorite_photo": "Suosikki- tai ei-suosikkikuva", + "favorite_or_unfavorite_photo": "Lisää tai poista kuva suosikeista", "favorites": "Suosikit", "favorites_page_no_favorites": "Suosikkikohteita ei lÃļytynyt", "feature_photo_updated": "Kansikuva ladattu", "features": "Ominaisuudet", + "features_in_development": "Kehityksessä olevat ominaisuudet", "features_setting_description": "Hallitse sovelluksen ominaisuuksia", "file_name": "Tiedoston nimi", "file_name_or_extension": "Tiedostonimi tai tiedostopääte", @@ -1074,12 +1093,15 @@ "gcast_enabled": "Google Cast", "gcast_enabled_description": "Ominaisuus lataa ulkoisia resursseja Googlelta toimiakseen.", "general": "Yleinen", + "geolocation_instruction_location": "Napsauta kuvaa, jossa on GPS-koordinaatit, käyttääksesi sen sijaintia, tai valitse sijainti suoraan kartalta", "get_help": "Hae apua", "get_wifiname_error": "Wi-Fi-verkon nimen hakeminen epäonnistui. Varmista, että olet myÃļntänyt tarvittavat käyttÃļoikeudet ja että olet yhteydessä Wi-Fi-verkkoon", "getting_started": "Aloittaminen", "go_back": "Palaa", "go_to_folder": "Mene kansioon", "go_to_search": "Siirry hakuun", + "gps": "GPS", + "gps_missing": "Ei GPS:ää", "grant_permission": "MyÃļnnä lupa", "group_albums_by": "Ryhmitä albumi...", "group_country": "Ryhmitä maan mukaan", @@ -1109,18 +1131,18 @@ "home_page_add_to_album_conflicts": "Lisätty {added} kohdetta albumiin {album}. {failed} kohdetta on jo albumissa.", "home_page_add_to_album_err_local": "Paikallisten kohteiden lisääminen albumeihin ei ole mahdollista, ohitetaan", "home_page_add_to_album_success": "Lisätty {added} kohdetta albumiin {album}.", - "home_page_album_err_partner": "Kumppanin kohteita ei voi vielä lisätä albumiin. Hypätään yli", + "home_page_album_err_partner": "Kumppanin kohteita ei voi vielä lisätä albumiin, ohitetaan", "home_page_archive_err_local": "Paikallisten kohteiden arkistointi ei ole mahdollista, ohitetaan", - "home_page_archive_err_partner": "Kumppanin kohteita ei voi arkistoida. Hypätään yli", + "home_page_archive_err_partner": "Kumppanin kohteita ei voi arkistoida, ohitetaan", "home_page_building_timeline": "Rakennetaan aikajanaa", - "home_page_delete_err_partner": "Kumppanin kohteita ei voi poistaa.Hypätään yli", + "home_page_delete_err_partner": "Kumppanin kohteita ei voi poistaa, ohitetaan", "home_page_delete_remote_err_local": "Paikallisia kohteita etäkohdevalintojen joukossa, ohitetaan", "home_page_favorite_err_local": "Paikallisten kohteiden lisääminen suosikkeihin ei ole mahdollista, ohitetaan", - "home_page_favorite_err_partner": "Kumppanin kohteita ei voi vielä merkitä suosikiksi. Hypätään yli", + "home_page_favorite_err_partner": "Kumppanin kohteita ei voi vielä merkitä suosikiksi, ohitetaan", "home_page_first_time_notice": "Jos käytät sovellusta ensimmäistä kertaa, muista valita varmuuskopioitavat albumi(t), jotta aikajanalla voi olla kuvia ja videoita", "home_page_locked_error_local": "Paikallisten kohteiden siirto lukittuun kansioon ei onnistu, ohitetaan", "home_page_locked_error_partner": "Kumppanin kohteita ei voi siirtää lukittuun kansioon, ohitetaan", - "home_page_share_err_local": "Paikallisia kohteita ei voitu jakaa linkkien avulla. Hypätään yli", + "home_page_share_err_local": "Paikallisia kohteita ei voitu jakaa linkkien avulla, ohitetaan", "home_page_upload_err_limit": "Voit lähettää palvelimelle enintään 30 kohdetta kerrallaan, ohitetaan", "host": "Isäntä", "hour": "Tunti", @@ -1148,7 +1170,7 @@ "immich_web_interface": "Immich-verkkokäyttÃļliittymä", "import_from_json": "Tuo JSON-tiedostosta", "import_path": "Tuontipolku", - "in_albums": "{count, plural, one {# Albumissa} other {# albumissa}}", + "in_albums": "{count, plural, one {# albumissa} other {# albumissa}}", "in_archive": "Arkistossa", "include_archived": "Sisällytä arkistoidut", "include_shared_albums": "Sisällytä jaetut albumit", @@ -1157,10 +1179,10 @@ "individual_shares": "Yksittäiset jaot", "info": "Lisätietoja", "interval": { - "day_at_onepm": "Joka päivä klo 13:00", + "day_at_onepm": "Joka päivä klo 13.00", "hours": "Joka {hours, plural, one {tunti} other {{hours, number} tuntia}}", "night_at_midnight": "Joka yÃļ keskiyÃļllä", - "night_at_twoam": "Joka yÃļ klo 02:00" + "night_at_twoam": "Joka yÃļ klo 2.00" }, "invalid_date": "Virheellinen päivämäärä", "invalid_date_format": "Virheellinen päivämäärämuoto", @@ -1215,6 +1237,7 @@ "local": "Paikallinen", "local_asset_cast_failed": "Kohdetta, joka ei ole ladattuna palvelimelle, ei voida striimata", "local_assets": "Paikalliset kohteet", + "local_media_summary": "Paikallisen median yhteenveto", "local_network": "Lähiverkko", "local_network_sheet_info": "Sovellus muodostaa yhteyden palvelimeen tämän URL-osoitteen kautta, kun käytetään määritettyä Wi-Fi-verkkoa", "location_permission": "Sijainnin käyttÃļoikeus", @@ -1226,6 +1249,7 @@ "location_picker_longitude_hint": "SyÃļtä pituusaste", "lock": "Lukitse", "locked_folder": "Lukittu kansio", + "log_detail_title": "Lokin yksityiskohtaisuus", "log_out": "Kirjaudu ulos", "log_out_all_devices": "Kirjaudu ulos kaikilta laitteilta", "logged_in_as": "Kirjautunut käyttäjänä {user}", @@ -1256,6 +1280,7 @@ "login_password_changed_success": "Salasan päivitetty onnistuneesti", "logout_all_device_confirmation": "Haluatko varmasti kirjautua ulos kaikilta laitteilta?", "logout_this_device_confirmation": "Haluatko varmasti kirjautua ulos näiltä laitteilta?", + "logs": "Loki", "longitude": "Pituusaste", "look": "Tyyli", "loop_videos": "Toista videot uudelleen", @@ -1263,6 +1288,7 @@ "main_branch_warning": "Käytät kehitysversiota; suosittelemme vahvasti käyttämään julkaisuversiota!", "main_menu": "Päävalikko", "make": "Valmistaja", + "manage_geolocation": "Muokkaa sijaintia", "manage_shared_links": "Hallitse jaettuja linkkejä", "manage_sharing_with_partners": "Hallitse jakamista kumppaneille", "manage_the_app_settings": "Hallitse sovelluksen asetuksia", @@ -1297,6 +1323,7 @@ "mark_as_read": "Merkitse luetuksi", "marked_all_as_read": "Merkitty kaikki luetuiksi", "matches": "Osumia", + "matching_assets": "Vastaava sisältÃļ", "media_type": "Median tyyppi", "memories": "Muistoja", "memories_all_caught_up": "Kaikki ajan tasalla", @@ -1330,13 +1357,14 @@ "moved_to_library": "Siirretty {count, plural, one {# kohde} other {# kohdetta}} kirjastoon", "moved_to_trash": "Siirretty roskakoriin", "multiselect_grid_edit_date_time_err_read_only": "Vain luku -tilassa olevien kohteiden päivämäärää ei voitu muokata, ohitetaan", - "multiselect_grid_edit_gps_err_read_only": "Vain luku-tilassa olevien kohteiden sijantitietoja ei voitu muokata, ohitetaan", + "multiselect_grid_edit_gps_err_read_only": "Vain luku -tilassa olevien kohteiden sijantitietoja ei voitu muokata, ohitetaan", "mute_memories": "Mykistä muistot", "my_albums": "Omat albumit", "name": "Nimi", "name_or_nickname": "Nimi tai lempinimi", "network_requirement_photos_upload": "Käytä mobiiliverkkoa kuvien varmuuskopioimiseksi", "network_requirement_videos_upload": "Käytä mobiiliverkkoa videoiden varmuuskopioimiseksi", + "network_requirements": "Verkkovaatimukset", "network_requirements_updated": "Verkkovaatimukset muuttuivat, nollataan varmuuskopiointijono", "networking_settings": "Verkko", "networking_subtitle": "Hallitse palvelinasetuksia", @@ -1347,6 +1375,7 @@ "new_person": "Uusi henkilÃļ", "new_pin_code": "Uusi PIN-koodi", "new_pin_code_subtitle": "Tämä on ensimmäinen kerta, kun käytät lukittua kansiota. Luo PIN-koodi päästäksesi tähän sisältÃļÃļn turvallisesti", + "new_timeline": "Uusi aikajana", "new_user_created": "Uusi käyttäjä lisätty", "new_version_available": "UUSI VERSIO SAATAVILLA", "newest_first": "Uusin ensin", @@ -1357,23 +1386,28 @@ "no_albums_with_name_yet": "Näyttää siltä, ettei sinulla ole yhtään tämän nimistä albumia.", "no_albums_yet": "Näyttää siltä, ettei sinulla ole vielä yhtään albumia.", "no_archived_assets_message": "Arkistoi kuvia ja videoita piilottaaksesi ne kuvat näkymästä", - "no_assets_message": "NAPAUTA LATAAKSESI ENSIMMÄISEN KUVASI", + "no_assets_message": "NAPAUTA LADATAKSESI ENSIMMÄINEN KUVASI", "no_assets_to_show": "Ei näytettäviä kohteita", "no_cast_devices_found": "Cast-laitteita ei lÃļytynyt", + "no_checksum_local": "Ei tarkistussummaa - paikallista sisältÃļä ei voida hakea", + "no_checksum_remote": "Ei tarkistussummaa - etänä olevaa sisältÃļä ei voida hakea", "no_duplicates_found": "Kaksoiskappaleita ei lÃļytynyt.", "no_exif_info_available": "EXIF-tietoa ei saatavilla", "no_explore_results_message": "Lataa lisää kuvia tutkiaksesi kokoelmaasi.", "no_favorites_message": "Lisää suosikkeja lÃļytääksesi nopeasti parhaat kuvasi ja videosi", "no_libraries_message": "Luo ulkoinen kirjasto nähdäksesi valokuvasi ja videot", + "no_local_assets_found": "Paikallista sisältÃļä ei lÃļytynyt tällä tarkistussummalla", "no_locked_photos_message": "Kuvat ja videot lukitussa kansiossa ovat piilotettuja, eivätkä ne näy selatessasi tai etsiessäsi kirjastoasi.", "no_name": "Ei nimeä", "no_notifications": "Ei ilmoituksia", "no_people_found": "Ei vastaavia henkilÃļitä", "no_places": "Ei paikkoja", + "no_remote_assets_found": "Etänä olevaa sisältÃļä ei lÃļytynyt tällä tarkistussummalla", "no_results": "Ei tuloksia", "no_results_description": "Kokeile synonyymiä tai yleisempää avainsanaa", "no_shared_albums_message": "Luo albumi, jotta voit jakaa kuvia ja videoita toisille", "no_uploads_in_progress": "Ei käynnissä olevia latauksia", + "not_available": "N/A", "not_in_any_album": "Ei yhdessäkään albumissa", "not_selected": "Ei valittu", "note_apply_storage_label_to_previously_uploaded assets": "Huom: Jotta voit soveltaa tallennustunnistetta aiemmin ladattuihin kohteisiin, suorita", @@ -1408,6 +1442,8 @@ "open_the_search_filters": "Avaa hakusuodattimet", "options": "Vaihtoehdot", "or": "tai", + "organize_into_albums": "Järjestä albumeihin", + "organize_into_albums_description": "Siirrä olemassa olevat kuvat albumeihin käyttäen nykyisiä synkronointiasetuksia", "organize_your_library": "Järjestele kirjastosi", "original": "alkuperäinen", "other": "Muut", @@ -1453,7 +1489,7 @@ "permanent_deletion_warning_setting_description": "Näytä varoitus, kun poistat kohteita pysyvästi", "permanently_delete": "Poista pysyvästi", "permanently_delete_assets_count": "Poista pysyvästi {count, plural, one {kohde} other {kohteita}}", - "permanently_delete_assets_prompt": "Haluatko varmasti poistaa pysyvästi {count, plural, one {tämän kohteen?} other {nämä # kohteet?}} Tämä poistaa myÃļs {count, plural, one {sen} other {ne}} kaikista albumeista.", + "permanently_delete_assets_prompt": "Haluatko varmasti poistaa pysyvästi {count, plural, one {tämän kohteen?} other {nämä # kohteet?}} Tämä poistaa {count, plural, one {sen} other {ne}} myÃļs kaikista albumeista.", "permanently_deleted_asset": "Media poistettu pysyvästi", "permanently_deleted_assets_count": "{count, plural, one {# media} other {# mediaa}} poistettu pysyvästi", "permission": "KäyttÃļoikeus", @@ -1493,6 +1529,7 @@ "port": "Portti", "preferences_settings_subtitle": "Hallitse sovelluksen asetuksia", "preferences_settings_title": "Asetukset", + "preparing": "Valmistellaan", "preset": "Asetus", "preview": "Esikatselu", "previous": "Edellinen", @@ -1509,6 +1546,7 @@ "profile_drawer_client_out_of_date_minor": "Sovelluksen mobiiliversio on vanhentunut. Päivitä viimeisimpään versioon.", "profile_drawer_client_server_up_to_date": "Asiakasohjelma ja palvelin ovat ajan tasalla", "profile_drawer_github": "GitHub", + "profile_drawer_readonly_mode": "Muokkaus on estetty. Paina käyttäjäkuvaketta pitkään palataksesi muokkaustilaan.", "profile_drawer_server_out_of_date_major": "Palvelimen ohjelmistoversio on vanhentunut. Päivitä viimeisimpään merkittävään versioon.", "profile_drawer_server_out_of_date_minor": "Palvelimen ohjelmistoversio on vanhentunut. Päivitä viimeisimpään versioon.", "profile_image_of_user": "Käyttäjän {user} profiilikuva", @@ -1547,6 +1585,7 @@ "purchase_server_description_2": "Tukijan tila", "purchase_server_title": "Palvelin", "purchase_settings_server_activated": "Palvelimen tuoteavainta hallinnoi ylläpitäjä", + "query_asset_id": "Kysy sisällÃļn ID:tä", "queue_status": "Jonossa {count}/{total}", "rating": "Tähtiarvostelu", "rating_clear": "Tyhjennä arvostelu", @@ -1554,6 +1593,9 @@ "rating_description": "Näytä EXIF-arvosana lisätietopaneelissa", "reaction_options": "Reaktioasetukset", "read_changelog": "Lue muutosloki", + "readonly_mode_disabled": "Muokkaustila päällä", + "readonly_mode_enabled": "Muokkaustila pois päältä", + "ready_for_upload": "Valmis lähetystä varten", "reassign": "Määritä uudelleen", "reassigned_assets_to_existing_person": "Uudelleen määritetty {count, plural, one {# kohde} other {# kohdetta}} {name, select, null {olemassa olevalle henkilÃļlle} other {{name}}}", "reassigned_assets_to_new_person": "Määritetty {count, plural, one {# media} other {# mediaa}} uudelle henkilÃļlle", @@ -1578,6 +1620,7 @@ "regenerating_thumbnails": "Regeneroidaan pikkukuvia", "remote": "Etä", "remote_assets": "Etäkohteet", + "remote_media_summary": "Yhteenveto etänä olevasta mediasta", "remove": "Poista", "remove_assets_album_confirmation": "Haluatko varmasti poistaa {count, plural, one {# median} other {# mediaa}} albumista?", "remove_assets_shared_link_confirmation": "Haluatko varmasti poistaa {count, plural, one {# median} other {# mediaa}} tästä jakolinkistä?", @@ -1630,6 +1673,7 @@ "restore_user": "Palauta käyttäjä", "restored_asset": "Palautettu media", "resume": "Jatka", + "resume_paused_jobs": "Jatka {count, plural, one {# paused job} other {# paused jobs}}", "retry_upload": "Yritä latausta uudelleen", "review_duplicates": "Tarkastele kaksoiskappaleita", "review_large_files": "Tarkista suuret tiedostot", @@ -1694,7 +1738,7 @@ "search_places": "Etsi paikkoja", "search_rating": "Hae luokituksen mukaan...", "search_result_page_new_search_hint": "Uusi haku", - "search_settings": "Hakuasetukset", + "search_settings": "Etsi asetuksia", "search_state": "Etsi maakuntaa...", "search_suggestion_list_smart_search_hint_1": "Älykäs haku on oletuksena käytÃļssä. Käytä metatietojen etsimiseen syntaksia ", "search_suggestion_list_smart_search_hint_2": "m:hakusana", @@ -1706,7 +1750,7 @@ "second": "Toinen", "see_all_people": "Näytä kaikki henkilÃļt", "select": "Valitse", - "select_album_cover": "Valitse albmin kansi", + "select_album_cover": "Valitse albumin kansi", "select_all": "Valitse kaikki", "select_all_duplicates": "Valitse kaikki kaksoiskappaleet", "select_all_in": "Valitse kaikki {group}", @@ -1723,6 +1767,7 @@ "select_user_for_sharing_page_err_album": "Albumin luonti epäonnistui", "selected": "Valittu", "selected_count": "{count, plural, other {# valittu}}", + "selected_gps_coordinates": "Valitut GPS-koordinaatit", "send_message": "Lähetä viesti", "send_welcome_email": "Lähetä tervetuloviesti", "server_endpoint": "Palvelinosoite", @@ -1764,7 +1809,7 @@ "setting_video_viewer_original_video_subtitle": "Kun toistat videota palvelimelta, toista alkuperäinen, vaikka transkoodattu versio olisi saatavilla. Tämä voi johtaa puskurointiin. Paikalliset videot toistetaan aina alkuperäislaadulla.", "setting_video_viewer_original_video_title": "Pakota alkuperäinen video", "settings": "Asetukset", - "settings_require_restart": "Käynnistä Immich uudelleen ottaaksesti tämän asetuksen käyttÃļÃļn", + "settings_require_restart": "Käynnistä Immich uudelleen ottaaksesi tämä asetus käyttÃļÃļn", "settings_saved": "Asetukset tallennettu", "setup_pin_code": "Määritä PIN-koodi", "share": "Jaa", @@ -1830,7 +1875,7 @@ "sharing_sidebar_description": "Näytä jakamislinkki sivupalkissa", "sharing_silver_appbar_create_shared_album": "Luo jaettu albumi", "sharing_silver_appbar_share_partner": "Jaa kumppanille", - "shift_to_permanent_delete": "Paina ⇧ poistaaksesi median pysyvästi", + "shift_to_permanent_delete": "Paina ⇧ poistaaksesi media pysyvästi", "show_album_options": "Näytä albumin asetukset", "show_albums": "Näytä albumit", "show_all_people": "Näytä kaikki henkilÃļt", @@ -1851,6 +1896,7 @@ "show_slideshow_transition": "Näytä diaesitys siirtymä", "show_supporter_badge": "Kannattajan merkki", "show_supporter_badge_description": "Näytä kannattajan merkki", + "show_text_search_menu": "Näytä tekstihakuvalikko", "shuffle": "Sekoita", "sidebar": "Sivupalkki", "sidebar_display_description": "Näytä linkki näkymään sivupalkissa", @@ -1881,6 +1927,7 @@ "stacktrace": "Vianetsintätiedot", "start": "Aloita", "start_date": "Alkupäivä", + "start_date_before_end_date": "Aloituspäivämäärän pitää olla ennen lopetuspäivämäärää", "state": "Maakunta", "status": "Tila", "stop_casting": "Lopeta suoratoisto", @@ -1905,6 +1952,8 @@ "sync_albums_manual_subtitle": "Synkronoi kaikki ladatut videot ja valokuvat valittuihin varmuuskopioalbumeihin", "sync_local": "Synkronoi paikallinen", "sync_remote": "Synkronoi etä", + "sync_status": "Synkronoinnin status", + "sync_status_subtitle": "Näytä ja hallinnoi synkronointijärjestelmää", "sync_upload_album_setting_subtitle": "Luo ja lataa valokuvasi ja videosi valittuihin albumeihin Immichissä", "tag": "Tunniste", "tag_assets": "Lisää tunnisteita", @@ -1942,7 +1991,9 @@ "to_change_password": "Vaihda salasana", "to_favorite": "Aseta suosikiksi", "to_login": "Kirjaudu sisään", + "to_multi_select": "usean valitsemiseksi", "to_parent": "Siirry vanhempaan", + "to_select": "valitsemiseksi", "to_trash": "Roskakoriin", "toggle_settings": "Määritä asetukset", "total": "Yhteensä", @@ -1950,7 +2001,7 @@ "trash": "Roskakori", "trash_action_prompt": "{count} siirretty roskakoriin", "trash_all": "Vie kaikki roskakoriin", - "trash_count": "Roskakori {count, number}", + "trash_count": "Vie {count, number} roskakoriin", "trash_delete_asset": "Poista / vie roskakoriin", "trash_emptied": "Roskakori tyhjennetty", "trash_no_results_message": "Roskakorissa olevat kuvat ja videot näytetään täällä.", @@ -1962,6 +2013,7 @@ "trash_page_select_assets_btn": "Valitse kohteet", "trash_page_title": "Roskakori ({count})", "trashed_items_will_be_permanently_deleted_after": "Roskakorin kohteet poistetaan pysyvästi {days, plural, one {# päivän} other {# päivän}} päästä.", + "troubleshoot": "Vianetsintä", "type": "Tyyppi", "unable_to_change_pin_code": "PIN-koodin vaihtaminen epäonnistui", "unable_to_setup_pin_code": "PIN-koodin määrittäminen epäonnistui", @@ -1992,6 +2044,7 @@ "unstacked_assets_count": "Poistettu pinosta {count, plural, one {# kohde} other {# kohdetta}}", "untagged": "Ilman tunnistetta", "up_next": "Seuraavaksi", + "update_location_action_prompt": "Päivitä {count} kohteen sijaintia:", "updated_at": "Päivitetty", "updated_password": "Salasana päivitetty", "upload": "Siirrä palvelimelle", @@ -2058,6 +2111,7 @@ "view_next_asset": "Näytä seuraava", "view_previous_asset": "Näytä edellinen", "view_qr_code": "Näytä QR-koodi", + "view_similar_photos": "Näytä samankaltaiset kuvat", "view_stack": "Näytä pinona", "view_user": "Näytä käyttäjä", "viewer_remove_from_stack": "Poista pinosta", @@ -2076,5 +2130,6 @@ "yes": "Kyllä", "you_dont_have_any_shared_links": "Sinulla ei ole jaettuja linkkejä", "your_wifi_name": "Wi-Fi-verkkosi nimi", - "zoom_image": "Zoomaa kuvaa" + "zoom_image": "Zoomaa kuvaa", + "zoom_to_bounds": "Zoomaa reunoihin" } diff --git a/i18n/fr.json b/i18n/fr.json index 7d30f4e25f..0c92c52764 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -28,10 +28,12 @@ "add_to_album": "Ajouter à l'album", "add_to_album_bottom_sheet_added": "AjoutÊ à {album}", "add_to_album_bottom_sheet_already_exists": "DÊjà dans {album}", + "add_to_album_bottom_sheet_some_local_assets": "Certains mÊdias n'ont pas pu ÃĒtre ajoutÊs à l'album", "add_to_album_toggle": "Basculer la sÊlection pour {album}", "add_to_albums": "Ajouter aux albums", "add_to_albums_count": "Ajouter aux albums ({count})", "add_to_shared_album": "Ajouter à l'album partagÊ", + "add_upload_to_stack": "Ajouter les ÊlÊments tÊlÊversÊs à la pile", "add_url": "Ajouter l'URL", "added_to_archive": "AjoutÊ à l'archive", "added_to_favorites": "AjoutÊ aux favoris", @@ -123,6 +125,13 @@ "logging_enable_description": "Activer la journalisation", "logging_level_description": "Niveau de journalisation lorsque cette option est activÊe.", "logging_settings": "Journalisation", + "machine_learning_availability_checks": "VÊrifications de disponibilitÊ", + "machine_learning_availability_checks_description": "DÊtecte automatiquement et choisit les serveurs d'apprentissage machine disponibles", + "machine_learning_availability_checks_enabled": "Activer les vÊrifications de disponibilitÊ", + "machine_learning_availability_checks_interval": "Intervalle de vÊrification", + "machine_learning_availability_checks_interval_description": "Intervalle en millisecondes entre les vÊrifications de disponibilitÊ", + "machine_learning_availability_checks_timeout": "DÊlai d'expiration de la requÃĒte", + "machine_learning_availability_checks_timeout_description": "DÊlai d'expiration en millisecondes pour les vÊrifications de disponibilitÊ", "machine_learning_clip_model": "Modèle de langage CLIP", "machine_learning_clip_model_description": "Le nom d'un modèle CLIP listÊ ici. Notez que vous devez rÊexÊcuter la tÃĸche 'Recherche intelligente' pour toutes les images après avoir changÊ de modèle.", "machine_learning_duplicate_detection": "DÊtection des doublons", @@ -387,9 +396,7 @@ "admin_password": "Mot de passe Admin", "administration": "Administration", "advanced": "AvancÊ", - "advanced_settings_beta_timeline_subtitle": "Essayer la nouvelle application", - "advanced_settings_beta_timeline_title": "Timeline de la bÊta", - "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_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 tous les albums.", "advanced_settings_enable_alternate_media_filter_title": "[EXPÉRIMENTAL] Utiliser le filtre de synchronisation d'album alternatif", "advanced_settings_log_level_title": "Niveau de journalisation : {level}", "advanced_settings_prefer_remote_subtitle": "Certains appareils sont très lents à charger des miniatures à partir de ressources locales. Activez ce paramètre pour charger des images externes à la place.", @@ -425,6 +432,7 @@ "album_remove_user_confirmation": "Êtes-vous sÃģr de vouloir supprimer {user} ?", "album_search_not_found": "Aucun album trouvÊ ne correspond à votre recherche", "album_share_no_users": "Il semble que vous ayez partagÊ cet album avec tous les utilisateurs ou que vous n'ayez aucun utilisateur avec lequel le partager.", + "album_summary": "RÊsumÊ de l'album", "album_updated": "Album mis à jour", "album_updated_setting_description": "Recevoir une notification par courriel lorsqu'un album partagÊ a de nouveaux mÊdias", "album_user_left": "{album} quittÊ", @@ -496,6 +504,8 @@ "asset_restored_successfully": "ÉlÊment restaurÊ avec succès", "asset_skipped": "SautÊ", "asset_skipped_in_trash": "À la corbeille", + "asset_trashed": "MÊdia mis à la corbeille", + "asset_troubleshoot": "DÊpannage de mÊdia", "asset_uploaded": "EnvoyÊ", "asset_uploading": "Envoiâ€Ļ", "asset_viewer_settings_subtitle": "Modifier les paramètres du visualiseur photos", @@ -529,8 +539,10 @@ "autoplay_slideshow": "Lecture automatique d'un diaporama", "back": "Retour", "back_close_deselect": "Retournez en arrière, fermez ou dÊsÊlectionnez", + "background_backup_running_error": "La sauvegarde en tÃĸche de fond est actuellement en cours, impossible de dÊmarrer une sauvegarde manuelle", "background_location_permission": "Permission de localisation en arrière plan", "background_location_permission_content": "Afin de pouvoir changer d'adresse en arrière plan, Immich doit avoir *en permanence* accès à la localisation prÊcise, afin d'accÊder au le nom du rÊseau Wi-Fi utilisÊ", + "background_options": "Options d'arrière-plan", "backup": "Sauvegarde", "backup_album_selection_page_albums_device": "Albums sur l'appareil ({count})", "backup_album_selection_page_albums_tap": "Tapez pour inclure, tapez deux fois pour exclure", @@ -538,6 +550,7 @@ "backup_album_selection_page_select_albums": "SÊlectionner les albums", "backup_album_selection_page_selection_info": "Informations sur la sÊlection", "backup_album_selection_page_total_assets": "Total des ÊlÊments uniques", + "backup_albums_sync": "Sauvegarde de la synchronisation des albums", "backup_all": "Tout", "backup_background_service_backup_failed_message": "Échec de la sauvegarde des mÊdias. Nouvelle tentativeâ€Ļ", "backup_background_service_connection_failed_message": "Impossible de se connecter au serveur. Nouvelle tentativeâ€Ļ", @@ -587,7 +600,8 @@ "backup_controller_page_turn_on": "Activer la sauvegarde au premier plan", "backup_controller_page_uploading_file_info": "Envoi des informations du fichier", "backup_err_only_album": "Impossible de retirer le seul album", - "backup_info_card_assets": "ÊlÊments", + "backup_error_sync_failed": "Échec de la synchronisation. Impossible d'exÊcuter la sauvegarde.", + "backup_info_card_assets": "mÊdias", "backup_manual_cancelled": "AnnulÊ", "backup_manual_in_progress": "Envoi dÊjà en cours. RÊessayez plus tard", "backup_manual_success": "Succès", @@ -597,8 +611,6 @@ "backup_setting_subtitle": "Ajuster les paramètres d'envoi au premier et en arrière-plan", "backup_settings_subtitle": "GÊrer les paramètres de tÊlÊversement", "backward": "Arrière", - "beta_sync": "Statut de la synchronisation bÊta", - "beta_sync_subtitle": "GÊrer le nouveau système de synchronisation", "biometric_auth_enabled": "Authentification biomÊtrique activÊe", "biometric_locked_out": "L'authentification biomÊtrique est verrouillÊ", "biometric_no_options": "Aucune option biomÊtrique disponible", @@ -656,6 +668,8 @@ "change_pin_code": "Changer le code PIN", "change_your_password": "Changer votre mot de passe", "changed_visibility_successfully": "VisibilitÊ modifiÊe avec succès", + "charging": "En charge", + "charging_requirement_mobile_backup": "La sauvegarde en tÃĸche de fond nÊcessite que l'appareil soit en charge", "check_corrupt_asset_backup": "VÊrifier la corruption des ÊlÊments enregistrÊs", "check_corrupt_asset_backup_button": "VÊrifier", "check_corrupt_asset_backup_description": "Lancer cette vÊrification uniquement lorsque connectÊ à un rÊseau Wi-Fi et que tout le contenu a ÊtÊ enregistrÊ. Cette procÊdure peut durer plusieurs minutes.", @@ -742,6 +756,7 @@ "create_user": "CrÊer un utilisateur", "created": "CrÊÊ", "created_at": "CrÊÊ à", + "creating_linked_albums": "CrÊation des albums liÊs...", "crop": "Recadrer", "curated_object_page_title": "Objets", "current_device": "Appareil actuel", @@ -891,7 +906,9 @@ "error": "Erreur", "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_getting_places": "Erreur à la rÊcupÊration des lieux", "error_loading_image": "Erreur de chargement de l'image", + "error_loading_partners": "Erreur de rÊcupÊration des partenaires : {error}", "error_saving_image": "Erreur : {error}", "error_tag_face_bounding_box": "Erreur lors de l'identification de visage - impossible de rÊcupÊrer les coordonnÊes du cadre entourant le visage", "error_title": "Erreur - Quelque chose s'est mal passÊ", @@ -1056,6 +1073,7 @@ "favorites_page_no_favorites": "Aucun ÊlÊment favori n'a ÊtÊ trouvÊ", "feature_photo_updated": "Photo de la personne mise à jour", "features": "FonctionnalitÊs", + "features_in_development": "FonctionnalitÊs en dÊveloppement", "features_setting_description": "GÊrer les fonctionnalitÊs de l'application", "file_name": "Nom du fichier", "file_name_or_extension": "Nom du fichier ou extension", @@ -1076,10 +1094,7 @@ "gcast_enabled": "Diffusion Google Cast", "gcast_enabled_description": "Cette fonctionnalitÊ charge des ressources externes depuis Google pour fonctionner.", "general": "GÊnÊral", - "geolocation_instruction_all_have_location": "Tous les mÊdias pour cette date ont dÊjà des donnÊes de localisation. Essayez d'afficher tous les mÊdias ou sÊlectionnez une date diffÊrente", "geolocation_instruction_location": "Cliquez sur un mÊdia avec des coordonnÊes GPS pour utiliser sa localisation, ou bien sÊlectionnez une localisation directement sur la carte", - "geolocation_instruction_no_date": "SÊlectionnez une date pour gÊrer les donnÊes de localisation pour les photos et vidÊos de ce jour", - "geolocation_instruction_no_photos": "Aucune photo ou vidÊo trouvÊe pour cette date. SÊlectionnez une date diffÊrente pour en afficher", "get_help": "Obtenir de l'aide", "get_wifiname_error": "Impossible d'obtenir le nom du rÊseau wifi. Assurez-vous d'avoir donnÊ les permissions nÊcessaires à l'application et que vous ÃĒtes connectÊ à un rÊseau wifi", "getting_started": "Commencer", @@ -1223,6 +1238,7 @@ "local": "Local", "local_asset_cast_failed": "Impossible de caster un mÊdia qui n'a pas envoyÊ vers le serveur", "local_assets": "MÊdia locaux", + "local_media_summary": "RÊsumÊ du mÊdia local", "local_network": "RÊseau local", "local_network_sheet_info": "L'application va se connecter au serveur via cette URL quand l'appareil est connectÊ à ce rÊseau Wi-Fi", "location_permission": "Autorisation de localisation", @@ -1234,6 +1250,7 @@ "location_picker_longitude_hint": "Saisir la longitude ici", "lock": "Verrouiller", "locked_folder": "Dossier verrouillÊ", + "log_detail_title": "Niveau de journalisation", "log_out": "Se dÊconnecter", "log_out_all_devices": "DÊconnecter tous les appareils", "logged_in_as": "ConnectÊ en tant que {user}", @@ -1264,6 +1281,7 @@ "login_password_changed_success": "Mot de passe mis à jour avec succès", "logout_all_device_confirmation": "Êtes-vous sÃģr de vouloir dÊconnecter tous les appareils ?", "logout_this_device_confirmation": "Êtes-vous sÃģr de vouloir dÊconnecter cet appareil ?", + "logs": "Journaux", "longitude": "Longitude", "look": "Regarder", "loop_videos": "VidÊos en boucle", @@ -1306,6 +1324,7 @@ "mark_as_read": "Marquer comme lu", "marked_all_as_read": "Tout a ÊtÊ marquÊ comme lu", "matches": "Correspondances", + "matching_assets": "MÊdias correspondants", "media_type": "Type de mÊdia", "memories": "Souvenirs", "memories_all_caught_up": "Vous avez tout vu", @@ -1346,6 +1365,7 @@ "name_or_nickname": "Nom ou surnom", "network_requirement_photos_upload": "Utiliser les donnÊes mobile pour sauvegarder les photos", "network_requirement_videos_upload": "Utiliser les donnÊes mobile pour sauvegarder les vidÊos", + "network_requirements": "PrÊrequis rÊseau", "network_requirements_updated": "Contraintes rÊseau modifiÊes, file d'attente de sauvegarde rÊinitialisÊe", "networking_settings": "RÊseau", "networking_subtitle": "GÊrer les adresses du serveur", @@ -1356,6 +1376,7 @@ "new_person": "Nouvelle personne", "new_pin_code": "Nouveau code PIN", "new_pin_code_subtitle": "C'est votre premier accès au dossier verrouillÊ. CrÊez un code PIN pour sÊcuriser l'accès à cette page", + "new_timeline": "Nouvelle vue chronologique", "new_user_created": "Nouvel utilisateur crÊÊ", "new_version_available": "NOUVELLE VERSION DISPONIBLE", "newest_first": "RÊcents en premier", @@ -1369,20 +1390,25 @@ "no_assets_message": "CLIQUEZ POUR ENVOYER VOTRE PREMIÈRE PHOTO", "no_assets_to_show": "Aucun ÊlÊment à afficher", "no_cast_devices_found": "Aucun appareil de diffusion trouvÊ", + "no_checksum_local": "Aucune empreinte numerique disponible - impossible de rÊcupÊrer les mÊdias locaux", + "no_checksum_remote": "Aucune empreinte numÊrique disponible - impossible de rÊcupÊrer les mÊdias distants", "no_duplicates_found": "Aucun doublon n'a ÊtÊ trouvÊ.", "no_exif_info_available": "Aucune information exif disponible", "no_explore_results_message": "Envoyez plus de photos pour explorer votre bibliothèque.", "no_favorites_message": "Ajouter des photos et vidÊos à vos favoris pour les retrouver plus rapidement", "no_libraries_message": "CrÊer une bibliothèque externe pour voir vos photos et vidÊos dans un autre espace de stockage", + "no_local_assets_found": "Aucun mÊdia local trouvÊ avec cette empreinte numerique", "no_locked_photos_message": "Les photos et vidÊos du dossier verrouillÊ sont masquÊs et ne s'afficheront pas dans votre galerie ou la recherche.", "no_name": "Pas de nom", "no_notifications": "Pas de notification", "no_people_found": "Aucune personne correspondante trouvÊe", "no_places": "Pas de lieu", + "no_remote_assets_found": "Aucun mÊdia distant trouvÊ avec cette empreinte numerique", "no_results": "Aucun rÊsultat", "no_results_description": "Essayez un synonyme ou un mot-clÊ plus gÊnÊral", "no_shared_albums_message": "CrÊer un album pour partager vos photos et vidÊos avec les personnes de votre rÊseau", "no_uploads_in_progress": "Pas d'envoi en cours", + "not_available": "N/A", "not_in_any_album": "Dans aucun album", "not_selected": "Non sÊlectionnÊ", "note_apply_storage_label_to_previously_uploaded assets": "Note : Pour appliquer l'Êtiquette de stockage aux mÊdias prÊcÊdemment envoyÊs, exÊcutez", @@ -1504,6 +1530,7 @@ "port": "Port", "preferences_settings_subtitle": "GÊrer les prÊfÊrences de l'application", "preferences_settings_title": "PrÊfÊrences", + "preparing": "PrÊparation", "preset": "PrÊrÊglage", "preview": "Aperçu", "previous": "PrÊcÊdent", @@ -1520,7 +1547,7 @@ "profile_drawer_client_out_of_date_minor": "L'application mobile est obsolète. Veuillez effectuer la mise à jour vers la dernière version mineure.", "profile_drawer_client_server_up_to_date": "Le client et le serveur sont à jour", "profile_drawer_github": "GitHub", - "profile_drawer_readonly_mode": "Mode lecture seule activÊ. Faites un appui double sur l'image de l'utilisateur pour quitter.", + "profile_drawer_readonly_mode": "Mode lecture seule activÊ. Faites un appui long sur l'image de l'utilisateur pour quitter.", "profile_drawer_server_out_of_date_major": "Le serveur est obsolète. Veuillez mettre à jour vers la dernière version majeure.", "profile_drawer_server_out_of_date_minor": "Le serveur est obsolète. Veuillez mettre à jour vers la dernière version mineure.", "profile_image_of_user": "Image de profil de {user}", @@ -1559,7 +1586,7 @@ "purchase_server_description_2": "Statut de contributeur", "purchase_server_title": "Serveur", "purchase_settings_server_activated": "La clÊ du produit pour le Serveur est gÊrÊe par l'administrateur", - "query_asset_id": "ID du mÊdia requis", + "query_asset_id": "Obtenir l'ID du mÊdia", "queue_status": "{count}/{total} en file d'attente", "rating": "Étoile d'Êvaluation", "rating_clear": "Effacer l'Êvaluation", @@ -1569,6 +1596,7 @@ "read_changelog": "Lire les changements", "readonly_mode_disabled": "Mode lecture seule dÊsactivÊ", "readonly_mode_enabled": "Mode lecture seule activÊ", + "ready_for_upload": "TÊlÊchargement prÃĒt", "reassign": "RÊattribuer", "reassigned_assets_to_existing_person": "{count, plural, one {# mÊdia rÊattribuÊ} other {# mÊdias rÊattribuÊs}} à {name, select, null {une personne existante} other {{name}}}", "reassigned_assets_to_new_person": "{count, plural, one {# mÊdia rÊattribuÊ} other {# mÊdias rÊattribuÊs}} à une nouvelle personne", @@ -1593,6 +1621,7 @@ "regenerating_thumbnails": "RegÊnÊration des miniatures", "remote": "À distance", "remote_assets": "MÊdia à distance", + "remote_media_summary": "RÊsumÊ du mÊdia distant", "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Ê ?", @@ -1645,6 +1674,7 @@ "restore_user": "Restaurer l'utilisateur", "restored_asset": "MÊdia restaurÊ", "resume": "Reprendre", + "resume_paused_jobs": "Reprendre {count, plural, one {la tÃĸche en cours} other {les # tÃĸches en cours}}", "retry_upload": "RÊessayer l'envoi", "review_duplicates": "Consulter les doublons", "review_large_files": "Consulter les fichiers volumineux", @@ -1849,10 +1879,8 @@ "shift_to_permanent_delete": "appuyez sur ⇧ pour supprimer dÊfinitivement le mÊdia", "show_album_options": "Afficher les options de l'album", "show_albums": "Montrer les albums", - "show_all_assets": "Montrer tous les mÊdias", "show_all_people": "Montrer toutes les personnes", "show_and_hide_people": "Afficher / Masquer les personnes", - "show_assets_without_location": "Montrer les mÊdias sans localisation", "show_file_location": "Afficher l'emplacement du fichier", "show_gallery": "Afficher la galerie", "show_hidden_people": "Afficher les personnes masquÊes", @@ -1869,6 +1897,7 @@ "show_slideshow_transition": "Afficher la transition du diaporama", "show_supporter_badge": "Badge de contributeur", "show_supporter_badge_description": "Afficher le badge de contributeur", + "show_text_search_menu": "Afficher le menu de recherche de texte", "shuffle": "MÊlanger", "sidebar": "Barre latÊrale", "sidebar_display_description": "Afficher un lien vers la vue dans la barre latÊrale", @@ -1899,6 +1928,7 @@ "stacktrace": "Trace de la pile", "start": "Commencer", "start_date": "Date de dÊbut", + "start_date_before_end_date": "La date de dÊbut doit ÃĒtre avant la date de fin", "state": "RÊgion", "status": "Statut", "stop_casting": "ArrÃĒter la diffusion", @@ -1923,6 +1953,8 @@ "sync_albums_manual_subtitle": "Synchroniser toutes les vidÊos et photos envoyÊes dans les albums sÊlectionnÊs", "sync_local": "Synchronisation locale", "sync_remote": "Synchronisation à distance", + "sync_status": "Statut de synchronisation", + "sync_status_subtitle": "Consulter et gÊrer le système de synchronisation", "sync_upload_album_setting_subtitle": "CrÊez et envoyez vos photos et vidÊos dans les albums sÊlectionnÊs sur Immich", "tag": "Étiquette", "tag_assets": "Étiqueter les mÊdias", @@ -1968,7 +2000,7 @@ "total": "Total", "total_usage": "Utilisation globale", "trash": "Corbeille", - "trash_action_prompt": "{count} mis à la corbeille", + "trash_action_prompt": "{count} mÊdia(s) mis à la corbeille", "trash_all": "Tout supprimer", "trash_count": "Corbeille {count, number}", "trash_delete_asset": "Mettre à la corbeille/Supprimer un mÊdia", @@ -1982,6 +2014,7 @@ "trash_page_select_assets_btn": "SÊlectionner les ÊlÊments", "trash_page_title": "Corbeille ({count})", "trashed_items_will_be_permanently_deleted_after": "Les ÊlÊments dans la corbeille seront supprimÊs dÊfinitivement après {days, plural, one {# jour} other {# jours}}.", + "troubleshoot": "DÊpannage", "type": "Type", "unable_to_change_pin_code": "Impossible de changer le code PIN", "unable_to_setup_pin_code": "Impossible de dÊfinir le code PIN", @@ -2037,7 +2070,6 @@ "use_biometric": "Utiliser l'authentification biomÊtrique", "use_current_connection": "Utiliser le rÊseau actuel", "use_custom_date_range": "Utilisez une plage de date personnalisÊe à la place", - "use_this_location": "Cliquez pour utiliser la localisation", "user": "Utilisateur", "user_has_been_deleted": "Cet utilisateur à ÊtÊ supprimÊ.", "user_id": "ID Utilisateur", @@ -2080,7 +2112,7 @@ "view_next_asset": "Voir le mÊdia suivant", "view_previous_asset": "Voir le mÊdia prÊcÊdent", "view_qr_code": "Voir le QR code", - "view_similar_photos": "Voir les photos similaires", + "view_similar_photos": "Afficher les photos similaires", "view_stack": "Afficher la pile", "view_user": "Voir l'utilisateur", "viewer_remove_from_stack": "Retirer de la pile", @@ -2099,5 +2131,6 @@ "yes": "Oui", "you_dont_have_any_shared_links": "Vous n'avez aucun lien partagÊ", "your_wifi_name": "Nom du rÊseau wifi", - "zoom_image": "Zoomer" + "zoom_image": "Zoomer", + "zoom_to_bounds": "Zoom sur la zone" } diff --git a/i18n/gl.json b/i18n/gl.json index ee1949250f..8a38ef2c86 100644 --- a/i18n/gl.json +++ b/i18n/gl.json @@ -11,73 +11,87 @@ "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 ubicaciÃŗn", + "add_a_location": "Engadir unha localizaciÃŗn", "add_a_name": "Engadir un nome", "add_a_title": "Engadir un título", - "add_endpoint": "Engadir endpoint", + "add_birthday": "Engadir cumpreanos", + "add_endpoint": "Engadir punto final", "add_exclusion_pattern": "Engadir patrÃŗn de exclusiÃŗn", "add_import_path": "Engadir ruta de importaciÃŗn", - "add_location": "Engadir ubicaciÃŗn", + "add_location": "Engadir localizaciÃŗn", "add_more_users": "Engadir mÃĄis usuarios", "add_partner": "Engadir compaÃąeiro/a", "add_path": "Engadir ruta", "add_photos": "Engadir fotos", + "add_tag": "Engadir etiqueta", "add_to": "Engadir aâ€Ļ", "add_to_album": "Engadir ao ÃĄlbum", "add_to_album_bottom_sheet_added": "Engadido a {album}", "add_to_album_bottom_sheet_already_exists": "Xa estÃĄ en {album}", + "add_to_album_bottom_sheet_some_local_assets": "Algunhas imaxes ou ficheiros locais non se puideron engadir ao ÃĄlbum", + "add_to_album_toggle": "Alternar selecciÃŗn para {album}", + "add_to_albums": "Engadir a ÃĄlbums", + "add_to_albums_count": "Engadir a {count} ÃĄlbums", "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": "Engadido {count, number} a favoritos", + "added_to_favorites_count": "Engadíronse {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.", + "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\", empregue \"**/Raw/**\". Para ignorar todos os ficheiros que rematen en \".tif\", use \"**/*.tif\". Para ignorar unha ruta absoluta, empregue \"/ruta/a/ignorar/**\".", + "admin_user": "Usuario administrador", + "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, comprobe a sÃēa liÃąa de tempo para o novo activo correspondente. Para restaurar este activo, asegÃērese 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 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_disable_all": "EstÃĄ seguro de que quere 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": "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", + "backup_database": "Crear unha copia da base de datos", + "backup_database_enable_description": "Activar a copia de seguridade da base de datos", + "backup_keep_last_amount": "NÃēmero de copias anteriores a conservar", + "backup_onboarding_1_description": "Copia externa na nube ou noutra localizaciÃŗn física.", + "backup_onboarding_2_description": "Copias locais en diferentes dispositivos. Isto inclÃēe os arquivos principais e as copias deses arquivos localmente.", + "backup_onboarding_3_description": "Copias totais da sÃēa informaciÃŗn, incluíndo os arquivos orixinais. Isto inclÃēe 1 copia externa e 2 copias locais.", + "backup_onboarding_description": "Unha estratexia de copia de seguridade 3-2-1 Ê recomendada para protexer os seus datos. Debería gardar copias das sÃēas fotos/vídeos subidos así como da base de datos de Immich como unha soluciÃŗn de seguridade.", + "backup_onboarding_footer": "Para mÃĄis informaciÃŗn sobre copias de seguridade de Immich, por favor use a seguinte ligazÃŗn ÃĄ documentaciÃŗn.", + "backup_onboarding_parts_title": "Unha copia de seguridade 3-2-1 inclÃēe:", + "backup_onboarding_title": "Copia de seguridade", + "backup_settings": "ConfiguraciÃŗn da copia da base de datos", + "backup_settings_description": "Xestionar a configuraciÃŗn da copia da base de datos", "cleared_jobs": "Traballos borrados para: {job}", "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}?", - "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_delete_library": "EstÃĄ seguro de que quere eliminar a biblioteca {library}?", + "confirm_delete_library_assets": "EstÃĄ seguro de que quere 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}?", - "confirm_user_pin_code_reset": "EstÃĄs seguro de que queres restablecer o PIN de {user}?", + "confirm_reprocess_all_faces": "EstÃĄ seguro de que quere reprocesar todas as caras? Isto tamÊn borrarÃĄ as persoas nomeadas.", + "confirm_user_password_reset": "EstÃĄ seguro de que quere restablecer o contrasinal de {user}?", + "confirm_user_pin_code_reset": "EstÃĄ seguro de que quere restablecer o PIN 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.", + "exclusion_pattern_description": "Os patrÃŗns de exclusiÃŗn permítenlle ignorar ficheiros e cartafoles ao escanear a sÃēa biblioteca. Isto Ê Ãētil se ten cartafoles que conteÃąen ficheiros que non quere importar, como ficheiros RAW.", "external_library_management": "XestiÃŗn da biblioteca externa", "face_detection": "DetecciÃŗn de caras", "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.", + "force_delete_user_warning": "AVISO: Isto eliminarÃĄ inmediatamente o usuario e todos os seus activos. Esta acciÃŗn non se pode desfacer e os ficheiros non se poderÃĄn recuperar.", "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_quality_description": "Calidade da imaxe a tamaÃąo completo de 1 a 100. Canto 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_embedded_preview_setting_description": "Usar vistas previas incrustadas en fotos RAW como entrada para o procesamento de imaxes 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 de cores 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_quality_description": "Calidade da vista previa de 1 a 100. Canto 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", @@ -85,11 +99,11 @@ "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_quality_description": "Calidade da miniatura de 1 a 100. Canto 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_not_concurrency_safe": "Este traballo non Ê seguro para execuciÃŗn concorrente.", "job_settings": "ConfiguraciÃŗn de traballos", "job_settings_description": "Xestionar a concorrencia de traballos", "job_status": "Estado do traballo", @@ -104,24 +118,31 @@ "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_enable_description": "Vixiar bibliotecas externas para detectar 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_availability_checks": "ComprobaciÃŗns de dispoÃąibilidade", + "machine_learning_availability_checks_description": "Detectar automaticamente e preferir servidores de aprendizaxe automÃĄtica dispoÃąibles", + "machine_learning_availability_checks_enabled": "Activar comprobaciÃŗns de dispoÃąibilidade", + "machine_learning_availability_checks_interval": "Intervalo de comprobaciÃŗn", + "machine_learning_availability_checks_interval_description": "Intervalo en milisegundos entre comprobaciÃŗns de dispoÃąibilidade", + "machine_learning_availability_checks_timeout": "Tempo de espera da solicitude", + "machine_learning_availability_checks_timeout_description": "Tempo de espera en milisegundos para as comprobaciÃŗns de dispoÃąibilidade", "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_clip_model_description": "O nome dun modelo CLIP listado aquí. TeÃąa 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_enabled_description": "Se estÃĄ desactivado, os activos exactamente idÊnticos aínda se eliminarÃĄn.", "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_enabled_description": "Se estÃĄ desactivado, todas as funciÃŗns de aprendizaxe automÃĄtica 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_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 debe 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", @@ -164,12 +185,26 @@ "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", + "nightly_tasks_cluster_faces_setting_description": "Executar recoÃąecemento facial nas novas caras detectadas", + "nightly_tasks_cluster_new_faces_setting": "Agrupar novas caras", + "nightly_tasks_database_cleanup_setting": "Tarefas de limpeza da base de datos", + "nightly_tasks_database_cleanup_setting_description": "Limpar informaciÃŗn vella e obsoleta da base de datos", + "nightly_tasks_generate_memories_setting": "Xerar recordos", + "nightly_tasks_generate_memories_setting_description": "Crear novos recordos a partir dos activos", + "nightly_tasks_missing_thumbnails_setting": "Xerar as miniaturas que faltan", + "nightly_tasks_missing_thumbnails_setting_description": "PoÃąer en cola os arquivos sen miniaturas para a sÃēa xeraciÃŗn", + "nightly_tasks_settings": "ConfiguraciÃŗn das tarefas nocturnas", + "nightly_tasks_settings_description": "Administrar as tarefas nocturnas", + "nightly_tasks_start_time_setting": "Hora de inicio", + "nightly_tasks_start_time_setting_description": "A hora na que o servidor comeza a executar as tarefas nocturnas", + "nightly_tasks_sync_quota_usage_setting": "Sincronizar uso de cota", + "nightly_tasks_sync_quota_usage_setting_description": "Actualizar a cota de almacenamento do usuario, en base ao uso actual", "no_paths_added": "Non se engadiron rutas", - "no_pattern_added": "Non se engadiu ningÃēn padrÃŗn", + "no_pattern_added": "Non se engadiu ningÃēn patrÃŗ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_from_address_description": "Enderezo de correo do remitente, por exemplo: \"Servidor de Fotos Immich noreply@exemplo.com\". AsegÃērese de empregar un enderezo dende o que teÃąa permiso para enviar correos.", "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 do certificado TLS (non recomendado)", @@ -178,8 +213,8 @@ "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_test_email_failed": "Erro ao enviar correo de proba, comprobe os seus valores", + "notification_email_test_email_sent": "Enviouse un correo electrÃŗnico de proba a {email}. Por favor, comprobe a sÃē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", @@ -189,10 +224,13 @@ "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_secret_description": "Requirido se o provedor OAuth non admite PKCE (Proof Key for Code Exchange)", "oauth_enable_description": "Iniciar sesiÃŗn con OAuth", "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_role_claim": "DeclaraciÃŗn de rol", + "oauth_role_claim_description": "Conceder acceso de administrador automaticamente segundo a presenza desta declaraciÃŗn. A declaraciÃŗn pode ter os valores 'user' ou 'admin'.", "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.", @@ -201,7 +239,9 @@ "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).", + "oauth_storage_quota_default_description": "Cota en GiB a empregar cando non se proporciona ningunha declaraciÃŗn.", + "oauth_timeout": "Tempo mÃĄximo de espera da solicitude", + "oauth_timeout_description": "Tempo mÃĄximo de espera para as solicitudes en milisegundos", "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", @@ -210,17 +250,17 @@ "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.", + "registration_description": "Dado que vostede Ê o primeiro usuario no sistema, asignarÃĄselle como Administrador e serÃĄ responsable das tarefas administrativas. Os usuarios adicionais serÃĄn creados por vostede.", "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", + "reset_settings_to_recent_saved": "Restablecer ÃĄ 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_public_users_description": "Todos os usuarios (nome e correo electrÃŗnico) lístanse 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", @@ -233,19 +273,20 @@ "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_hash_verification_enabled_description": "Activa a verificaciÃŗn de hash. Non desactive isto a menos que estea 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_v2": "Cando estÃĄ activada, esta funciÃŗn organizarÃĄ automaticamente os ficheiros segundo un modelo definido polo usuario. Para 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_available_tags": "Pode usar as seguintes variables no seu 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", @@ -253,15 +294,15 @@ "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.", + "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_custom_css_settings_description": "As Follas de Estilo en Cascada (CSS) 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", "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_api_description": "A API que interactuarÃĄ co seu 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 seu 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)", @@ -276,16 +317,16 @@ "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_codecs_learn_more": "Para saber mÃĄis sobre a terminoloxía usada aquí, consulte a documentaciÃŗn de FFmpeg para o cÃŗdec H.264, o cÃŗdec HEVC e o 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_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. Canto 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_acceleration_description": "Experimental: transcodificaciÃŗn mÃĄis rÃĄpida, pero pode reducir a calidade ao 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_max_b_frames": "MÃĄximo de B-frames", @@ -317,7 +358,7 @@ "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_two_pass_encoding_setting_description": "Transcodificar en dous pasos para producir vídeos codificados de mellor calidade. 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", @@ -325,6 +366,9 @@ "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", + "unlink_all_oauth_accounts": "Desvincular todas as contas OAuth", + "unlink_all_oauth_accounts_description": "Lembre desvincular todas as contas OAuth antes de migrar a un novo provedor.", + "unlink_all_oauth_accounts_prompt": "EstÃĄ seguro de que quere desvincular todas as contas OAuth? Isto reiniciarÃĄ o ID de OAuth de cada usuario e non se poderÃĄ desfacer.", "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", @@ -351,13 +395,15 @@ "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_subtitle": "Use esta opciÃŗn para filtrar medios durante a sincronizaciÃŗn baseÃĄndose en criterios alternativos. SÃŗ probe isto se ten problemas coa aplicaciÃŗn para detectar 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: {level}", - "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_subtitle": "AlgÃēns dispositivos tardan moito en cargar as miniaturas de ficheiros locais. Active esta opciÃŗ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_readonly_mode_subtitle": "Activa o modo de sÃŗ lectura, no que as fotos sÃŗ se poden visualizar; opciÃŗns como seleccionar varias imaxes, compartir, enviar a outros dispositivos ou eliminar estÃĄn deshabilitadas. Active/desactive o modo de sÃŗ lectura a travÊs do avatar do usuario na pantalla principal", + "advanced_settings_readonly_mode_title": "Modo de sÃŗ lectura", "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", @@ -365,32 +411,35 @@ "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 #}}", + "age_months": "Idade: {months, plural, one {# mes} other {# meses}}", + "age_year_months": "Idade: 1 ano e {months, plural, one {# mes} other {# meses}}", + "age_years": "Idade: {years, plural, one {# ano} other {# anos}}", "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_added_notification_setting_description": "Recibir unha notificaciÃŗn por correo electrÃŗnico cando sexa 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": "EstÃĄ seguro de que quere eliminar o ÃĄlbum {album}?", "album_delete_confirmation_description": "Se este ÃĄlbum estÃĄ compartido, outros usuarios non poderÃĄn acceder a el.", + "album_deleted": "Álbum eliminado", "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_leave_confirmation": "EstÃĄ seguro de que quere 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_remove_user_confirmation": "EstÃĄ seguro de que quere eliminar a {user}?", + "album_search_not_found": "Non se atoparon ÃĄlbums que coincidan coa sÃēa busca", + "album_share_no_users": "Parece que compartiu este ÃĄlbum con todos os usuarios ou non ten ningÃēn usuario co que compartir.", + "album_summary": "Resumo do ÃĄlbum", "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_user_removed": "Eliminouse a {user}", + "album_viewer_appbar_delete_confirm": "EstÃĄ seguro de que quere eliminar este ÃĄlbum da sÃē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_remove": "Houbo 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", @@ -398,6 +447,10 @@ "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}}", + "albums_default_sort_order": "Orde de clasificaciÃŗn predeterminada do ÃĄlbum", + "albums_default_sort_order_description": "Orde inicial dos ficheiros ao crear novos ÃĄlbums.", + "albums_feature_description": "ColecciÃŗns de ficheiros que se poden compartir con outros usuarios.", + "albums_on_device_count": "Álbums no dispositivo ({count})", "all": "Todo", "all_albums": "Todos os ÃĄlbums", "all_people": "Todas as persoas", @@ -412,12 +465,14 @@ "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_content": "EstÃĄ seguro de que quere 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", + "apply_count": "Aplicar ({count, number})", "archive": "Arquivo", + "archive_action_prompt": "{count} engadido(s) ao Arquivo", "archive_or_unarchive_photo": "Arquivar ou desarquivar foto", "archive_page_no_archived_assets": "Non se atoparon activos arquivados", "archive_page_title": "Arquivo ({count})", @@ -426,14 +481,14 @@ "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?", + "are_you_sure_to_do_this": "EstÃĄ seguro de que quere 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_has_unassigned_faces": "O activo ten caras sen asignar", "asset_hashing": "Calculando hashâ€Ļ", "asset_list_group_by_sub_title": "Agrupar por", "asset_list_layout_settings_dynamic_layout_title": "DeseÃąo dinÃĄmico", @@ -444,59 +499,71 @@ "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_offline_description": "Este activo externo xa non se atopa no disco. Por favor, contacte co seu administrador de Immich para obter axuda.", "asset_restored_successfully": "Activo restaurado correctamente", "asset_skipped": "Omitido", "asset_skipped_in_trash": "No lixo", + "asset_trashed": "Ficheiro enviado ao lixo", + "asset_troubleshoot": "SoluciÃŗn de problemas do ficheiro", "asset_uploaded": "Subido", "asset_uploading": "Subindoâ€Ļ", - "asset_viewer_settings_subtitle": "Xestionar a tÃēa configuraciÃŗn do visor da galería", + "asset_viewer_settings_subtitle": "Xestionar a sÃē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_albums_count": "Engadido {assetTotal, plural, one {# ficheiro} other {# ficheiros}} a {albumTotal, plural, one {# ÃĄlbum} other {# ÃĄlbums}}", + "assets_cannot_be_added_to_album_count": "{count, plural, one {O ficheiro non se pode engadir} other {Os ficheiros non se poden engadir}} ao ÃĄlbum", + "assets_cannot_be_added_to_albums": "{count, plural, one {O ficheiro non se pode engadir} other {Os ficheiros non se poden engadir}} a ningÃēn dos ÃĄlbums", "assets_count": "{count, plural, one {# activo} other {# activos}}", "assets_deleted_permanently": "{count} activo(s) eliminado(s) permanentemente", "assets_deleted_permanently_from_server": "{count} activo(s) eliminado(s) permanentemente do servidor Immich", + "assets_downloaded_failed": "{count, plural, one {Descargouse # ficheiro - fallou 1 ficheiro} other {DescargÃĄronse # ficheiros - fallaron {error} ficheiros}}", + "assets_downloaded_successfully": "{count, plural, one {Descargouse # ficheiro correctamente} other {DescargÃĄronse # ficheiros correctamente}}", "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": "{count} 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_removed_permanently_from_device": "{count} activo(s) eliminado(s) permanentemente do seu dispositivo", + "assets_restore_confirmation": "EstÃĄ seguro de que quere restaurar todos os activos no lixo? Non pode desfacer esta acciÃŗn! TeÃąa 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": "{count} activo(s) restaurado(s) correctamente", "assets_trashed": "{count} activo(s) movido(s) ao lixo", "assets_trashed_count": "Movido {count, plural, one {# activo} other {# activos}} ao lixo", "assets_trashed_from_server": "{count} 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", + "assets_were_part_of_albums_count": "{count, plural, one {O ficheiro xa estaba} other {Os ficheiros xa estaban}} neses ÃĄlbums", "authorized_devices": "Dispositivos Autorizados", "automatic_endpoint_switching_subtitle": "Conectar localmente a travÊs da wifi designada cando estea dispoÃąible e usar conexiÃŗns alternativas noutros lugares", "automatic_endpoint_switching_title": "Cambio automÃĄtico de URL", + "autoplay_slideshow": "ReproduciÃŗn automÃĄtica da presentaciÃŗn", "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 wifi", + "background_backup_running_error": "A copia de seguridade en segundo plano estÃĄ en curso, non se pode iniciar unha copia manual", + "background_location_permission": "Permiso de localizaciÃŗn en segundo plano", + "background_location_permission_content": "Para cambiar de rede cando se executa en segundo plano, Immich debe ter *sempre* acceso ÃĄ localizaciÃŗn precisa para que a aplicaciÃŗn poida ler o nome da rede wifi", + "background_options": "OpciÃŗns en segundo plano", "backup": "Copia de Seguridade", "backup_album_selection_page_albums_device": "Álbums no dispositivo ({count})", "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_assets_scatter": "Os activos poden estar dispersos 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_albums_sync": "SincronizaciÃŗn de ÃĄlbums da copia de seguridade", "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 {filename}", "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_in_progress_notification": "Facendo copia de seguridade dos seus activosâ€Ļ", "backup_background_service_upload_failure_notification": "Erro ao subir {filename}", "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_link": "MÃŗstreme como", + "backup_controller_page_background_battery_info_message": "Para a mellor experiencia de copia de seguridade en segundo plano, desactive 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 seu 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", @@ -532,29 +599,35 @@ "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_error_sync_failed": "A sincronizaciÃŗn fallou. Non se pode procesar a copia de seguridade.", "backup_info_card_assets": "activos", "backup_manual_cancelled": "Cancelado", - "backup_manual_in_progress": "Subida xa en progreso. Intenta despois dun tempo", + "backup_manual_in_progress": "Subida xa en progreso. IntÊnteo despois dun tempo", "backup_manual_success": "Éxito", "backup_manual_title": "Estado da subida", + "backup_options": "OpciÃŗns de copia de seguridade", "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", + "backup_settings_subtitle": "Xestionar configuraciÃŗn de subidas", "backward": "AtrÃĄs", "biometric_auth_enabled": "AutenticaciÃŗn biomÊtrica activada", + "biometric_locked_out": "EstÃĄ bloqueado da autenticaciÃŗn biomÊtrica", + "biometric_no_options": "Non hai opciÃŗns biomÊtricas dispoÃąibles", + "biometric_not_available": "A autenticaciÃŗn biomÊtrica non estÃĄ dispoÃąible neste dispositivo", "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", + "bulk_delete_duplicates_confirmation": "EstÃĄ seguro de que quere 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ÃĄ seguro de que quere conservar {count, plural, one {# activo duplicado} other {# activos duplicados}}? Isto resolverÃĄ todos os grupos duplicados sen eliminar nada.", + "bulk_trash_duplicates_confirmation": "EstÃĄ seguro de que quere 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": "Apoiar Immich", "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_subtitle": "Fotos e vídeos que a aplicaciÃŗn ten na lista de ignorados", "cache_settings_duplicated_assets_title": "Activos Duplicados ({count})", "cache_settings_statistics_album": "Miniaturas da biblioteca", "cache_settings_statistics_full": "Imaxes completas", @@ -571,24 +644,31 @@ "cancel": "Cancelar", "cancel_search": "Cancelar busca", "canceled": "Cancelado", + "canceling": "Cancelando", "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", + "cast": "Enviar a dispositivo", + "cast_description": "Configurar destinos dispoÃąibles para enviar a dispositivo", "change_date": "Cambiar data", + "change_description": "Cambiar descriciÃŗn", "change_display_order": "Cambiar orde de visualizaciÃŗn", "change_expiration_time": "Cambiar hora de caducidade", - "change_location": "Cambiar ubicaciÃŗn", + "change_location": "Cambiar localizaciÃŗ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_description": "Esta Ê a primeira vez que inicia sesiÃŗn no sistema ou solicitouse un cambio do seu 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_description": "Ola {name},\n\nEsta Ê a primeira vez que inicia sesiÃŗn no sistema ou solicitouse un cambio do seu 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", + "change_pin_code": "Cambiar cÃŗdigo PIN", + "change_your_password": "Cambiar o seu contrasinal", "changed_visibility_successfully": "Visibilidade cambiada correctamente", + "charging": "Cargando", + "charging_requirement_mobile_backup": "A copia de seguridade en segundo plano require que o dispositivo estea cargando", "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 da wifi e unha vez que todos os activos teÃąan copia de seguridade. O procedemento pode tardar uns minutos.", @@ -598,6 +678,7 @@ "clear": "Limpar", "clear_all": "Limpar todo", "clear_all_recent_searches": "Limpar todas as buscas recentes", + "clear_file_cache": "Limpar cachÊ de ficheiros", "clear_message": "Limpar mensaxe", "clear_value": "Limpar valor", "client_cert_dialog_msg_confirm": "Aceptar", @@ -619,21 +700,26 @@ "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.", + "common_server_error": "Por favor, comprobe a sÃēa conexiÃŗn de rede, asegÃērese 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_delete_face": "EstÃĄ seguro de que quere eliminar a cara de {name} do activo?", + "confirm_delete_shared_link": "EstÃĄ seguro de que quere eliminar esta ligazÃŗn compartida?", + "confirm_keep_this_delete_others": "Todos os demais activos na pila eliminaranse excepto este activo. EstÃĄ seguro de que quere continuar?", + "confirm_new_pin_code": "Confirmar novo cÃŗdigo PIN", "confirm_password": "Confirmar contrasinal", + "confirm_tag_face": "Quere etiquetar esta cara como {name}?", + "confirm_tag_face_unnamed": "Quere etiquetar esta cara?", + "connected_device": "Dispositivo conectado", + "connected_to": "Conectado a", "contain": "Conter", "context": "Contexto", "continue": "Continuar", "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_location": "Editar localizaciÃŗ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", @@ -663,19 +749,25 @@ "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_shared_link": "Crear ligazÃŗn compartida", "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", + "created_at": "Creado", + "creating_linked_albums": "Creando ÃĄlbums vinculados...", "crop": "Recortar", "curated_object_page_title": "Cousas", "current_device": "Dispositivo actual", + "current_pin_code": "CÃŗdigo PIN 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", + "custom_url": "URL personalizada", "daily_title_text_date": "E, dd MMM", "daily_title_text_date_year": "E, dd MMM, yyyy", "dark": "Escuro", + "dark_theme": "Alternar tema escuro", "date_after": "Data posterior a", "date_and_time": "Data e Hora", "date_before": "Data anterior a", @@ -683,45 +775,54 @@ "date_of_birth_saved": "Data de nacemento gardada correctamente", "date_range": "Rango de datas", "day": "Día", - "deduplicate_all": "Eliminar Duplicados Todos", + "days": "Días", + "deduplicate_all": "Eliminar todos os duplicados", "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", + "default_locale_description": "Formatar datas e nÃēmeros baseÃĄndose na configuraciÃŗn rexional do seu navegador", "delete": "Eliminar", + "delete_action_confirmation_message": "EstÃĄ seguro de que quere eliminar este ficheiro? Esta acciÃŗn moverÃĄ o ficheiro ao lixo do servidor e preguntaralle se tamÊn quere eliminalo localmente", + "delete_action_prompt": "{count} eliminado(s)", "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_api_key_prompt": "EstÃĄ seguro de que quere eliminar esta chave API?", + "delete_dialog_alert": "Estes elementos eliminaranse permanentemente de Immich e do seu dispositivo", + "delete_dialog_alert_local": "Estes elementos eliminaranse permanentemente do seu 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 seu 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_duplicates_confirmation": "EstÃĄ seguro de que quere eliminar permanentemente estes duplicados?", "delete_face": "Eliminar cara", "delete_key": "Eliminar chave", "delete_library": "Eliminar Biblioteca", "delete_link": "Eliminar ligazÃŗn", + "delete_local_action_prompt": "{count} eliminado(s) localmente", "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_permanently": "Eliminar permanentemente", + "delete_permanently_action_prompt": "{count} eliminado(s) permanentemente", "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_tag_confirmation_prompt": "EstÃĄ seguro de que quere 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", + "deselect_all": "Deseleccionar todo", "details": "Detalles", "direction": "DirecciÃŗn", "disabled": "Desactivado", "disallow_edits": "Non permitir ediciÃŗns", + "discord": "Discord", "discover": "Descubrir", + "discovered_devices": "Dispositivos descubertos", "dismiss_all_errors": "Descartar todos os erros", "dismiss_error": "Descartar erro", "display_options": "OpciÃŗns de visualizaciÃŗn", @@ -732,6 +833,7 @@ "documentation": "DocumentaciÃŗn", "done": "Feito", "download": "Descargar", + "download_action_prompt": "Descargando {count} activo(s)", "download_canceled": "Descarga cancelada", "download_complete": "Descarga completada", "download_enqueue": "Descarga en cola", @@ -758,40 +860,56 @@ "edit": "Editar", "edit_album": "Editar ÃĄlbum", "edit_avatar": "Editar avatar", + "edit_birthday": "Editar aniversario", "edit_date": "Editar data", "edit_date_and_time": "Editar data e hora", - "edit_exclusion_pattern": "Editar padrÃŗn de exclusiÃŗn", + "edit_date_and_time_action_prompt": "{count} data(s) e hora(s) editada(s)", + "edit_date_and_time_by_offset": "Cambiar data por desfase", + "edit_date_and_time_by_offset_interval": "Nova franxa de datas: {from} - {to}", + "edit_description": "Editar descriciÃŗn", + "edit_description_prompt": "Por favor, seleccione unha nova descriciÃŗn:", + "edit_exclusion_pattern": "Editar patrÃŗ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_location": "Editar localizaciÃŗn", + "edit_location_action_prompt": "{count} localizaciÃŗn(s) editada(s)", + "edit_location_dialog_title": "LocalizaciÃŗ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", + "email_notifications": "NotificaciÃŗns por 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!", + "empty_trash_confirmation": "EstÃĄ seguro de que quere baleirar o lixo? Isto eliminarÃĄ permanentemente todos os activos no lixo de Immich. Non pode desfacer esta acciÃŗn!", "enable": "Activar", + "enable_backup": "Activar copia de seguridade", + "enable_biometric_auth_description": "Introduza o seu cÃŗdigo PIN para activar a autenticaciÃŗn biomÊtrica", "enabled": "Activado", "end_date": "Data de fin", "enqueued": "En cola", "enter_wifi_name": "Introducir nome da wifi", + "enter_your_pin_code": "Introduza o seu cÃŗdigo PIN", + "enter_your_pin_code_subtitle": "Introduza o seu cÃŗdigo PIN para acceder ao cartafol bloqueado", "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_getting_places": "Erro ao obter lugares", "error_loading_image": "Erro ao cargar a imaxe", + "error_loading_partners": "Erro cargando compaÃąeiros/as: {error}", "error_saving_image": "Erro: {error}", + "error_tag_face_bounding_box": "Erro ao etiquetar cara - non se poden obter as coordenadas da caixa delimitadora", "error_title": "Erro - Algo saíu mal", "errors": { "cannot_navigate_next_asset": "Non se pode navegar ao seguinte activo", @@ -808,10 +926,10 @@ "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_hiding_buy_button": "Erro ao ocultar o botÃŗn de apoio", "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.", + "exclusion_pattern_already_exists": "Este patrÃŗn de exclusiÃŗn xa existe.", "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", @@ -822,6 +940,7 @@ "failed_to_load_notifications": "Erro ao cargar as notificaciÃŗns", "failed_to_load_people": "Erro ao cargar persoas", "failed_to_remove_product_key": "Erro ao eliminar a chave do produto", + "failed_to_reset_pin_code": "Erro ao restablecer o cÃŗdigo PIN", "failed_to_stack_assets": "Erro ao apilar activos", "failed_to_unstack_assets": "Erro ao desapilar activos", "failed_to_update_notification_status": "Erro ao actualizar o estado das notificaciÃŗns", @@ -830,10 +949,11 @@ "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", + "something_went_wrong": "Algo fallou", "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_exclusion_pattern": "Non se puido engadir o patrÃŗ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", @@ -841,13 +961,14 @@ "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_description": "Non se puido cambiar a descriciÃŗn", "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_location": "Non se puido cambiar a localizaciÃŗ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_copy_to_clipboard": "Non se puido copiar ao portapapeis, asegÃērate de acceder ÃĄ pÃĄxina a travÊs de https", + "unable_to_copy_to_clipboard": "Non se puido copiar ao portapapeis, asegÃērese 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", @@ -855,12 +976,12 @@ "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_exclusion_pattern": "Non se puido eliminar o patrÃŗ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_exclusion_pattern": "Non se puido editar o patrÃŗ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", @@ -884,6 +1005,7 @@ "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_reset_password": "Non se puido restablecer o contrasinal", + "unable_to_reset_pin_code": "Non Ê posible reiniciar o cÃŗdigo PIN", "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", @@ -905,22 +1027,25 @@ "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_location": "Non se puido actualizar a localizaciÃŗ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_description_error": "Erro ao actualizar a descriciÃŗn", "exif_bottom_sheet_details": "DETALLES", - "exif_bottom_sheet_location": "UBICACIÓN", + "exif_bottom_sheet_location": "LOCALIZACIÓN", "exif_bottom_sheet_people": "PERSOAS", "exif_bottom_sheet_person_add_person": "Engadir nome", "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_subtitle": "Use baixo o seu propio risco!", + "experimental_settings_title": "Experimental", "expire_after": "Caduca despois de", "expired": "Caducado", "expires_date": "Caduca o {date}", @@ -928,6 +1053,8 @@ "explorer": "Explorador", "export": "Exportar", "export_as_json": "Exportar como JSON", + "export_database": "Exportar a Base de Datos", + "export_database_description": "Exportar a base de datos SQLite", "extension": "ExtensiÃŗn", "external": "Externo", "external_libraries": "Bibliotecas Externas", @@ -935,14 +1062,17 @@ "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_authenticate": "Fallou a autenticaciÃŗn", "failed_to_load_assets": "Erro ao cargar activos", "failed_to_load_folder": "Erro ao cargar o cartafol", "favorite": "Favorito", + "favorite_action_prompt": "{count} engadido/a a Favoritos", "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_in_development": "Funcionalidades en Desenvolvemento", "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", @@ -951,20 +1081,27 @@ "filter": "Filtro", "filter_people": "Filtrar persoas", "filter_places": "Filtrar lugares", - "find_them_fast": "AtÃŗpaos rÃĄpido por nome coa busca", + "find_them_fast": "AtÃŗpeos rÃĄpido por nome coa busca", + "first": "Primeiro/a", "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", + "forgot_pin_code_question": "Esqueceu o seu PIN?", "forward": "Adiante", + "gcast_enabled": "Google Cast", + "gcast_enabled_description": "Esta funcionalidade carga recursos externos de Google para poder funcionar.", "general": "Xeral", + "geolocation_instruction_location": "Prema nun recurso con coordenadas GPS para usar a sÃēa localizaciÃŗn, ou seleccione unha localizaciÃŗn directamente no mapa", "get_help": "Obter Axuda", - "get_wifiname_error": "Non se puido obter o nome da wifi. AsegÃērate de que concedeu os permisos necesarios e estÃĄ conectado a unha rede wifi", + "get_wifiname_error": "Non se puido obter o nome da wifi. AsegÃērese de que concedeu os permisos necesarios e estÃĄ conectado a unha rede wifi", "getting_started": "Primeiros Pasos", "go_back": "Volver", "go_to_folder": "Ir ao cartafol", "go_to_search": "Ir ÃĄ busca", + "gps": "GPS", + "gps_missing": "Sen GPS", "grant_permission": "Conceder permiso", "group_albums_by": "Agrupar ÃĄlbums por...", "group_country": "Agrupar por país", @@ -975,6 +1112,9 @@ "haptic_feedback_switch": "Activar resposta hÃĄptica", "haptic_feedback_title": "Resposta HÃĄptica", "has_quota": "Ten cota", + "hash_asset": "Facer hash do recurso", + "hashed_assets": "Recursos cun hash", + "hashing": "Aplicando hash", "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", @@ -984,7 +1124,7 @@ "hi_user": "Ola {name} ({email})", "hide_all_people": "Ocultar todas as persoas", "hide_gallery": "Ocultar galería", - "hide_named_person": "Ocultar persoa {name}", + "hide_named_person": "Ocultar a persoa {name}", "hide_password": "Ocultar contrasinal", "hide_person": "Ocultar persoa", "hide_unnamed_people": "Ocultar persoas sen nome", @@ -999,10 +1139,16 @@ "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_first_time_notice": "Se esta Ê a primeira vez que usa a aplicaciÃŗn, asegÃērese 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_locked_error_local": "Non Ê posíbel mover os recursos locais ao cartafol bloqueado, saltando", + "home_page_locked_error_partner": "Non Ê posíbel mover os recursos do/a colaborador/a ao cartafol bloqueado, saltando", "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": "Servidor", "hour": "Hora", + "hours": "Horas", + "id": "ID", + "idle": "Inactivo/a", "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", @@ -1030,7 +1176,7 @@ "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", + "individual_shares": "ComparticiÃŗns individuais", "info": "InformaciÃŗn", "interval": { "day_at_onepm": "Todos os días ÃĄs 13:00", @@ -1042,6 +1188,12 @@ "invalid_date_format": "Formato de data invÃĄlido", "invite_people": "Invitar Persoas", "invite_to_album": "Invitar ao ÃĄlbum", + "ios_debug_info_fetch_ran_at": "Obtívose ÃĄs {dateTime}", + "ios_debug_info_last_sync_at": "Última sincronizaciÃŗn: {dateTime}", + "ios_debug_info_no_processes_queued": "Sen procesos en segundo plano en cola", + "ios_debug_info_no_sync_yet": "Aínda non se executou ningunha tarefa de sincronizaciÃŗn en segundo plano", + "ios_debug_info_processes_queued": "{count, plural, one {{count} proceso en segundo plano en cola} other {{count} procesos en segundo plano en cola}}", + "ios_debug_info_processing_ran_at": "O procesamento executouse ÃĄs {dateTime}", "items_count": "{count, plural, one {# elemento} other {# elementos}}", "jobs": "Traballos", "keep": "Conservar", @@ -1050,10 +1202,17 @@ "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", + "language_no_results_subtitle": "Probe axustar o seu termo de busca", + "language_no_results_title": "Non se atopou ningunha lingua", + "language_search_hint": "Buscar linguas...", + "language_setting_description": "Seleccione a sÃēa lingua preferida", + "large_files": "Ficheiros Grandes", + "last": "Último/a", "last_seen": "Visto por Ãēltima vez", "latest_version": "Última VersiÃŗn", + "latitude": "Latitude", "leave": "Saír", + "leave_album": "Deixar o ÃĄlbum", "lens_model": "Modelo da lente", "let_others_respond": "Permitir que outros respondan", "level": "Nivel", @@ -1065,7 +1224,9 @@ "library_page_sort_created": "Data de creaciÃŗn", "library_page_sort_last_modified": "Última modificaciÃŗn", "library_page_sort_title": "Título do ÃĄlbum", + "licenses": "Licenzas", "light": "Claro", + "like": "GÃēstame", "like_deleted": "GÃēstame eliminado", "link_motion_video": "Ligar vídeo en movemento", "link_to_oauth": "Ligar a OAuth", @@ -1073,25 +1234,33 @@ "list": "Lista", "loading": "Cargando", "loading_search_results_failed": "Erro ao cargar os resultados da busca", + "local": "Local", + "local_asset_cast_failed": "Non Ê posíbel proxectar un recurso que non estÃĄ cargado no servidor", + "local_assets": "Recursos Locais", + "local_media_summary": "Resumo de Contido Local", "local_network": "Rede local", "local_network_sheet_info": "A aplicaciÃŗn conectarase ao servidor a travÊs desta URL cando use a rede wifi 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_permission": "Permiso de localizaciÃŗn", + "location_permission_content": "Para usar a funciÃŗn de cambio automÃĄtico, Immich necesita permiso de localizaciÃŗ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_latitude_hint": "Introduza a sÃēa latitude aquí", "location_picker_longitude_error": "Introducir unha lonxitude vÃĄlida", - "location_picker_longitude_hint": "Introduza a tÃēa lonxitude aquí", + "location_picker_longitude_hint": "Introduza a sÃēa lonxitude aquí", + "lock": "Bloquear", + "locked_folder": "Cartafol Bloqueado", + "log_detail_title": "Detalle do Rexistro", "log_out": "Pechar sesiÃŗn", "log_out_all_devices": "Pechar SesiÃŗn en Todos os Dispositivos", + "logged_in_as": "SesiÃŗn iniciada como {user}", "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_email_hint": "oseuemail@dominio.com", + "login_form_endpoint_hint": "http://ip-do-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", @@ -1100,42 +1269,44 @@ "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_failed_login": "Erro ao iniciar sesiÃŗn, comprobe a URL do servidor, correo electrÃŗnico e contrasinal", + "login_form_handshake_exception": "Houbo unha ExcepciÃŗn de Handshake co servidor. Active o soporte para certificados autofirmados nas configuraciÃŗns se estÃĄ 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_error": "Houbo un erro ao actualizar o seu 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?", + "logout_all_device_confirmation": "EstÃĄ seguro de que quere pechar sesiÃŗn en todos os dispositivos?", + "logout_this_device_confirmation": "EstÃĄ seguro de que quere pechar sesiÃŗn neste dispositivo?", + "logs": "Rexistros", "longitude": "Lonxitude", - "look": "Ollar", + "look": "Aspecto", "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_geolocation": "Xestionar a localizaciÃŗn", "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", + "manage_your_account": "Xestionar a sÃēa conta", + "manage_your_api_keys": "Xestionar as sÃēas claves API", + "manage_your_devices": "Xestionar os seus dispositivos con sesiÃŗn iniciada", + "manage_your_oauth_connection": "Xestionar a sÃēa conexiÃŗn OAuth", "map": "Mapa", - "map_assets_in_bounds": "{count} fotos", - "map_cannot_get_user_location": "Non se pode obter a ubicaciÃŗn do usuario", + "map_assets_in_bounds": "{count, plural, =0 {Sen fotos nesta ÃĄrea} one {# foto} other {# fotos}}", + "map_cannot_get_user_location": "Non se pode obter a localizaciÃŗ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_location_picker_page_use_location": "Usar esta localizaciÃŗn", + "map_location_service_disabled_content": "O servizo de localizaciÃŗn debe estar activado para mostrar activos da sÃēa localizaciÃŗn actual. Quere activalo agora?", + "map_location_service_disabled_title": "Servizo de localizaciÃŗ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_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_no_location_permission_content": "Necesítase permiso de localizaciÃŗn para mostrar activos da sÃēa localizaciÃŗn actual. Quere permitilo agora?", + "map_no_location_permission_title": "Permiso de localizaciÃŗn denegado", "map_settings": "ConfiguraciÃŗn do mapa", "map_settings_dark_mode": "Modo escuro", "map_settings_date_range_option_day": "Últimas 24 horas", @@ -1147,40 +1318,54 @@ "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", + "map_zoom_to_see_photos": "Afaste o zoom para ver fotos", "mark_all_as_read": "Marcar todo como lido", "mark_as_read": "Marcar como lido", "marked_all_as_read": "Marcado todo como lido", "matches": "Coincidencias", + "matching_assets": "Recursos Correspondentes", "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_setting_description": "Xestionar o que ve nos seus recordos", "memories_start_over": "Comezar de novo", - "memories_swipe_to_close": "Deslizar cara arriba para pechar", + "memories_swipe_to_close": "Deslice cara arriba para pechar", "memory": "Recordo", - "memory_lane_title": "CamiÃąo dos Recordos {title}", + "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_prompt": "Quere 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", + "minutes": "Minutos", "missing": "Faltantes", "model": "Modelo", "month": "Mes", + "monthly_title_text_date_format": "MMMM a", "more": "MÃĄis", + "move": "Mover", + "move_off_locked_folder": "Mover fÃŗra do cartafol bloqueado", + "move_to_lock_folder_action_prompt": "{count} engadido/a ao cartafol bloqueado", + "move_to_locked_folder": "Mover ao cartafol bloqueado", + "move_to_locked_folder_confirmation": "Estas fotos e vídeo eliminaranse de todos os ÃĄlbums e sÃŗ serÃĄn visíbeis dende o cartafol bloqueado", + "moved_to_archive": "Moveuse {count, plural, one {# recurso} other {# recursos}} ao arquivo", + "moved_to_library": "Moveuse {count, plural, one {# recurso} other {# recursos}} ÃĄ biblioteca", "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", + "multiselect_grid_edit_gps_err_read_only": "Non se pode editar a localizaciÃŗ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", + "network_requirement_photos_upload": "Usar datos mÃŗbiles para facer copia de seguridade das fotos", + "network_requirement_videos_upload": "Usar datos mÃŗbiles para facer copia de seguridade dos vídeos", + "network_requirements": "Requisitos de rede", + "network_requirements_updated": "Os requisitos de rede cambiaron, reiniciando cola de copia de seguridade", "networking_settings": "Rede", "networking_subtitle": "Xestionar a configuraciÃŗn do punto final do servidor", "never": "Nunca", @@ -1188,29 +1373,34 @@ "new_api_key": "Nova Chave API", "new_password": "Novo contrasinal", "new_person": "Nova persoa", + "new_pin_code": "Novo cÃŗdigo PIN", + "new_pin_code_subtitle": "Esta Ê a tÃēa primeira vez accedendo ÃĄ carpeta segura. Crea un cÃŗdigo PIN para acceder de maneira segura a esta pÃĄxina", + "new_timeline": "Nova liÃąa de tempo", "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_albums_message": "Cree un ÃĄlbum para organizar as sÃēas fotos e vídeos", + "no_albums_with_name_yet": "Parece que aínda non ten ningÃēn ÃĄlbum con este nome.", + "no_albums_yet": "Parece que aínda non ten ningÃēn ÃĄlbum.", + "no_archived_assets_message": "Arquive fotos e vídeos para ocultalos da sÃē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_cast_devices_found": "Non se atoparon dispositivos de transmisiÃŗn", "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_exif_info_available": "Non hai informaciÃŗn EXIF dispoÃąible", + "no_explore_results_message": "Suba mÃĄis fotos para explorar a sÃēa colecciÃŗn.", + "no_favorites_message": "Engada favoritos para atopar rapidamente as sÃēas mellores fotos e vídeos", + "no_libraries_message": "Cree unha biblioteca externa para ver as sÃēas fotos e vídeos", + "no_local_assets_found": "Non se atoparon elementos locais con esta suma de comprobaciÃŗn", "no_name": "Sen Nome", "no_notifications": "Sen notificaciÃŗns", "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", + "no_results_description": "Probe cun sinÃŗnimo ou palabra chave mÃĄis xeral", + "no_shared_albums_message": "Cree un ÃĄlbum para compartir fotos e vídeos con persoas na sÃē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", @@ -1227,9 +1417,9 @@ "ok": "Aceptar", "oldest_first": "MÃĄis antigos primeiro", "on_this_device": "Neste dispositivo", - "onboarding": "IncorporaciÃŗn", + "onboarding": "Primeiros pasos", "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_theme_description": "Elixa un tema de cor para a sÃēa instancia. Pode cambialo mÃĄis tarde na sÃēa configuraciÃŗn.", "onboarding_welcome_user": "Benvido/a, {user}", "online": "En liÃąa", "only_favorites": "SÃŗ favoritos", @@ -1239,7 +1429,7 @@ "open_the_search_filters": "Abrir os filtros de busca", "options": "OpciÃŗns", "or": "ou", - "organize_your_library": "Organizar a tÃēa biblioteca", + "organize_your_library": "Organizar a sÃēa biblioteca", "original": "orixinal", "other": "Outro", "other_devices": "Outros dispositivos", @@ -1248,8 +1438,8 @@ "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_can_access_assets": "Todas as sÃēas fotos e vídeos excepto os de Arquivo e Eliminados", + "partner_can_access_location": "A localizaciÃŗn onde se tomaron as sÃē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.", @@ -1257,7 +1447,7 @@ "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": "{partner} xa non poderÃĄ acceder ÃĄs tÃēas fotos.", + "partner_page_stop_sharing_content": "{partner} xa non poderÃĄ acceder ÃĄs sÃēas fotos.", "partner_sharing": "ComparticiÃŗn con CompaÃąeiro/a", "partners": "CompaÃąeiros/as", "password": "Contrasinal", @@ -1270,7 +1460,7 @@ "years": "Últimos {years, plural, one {ano} other {# anos}}" }, "path": "Ruta", - "pattern": "PadrÃŗn", + "pattern": "PatrÃŗn", "pause": "Pausa", "pause_memories": "Pausar recordos", "paused": "Pausado", @@ -1283,7 +1473,7 @@ "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_delete_assets_prompt": "EstÃĄ seguro de que quere eliminar permanentemente {count, plural, one {este activo?} other {estes # activos?}} Isto tamÊn {count, plural, one {o eliminarÃĄ do seu} other {os eliminarÃĄ dos seus}} ÃĄ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", @@ -1292,17 +1482,17 @@ "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.", + "permission_onboarding_permission_limited": "Permiso limitado. Para permitir que Immich faga copia de seguridade e xestione toda a sÃē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 sÃē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.", + "photo_shared_all_users": "Parece que compartiu as sÃēas fotos con todos os usuarios ou non ten 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", + "pick_a_location": "Elixir unha localizaciÃŗn", "place": "Lugar", "places": "Lugares", "places_count": "{count, plural, one {{count, number} Lugar} other {{count, number} Lugares}}", @@ -1335,28 +1525,28 @@ "purchase_activated_time": "Activado o {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_buy": "Apoiar", + "purchase_button_buy_immich": "Apoiar 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_failed_activation": "Erro ao activar! Por favor, comprobe o seu 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_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_license_subtitle": "Apoie Immich para contribuír ao desenvolvemento continuado do servizo", + "purchase_lifetime_description": "ContribuciÃŗn vitalicia", + "purchase_option_title": "OPCIÓNS DE APOIO", "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_info_2": "Como estamos comprometidos a non engadir muros de pago, esta contribuciÃŗn non lle outorgarÃĄ ningunha funciÃŗn adicional en Immich. Dependemos de usuarios coma vostede 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_product_key_prompt": "EstÃĄ seguro de que quere 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_remove_server_product_key_prompt": "EstÃĄ seguro de que quere 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", @@ -1376,8 +1566,8 @@ "recent_searches": "Buscas recentes", "recently_added": "Engadido recentemente", "recently_added_page_title": "Engadido Recentemente", - "recently_taken": "Recentemente tomado", - "recently_taken_page_title": "Recentemente Tomado", + "recently_taken": "Tomado recentemente", + "recently_taken_page_title": "Tomado Recentemente", "refresh": "Actualizar", "refresh_encoded_videos": "Actualizar vídeos codificados", "refresh_faces": "Actualizar caras", @@ -1390,8 +1580,8 @@ "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_album_confirmation": "EstÃĄ seguro de que quere eliminar {count, plural, one {# activo} other {# activos}} do ÃĄlbum?", + "remove_assets_shared_link_confirmation": "EstÃĄ seguro de que quere 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", @@ -1437,7 +1627,7 @@ "saved_api_key": "Chave API gardada", "saved_profile": "Perfil gardado", "saved_settings": "ConfiguraciÃŗn gardada", - "say_something": "Dicir algo", + "say_something": "Dicir algo...", "scaffold_body_error_occurred": "Ocorreu un erro", "scan_all_libraries": "Escanear Todas as Bibliotecas", "scan_library": "Escanear", @@ -1462,8 +1652,8 @@ "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_location": "LocalizaciÃŗn", + "search_filter_location_title": "Seleccionar localizaciÃŗn", "search_filter_media_type": "Tipo de Medio", "search_filter_media_type_title": "Seleccionar tipo de medio", "search_filter_people_title": "Seleccionar persoas", @@ -1479,11 +1669,11 @@ "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_search_photos_videos": "Busca as sÃēas fotos e vídeos", "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_page_your_activity": "A sÃēa actividade", + "search_page_your_map": "O seu Mapa", "search_people": "Buscar persoas", "search_places": "Buscar lugares", "search_rating": "Buscar por clasificaciÃŗn...", @@ -1491,11 +1681,11 @@ "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_suggestion_list_smart_search_hint_2": "m:o-seu-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", + "search_your_photos": "Buscar as sÃēas fotos", "searching_locales": "Buscando configuraciÃŗns rexionais...", "second": "Segundo", "see_all_people": "Ver todas as persoas", @@ -1531,7 +1721,7 @@ "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_help": "O visor de detalles carga primeiro a miniatura pequena, despois carga a vista previa de tamaÃąo medio (se estÃĄ activada), e 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.", @@ -1547,11 +1737,11 @@ "setting_notifications_notify_seconds": "{count} 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_subtitle": "Axustar as sÃē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_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 reprodÃē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", @@ -1562,7 +1752,7 @@ "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_content": "Quere 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", @@ -1570,7 +1760,7 @@ "shared_album_section_people_title": "PERSOAS", "shared_by": "Compartido por", "shared_by_user": "Compartido por {user}", - "shared_by_you": "Compartido por ti", + "shared_by_you": "Compartido por vostede", "shared_from_partner": "Fotos de {partner}", "shared_intent_upload_button_progress_text": "{current} / {total} Subidos", "shared_link_app_bar_title": "LigazÃŗns Compartidas", @@ -1588,14 +1778,14 @@ "shared_link_edit_expire_after_option_year": "{count} 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_error_server_url_fetch": "Non se pode obter a URL do servidor", "shared_link_expires_day": "Caduca en {count} día", "shared_link_expires_days": "Caduca en {count} días", "shared_link_expires_hour": "Caduca en {count} hora", "shared_link_expires_hours": "Caduca en {count} horas", "shared_link_expires_minute": "Caduca en {count} minuto", "shared_link_expires_minutes": "Caduca en {count} minutos", - "shared_link_expires_never": "Caduca ∞", + "shared_link_expires_never": "Non caduca", "shared_link_expires_second": "Caduca en {count} segundo", "shared_link_expires_seconds": "Caduca en {count} segundos", "shared_link_individual_shared": "Compartido individualmente", @@ -1609,7 +1799,7 @@ "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_description": "Cree ÃĄlbums compartidos para compartir fotos e vídeos con persoas na sÃē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", @@ -1619,11 +1809,11 @@ "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_file_location": "Mostrar localizaciÃŗ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_in_timeline_setting_description": "Mostrar fotos e vídeos deste usuario na sÃē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", @@ -1666,10 +1856,10 @@ "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", + "stop_photo_sharing": "Deixar de compartir as sÃēas fotos?", + "stop_photo_sharing_description": "{partner} xa non poderÃĄ acceder ÃĄs sÃēas fotos.", + "stop_sharing_photos_with_user": "Deixar de compartir as sÃēas fotos con este usuario", + "storage": "Almacenamento", "storage_label": "Etiqueta de almacenamento", "storage_usage": "{used} de {available} usado", "submit": "Enviar", @@ -1677,12 +1867,12 @@ "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.", + "support_third_party_description": "A sÃēa instalaciÃŗn de Immich foi empaquetada por un terceiro. Os problemas que experimente poden ser causados por ese paquete, así que por favor, comunique 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", + "sync_upload_album_setting_subtitle": "Crear e subir as sÃēas fotos e vídeos aos ÃĄlbums seleccionados en Immich", "tag": "Etiqueta", "tag_assets": "Etiquetar activos", "tag_created": "Etiqueta creada: {tag}", @@ -1695,8 +1885,8 @@ "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_selection_description": "Establecer automaticamente o tema a claro ou escuro baseÃĄndose na preferencia do sistema do seu navegador", + "theme_setting_asset_list_storage_indicator_title": "Mostrar indicador de almacenamento nas celas de activos", "theme_setting_asset_list_tiles_per_row_title": "NÃēmero de activos por fila ({count})", "theme_setting_colorful_interface_subtitle": "Aplicar cor primaria ÃĄs superficies de fondo.", "theme_setting_colorful_interface_title": "Interface colorida", @@ -1724,12 +1914,12 @@ "total_usage": "Uso total", "trash": "Lixo", "trash_all": "Mover Todo ao Lixo", - "trash_count": "Lixo {count, number}", + "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_empty_trash_dialog_content": "Quere baleirar os seus activos no lixo? Estes elementos eliminaranse permanentemente de Immich", "trash_page_info": "Os elementos no lixo eliminaranse permanentemente despois de {days} días", "trash_page_no_assets": "Non hai activos no lixo", "trash_page_restore_all": "Restaurar Todo", @@ -1750,8 +1940,8 @@ "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", + "unnamed_album_delete_confirmation": "EstÃĄ seguro de que quere eliminar este ÃĄlbum?", + "unnamed_share": "ComparticiÃŗn Sen Nome", "unsaved_change": "Cambio sen gardar", "unselect_all": "Deseleccionar todo", "unselect_all_duplicates": "Deseleccionar todos os duplicados", @@ -1761,25 +1951,29 @@ "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_info": "Quere 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_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_success": "Subida exitosa. Actualice a pÃĄxina para ver os novos activos subidos.", "upload_to_immich": "Subir a Immich ({count})", "uploading": "Subindo", "usage": "Uso", "use_current_connection": "usar conexiÃŗn actual", "use_custom_date_range": "Usar rango de datas personalizado no seu lugar", "user": "Usuario", + "user_has_been_deleted": "Este usuario foi eliminado.", "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_pin_code_settings": "CÃŗdigo PIN", + "user_pin_code_settings_description": "Xestionar seu cÃŗdigo PIN", + "user_privacy": "Privacidade do usuario", + "user_purchase_settings": "ContribuciÃŗn", + "user_purchase_settings_description": "Xestionar a sÃēa contribuciÃŗn", "user_role_set": "Establecer {user} como {role}", "user_usage_detail": "Detalle de uso do usuario", "user_usage_stats": "Estatísticas de uso da conta", @@ -1789,9 +1983,10 @@ "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_message": "Ola! Unha nova versiÃŗn de Immich estÃĄ dispoÃąible. Por favor, tome un tempo para ler as notas de lanzamento para asegurarse de que a sÃēa configuraciÃŗn estÃĄ actualizada para evitar calquera configuraciÃŗn incorrecta, especialmente se usa WatchTower ou calquera mecanismo que xestione a actualizaciÃŗn automÃĄtica da sÃēa instancia de Immich.", "version_history": "Historial de VersiÃŗns", "version_history_item": "Instalado {version} o {date}", "video": "Vídeo", @@ -1803,6 +1998,7 @@ "view_album": "Ver Álbum", "view_all": "Ver Todo", "view_all_users": "Ver todos os usuarios", + "view_details": "Ver detalles", "view_in_timeline": "Ver na liÃąa de tempo", "view_link": "Ver ligazÃŗn", "view_links": "Ver ligazÃŗns", @@ -1824,7 +2020,7 @@ "year": "Ano", "years_ago": "Hai {years, plural, one {# ano} other {# anos}}", "yes": "Si", - "you_dont_have_any_shared_links": "Non tes ningunha ligazÃŗn compartida", - "your_wifi_name": "O nome da tÃēa wifi", + "you_dont_have_any_shared_links": "Non ten ningunha ligazÃŗn compartida", + "your_wifi_name": "O nome da sÃēa wifi", "zoom_image": "Ampliar Imaxe" } diff --git a/i18n/he.json b/i18n/he.json index efebd99564..458062832f 100644 --- a/i18n/he.json +++ b/i18n/he.json @@ -15,7 +15,7 @@ "add_a_name": "הוספ×Ē ×Š×", "add_a_title": "הוספ×Ē ×›×•×Ēר×Ē", "add_birthday": "הוספ×Ē ×™×•× הולד×Ē", - "add_endpoint": "×”×•×Ą×Ŗ נקוד×Ē ×§×Ļה", + "add_endpoint": "×”×•×Ą×Ŗ כ×Ēוב×Ē URL", "add_exclusion_pattern": "הוספ×Ē ×“×¤×•×Ą החרגה", "add_import_path": "הוספ×Ē × ×Ēיב יבוא", "add_location": "הוספ×Ē ×ž×™×§×•×", @@ -28,9 +28,10 @@ "add_to_album": "הוספה לאלבום", "add_to_album_bottom_sheet_added": "× ×•×Ą×Ŗ ל {album}", "add_to_album_bottom_sheet_already_exists": "כבר ב {album}", + "add_to_album_bottom_sheet_some_local_assets": "לא ני×Ēן היה ×œ×”×•×Ą×™×Ŗ חלק מהקב×Ļים המקומיים לאלבום", "add_to_album_toggle": "החלפ×Ē ×ž×Ļב בחירה ×ĸבור {album}", "add_to_albums": "הוספה לאלבומים", - "add_to_albums_count": "Add to albums ({count})", + "add_to_albums_count": "×”×•×Ą×Ŗ ({count}) לאלבום", "add_to_shared_album": "הוספה לאלבום משו×Ē×Ŗ", "add_url": "הוספ×Ē ×§×™×Š×•×¨", "added_to_archive": "× ×•×Ą×Ŗ לארכיון", @@ -123,6 +124,13 @@ "logging_enable_description": "אפ׊ר רישום ביומן", "logging_level_description": "כאשר פו×ĸל, באיזה רמ×Ē ×™×•×ž×Ÿ ל×Ē×ĸד.", "logging_settings": "רישום ביומן", + "machine_learning_availability_checks": "בדיק×Ē ×–×ž×™× ×•×Ē", + "machine_learning_availability_checks_description": "זהה ו×Ē×ĸדת אוטומטי×Ē ×Š×¨×Ēי למיד×Ē ×ž×›×•× ×” זמינים", + "machine_learning_availability_checks_enabled": "הפ×ĸל×Ē ×‘×“×™×§×•×Ē ×–×ž×™× ×•×Ē", + "machine_learning_availability_checks_interval": "×Ēזמון בדיקה", + "machine_learning_availability_checks_interval_description": "מרווח זמן במילישניו×Ē ×‘×™×Ÿ בדיקו×Ē ×–×ž×™× ×•×Ē", + "machine_learning_availability_checks_timeout": "פץק זמן לבקשה", + "machine_learning_availability_checks_timeout_description": "פץק זמן במילישניו×Ē ×ĸבור בדיקו×Ē ×–×ž×™× ×•×Ē", "machine_learning_clip_model": "מודל CLIP", "machine_learning_clip_model_description": "שמו של מודל CLIP רשום כאן. שים לב ׊×ĸליך להפ×ĸיל מחדש א×Ē ×”×ž×Š×™×ž×” 'חיפוש חכם' ×ĸבור כל ה×Ēמונו×Ē ×‘×ĸ×Ē ×Š×™× ×•×™ מודל.", "machine_learning_duplicate_detection": "אי×Ēור כפילויו×Ē", @@ -387,8 +395,6 @@ "admin_password": "סיסמ×Ē ×ž× ×”×œ", "administration": "ניהול", "advanced": "מ×Ēקדם", - "advanced_settings_beta_timeline_subtitle": "נסה א×Ē ×—×•×•×™×Ē ×”××¤×œ×™×§×Ļיה החדשה", - "advanced_settings_beta_timeline_title": "×Ļיר זמן (בטא)", "advanced_settings_enable_alternate_media_filter_subtitle": "הש×Ēמ׊ באפשרו×Ē ×–×• כדי לסנן מדיה במהלך הסנכרון לפי קריטריונים חלופיים. מומל×Ĩ להש×Ēמ׊ בזה רק אם יש ב×ĸיה בזיהוי כל האלבומים באפליק×Ļיה.", "advanced_settings_enable_alternate_media_filter_title": "[ניסיוני] הש×Ēמ׊ במסנן סנכרון אלבום חלופי שמבכשיר", "advanced_settings_log_level_title": "רמ×Ē ×¨×™×Š×•× ביומן: {level}", @@ -398,7 +404,7 @@ "advanced_settings_proxy_headers_title": "כו×Ēרו×Ē ×¤×¨×•×§×Ą×™", "advanced_settings_readonly_mode_subtitle": "מאפ׊ר א×Ē ×ž×Ļב לקריאה בלבד בו ה×Ēמונו×Ē × ×™×Ēנו×Ē ×œ×Ļפייה בלבד, דברים כמו בחיר×Ē ×Ēמונו×Ē ×ž×¨×•×‘×•×Ē, שי×Ēות, שידור, מחיקה הם כולם מושב×Ēים. אפ׊ר/השב×Ē ×ž×Ļב לקריאה בלבד באמ×Ļ×ĸו×Ē ×™×Ļגן המש×Ēמ׊ מהמסך הראשי", "advanced_settings_readonly_mode_title": "מ×Ļב לקריאה בלבד", - "advanced_settings_self_signed_ssl_subtitle": "מדלג ×ĸל אימו×Ē ×Ē×ĸוד×Ē SSL ×ĸבור נקוד×Ē ×”×§×Ļה של השר×Ē. דרוש ×ĸבור ×Ē×ĸודו×Ē ×‘×—×Ēימה ×ĸ×Ļמי×Ē.", + "advanced_settings_self_signed_ssl_subtitle": "מדלג ×ĸל אימו×Ē ×Ē×ĸוד×Ē SSL ×ĸבור כ×Ēוב×Ē URL של השר×Ē. דרוש ×ĸבור ×Ē×ĸודו×Ē ×‘×—×Ēימה ×ĸ×Ļמי×Ē.", "advanced_settings_self_signed_ssl_title": "ה×Ēר ×Ē×ĸודו×Ē SSL בח×Ēימה ×ĸ×Ļמי×Ē", "advanced_settings_sync_remote_deletions_subtitle": "מחק או שחזר ×Ēמונה במכשיר זה באופן אוטומטי כאשר פ×ĸולה זו × ×ĸשי×Ē ×‘×“×¤×“×¤×Ÿ", "advanced_settings_sync_remote_deletions_title": "סנכרן מחיקו×Ē ×Š×‘×•×Ļ×ĸו במכשירים אחרים [נסיוני]", @@ -425,6 +431,7 @@ "album_remove_user_confirmation": "האם באמ×Ē ×‘×¨×Ļונך להסיר א×Ē {user}?", "album_search_not_found": "לא נמ×Ļאו אלבומים ה×Ēואמים לחיפוש שלך", "album_share_no_users": "נראה ששי×Ēפ×Ē ××Ē ×”××œ×‘×•× הזה ×ĸם כל המש×Ēמשים או שאין לך את מ׊×Ēמ׊ לש×Ē×Ŗ אי×Ēו.", + "album_summary": "×Ē×§×Ļיר אלבום", "album_updated": "אלבום ×ĸודכן", "album_updated_setting_description": "קבל הוד×ĸ×Ē ×“×•×\"ל כאשר לאלבום משו×Ē×Ŗ יש ×Ēמונו×Ē ×—×“×Š×•×Ē", "album_user_left": "×ĸזב א×Ē {album}", @@ -496,6 +503,8 @@ "asset_restored_successfully": "×Ēמונה שוחזרה בה×Ļלחה", "asset_skipped": "דילג", "asset_skipped_in_trash": "באשפה", + "asset_trashed": "ה×Ēמונה הו×ĸברה לאשפה", + "asset_troubleshoot": "פ×Ēרון ב×ĸיו×Ē ×‘×Ēמונו×Ē", "asset_uploaded": "הו×ĸלה", "asset_uploading": "מ×ĸלהâ€Ļ", "asset_viewer_settings_subtitle": "ניהול הגדרו×Ē ×ž×Ļיג הגלריה שלך", @@ -529,8 +538,10 @@ "autoplay_slideshow": "מ×Ļג×Ē ×Ēמונו×Ē ××•×˜×•×ž×˜×™×Ē", "back": "חזרה", "back_close_deselect": "חזור, סגור, או בטל בחירה", + "background_backup_running_error": "גיבוי ברק×ĸ פו×ĸל כ×ĸ×Ē, לא ני×Ēן להפ×ĸיל גיבוי ידני", "background_location_permission": "הרשא×Ē ×ž×™×§×•× ברק×ĸ", "background_location_permission_content": "כדי ×œ×”×—×œ×™×Ŗ ר׊×Ēו×Ē ×‘×ĸ×Ē ×¨×™×Ļה ברק×ĸ, היישום ×Ļריך *×Ēמיד* גישה למיקום מדויק ×ĸל מנ×Ē ×œ×§×¨×•× א×Ē ×”×Š× של ר׊×Ē ×”××™× ×˜×¨× ×˜ האלחוטי", + "background_options": "אפשרויו×Ē ×¨×§×ĸ", "backup": "גיבוי", "backup_album_selection_page_albums_device": "({count}) אלבומים במכשיר", "backup_album_selection_page_albums_tap": "הקש כדי לכלול, הקש פ×ĸמיים כדי להחריג", @@ -538,6 +549,7 @@ "backup_album_selection_page_select_albums": "בחיר×Ē ××œ×‘×•×ž×™×", "backup_album_selection_page_selection_info": "פרטי בחירה", "backup_album_selection_page_total_assets": "סה״כ ×Ēמונו×Ē ×™×™×—×•×“×™×•×Ē", + "backup_albums_sync": "סנכרון אלבומי גיבוי", "backup_all": "הכל", "backup_background_service_backup_failed_message": "נכשל בגיבוי ×Ēמונו×Ē. מנסה שובâ€Ļ", "backup_background_service_connection_failed_message": "נכשל בה×Ēחברו×Ē ×œ×Š×¨×Ē. מנסה שובâ€Ļ", @@ -580,13 +592,14 @@ "backup_controller_page_start_backup": "ה×Ēחל גיבוי", "backup_controller_page_status_off": "גיבוי חזי×Ē ××•×˜×•×ž×˜×™ כבוי", "backup_controller_page_status_on": "גיבוי חזי×Ē ××•×˜×•×ž×˜×™ מופ×ĸל", - "backup_controller_page_storage_format": "{used}מ×Ēוך {total} בשימוש", + "backup_controller_page_storage_format": "{used} מ×Ēוך {total} בשימוש", "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_error_sync_failed": "הסינכרון נכשל. לא ני×Ēן להשלים א×Ē ×”×’×™×‘×•×™.", "backup_info_card_assets": "×Ēמונו×Ē", "backup_manual_cancelled": "בוטל", "backup_manual_in_progress": "ה×ĸלאה כבר ב×Ēהליך. נסה אחרי זמן מה", @@ -597,8 +610,6 @@ "backup_setting_subtitle": "ניהול הגדרו×Ē ×”×ĸלא×Ē ×¨×§×ĸ וחזי×Ē", "backup_settings_subtitle": "נהל הגדרו×Ē ×”×ĸלאה", "backward": "אחורה", - "beta_sync": "סטטוס סנכרון (בטא)", - "beta_sync_subtitle": "נהל א×Ē ×ž×ĸרכ×Ē ×”×Ą× ×›×¨×•×Ÿ החדשה", "biometric_auth_enabled": "אימו×Ē ×‘×™×•×ž×˜×¨×™ הופ×ĸל", "biometric_locked_out": "גישה לאימו×Ē ×”×‘×™×•×ž×˜×¨×™ נחסמה", "biometric_no_options": "אין אפשרויו×Ē ×–×ž×™× ×•×Ē ×ĸבור אימו×Ē ×‘×™×•×ž×˜×¨×™", @@ -656,6 +667,8 @@ "change_pin_code": "שנה קוד PIN", "change_your_password": "×”×—×œ×Ŗ א×Ē ×”×Ą×™×Ą×ž×” שלך", "changed_visibility_successfully": "הנראו×Ē ×Š×•× ×Ēה בה×Ļלחה", + "charging": "טו×ĸן", + "charging_requirement_mobile_backup": "גיבוי ברק×ĸ דורש ט×ĸינה של המכשיר", "check_corrupt_asset_backup": "בדוק גיבויים פגומים של ×Ēמונו×Ē", "check_corrupt_asset_backup_button": "ב×Ļ×ĸ בדיקה", "check_corrupt_asset_backup_description": "הר×Ĩ בדיקה זו רק ×ĸל Wi-Fi ולאחר שכל ה×Ēמונו×Ē ×’×•×‘×•. ההליך ×ĸשוי לקח×Ē ×›×ž×” דקו×Ē.", @@ -742,6 +755,7 @@ "create_user": "×Ļור מ׊×Ēמ׊", "created": "נו×Ļר", "created_at": "נו×Ļר", + "creating_linked_albums": "יו×Ļר אלבומים מקושרים...", "crop": "ח×Ēוך", "curated_object_page_title": "דברים", "current_device": "מכשיר נוכחי", @@ -891,7 +905,9 @@ "error": "שגיאה", "error_change_sort_album": "שינוי סדר מיון אלבום נכשל", "error_delete_face": "שגיאה במחיק×Ē ×¤× ×™× מ×Ēמונה", + "error_getting_places": "שגיאה בקבל×Ē ×ž×§×•×ž×•×Ē", "error_loading_image": "שגיאה בט×ĸינ×Ē ×”×Ēמונה", + "error_loading_partners": "שגיאה בט×ĸינ×Ē ×Š×•×Ēפים: {error}", "error_saving_image": "שגיאה: {error}", "error_tag_face_bounding_box": "שגיאה ב×Ēיוג הפנים – לא ני×Ēן לקבל א×Ē ×§×•××•×¨×“×™× ×˜×•×Ē ×”×ž×Ą×’×¨×Ē", "error_title": "שגיאה - משהו הש×Ēבש", @@ -1056,6 +1072,7 @@ "favorites_page_no_favorites": "לא נמ×Ļאו ×Ēמונו×Ē ×ž×•×ĸדפים", "feature_photo_updated": "×Ēמונה מיי×Ļג×Ē ×ĸודכנה", "features": "×Ēכונו×Ē", + "features_in_development": "×Ēכונו×Ē ×‘×¤×™×Ēוח", "features_setting_description": "ניהול ×Ēכונו×Ē ×”×™×™×Š×•×", "file_name": "׊ם הקוב×Ĩ", "file_name_or_extension": "׊ם קוב×Ĩ או סיומ×Ē", @@ -1076,10 +1093,7 @@ "gcast_enabled": "Google Cast", "gcast_enabled_description": "×Ēכונה זא×Ē ×˜×•×ĸ× ×Ē ×ž×Š××‘×™× חי×Ļוניים מגוגל בכדי לפ×ĸול.", "general": "כללי", - "geolocation_instruction_all_have_location": "לכל הפריטים ×ĸבור ×Ēאריך זה כבר יש × ×Ēוני מיקום. נסה לה×Ļיג א×Ē ×›×œ הפריטים או בחר ×Ēאריך אחר", "geolocation_instruction_location": "לח×Ĩ ×ĸל פריט ×ĸם קואורדינטו×Ē GPS כדי להש×Ēמ׊ במיקומו, או בחר מיקום ישירו×Ē ×ž×”×ž×¤×”", - "geolocation_instruction_no_date": "בחר ×Ēאריך כדי לנהל × ×Ēוני מיקום ×ĸבור ×Ēמונו×Ē ×•×Ą×¨×˜×•× ×™× מאו×Ēו יום", - "geolocation_instruction_no_photos": "לא נמ×Ļאו ×Ēמונו×Ē ××• סרטונים ×ĸבור ×Ēאריך זה. בחר ×Ēאריך אחר כדי לה×Ļיג או×Ēם", "get_help": "קבל ×ĸזרה", "get_wifiname_error": "לא היה ני×Ēן לקבל א×Ē ×Š× האינטרנט האלחוטי שלך. יש לודא שה×ĸ× ×§×Ē ××Ē ×”×”×¨×Š××•×Ē ×”×“×¨×•×Š×•×Ē ×•×Š××Ē/ה מחובר/×Ē ×œ×¨×Š×Ē ××™× ×˜×¨× ×˜ אלחוטי", "getting_started": "×Ēחיל×Ē ×”×ĸבודה", @@ -1098,7 +1112,7 @@ "haptic_feedback_switch": "אפ׊ר משוב ברטט", "haptic_feedback_title": "משוב ברטט", "has_quota": "יש מכסה", - "hash_asset": "גיבוב ×Ēמונה", + "hash_asset": "גבב פריט", "hashed_assets": "×Ēמונו×Ē ×ž×’×•×‘×‘×•×Ē", "hashing": "מגבב", "header_settings_add_header_tip": "×”×•×Ą×Ŗ כו×Ēר×Ē", @@ -1134,7 +1148,7 @@ "hour": "׊×ĸה", "hours": "׊×ĸו×Ē", "id": "מזהה", - "idle": "ממ×Ēין", + "idle": "במ×Ļב ץרק", "ignore_icloud_photos": "ה×Ē×ĸלם מ×Ēמונו×Ē iCloud", "ignore_icloud_photos_description": "×Ēמונו×Ē ×Š×ž××•×—×Ą× ×•×Ē ×‘-iCloud לא יו×ĸלו לשר×Ē", "image": "×Ēמונה", @@ -1223,6 +1237,7 @@ "local": "מקומי", "local_asset_cast_failed": "לא ני×Ēן לשדר ×Ēמונה שלא הו×ĸל×Ēה לשר×Ē", "local_assets": "×Ēמונו×Ē ×ž×§×•×ž×™×•×Ē", + "local_media_summary": "סיכום של מדיה מקומי×Ē", "local_network": "ר׊×Ē ×ž×§×•×ž×™×Ē", "local_network_sheet_info": "היישום י×Ēחבר לשר×Ē ×“×¨×š הכ×Ēוב×Ē ×”×–××Ē ×›××Š×¨ מ׊×Ēמשים ברש×Ē ×”××™× ×˜×¨× ×˜ האלחוטי ׊מ×Ļוינ×Ē", "location_permission": "הרשא×Ē ×ž×™×§×•×", @@ -1234,6 +1249,7 @@ "location_picker_longitude_hint": "הזן א×Ē ×§×• האורך שלך כאן", "lock": "× ×ĸל", "locked_folder": "×Ēיקיה × ×ĸולה", + "log_detail_title": "פרטי יומן", "log_out": "ה×Ē× ×Ē×§", "log_out_all_devices": "ה×Ē× ×Ē×§ מכל המכשירים", "logged_in_as": "מחובר כ {user}", @@ -1245,7 +1261,7 @@ "login_form_back_button_text": "חזרה", "login_form_email_hint": "yourmail@email.com", "login_form_endpoint_hint": "http://your-server-ip:port", - "login_form_endpoint_url": "כ×Ēוב×Ē × ×§×•×“×Ē ×§×Ļה השר×Ē", + "login_form_endpoint_url": "כ×Ēוב×Ē URL של השר×Ē", "login_form_err_http": "נא ל×Ļיין //:http או //:https", "login_form_err_invalid_email": "דוא\"ל שגוי", "login_form_err_invalid_url": "כ×Ēוב×Ē ×œ× חוקי×Ē", @@ -1264,6 +1280,7 @@ "login_password_changed_success": "סיסמה ×ĸודכנה בה×Ļלחה", "logout_all_device_confirmation": "האם באמ×Ē ×‘×¨×Ļונך לה×Ē× ×Ē×§ מכל המכשירים?", "logout_this_device_confirmation": "האם באמ×Ē ×‘×¨×Ļונך לה×Ē× ×Ē×§ מהמכשיר הזה?", + "logs": "יומנים", "longitude": "קו אורך", "look": "מראה", "loop_videos": "הפ×ĸלה חוזר×Ē ×Š×œ סרטונים", @@ -1306,6 +1323,7 @@ "mark_as_read": "סמן כנקרא", "marked_all_as_read": "כל הה×Ēראו×Ē ×Ą×•×ž× ×• כנקראו", "matches": "ה×Ēאמו×Ē", + "matching_assets": "×Ēמונו×Ē ×Ēואמו×Ē", "media_type": "סוג מדיה", "memories": "זכרונו×Ē", "memories_all_caught_up": "ראי×Ē ×”×›×œ", @@ -1346,9 +1364,10 @@ "name_or_nickname": "׊ם או כינוי", "network_requirement_photos_upload": "הש×Ēמ׊ בנ×Ēונים ניידים לגיבוי ×Ēמונו×Ē", "network_requirement_videos_upload": "הש×Ēמ׊ בנ×Ēונים ניידים לגיבוי סרטונים", + "network_requirements": "דרישו×Ē ×¨×Š×Ē", "network_requirements_updated": "דרישו×Ē ×”×¨×Š×Ē ×”×Š×Ēנו, ×Ēור הגיבוי אופס", "networking_settings": "ר׊×Ē", - "networking_subtitle": "ניהול הגדרו×Ē × ×§×•×“×Ē ×§×Ļה ׊ר×Ē", + "networking_subtitle": "ניהול הגדרו×Ē ×›×Ēוב×Ē URL של השר×Ē", "never": "את פ×ĸם", "new_album": "אלבום חדש", "new_api_key": "מפ×Ēח API חדש", @@ -1356,6 +1375,7 @@ "new_person": "אדם חדש", "new_pin_code": "קוד PIN חדש", "new_pin_code_subtitle": "זא×Ē ×”×¤×ĸם הראשונה שנכנס×Ē ×œ×Ēיקיה הנ×ĸולה. ×Ļור קוד PIN כדי לאבטח א×Ē ×”×’×™×Š×” ×œ×“×Ŗ זה", + "new_timeline": "×Ļיר הזמן החדש", "new_user_created": "מ׊×Ēמ׊ חדש נו×Ļר", "new_version_available": "גרסה חדשה זמינה", "newest_first": "החדש ביו×Ēר ראשון", @@ -1369,20 +1389,25 @@ "no_assets_message": "לח×Ĩ כדי לה×ĸלו×Ē ××Ē ×”×Ēמונה הראשונה שלך", "no_assets_to_show": "אין ×Ēמונו×Ē ×œ×”×Ļגה", "no_cast_devices_found": "לא נמ×Ļאו מכשירי שידור", + "no_checksum_local": "אין Checksum זמין - לא ני×Ēן לאחזר ×Ēמונו×Ē ×ž×§×•×ž×™×•×Ē", + "no_checksum_remote": "אין Checksum זמין - לא ני×Ēן לאחזר ×Ēמונו×Ē ×ž×”×Š×¨×Ē", "no_duplicates_found": "לא נמ×Ļאו כפילויו×Ē.", "no_exif_info_available": "אין מיד×ĸ זמין ×ĸל מטא-× ×Ēונים (exif)", "no_explore_results_message": "ה×ĸלה ×Ēמונו×Ē × ×•×Ą×¤×•×Ē ×›×“×™ לחקור א×Ē ×”××•×Ą×Ŗ שלך.", "no_favorites_message": "×”×•×Ą×Ŗ מו×ĸדפים כדי למ×Ļוא במהירו×Ē ××Ē ×”×Ēמונו×Ē ×•×”×Ą×¨×˜×•× ×™× הכי טובים שלך", "no_libraries_message": "×Ļור ספרייה חי×Ļוני×Ē ×›×“×™ לראו×Ē ××Ē ×”×Ēמונו×Ē ×•×”×Ą×¨×˜×•× ×™× שלך", + "no_local_assets_found": "לא נמ×Ļאו ×Ēמונו×Ē ×ĸם Checksum זהה", "no_locked_photos_message": "×Ēמונו×Ē ×•×Ą×¨×˜×•× ×™× ב×Ēיקייה הנ×ĸולה מוס×Ēרים ולא יופי×ĸו בזמן הגלישה או החיפוש בספרייה שלך.", "no_name": "אין ׊ם", "no_notifications": "אין ה×Ēראו×Ē", "no_people_found": "לא נמ×Ļאו אנשים ×Ēואמים", "no_places": "אין מקומו×Ē", + "no_remote_assets_found": "לא נמ×Ļאו ×Ēמונו×Ē ×‘×Š×¨×Ē ×ĸם Checksum זהה", "no_results": "אין ×Ēו×Ļאו×Ē", "no_results_description": "נסה להש×Ēמ׊ במילה נרדפ×Ē ××• במיל×Ē ×ž×¤×Ēח יו×Ēר כללי×Ē", "no_shared_albums_message": "×Ļור אלבום כדי לש×Ē×Ŗ ×Ēמונו×Ē ×•×Ą×¨×˜×•× ×™× ×ĸם אנשים ברש×Ē ×Š×œ×š", "no_uploads_in_progress": "אין ה×ĸלאו×Ē ×‘×Ēהליך", + "not_available": "לא רלוונטי", "not_in_any_album": "לא בשום אלבום", "not_selected": "לא נבחרו", "note_apply_storage_label_to_previously_uploaded assets": "ה×ĸרה: כדי להחיל א×Ē ×Ēווי×Ē ×”××—×Ą×•×Ÿ ×ĸל ×Ēמונו×Ē ×Š×”×•×ĸלו ב×ĸבר, הפ×ĸל א×Ē", @@ -1417,6 +1442,8 @@ "open_the_search_filters": "פ×Ēח א×Ē ×ž×Ą× × ×™ החיפוש", "options": "אפשרויו×Ē", "or": "או", + "organize_into_albums": "ארגן ב×Ēוך אלבומים", + "organize_into_albums_description": "שים ×Ēמונו×Ē ×§×™×™×ž×•×Ē ×‘×Ēוך אלבומים באמ×Ļ×ĸו×Ē ×”×’×“×¨×•×Ē ×”×Ą× ×›×¨×•×Ÿ הנוכחיו×Ē", "organize_your_library": "ארגן א×Ē ×”×Ą×¤×¨×™×™×” שלך", "original": "מקורי", "other": "אחר", @@ -1476,9 +1503,9 @@ "permission_onboarding_permission_limited": "הרשאה מוגבל×Ē. כדי ל×Ē×Ē ×œ×™×™×Š×•× לגבו×Ē ×•×œ× ×”×œ א×Ē ×›×œ ××•×Ą×Ŗ הגלריה שלך, ה×ĸ× ×§ הרשאה ל×Ēמונו×Ē ×•×Ą×¨×˜×•× ×™× בהגדרו×Ē.", "permission_onboarding_request": "היישום דורש הרשאה כדי לראו×Ē ××Ē ×”×Ēמונו×Ē ×•×”×Ą×¨×˜×•× ×™× שלך.", "person": "אדם", - "person_age_months": "בן {months, plural, one {חודש #} other {# חודשים}}", - "person_age_year_months": "בן שנה, {months, plural, one {חודש #} other {# חודשים}}", - "person_age_years": "בן {years, plural, other {# שנים}}", + "person_age_months": "{months, plural, one {חודש #} other {# חודשים}}", + "person_age_year_months": "בגיל שנה ו{months, plural, one {חודש #} other {# חודשים}}", + "person_age_years": "בגיל {years, plural, other {# שנים}}", "person_birthdate": "נולד ב×Ēאריך {date}", "person_hidden": "{name}{hidden, select, true { (מוס×Ēר)} other {}}", "photo_shared_all_users": "נראה ששי×Ēפ×Ē ××Ē ×”×Ēמונו×Ē ×Š×œ×š ×ĸם כל המש×Ēמשים או שאין לך את מ׊×Ēמ׊ לש×Ē×Ŗ אי×Ēו.", @@ -1502,6 +1529,7 @@ "port": "י×Ļיאה", "preferences_settings_subtitle": "ניהול ה×ĸדפו×Ē ×™×™×Š×•×", "preferences_settings_title": "ה×ĸדפו×Ē", + "preparing": "בהכנה", "preset": "הגדרו×Ē ×§×‘×•×ĸו×Ē ×ž×¨××Š", "preview": "×Ē×Ļוגה מקדימה", "previous": "הקודם", @@ -1518,7 +1546,7 @@ "profile_drawer_client_out_of_date_minor": "גרס×Ē ×”×™×™×Š×•× לנייד מיושנ×Ē. נא ל×ĸדכן לגרסה המשני×Ē ×”××—×¨×•× ×”.", "profile_drawer_client_server_up_to_date": "היישום והשר×Ē ×ž×ĸודכנים", "profile_drawer_github": "GitHub", - "profile_drawer_readonly_mode": "מ×Ļב לקריאה בלבד מופ×ĸל. הקש הקשה כפולה ×ĸל סמל הי×Ļגן של המש×Ēמ׊ כדי ל×Ļא×Ē.", + "profile_drawer_readonly_mode": "מ×Ļב לקריאה בלבד מופ×ĸל. לח×Ĩ לחי×Ļה ארוכה ×ĸל סמל הי×Ļגן של המש×Ēמ׊ כדי ל×Ļא×Ē.", "profile_drawer_server_out_of_date_major": "השר×Ē ××™× ×• מ×ĸודכן. נא ל×ĸדכן לגרסה הראשי×Ē ×”××—×¨×•× ×”.", "profile_drawer_server_out_of_date_minor": "השר×Ē ××™× ×• מ×ĸודכן. נא ל×ĸדכן לגרסה המשני×Ē ×”××—×¨×•× ×”.", "profile_image_of_user": "×Ēמונ×Ē ×¤×¨×•×¤×™×œ של {user}", @@ -1557,7 +1585,8 @@ "purchase_server_description_2": "מ×ĸמד ×Ēומך", "purchase_server_title": "׊ר×Ē", "purchase_settings_server_activated": "מפ×Ēח המו×Ļר של השר×Ē ×ž× ×•×”×œ ×ĸל ידי מנהל המ×ĸרכ×Ē", - "queue_status": "ב×Ēור {count}/{total}", + "query_asset_id": "שאיל×Ēה ×ĸל מזהה הפריט", + "queue_status": "{count} מ×Ēוך {total} ×ĸומדים ב×Ēור", "rating": "דירוג כוכב", "rating_clear": "נקה דירוג", "rating_count": "{count, plural, one {כוכב #} other {# כוכבים}}", @@ -1566,10 +1595,11 @@ "read_changelog": "קרא א×Ē ×™×•×ž×Ÿ השינויים", "readonly_mode_disabled": "מ×Ļב לקריאה בלבד מושב×Ē", "readonly_mode_enabled": "מ×Ļב לקריאה בלבד מופ×ĸל", - "reassign": "הק×Ļה מחדש", + "ready_for_upload": "מוכן לה×ĸלאה", + "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": "הק×Ļה ×Ēמונו×Ē ×Š× ×‘×—×¨×• לאדם קיים", + "reassing_hint": "הק×Ļא×Ē ×Ēמונו×Ē ×Š× ×‘×—×¨×• לאדם קיים", "recent": "חדש", "recent-albums": "אלבומים אחרונים", "recent_searches": "חיפושים אחרונים", @@ -1577,11 +1607,11 @@ "recently_added_page_title": "× ×•×Ą×Ŗ לאחרונה", "recently_taken": "×Ļולם לאחרונה", "recently_taken_page_title": "×Ļולם לאחרונה", - "refresh": "ר×ĸנן", - "refresh_encoded_videos": "ר×ĸנן סרטונים מקודדים", - "refresh_faces": "ר×ĸנן פנים", - "refresh_metadata": "ר×ĸנן מטא-× ×Ēונים", - "refresh_thumbnails": "ר×ĸנן ×Ēמונו×Ē ×ž×ž×•×–×ĸרו×Ē", + "refresh": "ר×ĸנון", + "refresh_encoded_videos": "ר×ĸנון סרטונים מקודדים", + "refresh_faces": "ר×ĸנון פנים", + "refresh_metadata": "ר×ĸנון מטא-× ×Ēונים", + "refresh_thumbnails": "ר×ĸנון ×Ēמונו×Ē ×ž×ž×•×–×ĸרו×Ē", "refreshed": "רו×ĸנן", "refreshes_every_file": "קורא מחדש א×Ē ×›×œ הקב×Ļים הקיימים והחדשים", "refreshing_encoded_video": "מר×ĸנן סרטון מקודד", @@ -1590,15 +1620,16 @@ "regenerating_thumbnails": "מחדש ×Ēמונו×Ē ×ž×ž×•×–×ĸרו×Ē", "remote": "מרוחק", "remote_assets": "×Ēמונו×Ē ×ž×¨×•×—×§×•×Ē", - "remove": "הסר", + "remote_media_summary": "×Ē×§×Ļיר ×Ēמונו×Ē ×ž×¨×•×—×§×•×Ē", + "remove": "הסרה", "remove_assets_album_confirmation": "האם באמ×Ē ×‘×¨×Ļונך להסיר {count, plural, one {×Ēמונה #} other {# ×Ēמונו×Ē}} מהאלבום?", - "remove_assets_shared_link_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": "הסר מאלבום", + "remove_custom_date_range": "הסר×Ē ×˜×•×•×— ×Ēאריכים מו×Ēאם", + "remove_deleted_assets": "הסר×Ē ×§×‘×Ļים לא מקוונים", + "remove_from_album": "הסרה מאלבום", "remove_from_album_action_prompt": "{count} הוסרו מהאלבום", - "remove_from_favorites": "הסר מהמו×ĸדפים", + "remove_from_favorites": "הסרה מהמו×ĸדפים", "remove_from_lock_folder_action_prompt": "{count} הוסרו מה×Ēיקייה הנ×ĸולה", "remove_from_locked_folder": "הסר מה×Ēיקייה הנ×ĸולה", "remove_from_locked_folder_confirmation": "האם א×Ēה בטוח שבר×Ļונך לה×ĸביר א×Ē ×”×Ēמונו×Ē ×•×”×Ą×¨×˜×•× ×™× האלה מחו×Ĩ ל×Ēיקייה הנ×ĸולה? הם יהיו מו×Ļגים בספרייה שלך.", @@ -1642,6 +1673,7 @@ "restore_user": "שחזר מ׊×Ēמ׊", "restored_asset": "ה×Ēמונה שוחזרה", "resume": "המשך", + "resume_paused_jobs": "המשך {count, plural, one {×ĸבודה # שהופסקה} other {# ×ĸבודו×Ē ×Š×”×•×¤×Ą×§×•}}", "retry_upload": "נסה שוב לה×ĸלו×Ē", "review_duplicates": "בדוק כפילויו×Ē", "review_large_files": "×Ļפייה בקב×Ļים גדולים", @@ -1738,7 +1770,7 @@ "selected_gps_coordinates": "קואורדינטו×Ē GPS שנבחרו", "send_message": "שלח הוד×ĸה", "send_welcome_email": "שלח דוא\"ל קבל×Ē ×¤× ×™×", - "server_endpoint": "נקוד×Ē ×§×Ļה ׊ר×Ē", + "server_endpoint": "כ×Ēוב×Ē URL של השר×Ē", "server_info_box_app_version": "גרס×Ē ×™×™×Š×•×", "server_info_box_server_url": "כ×Ēוב×Ē ×Š×¨×Ē", "server_offline": "השר×Ē ×ž× ×•×Ē×§", @@ -1846,10 +1878,8 @@ "shift_to_permanent_delete": "לח×Ĩ ⇧ כדי למחוק ×Ēמונה ל×Ļמי×Ēו×Ē", "show_album_options": "ה×Ļג אפשרויו×Ē ××œ×‘×•×", "show_albums": "ה×Ļג אלבומים", - "show_all_assets": "ה×Ļג א×Ē ×›×œ הפריטים", "show_all_people": "ה×Ļג א×Ē ×›×œ האנשים", "show_and_hide_people": "ה×Ļג & הס×Ēר אנשים", - "show_assets_without_location": "ה×Ļג פריטים ללא מיקום", "show_file_location": "ה×Ļג א×Ē ×ž×™×§×•× הקוב×Ĩ", "show_gallery": "ה×Ļג גלריה", "show_hidden_people": "ה×Ļג אנשים מוס×Ēרים", @@ -1866,6 +1896,7 @@ "show_slideshow_transition": "ה×Ļג מ×ĸבר מ×Ļג×Ē", "show_supporter_badge": "×Ēג ×Ēומך", "show_supporter_badge_description": "ה×Ļג ×Ēג ×Ēומך", + "show_text_search_menu": "ה×Ļג ×Ēפריט חיפוש טקץט", "shuffle": "×ĸרבוב", "sidebar": "סרגל ×Ļד", "sidebar_display_description": "ה×Ļג קישור ל×Ē×Ļוגה בסרגל ה×Ļד", @@ -1896,6 +1927,7 @@ "stacktrace": "Stack trace", "start": "ה×Ēחל", "start_date": "×Ēאריך ה×Ēחלה", + "start_date_before_end_date": "×Ēאריך הה×Ēחלה חייב להיו×Ē ×œ×¤× ×™ ×Ēאריך הסיום", "state": "מדינה", "status": "מ×Ļב", "stop_casting": "הפסק×Ē ×Š×™×“×•×¨", @@ -1910,7 +1942,7 @@ "submit": "שלח", "success": "בו×Ļ×ĸ בה×Ļלחה", "suggestions": "ה×Ļ×ĸו×Ē", - "sunrise_on_the_beach": "Sunrise on the beach (מומל×Ĩ לחפש באנגלי×Ē ×œ×Ēו×Ļאו×Ē ×˜×•×‘×•×Ē ×™×•×Ēר)", + "sunrise_on_the_beach": "שקי×ĸה בחות", "support": "×Ēמיכה", "support_and_feedback": "×Ēמיכה & משוב", "support_third_party_description": "ה×Ē×§× ×Ē ×”-Immich שלך נארזה ×ĸל ידי ×Ļד שלישי. ב×ĸיו×Ē ×Š××Ēה חווה ×ĸשויו×Ē ×œ×”×™×’×¨× ×ĸל ידי חבילה זו, אז בבקשה ×Ē×ĸלה ב×ĸיו×Ē ××™×Ēם ראשי×Ē ×›×œ באמ×Ļ×ĸו×Ē ×”×§×™×Š×•×¨×™× למטה.", @@ -1919,7 +1951,9 @@ "sync_albums": "סנכרן אלבומים", "sync_albums_manual_subtitle": "סנכרן א×Ē ×›×œ הסרטונים וה×Ēמונו×Ē ×Š×”×•×ĸלו לאלבומי הגיבוי שנבחרו", "sync_local": "סנכרן מקומי", - "sync_remote": "סנכרן מרוחק", + "sync_remote": "סנכרן מהשר×Ē", + "sync_status": "סטטוס סנכרון", + "sync_status_subtitle": "ה×Ļג ונהל א×Ē ×ž×ĸרכ×Ē ×”×Ą× ×›×¨×•×Ÿ", "sync_upload_album_setting_subtitle": "×Ļור וה×ĸלה ×Ēמונו×Ē ×•×Ą×¨×˜×•× ×™× שלך לאלבומים שנבחרו ביישום", "tag": "×Ēג", "tag_assets": "×Ēיוג ×Ēמונו×Ē", @@ -1979,6 +2013,7 @@ "trash_page_select_assets_btn": "בחר ×Ēמונו×Ē", "trash_page_title": "אשפה ({count})", "trashed_items_will_be_permanently_deleted_after": "פריטים באשפה ימחקו ל×Ļמי×Ēו×Ē ×œ××—×¨ {days, plural, one {יום #} other {# ימים}}.", + "troubleshoot": "פ×Ēור ב×ĸיו×Ē", "type": "סוג", "unable_to_change_pin_code": "לא ני×Ēן לשנו×Ē ××Ē ×§×•×“ ה PIN", "unable_to_setup_pin_code": "לא ני×Ēן להגדיר קוד PIN", @@ -2034,7 +2069,6 @@ "use_biometric": "הש×Ēמ׊ באימו×Ē ×‘×™×•×ž×˜×¨×™", "use_current_connection": "הש×Ēמ׊ בחיבור נוכחי", "use_custom_date_range": "הש×Ēמ׊ בטווח ×Ēאריכים מו×Ēאם במקום", - "use_this_location": "לח×Ĩ כדי להש×Ēמ׊ במיקום", "user": "מ׊×Ēמ׊", "user_has_been_deleted": "מ׊×Ēמ׊ זה נמחק.", "user_id": "מזהה מ׊×Ēמ׊", @@ -2053,7 +2087,7 @@ "users_added_to_album_count": "נוספו {count, plural, one {מ׊×Ēמ׊ #} other {# מ׊×Ēמשים}} לאלבום", "utilities": "כלים", "validate": "לאמ×Ē", - "validate_endpoint_error": "נא להזין כ×Ēוב×Ē ×Ēקני×Ē", + "validate_endpoint_error": "נא להזין כ×Ēוב×Ē URL ×Ēקני×Ē", "variables": "מ׊×Ēנים", "version": "גרסה", "version_announcement_closing": "החבר שלך, אלכס", @@ -2077,6 +2111,7 @@ "view_next_asset": "ה×Ļג א×Ē ×”×Ēמונה הבאה", "view_previous_asset": "ה×Ļג א×Ē ×”×Ēמונה הקודמ×Ē", "view_qr_code": "ה×Ļג ברקוד", + "view_similar_photos": "ה×Ļג ×Ēמונו×Ē ×“×•×ž×•×Ē", "view_stack": "ה×Ļג ×ĸרימה", "view_user": "ה×Ļג מ׊×Ēמ׊", "viewer_remove_from_stack": "הסר מ×ĸרימה", @@ -2095,5 +2130,6 @@ "yes": "כן", "you_dont_have_any_shared_links": "אין לך קישורים משו×Ēפים", "your_wifi_name": "׊ם אינטרנט אלחוטי שלך", - "zoom_image": "זום ל×Ēמונה" + "zoom_image": "זום ל×Ēמונה", + "zoom_to_bounds": "ה×Ēמקד באזור" } diff --git a/i18n/hi.json b/i18n/hi.json index 9662eb1203..aaf5bcbe7a 100644 --- a/i18n/hi.json +++ b/i18n/hi.json @@ -28,6 +28,7 @@ "add_to_album": "ā¤ā¤˛āĨā¤Ŧā¤Ž ā¤ŽāĨ‡ā¤‚ ā¤Ąā¤žā¤˛āĨ‡ā¤‚", "add_to_album_bottom_sheet_added": "{album} ā¤ŽāĨ‡ā¤‚ ā¤Ąā¤žā¤˛āĨ‡ā¤‚", "add_to_album_bottom_sheet_already_exists": "{album} ā¤ŽāĨ‡ā¤‚ ā¤Ēā¤šā¤˛āĨ‡ ⤏āĨ‡ ā¤šāĨˆ", + "add_to_albums": "ā¤ā¤•ā¤žā¤§ā¤ŋ⤕ ā¤ā¤˛āĨā¤Ŧā¤Ž ā¤ŽāĨ‡ā¤‚ ā¤Ąā¤žā¤˛āĨ‡", "add_to_shared_album": "ā¤ļāĨ‡ā¤¯ā¤° ⤕ā¤ŋā¤ ā¤—ā¤ ā¤ā¤˛āĨā¤Ŧā¤Ž ā¤ŽāĨ‡ā¤‚ ā¤Ąā¤žā¤˛āĨ‡ā¤‚", "add_url": "URL ā¤Ąā¤žā¤˛āĨ‡ā¤‚", "added_to_archive": "⤏⤂⤗āĨā¤°ā¤šāĨ€ā¤¤ ⤕⤰ ā¤Ļā¤ŋā¤¯ā¤ž ā¤—ā¤¯ā¤ž ā¤šāĨˆ", @@ -381,8 +382,6 @@ "admin_password": "ā¤ĩāĨā¤¯ā¤ĩ⤏āĨā¤Ĩā¤žā¤Ē⤕ ā¤Ēā¤žā¤¸ā¤ĩ⤰āĨā¤Ą", "administration": "ā¤ĒāĨā¤°ā¤ļā¤žā¤¸ā¤¨", "advanced": "ā¤ĩā¤ŋ⤕⤏ā¤ŋ⤤", - "advanced_settings_beta_timeline_subtitle": "ā¤¨ā¤ ⤐ā¤Ē ⤅⤍āĨā¤­ā¤ĩ ⤕āĨ‹ ā¤†ā¤œā¤ŧā¤Žā¤žā¤ā¤", - "advanced_settings_beta_timeline_title": "ā¤ŦāĨ€ā¤Ÿā¤ž ā¤Ÿā¤žā¤‡ā¤Žā¤˛ā¤žā¤‡ā¤¨", "advanced_settings_enable_alternate_media_filter_subtitle": "⤏ā¤ŋ⤂⤕ ⤕āĨ‡ ā¤ĻāĨŒā¤°ā¤žā¤¨ ā¤ĩāĨˆā¤•⤞āĨā¤Ēā¤ŋ⤕ ā¤Žā¤žā¤¨ā¤Ļā¤‚ā¤ĄāĨ‹ā¤‚ ⤕āĨ‡ ā¤†ā¤§ā¤žā¤° ā¤Ē⤰ ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ⤕āĨ‹ ā¤Ģā¤ŧā¤ŋ⤞āĨā¤Ÿā¤° ⤕⤰⤍āĨ‡ ⤕āĨ‡ ⤞ā¤ŋā¤ ⤇⤏ ā¤ĩā¤ŋ⤕⤞āĨā¤Ē ā¤•ā¤ž ⤉ā¤Ē⤝āĨ‹ā¤— ⤕⤰āĨ‡ā¤‚āĨ¤ ⤇⤏āĨ‡ ⤕āĨ‡ā¤ĩ⤞ ⤤⤭āĨ€ ā¤†ā¤œā¤ŧā¤Žā¤žā¤ā¤ ⤜ā¤Ŧ ⤆ā¤Ē⤕āĨ‹ ⤐ā¤Ē ā¤ĻāĨā¤ĩā¤žā¤°ā¤ž ⤏⤭āĨ€ ā¤ā¤˛āĨā¤Ŧā¤ŽāĨ‹ā¤‚ ā¤•ā¤ž ā¤Ēā¤¤ā¤ž ā¤˛ā¤—ā¤žā¤¨āĨ‡ ā¤ŽāĨ‡ā¤‚ ā¤¸ā¤Žā¤¸āĨā¤¯ā¤ž ā¤šāĨ‹āĨ¤", "advanced_settings_enable_alternate_media_filter_title": "[ā¤ĒāĨā¤°ā¤¯āĨ‹ā¤—ā¤žā¤¤āĨā¤Žā¤•] ā¤ĩāĨˆā¤•⤞āĨā¤Ēā¤ŋ⤕ ā¤Ąā¤ŋā¤ĩā¤žā¤‡ā¤¸ ā¤ā¤˛āĨā¤Ŧā¤Ž ⤏ā¤ŋ⤂⤕ ā¤Ģā¤ŧā¤ŋ⤞āĨā¤Ÿā¤° ā¤•ā¤ž ⤉ā¤Ē⤝āĨ‹ā¤— ⤕⤰āĨ‡ā¤‚", "advanced_settings_log_level_title": "⤞āĨ‰ā¤— ⤏āĨā¤¤ā¤°:{level}", @@ -585,8 +584,6 @@ "backup_setting_subtitle": "ā¤ĒāĨƒā¤ˇāĨā¤ ā¤­āĨ‚ā¤Žā¤ŋ ⤔⤰ ⤅⤗āĨā¤°ā¤­āĨ‚ā¤Žā¤ŋ ⤅ā¤Ē⤞āĨ‹ā¤Ą ⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗ ā¤ĒāĨā¤°ā¤Ŧ⤂⤧ā¤ŋ⤤ ⤕⤰āĨ‡ā¤‚", "backup_settings_subtitle": "⤅ā¤Ē⤞āĨ‹ā¤Ą ⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗āĨā¤¸ ā¤¸ā¤‚ā¤­ā¤žā¤˛āĨ‡ā¤‚", "backward": "ā¤Ēā¤ŋā¤›ā¤˛ā¤ž", - "beta_sync": "ā¤ŦāĨ€ā¤Ÿā¤ž ⤏ā¤ŋ⤂⤕ ⤏āĨā¤Ĩā¤ŋ⤤ā¤ŋ", - "beta_sync_subtitle": "ā¤¨ā¤ ⤏ā¤ŋ⤂⤕ ⤏ā¤ŋ⤏āĨā¤Ÿā¤Ž ā¤•ā¤ž ā¤ĒāĨā¤°ā¤Ŧ⤂⤧⤍ ⤕⤰āĨ‡ā¤‚", "biometric_auth_enabled": "ā¤Ŧā¤žā¤¯āĨ‹ā¤ŽāĨ‡ā¤ŸāĨā¤°ā¤ŋ⤕ ā¤ĒāĨā¤°ā¤Žā¤žā¤ŖāĨ€ā¤•⤰⤪ ⤏⤕āĨā¤ˇā¤Ž", "biometric_locked_out": "⤆ā¤Ē ā¤Ŧā¤žā¤¯āĨ‹ā¤ŽāĨ‡ā¤ŸāĨā¤°ā¤ŋ⤕ ā¤ĒāĨā¤°ā¤Žā¤žā¤ŖāĨ€ā¤•⤰⤪ ⤏āĨ‡ ā¤Ŧā¤žā¤šā¤° ā¤šāĨˆā¤‚", "biometric_no_options": "⤕āĨ‹ā¤ˆ ā¤Ŧā¤žā¤¯āĨ‹ā¤ŽāĨ‡ā¤ŸāĨā¤°ā¤ŋ⤕ ā¤ĩā¤ŋ⤕⤞āĨā¤Ē ⤉ā¤Ē⤞ā¤ŦāĨā¤§ ā¤¨ā¤šāĨ€ā¤‚ ā¤šāĨˆ", @@ -1550,6 +1547,7 @@ "year": "ā¤ĩ⤰āĨā¤ˇ", "yes": "ā¤šā¤žā¤", "you_dont_have_any_shared_links": "⤆ā¤Ē⤕āĨ‡ ā¤Ēā¤žā¤¸ ⤕āĨ‹ā¤ˆ ā¤¸ā¤žā¤ā¤ž ⤞ā¤ŋ⤂⤕ ā¤¨ā¤šāĨ€ā¤‚ ā¤šāĨˆ", - "your_wifi_name": "Your WiFi name", - "zoom_image": "⤛ā¤ĩā¤ŋ ⤜ā¤ŧāĨ‚ā¤Ž ⤕⤰āĨ‡ā¤‚" + "your_wifi_name": "⤆ā¤Ē⤕āĨ‡ ā¤ĩā¤žā¤ˆā¤Ģā¤žā¤ˆ ā¤•ā¤ž ā¤¨ā¤žā¤Ž", + "zoom_image": "⤛ā¤ĩā¤ŋ ⤜ā¤ŧāĨ‚ā¤Ž ⤕⤰āĨ‡ā¤‚", + "zoom_to_bounds": "⤏āĨ€ā¤Žā¤ž ⤤⤕ āĨ›āĨ‚ā¤Ž ⤕⤰āĨ‡ā¤‚" } diff --git a/i18n/hr.json b/i18n/hr.json index 036078f23a..4e54541c2d 100644 --- a/i18n/hr.json +++ b/i18n/hr.json @@ -15,9 +15,9 @@ "add_a_name": "Dodaj ime", "add_a_title": "Dodaj naslov", "add_birthday": "Dodaj rođendan", - "add_endpoint": "Dodaj krajnju točnu", + "add_endpoint": "Dodaj krajnju točku", "add_exclusion_pattern": "Dodaj uzorak izuzimanja", - "add_import_path": "Dodaj import folder", + "add_import_path": "Dodaj putanju uvoza", "add_location": "Dodaj lokaciju", "add_more_users": "Dodaj joÅĄ korisnika", "add_partner": "Dodaj partnera", @@ -28,35 +28,37 @@ "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_album_bottom_sheet_some_local_assets": "Neke lokalne stavke nije moguće dodati u album", "add_to_album_toggle": "Uključi/isključi odabir za {album}", "add_to_albums": "Dodaj u albume", "add_to_albums_count": "Dodaj u albume ({count})", "add_to_shared_album": "Dodaj u dijeljeni album", + "add_upload_to_stack": "Dodaj preneseno u skup", "add_url": "Dodaj URL", "added_to_archive": "Dodano u arhivu", "added_to_favorites": "Dodano u omiljeno", "added_to_favorites_count": "Dodano {count, number} u omiljeno", "admin": { - "add_exclusion_pattern_description": "Dodajte uzorke izuzimanja. Globiranje pomoću *, ** i ? je podrÅžano. Za ignoriranje svih datoteka u bilo kojem direktoriju pod nazivom \"Raw\", koristite \"**/Raw/**\". Da biste zanemarili sve datoteke koje zavrÅĄavaju na \".tif\", koristite \"**/*.tif\". Da biste zanemarili apsolutni put, koristite \"/path/to/ignore/**\".", + "add_exclusion_pattern_description": "Dodajte uzorke izuzimanja. Globiranje pomoću *, ** i ? je podrÅžano. Za ignoriranje svih datoteka u bilo kojem direktoriju pod nazivom \"Raw\", koristite \"**/Raw/**\". Kako biste ignorirali sve datoteke koje zavrÅĄavaju na \".tif\", koristite \"**/*.tif\". Kako biste ignorirali apsolutnu putanju, koristite \"/putanja/za/ignoriranje/**\".", "admin_user": "Administrator", - "asset_offline_description": "Ovo sredstvo vanjske knjiÅžnice viÅĄe nije pronađeno na disku i premjeÅĄteno je u smeće. Ako je datoteka premjeÅĄtena unutar biblioteke, provjerite svoju vremensku traku za novo odgovarajuće sredstvo. Da biste vratili ovo sredstvo, provjerite moÅže li Immich pristupiti donjoj stazi datoteke i skenirajte biblioteku.", - "authentication_settings": "Postavke autentikacije", - "authentication_settings_description": "Uredi lozinku, OAuth, i druge postavke autentikacije", - "authentication_settings_disable_all": "Jeste li sigurni da Åželite onemogućenit sve načine prijave? Prijava će biti potpuno onemogućena.", - "authentication_settings_reenable": "Za ponovno uključivanje upotrijebite naredbu posluÅžitelja.", + "asset_offline_description": "Ova stavka vanjske biblioteke nije pronađena na disku i premjeÅĄtena je u smeće. Ako je datoteka premjeÅĄtena unutar biblioteke, provjerite svoju vremensku traku za novu odgovarajuću stavku. Da biste vratili ovu stavku, provjerite moÅže li Immich pristupiti donjoj putanji datoteke i skenirajte biblioteku.", + "authentication_settings": "Postavke autentifikacije", + "authentication_settings_description": "Upravljajte lozinkom, OAuthom i drugim postavkama autentifikacije", + "authentication_settings_disable_all": "Jeste li sigurni da Åželite onemogućiti sve načine prijave? Prijava će biti potpuno onemogućena.", + "authentication_settings_reenable": "Za ponovno uključivanje upotrijebite naredbu servera.", "background_task_job": "Pozadinski zadaci", "backup_database": "Kreiraj sigurnosnu kopiju baze podataka", "backup_database_enable_description": "Omogućite sigurnosne kopije baze podataka", "backup_keep_last_amount": "Količina prethodnih sigurnosnih kopija za čuvanje", "backup_onboarding_1_description": "kopija izvan lokacije u oblaku ili na drugoj fizičkoj lokaciji.", - "backup_onboarding_2_description": "lokalne kopije na različitim uređajima. To uključuje glavne datoteke i sigurnosnu kopiju tih datoteka lokalno.", + "backup_onboarding_2_description": "lokalne kopije na različitim uređajima. To uključuje glavne datoteke i lokalnu sigurnosnu kopiju tih datoteka.", "backup_onboarding_3_description": "ukupne kopije vaÅĄih podataka, uključujući izvorne datoteke. To uključuje 1 kopiju izvan lokacije i 2 lokalne kopije.", "backup_onboarding_description": "Preporučuje se 3-2-1 strategija sigurnosnog kopiranja za zaÅĄtitu vaÅĄih podataka. Trebali biste čuvati kopije svojih prenesenih fotografija/videozapisa kao i Immich bazu podataka za sveobuhvatno rjeÅĄenje sigurnosne kopije.", - "backup_onboarding_footer": "Za viÅĄe informacija o sigurnosnom kopiranju Immich, molimo pogledajte dokumentaciju.", + "backup_onboarding_footer": "Za viÅĄe informacija o sigurnosnom kopiranju Immicha, molimo pogledajte dokumentaciju.", "backup_onboarding_parts_title": "3-2-1 sigurnosna kopija uključuje:", "backup_onboarding_title": "Sigurnosne kopije", - "backup_settings": "Postavke sigurnosne kopije", - "backup_settings_description": "Upravljajte postavkama izvoza baze podataka.", + "backup_settings": "Postavke sigurnosne kopije baze podataka", + "backup_settings_description": "Upravljajte postavkama sigurnosne kopije baze podataka.", "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,23 +67,23 @@ "confirm_reprocess_all_faces": "Jeste li sigurni da Åželite ponovno obraditi sva lica? Ovo će također obrisati imenovane osobe.", "confirm_user_password_reset": "Jeste li sigurni da Åželite poniÅĄtiti lozinku korisnika {user}?", "confirm_user_pin_code_reset": "Jeste li sigurni da Åželite resetirati PIN korisnika {user}?", - "create_job": "Izradi zadatak", - "cron_expression": "Cron izraz (expression)", + "create_job": "Stvori posao", + "cron_expression": "Cron izraz", "cron_expression_description": "Postavite interval skeniranja koristeći cron format. Za viÅĄe informacija pogledajte npr. Crontab Guru", - "cron_expression_presets": "Cron unaprijed postavljene postavke izraza", + "cron_expression_presets": "Unaprijed postavljene postavke cron izraza", "disable_login": "Onemogući prijavu", - "duplicate_detection_job_description": "Pokrenite strojno učenje na materijalima kako biste otkrili slične slike. Oslanja se na Pametno PretraÅživanje", - "exclusion_pattern_description": "Uzorci izuzimanja omogućuju vam da zanemarite datoteke i mape prilikom skeniranja svoje biblioteke. Ovo je korisno ako imate mape koje sadrÅže datoteke koje ne Åželite uvesti, kao ÅĄto su RAW datoteke.", - "external_library_management": "Upravljanje vanjskom knjiÅžnicom", + "duplicate_detection_job_description": "Pokrenite strojno učenje na stavkama kako biste otkrili slične slike. Oslanja se na Pametno pretraÅživanje", + "exclusion_pattern_description": "Uzorci izuzimanja omogućuju vam da ignorirate datoteke i mape prilikom skeniranja svoje biblioteke. Ovo je korisno ako imate mape koje sadrÅže datoteke koje ne Åželite uvesti, kao ÅĄto su RAW datoteke.", + "external_library_management": "Upravljanje vanjskom bibliotekom", "face_detection": "Detekcija lica", - "face_detection_description": "Prepoznajte lica u sredstvima pomoću strojnog učenja. Za videozapise u obzir se uzima samo minijaturni prikaz. \"Sve\" (ponovno) obrađuje svu imovinu. \"Nedostaje\" stavlja u red čekanja sredstva koja joÅĄ nisu obrađena. Otkrivena lica bit će stavljena u red čekanja za prepoznavanje lica nakon dovrÅĄetka prepoznavanja lica, grupirajući ih u postojeće ili nove osobe.", - "facial_recognition_job_description": "Grupirajte otkrivena lica u osobe. Ovaj se korak pokreće nakon dovrÅĄetka prepoznavanja lica. \"Sve\" (ponovno) grupira sva lica. \"Nedostajuća\" lica u redovima kojima nije dodijeljena osoba.", + "face_detection_description": "Detektirajte lica u stavkama pomoću strojnog učenja. Za videozapise se uzima u obzir samo sličica. \"OsvjeÅži\" (ponovno) obrađuje sve stavke. \"PoniÅĄti\" dodatno briÅĄe sve trenutne podatke o licu. \"Nedostaje\" stavlja u red čekanja stavke koje joÅĄ nisu obrađene. Detektirana lica bit će stavljena u red čekanja za Prepoznavanje lica nakon ÅĄto se dovrÅĄi Detekcija lica, grupirajući ih u postojeće ili nove osobe.", + "facial_recognition_job_description": "Grupirajte otkrivena lica u osobe. Ovaj korak se izvrÅĄava nakon ÅĄto je Detekcija lica dovrÅĄena. \"Resetiraj\" (ponovno) grupira sva lica. \"Nedostaje\" stavlja u red lica kojima nije dodijeljena osoba.", "failed_job_command": "Naredba {command} nije uspjela za posao: {job}", - "force_delete_user_warning": "UPOZORENJE: Ovo će odmah ukloniti korisnika i sve pripadajuće podatke. Ovo se ne moÅže poniÅĄtiti i datoteke se ne mogu vratiti.", + "force_delete_user_warning": "UPOZORENJE: Ovo će odmah ukloniti korisnika i sve pripadajuće stavke. Ovo se ne moÅže poniÅĄtiti i datoteke se ne mogu vratiti.", "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_description": "Slika pune veličine bez metapodataka, koristi se prilikom zumiranja", + "image_fullsize_enabled": "Omogući generiranje slika 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", @@ -89,7 +91,7 @@ "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", + "image_preview_description": "Slika srednje veličine s uklonjenim metapodacima, koristi se prilikom pregledavanja jedne stavke i za strojno učenje", "image_preview_quality_description": "Kvaliteta pregleda od 1-100. ViÅĄe je bolje, ali proizvodi veće datoteke i moÅže smanjiti odziv aplikacije. Postavljanje niske vrijednosti moÅže utjecati na kvalitetu strojnog učenja.", "image_preview_title": "Postavke pregleda", "image_quality": "Kvaliteta", @@ -116,27 +118,31 @@ "library_scanning_enable_description": "Omogući periodično skeniranje biblioteke", "library_settings": "Externa biblioteka", "library_settings_description": "Upravljajte postavkama vanjske biblioteke", - "library_tasks_description": "Skeniraj eksterne biblioteke za nove i/ili promijenjene resurse", + "library_tasks_description": "Skeniraj vanjske biblioteke za nove i/ili promijenjene stavke", "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", "logging_enable_description": "Omogući zapisivanje", "logging_level_description": "Kada je omogućeno, koju razinu zapisivanja koristiti.", "logging_settings": "Zapisivanje", + "machine_learning_availability_checks": "Provjere dostupnosti", + "machine_learning_availability_checks_enabled": "Omogući provjere dostupnosti", + "machine_learning_availability_checks_interval": "Provjeri interval", + "machine_learning_availability_checks_interval_description": "Interval u milisekundama između provjera dostupnosti", "machine_learning_clip_model": "CLIP model", "machine_learning_clip_model_description": "Naziv CLIP modela navedenog ovdje. Imajte na umu da morate ponovno pokrenuti posao 'Pametno PretraÅživanje' za sve slike nakon promjene modela.", "machine_learning_duplicate_detection": "Detekcija Duplikata", "machine_learning_duplicate_detection_enabled": "Omogući detekciju duplikata", - "machine_learning_duplicate_detection_enabled_description": "Ako je onemogućeno, potpuno identična sredstva i dalje će biti deduplicirana.", + "machine_learning_duplicate_detection_enabled_description": "Ako je onemogućeno, potpuno identične stavke i dalje će biti deduplicirane.", "machine_learning_duplicate_detection_setting_description": "Upotrijebite CLIP ugradnje da biste pronaÅĄli vjerojatne duplikate", "machine_learning_enabled": "Uključi strojsko učenje", "machine_learning_enabled_description": "Ukoliko je ovo isključeno, sve funkcije strojnoga učenja biti će isključene bez obzira na postavke ispod.", - "machine_learning_facial_recognition": "Detekcija lica", + "machine_learning_facial_recognition": "Prepoznavanje lica", "machine_learning_facial_recognition_description": "Detektiraj, prepoznaj i grupiraj lica u fotografijama", "machine_learning_facial_recognition_model": "Model prepoznavanja lica", "machine_learning_facial_recognition_model_description": "Modeli su navedeni silaznim redoslijedom veličine. Veći modeli su sporiji i koriste viÅĄe memorije, ali daju bolje rezultate. Imajte na umu da morate ponovno pokrenuti posao detekcije lica za sve slike nakon promjene modela.", "machine_learning_facial_recognition_setting": "Omogući prepoznavanje lica", - "machine_learning_facial_recognition_setting_description": "Ako je onemogućeno, slike neće biti kodirane za prepoznavanje lica i neće popuniti odjeljak Ljudi na stranici IstraÅživanje.", + "machine_learning_facial_recognition_setting_description": "Ako je onemogućeno, slike neće biti kodirane za prepoznavanje lica i neće popuniti odjeljak Osobe na stranici IstraÅži.", "machine_learning_max_detection_distance": "Maksimalna udaljenost za detektiranje", "machine_learning_max_detection_distance_description": "Maksimalna udaljenost između dvije slike da bi se smatrale duplikatima, u rasponu od 0,001-0,1. ViÅĄe vrijednosti otkrit će viÅĄe duplikata, ali mogu rezultirati netočnim rezultatima.", "machine_learning_max_recognition_distance": "Maksimalna udaljenost za detekciju", @@ -144,7 +150,7 @@ "machine_learning_min_detection_score": "Minimalni rezultat otkrivanja", "machine_learning_min_detection_score_description": "Minimalni rezultat pouzdanosti za detektirano lice od 0-1. NiÅže vrijednosti otkrit će viÅĄe lica, ali mogu dovesti do laÅžno pozitivnih rezultata.", "machine_learning_min_recognized_faces": "Minimum prepoznatih lica", - "machine_learning_min_recognized_faces_description": "Najmanji broj prepoznatih lica za osobu koja se stvara. Povećanje toga čini prepoznavanje lica preciznijim po cijenu povećanja ÅĄanse da lice nije dodijeljeno osobi.", + "machine_learning_min_recognized_faces_description": "Najmanji broj prepoznatih lica za osobu koja se stvara. Povećanje toga čini Prepoznavanje lica preciznijim po cijenu povećanja ÅĄanse da lice nije dodijeljeno osobi.", "machine_learning_settings": "Postavke strojnog učenja", "machine_learning_settings_description": "Upravljajte značajkama i postavkama strojnog učenja", "machine_learning_smart_search": "Pametna pretraga", @@ -170,21 +176,21 @@ "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_extraction_job_description": "Izdvojite metapodatke iz svake stavke, kao ÅĄto su GPS, lica i rezolucija", "metadata_faces_import_setting": "Omogući uvoz lica", "metadata_faces_import_setting_description": "Uvezite lica iz EXIF podataka slike i sidecar datoteka", "metadata_settings": "Postavke Metapodataka", "metadata_settings_description": "Upravljanje postavkama metapodataka", "migration_job": "Migracija", - "migration_job_description": "Premjestite minijature za sredstva i lica u najnoviju strukturu mapa", + "migration_job_description": "Premjestite sličice za stavke i lica u najnoviju strukturu mapa", "nightly_tasks_cluster_faces_setting_description": "Pokreni prepoznavanje lica na novootkrivenim licima", "nightly_tasks_cluster_new_faces_setting": "Grupiraj nova lica", "nightly_tasks_database_cleanup_setting": "Zadaci čiÅĄÄ‡enja baze podataka", "nightly_tasks_database_cleanup_setting_description": "Očisti stare, istekle podatke iz baze podataka", "nightly_tasks_generate_memories_setting": "Generiraj uspomene", - "nightly_tasks_generate_memories_setting_description": "Stvori nove uspomene iz sadrÅžaja", + "nightly_tasks_generate_memories_setting_description": "Stvori nove uspomene iz stavki", "nightly_tasks_missing_thumbnails_setting": "Generiraj nedostajuće sličice", - "nightly_tasks_missing_thumbnails_setting_description": "Stavi u red čekanja sadrÅžaje bez sličica za generiranje sličica", + "nightly_tasks_missing_thumbnails_setting_description": "Stavke bez sličica stavi u red čekanja za generiranje sličica", "nightly_tasks_settings": "Postavke noćnih zadataka", "nightly_tasks_settings_description": "Upravljanje noćnim zadacima", "nightly_tasks_start_time_setting": "Vrijeme početka", @@ -193,7 +199,7 @@ "nightly_tasks_sync_quota_usage_setting_description": "AÅžuriraj korisničku kvotu za pohranu na temelju trenutne potroÅĄnje", "no_paths_added": "Nema dodanih putanja", "no_pattern_added": "Nije dodan uzorak", - "note_apply_storage_label_previous_assets": "Napomena: da biste primijenili Oznaku Pohrane na prethodno prenesena sredstva, pokrenite", + "note_apply_storage_label_previous_assets": "Napomena: Da biste primijenili Oznaku pohrane na prethodno prenesene stavke, pokrenite", "note_cannot_be_changed_later": "NAPOMENA: Ovo se ne moÅže promijeniti kasnije!", "notification_email_from_address": "Od adrese", "notification_email_from_address_description": "E-mail adresa poÅĄiljatelja, na primjer: \"Immich Photo Server \". Obavezno koristite adresu s koje vam je dopuÅĄteno slanje e-poÅĄte.", @@ -260,21 +266,21 @@ "sidecar_job": "Sidecar metapodaci", "sidecar_job_description": "Otkrijte ili sinkronizirajte sidecar metapodatke iz datotečnog sustava", "slideshow_duration_description": "Broj sekundi za prikaz svake slike", - "smart_search_job_description": "Pokrenite strojno učenje na sredstvima za podrÅĄku pametnog pretraÅživanja", - "storage_template_date_time_description": "Vremenska oznaka stvaranja sredstva koristi se za informacije o datumu i vremenu", + "smart_search_job_description": "Pokrenite strojno učenje na stavkama za koriÅĄtenje Pametnog pretraÅživanja", + "storage_template_date_time_description": "Vremenska oznaka stvaranja stavke koristi se za informacije o datumu i vremenu", "storage_template_date_time_sample": "Vrijeme uzorka {date}", "storage_template_enable_description": "Omogući mehanizam predloÅĄka za pohranu", "storage_template_hash_verification_enabled": "Omogućena hash provjera", "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": "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_description": "Primijenite trenutni {template} na prethodno prenesene stavke", + "storage_template_migration_info": "PredloÅžak za pohranu pretvorit će sve datotečne nastavke u mala slova. Promjene predloÅĄka primijenit će se samo na nove stavke. Da biste retroaktivno primijenili predloÅžak na prethodno prenesene stavke, 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_v2": "Kada je omogućena, ova će značajka automatski organizira datoteke prema predloÅĄku koji je definirao korisnik. Za viÅĄe informacija pogledajte dokumentaciju.", "storage_template_path_length": "PribliÅžno ograničenje duljine putanje: {length, number}/{limit, number}", "storage_template_settings": "PredloÅžak pohrane", - "storage_template_settings_description": "Upravljajte strukturom mape i nazivom datoteke učitanog sredstva", + "storage_template_settings_description": "Upravljajte strukturom mape i nazivom datoteke učitane stavke", "storage_template_user_label": "{label} je korisnička oznaka za pohranu", "system_settings": "Postavke Sustava", "tag_cleanup_job": "ČiÅĄÄ‡enje oznaka", @@ -292,7 +298,7 @@ "theme_settings": "Postavke tema", "theme_settings_description": "Upravljajte prilagodbom Immich web sučelja", "thumbnail_generation_job": "Generirajte sličice", - "thumbnail_generation_job_description": "Generirajte velike, male i zamućene sličice za svaki materijal, kao i sličice za svaku osobu", + "thumbnail_generation_job_description": "Generirajte velike, male i zamućene sličice za svaku stavku, kao i sličice za svaku osobu", "transcoding_acceleration_api": "API ubrzanja", "transcoding_acceleration_api_description": "API koji će komunicirati s vaÅĄim uređajem radi ubrzanja transkodiranja. Ova postavka je 'najveći trud': vratit će se na softversko transkodiranje u slučaju kvara. VP9 moÅže ili ne mora raditi ovisno o vaÅĄem hardveru.", "transcoding_acceleration_nvenc": "NVENC (zahtjeva NVIDIA GPU)", @@ -355,20 +361,20 @@ "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", - "trash_number_of_days_description": "Broj dana za drÅžanje sredstava u smeću prije njihovog trajnog uklanjanja", + "trash_number_of_days_description": "Broj dana za čuvanje stavki u smeću prije njihovog trajnog uklanjanja", "trash_settings": "Postavke Smeća", "trash_settings_description": "Upravljanje postavkama smeća", "unlink_all_oauth_accounts": "Odspoji sve OAuth račune", "unlink_all_oauth_accounts_description": "Zapamtite da odspojite sve OAuth račune prije prelaska na novog pruÅžatelja usluge.", "unlink_all_oauth_accounts_prompt": "Jeste li sigurni da Åželite odspojiti sve OAuth račune? Ovo će resetirati OAuth ID za svakog korisnika i ne moÅže se poniÅĄtiti.", "user_cleanup_job": "ČiÅĄÄ‡enje korisnika", - "user_delete_delay": "Račun i sredstva korisnika {user} bit će zakazani za trajno brisanje za {delay, plural, one {# day} other {# days}}.", + "user_delete_delay": "Račun i stavke korisnika {user} bit će stavljeni u red čekanja trajnog brisanja za {delay, plural, one {# dan} other {# dana}}.", "user_delete_delay_settings": "Brisanje odgode", - "user_delete_delay_settings_description": "Broj dana nakon uklanjanja za trajno brisanje korisničkog računa i imovine. Posao brisanja korisnika pokreće se u ponoć kako bi se provjerili korisnici koji su spremni za brisanje. Promjene ove postavke bit će procijenjene pri sljedećem izvrÅĄavanju.", - "user_delete_immediately": "Račun i sredstva korisnika {user} bit će stavljeni u red čekanja za trajno brisanje odmah.", - "user_delete_immediately_checkbox": "Stavite korisnika i imovinu u red za trenutačno brisanje", + "user_delete_delay_settings_description": "Broj dana nakon uklanjanja za trajno brisanje korisničkog računa i stavki. Posao brisanja korisnika pokreće se u ponoć kako bi se provjerili korisnici koji su spremni za brisanje. Promjene ove postavke bit će procijenjene pri sljedećem izvrÅĄavanju.", + "user_delete_immediately": "Račun i stavke korisnika {user} bit će stavljeni u red čekanja za trajno brisanje odmah.", + "user_delete_immediately_checkbox": "Stavite korisnika i stavke u red čekanja za trenutno brisanje", "user_details": "Detalji korisnika", - "user_management": "Upravljanje Korisnicima", + "user_management": "Upravljanje korisnicima", "user_password_has_been_reset": "Korisnička lozinka je poniÅĄtena:", "user_password_reset_description": "Molimo dostavite privremenu lozinku korisniku i obavijestite ga da će morati promijeniti lozinku pri sljedećoj prijavi.", "user_restore_description": "Račun korisnika {user} bit će vraćen.", @@ -387,18 +393,16 @@ "admin_password": "Admin lozinka", "administration": "Administracija", "advanced": "Napredno", - "advanced_settings_beta_timeline_subtitle": "Isprobaj novo iskustvo aplikacije", - "advanced_settings_beta_timeline_title": "Beta vremenska crta", "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: {level}", - "advanced_settings_prefer_remote_subtitle": "Neki uređaji sporo učitavaju sličice s lokalnih resursa. Aktivirajte ovu postavku kako biste umjesto toga učitali slike s udaljenih izvora.", + "advanced_settings_prefer_remote_subtitle": "Neki uređaji sporo učitavaju sličice s lokalnih stavki. 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": "Proxy zaglavlja", "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_subtitle": "Automatski izbriÅĄi ili obnovi stavku 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", @@ -423,14 +427,15 @@ "album_remove_user_confirmation": "Jeste li sigurni da Åželite ukloniti {user}?", "album_search_not_found": "Nema albuma koji odgovaraju vaÅĄem pretraÅživanju", "album_share_no_users": "Čini se da ste podijelili ovaj album sa svim korisnicima ili nemate nijednog korisnika s kojim biste ga dijelili.", + "album_summary": "SaÅžetak albuma", "album_updated": "Album aÅžuriran", - "album_updated_setting_description": "Primite obavijest e-poÅĄtom kada dijeljeni album ima nova sredstva", + "album_updated_setting_description": "Primite obavijest e-poÅĄtom kada dijeljeni album ima nove stavke", "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_remove": "Postoje problemi s uklanjanjem stavki 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", @@ -439,8 +444,8 @@ "albums": "Albumi", "albums_count": "{count, plural, one {{count, number} Album} other {{count, number} Albumi}}", "albums_default_sort_order": "Zadani redoslijed sortiranja albuma", - "albums_default_sort_order_description": "Početni redoslijed sortiranja elemenata prilikom izrade novih albuma.", - "albums_feature_description": "Zbirke resursa koje se mogu dijeliti s drugim korisnicima.", + "albums_default_sort_order_description": "Početni redoslijed sortiranja stavki prilikom izrade novih albuma.", + "albums_feature_description": "Zbirke stavki koje se mogu dijeliti s drugim korisnicima.", "albums_on_device_count": "Albumi na uređaju ({count})", "all": "Sve", "all_albums": "Svi albumi", @@ -459,58 +464,60 @@ "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", + "app_settings": "Postavke aplikacije", "appears_in": "Pojavljuje se u", "archive": "Arhiva", "archive_action_prompt": "{count} dodano u arhivu", "archive_or_unarchive_photo": "Arhivirajte ili dearhivirajte fotografiju", - "archive_page_no_archived_assets": "Nema arhiviranih resursa", + "archive_page_no_archived_assets": "Nema arhiviranih stavki", "archive_page_title": "Arhiviraj ({count})", "archive_size": "Veličina arhive", "archive_size_description": "Konfigurirajte veličinu arhive za preuzimanja (u GiB)", - "archived": "Ahrivirano", + "archived": "Arhivirano", "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_action_delete_err_read_only": "Nije moguće izbrisati stavke samo za čitanje, preskakanje", + "asset_action_share_err_offline": "Nije moguće dohvatiti izvanmreÅžne stavke, preskakanje", "asset_added_to_album": "Dodano 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": "SaÅžimanjeâ€Ļ", + "asset_description_updated": "Opis stavke je aÅžuriran", + "asset_filename_is_offline": "Stavka {filename} je izvan mreÅže", + "asset_has_unassigned_faces": "Stavka ima nedodijeljena lica", + "asset_hashing": "Hashiranjeâ€Ļ", "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": "Grupiraj stavke 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_list_settings_subtitle": "Postavke izgleda MreÅže fotografija", + "asset_list_settings_title": "MreÅža fotografija", + "asset_offline": "Stavka izvan mreÅže", + "asset_offline_description": "Ova vanjska stavka nije pronađena na disku. Za pomoć se obratite Immich administratoru.", + "asset_restored_successfully": "Stavka uspjeÅĄno obnovljena", "asset_skipped": "Preskočeno", "asset_skipped_in_trash": "U smeću", - "asset_uploaded": "Učitano", - "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_albums_count": "Dodano je {assetTotal} datoteka u {albumTotal} albuma", - "assets_cannot_be_added_to_album_count": "{count, plural, one {SadrÅžaj se ne moÅže dodati u album} other {{count} sadrÅžaja se ne mogu dodati u album}}", - "assets_cannot_be_added_to_albums": "{count, plural, one {Datoteka se ne moÅže dodati ni u jedan album} few {Datoteke se ne mogu dodati ni u jedan album} other {Datoteka se ne moÅže dodati ni u jedan album}}", - "assets_count": "{count, plural, one {# asset} other {# assets}}", - "assets_deleted_permanently": "{count} resurs(i) uspjeÅĄno uklonjeni", - "assets_deleted_permanently_from_server": "{count} resurs(i) trajno obrisan(i) sa Immich posluÅžitelja", - "assets_downloaded_failed": "{count, plural, one {Preuzeta # datoteka – {error} datoteka nije uspjela} other {Preuzeto je # datoteka – {error} datoteke nisu uspjele}}", - "assets_downloaded_successfully": "{count, plural, one {UspjeÅĄno preuzeta # datoteka} other {UspjeÅĄno preuzete # datoteke}}", - "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}}", + "asset_trashed": "Stavka premjeÅĄtena u smeće", + "asset_troubleshoot": "RjeÅĄavanje problema sa stavkom", + "asset_uploaded": "Preneseno", + "asset_uploading": "PrenoÅĄenjeâ€Ļ", + "asset_viewer_settings_subtitle": "Upravljajte postavkama vaÅĄeg preglednika galerije", + "asset_viewer_settings_title": "Preglednik stavki", + "assets": "Stavke", + "assets_added_count": "{count, plural, one {Dodana # stavka} few {Dodane # stavke} other {Dodano # stavki}}", + "assets_added_to_album_count": "{count, plural, one {Dodana # stavka} few {Dodane # stavke} other {Dodano # stavki}} u album", + "assets_added_to_albums_count": "{assetTotal, plural, one {Dodana # stavka} other {Dodano # stavki}} u {albumTotal, plural, one {# album} other {# albuma}}", + "assets_cannot_be_added_to_album_count": "{count, plural, one {Stavka se ne moÅže} other {Stavke se ne mogu}} dodati u album", + "assets_cannot_be_added_to_albums": "{count, plural, one {Stavka se ne moÅže} few {Stavke se ne mogu} other {Stavki se ne moÅže}} dodati ni u jedan album", + "assets_count": "{count, plural, one {# stavka} few {# stavke} other {# stavki}}", + "assets_deleted_permanently": "Trajno {count, plural, one {izbrisana # stavka} few {izbrisane # stavke} other {izbrisano # stavki}}", + "assets_deleted_permanently_from_server": "Trajno {count, plural, one {izbrisana # stavka} few {izbrisane # stavke} other {izbrisano # stavki}} s Immich servera", + "assets_downloaded_failed": "{count, plural, one {Preuzeta # datoteka – {error} datoteka nije uspjela} few {Preuzete # datoteke - {error} datoteke nisu uspjele} other {Preuzeto # datoteka – {error} datoteke nisu uspjele}}", + "assets_downloaded_successfully": "{count, plural, one {UspjeÅĄno preuzeta # datoteka} few {UspjeÅĄno preuzete # datoteke} other {UspjeÅĄno preueto # datoteka}}", + "assets_moved_to_trash_count": "{count, plural, one {# stavka premjeÅĄtena} few {# stavke premjeÅĄtene} other {# stavk premjeÅĄtenoi}} u smeće", + "assets_permanently_deleted_count": "Trajno {count, plural, one {izbrisana # stavka} few {izbrisane # stavke} other {izbrisano # stavki}}", + "assets_removed_count": "{count, plural, one {Uklonjena # stavka} few {Uklonjene # stavke} other {Uklonjeno # stavki}}", "assets_removed_permanently_from_device": "{count} 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}}", @@ -520,7 +527,7 @@ "assets_trashed_from_server": "{count} 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", "assets_were_part_of_albums_count": "{count, plural, one {Datoteka je već bila dio albuma} few {Datoteke su već bile dio albuma} other {Datoteka je već bila dio albuma}}", - "authorized_devices": "OvlaÅĄteni Uređaji", + "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", "autoplay_slideshow": "Automatsko prikazivanje slajdova", @@ -594,8 +601,6 @@ "backup_setting_subtitle": "Upravljajte postavkama učitavanja u pozadini i prvom planu", "backup_settings_subtitle": "Upravljaj postavkama slanja", "backward": "Unazad", - "beta_sync": "Beta status sinkronizacije", - "beta_sync_subtitle": "Upravljaj novim sustavom sinkronizacije", "biometric_auth_enabled": "Biometrijska autentikacija omogućena", "biometric_locked_out": "Zaključani ste iz biometrijske autentikacije", "biometric_no_options": "Nema dostupnih biometrijskih opcija", @@ -1038,7 +1043,7 @@ "export_database_description": "Izvezi SQLite bazu podataka", "extension": "ProÅĄirenje (Extension)", "external": "Vanjski", - "external_libraries": "Vanjske Biblioteke", + "external_libraries": "Vanjske biblioteke", "external_network": "Vanjska mreÅža", "external_network_sheet_info": "Kada niste na Åželjenoj Wi-Fi mreÅži, aplikacija će se povezati s posluÅžiteljem putem prve dostupne URL adrese s popisa ispod, redom od vrha prema dnu", "face_unassigned": "Nedodijeljeno", @@ -1052,7 +1057,7 @@ "favorites": "Omiljene", "favorites_page_no_favorites": "Nema pronađenih omiljenih stavki", "feature_photo_updated": "Istaknuta fotografija aÅžurirana", - "features": "Značajke (Features)", + "features": "Značajke", "features_setting_description": "Upravljajte značajkama aplikacije", "file_name": "Naziv datoteke", "file_name_or_extension": "Naziv ili ekstenzija datoteke", @@ -1224,7 +1229,7 @@ "location_picker_longitude_error": "Unesite valjanu geografsku duÅžinu", "location_picker_longitude_hint": "Unesite ovdje svoju geografsku duÅžinu", "lock": "Zaključaj", - "locked_folder": "Zaključana Mapa", + "locked_folder": "Zaključana mapa", "log_out": "Odjavi se", "log_out_all_devices": "Odjava sa svih uređaja", "logged_in_as": "Prijavljeni kao {user}", @@ -1904,6 +1909,8 @@ "sync_albums_manual_subtitle": "Sinkroniziraj sve prenesene videozapise i fotografije u odabrane albume za sigurnosnu kopiju", "sync_local": "Sinkroniziraj lokalno", "sync_remote": "Sinkroniziraj udaljeno", + "sync_status": "Status sinkronizacije", + "sync_status_subtitle": "Pregledajte i upravljajte sistemom sinkronizacije", "sync_upload_album_setting_subtitle": "Kreiraj i prenesi svoje fotografije i videozapise u odabrane albume na Immichu", "tag": "Oznaka", "tag_assets": "Označi stavke", diff --git a/i18n/hu.json b/i18n/hu.json index 490833a794..081bc12f99 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -28,6 +28,7 @@ "add_to_album": "FelvÊtel albumba", "add_to_album_bottom_sheet_added": "HozzÃĄadva a(z) \"{album}\" albumhoz", "add_to_album_bottom_sheet_already_exists": "MÃĄr benne van a(z) \"{album}\" albumban", + "add_to_album_bottom_sheet_some_local_assets": "NÊhÃĄny helyi elem nem adhatÃŗ hozzÃĄ az albumhoz", "add_to_album_toggle": "{album} kijelÃļlÊsÊnek vÃĄltÃĄsa", "add_to_albums": "HozzÃĄadÃĄs albumokhoz", "add_to_albums_count": "HozzÃĄadÃĄs albumokhoz ({count})", @@ -123,6 +124,13 @@ "logging_enable_description": "NaplÃŗzÃĄs engedÊlyezÊse", "logging_level_description": "Ha be van kapcsolva, milyen rÊszletessÊgÅą legyen a naplÃŗzÃĄs.", "logging_settings": "NaplÃŗzÃĄs", + "machine_learning_availability_checks": "ElÊrhetősÊg ellenőrzÊse", + "machine_learning_availability_checks_description": "Automatikusan keressen Ês vÃĄlasszon elÊrhető gÊpi tanulÃĄs szervereket", + "machine_learning_availability_checks_enabled": "ElÊrhetősÊg ellenőrzÊsÊnek bekapcsolÃĄsa", + "machine_learning_availability_checks_interval": "EllenőrzÊsi intervallum", + "machine_learning_availability_checks_interval_description": "ElÊrhetősÊg-ellenőrzÊsek kÃļzÃļtti kÊsleltetÊs milliszekundumban", + "machine_learning_availability_checks_timeout": "KÊrÊsek időkorlÃĄtja", + "machine_learning_availability_checks_timeout_description": "ElÊrhetősÊg-ellenőrzÊsek időkorlÃĄtja milliszekundumban", "machine_learning_clip_model": "CLIP modell", "machine_learning_clip_model_description": "Egy CLIP modell neve az itt felsoroltak kÃļzÃŧl. A modell megvÃĄltoztatÃĄsa utÃĄn Ãējra kell futtatni az 'Okos KeresÊs' feladatot minden kÊpre.", "machine_learning_duplicate_detection": "DuplikÃĄciÃŗk KeresÊse", @@ -168,7 +176,7 @@ "map_settings_description": "TÊrkÊp beÃĄllítÃĄsok kezelÊse", "map_style_description": "Egy style.json tÊrkÊptÊmÃĄra mutatÃŗ URL cím", "memory_cleanup_job": "MemÃŗria takarítÃĄs", - "memory_generate_job": "EmlÊk generÃĄlÃĄsa", + "memory_generate_job": "EmlÊkek generÃĄlÃĄsa", "metadata_extraction_job": "Metaadatok kinyerÊse", "metadata_extraction_job_description": "Metaadat informÃĄciÃŗk (pl. GPS, arcok Ês felbontÃĄs) kinyerÊse minden elemből", "metadata_faces_import_setting": "Arc importÃĄlÃĄs engedÊlyezÊse", @@ -387,8 +395,6 @@ "admin_password": "Admin JelszÃŗ", "administration": "AdminisztrÃĄciÃŗ", "advanced": "HaladÃŗ", - "advanced_settings_beta_timeline_subtitle": "PrÃŗbÃĄld ki az Ãēj alkalmazÃĄst", - "advanced_settings_beta_timeline_title": "BÊta Idővonal", "advanced_settings_enable_alternate_media_filter_subtitle": "Ezzel a beÃĄllítÃĄssal a szinkronizÃĄlÃĄs sorÃĄn alternatív kritÊriumok alapjÃĄn szÅąrheted a fÃĄjlokat. Csak akkor prÃŗbÃĄld ki, ha problÊmÃĄid vannak azzal, hogy az alkalmazÃĄs nem ismeri fel az Ãļsszes albumot.", "advanced_settings_enable_alternate_media_filter_title": "[KÍSÉRLETI] Alternatív eszkÃļz album szinkronizÃĄlÃĄsi szÅąrő hasznÃĄlata", "advanced_settings_log_level_title": "NaplÃŗzÃĄs szintje: {level}", @@ -396,6 +402,8 @@ "advanced_settings_prefer_remote_title": "TÃĄvoli kÊpek előnyben rÊszesítÊse", "advanced_settings_proxy_headers_subtitle": "Add meg azokat a proxy fejlÊceket, amiket az app elkÃŧldjÃļn minden hÃĄlÃŗzati kÊrÊsnÊl", "advanced_settings_proxy_headers_title": "Proxy FejlÊcek", + "advanced_settings_readonly_mode_subtitle": "Bekapcsol egy írÃĄsvÊdett mÃŗdot ahol csak fotÃŗkat nÊzni lehetsÊges, egyebek, mint tÃļbb kÊp kivÃĄlasztÃĄsa, megosztÃĄs, kivetítÊs Ês tÃļrlÊs ki vannak kapcsolva. Ki/bekapcsolhatÃŗ a felhasznÃĄlÃŗ ikonjÃĄrÃŗl a fő kÊpernyőn", + "advanced_settings_readonly_mode_title": "ÍrÃĄsvÊdett MÃŗd", "advanced_settings_self_signed_ssl_subtitle": "Nem ellenőrzi a szerver SSL tanÃēsítvÃĄnyÃĄt. ÖnalÃĄÃ­rt tanÃēsítvÃĄny esetÊn szÃŧksÊges beÃĄllítÃĄs.", "advanced_settings_self_signed_ssl_title": "ÖnalÃĄÃ­rt SSL tanÃēsítvÃĄnyok engedÊlyezÊse", "advanced_settings_sync_remote_deletions_subtitle": "Automatikusan tÃļrÃļlni vagy visszaÃĄllítani egy elemet ezen az eszkÃļzÃļn, ha az adott mÅąveletet a weben hajtottÃĄk vÊgre", @@ -423,6 +431,7 @@ "album_remove_user_confirmation": "Biztos, hogy el szeretnÊd tÃĄvolítani {user} felhasznÃĄlÃŗt?", "album_search_not_found": "Nem talÃĄlhatÃŗ a keresÊsnek megfelelő album", "album_share_no_users": "Úgy tÅąnik, hogy mÃĄr minden felhasznÃĄlÃŗval megosztottad ezt az albumot, vagy nincs senki, akivel meg tudnÃĄd osztani.", + "album_summary": "Album ÃļsszefogalalÃŗ", "album_updated": "Album frissÃŧlt", "album_updated_setting_description": "KÃŧldjÃļn email Êrtesítőt, amikor egy megosztott albumhoz Ãēj elemeket adnak hozzÃĄ", "album_user_left": "KilÊptÊl a(z) {album} albumbÃŗl", @@ -461,6 +470,7 @@ "app_bar_signout_dialog_title": "KijelentkezÊs", "app_settings": "AlkalmazÃĄs BeÃĄllítÃĄsok", "appears_in": "Itt szerepel", + "apply_count": "Alkalmaz ({count, number})", "archive": "Archívum", "archive_action_prompt": "{count} elem hozzÃĄadva az Archívumhoz", "archive_or_unarchive_photo": "FotÃŗ archivÃĄlÃĄsa vagy archivÃĄlÃĄsÃĄnak visszavonÃĄsa", @@ -493,6 +503,8 @@ "asset_restored_successfully": "Elem sikeresen helyreÃĄllítva", "asset_skipped": "Kihagyva", "asset_skipped_in_trash": "LomtÃĄrban", + "asset_trashed": "Elem lomtÃĄrba helyezve", + "asset_troubleshoot": "HibajavítÃĄs", "asset_uploaded": "FeltÃļltve", "asset_uploading": "FeltÃļltÊsâ€Ļ", "asset_viewer_settings_subtitle": "A kÊpnÊzegető beÃĄllítÃĄsainak kezelÊse", @@ -500,7 +512,7 @@ "assets": "Elemek", "assets_added_count": "{count, plural, other {# elem}} hozzÃĄadva", "assets_added_to_album_count": "{count, plural, other {# elem}} hozzÃĄadva az albumhoz", - "assets_added_to_albums_count": "Az {assetTotal, plural, one {elem} other {elemek}} hozzÃĄadva {albumTotal} albumhoz", + "assets_added_to_albums_count": "{assetTotal, plural, one {# elem} other {# elemek}} hozzÃĄadva {albumTotal, plural, one {# albumhoz} other {# albumokhoz}}", "assets_cannot_be_added_to_album_count": "{count, plural, one {Az elem} other {Az elemek}} nem adhatÃŗak hozzÃĄ az albumhoz", "assets_cannot_be_added_to_albums": "Az {count, plural, one {elemet} other {elemeket}} nem lehet hozzÃĄadni egy albumhoz sem", "assets_count": "{count, plural, other {# elem}}", @@ -526,8 +538,10 @@ "autoplay_slideshow": "Automatikus diavetítÊs", "back": "Vissza", "back_close_deselect": "Vissza, bezÃĄrÃĄs, vagy kijelÃļlÊs tÃļrlÊse", + "background_backup_running_error": "HÃĄttÊrben futÃŗ mentÊs folyamatban, kÊzi mentÊs nem indíthatÃŗ", "background_location_permission": "HÃĄttÊrben tÃļrtÊnő helymeghatÃĄrozÃĄsi engedÊly", "background_location_permission_content": "HÃĄlÃŗzatok automatikus vÃĄltÃĄsÃĄhoz az Immich-nek *mindenkÊppen* hozzÃĄ kell fÊrnie a pontos helyzethez, hogy az alkalmazÃĄs le tudja kÊrni a Wi-Fi hÃĄlÃŗzat nevÊt", + "background_options": "HÃĄttÊrbeli futÃĄs beÃĄllítÃĄsai", "backup": "MentÊs", "backup_album_selection_page_albums_device": "Ezen az eszkÃļzÃļn lÊvő albumok ({count})", "backup_album_selection_page_albums_tap": "Koppints a hozzÃĄadÃĄshoz, duplÃĄn koppints az eltÃĄvolítÃĄshoz", @@ -535,6 +549,7 @@ "backup_album_selection_page_select_albums": "VÃĄlassz albumokat", "backup_album_selection_page_selection_info": "ÖsszegzÊs", "backup_album_selection_page_total_assets": "Összes egyedi elem", + "backup_albums_sync": "Backup albumok szinkronizÃĄlÃĄsa", "backup_all": "Összes", "backup_background_service_backup_failed_message": "Az elemek mentÊse sikertelen. ÚjraprÃŗbÃĄlkozÃĄsâ€Ļ", "backup_background_service_connection_failed_message": "A szerverhez csatlakozÃĄs sikertelen. ÚjraprÃŗbÃĄlkozÃĄsâ€Ļ", @@ -584,6 +599,7 @@ "backup_controller_page_turn_on": "ElőtÊrben mentÊs bekapcsolÃĄsa", "backup_controller_page_uploading_file_info": "FÃĄjl informÃĄciÃŗk feltÃļltÊse", "backup_err_only_album": "Az utolsÃŗ albumot nem tudod tÃļrÃļlni", + "backup_error_sync_failed": "A szinkronizÃĄlÃĄs nem sikerÃŧlt. A biztonsÃĄgi mentÊs nem elkÊszíthető.", "backup_info_card_assets": "elemek", "backup_manual_cancelled": "Megszakítva", "backup_manual_in_progress": "FeltÃļltÊs mÃĄr folyamatban. PrÃŗbÃĄld meg kÊsőbb", @@ -594,8 +610,6 @@ "backup_setting_subtitle": "A hÃĄttÊrben Ês előtÊrben mentÊs beÃĄllítÃĄsainak kezelÊse", "backup_settings_subtitle": "FeltÃļltÊs beÃĄllítÃĄsai", "backward": "Visszafele", - "beta_sync": "BÊta SzinkronizÃĄlÃĄs Állapota", - "beta_sync_subtitle": "Az Ãēj szinkronizÃĄlÃĄsi rendszer kezelÊse", "biometric_auth_enabled": "Biometrikus azonosítÃĄs engedÊlyezve", "biometric_locked_out": "Ki vagy zÃĄrva a biometrikus azonosítÃĄsbÃŗl", "biometric_no_options": "Nincsen elÊrhető biometrikus azonosítÃĄs", @@ -653,6 +667,8 @@ "change_pin_code": "PIN kÃŗd megvÃĄltoztatÃĄsa", "change_your_password": "Jelszavad megvÃĄltoztatÃĄsa", "changed_visibility_successfully": "LÃĄthatÃŗsÃĄg sikeresen megvÃĄltoztatva", + "charging": "TÃļltÊs", + "charging_requirement_mobile_backup": "HÃĄttÊrben mentÊshez szÃŧksÊges, hogy az eszkÃļz tÃļltőn legyen", "check_corrupt_asset_backup": "SÊrÃŧlt elemek keresÊse a mentÊsben", "check_corrupt_asset_backup_button": "EllenőrzÊs", "check_corrupt_asset_backup_description": "Ezt az ellenőtzÊst csak Wi-Fi hÃĄlÃŗzaton futtasd Ês csak akkot, ha mÃĄr az Ãļsszes elem feltÃļltÊsre kerÃŧlt. A folyamat nÊhÃĄny percig is eltarthat.", @@ -739,6 +755,7 @@ "create_user": "FelhasznÃĄlÃŗ lÊtrehozÃĄsa", "created": "KÊszÃŧlt", "created_at": "LÊtrehozva", + "creating_linked_albums": "Kapcsolt albumok lÊtrehozÃĄsa...", "crop": "KivÃĄgÃĄs", "curated_object_page_title": "Dolgok", "current_device": "Ez az eszkÃļz", @@ -888,7 +905,9 @@ "error": "Hiba", "error_change_sort_album": "Album sorbarendezÊsÊnek megvÃĄltoztatÃĄsa sikertelen", "error_delete_face": "Hiba az arc tÃļrlÊse sorÃĄn", + "error_getting_places": "Hiba a helyek betÃļltÊsekor", "error_loading_image": "Hiba a kÊp betÃļltÊse kÃļzben", + "error_loading_partners": "Hiba a partnerek betÃļltÊsÊnÊl: {error}", "error_saving_image": "Hiba: {error}", "error_tag_face_bounding_box": "Hiba az arc megjelÃļlÊse kÃļzben - nem elÊrhetőek a hatÃĄrolÃŗ koordinÃĄtÃĄk", "error_title": "Hiba - valami fÊlresikerÃŧlt", @@ -1053,6 +1072,7 @@ "favorites_page_no_favorites": "Nem talÃĄlhatÃŗ kedvencnek jelÃļlt elem", "feature_photo_updated": "CímlapkÊp frissítve", "features": "Jellemzők", + "features_in_development": "Folyamatban lÊvő fejlesztÊsek", "features_setting_description": "Az alkalmazÃĄs jellemzőinek kezelÊse", "file_name": "FÃĄjlnÊv", "file_name_or_extension": "FÃĄjlnÊv vagy kiterjesztÊs", @@ -1073,12 +1093,15 @@ "gcast_enabled": "Google Cast", "gcast_enabled_description": "Ez a funkciÃŗ a Google-től tÃļlti be a mÅąkÃļdÊsÊhez szÃŧksÊges kÃŧlső adatokat.", "general": "ÁltalÃĄnos", + "geolocation_instruction_location": "Kattints egy elemre, amelynek ismert a helyszíne a pozíciÃŗ kivÃĄlasztÃĄsÃĄhoz, vagy vÃĄlassz a tÊrkÊpen", "get_help": "SegítsÊgkÊrÊs", "get_wifiname_error": "Nem sikerÃŧlt lekÊrni a Wi-Fi nevÊt. Győződj meg rÃŗla, hogy megadtad a szÃŧksÊges engedÊlyeket Ês csatlakoztÃĄl egy Wi-Fi hÃĄlÃŗzathoz", "getting_started": "Kezdő LÊpÊsek", "go_back": "VisszalÊpÊs", "go_to_folder": "UgrÃĄs a mappÃĄhoz", "go_to_search": "UgrÃĄs a keresÊshez", + "gps": "GPS", + "gps_missing": "Nincs GPS", "grant_permission": "EngedÊly megadÃĄsa", "group_albums_by": "Albumok csoportosítÃĄsa...", "group_country": "CsoportosítÃĄs orszÃĄg szerint", @@ -1214,6 +1237,7 @@ "local": "Helyi", "local_asset_cast_failed": "Nem lehet olyan elemet vetíteni, ami nincs a szerverre feltÃļltve", "local_assets": "Helyi Elemek", + "local_media_summary": "Helyi mÊdia ÃļsszegzÊs", "local_network": "Helyi hÃĄlÃŗzat", "local_network_sheet_info": "Az alkalmazÊs ezen az URL címen fogja elÊrni a szervert, ha a megadott WiFi hÃĄlÃŗzathoz van csatlankozva", "location_permission": "HelymeghatÃĄrozÃĄsi engedÊly", @@ -1225,6 +1249,7 @@ "location_picker_longitude_hint": "Ide írd a hosszÃēsÃĄgi kÃļrt", "lock": "ZÃĄrolÃĄs", "locked_folder": "ZÃĄrolt mappa", + "log_detail_title": "NaplÃŗk rÊszletei", "log_out": "KijelentkezÊs", "log_out_all_devices": "KijelentkezÊs Minden EszkÃļzÃļn", "logged_in_as": "BelÊpve: {user} nÊven", @@ -1255,6 +1280,7 @@ "login_password_changed_success": "JelszÃŗ sikeresen mÃŗdosítva", "logout_all_device_confirmation": "Biztos, hogy minden eszkÃļzÃļn ki szeretnÊl jelentkezni?", "logout_this_device_confirmation": "Biztos, hogy ki szeretnÊl jelentkezni ezen az eszkÃļzÃļn?", + "logs": "NaplÃŗk", "longitude": "HosszÃēsÃĄg", "look": "MegjelenítÊs", "loop_videos": "VideÃŗk ismÊtlÊse", @@ -1262,6 +1288,7 @@ "main_branch_warning": "Fejlesztői verziÃŗt hasznÃĄlsz. Javasoljuk a stabil verziÃŗ hasznÃĄlatÃĄt!", "main_menu": "FőmenÃŧ", "make": "GyÃĄrtÃŗ", + "manage_geolocation": "Helyadatok kezelÊse", "manage_shared_links": "MegosztÃĄsi linkek kezelÊse", "manage_sharing_with_partners": "Partnerekkel valÃŗ megosztÃĄs kezelÊse", "manage_the_app_settings": "AlkalmazÃĄs beÃĄllítÃĄsainak kezelÊse", @@ -1296,6 +1323,7 @@ "mark_as_read": "MegjelÃļlÊs olvasottkÊnt", "marked_all_as_read": "Összes megjelÃļlve olvasottkÊnt", "matches": "Azonosak", + "matching_assets": "KapcsolÃŗdÃŗ elemek", "media_type": "MÊdiatípus", "memories": "EmlÊkek", "memories_all_caught_up": "NaprakÊsz vagy", @@ -1336,6 +1364,7 @@ "name_or_nickname": "NÊv vagy becenÊv", "network_requirement_photos_upload": "Mobil adatforgalmat hasznÃĄljon a fÊnykÊpek biztonsÃĄgi mentÊsÊhez", "network_requirement_videos_upload": "Mobil adatforgalmat hasznÃĄljon a videÃŗk biztonsÃĄgi mentÊsÊhez", + "network_requirements": "HÃĄlÃŗzati kÃļvetelmÊnyek", "network_requirements_updated": "A hÃĄlÃŗzat megvÃĄltozott, a biztonsÃĄgi mentÊsi sor visszaÃĄllítÃĄsa", "networking_settings": "HÃĄlÃŗzat", "networking_subtitle": "Szerver vÊgpont beÃĄllítÃĄsok kezelÊse", @@ -1346,6 +1375,7 @@ "new_person": "Új szemÊly", "new_pin_code": "Új PIN kÃŗd", "new_pin_code_subtitle": "Ez az első alkalom hogy megnyitod a zÃĄrolt mappÃĄt. Hozz lÊtre egy jelszÃŗt a mappa biztonsÃĄgos elÊrÊsÊhez", + "new_timeline": "Új idővonal", "new_user_created": "Új felhasznÃĄlÃŗ lÊtrehozva", "new_version_available": "ÚJ VERZIÓ ÉRHETŐ EL", "newest_first": "LegÃējabb előszÃļr", @@ -1359,20 +1389,25 @@ "no_assets_message": "KATTINTS AZ ELSŐ FÉNYKÉP FELTÖLTÉSÉHEZ", "no_assets_to_show": "Nincs megjeleníthető elem", "no_cast_devices_found": "Nem talÃĄlhatÃŗ eszkÃļz vetítÊshez", + "no_checksum_local": "Nincs elÊrhető ellenőrzőÃļsszeg - a helyi eszkÃļzÃļk nem kÊrhetők le", + "no_checksum_remote": "Nincs elÊrhető ellenőrzőÃļsszeg - a tÃĄvoli eszkÃļz nem kÊrhető le", "no_duplicates_found": "Nem talÃĄlhatÃŗk duplikÃĄtumok.", "no_exif_info_available": "Nincs elÊrhető Exif informÃĄciÃŗ", "no_explore_results_message": "TÃļlts fel tÃļbb kÊpet, hogy bÃļngÊszhesd a gyÅąjtemÊnyed.", "no_favorites_message": "Add hozzÃĄ a kedvencekhez, hogy gyorsan megtalÃĄld a legjobb kÊpeidet Ês videÃŗidat", "no_libraries_message": "Hozz lÊtre kÃŧlső kÊptÃĄrat a fÊnykÊpeid Ês videÃŗid megtekintÊsÊhez", + "no_local_assets_found": "Nem talÃĄlhatÃŗk helyi eszkÃļzÃļk ezzel az ellenőrzőÃļsszeggel", "no_locked_photos_message": "A zÃĄrolt mappÃĄban elhelyezett fotÃŗk Ês videÃŗk rejtettek, Ês nem jelennek meg a kÃļnyvtÃĄrad bÃļngÊszÊse vagy keresÊse kÃļzben sem.", "no_name": "Nincs NÊv", "no_notifications": "Nincsenek ÊrtesítÊsek", "no_people_found": "Nem talÃĄlhatÃŗ szemÊly", "no_places": "Nincsenek helyek", + "no_remote_assets_found": "Nem talÃĄlhatÃŗk tÃĄvoli eszkÃļzÃļk ezzel az ellenőrzőÃļsszeggel", "no_results": "Nincs talÃĄlat", "no_results_description": "PrÃŗbÃĄlkozz szinonimÃĄkkal vagy ÃĄltalÃĄnosabb kulcsszavakkal", "no_shared_albums_message": "Hozz lÊtre egy Ãēj albumot, hogy megoszthasd fÊnykÊpeid Ês videÃŗid mÃĄsokkal", "no_uploads_in_progress": "Nincs folyamatban lÊvő feltÃļltÊs", + "not_available": "N/A", "not_in_any_album": "Nincs albumban", "not_selected": "Nincs kivÃĄlasztva", "note_apply_storage_label_to_previously_uploaded assets": "MegjegyzÊs: a korÃĄbban feltÃļltÃļtt elemek TÃĄrhely CímkÊzÊsÊhez futtasd a(z)", @@ -1407,6 +1442,8 @@ "open_the_search_filters": "KeresÊsi szÅąrők megnyitÃĄsa", "options": "BeÃĄllítÃĄsok", "or": "vagy", + "organize_into_albums": "Albumokba rendezÊs", + "organize_into_albums_description": "MeglÊvő fotÃŗk albumokba helyezÊse, a jelenlegi szinkronizÃĄciÃŗs beÃĄllítÃĄsok alapjÃĄn", "organize_your_library": "Rendszerezd a kÊptÃĄradat", "original": "eredeti", "other": "EgyÊb", @@ -1492,6 +1529,7 @@ "port": "Port", "preferences_settings_subtitle": "AlkalmazÃĄsbeÃĄllítÃĄsok kezelÊse", "preferences_settings_title": "BeÃĄllítÃĄsok", + "preparing": "ElőkÊszítÊs", "preset": "Sablon", "preview": "ElőnÊzet", "previous": "Előző", @@ -1508,6 +1546,7 @@ "profile_drawer_client_out_of_date_minor": "A mobilalkalmazÃĄs elavult. KÊrjÃŧk, frissítsd a legfrisebb alverziÃŗra.", "profile_drawer_client_server_up_to_date": "A Kliens Ês a Szerver is naprakÊsz", "profile_drawer_github": "GitHub", + "profile_drawer_readonly_mode": "Csak olvashatÃŗ mÃŗd engedÊlyezve. A kilÊpÊshez hosszan nyomja meg a felhasznÃĄlÃŗi avatar ikont.", "profile_drawer_server_out_of_date_major": "A szerver elavult. KÊrjÃŧk, frissítsd a legfrisebb főverziÃŗra.", "profile_drawer_server_out_of_date_minor": "A szerver elavult. KÊrjÃŧk, frissítsd a legfrisebb alverziÃŗra.", "profile_image_of_user": "{user} profilkÊpe", @@ -1546,6 +1585,7 @@ "purchase_server_description_2": "TÃĄmogatÃŗ stÃĄtusz", "purchase_server_title": "Szerver", "purchase_settings_server_activated": "A szerver termÊkkulcsot az admin kezeli", + "query_asset_id": "LekÊrdezÊsi eszkÃļz azonosítÃŗja", "queue_status": "Feldolgozva {count}/{total}", "rating": "ÉrtÊkelÊs csillagokkal", "rating_clear": "ÉrtÊkelÊs tÃļrlÊse", @@ -1553,6 +1593,9 @@ "rating_description": "Exif ÊrtÊkelÊs megjelenítÊse az infÃŗpanelen", "reaction_options": "ReakciÃŗ lehetősÊgek", "read_changelog": "VÃĄltozÃĄsnaplÃŗ ElolvasÃĄsa", + "readonly_mode_disabled": "Csak olvashatÃŗ mÃŗd kikapcsolva", + "readonly_mode_enabled": "Csak olvashatÃŗ mÃŗd bekapcsolva", + "ready_for_upload": "KÊszen ÃĄll a feltÃļltÊsre", "reassign": "HozzÃĄrendel", "reassigned_assets_to_existing_person": "{count, plural, other {# elem}} hozzÃĄrendelve{name, select, null { egy lÊtező szemÊlyhez} other {: {name}}}", "reassigned_assets_to_new_person": "{count, plural, other {# elem}} hozzÃĄrendelve egy Ãēj szemÊlyhez", @@ -1577,6 +1620,7 @@ "regenerating_thumbnails": "BÊlyegkÊpek ÃējragenerÃĄlÃĄsa folyamatban", "remote": "TÃĄvoli", "remote_assets": "TÃĄvoli Elemek", + "remote_media_summary": "TÃĄvoli mÊdiaÃļsszefoglalÃŗ", "remove": "EltÃĄvolítÃĄs", "remove_assets_album_confirmation": "Biztosan el szeretnÊl tÃĄvolítani {count, plural, one {# elemet} other {# elemet}} az albumbÃŗl?", "remove_assets_shared_link_confirmation": "Biztosan el szeretnÊl tÃĄvolítani {count, plural, one {# elemet} other {# elemet}} ebből a megosztott linkből?", @@ -1629,6 +1673,7 @@ "restore_user": "FelhasznÃĄlÃŗ visszaÃĄllítÃĄsa", "restored_asset": "VisszaÃĄllított elem", "resume": "FolytatÃĄs", + "resume_paused_jobs": "FolytatÃĄs {count, plural, one {# paused job} other {# paused jobs}}", "retry_upload": "FeltÃļltÊs ÃējraprÃŗbÃĄlÃĄsa", "review_duplicates": "DuplikÃĄtumok ÃĄttekintÊse", "review_large_files": "Nagy fÃĄjlok ÃĄttekintÊse", @@ -1722,6 +1767,7 @@ "select_user_for_sharing_page_err_album": "Az album lÊtrehozÃĄsa sikertelen", "selected": "KivÃĄlasztott", "selected_count": "{count, plural, other {# kivÃĄlasztva}}", + "selected_gps_coordinates": "KivÃĄlasztott GPS KordinÃĄtÃĄk", "send_message": "Üzenet kÃŧldÊse", "send_welcome_email": "ÜdvÃļzlő email kÃŧldÊse", "server_endpoint": "Szerver VÊgpont", @@ -1850,6 +1896,7 @@ "show_slideshow_transition": "VetítÊs ÃĄttÅąnÊsi effekt mutatÃĄsa", "show_supporter_badge": "TÃĄmogatÃŗ jelvÊny", "show_supporter_badge_description": "TÃĄmogatÃŗ jelvÊny mutatÃĄsa", + "show_text_search_menu": "Mutasd a szÃļvegkeresÊsi menÃŧt", "shuffle": "VÊletlenszerÅą", "sidebar": "OldalsÃĄv", "sidebar_display_description": "NÊzet link megjelenítÊse az oldalsÃĄvban", @@ -1880,6 +1927,7 @@ "stacktrace": "Hiba leírÃĄsa", "start": "Elindít", "start_date": "Kezdő dÃĄtum", + "start_date_before_end_date": "A kezdeti dÃĄtumnak a befejezÊsi dÃĄtum előtt kell lennie", "state": "Megye/Állam", "status": "Állapot", "stop_casting": "VetítÊs megszÃŧntetÊse", @@ -1904,6 +1952,8 @@ "sync_albums_manual_subtitle": "Összes fotÃŗ Ês videÃŗ lÊtrehozÃĄsa Ês szinkronizÃĄlÃĄsa a kivÃĄlasztott Immich albumokba", "sync_local": "Helyi SzinkronizÃĄlÃĄsa", "sync_remote": "TÃĄvoli SzinkronizÃĄlÃĄsa", + "sync_status": "SzinkronizÃĄlÃĄs ÃĄllapota", + "sync_status_subtitle": "SzinkronizÃĄlÃĄs megtekintÊse Ês kezelÊse", "sync_upload_album_setting_subtitle": "FotÃŗk Ês videÃŗk lÊtrehozÃĄsa Ês szinkronizÃĄlÃĄsa a kivÃĄlasztott Immich albumba", "tag": "Címke", "tag_assets": "Elemek címkÊzÊse", @@ -1941,7 +1991,9 @@ "to_change_password": "JelszÃŗ megvÃĄltoztatÃĄsa", "to_favorite": "Kedvenc", "to_login": "BejelentkezÊs", + "to_multi_select": "tÃļbb elem kivÃĄlasztÃĄsÃĄhoz", "to_parent": "Egy szinttel feljebb", + "to_select": "a kivÃĄlasztÃĄshoz", "to_trash": "LomtÃĄrba helyezÊs", "toggle_settings": "BeÃĄllítÃĄsok ÃĄtÃĄllítÃĄsa", "total": "Összesen", @@ -1961,6 +2013,7 @@ "trash_page_select_assets_btn": "Elemek kivÃĄlasztÃĄsa", "trash_page_title": "LomtÃĄr ({count})", "trashed_items_will_be_permanently_deleted_after": "A lomtÃĄrban lÊvő elemek vÊglegesen tÃļrlÊsre kerÃŧlnek {days, plural, other {# nap}} mÃēlva.", + "troubleshoot": "HibaelhÃĄrítÃĄs", "type": "Típus", "unable_to_change_pin_code": "Sikertelen PIN kÃŗd vÃĄltoztatÃĄs", "unable_to_setup_pin_code": "Sikertelen PIN kÃŗd beÃĄllítÃĄs", @@ -1991,6 +2044,7 @@ "unstacked_assets_count": "{count, plural, other {# elemből}} ÃĄllÃŗ csoport szÊtszedve", "untagged": "Címke eltÃĄvolítva", "up_next": "KÃļvetkezik", + "update_location_action_prompt": "{count} elem pozíciÃŗjÃĄnak frissítÊse a kÃļvetkezővel:", "updated_at": "Frissített", "updated_password": "JelszÃŗ megvÃĄltoztatva", "upload": "FeltÃļltÊs", @@ -2057,6 +2111,7 @@ "view_next_asset": "KÃļvetkező elem megtekintÊse", "view_previous_asset": "Előző elem megtekintÊse", "view_qr_code": "QR kÃŗd megtekintÊse", + "view_similar_photos": "HasonlÃŗ kÊpek keresÊse", "view_stack": "Csoport MegtekintÊse", "view_user": "FelhasznÃĄlÃŗ MegtekintÊse", "viewer_remove_from_stack": "EltÃĄvolít a CsoportbÃŗl", @@ -2075,5 +2130,6 @@ "yes": "Igen", "you_dont_have_any_shared_links": "Nincsenek megosztott linkjeid", "your_wifi_name": "A Wi-Fi hÃĄlÃŗzatod neve", - "zoom_image": "KÊp NagyítÃĄsa" + "zoom_image": "KÊp NagyítÃĄsa", + "zoom_to_bounds": "NagyítÃĄs a hatÃĄrokhoz" } diff --git a/i18n/id.json b/i18n/id.json index dd9e8e009e..abf8ef4747 100644 --- a/i18n/id.json +++ b/i18n/id.json @@ -28,8 +28,12 @@ "add_to_album": "Tambahkan ke album", "add_to_album_bottom_sheet_added": "Ditambahkan ke {album}", "add_to_album_bottom_sheet_already_exists": "Sudah ada di {album}", + "add_to_album_bottom_sheet_some_local_assets": "Beberapa aset lokal tidak dapat ditambahkan ke album", + "add_to_album_toggle": "Masukkan ke {album} / Batalkan dari {album}", "add_to_albums": "Tambahkan ke album", + "add_to_albums_count": "Tambahkan ke album ({count})", "add_to_shared_album": "Tambahkan ke album terbagi", + "add_upload_to_stack": "Tambahkan unggahan ke tumpukan", "add_url": "Tambahkan URL", "added_to_archive": "Ditambahkan ke arsip", "added_to_favorites": "Ditambahkan ke favorit", @@ -121,6 +125,13 @@ "logging_enable_description": "Aktifkan log", "logging_level_description": "Ketika diaktifkan, tingkat log apa yang digunakan.", "logging_settings": "Penulisan log", + "machine_learning_availability_checks": "Pemeriksaan ketersediaan", + "machine_learning_availability_checks_description": "Secara otomatis mendeteksi dan memprioritaskan server machine learning yang tersedia", + "machine_learning_availability_checks_enabled": "Aktifkan pemeriksaan ketersediaan", + "machine_learning_availability_checks_interval": "Interval pemeriksaan", + "machine_learning_availability_checks_interval_description": "Interval dalam milidetik antar pemeriksaan ketersediaan", + "machine_learning_availability_checks_timeout": "Batas waktu permintaan", + "machine_learning_availability_checks_timeout_description": "Batas waktu dalam milidetik untuk pemeriksaan ketersediaan", "machine_learning_clip_model": "Model CLIP", "machine_learning_clip_model_description": "Nama model CLIP yang didaftarkan di sini. Anda harus menjalankan ulang tugas 'Pencarian Otomatis' untuk semua gambar ketika mengganti model.", "machine_learning_duplicate_detection": "Deteksi Duplikat", @@ -385,8 +396,6 @@ "admin_password": "Kata Sandi Admin", "administration": "Administrasi", "advanced": "Tingkat lanjut", - "advanced_settings_beta_timeline_subtitle": "Coba pengalaman aplikasi baru", - "advanced_settings_beta_timeline_title": "Garis waktu Beta", "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: {level}", @@ -394,6 +403,8 @@ "advanced_settings_prefer_remote_title": "Prioritaskan gambar dari server", "advanced_settings_proxy_headers_subtitle": "Tentukan header proxy yang harus dikirim Immich dengan setiap permintaan jaringan", "advanced_settings_proxy_headers_title": "Tajuk Proksi", + "advanced_settings_readonly_mode_subtitle": "Mengaktifkan mode baca-saja, di mana foto hanya bisa dilihat. Fitur seperti memilih banyak foto, berbagi, cast, dan hapus akan dinonaktifkan. Mode baca-saja bisa diaktifkan/nonaktifkan lewat avatar pengguna di layar utama", + "advanced_settings_readonly_mode_title": "Mode Baca-Saja", "advanced_settings_self_signed_ssl_subtitle": "Melewati verifikasi sertifikat SSL untuk titik akhir server. Diperlukan untuk sertifikat yang ditandatangani sendiri.", "advanced_settings_self_signed_ssl_title": "Izinkan sertifikat SSL yang ditandatangani sendiri", "advanced_settings_sync_remote_deletions_subtitle": "Hapus atau pulihkan aset pada perangkat ini secara otomatis ketika tindakan dilakukan di web", @@ -421,6 +432,7 @@ "album_remove_user_confirmation": "Apakah Anda yakin ingin mengeluarkan {user}?", "album_search_not_found": "Tidak ada album yang ditemukan sesuai pencarian Anda", "album_share_no_users": "Sepertinya Anda telah membagikan album ini dengan semua pengguna atau tidak memiliki pengguna siapa pun untuk dibagikan.", + "album_summary": "Ringkasan album", "album_updated": "Album diperbarui", "album_updated_setting_description": "Terima notifikasi surel ketika album terbagi memiliki aset baru", "album_user_left": "Keluar dari {album}", @@ -459,6 +471,7 @@ "app_bar_signout_dialog_title": "Keluar akun", "app_settings": "Pengaturan Aplikasi", "appears_in": "Muncul dalam", + "apply_count": "Terapkan ({count, number})", "archive": "Arsip", "archive_action_prompt": "{count} telah ditambahkan ke Arsip", "archive_or_unarchive_photo": "Arsipkan atau batalkan pengarsipan foto", @@ -491,6 +504,8 @@ "asset_restored_successfully": "Aset telah berhasil dipulihkan", "asset_skipped": "Dilewati", "asset_skipped_in_trash": "Dalam sampah", + "asset_trashed": "Aset dibuang", + "asset_troubleshoot": "Troubleshoot Aset", "asset_uploaded": "Sudah diunggah", "asset_uploading": "Mengunggahâ€Ļ", "asset_viewer_settings_subtitle": "Kelola pengaturan penampil galeri Anda", @@ -498,7 +513,9 @@ "assets": "Aset", "assets_added_count": "{count, plural, one {# aset} other {# aset}} ditambahkan", "assets_added_to_album_count": "Ditambahkan {count, plural, one {# aset} other {# aset}} ke album", + "assets_added_to_albums_count": "Ditambahkan {assetTotal, plural, one {# aset} other {# aset}} ke {albumTotal, plural, one {# album} other {# album}}", "assets_cannot_be_added_to_album_count": "{count, plural, one {Asset} other {Assets}} tidak dapat ditambahkan ke album", + "assets_cannot_be_added_to_albums": "{count, plural, one {Aset} other {Aset}} tidak dapat ditambahkan ke album mana pun", "assets_count": "{count, plural, one {# aset} other {# aset}}", "assets_deleted_permanently": "{count} aset dihapus secara permanen", "assets_deleted_permanently_from_server": "{count} aset dihapus secara permanen dari server Immich", @@ -515,14 +532,17 @@ "assets_trashed_count": "{count, plural, one {# aset} other {# aset}} dibuang ke sampah", "assets_trashed_from_server": "{count} aset dipindahkan ke sampah dari server Immich", "assets_were_part_of_album_count": "{count, plural, one {Aset telah} other {Aset telah}} menjadi bagian dari album", + "assets_were_part_of_albums_count": "{count, plural, one {Aset sudah} other {Aset sudah}} ada di album", "authorized_devices": "Perangkat Terautentikasi", "automatic_endpoint_switching_subtitle": "Sambungkan secara lokal melalui Wi-Fi yang telah ditetapkan saat tersedia, dan gunakan koneksi alternatif lain", "automatic_endpoint_switching_title": "Peralihan URL otomatis", "autoplay_slideshow": "Putar otomatis tayangan slide", "back": "Kembali", "back_close_deselect": "Kembali, tutup, atau batalkan pemilihan", + "background_backup_running_error": "Cadangan latar belakang sedang berjalan, tidak dapat memulai cadangan manual", "background_location_permission": "Izin lokasi latar belakang", "background_location_permission_content": "Untuk beralih jaringan saat berjalan di latar belakang, Immich harus selalu memiliki akses lokasi akurat agar aplikasi dapat membaca nama jaringan Wi-Fi", + "background_options": "Opsi Latar Belakang", "backup": "Cadangkan", "backup_album_selection_page_albums_device": "Album di perangkat ({count})", "backup_album_selection_page_albums_tap": "Sentuh untuk memilih, sentuh 2x untuk mengecualikan", @@ -530,6 +550,7 @@ "backup_album_selection_page_select_albums": "Pilih album", "backup_album_selection_page_selection_info": "Info Pilihan", "backup_album_selection_page_total_assets": "Total aset unik", + "backup_albums_sync": "Sinkronisasi cadangan album", "backup_all": "Semua", "backup_background_service_backup_failed_message": "Gagal mencadangkan aset. Mencoba lagiâ€Ļ", "backup_background_service_connection_failed_message": "Koneksi ke server gagal. Mencoba ulangâ€Ļ", @@ -579,6 +600,7 @@ "backup_controller_page_turn_on": "Aktifkan pencadangan latar depan", "backup_controller_page_uploading_file_info": "Mengunggah info file", "backup_err_only_album": "Tidak dapat menghapus album", + "backup_error_sync_failed": "Sinkronisasi gagal. Tidak dapat memproses cadangan.", "backup_info_card_assets": "aset", "backup_manual_cancelled": "Dibatalkan", "backup_manual_in_progress": "Dalam proses unggah. Coba lagi nanti", @@ -589,8 +611,6 @@ "backup_setting_subtitle": "Kelola pengaturan unggahan latar belakang dan latar depan", "backup_settings_subtitle": "Kelola pengaturan unggahan", "backward": "Maju", - "beta_sync": "Status proses sinkronisasi versi beta", - "beta_sync_subtitle": "Kelola sistem sinkronisasi baru", "biometric_auth_enabled": "Autentikasi biometrik diaktifkan", "biometric_locked_out": "Anda terkunci oleh autentikasi biometrik", "biometric_no_options": "Opsi biometrik tidak tersedia", @@ -648,6 +668,8 @@ "change_pin_code": "Ubah kode PIN", "change_your_password": "Ubah kata sandi Anda", "changed_visibility_successfully": "Keterlihatan berhasil diubah", + "charging": "Mengisi daya", + "charging_requirement_mobile_backup": "Cadangan latar belakang memerlukan perangkat dalam keadaan mengisi daya", "check_corrupt_asset_backup": "Periksa cadangan aset yang rusak", "check_corrupt_asset_backup_button": "Lakukan pemeriksaan", "check_corrupt_asset_backup_description": "Jalankan pemeriksaan ini hanya melalui Wi-Fi dan setelah semua aset dicadangkan. Prosedur ini mungkin memerlukan waktu beberapa menit.", @@ -734,6 +756,7 @@ "create_user": "Buat pengguna", "created": "Dibuat", "created_at": "Dibuat", + "creating_linked_albums": "Membuat album tertaut...", "crop": "Pangkas", "curated_object_page_title": "Benda", "current_device": "Perangkat saat ini", @@ -883,7 +906,9 @@ "error": "Eror", "error_change_sort_album": "Gagal mengubah urutan album", "error_delete_face": "Terjadi kesalahan menghapus wajah dari aset", + "error_getting_places": "Kesalahan saat mengambil lokasi", "error_loading_image": "Terjadi eror memuat gambar", + "error_loading_partners": "Kesalahan saat memuat partner: {error}", "error_saving_image": "Kesalahan: {error}", "error_tag_face_bounding_box": "Galat saat memberi tag wajah – tidak dapat memperoleh koordinat kotak pembatas", "error_title": "Eror - Ada yang salah", @@ -1048,6 +1073,7 @@ "favorites_page_no_favorites": "Tidak ada aset favorit", "feature_photo_updated": "Foto terfitur diperbarui", "features": "Fitur", + "features_in_development": "Fitur dalam Pengembangan", "features_setting_description": "Kelola fitur aplikasi", "file_name": "Nama berkas", "file_name_or_extension": "Nama berkas atau ekstensi", @@ -1057,6 +1083,7 @@ "filter_people": "Saring orang", "filter_places": "Saring tempat", "find_them_fast": "Temukan dengan cepat berdasarkan nama dengan pencarian", + "first": "Pertama", "fix_incorrect_match": "Perbaiki pencocokan salah", "folder": "Berkas", "folder_not_found": "Berkas tidak ditemukan", @@ -1067,12 +1094,15 @@ "gcast_enabled": "Google Cast", "gcast_enabled_description": "Fitur ini memuat sumber daya eksternal dari Google agar dapat berfungsi.", "general": "Umum", + "geolocation_instruction_location": "Klik aset yang memiliki koordinat GPS untuk menggunakan lokasinya, atau pilih lokasi langsung dari peta", "get_help": "Dapatkan Bantuan", "get_wifiname_error": "Tidak dapat mendapatkan nama Wi-Fi. Pastikan Anda telah memberikan izin yang diperlukan dan terhubung ke jaringan Wi-Fi", "getting_started": "Memulai", "go_back": "Kembali", "go_to_folder": "Pergi ke folder", "go_to_search": "Pergi ke pencarian", + "gps": "GPS", + "gps_missing": "Tidak ada GPS", "grant_permission": "Izinkan", "group_albums_by": "Kelompokkan album berdasarkan...", "group_country": "Kelompokkan berdasarkan negara", @@ -1178,6 +1208,7 @@ "language_search_hint": "Mencari Bahasa...", "language_setting_description": "Pilih bahasa Anda yang disukai", "large_files": "File Besar", + "last": "Terakhir", "last_seen": "Terakhir dilihat", "latest_version": "Versi Terkini", "latitude": "Lintang", @@ -1196,6 +1227,7 @@ "library_page_sort_title": "Judul album", "licenses": "Lisensi", "light": "Terang", + "like": "Suka", "like_deleted": "Suka dihapus", "link_motion_video": "Tautan video gerak", "link_to_oauth": "Tautkan ke OAuth", @@ -1206,6 +1238,7 @@ "local": "Lokal", "local_asset_cast_failed": "Tidak dapat melakukan cast aset yang belum diunggah ke server", "local_assets": "Aset Lokal", + "local_media_summary": "Ringkasan Media Lokal", "local_network": "Jaringan Lokal", "local_network_sheet_info": "Aplikasi akan terhubung ke server melalui URL ini saat menggunakan jaringan Wi-Fi yang ditentukan", "location_permission": "Izin lokasi", @@ -1217,6 +1250,7 @@ "location_picker_longitude_hint": "Masukkan bujur di sini", "lock": "Kunci", "locked_folder": "Folder Terkunci", + "log_detail_title": "Detail Log", "log_out": "Log keluar", "log_out_all_devices": "Keluar dari Semua Perangkat", "logged_in_as": "Masuk sebagai {user}", @@ -1247,6 +1281,7 @@ "login_password_changed_success": "Sandi berhasil diperbarui", "logout_all_device_confirmation": "Apakah Anda yakin ingin keluar dari semua perangkat?", "logout_this_device_confirmation": "Apakah Anda yakin ingin mengeluarkan perangkat ini?", + "logs": "Log", "longitude": "Bujur", "look": "Tampilan", "loop_videos": "Ulangi video", @@ -1254,6 +1289,7 @@ "main_branch_warning": "Anda menggunakan versi pengembangan; kami sangat menyarankan menggunakan versi rilis!", "main_menu": "Menu utama", "make": "Merek", + "manage_geolocation": "Atur lokasi", "manage_shared_links": "Kelola tautan terbagi", "manage_sharing_with_partners": "Kelola pembagian dengan partner", "manage_the_app_settings": "Kelola pengaturan aplikasi", @@ -1288,6 +1324,7 @@ "mark_as_read": "Tandai sebagai telah dibaca", "marked_all_as_read": "Semua telah ditandai sebagai telah dibaca", "matches": "Cocokan", + "matching_assets": "Aset yang Cocok", "media_type": "Jenis media", "memories": "Kenangan", "memories_all_caught_up": "Semua telah dilihat", @@ -1328,6 +1365,7 @@ "name_or_nickname": "Nama atau nama panggilan", "network_requirement_photos_upload": "Gunakan data seluler untuk cadangkan foto", "network_requirement_videos_upload": "Gunakan data seluler untuk cadangkan video", + "network_requirements": "Persyaratan Jaringan", "network_requirements_updated": "Persyaratan jaringan telah berubah, antrean pencadangan diatur ulang", "networking_settings": "Jaringan", "networking_subtitle": "Kelola pengaturan Endpoint server", @@ -1338,6 +1376,7 @@ "new_person": "Orang baru", "new_pin_code": "Kode PIN baru", "new_pin_code_subtitle": "Ini adalah akses pertama Anda ke folder terkunci. Buat kode PIN untuk mengamankan akses ke halaman ini", + "new_timeline": "Linimasa Baru", "new_user_created": "Pengguna baru dibuat", "new_version_available": "VERSI BARU TERSEDIA", "newest_first": "Terkini dahulu", @@ -1351,20 +1390,25 @@ "no_assets_message": "KLIK UNTUK MENGUNGGAH FOTO PERTAMA ANDA", "no_assets_to_show": "Tidak ada aset", "no_cast_devices_found": "Tidak ada perangkat cast yang ditemukan", + "no_checksum_local": "Tidak ada checksum yang tersedia - tidak dapat mengambil aset lokal", + "no_checksum_remote": "Tidak ada checksum yang tersedia - tidak dapat mengambil aset jarak jauh", "no_duplicates_found": "Tidak ada duplikat yang ditemukan.", "no_exif_info_available": "Tidak ada info EXIF yang tersedia", "no_explore_results_message": "Unggah lebih banyak foto untuk menjelajahi koleksi Anda.", "no_favorites_message": "Tambahkan favorit untuk mencari foto dan video terbaik Anda dengan cepat", "no_libraries_message": "Buat pustaka eksternal untuk menampilkan foto dan video Anda", + "no_local_assets_found": "Tidak ada aset lokal yang ditemukan dengan checksum ini", "no_locked_photos_message": "Foto dan video di folder terkunci disembunyikan dan tidak akan muncul saat Anda menelusuri atau mencari di pustaka.", "no_name": "Tidak Ada Nama", "no_notifications": "Tidak ada notifikasi", "no_people_found": "Orang tidak ditemukan", "no_places": "Tidak ada tempat", + "no_remote_assets_found": "Tidak ada aset jarak jauh yang ditemukan dengan checksum ini", "no_results": "Tidak ada hasil", "no_results_description": "Coba sinonim atau kata kunci yang lebih umum", "no_shared_albums_message": "Buat sebuah album untuk membagikan foto dan video dengan orang-orang dalam jaringan Anda", "no_uploads_in_progress": "Tidak ada unggahan yang sedang berlangsung", + "not_available": "T/T", "not_in_any_album": "Tidak ada dalam album apa pun", "not_selected": "Belum dipilih", "note_apply_storage_label_to_previously_uploaded assets": "Catatan: Untuk menerapkan Label Penyimpanan pada aset yang sebelumnya telah diunggah, jalankan", @@ -1399,6 +1443,8 @@ "open_the_search_filters": "Buka saringan pencarian", "options": "Opsi", "or": "atau", + "organize_into_albums": "Atur ke dalam album", + "organize_into_albums_description": "Masukkan foto lama ke album sesuai pengaturan sinkronisasi", "organize_your_library": "Kelola pustaka Anda", "original": "asli", "other": "Lainnya", @@ -1458,9 +1504,9 @@ "permission_onboarding_permission_limited": "Izin dibatasi. Agai Immich dapat mencadangkan dan mengatur seluruh koleksi galeri, izinkan akses foto dan video pada Setelan.", "permission_onboarding_request": "Immich memerlukan izin untuk melihat foto dan video kamu.", "person": "Orang", - "person_age_months": "{months} bulan", - "person_age_year_months": "1 tahun, {months} bulan", - "person_age_years": "{years} tahun", + "person_age_months": "{months, plural, one {# bulan} other {# bulan}} old", + "person_age_year_months": "1 year, {months, plural, one {# bulan} other {# bulan}} old", + "person_age_years": "{years, plural, other {# tahun}} old", "person_birthdate": "Lahir pada {date}", "person_hidden": "{name}{hidden, select, true { (tersembunyi)} other {}}", "photo_shared_all_users": "Sepertinya Anda membagikan foto Anda dengan semua pengguna atau Anda tidak memiliki pengguna siapa pun untuk dibagikan.", @@ -1484,6 +1530,7 @@ "port": "Porta", "preferences_settings_subtitle": "Kelola preferensi aplikasi", "preferences_settings_title": "Preferensi", + "preparing": "Mempersiapkan", "preset": "Prasetel", "preview": "Pratinjau", "previous": "Sebelumnya", @@ -1500,6 +1547,7 @@ "profile_drawer_client_out_of_date_minor": "Versi app seluler ini sudah kedaluwarsa. Silakan perbarui ke versi minor terbaru.", "profile_drawer_client_server_up_to_date": "Klien dan server menjalankan versi terbaru", "profile_drawer_github": "GitHub", + "profile_drawer_readonly_mode": "Mode baca-saja aktif. Tekan lama ikon avatar pengguna untuk keluar.", "profile_drawer_server_out_of_date_major": "Versi server ini telah kedaluwarsa. Silakan perbarui ke versi major terbaru.", "profile_drawer_server_out_of_date_minor": "Versi server ini telah kedaluwarsa. Silakan perbarui ke versi minor terbaru.", "profile_image_of_user": "Foto profil dari {user}", @@ -1538,6 +1586,7 @@ "purchase_server_description_2": "Status pendukung", "purchase_server_title": "Server", "purchase_settings_server_activated": "Kunci produk server dikelola oleh admin", + "query_asset_id": "ID Aset Kueri", "queue_status": "Antrian {count}/{total}", "rating": "Peringkat bintang", "rating_clear": "Hapus peringkat", @@ -1545,6 +1594,9 @@ "rating_description": "Tampilkan peringkat EXIF pada panel info", "reaction_options": "Opsi reaksi", "read_changelog": "Baca Log Perubahan", + "readonly_mode_disabled": "Mode baca-saja dimatikan", + "readonly_mode_enabled": "Mode baca-saja diaktifkan", + "ready_for_upload": "Siap untuk mengunggah", "reassign": "Tetapkan ulang", "reassigned_assets_to_existing_person": "Menetapkan ulang {count, plural, one {# aset} other {# aset}} kepada {name, select, null {orang yang sudah ada} other {{name}}}", "reassigned_assets_to_new_person": "Menetapkan ulang {count, plural, one {# aset} other {# aset}} kepada orang baru", @@ -1569,6 +1621,7 @@ "regenerating_thumbnails": "Membuat ulang gambar kecil", "remote": "Jarak Jauh", "remote_assets": "Aset Jarak Jauh", + "remote_media_summary": "Ringkasan Media Jarak Jauh", "remove": "Hapus", "remove_assets_album_confirmation": "Apakah Anda yakin ingin menghapus {count, plural, one {# aset} other {# aset}} dari album?", "remove_assets_shared_link_confirmation": "Apakah Anda yakin ingin menghapus {count, plural, one {# aset} other {# aset}} dari tautan terbagi ini?", @@ -1621,6 +1674,7 @@ "restore_user": "Pulihkan pengguna", "restored_asset": "Aset dipulihkan", "resume": "Lanjutkan", + "resume_paused_jobs": "Lanjutkan {count, plural, one {# pekerjaan yang dijeda} other {# pekerjaan yang dijeda}}", "retry_upload": "Ulangi pengunggahan", "review_duplicates": "Pratinjau duplikat", "review_large_files": "Meninjau berkas berukuran besar", @@ -1714,6 +1768,7 @@ "select_user_for_sharing_page_err_album": "Gagal membuat album", "selected": "Dipilih", "selected_count": "{count, plural, other {# dipilih}}", + "selected_gps_coordinates": "Koordinat GPS yang dipilih", "send_message": "Kirim pesan", "send_welcome_email": "Kirim surel selamat datang", "server_endpoint": "Endpoint server", @@ -1842,6 +1897,7 @@ "show_slideshow_transition": "Tampilkan transisi salindia", "show_supporter_badge": "Lencana suporter", "show_supporter_badge_description": "Tampilkan lencana suporter", + "show_text_search_menu": "Tampilkan menu pencarian teks", "shuffle": "Acak", "sidebar": "Bilah sisi", "sidebar_display_description": "Menampilkan tautan ke tampilan di bilah sisi", @@ -1857,6 +1913,7 @@ "sort_created": "Tanggal dibuat", "sort_items": "Jumlah item", "sort_modified": "Tanggal diubah", + "sort_newest": "Foto terbaru", "sort_oldest": "Foto terlawas", "sort_people_by_similarity": "Urutkan orang berdasarkan kemiripan", "sort_recent": "Foto paling terkini", @@ -1871,6 +1928,7 @@ "stacktrace": "Jejak tumpukan", "start": "Mulai", "start_date": "Tanggal mulai", + "start_date_before_end_date": "Tanggal mulai harus sebelum tanggal akhir", "state": "Keadaan", "status": "Status", "stop_casting": "Hentikan cast", @@ -1895,6 +1953,8 @@ "sync_albums_manual_subtitle": "Melakukan sinkronisasi semua video dan foto yang telah diunggah ke album cadangan yang dipilih", "sync_local": "Sinkronkan lokal", "sync_remote": "Sinkronkan jarak jauh", + "sync_status": "Status Sinkronisasi", + "sync_status_subtitle": "Lihat dan atur sistem sinkronisasi", "sync_upload_album_setting_subtitle": "Membuat dan mengunggah foto serta video Anda ke album yang telah dipilih pada Immich", "tag": "Label", "tag_assets": "Tag aset", @@ -1932,7 +1992,9 @@ "to_change_password": "Ubah kata sandi", "to_favorite": "Favorit", "to_login": "Log masuk", + "to_multi_select": "untuk memilih beberapa", "to_parent": "Ke induk", + "to_select": "untuk memilih", "to_trash": "Sampah", "toggle_settings": "Saklar pengaturan", "total": "Jumlah", @@ -1952,6 +2014,7 @@ "trash_page_select_assets_btn": "Pilih aset", "trash_page_title": "Sampah ({count})", "trashed_items_will_be_permanently_deleted_after": "Item yang dibuang akan dihapus secara permanen setelah {days, plural, one {# hari} other {# hari}}.", + "troubleshoot": "Pemecahan Masalah", "type": "Jenis", "unable_to_change_pin_code": "Tidak dapat mengubah kode PIN", "unable_to_setup_pin_code": "Tidak dapat memasang kode PIN", @@ -1982,6 +2045,7 @@ "unstacked_assets_count": "Penumpukan {count, plural, one {# aset} other {# aset}} dibatalkan", "untagged": "Tidak ditandai", "up_next": "Berikutnya", + "update_location_action_prompt": "Perbarui lokasi {count} aset yang dipilih dengan:", "updated_at": "Diperbarui", "updated_password": "Kata sandi diperbarui", "upload": "Unggah", @@ -2048,6 +2112,7 @@ "view_next_asset": "Tampilkan aset berikutnya", "view_previous_asset": "Tampilkan aset sebelumnya", "view_qr_code": "Tampilkan kode QR", + "view_similar_photos": "Lihat foto yang mirip", "view_stack": "Tampilkan Tumpukan", "view_user": "Lihat Pengguna", "viewer_remove_from_stack": "Keluarkan dari Tumpukan", @@ -2066,5 +2131,6 @@ "yes": "Ya", "you_dont_have_any_shared_links": "Anda tidak memiliki tautan terbagi", "your_wifi_name": "Nama Wi-Fi Anda", - "zoom_image": "Perbesar Gambar" + "zoom_image": "Perbesar Gambar", + "zoom_to_bounds": "Perbesar ke batas" } diff --git a/i18n/it.json b/i18n/it.json index 0bf48a378c..b1aeabd33e 100644 --- a/i18n/it.json +++ b/i18n/it.json @@ -14,7 +14,7 @@ "add_a_location": "Aggiungi una posizione", "add_a_name": "Aggiungi un nome", "add_a_title": "Aggiungi un titolo", - "add_birthday": "Aggiungi un compleanno", + "add_birthday": "Aggiungi compleanno", "add_endpoint": "Aggiungi un endpoint", "add_exclusion_pattern": "Aggiungi un pattern di esclusione", "add_import_path": "Aggiungi un percorso per l’importazione", @@ -28,10 +28,12 @@ "add_to_album": "Aggiungi all'album", "add_to_album_bottom_sheet_added": "Aggiunto in {album}", "add_to_album_bottom_sheet_already_exists": "Già presente in {album}", + "add_to_album_bottom_sheet_some_local_assets": "Alcune risorse locali non possono essere aggiunte all'album", "add_to_album_toggle": "Attiva/disattiva selezione per {album}", "add_to_albums": "Aggiungi ad album", "add_to_albums_count": "Aggiungi ad album ({count})", "add_to_shared_album": "Aggiungi ad album condiviso", + "add_upload_to_stack": "Aggiungi caricamento allo stack", "add_url": "Aggiungi URL", "added_to_archive": "Aggiunto all'archivio", "added_to_favorites": "Aggiunto ai preferiti", @@ -123,6 +125,13 @@ "logging_enable_description": "Attiva il logging", "logging_level_description": "Quando attivato, che livello di log utilizzare.", "logging_settings": "Registro dei Log", + "machine_learning_availability_checks": "Verifiche di disponibilità", + "machine_learning_availability_checks_description": "Rileva automaticamente e usa i server di machine learning disponibili", + "machine_learning_availability_checks_enabled": "Attiva verifiche di disponibilità", + "machine_learning_availability_checks_interval": "Intervallo di verifica", + "machine_learning_availability_checks_interval_description": "Intervallo (ms) tra le verifiche di disponibilità", + "machine_learning_availability_checks_timeout": "Timeout richiesta", + "machine_learning_availability_checks_timeout_description": "Timeout (ms) per le verifiche di disponibilità", "machine_learning_clip_model": "Modello CLIP", "machine_learning_clip_model_description": "Il nome del modello CLIP mostrato qui. Nota che devi rieseguire il processo 'Ricerca Intelligente' per tutte le immagini al cambio del modello.", "machine_learning_duplicate_detection": "Rilevamento Duplicati", @@ -169,7 +178,7 @@ "map_style_description": "URL per un tema della mappa style.json", "memory_cleanup_job": "Pulizia dei vecchi Ricordi", "memory_generate_job": "Generazione dei Ricordi", - "metadata_extraction_job": "Estrazione Metadata", + "metadata_extraction_job": "Estrazione Metadati", "metadata_extraction_job_description": "Estrai informazioni dai metadati di ciascuna risorsa, come coordinate GPS, volti e risoluzione", "metadata_faces_import_setting": "Abilita l'importazione dei volti", "metadata_faces_import_setting_description": "Importa i volti dai dati EXIF dell'immagine e dai file sidecar", @@ -300,11 +309,11 @@ "transcoding_acceleration_rkmpp": "RKMPP (Solo per SOC Rockchip)", "transcoding_acceleration_vaapi": "VAAPI", "transcoding_accepted_audio_codecs": "Codifiche audio accettate", - "transcoding_accepted_audio_codecs_description": "Seleziona quali codifiche audio non devono essere trascodificate. Solo usato per alcune politiche di trascodifica.", + "transcoding_accepted_audio_codecs_description": "Seleziona quali codifiche audio non devono essere transcodificate. Solo usato per alcune politiche di transcodifica.", "transcoding_accepted_containers": "Contenitori accettati", "transcoding_accepted_containers_description": "Seleziona quali formati non hanno bisogno di essere remuxati in MP4. Usato solo per certe politiche di transcodifica.", "transcoding_accepted_video_codecs": "Codifiche video accettate", - "transcoding_accepted_video_codecs_description": "Seleziona quali codifiche video non devono essere trascodificate. Usato solo per alcune politiche di trascodifica.", + "transcoding_accepted_video_codecs_description": "Seleziona quali codifiche video non devono essere transcodificate. Usato solo per alcune politiche di transcodifica.", "transcoding_advanced_options_description": "Impostazioni che la maggior parte degli utenti non dovrebbero cambiare", "transcoding_audio_codec": "Codifica Audio", "transcoding_audio_codec_description": "Opus è l'opzione con la qualità piÚ alta, ma è meno compatibile con dispositivi o software vecchi.", @@ -337,7 +346,7 @@ "transcoding_reference_frames": "Frame di riferimento", "transcoding_reference_frames_description": "Il numero di frame da prendere in considerazione nel comprimere un determinato frame. Valori piÚ alti migliorano l'efficienza di compressione, ma rallentano la codifica. 0 imposta questo valore automaticamente.", "transcoding_required_description": "Solo video che non sono in un formato accettato", - "transcoding_settings": "Impostazioni Trascodifica Video", + "transcoding_settings": "Impostazioni Transcodifica Video", "transcoding_settings_description": "Gestisci quali video transcodificare e come processarli", "transcoding_target_resolution": "Risoluzione desiderata", "transcoding_target_resolution_description": "Risoluzioni piÚ elevate possono preservare piÚ dettagli ma richiedono piÚ tempo per la codifica, producono file di dimensioni maggiori e possono ridurre la reattività dell'applicazione.", @@ -348,11 +357,11 @@ "transcoding_tone_mapping": "Mappatura della tonalità", "transcoding_tone_mapping_description": "Tenta di preservare l'aspetto dei video HDR quando convertiti in SDR. Ciascun algoritmo fa diversi compromessi per colore, dettaglio e luminosità. Hable conserva il dettaglio, Mobius conserva il colore e Reinhard conserva la luminosità.", "transcoding_transcode_policy": "Politica di transcodifica", - "transcoding_transcode_policy_description": "Politica che determina quando un video deve essere trascodificato. I video HDR verranno sempre trascodificati (eccetto quando la trascodifica è disabilitata).", + "transcoding_transcode_policy_description": "Politica che determina quando un video deve essere transcodificato. I video HDR verranno sempre transcodificati (eccetto quando la transcodifica è disabilitata).", "transcoding_two_pass_encoding": "Codifica a due passaggi", - "transcoding_two_pass_encoding_setting_description": "Trascodifica in due passaggi per produrre video codificati migliori. Quando il bitrate massimo è abilitato (necessario affinchÊ funzioni con H.264 e HEVC), questa modalità utilizza un intervallo di bitrate basato sul bitrate massimo e ignora CRF. Per VP9, CRF puÃ˛ essere utilizzato se il bitrate massimo è disabilitato.", + "transcoding_two_pass_encoding_setting_description": "Transcodifica in due passaggi per produrre video codificati migliori. Quando il bitrate massimo è abilitato (necessario affinchÊ funzioni con H.264 e HEVC), questa modalità utilizza un intervallo di bitrate basato sul bitrate massimo e ignora CRF. Per VP9, CRF puÃ˛ essere utilizzato se il bitrate massimo è disabilitato.", "transcoding_video_codec": "Codec video", - "transcoding_video_codec_description": "VP9 ha alta efficienza e compatibilità web, ma richiede piÚ tempo per la trascodifica. HEVC ha prestazioni simili, ma una minore compatibilità web. H.264 è ampiamente compatibile e veloce da transcodificare, ma produce file molto piÚ grandi. AV1 è il codec piÚ efficiente, ma non è supportato sui dispositivi piÚ vecchi.", + "transcoding_video_codec_description": "VP9 ha alta efficienza e compatibilità web, ma richiede piÚ tempo per la transcodifica. HEVC ha prestazioni simili, ma una minore compatibilità web. H.264 è ampiamente compatibile e veloce da transcodificare, ma produce file molto piÚ grandi. AV1 è il codec piÚ efficiente, ma non è supportato sui dispositivi piÚ vecchi.", "trash_enabled_description": "Abilita Funzionalità Cestino", "trash_number_of_days": "Numero di giorni", "trash_number_of_days_description": "Numero di giorni per cui mantenere gli asset nel cestino prima di rimuoverli definitivamente", @@ -380,15 +389,13 @@ "version_check_implications": "La funzione di controllo della versione fa uso di una comunicazione periodica con github.com", "version_check_settings": "Controllo Versione", "version_check_settings_description": "Abilita/disabilita la notifica per nuove versioni", - "video_conversion_job": "Trascodifica video", - "video_conversion_job_description": "Trascodifica video per maggiore compatibilità con browser e dispositivi" + "video_conversion_job": "Transcodifica video", + "video_conversion_job_description": "Transcodifica video per maggiore compatibilità con browser e dispositivi" }, "admin_email": "Email Amministratore", "admin_password": "Password Amministratore", "administration": "Amministrazione", "advanced": "Avanzate", - "advanced_settings_beta_timeline_subtitle": "Prova la nuova esperienza dell'app", - "advanced_settings_beta_timeline_title": "Timeline beta", "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: {level}", @@ -425,6 +432,7 @@ "album_remove_user_confirmation": "Sicuro di voler rimuovere l'utente {user}?", "album_search_not_found": "Nessun album trovato corrispondente alla tua ricerca", "album_share_no_users": "Sembra che tu abbia condiviso questo album con tutti gli utenti oppure non hai nessun utente con cui condividere.", + "album_summary": "Sommario Album", "album_updated": "Album aggiornato", "album_updated_setting_description": "Ricevi una notifica email quando un album condiviso ha nuovi media", "album_user_left": "{album} abbandonato", @@ -496,6 +504,8 @@ "asset_restored_successfully": "Elemento ripristinato con successo", "asset_skipped": "Saltato", "asset_skipped_in_trash": "Nel cestino", + "asset_trashed": "Asset cestinato", + "asset_troubleshoot": "Risoluzione dei problemi dell'asset", "asset_uploaded": "Caricato", "asset_uploading": "Caricamentoâ€Ļ", "asset_viewer_settings_subtitle": "Gestisci le impostazioni del visualizzatore della galleria", @@ -529,8 +539,10 @@ "autoplay_slideshow": "Avvio automatico presentazione", "back": "Indietro", "back_close_deselect": "Indietro, chiudi o deseleziona", + "background_backup_running_error": "Il backup in background è attualmente in esecuzione, impossibile avviare il backup manuale", "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", + "background_options": "Opzioni sfondo", "backup": "Backup", "backup_album_selection_page_albums_device": "Album sul dispositivo ({count})", "backup_album_selection_page_albums_tap": "Tap per includere, doppio tap per escludere", @@ -538,6 +550,7 @@ "backup_album_selection_page_select_albums": "Seleziona gli album", "backup_album_selection_page_selection_info": "Informazioni sulla selezione", "backup_album_selection_page_total_assets": "Numero totale delle risorse", + "backup_albums_sync": "Sincronizzazione album di backup", "backup_all": "Tutti", "backup_background_service_backup_failed_message": "È stato impossibile fare il backup dei contenuti. Riprovoâ€Ļ", "backup_background_service_connection_failed_message": "Impossibile connettersi al server. Riprovoâ€Ļ", @@ -587,6 +600,7 @@ "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_error_sync_failed": "Sincronizzazione non riuscita. Impossibile elaborare il backup.", "backup_info_card_assets": "risorse", "backup_manual_cancelled": "Annullato", "backup_manual_in_progress": "Caricamento già in corso. Riprova piÚ tardi", @@ -597,8 +611,6 @@ "backup_setting_subtitle": "Gestisci le impostazioni di upload in primo piano e in background", "backup_settings_subtitle": "Gestisci le impostazioni di caricamento", "backward": "Indietro", - "beta_sync": "Status sincronizzazione beta", - "beta_sync_subtitle": "Gestisci il nuovo sistema di sincronizzazione", "biometric_auth_enabled": "Autenticazione biometrica attivata", "biometric_locked_out": "Sei stato bloccato dall'autenticazione biometrica", "biometric_no_options": "Nessuna opzione biometrica disponibile", @@ -608,7 +620,7 @@ "blurred_background": "Sfondo sfocato", "bugs_and_feature_requests": "Bug & Richieste di nuove funzionalità", "build": "Compilazione", - "build_image": "Compila Immagine", + "build_image": "Immagine Compilata", "bulk_delete_duplicates_confirmation": "Sei 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. Non puoi annullare questa operazione!", "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.", @@ -656,6 +668,8 @@ "change_pin_code": "Cambia il codice PIN", "change_your_password": "Modifica la tua password", "changed_visibility_successfully": "Visibilità modificata con successo", + "charging": "In carica", + "charging_requirement_mobile_backup": "Il backup in background richiede che il dispositivo sia in carica", "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.", @@ -722,7 +736,7 @@ "copy_to_clipboard": "Copia negli appunti", "country": "Nazione", "cover": "Riempi la finestra", - "covers": "Copre", + "covers": "Copertine", "create": "Crea", "create_album": "Crea album", "create_album_page_untitled": "Senza titolo", @@ -742,6 +756,7 @@ "create_user": "Crea utente", "created": "Creato", "created_at": "Creato il", + "creating_linked_albums": "Creazione di album collegati...", "crop": "Ritaglia", "curated_object_page_title": "Oggetti", "current_device": "Dispositivo attuale", @@ -754,9 +769,9 @@ "daily_title_text_date_year": "E, dd MMM, yyyy", "dark": "Scuro", "dark_theme": "Imposta tema scuro", - "date_after": "Data dopo", + "date_after": "Dopo la data", "date_and_time": "Data e ora", - "date_before": "Data prima", + "date_before": "Prima della data", "date_format": "E, d LLL, y â€ĸ hh:mm", "date_of_birth_saved": "Data di nascita salvata con successo", "date_range": "Intervallo di date", @@ -891,7 +906,9 @@ "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_getting_places": "Errore durante il recupero dei luoghi", "error_loading_image": "Errore nel caricamento dell'immagine", + "error_loading_partners": "Errore durante il caricamento dei partner: {error}", "error_saving_image": "Errore: {error}", "error_tag_face_bounding_box": "Errore durante il tag del volto - impossibile ricavare le coordinate del riquadro", "error_title": "Errore - Qualcosa è andato storto", @@ -1022,6 +1039,7 @@ "exif_bottom_sheet_description_error": "Errore durante l'aggiornamento della descrizione", "exif_bottom_sheet_details": "DETTAGLI", "exif_bottom_sheet_location": "POSIZIONE", + "exif_bottom_sheet_no_description": "Nessuna descrizione", "exif_bottom_sheet_people": "PERSONE", "exif_bottom_sheet_person_add_person": "Aggiungi nome", "exit_slideshow": "Esci dalla presentazione", @@ -1056,6 +1074,7 @@ "favorites_page_no_favorites": "Nessun preferito", "feature_photo_updated": "Foto in evidenza aggiornata", "features": "Funzionalità", + "features_in_development": "Funzionalità in fase di sviluppo", "features_setting_description": "Gestisci le funzionalità dell'app", "file_name": "Nome file", "file_name_or_extension": "Nome file o estensione", @@ -1076,10 +1095,7 @@ "gcast_enabled": "Google Cast Abilitato", "gcast_enabled_description": "Questa funzione carica risorse esterne da Google per poter funzionare.", "general": "Generale", - "geolocation_instruction_all_have_location": "Tutte le risorse per questa data hanno già dati sulla posizione. Prova a mostrare tutte le risorse o seleziona una data diversa", "geolocation_instruction_location": "Fai clic su una risorsa con coordinate GPS per utilizzare la sua posizione oppure seleziona una posizione direttamente dalla mappa", - "geolocation_instruction_no_date": "Seleziona una data per gestire i dati sulla posizione per foto e video di quel giorno", - "geolocation_instruction_no_photos": "Nessuna foto o video trovato per questa data. Seleziona una data diversa per visualizzarli", "get_help": "Chiedi Aiuto", "get_wifiname_error": "Non sono riuscito a recuperare il nome della rete Wi-Fi. Accertati di aver concesso i permessi necessari e di essere connesso ad una rete Wi-Fi", "getting_started": "Iniziamo", @@ -1160,7 +1176,7 @@ "in_archive": "In archivio", "include_archived": "Includi Archiviati", "include_shared_albums": "Includi album condivisi", - "include_shared_partner_assets": "Includi asset condivisi del compagno", + "include_shared_partner_assets": "Includi elementi condivisi dai compagni", "individual_share": "Condivisione individuale", "individual_shares": "Condivisioni individuali", "info": "Info", @@ -1223,6 +1239,7 @@ "local": "Locale", "local_asset_cast_failed": "Impossibile trasmettere una risorsa che non è caricata sul server", "local_assets": "Risorsa locale", + "local_media_summary": "Riepilogo dei Media Locali", "local_network": "Rete locale", "local_network_sheet_info": "L'app si collegherà al server tramite questo URL quando è in uso la rete Wi-Fi specificata", "location_permission": "Permesso di localizzazione", @@ -1234,6 +1251,7 @@ "location_picker_longitude_hint": "Inserisci la longitudine qui", "lock": "Rendi privato", "locked_folder": "Cartella Privata", + "log_detail_title": "Dettaglio dei Log", "log_out": "Esci", "log_out_all_devices": "Disconnetti tutti i dispositivi", "logged_in_as": "Effettuato l'accesso come {user}", @@ -1264,6 +1282,7 @@ "login_password_changed_success": "Password aggiornata con successo", "logout_all_device_confirmation": "Sei sicuro di volerti disconnettere da tutti i dispositivi?", "logout_this_device_confirmation": "Sei sicuro di volerti disconnettere da questo dispositivo?", + "logs": "Logs", "longitude": "Longitudine", "look": "Guarda", "loop_videos": "Riproduci video in loop", @@ -1306,6 +1325,7 @@ "mark_as_read": "Segna come letto", "marked_all_as_read": "Segnato tutto come letto", "matches": "Corrispondenze", + "matching_assets": "Assets Corrispondenti", "media_type": "Tipo Media", "memories": "Ricordi", "memories_all_caught_up": "Tutto a posto", @@ -1346,6 +1366,7 @@ "name_or_nickname": "Nome o soprannome", "network_requirement_photos_upload": "Utilizza la connessione dati per il backup delle foto", "network_requirement_videos_upload": "Utilizza la connessione dati per il backup dei video", + "network_requirements": "Requisiti di rete", "network_requirements_updated": "Requisiti di rete modificati, coda di backup reimpostata", "networking_settings": "Rete", "networking_subtitle": "Gestisci le impostazioni riguardanti gli endpoint del server", @@ -1356,6 +1377,7 @@ "new_person": "Nuova persona", "new_pin_code": "Nuovo codice PIN", "new_pin_code_subtitle": "Questa è la prima volta che accedi alla cartella privata. Crea un codice PIN per accedere in modo sicuro a questa pagina", + "new_timeline": "Nuova Timeline", "new_user_created": "Nuovo utente creato", "new_version_available": "NUOVA VERSIONE DISPONIBILE", "newest_first": "Prima recenti", @@ -1369,20 +1391,25 @@ "no_assets_message": "CLICCA PER CARICARE LA TUA PRIMA FOTO", "no_assets_to_show": "Nessuna risorsa da mostrare", "no_cast_devices_found": "Nessun dispositivo di trasmissione trovato", + "no_checksum_local": "Nessun checksum disponibile: impossibile recuperare gli assets locali", + "no_checksum_remote": "Nessun checksum disponibile: impossibile recuperare l'asset remoto", "no_duplicates_found": "Nessun duplicato trovato.", "no_exif_info_available": "Nessuna informazione exif disponibile", "no_explore_results_message": "Carica piÚ foto per esplorare la tua collezione.", "no_favorites_message": "Aggiungi preferiti per trovare facilmente le tue migliori foto e video", "no_libraries_message": "Crea una libreria esterna per vedere le tue foto e i tuoi video", + "no_local_assets_found": "Nessun asset locale trovato con questo checksum", "no_locked_photos_message": "Le foto e i video nella cartella privata sono nascosti e non vengono visualizzati mentre navighi o cerchi nella tua libreria.", "no_name": "Nessun nome", "no_notifications": "Nessuna notifica", "no_people_found": "Nessuna persona trovata", "no_places": "Nessun posto", + "no_remote_assets_found": "Nessun asset remoto trovato con questo checksum", "no_results": "Nessun risultato", "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", "no_uploads_in_progress": "Nessun upload in corso", + "not_available": "N/A", "not_in_any_album": "In nessun album", "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", @@ -1417,6 +1444,8 @@ "open_the_search_filters": "Apri filtri di ricerca", "options": "Opzioni", "or": "o", + "organize_into_albums": "Organizza all'interno degli albums", + "organize_into_albums_description": "Inserisci le foto esistenti all'interno degli albums utilizzando le attuale impostazioni di sincronizzazione", "organize_your_library": "Organizza la tua libreria", "original": "originale", "other": "Altro", @@ -1502,6 +1531,7 @@ "port": "Porta", "preferences_settings_subtitle": "Gestisci le preferenze dell'app", "preferences_settings_title": "Preferenze", + "preparing": "Preparando", "preset": "Preimpostazione", "preview": "Anteprima", "previous": "Precedente", @@ -1518,7 +1548,7 @@ "profile_drawer_client_out_of_date_minor": "L'applicazione non è aggiornata. Aggiorna all'ultima versione minore.", "profile_drawer_client_server_up_to_date": "Client e server sono aggiornati", "profile_drawer_github": "GitHub", - "profile_drawer_readonly_mode": "Modalità di sola lettura abilitata. Tocca due volte l'icona dell'avatar dell'utente per disabilitarla.", + "profile_drawer_readonly_mode": "Modalità di sola lettura abilitata. Tieni premuto sull'avatar dell'utente per disabilitarla.", "profile_drawer_server_out_of_date_major": "Il server non è aggiornato. Aggiorna all'ultima versione principale.", "profile_drawer_server_out_of_date_minor": "Il server non è aggiornato. Aggiorna all'ultima versione minore.", "profile_image_of_user": "Immagine profilo di {user}", @@ -1557,6 +1587,7 @@ "purchase_server_description_2": "Stato di Contributore", "purchase_server_title": "Server", "purchase_settings_server_activated": "La chiave del prodotto del server è gestita dall'amministratore", + "query_asset_id": "Esegui una query sull'ID dell'asset", "queue_status": "Messi in coda {count}/{total}", "rating": "Valutazione a stelle", "rating_clear": "Crea valutazione", @@ -1566,6 +1597,7 @@ "read_changelog": "Leggi Riepilogo Modifiche", "readonly_mode_disabled": "Modalità di sola lettura disabilitata", "readonly_mode_enabled": "Modalità di sola lettura abilitata", + "ready_for_upload": "Pronto per il caricamento", "reassign": "Riassegna", "reassigned_assets_to_existing_person": "{count, plural, one {Riassegnato # asset} other {Riassegnati # assets}} {name, select, null {ad una persona esistente} other {a {name}}}", "reassigned_assets_to_new_person": "{count, plural, one {Riassegnato # asset} other {Riassegnati # assets}} ad una nuova persona", @@ -1590,6 +1622,7 @@ "regenerating_thumbnails": "Rigenerando le anteprime", "remote": "Remoto", "remote_assets": "Risorse remote", + "remote_media_summary": "Riepilogo dei Media Remoti", "remove": "Rimuovi", "remove_assets_album_confirmation": "Sei sicuro di voler rimuovere {count, plural, one {# asset} other {# asset}} dall'album?", "remove_assets_shared_link_confirmation": "Sei sicuro di voler rimuovere {count, plural, one {# asset} other {# asset}} da questo link condiviso?", @@ -1642,6 +1675,7 @@ "restore_user": "Ripristina utente", "restored_asset": "Asset ripristinato", "resume": "Riprendi", + "resume_paused_jobs": "Riprendi {count, plural, one {# processo in pausa} other {# i processi in pausa}}", "retry_upload": "Riprova caricamento", "review_duplicates": "Esamina duplicati", "review_large_files": "Revisiona file pesanti", @@ -1690,11 +1724,11 @@ "search_no_people": "Nessuna persona", "search_no_people_named": "Nessuna persona chiamate \"{name}\"", "search_no_result": "Nessun risultato trovato, prova con un termine o combinazione diversi", - "search_options": "Opzioni Ricerca", + "search_options": "Opzioni di ricerca", "search_page_categories": "Categoria", "search_page_motion_photos": "Foto in movimento", - "search_page_no_objects": "Nessuna informazione relativa all'oggetto disponibile", - "search_page_no_places": "Nessun informazione sul luogo disponibile", + "search_page_no_objects": "Nessuna informazione sugli oggetti disponibile", + "search_page_no_places": "Nessuna informazione sui luoghi disponibile", "search_page_screenshots": "Screenshot", "search_page_search_photos_videos": "Ricerca le tue foto e i tuoi video", "search_page_selfies": "Selfie", @@ -1735,7 +1769,7 @@ "select_user_for_sharing_page_err_album": "Impossibile nel creare l'album", "selected": "Selezionato", "selected_count": "{count, plural, one {# selezionato} other {# selezionati}}", - "selected_gps_coordinates": "coordinate GPS selezionate", + "selected_gps_coordinates": "Coordinate GPS selezionate", "send_message": "Manda messaggio", "send_welcome_email": "Invia email di benvenuto", "server_endpoint": "Server endpoint", @@ -1846,10 +1880,8 @@ "shift_to_permanent_delete": "premi ⇧ per cancellare definitivamente l'asset", "show_album_options": "Mostra opzioni album", "show_albums": "Mostra gli album", - "show_all_assets": "Mostra tutte le risorse", "show_all_people": "Mostra tutte le persone", "show_and_hide_people": "Mostra & nascondi persone", - "show_assets_without_location": "Mostra risorse senza posizione", "show_file_location": "Mostra percorso file", "show_gallery": "Mostra galleria", "show_hidden_people": "Mostra persone nascoste", @@ -1866,6 +1898,7 @@ "show_slideshow_transition": "Mostra la transizione della presentazione", "show_supporter_badge": "Medaglia di Contributore", "show_supporter_badge_description": "Mostra la medaglia di contributore", + "show_text_search_menu": "Mostra il menu di ricerca del testo", "shuffle": "Casuale", "sidebar": "Barra laterale", "sidebar_display_description": "Visualizzare un link alla vista nella barra laterale", @@ -1891,11 +1924,12 @@ "stack_action_prompt": "{count} elementi raggruppati", "stack_duplicates": "Raggruppa i duplicati", "stack_select_one_photo": "Seleziona una foto principale per il gruppo", - "stack_selected_photos": "Impila foto selezionate", + "stack_selected_photos": "Raggruppa foto selezionate", "stacked_assets_count": "{count, plural, one {Raggruppato # asset} other {Raggruppati # asset}}", "stacktrace": "Traccia dell'errore", "start": "Avvia", "start_date": "Data di inizio", + "start_date_before_end_date": "La data di inizio deve essere precedente alla data di fine", "state": "Provincia", "status": "Stato", "stop_casting": "Interrompi trasmissione", @@ -1920,6 +1954,8 @@ "sync_albums_manual_subtitle": "Sincronizza tutti i video e le foto caricati con gli album di backup selezionati", "sync_local": "Sincronizza gli elementi locali", "sync_remote": "Sincronizza gli elementi remoti", + "sync_status": "Stato di Sincronizzazione", + "sync_status_subtitle": "Visualizza e gestisci il sistema di sincronizzazione", "sync_upload_album_setting_subtitle": "Crea e carica le tue foto e video sull'album selezionato in Immich", "tag": "Tag", "tag_assets": "Tagga risorse", @@ -1979,6 +2015,7 @@ "trash_page_select_assets_btn": "Seleziona elemento", "trash_page_title": "Cestino ({count})", "trashed_items_will_be_permanently_deleted_after": "Gli elementi cestinati saranno eliminati definitivamente dopo {days, plural, one {# giorno} other {# giorni}}.", + "troubleshoot": "Risoluzione dei problemi", "type": "Tipo", "unable_to_change_pin_code": "Impossibile cambiare il codice PIN", "unable_to_setup_pin_code": "Impossibile configurare il codice PIN", @@ -2004,7 +2041,7 @@ "unselect_all": "Deseleziona tutto", "unselect_all_duplicates": "Deseleziona tutti i duplicati", "unselect_all_in": "Deseleziona tutto in {group}", - "unstack": "Rimuovi dal gruppo", + "unstack": "Separa dal gruppo", "unstack_action_prompt": "{count} separati", "unstacked_assets_count": "{count, plural, one {Separato # asset} other {Separati # asset}}", "untagged": "Senza tag", @@ -2034,7 +2071,6 @@ "use_biometric": "Usa biometrica", "use_current_connection": "usa la connessione attuale", "use_custom_date_range": "Altrimenti utilizza un intervallo date personalizzato", - "use_this_location": "Clicca per usare la posizione", "user": "Utente", "user_has_been_deleted": "L'utente è stato rimosso.", "user_id": "ID utente", @@ -2077,11 +2113,12 @@ "view_next_asset": "Visualizza risorsa successiva", "view_previous_asset": "Visualizza risorsa precedente", "view_qr_code": "Visualizza Codice QR", + "view_similar_photos": "Visualizza le foto simili", "view_stack": "Visualizza Raggruppamento", "view_user": "Visualizza Utente", - "viewer_remove_from_stack": "Rimuovi dalla pila", + "viewer_remove_from_stack": "Rimuovi dal gruppo", "viewer_stack_use_as_main_asset": "Usa come risorsa principale", - "viewer_unstack": "Rimuovi dal gruppo", + "viewer_unstack": "Separa dal gruppo", "visibility_changed": "Visibilità modificata per {count, plural, one {# persona} other {# persone}}", "waiting": "In Attesa", "warning": "Attenzione", @@ -2092,8 +2129,9 @@ "wrong_pin_code": "Codice PIN errato", "year": "Anno", "years_ago": "{years, plural, one {# anno} other {# anni}} fa", - "yes": "Si", - "you_dont_have_any_shared_links": "Non è presente alcun link condiviso", + "yes": "SÃŦ", + "you_dont_have_any_shared_links": "Non hai nessun link condiviso", "your_wifi_name": "Nome della tua rete Wi-Fi", - "zoom_image": "Ingrandisci immagine" + "zoom_image": "Ingrandisci immagine", + "zoom_to_bounds": "Ingrandisci fino ai bordi" } diff --git a/i18n/ja.json b/i18n/ja.json index b7e484ca52..bec51aeca8 100644 --- a/i18n/ja.json +++ b/i18n/ja.json @@ -28,6 +28,7 @@ "add_to_album": "ã‚ĸãƒĢバムãĢčŋŊ加", "add_to_album_bottom_sheet_added": "{album}ãĢčŋŊ加", "add_to_album_bottom_sheet_already_exists": "{album}ãĢčŋŊ加済ãŋ", + "add_to_album_bottom_sheet_some_local_assets": "ã„ãã¤ã‹ãŽé …į›Žã¯ãžã ã‚ĩãƒŧバãƒŧへã‚ĸップロãƒŧドされãĻいãĒいためã‚ĸãƒĢバムãĢčŋŊ加できぞせんでした", "add_to_album_toggle": "{album}ぎ選択を切りæ›ŋえ", "add_to_albums": "ã‚ĸãƒĢバムãĢčŋŊ加", "add_to_albums_count": "{count}つぎã‚ĸãƒĢバムへčŋŊ加", @@ -123,6 +124,13 @@ "logging_enable_description": "ログぎ有劚化", "logging_level_description": "有劚ãĒ場合ãĢäŊŋį”¨ã•ã‚Œã‚‹ãƒ­ã‚° ãƒŦベãƒĢ。", "logging_settings": "ログ", + "machine_learning_availability_checks": "å¯į”¨æ€§ãŽįĸēčĒ", + "machine_learning_availability_checks_description": "åˆŠį”¨å¯čƒŊãĒ抟æĸ°å­Ļįŋ’ぎã‚ĩãƒŧバãƒŧをč‡Ē動で検įŸĨしå„Ēå…ˆįš„ãĢäŊŋį”¨ã—ãžã™", + "machine_learning_availability_checks_enabled": "å¯į”¨æ€§ãƒã‚§ãƒƒã‚¯ã‚’æœ‰åŠšãĢする", + "machine_learning_availability_checks_interval": "チェックぎ間隔", + "machine_learning_availability_checks_interval_description": "å¯į”¨æ€§ãƒã‚§ãƒƒã‚¯ãŽé–“éš”īŧˆãƒŸãƒĒį§’å˜äŊīŧ‰", + "machine_learning_availability_checks_timeout": "ãƒĒクエ゚トã‚ŋイムã‚ĸã‚Ļト", + "machine_learning_availability_checks_timeout_description": "å¯į”¨æ€§ãƒã‚§ãƒƒã‚¯ãŽã‚ŋイムã‚ĸã‚Ļト時間īŧˆãƒŸãƒĒį§’å˜äŊīŧ‰", "machine_learning_clip_model": "ClipãƒĸデãƒĢ", "machine_learning_clip_model_description": "CLIP ãƒĸデãƒĢぎ名前はここãĢãƒĒ゚トされãĻいぞす。ãƒĸデãƒĢを変更した場合は、すずãĻãŽã‚¤ãƒĄãƒŧジãĢ寞しãĻ「゚マãƒŧト検į´ĸã€ã‚¸ãƒ§ãƒ–ã‚’å†åŽŸčĄŒã™ã‚‹åŋ…čĻãŒã‚ã‚Šãžã™ã€‚", "machine_learning_duplicate_detection": "é‡č¤‡æ¤œå‡ē", @@ -387,8 +395,6 @@ "admin_password": "įŽĄį†č€…ãƒ‘ã‚šãƒ¯ãƒŧド", "administration": "įŽĄį†", "advanced": "čŠŗį´°č¨­åŽš", - "advanced_settings_beta_timeline_subtitle": "新しいã‚ĸプãƒĒをäŊ“験しãĻãŋぞしょう", - "advanced_settings_beta_timeline_title": "čŠĻé¨“é‹į”¨ãŽã‚ŋã‚¤ãƒ ãƒŠã‚¤ãƒŗ", "advanced_settings_enable_alternate_media_filter_subtitle": "åˆĨぎåŸēæē–ãĢåž“ãŖãĻãƒĄãƒ‡ã‚Ŗã‚ĸãƒ•ã‚Ąã‚¤ãƒĢãĢãƒ•ã‚ŖãƒĢã‚ŋãƒŧをかけãĻã€åŒæœŸã‚’čĄŒã„ãžã™ã€‚ã‚ĸプãƒĒがすずãĻぎã‚ĸãƒĢバムをčĒ­ãŋčžŧんでくれãĒい場合ãĢぎãŋ、こぎ抟čƒŊをčŠĻしãĻください。", "advanced_settings_enable_alternate_media_filter_title": "[čŠĻ鍓運ᔍ] åˆĨぎデバイ゚ぎã‚ĸãƒĢãƒãƒ åŒæœŸãƒ•ã‚ŖãƒĢã‚ŋãƒŧをäŊŋį”¨ã™ã‚‹", "advanced_settings_log_level_title": "ログãƒŦベãƒĢ: {level}", @@ -425,6 +431,7 @@ "album_remove_user_confirmation": "æœŦåŊ“ãĢ{user}を削除しぞすか?", "album_search_not_found": "検į´ĸãĢä¸€č‡´ã™ã‚‹ã‚ĸãƒĢバムがありぞせん", "album_share_no_users": "こぎã‚ĸãƒĢバムを全ãĻぎãƒĻãƒŧã‚ļãƒŧã¨å…ąæœ‰ã—ãŸã‹ã€å…ąæœ‰ã™ã‚‹ãƒĻãƒŧã‚ļãƒŧがいãĒいようです。", + "album_summary": "ã‚ĸãƒĢバムぎぞとめ", "album_updated": "ã‚ĸãƒĢバム更新", "album_updated_setting_description": "å…ąæœ‰ã‚ĸãƒĢバムãĢ新しいã‚ĸã‚ģットがčŋŊ加されたとき通įŸĨを受け取る", "album_user_left": "{album} をåŽģりぞした", @@ -496,6 +503,8 @@ "asset_restored_successfully": "垊元できぞした", "asset_skipped": "゚キップ済", "asset_skipped_in_trash": "ã‚´ãƒŸįŽąãŽä¸­", + "asset_trashed": "é …į›ŽãŒå‰Šé™¤ã•ã‚Œãžã—ãŸ", + "asset_troubleshoot": "é …į›Žã‚’ãƒˆãƒŠãƒ–ãƒĢã‚ˇãƒĨãƒŧã‡ŗ", "asset_uploaded": "ã‚ĸップロãƒŧド済", "asset_uploading": "ã‚ĸップロãƒŧド中â€Ļ", "asset_viewer_settings_subtitle": "ã‚ŽãƒŖãƒŠãƒĒãƒŧビãƒĨãƒŧã‚ĸãƒŧãĢé–ĸã™ã‚‹č¨­åŽš", @@ -529,8 +538,10 @@ "autoplay_slideshow": "ã‚šãƒŠã‚¤ãƒ‰ã‚ˇãƒ§ãƒŧをč‡Ēå‹•å†į”Ÿ", "back": "æˆģる", "back_close_deselect": "æˆģã‚‹ã€é–‰ã˜ã‚‹ã€é¸æŠžč§Ŗé™¤", + "background_backup_running_error": "バックグナã‚Ļãƒŗãƒ‰ãŽãƒãƒƒã‚¯ã‚ĸップがすでãĢčĄŒã‚ã‚ŒãĻいる最中です。そぎため、マニãƒĨã‚ĸãƒĢでぎバックã‚ĸップを開始することはできぞせん。", "background_location_permission": "バックグナã‚Ļãƒŗãƒ‰äŊįŊŽæƒ…å ąã‚ĸクã‚ģ゚", "background_location_permission_content": "æ­Ŗå¸¸ãĢWi-Fiぎ名前(SSID)ã‚’į˛åž—ã™ã‚‹ãĢはã‚ĸプãƒĒが常ãĢčŠŗį´°ãĒäŊįŊŽæƒ…å ąãĢã‚ĸクã‚ģ゚できるåŋ…čĻãŒã‚ã‚Šãžã™", + "background_options": "バックグナã‚Ļãƒŗãƒ‰ãŽå‹•äŊœã‚Ēãƒ—ã‚ˇãƒ§ãƒŗ", "backup": "バックã‚ĸップ", "backup_album_selection_page_albums_device": "デバイ゚上ぎã‚ĸãƒĢバム({count})", "backup_album_selection_page_albums_tap": "ã‚ŋップで選択、ダブãƒĢã‚ŋップで除外", @@ -538,6 +549,7 @@ "backup_album_selection_page_select_albums": "ã‚ĸãƒĢバムを選択", "backup_album_selection_page_selection_info": "選択ãƒģ除外中ぎã‚ĸãƒĢバム", "backup_album_selection_page_total_assets": "選択されたã‚ĸãƒĢãƒãƒ ãŽå†™įœŸã¨å‹•į”ģぎ数", + "backup_albums_sync": "ã‚ĸãƒĢバム同期įŠļ態をバックã‚ĸップ", "backup_all": "すずãĻ", "backup_background_service_backup_failed_message": "ã‚ĸップロãƒŧドãĢå¤ąæ•—ã—ãžã—ãŸã€‚ãƒĒトナイ中â€Ļ", "backup_background_service_connection_failed_message": "ã‚ĩãƒŧバãƒŧãĢæŽĨįļšã§ããžã›ã‚“。ãƒĒトナイ中â€Ļ", @@ -587,6 +599,7 @@ "backup_controller_page_turn_on": "バックã‚ĸップをã‚ĒãƒŗãĢする", "backup_controller_page_uploading_file_info": "ã‚ĸップロãƒŧãƒ‰ä¸­ãŽãƒ•ã‚Ąã‚¤ãƒĢ", "backup_err_only_album": "最äŊŽ1つぎã‚ĸãƒĢバムを選択しãĻください", + "backup_error_sync_failed": "同期ãĢå¤ąæ•—ã—ãžã—ãŸã€‚ãƒãƒƒã‚¯ã‚ĸップができぞせん。", "backup_info_card_assets": "å†™įœŸã¨å‹•į”ģ", "backup_manual_cancelled": "ã‚­ãƒŖãƒŗã‚ģãƒĢされぞした", "backup_manual_in_progress": "ã‚ĸップロãƒŧãƒ‰ãŒé€˛čĄŒä¸­ã§ã™ã€‚åžŒã§ã‚‚ã†ä¸€åēĻčŠĻしãĻください", @@ -597,8 +610,6 @@ "backup_setting_subtitle": "ã‚ĸップロãƒŧドãĢé–ĸã™ã‚‹č¨­åŽš", "backup_settings_subtitle": "ã‚ĸップロãƒŧãƒ‰č¨­åŽšã‚’įŽĄį†", "backward": "新しい斚へ", - "beta_sync": "同期ぎįŠļ態", - "beta_sync_subtitle": "同期ぎäģ•įĩ„ãŋã‚’įŽĄį†", "biometric_auth_enabled": "į”ŸäŊ“čĒč¨ŧを有劚化しぞした", "biometric_locked_out": "į”ŸäŊ“čĒč¨ŧãĢより、ã‚ĸクã‚ģ゚できぞせん", "biometric_no_options": "į”ŸäŊ“čĒč¨ŧã‚’åˆŠį”¨ã§ããžã›ã‚“", @@ -656,6 +667,8 @@ "change_pin_code": "PINã‚ŗãƒŧドを変更", "change_your_password": "パ゚ワãƒŧドを変更しぞす", "changed_visibility_successfully": "非表į¤ēč¨­åŽšã‚’æ­Ŗå¸¸ãĢ変更しぞした", + "charging": "充é›ģ中", + "charging_requirement_mobile_backup": "バックグナã‚Ļãƒŗãƒ‰ã§ãŽãƒãƒƒã‚¯ã‚ĸãƒƒãƒ—ã‚’čĄŒã†ãŸã‚ãĢは、デバイ゚が充é›ģ中であるåŋ…čĻãŒã‚ã‚Šãžã™", "check_corrupt_asset_backup": "į ´æã•ã‚ŒãĻã„ã‚‹é …į›Žã‚’æŽĸす", "check_corrupt_asset_backup_button": "ãƒã‚§ãƒƒã‚¯ã‚’čĄŒã†", "check_corrupt_asset_backup_description": "å†™įœŸã‚„å‹•į”ģãĒおが全ãĻã‚ĸップロãƒŧドしįĩ‚えãĻからWi-FiãĢæŽĨį™‚ぎãŋãƒã‚§ãƒƒã‚¯ã‚’čĄŒãĒãŖãĻください。äŊœæĨ­ãŒåތäē†ã™ã‚‹ãĢは数分かかる場合がありぞす", @@ -742,6 +755,7 @@ "create_user": "ãƒĻãƒŧã‚ļãƒŧをäŊœæˆ", "created": "äŊœæˆ", "created_at": "äŊœæˆ:", + "creating_linked_albums": "ãƒĒãƒŗã‚¯ã•ã‚ŒãŸã‚ĸãƒĢバムをäŊœæˆä¸­ãƒģãƒģãƒģ", "crop": "クロップ", "curated_object_page_title": "čĸĢ写äŊ“", "current_device": "įžåœ¨ãŽãƒ‡ãƒã‚¤ã‚š", @@ -891,7 +905,9 @@ "error": "エナãƒŧ", "error_change_sort_album": "ã‚ĸãƒĢãƒãƒ ãŽčĄ¨į¤ē順ぎ変更ãĢå¤ąæ•—ã—ãžã—ãŸ", "error_delete_face": "ã‚ĸã‚ģãƒƒãƒˆã‹ã‚‰éĄ”ãŽå‰Šé™¤ãŒã§ããžã›ã‚“ã§ã—ãŸ", + "error_getting_places": "場所ぎ取垗ãĢå¤ąæ•—ã—ãžã—ãŸ", "error_loading_image": "į”ģ像ぎčĒ­ãŋčžŧãŋエナãƒŧ", + "error_loading_partners": "パãƒŧトナãƒŧぎčĒ­ãŋčžŧãŋãĢå¤ąæ•—ã—ãžã—ãŸ: {error}", "error_saving_image": "エナãƒŧ: {error}", "error_tag_face_bounding_box": "éĄ”ãŽį™ģ錞ãĢå¤ąæ•—ã—ãžã—ãŸ - éĄ”ã‚’å›˛ã‚€å››č§’åŊĸぎåē§æ¨™å–åž—ãĢå¤ąæ•—", "error_title": "エナãƒŧ - å•éĄŒãŒį™ēį”Ÿã—ãžã—ãŸ", @@ -1056,6 +1072,7 @@ "favorites_page_no_favorites": "お気ãĢå…Ĩりį™ģéŒ˛ã•ã‚ŒãŸé …į›ŽãŒã‚ã‚Šãžã›ã‚“", "feature_photo_updated": "äēēį‰Šį”ģ像が更新されぞした", "features": "抟čƒŊ", + "features_in_development": "開į™ē中ぎ抟čƒŊ", "features_setting_description": "ã‚ĸプãƒĒぎ抟čƒŊã‚’įŽĄį†ã™ã‚‹", "file_name": "ãƒ•ã‚Ąã‚¤ãƒĢ名", "file_name_or_extension": "ãƒ•ã‚Ąã‚¤ãƒĢåãžãŸã¯æ‹Ąåŧĩ子", @@ -1076,10 +1093,7 @@ "gcast_enabled": "Google Cast", "gcast_enabled_description": "こぎ抟čƒŊは動äŊœãŽãŸã‚ãĢGoogleぎãƒĒã‚Ŋãƒŧ゚をčĒ­ãŋčžŧãŋぞす。", "general": "一čˆŦ", - "geolocation_instruction_all_have_location": "こぎæ—Ĩäģ˜ãŽã™ãšãĻãŽé …į›ŽãĢäŊįŊŽæƒ…å ąãŒã™ã§ãĢついãĻいぞす。すずãĻãŽé …į›Žã‚’čĄ¨į¤ēをčŠĻãŋるかåˆĨぎæ—Ĩäģ˜ã‚’選択しãĻください", "geolocation_instruction_location": "äŊįŊŽæƒ…å ąäģ˜ããŽé …į›Žã‚’ã‚¯ãƒĒックしãĻ、そぎäŊįŊŽæƒ…å ąã‚’åˆŠį”¨ã—ãžã™ã€‚ã‚ã‚‹ã„ã¯ã€åœ°å›ŗä¸ŠãŽåœ°į‚šã‚’į›´æŽĨ選ãļことも可čƒŊです", - "geolocation_instruction_no_date": "æ—Ĩäģ˜ã‚’選択しãĻ、そぎæ—ĨãŽå†™įœŸã‚„å‹•į”ģぎäŊįŊŽæƒ…å ąã‚’įŽĄį†ã—ãžã—ã‚‡ã†", - "geolocation_instruction_no_photos": "こぎæ—Ĩäģ˜ãĢå†™įœŸã‚„å‹•į”ģãŒį„Ąã„ã‚ˆã†ã§ã™ã€‚åˆĨぎæ—Ĩäģ˜ã‚’選択しãĻãŋãĻください", "get_help": "åŠŠã‘ã‚’æą‚ã‚ã‚‹", "get_wifiname_error": "Wi-Fiぎ名前(SSID)がå…Ĩ手できぞせんでした。Wi-FiãĢįš‹ãŒãŖãĻるぎとåŋ…čρãĒæ¨Šé™ã‚’č¨ąå¯ã—ãŸã‹įĸēčĒã—ãĻください", "getting_started": "はじめる", @@ -1223,6 +1237,7 @@ "local": "ロãƒŧã‚ĢãƒĢ", "local_asset_cast_failed": "ã‚ĩãƒŧバãƒŧãĢã‚ĸップロãƒŧドされãĻいãĒã„é …į›Žã¯ã‚­ãƒŖã‚šãƒˆã§ããžã›ã‚“", "local_assets": "ロãƒŧã‚ĢãƒĢãŽé …į›Ž", + "local_media_summary": "ロãƒŧã‚ĢãƒĢãƒĄãƒ‡ã‚Ŗã‚ĸぎぞとめ", "local_network": "ロãƒŧã‚ĢãƒĢネットワãƒŧク", "local_network_sheet_info": "ã‚ĸプãƒĒは指厚されたWi-FiãĢįš‹ãŒãŖãĻいる時ã‚ĩãƒŧバãƒŧへぎæŽĨįļšã‚’ä¸‹č¨˜ãŽURLã§čĄŒã„ãžã™", "location_permission": "äŊįŊŽæƒ…å ąæ¨Šé™", @@ -1234,6 +1249,7 @@ "location_picker_longitude_hint": "įĩŒåēĻをå…Ĩ力", "lock": "ロック", "locked_folder": "éĩäģ˜ããƒ•りãƒĢダãƒŧ", + "log_detail_title": "ãƒ­ã‚°ãŽčŠŗį´°", "log_out": "ログã‚ĸã‚Ļト", "log_out_all_devices": "全ãĻぎデバイ゚からログã‚ĸã‚Ļト", "logged_in_as": "{user}としãĻãƒ­ã‚°ã‚¤ãƒŗä¸­", @@ -1264,6 +1280,7 @@ "login_password_changed_success": "パ゚ワãƒŧドぎ変更ãĢ成功", "logout_all_device_confirmation": "æœŦåŊ“ãĢ全ãĻぎデバイ゚からログã‚ĸã‚Ļトしぞすか?", "logout_this_device_confirmation": "æœŦåŊ“ãĢこぎデバイ゚からログã‚ĸã‚Ļトしぞすか?", + "logs": "ログ", "longitude": "įĩŒåēĻ", "look": "čĻ‹ãŸį›Ž", "loop_videos": "動į”ģをãƒĢãƒŧプ", @@ -1306,6 +1323,7 @@ "mark_as_read": "æ—ĸčĒ­ãĢする", "marked_all_as_read": "すずãĻæ—ĸčĒ­ãĢしぞした", "matches": "マッチ", + "matching_assets": "ä¸€č‡´ã™ã‚‹é …į›Ž", "media_type": "ãƒĄãƒ‡ã‚Ŗã‚ĸã‚ŋイプ", "memories": "ãƒĄãƒĸãƒĒãƒŧ", "memories_all_caught_up": "これで全部です", @@ -1346,6 +1364,7 @@ "name_or_nickname": "名前ぞたはニックネãƒŧム", "network_requirement_photos_upload": "ãƒĸバイãƒĢ通äŋĄã‚’äŊŋį”¨ã—ãĻå†™įœŸãŽãƒãƒƒã‚¯ã‚ĸãƒƒãƒ—ã‚’čĄŒã†", "network_requirement_videos_upload": "ãƒĸバイãƒĢ通äŋĄã‚’äŊŋį”¨ã—ãĻ動į”ģぎバックã‚ĸãƒƒãƒ—ã‚’čĄŒã†", + "network_requirements": "ネットワãƒŧクぎčρäģļ", "network_requirements_updated": "ネットワãƒŧã‚¯ãŽæĄäģļが変更されたため、バックã‚ĸップぎ順į•Ēåž…ãĄã‚’ãƒĒã‚ģットしぞす", "networking_settings": "ネットワãƒŧク", "networking_subtitle": "ã‚ĩãƒŧバãƒŧã‚¨ãƒŗãƒ‰ãƒã‚¤ãƒŗãƒˆãĢé–ĸã™ã‚‹č¨­åŽš", @@ -1356,6 +1375,7 @@ "new_person": "新しいäēēį‰Š", "new_pin_code": "新しいPINã‚ŗãƒŧド", "new_pin_code_subtitle": "éĩäģ˜ããƒ•りãƒĢダãƒŧã‚’åˆŠį”¨ã™ã‚‹ãŽãŒåˆã‚ãĻぎようです。PINã‚ŗãƒŧドをäŊœæˆã—ãĻください", + "new_timeline": "新たãĒã‚ŋã‚¤ãƒ ãƒŠã‚¤ãƒŗ", "new_user_created": "新しいãƒĻãƒŧã‚ļãƒŧがäŊœæˆã•れぞした", "new_version_available": "新しいバãƒŧã‚¸ãƒ§ãƒŗãŒåˆŠį”¨å¯čƒŊ", "newest_first": "最新順", @@ -1369,20 +1389,25 @@ "no_assets_message": "クãƒĒックしãĻæœ€åˆãŽå†™įœŸã‚’ã‚ĸップロãƒŧド", "no_assets_to_show": "襨į¤ēã™ã‚‹é …į›ŽãŒã‚ã‚Šãžã›ã‚“", "no_cast_devices_found": "ã‚­ãƒŖã‚šãƒˆå…ˆãŽãƒ‡ãƒã‚¤ã‚šãŒčĻ‹ã¤ã‹ã‚Šãžã›ã‚“", + "no_checksum_local": "チェックã‚ĩムがčĻ‹ã¤ã‹ã‚Šãžã›ã‚“ - ãƒ‡ãƒã‚¤ã‚šä¸ŠãŽé …į›Žã‚’å–åž—ã§ããĒいようです", + "no_checksum_remote": "チェックã‚ĩムがčĻ‹ã¤ã‹ã‚Šãžã›ã‚“ - ã‚ĩãƒŧバãƒŧä¸ŠãŽé …į›Žã‚’å–åž—ã§ããĒいようです", "no_duplicates_found": "é‡č¤‡ã¯čĻ‹ã¤ã‹ã‚Šãžã›ã‚“ã§ã—ãŸã€‚", "no_exif_info_available": "exifæƒ…å ąãŒåˆŠį”¨ã§ããžã›ã‚“", "no_explore_results_message": "ã‚ŗãƒŦã‚¯ã‚ˇãƒ§ãƒŗã‚’æŽĸį´ĸするãĢはさらãĢå†™įœŸã‚’ã‚ĸップロãƒŧドしãĻください。", "no_favorites_message": "お気ãĢå…Ĩりį™ģéŒ˛ã™ã‚‹ã¨åĨŊきãĒå†™įœŸã‚„å‹•į”ģをすぐãĢčĻ‹ã¤ã‘ã‚‰ã‚Œãžã™", "no_libraries_message": "あãĒãŸãŽå†™įœŸã‚„å‹•į”ģã‚’čĄ¨į¤ēするためぎ外部ナイブナãƒĒをäŊœæˆã—ぞしょう", + "no_local_assets_found": "こぎチェックã‚ĩãƒ ãŽé …į›Žã¯ãƒ‡ãƒã‚¤ã‚šä¸ŠãĢ存在しぞせん", "no_locked_photos_message": "éĩäģ˜ããƒ•りãƒĢダãƒŧå†…ãŽå†™įœŸã‚„å‹•į”ģは通常ぎナイブナãƒĒãĢ襨į¤ēされãĒくãĒりぞす。", "no_name": "名前ãĒし", "no_notifications": "通įŸĨãĒし", "no_people_found": "ä¸€č‡´ã™ã‚‹äēēį‰ŠãŒčĻ‹ã¤ã‹ã‚Šãžã›ã‚“", "no_places": "場所ãĒし", + "no_remote_assets_found": "こぎチェックã‚ĩãƒ ãŽé …į›Žã¯ã‚ĩãƒŧバãƒŧ上ãĢ存在しぞせん", "no_results": "įĩæžœãŒã‚りぞせん", "no_results_description": "åŒįžŠčĒžã‚„ã‚ˆã‚Šä¸€čˆŦįš„ãĒキãƒŧワãƒŧドをčŠĻしãĻください", "no_shared_albums_message": "ã‚ĸãƒĢバムをäŊœæˆã—ãĻå†™įœŸã‚„å‹•į”ģã‚’å…ąæœ‰ã—ãžã—ã‚‡ã†", "no_uploads_in_progress": "ã‚ĸップロãƒŧãƒ‰ã¯čĄŒã‚ã‚ŒãĻいぞせん", + "not_available": "éŠį”¨ãĒし", "not_in_any_album": "おぎã‚ĸãƒĢバムãĢもå…ĨãŖãĻいãĒい", "not_selected": "選択ãĒし", "note_apply_storage_label_to_previously_uploaded assets": "æŗ¨æ„: äģĨ前ãĢã‚ĸップロãƒŧドしたã‚ĸã‚ģットãĢ゚トãƒŦãƒŧジナベãƒĢã‚’éŠį”¨ã™ã‚‹ãĢはäģĨä¸‹ã‚’åŽŸčĄŒã—ãĻください", @@ -1417,6 +1442,8 @@ "open_the_search_filters": "検į´ĸãƒ•ã‚ŖãƒĢã‚ŋを開く", "options": "ã‚Ēãƒ—ã‚ˇãƒ§ãƒŗ", "or": "ぞたは", + "organize_into_albums": "ã‚ĸãƒĢバムãĢčŋŊ加しãĻæ•´į†ã™ã‚‹", + "organize_into_albums_description": "æ—ĸå­˜ãŽå†™įœŸã‚’ã€įžåœ¨ãŽåŒæœŸč¨­åŽšãĢåŸēãĨきã‚ĸãƒĢバムãĢčŋŊ加する", "organize_your_library": "ナイブナãƒĒã‚’æ•´į†", "original": "ã‚ĒãƒĒジナãƒĢ", "other": "そぎäģ–", @@ -1476,9 +1503,9 @@ "permission_onboarding_permission_limited": "å†™įœŸã¸ãŽã‚ĸクã‚ģ゚がåˆļ限されãĻいぞす。ImmichãŒå†™įœŸãŽãƒãƒƒã‚¯ã‚ĸãƒƒãƒ—ã¨įŽĄį†ã‚’čĄŒã†ãĢã¯ã€ã‚ˇã‚šãƒ†ãƒ č¨­åŽšã‹ã‚‰å†™įœŸã¨å‹•į”ģぎã‚ĸクã‚ģ゚樊限を変更しãĻください。", "permission_onboarding_request": "Immichã¯å†™įœŸã¸ãŽã‚ĸクã‚ģã‚šč¨ąå¯ãŒåŋ…čĻã§ã™", "person": "äēēį‰Š", - "person_age_months": "{months, plural, one {# ãƒļ月} other {# ãƒļ月}} 前", - "person_age_year_months": "1 åš´, {months, plural, one {# ãƒļ月} other {# ãƒļ月}} 前", - "person_age_years": "{years, plural, other {# åš´}}前", + "person_age_months": "į”ŸåžŒ {months, plural, one {# ãƒļ月} other {# ãƒļ月}}", + "person_age_year_months": "1 æ­ŗã¨, {months, plural, one {# ãƒļ月} other {# ãƒļ月}}", + "person_age_years": "{years, plural, other {# æ­ŗ}}", "person_birthdate": "{date}į”Ÿãžã‚Œ", "person_hidden": "{name}{hidden, select, true { (非表į¤ē)} other {}}", "photo_shared_all_users": "å†™įœŸã‚’ã™ãšãĻぎãƒĻãƒŧã‚ļãƒŧã¨å…ąæœ‰ã—ãŸã‹ã€å…ąæœ‰ã™ã‚‹ãƒĻãƒŧã‚ļãƒŧがいãĒいようです。", @@ -1502,6 +1529,7 @@ "port": "ポãƒŧトãƒŦãƒŧト", "preferences_settings_subtitle": "ã‚ĸプãƒĒãĢé–ĸã™ã‚‹č¨­åŽš", "preferences_settings_title": "č¨­åŽš", + "preparing": "æē–備中", "preset": "プãƒĒã‚ģット", "preview": "プãƒŦビãƒĨãƒŧ", "previous": "前", @@ -1518,7 +1546,7 @@ "profile_drawer_client_out_of_date_minor": "ã‚ĸプãƒĒが更新されãĻぞせん。最新ぎバãƒŧã‚¸ãƒ§ãƒŗãĢ更新しãĻください", "profile_drawer_client_server_up_to_date": "すずãĻæœ€æ–°į‰ˆã§ã™", "profile_drawer_github": "GitHub", - "profile_drawer_readonly_mode": "čĒ­ãŋå–ã‚Šå°‚į”¨ãƒĸãƒŧドが有劚です。ãƒĻãƒŧã‚ļãƒŧぎã‚ĸã‚¤ã‚ŗãƒŗã‚’ãƒ€ãƒ–ãƒĢã‚ŋップしãĻčĒ­ãŋå–ã‚Šå°‚į”¨ãƒĸãƒŧãƒ‰ã‚’č§Ŗé™¤ã—ãĻください。", + "profile_drawer_readonly_mode": "čĒ­ãŋå–ã‚Šå°‚į”¨ãƒĸãƒŧドが有劚です。ãƒĻãƒŧã‚ļãƒŧぎã‚ĸã‚¤ã‚ŗãƒŗã‚’é•ˇæŠŧししãĻčĒ­ãŋå–ã‚Šå°‚į”¨ãƒĸãƒŧãƒ‰ã‚’č§Ŗé™¤ã—ãĻください。", "profile_drawer_server_out_of_date_major": "ã‚ĩãƒŧバãƒŧが更新されãĻぞせん。最新ぎバãƒŧã‚¸ãƒ§ãƒŗãĢ更新しãĻください", "profile_drawer_server_out_of_date_minor": "ã‚ĩãƒŧバãƒŧが更新されãĻぞせん。最新ぎバãƒŧã‚¸ãƒ§ãƒŗãĢ更新しãĻください", "profile_image_of_user": "{user} ãŽãƒ—ãƒ­ãƒ•ã‚ŖãƒŧãƒĢį”ģ像", @@ -1557,6 +1585,7 @@ "purchase_server_description_2": "ã‚ĩポãƒŧã‚ŋãƒŧぎįŠļ態", "purchase_server_title": "ã‚ĩãƒŧバãƒŧ", "purchase_settings_server_activated": "ã‚ĩãƒŧバãƒŧぎプロダクトキãƒŧã¯įŽĄį†č€…ãĢįŽĄį†ã•ã‚ŒãĻいぞす", + "query_asset_id": "順į•Ēåž…ãĄãŽé …į›ŽID", "queue_status": "順į•Ēåž…ãĄä¸­ {count}/{total}", "rating": "æ˜Ÿã§ãŽčŠ•äžĄ", "rating_clear": "čŠ•äžĄã‚’å–ã‚Šæļˆã™", @@ -1566,6 +1595,7 @@ "read_changelog": "変更åąĨ歴をčĒ­ã‚€", "readonly_mode_disabled": "čĒ­ãŋå–ã‚Šå°‚į”¨ãƒĸãƒŧãƒ‰į„ĄåŠš", "readonly_mode_enabled": "čĒ­ãŋå–ã‚Šå°‚į”¨ãƒĸãƒŧド有劚", + "ready_for_upload": "ã‚ĸップロãƒŧドæē–å‚™åތäē†", "reassign": "å†å‰˛ã‚ŠåŊ“ãĻ", "reassigned_assets_to_existing_person": "{count, plural, one {#個} other {#個}}ぎã‚ĸã‚ģットを{name, select, null {æ—ĸ存ぎäēēį‰Š} other {{name}}}ãĢå†å‰˛ã‚ŠåŊ“ãĻしぞした", "reassigned_assets_to_new_person": "{count, plural, one {#個} other {#個}}ぎã‚ĸã‚ģットを新しいäēēį‰ŠãĢå‰˛ã‚ŠåŊ“ãĻぞした", @@ -1590,6 +1620,7 @@ "regenerating_thumbnails": "ã‚ĩムネイãƒĢã‚’å†į”Ÿæˆä¸­", "remote": "ãƒĒãƒĸãƒŧト", "remote_assets": "ãƒĒãƒĸãƒŧãƒˆãŽé …į›Ž", + "remote_media_summary": "ã‚ĩãƒŧバãƒŧä¸ŠãŽãƒĄãƒ‡ã‚Ŗã‚ĸぞとめ", "remove": "削除", "remove_assets_album_confirmation": "æœŦåŊ“ãĢ{count, plural, one {#個} other {#個}}ぎã‚ĸã‚ģットをã‚ĸãƒĢバムから削除しぞすか?", "remove_assets_shared_link_confirmation": "æœŦåŊ“ãĢã“ãŽå…ąæœ‰ãƒĒãƒŗã‚¯ã‹ã‚‰{count, plural, one {#個} other {#個}}ぎã‚ĸã‚ģットを削除しぞすか?", @@ -1642,6 +1673,7 @@ "restore_user": "ãƒĻãƒŧã‚ļãƒŧを垊元", "restored_asset": "é …į›Žã‚’åžŠå…ƒã—ãžã—ãŸ", "resume": "再開", + "resume_paused_jobs": "再開: {count, plural, one {# paused job} other {# paused jobs}}", "retry_upload": "ã‚ĸップロãƒŧドを再čŠĻ行", "review_duplicates": "é‡č¤‡ã‚’čĒŋæŸģ", "review_large_files": "ã‚ĩイã‚ēぎ大きãĒãƒ•ã‚Ąã‚¤ãƒĢをčĻ‹ã‚‹", @@ -1846,10 +1878,8 @@ "shift_to_permanent_delete": "⇧をæŠŧしãĻã‚ĸã‚ģットを厌全ãĢ削除", "show_album_options": "ã‚ĸãƒĢãƒãƒ č¨­åŽšã‚’čĄ¨į¤ē", "show_albums": "ã‚ĸãƒĢãƒãƒ ã‚’čĄ¨į¤ē", - "show_all_assets": "すずãĻãŽé …į›Žã‚’čĄ¨į¤ē", "show_all_people": "全ãĻぎäēēį‰Šã‚’čĄ¨į¤ē", "show_and_hide_people": "äēēį‰Šã‚’čĄ¨į¤ē/非表į¤ē", - "show_assets_without_location": "äŊįŊŽæƒ…å ąį„Ąã—ãŽé …į›Žã‚’čĄ¨į¤ē", "show_file_location": "ãƒ•ã‚Ąã‚¤ãƒĢãŽå ´æ‰€ã‚’čĄ¨į¤ē", "show_gallery": "ã‚ŽãƒŖãƒŠãƒĒãƒŧã‚’čĄ¨į¤ē", "show_hidden_people": "非表į¤ēぎäēēį‰Šã‚’čĄ¨į¤ē", @@ -1866,6 +1896,7 @@ "show_slideshow_transition": "ã‚šãƒŠã‚¤ãƒ‰ã‚ˇãƒ§ãƒŧãŽãƒˆãƒŠãƒŗã‚¸ã‚ˇãƒ§ãƒŗã‚’čĄ¨į¤ē", "show_supporter_badge": "ã‚ĩポãƒŧã‚ŋãƒŧバッジ", "show_supporter_badge_description": "ã‚ĩポãƒŧã‚ŋãƒŧãƒãƒƒã‚¸ã‚’čĄ¨į¤ē", + "show_text_search_menu": "テキ゚ト検į´ĸãƒĄãƒ‹ãƒĨãƒŧã‚’čĄ¨į¤ē", "shuffle": "ãƒŠãƒŗãƒ€ãƒ ", "sidebar": "ã‚ĩイドバãƒŧ", "sidebar_display_description": "ã‚ĩイドバãƒŧãĢビãƒĨãƒŧへぎãƒĒãƒŗã‚¯ã‚’čĄ¨į¤ē", @@ -1896,6 +1927,7 @@ "stacktrace": "゚ã‚ŋックトãƒŦãƒŧ゚", "start": "開始", "start_date": "開始æ—Ĩ", + "start_date_before_end_date": "開始æ—Ĩはįĩ‚ä熿—Ĩより前でãĒければãĒりぞせん", "state": "éƒŊ道åēœįœŒ", "status": "゚テãƒŧã‚ŋ゚", "stop_casting": "ã‚­ãƒŖã‚šãƒˆã‚’åœæ­ĸ", @@ -1920,6 +1952,8 @@ "sync_albums_manual_subtitle": "ã‚ĸップロãƒŧド済ãŋぎ全ãĻãŽå†™įœŸã‚„å‹•į”ģを選択されたバックã‚ĸップã‚ĸãƒĢバムãĢ同期する", "sync_local": "ロãƒŧã‚ĢãƒĢを同期", "sync_remote": "ãƒĒãƒĸãƒŧトを同期", + "sync_status": "同期ぎįŠļ態", + "sync_status_subtitle": "åŒæœŸã‚ˇã‚šãƒ†ãƒ ã‚’įĸēčĒãƒģįŽĄį†", "sync_upload_album_setting_subtitle": "ã‚ĩãƒŧバãƒŧ上ぎã‚ĸãƒĢバムぎ内厚をį̝æœĢ上ぎã‚ĸãƒĢバムと同期しぞす (ã‚ĩãƒŧバãƒŧãĢã‚ĸãƒĢãƒãƒ ãŒį„Ąã„å ´åˆč‡Ē動でäŊœæˆã•れぞす。ぞた、ã‚ĸップロãƒŧドされãĻいãĒã„å†™įœŸã‚„å‹•į”ģは同期されぞせん)", "tag": "ã‚ŋグäģ˜ã‘する", "tag_assets": "ã‚ĸã‚ģットãĢã‚ŋグäģ˜ã‘する", @@ -1979,6 +2013,7 @@ "trash_page_select_assets_btn": "é …į›Žã‚’é¸æŠž", "trash_page_title": "ã‚´ãƒŸįŽą ({count})", "trashed_items_will_be_permanently_deleted_after": "ã‚´ãƒŸįŽąãĢå…Ĩれられたã‚ĸイテムは{days, plural, one {#æ—Ĩ} other {#æ—Ĩ}}垌ãĢ厌全ãĢ削除されぞす。", + "troubleshoot": "トナブãƒĢã‚ˇãƒĨãƒŧãƒ†ã‚Ŗãƒŗã‚°", "type": "ã‚ŋイプ", "unable_to_change_pin_code": "PINã‚ŗãƒŧドを変更できぞせんでした", "unable_to_setup_pin_code": "PINã‚ŗãƒŧドをã‚ģットã‚ĸップできぞせんでした", @@ -2028,13 +2063,12 @@ "upload_success": "ã‚ĸップロãƒŧド成功、新しくã‚ĸップロãƒŧドされたã‚ĸã‚ģットをčĻ‹ã‚‹ãĢはペãƒŧジを更新しãĻください。", "upload_to_immich": "ImmichãĢã‚ĸップロãƒŧド ({count})", "uploading": "ã‚ĸップロãƒŧド中", - "uploading_media": "ãƒĄãƒ‡ã‚Ŗã‚ĸをã‚ĸップロãƒŧド", + "uploading_media": "ãƒĄãƒ‡ã‚Ŗã‚ĸをã‚ĸップロãƒŧド中", "url": "URL", "usage": "äŊŋį”¨åŽšé‡", "use_biometric": "į”ŸäŊ“čĒč¨ŧã‚’ã”åˆŠį”¨ãã ã•ã„", "use_current_connection": "įžåœ¨ãŽæŽĨįƒ…å ąã‚’äŊŋᔍ", "use_custom_date_range": "äģŖã‚ã‚ŠãĢã‚Ģ゚ã‚ŋムæ—Ĩäģ˜į¯„å›˛ã‚’äŊŋᔍ", - "use_this_location": "クãƒĒックしãĻäŊįŊŽæƒ…å ąã‚’äŊŋう", "user": "ãƒĻãƒŧã‚ļãƒŧ", "user_has_been_deleted": "こぎãƒĻãƒŧã‚ļãƒŧは削除されぞした", "user_id": "ãƒĻãƒŧã‚ļãƒŧID", @@ -2077,6 +2111,7 @@ "view_next_asset": "æŦĄãŽã‚ĸã‚ģットをčĻ‹ã‚‹", "view_previous_asset": "前ぎã‚ĸã‚ģットをčĻ‹ã‚‹", "view_qr_code": "QRã‚ŗãƒŧドをčĻ‹ã‚‹", + "view_similar_photos": "類äŧŧã™ã‚‹å†™įœŸã‚’čĻ‹ã‚‹", "view_stack": "ビãƒĨãƒŧ゚ã‚ŋック", "view_user": "ãƒĻãƒŧã‚ļãƒŧをčĻ‹ã‚‹", "viewer_remove_from_stack": "゚ã‚ŋックから外す", @@ -2095,5 +2130,6 @@ "yes": "はい", "you_dont_have_any_shared_links": "å…ąæœ‰ãƒĒãƒŗã‚¯ã¯ã‚ã‚Šãžã›ã‚“", "your_wifi_name": "Wi-Fiぎ名前(SSID)", - "zoom_image": "į”ģåƒã‚’æ‹Ąå¤§" + "zoom_image": "į”ģåƒã‚’æ‹Ąå¤§", + "zoom_to_bounds": "į”ģéĸįĢ¯ãžã§ã‚ēãƒŧム" } diff --git a/i18n/ka.json b/i18n/ka.json index 13b0e1d065..bc1c05492b 100644 --- a/i18n/ka.json +++ b/i18n/ka.json @@ -14,6 +14,7 @@ "add_a_location": "დაამაáƒĸე ადგილი", "add_a_name": "დაამაáƒĸე სახელი", "add_a_title": "áƒ“áƒáƒáƒĄáƒáƒ—áƒáƒŖáƒ áƒ”", + "add_birthday": "დაბადების დáƒĻიქ დამაáƒĸება", "add_exclusion_pattern": "დაამაáƒĸე გამონაკლისი áƒœáƒ˜áƒ›áƒŖáƒ¨áƒ˜", "add_import_path": "დაამაáƒĸე საიმპორáƒĸო მისამართი", "add_location": "დაამაáƒĸე ადგილი", @@ -21,16 +22,20 @@ "add_partner": "დაამაáƒĸე პარáƒĸნიორი", "add_path": "დაამაáƒĸე მისამართი", "add_photos": "დაამაáƒĸე ფოáƒĸოები", + "add_tag": "დაამაáƒĸე თეგი", "add_to": "დაამაáƒĸე ...ში", "add_to_album": "დაამაáƒĸე ალბომში", "add_to_album_bottom_sheet_added": "დამაáƒĸáƒ”áƒ‘áƒŖáƒšáƒ˜áƒ {album}-ში", "add_to_album_bottom_sheet_already_exists": "{album}-ში áƒŖáƒ™áƒ•áƒ” არსებობს", + "add_to_albums": "დაამაáƒĸე ალბომებში", + "add_to_albums_count": "დაამაáƒĸე ალბომში ({count})", "add_to_shared_album": "დაამაáƒĸე საზიარო ალბომში", "add_url": "დაამაáƒĸე URL", "added_to_archive": "დაარáƒĨივდა", "added_to_favorites": "დაამაáƒĸე áƒ áƒŠáƒ”áƒŖáƒšáƒ”áƒ‘áƒ¨áƒ˜", "added_to_favorites_count": "{count, number} დაემაáƒĸა áƒ áƒŠáƒ”áƒŖáƒšáƒ”áƒ‘áƒ¨áƒ˜", "admin": { + "admin_user": "ადმინ მომხმარებელი", "asset_offline_description": "ეს საგარეო ბიბლიოთეკის აáƒĨáƒĸივი დისკზე ვერ მოიáƒĢებნა და სანაგვეში იáƒĨნა áƒ›áƒáƒ—áƒáƒ•áƒĄáƒ”áƒ‘áƒŖáƒšáƒ˜. áƒ—áƒŖ ფაილი ბიბლიოთეკის შიგნით მდებარეობს, შეამოáƒŦმეთ შესაბამისი აáƒĨáƒĸივი áƒĸაიმლაინზე. ამ აáƒĨáƒĸივის აáƒĻსადგენად, დარáƒŦáƒ›áƒŖáƒœáƒ“áƒ˜áƒ— რომ áƒĨვემოთ მოáƒĒáƒ”áƒ›áƒŖáƒšáƒ˜ ფაილის მისამართი Immich-იქ მიერ áƒŦვდომადია და დაასკანერეთ ბიბლიოთეკა.", "authentication_settings": "ავთენáƒĸიკაáƒĒიიქ პარამეáƒĸრები", "authentication_settings_description": "პაროლის, OAuth-იქ და სხვა ავáƒĸენთიფიკაáƒĒიიქ პარამეáƒĸრების მართვა", @@ -41,7 +46,7 @@ "backup_database_enable_description": "ბაზის დამპების ჩართვა", "backup_keep_last_amount": "áƒŦინა დამპების áƒ¨áƒ”áƒĄáƒáƒœáƒáƒ áƒŠáƒŖáƒœáƒ”áƒ‘áƒ”áƒšáƒ˜ რაოდენობა", "backup_settings": "მონაáƒĒემთა ბაზის დამპის მორგება", - "backup_settings_description": "მონაáƒĒემთა ბაზის პარამეáƒĸრების ამრთვა. შენიშვნა: ამ დავალებების მონიáƒĸორინგი არ ხდება და თáƒĨვენ არ მოგივათ შეáƒĸყობინება, áƒ—áƒŖ იქ ჩავარდება.", + "backup_settings_description": "მონაáƒĒემთა ბაზის ასლის შეáƒĨმნის პარამეáƒĸრების მრთვა.", "cleared_jobs": "დავალებები {job}-ისათვის გაáƒŦმენდილია", "config_set_by_file": "მიმდინარე áƒ™áƒáƒœáƒ¤áƒ˜áƒ’áƒŖáƒ áƒáƒĒია ფაილის მიერ არიქ áƒ“áƒáƒ§áƒ”áƒœáƒ”áƒ‘áƒŖáƒšáƒ˜", "confirm_delete_library": "ნამდვილად გინდა {library} ბიბლიოთეკის áƒŦაშლა?", @@ -58,6 +63,7 @@ "image_format_description": "WebP ფორმაáƒĸი JPEG-ზე პაáƒĸარა ფაილებს აáƒŦარმოებს, მაგრამ მის დამზადებას áƒŖáƒ¤áƒ áƒ მეáƒĸი დრო სჭირდება.", "image_fullsize_title": "áƒĄáƒ áƒŖáƒšáƒ˜ ზომის áƒ’áƒáƒ›áƒáƒĄáƒáƒŽáƒŖáƒšáƒ”áƒ‘áƒ˜áƒĄ პარამეáƒĸრები", "image_prefer_wide_gamut": "áƒŖáƒžáƒ˜áƒ áƒáƒĸესობა მიენიჭოს ფერის ფართე დიაპაზონს", + "image_preview_title": "áƒ’áƒáƒ›áƒáƒĄáƒáƒŽáƒŖáƒšáƒ”áƒ‘áƒ˜áƒĄ გადახედვის პარამეáƒĸრები", "image_quality": "჎არიქ჎ი", "image_resolution": "გაფართოება", "image_settings": "áƒ’áƒáƒ›áƒáƒĄáƒáƒŽáƒŖáƒšáƒ”áƒ‘áƒ˜áƒĄ პარამეáƒĸრები", @@ -68,6 +74,7 @@ "library_created": "შეიáƒĨმნა ბიბლიოთეკა: {library}", "library_deleted": "ბიბლიოთეკა áƒŦაიშალა", "library_import_path_description": "აირჩიე დასაიმპორáƒĸებელი ქაáƒĨაáƒĻალდე. ფოáƒĸოები და ვიდეოები მოიáƒĢებნება ამ ქაáƒĨაáƒĻალდესა და მასში áƒáƒ áƒĄáƒ”áƒ‘áƒŖáƒš ქაáƒĨაáƒĻალდეებში.", + "library_settings": "გარე ბიბლიოთეკა", "library_settings_description": "გარე ბიბლიოთეკების პარამეáƒĸრების მართვა", "logging_settings": "áƒŸáƒŖáƒ áƒœáƒáƒšáƒ˜", "map_settings": "áƒ áƒŖáƒ™áƒ", diff --git a/i18n/kn.json b/i18n/kn.json index 388f06704c..111c802a1e 100644 --- a/i18n/kn.json +++ b/i18n/kn.json @@ -8,11 +8,13 @@ "actions": "ā˛•āŗā˛°ā˛ŋ➝⺆➗➺⺁", "active": "ā˛¸ā˛•āŗā˛°ā˛ŋ➝", "activity": "➚➟⺁ā˛ĩ➟ā˛ŋ➕⺆", + "activity_changed": "➚➟⺁ā˛ĩ➟ā˛ŋ➕⺆ {enabled, select, true{ā˛¸ā˛•āŗā˛°ā˛ŋā˛¯ā˛—āŗŠā˛ŗā˛ŋā˛¸ā˛˛ā˛žā˛—ā˛ŋā˛Ļāŗ†} other {➍ā˛ŋā˛ˇāŗā˛•āŗā˛°ā˛ŋā˛¯ā˛—āŗŠā˛ŗā˛ŋā˛¸ā˛˛ā˛žā˛—ā˛ŋā˛Ļāŗ†}}", "add": "➏⺇➰ā˛ŋ➏ā˛ŋ", "add_a_description": "ā˛ĩā˛ŋā˛ĩā˛°ā˛Ŗāŗ†ā˛¯ā˛¨āŗā˛¨āŗ ➏⺇➰ā˛ŋ➏ā˛ŋ", "add_a_location": "ā˛¸āŗā˛Ĩ➺ā˛ĩā˛¨āŗā˛¨āŗ ➏⺇➰ā˛ŋ➏ā˛ŋ", "add_a_name": "ā˛šāŗ†ā˛¸ā˛°ā˛¨āŗā˛¨āŗ ➏⺇➰ā˛ŋ➏ā˛ŋ", "add_a_title": "ā˛ļāŗ€ā˛°āŗā˛ˇā˛ŋā˛•āŗ†ā˛¯ā˛¨āŗā˛¨āŗ ➏⺇➰ā˛ŋ➏ā˛ŋ", + "add_birthday": "ā˛œā˛¨āŗā˛Žā˛Ļā˛ŋ➍ ➏⺇➰ā˛ŋ➏ā˛ŋ", "add_endpoint": "ā˛Žā˛‚ā˛Ąāŗâ€Œā˛Ēā˛žā˛¯ā˛ŋā˛‚ā˛Ÿāŗ ➏⺇➰ā˛ŋ➏ā˛ŋ", "add_exclusion_pattern": "ā˛šāŗŠā˛°ā˛—ā˛ŋā˛Ąāŗā˛ĩā˛ŋ➕⺆ ā˛Žā˛žā˛Ļ➰ā˛ŋā˛¯ā˛¨āŗā˛¨āŗ ➏⺇➰ā˛ŋ➏ā˛ŋ", "add_import_path": "ā˛†ā˛Žā˛Ļ⺁ ā˛Žā˛žā˛°āŗā˛—ā˛ĩā˛¨āŗā˛¨āŗ ➏⺇➰ā˛ŋ➏ā˛ŋ", @@ -22,5 +24,6 @@ "add_path": "ā˛šā˛žā˛Ļā˛ŋā˛¯ā˛¨āŗā˛¨āŗ ➏⺇➰ā˛ŋ➏ā˛ŋ", "add_photos": "ā˛Ģāŗ‹ā˛Ÿāŗ‹ā˛—ā˛ŗā˛¨āŗā˛¨āŗ ➏⺇➰ā˛ŋ➏ā˛ŋ", "add_to": "➏⺇➰ā˛ŋ➏ā˛ŋâ€Ļ", - "add_to_album": "ā˛†ā˛˛āŗā˛Ŧā˛Žāŗâ€Œā˛—āŗ† ➏⺇➰ā˛ŋ➏ā˛ŋ" + "add_to_album": "ā˛†ā˛˛āŗā˛Ŧā˛Žāŗâ€Œā˛—āŗ† ➏⺇➰ā˛ŋ➏ā˛ŋ", + "add_to_album_bottom_sheet_added": "{album}➗⺆ ➏⺇➰ā˛ŋ➏ā˛ŋā˛Ļāŗ†" } diff --git a/i18n/ko.json b/i18n/ko.json index bed0418c3b..0c01c03263 100644 --- a/i18n/ko.json +++ b/i18n/ko.json @@ -8,7 +8,7 @@ "actions": "ėž‘ė—…", "active": "í™œė„ą", "activity": "활동", - "activity_changed": "í™œë™ė´ {enabled, select, true {í™œė„ąí™”} other {ëš„í™œė„ąí™”}}ë˜ė—ˆėŠĩ니다.", + "activity_changed": "í™œë™ė´ {enabled, select, true {í™œė„ąí™”} other {ëš„í™œė„ąí™”}}ë˜ė—ˆėŠĩ니다", "add": "ėļ”ę°€", "add_a_description": "네ëĒ… ėļ”ę°€", "add_a_location": "ėœ„ėš˜ ėļ”ę°€", @@ -28,20 +28,21 @@ "add_to_album": "ė•¨ë˛”ė— ėļ”ę°€", "add_to_album_bottom_sheet_added": "{album}뗐 ėļ”가됨", "add_to_album_bottom_sheet_already_exists": "ė´ë¯¸ {album}뗐 ėžˆėŒ", + "add_to_album_bottom_sheet_some_local_assets": "ëLJ ę°œė˜ 로ėģŦ 항ëĒŠė´ ė•¨ë˛”ė— ėļ”ę°€ë˜ė§€ ė•Šė•˜ėŠĩ니다", "add_to_album_toggle": "{album} ė„ íƒ/í•´ė œ", "add_to_albums": "ė—ŦëŸŦ ė•¨ë˛”ė— ėļ”ę°€", "add_to_albums_count": "ė—ŦëŸŦ ė•¨ë˛”ė— ėļ”ę°€ ({count})", "add_to_shared_album": "ęŗĩ뜠 ė•¨ë˛”ė— ėļ”ę°€", "add_url": "URL ėļ”ę°€", - "added_to_archive": "ëŗ´ę´€í•¨ėœŧ로 ė´ë™ë˜ė—ˆėŠĩ니다.", - "added_to_favorites": "ėĻę˛¨ė°žę¸°ė— ėļ”ę°€ë˜ė—ˆėŠĩ니다.", + "added_to_archive": "ëŗ´ę´€í•¨ėœŧ로 ė´ë™ë˜ė—ˆėŠĩ니다", + "added_to_favorites": "ėĻę˛¨ė°žę¸°ė— ėļ”ę°€ë˜ė—ˆėŠĩ니다", "added_to_favorites_count": "ėĻę˛¨ė°žę¸°ė— 항ëĒŠ {count, number}氜 ėļ”가됨", "admin": { "add_exclusion_pattern_description": "*, **, ? ë“ąė˜ glob íŒ¨í„´ė„ ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다. 똈ëĨŧ ë“¤ė–´ \"Raw\" 폴더 내 ëĒ¨ë“  파ėŧė„ ė œė™¸í•˜ë ¤ëŠ´ \"**/Raw/**\"ëĨŧ, .tif 파ėŧė„ ė œė™¸í•˜ë ¤ëŠ´ \"**/*.tif\", íŠšė •í•œ ė ˆëŒ€ ę˛Ŋ로ëĨŧ ė œė™¸í•˜ë ¤ëŠ´ \"/path/to/ignore/**\" 래ëŸŧ ė‚ŦėšŠí•Šë‹ˆë‹¤.", "admin_user": "관ëĻŦėž", "asset_offline_description": "ė´ 항ëĒŠė€ 뙏ëļ€ ëŧė´ë¸ŒëŸŦëĻŦ뗐 ë“ąëĄë˜ė—ˆėœŧ나 ë””ėŠ¤íŦė—ė„œ ė°žė„ 눘 뗆떴 íœ´ė§€í†ĩėœŧ로 ė´ë™í–ˆėŠĩ니다. 파ėŧė´ ëŧė´ë¸ŒëŸŦëĻŦ ę˛Ŋ로 ë‚´ė—ė„œ ė´ë™ëœ ę˛Ŋ뚰 íƒ€ėž„ëŧė¸ė—ė„œ ėƒˆëĄœ ė¸ė‹ëœ 항ëĒŠė´ ėžˆëŠ”ė§€ í™•ė¸í•´ëŗ´ė„¸ėš”. ė´ 항ëĒŠė„ ëŗĩė›í•˜ë ¤ëŠ´ ė•„ëž˜ ę˛ŊëĄœė— Immich가 ė ‘ęˇŧ할 눘 ėžˆëŠ”ė§€ í™•ė¸í•˜ęŗ  ëŧė´ë¸ŒëŸŦëĻŦëĨŧ ë‹¤ė‹œ 늤ėē”í•˜ė„¸ėš”.", "authentication_settings": "ė¸ėĻ 네렕", - "authentication_settings_description": "비밀번호, OAuth 및 기타 ė¸ėĻ ė„¤ė •ė„ 관ëĻŦ합니다.", + "authentication_settings_description": "비밀번호, OAuth 및 기타 ė¸ėĻ ė„¤ė •ė„ 관ëĻŦ합니다", "authentication_settings_disable_all": "ëĒ¨ë“  ëĄœęˇ¸ė¸ ėˆ˜ë‹¨ė„ ëš„í™œė„ąí™”í•˜ė‹œę˛ ėŠĩ니까? ë”ė´ėƒ ëĄœęˇ¸ė¸í•  눘 ė—†ėŠĩ니다.", "authentication_settings_reenable": "ë‹¤ė‹œ í™œė„ąí™”í•˜ë ¤ëŠ´ ė„œë˛„ ëĒ…ë šė–´ëĨŧ ė‚ŦėšŠí•˜ė„¸ėš”.", "background_task_job": "밹꡸ëŧėš´ë“œ ėž‘ė—…", @@ -49,7 +50,7 @@ "backup_database_enable_description": "ë°ė´í„°ë˛ ė´ėŠ¤ 덤프 í™œė„ąí™”", "backup_keep_last_amount": "ëŗ´ę´€í•  ė´ė „ 덤프 눘", "backup_onboarding_1_description": "개는 클ëŧėš°ë“œë‚˜ 다ëĨ¸ ëŦŧëĻŦ렁 ėœ„ėš˜ė— ëŗ´ę´€í•Šë‹ˆë‹¤.", - "backup_onboarding_2_description": "개는 ė„œëĄœ 다ëĨ¸ 로ėģŦ ėžĨėš˜ė— ëŗ´ę´€í•˜ęŗ ,", + "backup_onboarding_2_description": "다ëĨ¸ ę¸°ę¸°ė˜ 로ėģŦ ė‚Ŧëŗ¸. ëŠ”ė¸ 파ėŧęŗŧ 로ėģŦ ë°ąė—…ė„ íŦ함합니다.", "backup_onboarding_3_description": "ę°œė˜ ë°ė´í„° ė‚Ŧëŗ¸ė„ 만듭니다.", "backup_onboarding_description": "ė†Œė¤‘í•œ ë°ė´í„°ëĨŧ ė•ˆė „í•˜ę˛Œ ëŗ´í˜¸í•˜ę¸° ėœ„í•´ 3-2-1 ë°ąė—… ė „ëžĩ ė‚ŦėšŠė„ ęļŒėžĨ합니다. ImmichëĨŧ ë°ąė—…í•  때 ė—…ëĄœë“œí•œ ė‚Ŧė§„ 및 ë™ė˜ėƒëŋ ė•„ë‹ˆëŧ ë°ė´í„°ë˛ ė´ėŠ¤ë„ 함ęģ˜ ëŗ´ę´€í•´ė•ŧ 한다는 ė ė„ ėžŠė§€ ë§ˆė„¸ėš”.", "backup_onboarding_footer": "Immich ë°ąė—…ė— 대한 ėžė„¸í•œ ë‚´ėšŠė€ ęŗĩė‹ ëŦ¸ė„œëĨŧ ė°¸ėĄ°í•˜ė„¸ėš”.", @@ -58,10 +59,10 @@ "backup_settings": "ë°ė´í„°ë˛ ė´ėŠ¤ 덤프 네렕", "backup_settings_description": "ë°ė´í„°ë˛ ė´ėŠ¤ 덤프 ėŖŧ揰뙀 ëŗ´ę´€ ę¸°ę°„ė„ ė„¤ė •í•Šë‹ˆë‹¤.", "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}\"ė„(ëĨŧ) ėž…ë Ĩí•˜ė„¸ėš”.", + "confirm_email_below": "ęŗ„ė†í•˜ë ¤ëŠ´ ė•„ëž˜ė— \"{email}\"ė„(ëĨŧ) ėž…ë Ĩí•˜ė„¸ėš”", "confirm_reprocess_all_faces": "ëĒ¨ë“  ė–ŧęĩ´ė„ ë‹¤ė‹œ 래ëĻŦí•˜ė‹œę˛ ėŠĩ니까? ė´ëĻ„ė´ ė§€ė •ëœ ė¸ëŦŧ도 ė´ˆę¸°í™”ëŠë‹ˆë‹¤.", "confirm_user_password_reset": "{user}ë‹˜ė˜ 비밀번호ëĨŧ ė´ˆę¸°í™”í•˜ė‹œę˛ ėŠĩ니까?", "confirm_user_pin_code_reset": "{user}ë‹˜ė˜ PIN ėŊ”드ëĨŧ ė´ˆę¸°í™”í•˜ė‹œę˛ ėŠĩ니까?", @@ -70,7 +71,7 @@ "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_management": "뙏ëļ€ ëŧė´ë¸ŒëŸŦëĻŦ 관ëĻŦ", "face_detection": "ė–ŧęĩ´ 氐맀", @@ -123,6 +124,13 @@ "logging_enable_description": "로그 기록 í™œė„ąí™”", "logging_level_description": "í™œė„ąí™” ė‹œ ė‚ŦėšŠí•  로그 ë ˆë˛¨ė„ ė„ íƒí•Šë‹ˆë‹¤.", "logging_settings": "로깅", + "machine_learning_availability_checks": "ę°€ėšŠė„ą í™•ė¸", + "machine_learning_availability_checks_description": "ė‚ŦėšŠ 가ëŠĨ한 ë¨¸ė‹  ëŸŦ닝 ė„œë˛„ëĨŧ ėžë™ėœŧ로 ę°ė§€í•˜ęŗ  ėš°ė„ ė ėœŧ로 ė„ íƒí•Šë‹ˆë‹¤", + "machine_learning_availability_checks_enabled": "ę°€ėšŠė„ą í™•ė¸ í™œė„ąí™”", + "machine_learning_availability_checks_interval": "í™•ė¸ ėŖŧ기", + "machine_learning_availability_checks_interval_description": "ę°€ėšŠė„ą í™•ė¸ ėŖŧ기 (밀ëĻŦ봈 ë‹¨ėœ„)", + "machine_learning_availability_checks_timeout": "ėš”ė˛­ íƒ€ėž„ė•„ė›ƒ", + "machine_learning_availability_checks_timeout_description": "ę°€ėšŠė„ą í™•ė¸ ėš”ė˛­ íƒ€ėž„ė•„ė›ƒ (밀ëĻŦ봈 ë‹¨ėœ„)", "machine_learning_clip_model": "CLIP ëĒ¨ë¸", "machine_learning_clip_model_description": "CLIP ëĒ¨ë¸ė˜ ėĸ…ëĨ˜ëŠ” ė´ęŗŗė„ ė°¸ėĄ°í•˜ė„¸ėš”. 한ęĩ­ė–´ 등 ė—ŦëŸŦ ė–¸ė–´ëĄœ ę˛€ėƒ‰í•˜ë ¤ëŠ´ Multilingual CLIP ëĒ¨ë¸ė„ ė„ íƒí•˜ė„¸ėš”. ëĒ¨ë¸ė„ ëŗ€ę˛Ŋ한 ę˛Ŋ뚰 ëĒ¨ë“  ė´ë¯¸ė§€ė˜ 'ėŠ¤ë§ˆíŠ¸ ę˛€ėƒ‰' ėž‘ė—…ė„ ë‹¤ė‹œ ė‹¤í–‰í•´ė•ŧ 합니다.", "machine_learning_duplicate_detection": "ëš„ėŠˇí•œ 항ëĒŠ 氐맀", @@ -387,8 +395,6 @@ "admin_password": "관ëĻŦėž 비밀번호", "administration": "관ëĻŦ", "advanced": "溠揉", - "advanced_settings_beta_timeline_subtitle": "ėƒˆëĄœėš´ ė•ą ę˛Ŋ험 ė‚ŦėšŠí•´ëŗ´ę¸°", - "advanced_settings_beta_timeline_title": "베타 íƒ€ėž„ëŧė¸", "advanced_settings_enable_alternate_media_filter_subtitle": "ė´ ė˜ĩė…˜ė„ ė‚ŦėšŠí•˜ëŠ´ 동기화 뤑 ë¯¸ë””ė–´ëĨŧ ëŒ€ė˛´ 揰뤀ėœŧ로 필터링할 눘 ėžˆėŠĩ니다. ė•ąė´ ëĒ¨ë“  ė•¨ë˛”ė„ ė œëŒ€ëĄœ ę°ė§€í•˜ė§€ ëĒģ할 때만 ė‚ŦėšŠí•˜ė„¸ėš”.", "advanced_settings_enable_alternate_media_filter_title": "ëŒ€ė˛´ 기기 ė•¨ë˛” 동기화 필터 ė‚ŦėšŠ (ė‹¤í—˜ė )", "advanced_settings_log_level_title": "로그 레벨: {level}", @@ -396,6 +402,7 @@ "advanced_settings_prefer_remote_title": "ė„œë˛„ ė´ë¯¸ė§€ ė„ í˜¸", "advanced_settings_proxy_headers_subtitle": "Immich가 ë„¤íŠ¸ė›ŒíŦ ėš”ė˛­ ė‹œ ė‚ŦėšŠí•  í”„ëĄė‹œ 헤더ëĨŧ ė •ė˜í•Šë‹ˆë‹¤.", "advanced_settings_proxy_headers_title": "í”„ëĄė‹œ 헤더", + "advanced_settings_readonly_mode_subtitle": "ėŊ기 ė „ėšŠ ëĒ¨ë“œëĨŧ í™œė„ąí™”í•˜ëŠ´ ė—ŦëŸŦ ė´ë¯¸ė§€ ė„ íƒ, ęŗĩ뜠, ėēėŠ¤íŠ¸, ė‚­ė œ ë™ėž‘ė´ ëĒ¨ë‘ ëš„í™œė„ąí™”ëŠë‹ˆë‹¤. ëŠ”ė¸ í™”ëŠ´ė—ė„œ ė‚ŦėšŠėž í”„ëĄœí•„ė„ í†ĩ해 ėŊ기 ė „ėšŠ ëĒ¨ë“œė˜ í™œė„ą ėƒíƒœëĨŧ ė „í™˜í•˜ė„¸ėš”", "advanced_settings_readonly_mode_title": "ėŊ기 ė „ėšŠ ëĒ¨ë“œ", "advanced_settings_self_signed_ssl_subtitle": "ė„œë˛„ ė—”ë“œíŦė¸íŠ¸ė˜ SSL ė¸ėĻė„œ 검ėĻė„ 건너뜁니다. ėžė˛´ ė„œëĒ… ė¸ėĻė„œëĨŧ ė‚ŦėšŠí•˜ëŠ” ę˛Ŋ뚰 í™œė„ąí™”í•˜ė„¸ėš”.", "advanced_settings_self_signed_ssl_title": "ėžė˛´ ė„œëĒ…ëœ SSL ė¸ėĻė„œ í—ˆėšŠ", @@ -424,6 +431,7 @@ "album_remove_user_confirmation": "{user}ë‹˜ė„ ė•¨ë˛”ė—ė„œ ė œęą°í•˜ė‹œę˛ ėŠĩ니까?", "album_search_not_found": "ę˛€ėƒ‰ 결ęŗŧ뗐 해당하는 ė•¨ë˛”ė´ ė—†ėŠĩ니다.", "album_share_no_users": "ė´ë¯¸ ëĒ¨ë“  ė‚ŦėšŠėžė™€ ė•¨ë˛”ė„ ęŗĩėœ í–ˆęą°ë‚˜ ęŗĩėœ í•  ė‚ŦėšŠėžę°€ ė—†ėŠĩ니다.", + "album_summary": "ė•¨ë˛” ėš”ė•Ŋ", "album_updated": "항ëĒŠ ėļ”ę°€ ė•ŒëĻŧ", "album_updated_setting_description": "ęŗĩ뜠 ė•¨ë˛”ė— 항ëĒŠė´ ėļ”ę°€ëœ ę˛Ŋ뚰 ė´ëŠ”ėŧ ė•ŒëĻŧ 받기", "album_user_left": "{album} ė•¨ë˛”ė—ė„œ ë‚˜ė˜´", @@ -495,6 +503,8 @@ "asset_restored_successfully": "항ëĒŠė´ ëŗĩė›ë˜ė—ˆėŠĩ니다.", "asset_skipped": "건너뜀", "asset_skipped_in_trash": "íœ´ė§€í†ĩė˜ 항ëĒŠ", + "asset_trashed": "항ëĒŠ ė‚­ė œë¨", + "asset_troubleshoot": "항ëĒŠ 트ëŸŦë¸”ėŠˆíŒ…", "asset_uploaded": "ė—…ëĄœë“œ ė™„ëŖŒ", "asset_uploading": "ė—…ëĄœë“œ 뤑â€Ļ", "asset_viewer_settings_subtitle": "ę°¤ëŸŦëĻŦ ëŗ´ę¸° ė„¤ė •ė„ 관ëĻŦ합니다.", @@ -528,8 +538,10 @@ "autoplay_slideshow": "ėŠŦëŧė´ë“œ ė‡ŧ ėžë™ ėžŦėƒ", "back": "뒤로", "back_close_deselect": "뒤로, ë‹Ģ기 또는 ė„ íƒ í•´ė œ", + "background_backup_running_error": "밹꡸ëŧėš´ë“œ ë°ąė—…ė´ 현ėžŦ ė§„í–‰ ė¤‘ė´ë¯€ëĄœ ėˆ˜ë™ ë°ąė—…ė„ ė‹œėž‘í•  눘 ė—†ėŠĩ니다", "background_location_permission": "밹꡸ëŧėš´ë“œ ėœ„ėš˜ ęļŒí•œ", "background_location_permission_content": "Immich가 밹꡸ëŧėš´ë“œė—ė„œ ė‹¤í–‰ 뤑ėŧ 때 ë„¤íŠ¸ė›ŒíŦëĨŧ ė „í™˜í•˜ë ¤ëŠ´ Wi-Fi ë„¤íŠ¸ė›ŒíŦ ė´ëĻ„ė„ í™•ė¸í•´ė•ŧ 하며, ė´ëĨŧ ėœ„í•´ 'ė •í™•í•œ ėœ„ėš˜' ęļŒí•œė„ í•­ėƒ í—ˆėšŠí•´ė•ŧ 합니다.", + "background_options": "밹꡸ëŧėš´ë“œ ė˜ĩė…˜", "backup": "ë°ąė—…", "backup_album_selection_page_albums_device": "ę¸°ę¸°ė˜ ė•¨ë˛” ({count})", "backup_album_selection_page_albums_tap": "탭하ė—Ŧ íŦ함, 두 번 탭하ė—Ŧ ė œė™¸", @@ -537,6 +549,7 @@ "backup_album_selection_page_select_albums": "ė•¨ë˛” ė„ íƒ", "backup_album_selection_page_selection_info": "ė„ íƒí•œ ė•¨ë˛”", "backup_album_selection_page_total_assets": "렄랴 항ëĒŠ", + "backup_albums_sync": "ė•¨ë˛” 동기화 ë°ąė—…", "backup_all": "ëĒ¨ë‘", "backup_background_service_backup_failed_message": "항ëĒŠ ë°ąė—…ė— ė‹¤íŒ¨í–ˆėŠĩ니다. ë‹¤ė‹œ ė‹œë„í•˜ëŠ” 뤑â€Ļ", "backup_background_service_connection_failed_message": "ė„œë˛„ 뗰枰뗐 ė‹¤íŒ¨í–ˆėŠĩ니다. ë‹¤ė‹œ ė‹œë„í•˜ëŠ” 뤑â€Ļ", @@ -586,6 +599,7 @@ "backup_controller_page_turn_on": "í™œė„ąí™”", "backup_controller_page_uploading_file_info": "파ėŧ ė •ëŗ´ ė—…ëĄœë“œ 뤑", "backup_err_only_album": "뜠ėŧ한 ė•¨ë˛”ė€ ė‚­ė œí•  눘 ė—†ėŠĩ니다.", + "backup_error_sync_failed": "ë™ę¸°í™”ė— ė‹¤íŒ¨í–ˆėŠĩ니다. ë°ąė—…ė„ ė§„í–‰í•  눘 ė—†ėŠĩ니다.", "backup_info_card_assets": "항ëĒŠ", "backup_manual_cancelled": "ėˇ¨ė†Œë¨", "backup_manual_in_progress": "ė—…ëĄœë“œę°€ ė´ë¯¸ ė§„í–‰ ė¤‘ėž…ë‹ˆë‹¤. ėž ė‹œ 후 ë‹¤ė‹œ ė‹œë„í•˜ė„¸ėš”", @@ -596,8 +610,6 @@ "backup_setting_subtitle": "밹꡸ëŧėš´ë“œ 및 íŦ꡸ëŧėš´ë“œ ë°ąė—… ė„¤ė •ė„ 관ëĻŦ합니다.", "backup_settings_subtitle": "ė—…ëĄœë“œ ė„¤ė •ė„ 관ëĻŦ합니다.", "backward": "뒤로", - "beta_sync": "동기화 (베타) ėƒíƒœ", - "beta_sync_subtitle": "냈 동기화 ė‹œėŠ¤í…œė˜ ė„¤ė •ė„ 관ëĻŦ합니다.", "biometric_auth_enabled": "ėƒė˛´ ė¸ėĻė´ í™œė„ąí™”ë˜ė—ˆėŠĩ니다.", "biometric_locked_out": "ėƒė˛´ ė¸ėĻė´ ėŧė‹œė ėœŧ로 ëš„í™œė„ąí™”ë˜ė—ˆėŠĩ니다.", "biometric_no_options": "ė‚ŦėšŠ 가ëŠĨ한 ėƒė˛´ ė¸ėĻ ė˜ĩė…˜ ė—†ėŒ", @@ -655,6 +667,8 @@ "change_pin_code": "PIN ėŊ”드 ëŗ€ę˛Ŋ", "change_your_password": "ė‚ŦėšŠėž ęŗ„ė •ė˜ 비밀번호ëĨŧ ëŗ€ę˛Ŋ합니다.", "changed_visibility_successfully": "ėˆ¨ęš€ ė—Ŧëļ€ę°€ ëŗ€ę˛Ŋë˜ė—ˆėŠĩ니다.", + "charging": "ėļŠė „ 뤑", + "charging_requirement_mobile_backup": "밹꡸ëŧėš´ë“œ ë°ąė—…ė€ 기기 ėļŠė „ ėƒíƒœė—ė„œ 가ëŠĨ합니다", "check_corrupt_asset_backup": "ë°ąė—…ëœ 항ëĒŠė˜ ė†ėƒ ė—Ŧëļ€ í™•ė¸", "check_corrupt_asset_backup_button": "í™•ė¸ ėˆ˜í–‰", "check_corrupt_asset_backup_description": "ė´ 검ė‚Ŧ는 ëĒ¨ë“  항ëĒŠė´ ë°ąė—…ëœ 후 Wi-Fi가 ė—°ę˛°ëœ ėƒíƒœė—ė„œë§Œ ė‹¤í–‰í•˜ė„¸ėš”. ė´ ėž‘ė—…ė€ ëLJ ëļ„ ė •ë„ ė†Œėš”ë  눘 ėžˆėŠĩ니다.", @@ -741,6 +755,7 @@ "create_user": "ė‚ŦėšŠėž ęŗ„ė • ėƒė„ą", "created": "ėƒė„ąë¨", "created_at": "ėƒė„ąë¨", + "creating_linked_albums": "링íŦ ė—°ę˛°ëœ ė•¨ë˛” ėƒė„ą 뤑...", "crop": "ėžëĨ´ę¸°", "curated_object_page_title": "ė‚ŦëŦŧ", "current_device": "현ėžŦ 기기", @@ -890,7 +905,9 @@ "error": "똤ëĨ˜", "error_change_sort_album": "ė•¨ë˛” í‘œė‹œ ėˆœė„œ ëŗ€ę˛Ŋ ė‹¤íŒ¨", "error_delete_face": "항ëĒŠė—ė„œ ė–ŧęĩ´ ė‚­ė œ 뤑 똤ëĨ˜ ë°œėƒ", + "error_getting_places": "ėžĨė†Œ ė •ëŗ´ ėž…ë Ĩ ė‹¤íŒ¨", "error_loading_image": "ė´ë¯¸ė§€ëĨŧ ëļˆëŸŦė˜¤ëŠ” 뤑 똤ëĨ˜ ë°œėƒ", + "error_loading_partners": "파트너 ëļˆëŸŦ똤揰 ė‹¤íŒ¨: {error}", "error_saving_image": "똤ëĨ˜: {error}", "error_tag_face_bounding_box": "ė–ŧęĩ´ 태그 ė‹¤íŒ¨ - ė–ŧęĩ´ė˜ ėœ„ėš˜ëĨŧ 氀렏ė˜Ŧ 눘 ė—†ėŠĩ니다.", "error_title": "똤ëĨ˜ - ëŦ¸ė œę°€ ë°œėƒí–ˆėŠĩ니다", @@ -1055,6 +1072,7 @@ "favorites_page_no_favorites": "ėĻę˛¨ė°žę¸°ëœ 항ëĒŠ ė—†ėŒ", "feature_photo_updated": "대표 ė‚Ŧė§„ ė—…ë°ė´íŠ¸ë¨", "features": "기ëŠĨ", + "features_in_development": "개발 ė¤‘ė¸ 기ëŠĨ", "features_setting_description": "ė‚Ŧė§„ 및 ë™ė˜ėƒ 관ëĻŦ 기ëŠĨė„ ė„¤ė •í•Šë‹ˆë‹¤.", "file_name": "파ėŧ ė´ëĻ„", "file_name_or_extension": "파ėŧëĒ… 또는 확ėžĨėž", @@ -1075,6 +1093,7 @@ "gcast_enabled": "ęĩŦ글 ėēėŠ¤íŠ¸", "gcast_enabled_description": "ė´ 기ëŠĨė€ Googleė˜ 뙏ëļ€ ëĻŦė†ŒėŠ¤ëĨŧ ė‚ŦėšŠí•˜ė—Ŧ ė‹¤í–‰ëŠë‹ˆë‹¤.", "general": "ėŧ반", + "geolocation_instruction_location": "GPS ėĸŒí‘œę°€ íŦ함된 항ëĒŠė„ 클ëĻ­í•´ ėœ„ėš˜ëĨŧ ė‚ŦėšŠí•˜ęą°ë‚˜, ė§€ë„ė—ė„œ 링렑 ėœ„ėš˜ëĨŧ ė„ íƒí•˜ė„¸ėš”", "get_help": "ë„ė›€ ė–ģ기", "get_wifiname_error": "Wi-Fi ė´ëĻ„ė„ 氀렏ė˜Ŧ 눘 ė—†ėŠĩ니다. í•„ėˆ˜ ęļŒí•œė´ ëļ€ė—Ŧë˜ė—ˆëŠ”ė§€, Wi-Fi ë„¤íŠ¸ė›ŒíŦ뗐 ė—°ę˛°ë˜ė–´ ėžˆëŠ”ė§€ í™•ė¸í•˜ė„¸ėš”.", "getting_started": "ė‹œėž‘í•˜ę¸°", @@ -1218,6 +1237,7 @@ "local": "로ėģŦ", "local_asset_cast_failed": "ė„œë˛„ė— ė—…ëĄœë“œë˜ė§€ ė•Šė€ 항ëĒŠė„ ėēėŠ¤íŒ…í•  눘 ė—†ėŒ", "local_assets": "로ėģŦ 항ëĒŠ", + "local_media_summary": "로ėģŦ ë¯¸ë””ė–´ ėš”ė•Ŋ", "local_network": "로ėģŦ ë„¤íŠ¸ė›ŒíŦ", "local_network_sheet_info": "ė§€ė •ëœ Wi-FiëĨŧ ė‚ŦėšŠí•  때 ė•ąė´ ė•„ëž˜ URL로 ė„œë˛„ė— ė—°ę˛°í•Šë‹ˆë‹¤.", "location_permission": "ėœ„ėš˜ ęļŒí•œ", @@ -1229,6 +1249,7 @@ "location_picker_longitude_hint": "ė—Ŧ揰뗐 ę˛Ŋ도ëĨŧ ėž…ë Ĩí•˜ė„¸ėš”", "lock": "ėž ę¸ˆ", "locked_folder": "ėž ę¸ˆ 폴더", + "log_detail_title": "ėƒė„¸ 로그", "log_out": "ëĄœęˇ¸ė•„ė›ƒ", "log_out_all_devices": "ëĒ¨ë“  ę¸°ę¸°ė—ė„œ ëĄœęˇ¸ė•„ė›ƒ", "logged_in_as": "{user}로 ëĄœęˇ¸ė¸ë¨", @@ -1259,6 +1280,7 @@ "login_password_changed_success": "비밀번호가 ëŗ€ę˛Ŋë˜ė—ˆėŠĩ니다.", "logout_all_device_confirmation": "ëĒ¨ë“  ę¸°ę¸°ė—ė„œ ëĄœęˇ¸ė•„ė›ƒí•˜ė‹œę˛ ėŠĩ니까?", "logout_this_device_confirmation": "ė´ ę¸°ę¸°ė—ė„œ ëĄœęˇ¸ė•„ė›ƒí•˜ė‹œę˛ ėŠĩ니까?", + "logs": "로그", "longitude": "ę˛Ŋ도", "look": "ëŗ´ę¸°", "loop_videos": "ë™ė˜ėƒ 반ëŗĩ", @@ -1301,6 +1323,7 @@ "mark_as_read": "ėŊėŒėœŧ로 í‘œė‹œ", "marked_all_as_read": "ëĒ¨ë‘ ėŊėŒėœŧ로 í‘œė‹œí–ˆėŠĩ니다.", "matches": "ėŧėš˜", + "matching_assets": "ėŧėš˜í•˜ëŠ” 항ëĒŠ", "media_type": "ë¯¸ë””ė–´ ėĸ…ëĨ˜", "memories": "ėļ”ė–ĩ", "memories_all_caught_up": "ëĒ¨ë‘ í™•ė¸í•¨", @@ -1341,6 +1364,7 @@ "name_or_nickname": "ė´ëĻ„ 또는 ë‹‰ë„¤ėž„", "network_requirement_photos_upload": "ė‚Ŧė§„ ë°ąė—…ė— ëĒ¨ë°”ėŧ ë°ė´í„° ė‚ŦėšŠ", "network_requirement_videos_upload": "ë™ė˜ėƒ ë°ąė—…ė— ëĒ¨ë°”ėŧ ë°ė´í„° ė‚ŦėšŠ", + "network_requirements": "ë„¤íŠ¸ė›ŒíŦ ėš”ęĩŦė‚Ŧ항", "network_requirements_updated": "ë„¤íŠ¸ė›ŒíŦ ėƒíƒœę°€ ëŗ€ę˛Ŋë˜ė—ˆėŠĩ니다. ë°ąė—… ëŒ€ę¸°ė—´ė„ ė´ˆę¸°í™”í•Šë‹ˆë‹¤.", "networking_settings": "뗰枰", "networking_subtitle": "ė„œë˛„ ė—”ë“œíŦė¸íŠ¸ ė„¤ė •ė„ 관ëĻŦ합니다.", @@ -1351,6 +1375,7 @@ "new_person": "냈 ė¸ëŦŧ ėƒė„ą", "new_pin_code": "냈 PIN ėŊ”드", "new_pin_code_subtitle": "ėž ę¸ˆ í´ë”ė— ė˛˜ėŒ ė ‘ęˇŧí•˜ė…¨ėŠĩ니다. ė´ęŗŗė— ė•ˆė „í•˜ę˛Œ ė ‘ęˇŧ하기 ėœ„í•œ PIN ėŊ”드ëĨŧ ė„¤ė •í•˜ė„¸ėš”.", + "new_timeline": "냈 íƒ€ėž„ëŧė¸", "new_user_created": "ė‚ŦėšŠėž ęŗ„ė •ė´ ėƒė„ąë˜ė—ˆėŠĩ니다.", "new_version_available": "냈 ë˛„ė „ ė‚ŦėšŠ 가ëŠĨ", "newest_first": "ėĩœė‹ ėˆœ", @@ -1364,20 +1389,25 @@ "no_assets_message": "ė—Ŧ기ëĨŧ 클ëĻ­í•´ ė˛Ģ ė‚Ŧė§„ė„ ė—…ëĄœë“œí•˜ė„¸ėš”.", "no_assets_to_show": "í‘œė‹œí•  항ëĒŠ ė—†ėŒ", "no_cast_devices_found": "ėēėŠ¤íŠ¸ 기기 ė—†ėŒ", + "no_checksum_local": "랴íŦė„Ŧė´ ė—†ėŠĩ니다. 로ėģŦ 항ëĒŠė„ ëļˆëŸŦė˜Ŧ 눘 ė—†ėŠĩ니다", + "no_checksum_remote": "랴íŦė„Ŧė´ ė—†ėŠĩ니다. 뙏ëļ€ í•­ëĒŠė„ ëļˆëŸŦė˜Ŧ 눘 ė—†ėŠĩ니다", "no_duplicates_found": "ëš„ėŠˇí•œ 항ëĒŠė´ ė—†ėŠĩ니다.", "no_exif_info_available": "EXIF ė •ëŗ´ ė—†ėŒ", "no_explore_results_message": "더 ë§Žė€ ė‚Ŧė§„ė„ ė—…ëĄœë“œí•˜ė—Ŧ íƒėƒ‰ 기ëŠĨė„ ė‚ŦėšŠí•˜ė„¸ėš”.", "no_favorites_message": "ėĻę˛¨ė°žę¸°ė—ė„œ ė‚Ŧė§„ęŗŧ ë™ė˜ėƒė„ ëš ëĨ´ę˛Œ ė°žę¸°", "no_libraries_message": "뙏ëļ€ ëŧė´ë¸ŒëŸŦëĻŦ로 다ëĨ¸ ę˛ŊëĄœė˜ ė‚Ŧė§„ęŗŧ ë™ė˜ėƒė„ í™•ė¸í•˜ė„¸ėš”.", + "no_local_assets_found": "랴íŦė„Ŧ뗐 맞는 로ėģŦ 항ëĒŠė„ ė°žė„ 눘 ė—†ėŠĩ니다", "no_locked_photos_message": "ėž ę¸ˆ í´ë”ė˜ ė‚Ŧė§„ 및 ë™ė˜ėƒė€ ėˆ¨ę˛¨ė§€ëŠ° ëŧė´ë¸ŒëŸŦëĻŦëĨŧ íƒėƒ‰í•  때 í‘œė‹œë˜ė§€ ė•ŠėŠĩ니다.", "no_name": "ė´ëĻ„ ė—†ėŒ", "no_notifications": "ė•ŒëĻŧ ė—†ėŒ", "no_people_found": "ėŧėš˜í•˜ëŠ” ė¸ëŦŧ ė—†ėŒ", "no_places": "ėžĨė†Œ ė—†ėŒ", + "no_remote_assets_found": "랴íŦė„Ŧ뗐 맞는 뙏ëļ€ í•­ëĒŠė„ ė°žė„ 눘 ė—†ėŠĩ니다", "no_results": "결ęŗŧ ė—†ėŒ", "no_results_description": "ë™ė˜ė–´ 또는 더 ėŧë°˜ė ė¸ ë‹¨ė–´ëĨŧ ė‚ŦėšŠí•´ ëŗ´ė„¸ėš”.", "no_shared_albums_message": "ė•¨ë˛”ė„ ë§Œë“¤ė–´ ėŖŧëŗ€ ė‚Ŧ람들ęŗŧ ė‚Ŧė§„ 및 ë™ė˜ėƒė„ ęŗĩėœ í•˜ė„¸ėš”.", "no_uploads_in_progress": "ė§„í–‰ ė¤‘ė¸ ė—…ëĄœë“œ ė—†ėŒ", + "not_available": "ė—†ėŒ", "not_in_any_album": "ė•¨ë˛”ė— ė—†ėŒ", "not_selected": "ė„ íƒë˜ė§€ ė•ŠėŒ", "note_apply_storage_label_to_previously_uploaded assets": "및溠: ė´ė „ė— ė—…ëĄœë“œí•œ 항ëĒŠė—ë„ ėŠ¤í† ëĻŦė§€ ë ˆė´ë¸”ė„ ė ėšŠí•˜ë ¤ëŠ´ ë‹¤ėŒė„ ė‹¤í–‰í•Šë‹ˆë‹¤,", @@ -1412,6 +1442,8 @@ "open_the_search_filters": "ę˛€ėƒ‰ 필터 뗴揰", "options": "ė˜ĩė…˜", "or": "또는", + "organize_into_albums": "ė•¨ë˛”ėœŧ로 ė •ëĻŦ하기", + "organize_into_albums_description": "현ėžŦ 동기화 ė„¤ė •ė„ ė‚ŦėšŠí•˜ė—Ŧ ę¸°ėĄ´ ė‚Ŧė§„ė„ ė•¨ë˛”ėœŧ로 ė •ëĻŦ합니다", "organize_your_library": "ëŧė´ë¸ŒëŸŦëĻŦ ė •ëĻŦ", "original": "ė›ëŗ¸", "other": "기타", @@ -1497,6 +1529,7 @@ "port": "íŦ트", "preferences_settings_subtitle": "ė•ą ę°œė¸ ė„¤ė •ė„ 관ëĻŦ합니다.", "preferences_settings_title": "ę°œė¸ 네렕", + "preparing": "ė¤€ëš„ 뤑", "preset": "프ëĻŦė…‹", "preview": "미ëĻŦ ëŗ´ę¸°", "previous": "ė´ė „", @@ -1513,6 +1546,7 @@ "profile_drawer_client_out_of_date_minor": "ëĒ¨ë°”ėŧ ė•ąė´ ėĩœė‹  ë˛„ė „ė´ ė•„ë‹™ë‹ˆë‹¤. ėĩœė‹  ë˛„ė „ėœŧ로 ė—…ë°ė´íŠ¸í•˜ė„¸ėš”.", "profile_drawer_client_server_up_to_date": "클ëŧė´ė–¸íŠ¸ė™€ ė„œë˛„ę°€ ėĩœė‹  ėƒíƒœėž…ë‹ˆë‹¤.", "profile_drawer_github": "Github", + "profile_drawer_readonly_mode": "ėŊ기 ė „ėšŠ ëĒ¨ë“œ í™œė„ąí™”. ėœ ė € ė•„ë°”íƒ€ ė•„ė´ėŊ˜ė„ 描枌 눌ëŸŦ í•´ė œí•  눘 ėžˆėŠĩ니다.", "profile_drawer_server_out_of_date_major": "ė„œë˛„ ë˛„ė „ė´ ėĩœė‹ ė´ ė•„ë‹™ë‹ˆë‹¤. ėĩœė‹  ë˛„ė „ėœŧ로 ė—…ë°ė´íŠ¸í•˜ė„¸ėš”.", "profile_drawer_server_out_of_date_minor": "ė„œë˛„ ë˛„ė „ė´ ėĩœė‹ ė´ ė•„ë‹™ë‹ˆë‹¤. ėĩœė‹  ë˛„ė „ėœŧ로 ė—…ë°ė´íŠ¸í•˜ė„¸ėš”.", "profile_image_of_user": "{user}ë‹˜ė˜ 프로필 ė´ë¯¸ė§€", @@ -1551,6 +1585,7 @@ "purchase_server_description_2": "ė„œíŦ터 ë°°ė§€", "purchase_server_title": "ė„œë˛„", "purchase_settings_server_activated": "ė„œë˛„ ė œí’ˆ 키는 관ëĻŦėžę°€ ė œė–´í•Šë‹ˆë‹¤.", + "query_asset_id": "ėŋŧëĻŦ 항ëĒŠ ID", "queue_status": "렄랴 {total}, {count} 대기 뤑", "rating": "등급", "rating_clear": "등급 ė´ˆę¸°í™”", @@ -1558,6 +1593,9 @@ "rating_description": "ėƒė„¸ ė •ëŗ´ íŒ¨ë„ė— EXIF 등급 태그 í‘œė‹œ", "reaction_options": "ë°˜ė‘ ė˜ĩė…˜", "read_changelog": "ëŗ€ę˛Ŋ ë‚´ė—­ ëŗ´ę¸°", + "readonly_mode_disabled": "ėŊ기 ė „ėšŠ ëĒ¨ë“œ ëš„í™œė„ąí™”", + "readonly_mode_enabled": "ėŊ기 ė „ėšŠ ëĒ¨ë“œ í™œė„ąí™”", + "ready_for_upload": "ė—…ëĄœë“œ ė¤€ëš„ ė™„ëŖŒ", "reassign": "ë‹¤ė‹œ 할당", "reassigned_assets_to_existing_person": "{count, plural, one {항ëĒŠ #氜} other {항ëĒŠ #氜}}ëĨŧ {name, select, null {ę¸°ėĄ´ ė¸ëŦŧ} other {ę¸°ėĄ´ ė¸ëŦŧ {name}}}ė—ę˛Œ ėžŦė§€ė •í–ˆėŠĩ니다.", "reassigned_assets_to_new_person": "{count, plural, one {항ëĒŠ #氜} other {항ëĒŠ #氜}}ëĨŧ 냈 ė¸ëŦŧė—ę˛Œ ėžŦė§€ė •í–ˆėŠĩ니다.", @@ -1582,6 +1620,7 @@ "regenerating_thumbnails": "ė„Ŧ네ėŧė„ ë‹¤ė‹œ ėƒė„ąí•˜ëŠ” 뤑...", "remote": "ė›ę˛Š", "remote_assets": "ė›ę˛Š 항ëĒŠ", + "remote_media_summary": "ė›ę˛Š ë¯¸ë””ė–´ ėš”ė•Ŋ", "remove": "ė œęą°", "remove_assets_album_confirmation": "ė•¨ë˛”ė—ė„œ 항ëĒŠ {count, plural, one {#氜} other {#氜}}ëĨŧ ė œęą°í•˜ė‹œę˛ ėŠĩ니까?", "remove_assets_shared_link_confirmation": "ęŗĩ뜠 링íŦė—ė„œ 항ëĒŠ {count, plural, one {#氜} other {#氜}}ëĨŧ ė œęą°í•˜ė‹œę˛ ėŠĩ니까?", @@ -1634,6 +1673,7 @@ "restore_user": "ė‚ŦėšŠėž ëŗĩ뛐", "restored_asset": "항ëĒŠė´ ëŗĩė›ë˜ė—ˆėŠĩ니다.", "resume": "ėžŦ氜", + "resume_paused_jobs": "ėžŦ氜 {count, plural, one {# ėŧė‹œ ė¤‘ė§€ëœ ėž‘ė—…} other {# ėŧė‹œ ė¤‘ė§€ëœ ėž‘ė—…}}", "retry_upload": "ë‹¤ė‹œ ė‹œë„", "review_duplicates": "ëš„ėŠˇí•œ 항ëĒŠ í™•ė¸", "review_large_files": "ėšŠëŸ‰ė´ 큰 파ėŧ í™•ė¸", @@ -1727,6 +1767,7 @@ "select_user_for_sharing_page_err_album": "ė•¨ë˛”ė„ ėƒė„ąí•˜ė§€ ëĒģ했ėŠĩ니다.", "selected": "ė„ íƒë¨", "selected_count": "{count, plural, other {#氜 ė„ íƒë¨}}", + "selected_gps_coordinates": "ė„ íƒí•œ GPS ėĸŒí‘œ", "send_message": "ëŠ”ė‹œė§€ ė „ė†Ą", "send_welcome_email": "í™˜ė˜ ė´ëŠ”ėŧ ė „ė†Ą", "server_endpoint": "ė„œë˛„ ė—”ë“œíŦė¸íŠ¸", @@ -1855,6 +1896,7 @@ "show_slideshow_transition": "ėŠŦëŧė´ë“œ ė „í™˜ í‘œė‹œ", "show_supporter_badge": "ė„œíŦ터 ë°°ė§€", "show_supporter_badge_description": "ė„œíŦ터 ë°°ė§€ í‘œė‹œ", + "show_text_search_menu": "í…ėŠ¤íŠ¸ ę˛€ėƒ‰ 메뉴 í‘œė‹œ", "shuffle": "ė…”í”Œ", "sidebar": "ė‚Ŧė´ë“œë°”", "sidebar_display_description": "ëŗ´ę¸° 링íŦëĨŧ ė‚Ŧė´ë“œë°”ė— í‘œė‹œ", @@ -1885,6 +1927,7 @@ "stacktrace": "ėŠ¤íƒ ėļ”렁", "start": "ė‹œėž‘", "start_date": "ė‹œėž‘ėŧ", + "start_date_before_end_date": "ė‹œėž‘ėŧė€ ėĸ…ëŖŒėŧëŗ´ë‹¤ ė´ė „ė´ė–´ė•ŧ 합니다", "state": "맀뗭", "status": "ėƒíƒœ", "stop_casting": "ėēėŠ¤íŒ… ė¤‘ë‹¨", @@ -1909,6 +1952,8 @@ "sync_albums_manual_subtitle": "ė—…ëĄœë“œí•œ ëĒ¨ë“  ë™ė˜ėƒęŗŧ ė‚Ŧė§„ė„ ė„ íƒí•œ ë°ąė—… ė•¨ë˛”ė— 동기화", "sync_local": "로ėģŦ 동기화", "sync_remote": "ė›ę˛Š 동기화", + "sync_status": "동기화 ėƒíƒœ", + "sync_status_subtitle": "동기화 ė‹œėŠ¤í…œ í™•ė¸ 및 관ëĻŦ", "sync_upload_album_setting_subtitle": "ė„ íƒí•œ ė•¨ë˛”ė„ Immich뗐 ėƒė„ąí•˜ęŗ  ė‚Ŧė§„ 및 ë™ė˜ėƒ ė—…ëĄœë“œ", "tag": "태그", "tag_assets": "항ëĒŠ 태그", @@ -1968,6 +2013,7 @@ "trash_page_select_assets_btn": "항ëĒŠ ė„ íƒ", "trash_page_title": "íœ´ė§€í†ĩ ({count})", "trashed_items_will_be_permanently_deleted_after": "íœ´ė§€í†ĩėœŧ로 ė´ë™ëœ 항ëĒŠė€ {days, plural, one {#ėŧ} other {#ėŧ}} 후 똁ęĩŦ렁ėœŧ로 ė‚­ė œëŠë‹ˆë‹¤.", + "troubleshoot": "트ëŸŦë¸”ėŠˆíŒ…", "type": "í˜•ė‹", "unable_to_change_pin_code": "PIN ėŊ”드ëĨŧ ëŗ€ę˛Ŋ할 눘 ė—†ėŒ", "unable_to_setup_pin_code": "PIN ėŊ”드ëĨŧ ė„¤ė •í•  눘 ė—†ėŒ", @@ -1998,6 +2044,7 @@ "unstacked_assets_count": "항ëĒŠ {count, plural, one {#氜} other {#氜}}ė˜ ėŠ¤íƒė„ í’€ė—ˆėŠĩ니다.", "untagged": "태그 í•´ė œë¨", "up_next": "ë‹¤ėŒ", + "update_location_action_prompt": "ė„ íƒí•œ {count}氜 항ëĒŠ ėœ„ėš˜ ė—…ë°ė´íŠ¸:", "updated_at": "ė—…ë°ė´íŠ¸ë¨", "updated_password": "비밀번호가 ëŗ€ę˛Ŋë˜ė—ˆėŠĩ니다.", "upload": "ė—…ëĄœë“œ", @@ -2064,6 +2111,7 @@ "view_next_asset": "ë‹¤ėŒ 항ëĒŠ ëŗ´ę¸°", "view_previous_asset": "ė´ė „ 항ëĒŠ ëŗ´ę¸°", "view_qr_code": "QR ėŊ”드 ëŗ´ę¸°", + "view_similar_photos": "ëš„ėŠˇí•œ ė‚Ŧė§„ ëŗ´ę¸°", "view_stack": "ėŠ¤íƒ ëŗ´ę¸°", "view_user": "ė‚ŦėšŠėž ëŗ´ę¸°", "viewer_remove_from_stack": "ėŠ¤íƒė—ė„œ ė œęą°", @@ -2082,5 +2130,6 @@ "yes": "네", "you_dont_have_any_shared_links": "ęŗĩ뜠 링íŦ가 ė—†ėŠĩ니다.", "your_wifi_name": "Wi-Fi ë„¤íŠ¸ė›ŒíŦ ė´ëĻ„", - "zoom_image": "ė´ë¯¸ė§€ 확대" + "zoom_image": "ė´ë¯¸ė§€ 확대", + "zoom_to_bounds": "í™”ëŠ´ė— 맞ėļ° í™•ëŒ€" } diff --git a/i18n/lt.json b/i18n/lt.json index a35ddfa775..b849d335a4 100644 --- a/i18n/lt.json +++ b/i18n/lt.json @@ -28,13 +28,16 @@ "add_to_album": "Pridėti į albumą", "add_to_album_bottom_sheet_added": "Pridėta į {album}", "add_to_album_bottom_sheet_already_exists": "Jau yra albume {album}", + "add_to_album_toggle": "Perjungti paÅžymėjimus albumui {album}", + "add_to_albums": "Pridėti į albumus", + "add_to_albums_count": "Pridėti į albumus ({count})", "add_to_shared_album": "Pridėti į bendrinamą albumą", "add_url": "Pridėti URL", "added_to_archive": "Pridėta į archyvą", "added_to_favorites": "Pridėta prie mėgstamiausiÅŗ", "added_to_favorites_count": "{count, plural, one {# pridėtas} few {# pridėti} other {# pridėta}} prie mėgstamiausiÅŗ", "admin": { - "add_exclusion_pattern_description": "Pridėti iÅĄimčiÅŗ taisyklęs. Plaikomi simboliai *,**, ir ?. Ignoruoti bet kokius failus bet kuriame aplanke uÅžvadintame \"Raw\", naudokite \"**/RAW/**\". Ignoravimui failÅŗ su plėtiniu \".tif\", naudokite \"**/*.tiff\". Aplanko kelio nustatymams, naudokite \"/aplanko/kelias/ignoruoti/**\"", + "add_exclusion_pattern_description": "Pridėti iÅĄimčiÅŗ taisykles. Palaikomi simboliai *,**, ir ?. Ignoruoti bet kokius failus bet kuriame aplanke pavadintame \"Raw\", naudokite \"**/RAW/**\". Ignoravimui failÅŗ su plėtiniu \".tif\", naudokite \"**/*.tiff\". Aplanko kelio nustatymams, naudokite \"/aplanko/kelias/ignoruoti/**\".", "admin_user": "Administratorius", "asset_offline_description": "Å is iÅĄorinės bibliotekos elementas nebepasiekiamas diske ir buvo perkeltas į ÅĄiukÅĄliadėŞę. Jei failas buvo perkeltas toje pačioje bibliotekoje, laiko skalėje rasite naują atitinkamą elementą. Jei norite ÅĄÄ¯ elementą atkurti, įsitikinkite, kad Immich gali pasiekti failą Åžemiau nurodytu adresu, ir suvykdykite bibliotekos skenavimą.", "authentication_settings": "Autentifikavimo nustatymai", @@ -45,6 +48,10 @@ "backup_database": "Sukurti duomenÅŗ bazės iÅĄklotinę", "backup_database_enable_description": "ÄŽgalinti duomenÅŗ bazės iÅĄklotinės", "backup_keep_last_amount": "IÅĄsaugomÅŗ ankstesniÅŗ duomenÅŗ bazės iÅĄklotiniÅŗ skaičius", + "backup_onboarding_1_description": "iÅĄorinė kopija debesyje arba kitoje fizinėje lokacijoje.", + "backup_onboarding_2_description": "vietinės kopijos kituose prietaisuose. Tai apima pagrindinius failus ir jÅŗ vietines kopijas.", + "backup_onboarding_3_description": "viso jÅĢsÅŗ duomenÅŗ kopijÅŗ, įskaitant originalius failus. Tai apima 1 iÅĄorinę ir 2 vietines kopijas.", + "backup_onboarding_description": "JÅĢsÅŗ duomenÅŗ apsaugojimui rekomenduojama 3-2-1 atsarginės kopijos strategija . JÅĢs turėtumėte saugoti įkeltÅŗ nuotraukÅŗ/video bei Immich duomenÅŗ bazės kopijas iÅĄsamiam atsarginiÅŗ kopijÅŗ sprendimui.", "backup_onboarding_footer": "Daugiau informacijos apie „Immich“ atsarginiÅŗ kopijÅŗ kÅĢrimą rasite dokumentacijoje.", "backup_onboarding_parts_title": "3-2-1 atsarginė kopija apima:", "backup_onboarding_title": "Atsarginės kopijos", @@ -75,7 +82,7 @@ "image_format_description": "WebP sukuria maÅžesnius failus nei JPEG, tačiau lėčiau juos apdoroja.", "image_fullsize_description": "Pilno dydÅžio nuotrauka be meta duomenÅŗ naudojama priartinus", "image_fullsize_enabled": "ÄŽgalinti pilno dydÅžio nuotraukÅŗ generavimą", - "image_fullsize_enabled_description": "Generuoti viso dydÅžio vaizdą neinternetui pritaikytiems formatams. Kai įjungta parinktis „Pirmenybė įterptai perÅžiÅĢrai“, įterptosios perÅžiÅĢros naudojamos tiesiogiai be konvertavimo. Tai neturi įtakos internetui pritaikytiems formatams, pvz., JPEG", + "image_fullsize_enabled_description": "Generuoti viso dydÅžio vaizdą narÅĄyklėms nepritaikytiems formatams. Kai įjungta parinktis „Pirmenybė įterptai perÅžiÅĢrai“, įterptosios perÅžiÅĢros naudojamos tiesiogiai be konvertavimo. Tai neturi įtakos internetui pritaikytiems formatams, pvz., JPEG.", "image_fullsize_quality_description": "Pilno dydÅžio nuotraukÅŗ kokybė 1-100. Didesnė yra geresnė, tačiau sukuria didesniu failus.", "image_fullsize_title": "Pilno dydÅžio nuotraukÅŗ Nustatymai", "image_prefer_embedded_preview": "Pageidautinai rodyti įterptą perÅžiÅĢrą", @@ -99,8 +106,8 @@ "job_settings": "UÅžduočiÅŗ nustatymai", "job_settings_description": "Keisti uÅžduočiÅŗ lygiagretumą", "job_status": "UÅžduočiÅŗ bÅĢsenos", - "jobs_delayed": "{jobCount, plural, other {# delayed}}", - "jobs_failed": "{jobCount, plural, other {# failed}}", + "jobs_delayed": "{jobCount, plural, one {# atidėtas} few {# atidėti} other {# atidėtÅŗ}}", + "jobs_failed": "{jobCount, plural, other {# nepavyko}}", "library_created": "Sukurta biblioteka: {library}", "library_deleted": "Biblioteka iÅĄtrinta", "library_import_path_description": "Nurodykite aplanką, kurį norite importuoti. Å iame aplanke, įskaitant poaplankius, bus nuskaityti vaizdai ir vaizdo įraÅĄai.", @@ -116,6 +123,13 @@ "logging_enable_description": "ÄŽjungti Åžurnalo vedimą", "logging_level_description": "ÄŽjungus, kokį Åžurnalo vedimo lygį naudot.", "logging_settings": "ÅŊurnalo vedimas", + "machine_learning_availability_checks": "Prieinamumo patikrinimai", + "machine_learning_availability_checks_description": "AutomatiÅĄkai aptikti ir teikti pirmenybę prieinamiems maÅĄininio mokymosi serveriams", + "machine_learning_availability_checks_enabled": "ÄŽjungti prieinamumo patikrinimus", + "machine_learning_availability_checks_interval": "Patikros intervalas", + "machine_learning_availability_checks_interval_description": "Intervalas milisekundėmis tarp prieinamumo patikrinimÅŗ", + "machine_learning_availability_checks_timeout": "UÅžklausos laiko limitas", + "machine_learning_availability_checks_timeout_description": "Laiko limitas milisekundėmis prieinamumo patikrinimams", "machine_learning_clip_model": "CLIP modelis", "machine_learning_clip_model_description": "Pavadinimas CLIP modelio įvardintio here. Dėmesio, keičiant modelį jÅĢs privalote iÅĄ naujo paleisti 'IÅĄmaniosios PaieÅĄkos' uÅžduotį visiems vaizdams.", "machine_learning_duplicate_detection": "DublikatÅŗ aptikimas", @@ -165,7 +179,7 @@ "metadata_extraction_job": "MetaduomenÅŗ nuskaitymas", "metadata_extraction_job_description": "Kiekvieno bibliotekos elemento metaduomenÅŗ nuskaitymas, tokiÅŗ kaip GPS koordinatės, veidai ar rezoliucija", "metadata_faces_import_setting": "ÄŽjungti veidÅŗ importą", - "metadata_faces_import_setting_description": "Importuoti veidus iÅĄ vaizdo EXIF duomenÅŗ ir papildomÅŗ failÅŗ", + "metadata_faces_import_setting_description": "Importuoti veidus iÅĄ vaizdo EXIF duomenÅŗ ir susietÅŗ failÅŗ", "metadata_settings": "MetaduomenÅŗ nustatymai", "metadata_settings_description": "Tvarkyti metaduomenÅŗ nustatymus", "migration_job": "Tvarkymas", @@ -182,6 +196,8 @@ "nightly_tasks_settings_description": "Valdyti naktines uÅžduotis", "nightly_tasks_start_time_setting": "PradÅžios laikas", "nightly_tasks_start_time_setting_description": "Laikas kada serveris pradės vykdyti naktines uÅžduotis", + "nightly_tasks_sync_quota_usage_setting": "Sinchronizuoti kvotos naudojimą", + "nightly_tasks_sync_quota_usage_setting_description": "Atnaujinti vartotojo vietos kvotą remiantis dabartiniu vartojimu", "no_paths_added": "Keliai nepridėti", "no_pattern_added": "Å ablonas nepridėtas", "note_apply_storage_label_previous_assets": "Pastaba: norėdami pritaikyti Saugyklos ÅŊymą seniau įkeltiems iÅĄtekliams, paleiskite", @@ -255,8 +271,8 @@ "storage_template_date_time_description": "Elemento sukÅĢrimo laiko Åžymė yra naudojama laiko informacijai", "storage_template_date_time_sample": "Pavyzdinis laikas {date}", "storage_template_enable_description": "Aktyvuoti saugyklos ÅĄabloną", - "storage_template_hash_verification_enabled": "Aktyvuoti Hash tikrinimą", - "storage_template_hash_verification_enabled_description": "Aktyvuojamas Hash tikrinimas, neiÅĄjungti nebent gerai suprantate galimas pasekmes", + "storage_template_hash_verification_enabled": "Aktyvuoti failo paraÅĄo tikrinimą", + "storage_template_hash_verification_enabled_description": "Aktyvuojamas failo paraÅĄo tikrinimas, neiÅĄjungti nebent gerai suprantate galimas pasekmes", "storage_template_migration": "Saugyklos tvarkymas pagal ÅĄabloną", "storage_template_migration_description": "Taikyti dabartinį {template} anksčiau įkeltiems duomenims", "storage_template_migration_info": "Saugyklos tvarkyklė konvertuos visus plėtinius maÅžosiomis raidėmis. Å ablonas bus taikomas tik naujiems duomenims. Taikyti ÅĄabloną retroaktyviai anksčiau įkeltiems duomenims, paleiskite ÅĄią {job}.", @@ -303,29 +319,72 @@ "transcoding_codecs_learn_more": "SuÅžinoti daugiau apie naudojamą terminologiją, naudokite FFmpeg dokumentaciją H.264 codec, HEVC codec and VP9 codec.", "transcoding_constant_quality_mode": "Pastovios kokybės reÅžimas", "transcoding_constant_quality_mode_description": "ICQ yra geriau nei CPQ, tačiau ne visi įrenginiai palaiko ÅĄÄ¯ spartinimo bÅĢdą. Å is pasirinkimas bÅĢtÅŗ naudojamas kai nustatytas Kodavimas Pagal Kokybę. NVENC nepalaiko ÅĄio pasirinkimo todėl bus ignoruojamas.", + "transcoding_constant_rate_factor": "Pastovaus greičio faktorius (-crf)", "transcoding_constant_rate_factor_description": "Video kokybės lygis. Tipinės reikÅĄmės yra 23 jei H.264, 28 jei HVEC, 31 jei VP9, ir 35 jei AV1. Kuo maÅžesnis tuo kokybiÅĄkesnis tačiau didesni failai.", "transcoding_disabled_description": "Nedaryti perkodavimo, įraÅĄÅŗ perÅžiÅĢra gali neveikti ant kai kÅĢriÅŗ sąsajÅŗ", + "transcoding_encoding_options": "UÅžkodavimo parinktys", + "transcoding_encoding_options_description": "Nustatyti kodekus, rezoliuciją, kokybę ir kitas parinktis uÅžkoduojamiems vaizdo įraÅĄams", "transcoding_hardware_acceleration": "Techninės įrangos spartinimas", + "transcoding_hardware_acceleration_description": "Eksperimentinis: greitesnis perkodavimas, bet galimai prastesne kokybe prie tos pačios bitÅŗ spartos", "transcoding_hardware_decoding": "Aparatinis dekodavimas", + "transcoding_hardware_decoding_setting_description": "ÄŽgalina visapusiÅĄką paspartinimą vietoje tik uÅžkodavimo paspartinimo. Gali neveikti su kai kuriais vaizdo įraÅĄais.", + "transcoding_max_b_frames": "Maksimaliai B-kadrÅŗ", + "transcoding_max_b_frames_description": "Didesnės reikÅĄmės pagerina suspaudimo efektyvumą, bet sulėtina uÅžkodavimą. Senesniuose prietaisuose gali bÅĢti nepalaikomas aparatinis spartinimas. 0 iÅĄjungia B-kadrus, o -1 nustato reikÅĄmę automatiÅĄkai.", "transcoding_max_bitrate": "Maksimalus bitÅŗ srautas", "transcoding_max_bitrate_description": "Pasirenkant max bitrate galima pasiekti labiau nuspėjamą failÅŗ dydį su minimaliais kokybės praradimais. Prie 720p, tipinės reikÅĄmės yra 2600 kbits/s jei BP9 ar HVEC, arba 4500 kbits/s jei H.264. Neveiksnus jei pasirenkamas 0.", + "transcoding_max_keyframe_interval": "Maksimalus raktinio kadro intervalas", + "transcoding_max_keyframe_interval_description": "Nustato maksimalÅŗ kadro atstumą tarp raktiniÅŗ kadrÅŗ. ÅŊemesnės reikÅĄmės pablogina suspaudimo efektyvumą, bet pagerina prasukimo laiką ir gali pagerinti greito veiksmo scenÅŗ kokybę. 0 - nustato ÅĄią reikÅĄmę automatiÅĄkai.", + "transcoding_optimal_description": "Vaizdo įraÅĄai aukÅĄtesne nei tikslinė rezoliucija arba nepalaikomu formatu", "transcoding_policy": "Transkodavimo politika", + "transcoding_policy_description": "Nustatyti kada vaizdo įraÅĄas bus perkoduotas", + "transcoding_preferred_hardware_device": "Pageidaujamas aparatinės įrangos įrenginys", + "transcoding_preferred_hardware_device_description": "Galioja tik VAAPI ir QSV. Nustato dri mazgą aparatiniam perkodavimui.", + "transcoding_preset_preset": "IÅĄ anksto nustatytas (-preset)", "transcoding_preset_preset_description": "Kompresijos greitis. Siekiant tam tikro bitrate lėtesnis apdorojimas lems maÅžesnius failÅŗ dydÅžius ir padidins kokybę. VP9 ignoruos greičius virÅĄ \"gretesnis\" lygio.", + "transcoding_reference_frames": "Nuorodiniai kadrai", + "transcoding_reference_frames_description": "KadrÅŗ, į kuriuos reikia remtis suspaudÅžiant duotą kadrą, skaičius. AukÅĄtesnė reikÅĄmė pagerina suspaudimo efektyvumą, bet sulėtina uÅžkodavimą. 0 - nustato reikÅĄmę automatiÅĄkai.", + "transcoding_required_description": "Tik nepalaikomo formato vaizdo įraÅĄai", + "transcoding_settings": "Vaizdo įraÅĄÅŗ perkodavimo nustatymai", + "transcoding_settings_description": "Valdyti kuriuos vaizdo įraÅĄus perkoduoti ir kaip juos apdoroti", + "transcoding_target_resolution": "Skiriamoji geba", "transcoding_target_resolution_description": "Didesnės skiriamosios gebos gali iÅĄsaugoti daugiau detaliÅŗ, tačiau jas koduoti uÅžtrunka ilgiau, failÅŗ dydÅžiai yra didesni ir gali sumaŞėti programos jautrumas.", + "transcoding_temporal_aq": "Laikinas adaptyvus kvantavimas", + "transcoding_temporal_aq_description": "Galioja tik NVENC. Pagerina detaliÅŗ, maÅžo judesio scenÅŗ kokybę. Gali bÅĢti nepalaikoma senesniÅŗ įrenginiÅŗ.", + "transcoding_threads": "Gijos", + "transcoding_threads_description": "Didesnės reikÅĄmės pagreitina kodavimą, bet kol aktyvus palieka maÅžiau serverio resursÅŗ kitoms uÅžduotims. Å i reikÅĄmė negali bÅĢti didesnė uÅž procesoriaus branduoliÅŗ kiekį. Jei reikÅĄmė 0, tai iÅĄnaudoja maksimaliai.", + "transcoding_tone_mapping": "TonÅŗ atvaizdavimas", + "transcoding_tone_mapping_description": "Bandoma iÅĄsaugoti HDR vaizdo įraÅĄÅŗ iÅĄvaizdą konvertuojant į SDR. Kiekvienas algoritmas taiko skirtingus kompromisus dėl spalvÅŗ, detaliÅŗ ir ÅĄviesumo. Hable iÅĄsaugo detales, Mobius iÅĄsaugo spalvas, o Reinhard iÅĄsaugo ÅĄviesumą.", + "transcoding_transcode_policy": "Perkodavimo strategija", + "transcoding_transcode_policy_description": "Strategija, kada vaizdo įraÅĄas turi bÅĢti perkoduotas. HDR vaizdo įraÅĄai visada bus perkoduoti (iÅĄskyrus jei perkodavimas iÅĄjungtas).", + "transcoding_two_pass_encoding": "DviejÅŗ perėjimÅŗ uÅžkodavimas", + "transcoding_two_pass_encoding_setting_description": "Perkoduoti su dviem perėjimais, kad gauti geriau uÅžkoduotą vaizdo įraÅĄÄ…. Kai maksimalus bitÅŗ srautas įjungtas (veikimui reikalaujamas H.264 ir HVEC), tada naudojamas bitÅŗ intervalas remiantis maksimaliu bitÅŗ srautu ir ignoruojamas CRF. Su VP9 gali bÅĢti naudojamas CRF, jei maksimalus bitÅŗ srautas yra iÅĄjungtas.", "transcoding_video_codec": "Video kodekas", + "transcoding_video_codec_description": "VP9 turi didelį efektyvumą ir tinklo suderinamumą, bet uÅžtrunka ilgiau perkoduojant. HVEC veikia panaÅĄiai, bet turi maÅžesnį tinklo suderinamumą. H.264 yra plačiai palaikomas ir greitai perkoduojamas, bet kuria didelius failus. AV1 yra efektyviausias kodekas, bet nepalaikomas senesniÅŗ prietaisÅŗ.", "trash_enabled_description": "ÄŽgalinti ÅĄiukÅĄliadėŞės funkcijas", "trash_number_of_days": "DienÅŗ skaičius", + "trash_number_of_days_description": "Kiek dienÅŗ bus laikomi elementai ÅĄiukÅĄliadėŞėje prieÅĄ galutinai juos iÅĄtrinant", "trash_settings": "Å iukÅĄliadėŞės nustatymai", "trash_settings_description": "Tvarkyti ÅĄiukÅĄliadėŞės nustatymus", + "unlink_all_oauth_accounts": "Atsieti visas OAuth paskyras", + "unlink_all_oauth_accounts_description": "NepamirÅĄkite atsieti visas OAuth paskyras prieÅĄ migruojant pas naują tiekėją.", + "unlink_all_oauth_accounts_prompt": "Ar tikrai norite atsieti visas OAuth paskyras? Tai negrįŞtama operacija kuri atstatys OAuth ID kiekvienam vartotojui.", "user_cleanup_job": "VartotojÅŗ iÅĄvalymas", + "user_delete_delay": "{user} paskyra ir elementai bus nustatyti galutiniam iÅĄtrynimui uÅž {delay, plural, one {# dienos} other {# dienÅŗ}}.", "user_delete_delay_settings": "IÅĄtrynimo delsa", - "user_delete_delay_settings_description": "Skaičius dienÅŗ po iÅĄtrynimo kuomet vartotojo paskyrą ir susiję duomenys bus negraÅžinamai iÅĄtrinti. Vartotojo Trynimo uÅžduotis paleidÅžiama vidurnaktį ir tikrina kurie vartotojai gali bÅĢti trinami. Å io nustatymo pakeitimai bus naudojami sekančio uÅžduoties paleidimo metu.", + "user_delete_delay_settings_description": "Skaičius dienÅŗ po iÅĄtrynimo kuomet naudotojo paskyra ir susiję duomenys bus negraÅžinamai iÅĄtrinti. Naudotojo trynimo uÅžduotis paleidÅžiama vidurnaktį ir tikrina kurie naudotojai gali bÅĢti trinami. Å io nustatymo pakeitimai bus naudojami sekančio uÅžduoties paleidimo metu.", + "user_delete_immediately": "{user} paskyra ir elementai bus nedelsiant įtraukti galutiniam paÅĄalinimui.", + "user_delete_immediately_checkbox": "IÅĄtrinti naudotoją ir elementus nedelsiant", + "user_details": "Naudotojo duomenys", "user_management": "NaudotojÅŗ valdymas", "user_password_has_been_reset": "Naudotojo slaptaÅžodis buvo iÅĄ naujo nustatytas:", + "user_password_reset_description": "Perduokite laikiną slaptaÅžodį naudotojui ir informuokite, kad pasikeistÅŗ slaptaÅžodį pirmo prisijungimo metu.", "user_restore_description": "Naudotojo {user} paskyra bus atkurta.", + "user_restore_scheduled_removal": "Atkurti naudotoją - suplanuotas paÅĄalinimas {date, date, long}", "user_settings": "Naudotojo nustatymai", "user_settings_description": "Valdyti naudotojo nustatymus", "user_successfully_removed": "Naudotojas {email} sėkmingai paÅĄalintas.", + "version_check_enabled_description": "ÄŽgalinti versijÅŗ tikrinimą", + "version_check_implications": "VersijÅŗ tikrinimas reikalauja periodiÅĄkos komunikacijos su github.com", "version_check_settings": "Versijos tikrinimas", "version_check_settings_description": "ÄŽjungti/iÅĄjungti naujos versijos praneÅĄimus", "video_conversion_job": "Vaizdo įraÅĄÅŗ konvertavimas", @@ -334,10 +393,34 @@ "admin_email": "Administratoriaus el. paÅĄtas", "admin_password": "Administratoriaus slaptaÅžodis", "administration": "Administravimas", + "advanced": "Sudėtingesnis", + "advanced_settings_enable_alternate_media_filter_subtitle": "Naudokite ÅĄÄ¯ nustatymą medijos filtravimui sinchronizuojant remiantis alternatyviais kriterijais. Naudokite tik jei programa turi problemÅŗ su visÅŗ albumÅŗ aptikimu.", + "advanced_settings_enable_alternate_media_filter_title": "[EKSPERIMENTINIS] Naudokite alternatyvÅŗ įrenginio albumÅŗ sinchronizavimo filtrą", + "advanced_settings_log_level_title": "ÅŊurnalo įraÅĄÅŗ lygis: {level}", + "advanced_settings_prefer_remote_subtitle": "Kai kurie įrenginiai labai lėtai įkelia miniatiÅĢras iÅĄ vietiniÅŗ elementÅŗ. Aktyvuokite ÅĄÄ¯ nustatymą, kad vietoje to uÅžkrautumėte nuotolines nuotraukas.", + "advanced_settings_prefer_remote_title": "Teikti pirmenybę nuotolinėms nuotraukoms", + "advanced_settings_proxy_headers_subtitle": "Nustatykite tarpinio serverio antraÅĄtes kurias Immich siÅŗs su kiekvienu uÅžklausimu", + "advanced_settings_proxy_headers_title": "Tarpinio serverio antraÅĄtės", + "advanced_settings_readonly_mode_subtitle": "ÄŽgalina tik skaitymo reÅžimą kai nuotraukas galima tik ÅžiÅĢrėti, draudÅžiama paÅžymėti kelias, dalintis, transliuoti ar iÅĄtrinti. ÄŽgalinkit/uÅždrauskit tik skaitymą per naudotojo avatar'ą iÅĄ pagrindinio lango", + "advanced_settings_readonly_mode_title": "Tik skaitymo reÅžimas", + "advanced_settings_self_signed_ssl_subtitle": "PraleidÅžia SSL sertifikato tikrinimą serverio galutiniam taÅĄkui. Privaloma pačiÅŗ pasiraÅĄytiems sertifikatams.", + "advanced_settings_self_signed_ssl_title": "Leisti pačiÅŗ pasiraÅĄytus SSL sertifikatus", + "advanced_settings_sync_remote_deletions_subtitle": "AutomatiÅĄkai iÅĄtrinti ar atkurti elementus įrenginyje, kai tie veiksmai atliekami narÅĄyklėje", + "advanced_settings_sync_remote_deletions_title": "Sinchronizuoti nuotolinius iÅĄtrynimus [EKSPERIMENTINIS]", + "advanced_settings_tile_subtitle": "PaÅžangesni naudotojÅŗ nustatymai", + "advanced_settings_troubleshooting_subtitle": "ÄŽgalinti papildomas galimybes trikčiÅŗ ÅĄalinimui", + "advanced_settings_troubleshooting_title": "TrikčiÅŗ ÅĄalinimas", + "age_months": "AmÅžius {months, plural, one {# mėnesis} few {# mėnesiai} other {# mėnesiÅŗ}}", + "age_year_months": "AmÅžius 1 metai, {months, plural, one {# mėnesis} few {# mėnesiai} other {# mėnesiÅŗ}}", + "age_years": "{years, plural, other {AmÅžius #}}", "album_added": "Albumas pridėtas", "album_added_notification_setting_description": "Gauti el. paÅĄto praneÅĄimą, kai bÅĢsite pridėtas prie bendrinamo albumo", "album_cover_updated": "Albumo virÅĄelis atnaujintas", "album_delete_confirmation": "Ar tikrai norite iÅĄtrinti albumą {album}?", + "album_delete_confirmation_description": "Jei ÅĄiuo albumu dalijamasi, tai kiti naudotojai jo nebegalės pasiekti.", + "album_deleted": "Albumas iÅĄtrintas", + "album_info_card_backup_album_excluded": "neįtrauktas", + "album_info_card_backup_album_included": "įtrauktas", "album_info_updated": "Albumo informacija atnaujinta", "album_leave": "Palikti albumą?", "album_leave_confirmation": "Ar tikrai norite palikti albumą {album}?", @@ -345,16 +428,28 @@ "album_options": "Albumo parinktys", "album_remove_user": "PaÅĄalinti naudotoją?", "album_remove_user_confirmation": "Ar tikrai norite paÅĄalinti naudotoją {user}?", + "album_search_not_found": "Pagal jÅĢsÅŗ paieÅĄką albumÅŗ nerasta", "album_share_no_users": "Atrodo, kad bendrinate ÅĄÄ¯ albumą su visais naudotojais, arba neturite naudotojÅŗ, su kuriais galėtumėte bendrinti.", + "album_summary": "Albumo santrauka", "album_updated": "Albumas atnaujintas", "album_updated_setting_description": "Gauti praneÅĄimą el. paÅĄtu, kai bendrinamas albumas turi naujÅŗ elementÅŗ", + "album_user_left": "Paliko {album}", "album_user_removed": "PaÅĄalintas {user}", + "album_viewer_appbar_delete_confirm": "Ar tikrai norite iÅĄtrinti ÅĄÄ¯ albumą iÅĄ savo paskyros?", "album_viewer_appbar_share_err_delete": "Nepavyko iÅĄtrinti albumo", "album_viewer_appbar_share_err_leave": "Nepavyko iÅĄeiti iÅĄ albumo", + "album_viewer_appbar_share_err_remove": "Kilo problemÅŗ paÅĄalinant elementus iÅĄ albumo", "album_viewer_appbar_share_err_title": "Nepavyko pakeisti albumo pavadinimą", + "album_viewer_appbar_share_leave": "Palikti albumą", + "album_viewer_appbar_share_to": "Dalintis su", + "album_viewer_page_share_add_users": "Pridėti naudotojÅŗ", "album_with_link_access": "Tegul visi, turintys nuorodą, mato ÅĄio albumo nuotraukas ir Åžmones.", "albums": "Albumai", "albums_count": "{count, plural, one {# albumas} few {# albumai} other {# albumÅŗ}}", + "albums_default_sort_order": "Pradinė albumo rÅĢÅĄiavimo tvarka", + "albums_default_sort_order_description": "Pradinė elementÅŗ rÅĢÅĄiavimo tvarka kai kuriamas naujas albumas.", + "albums_feature_description": "ElementÅŗ rinkinys kuriuo galima dalintis su kitais naudotojais.", + "albums_on_device_count": "AlbumÅŗ įrenginyje ({count})", "all": "Visi", "all_albums": "Visi albumai", "all_people": "Visi Åžmonės", @@ -363,51 +458,159 @@ "allow_edits": "Leisti redagavimus", "allow_public_user_to_download": "Leisti vieÅĄam naudotojui atsisiÅŗsti", "allow_public_user_to_upload": "Leisti vieÅĄam naudotojui įkelti", + "alt_text_qr_code": "QR kodo paveiksliukas", + "anti_clockwise": "PrieÅĄ laikrodÅžio rodykles", "api_key": "API raktas", + "api_key_description": "Å i reikÅĄmė bus parodyta tik vieną kartą. PraÅĄome nusikopijuoti prieÅĄ uÅždarant ÅĄÄ¯ langą.", "api_key_empty": "JÅĢsÅŗ API rakto pavadinimas netÅĢrėtÅŗ bÅĢti tuÅĄÄias", "api_keys": "API raktai", + "app_bar_signout_dialog_content": "Ar tikrai norite atsijungti?", + "app_bar_signout_dialog_ok": "Taip", + "app_bar_signout_dialog_title": "Atsijungti", "app_settings": "Programos nustatymai", + "appears_in": "Susiję", + "apply_count": "Taikyti ({count, number})", "archive": "Archyvas", + "archive_action_prompt": "{count} pridėta į archyvą", "archive_or_unarchive_photo": "Archyvuoti arba iÅĄarchyvuoti nuotrauką", "archive_page_no_archived_assets": "Nerasta jokiÅŗ archyvuotÅŗ elementÅŗ", + "archive_page_title": "Archyve ({count})", "archive_size": "Archyvo dydis", "archive_size_description": "KonfigÅĢruoti archyvo dydį atsisiuntimams (GiB)", "archived": "Archyvuota", "archived_count": "{count, plural, other {# suarchyvuota}}", "are_these_the_same_person": "Ar tai tas pats asmuo?", "are_you_sure_to_do_this": "Ar tikrai norite tai daryti?", + "asset_action_delete_err_read_only": "Negalima iÅĄtrinti tik skaitom(o, Åŗ) element(o, Åŗ), praleidÅžiama", + "asset_action_share_err_offline": "Negalima uÅžkrauti neprisijungusiÅŗ elementÅŗ, praleidÅžiama", "asset_added_to_album": "Pridėta į albumą", - "asset_adding_to_album": "Pridedama į albumą...", + "asset_adding_to_album": "Pridedama į albumąâ€Ļ", "asset_description_updated": "Elemento apraÅĄymas buvo atnaujintas", "asset_filename_is_offline": "Elementas {filename} nepasiekiamas", + "asset_has_unassigned_faces": "Elementas turi nepriskirtÅŗ veidÅŗ", + "asset_hashing": "Kuriami bylÅŗ paraÅĄaiâ€Ļ", + "asset_list_group_by_sub_title": "Grupuoti pagal", + "asset_list_layout_settings_dynamic_layout_title": "Dinaminis iÅĄdėstymas", + "asset_list_layout_settings_group_automatically": "AutomatiÅĄkai", + "asset_list_layout_settings_group_by": "Grupuoti elementus pagal", + "asset_list_layout_settings_group_by_month_day": "Mėnesis + diena", + "asset_list_layout_sub_title": "IÅĄdėstymas", + "asset_list_settings_subtitle": "NuotraukÅŗ tinklelio iÅĄdėstymo nustatymai", + "asset_list_settings_title": "NuotraukÅŗ tinklelis", "asset_offline": "Elementas nepasiekiamas", "asset_offline_description": "Å is iÅĄorinis elementas neberandamas diske. Dėl pagalbos susisiekite su savo Immich administratoriumi.", + "asset_restored_successfully": "Elementas atkurtas sėkmingai", + "asset_skipped": "Praleista", + "asset_skipped_in_trash": "Å iukÅĄliadėŞėje", + "asset_trashed": "Elementai iÅĄtrinti", + "asset_troubleshoot": "ElementÅŗ trikčiÅŗ ÅĄalinimas", "asset_uploaded": "ÄŽkelta", - "asset_uploading": "ÄŽkeliama...", + "asset_uploading": "ÄŽkeliamaâ€Ļ", + "asset_viewer_settings_subtitle": "Tvarkykite savo galerijos perÅžiÅĢros nustatymus", + "asset_viewer_settings_title": "ElementÅŗ perÅžiÅĢra", "assets": "Elementai", "assets_added_count": "{count, plural, one {Pridėtas # elementas} few {Pridėti # elementai} other {Pridėta # elementÅŗ}}", "assets_added_to_album_count": "ÄŽ albumą {count, plural, one {įtrauktas # elementas} few {įtraukti # elementai} other {įtraukta # elementÅŗ}}", + "assets_added_to_albums_count": "Pridėta {assetTotal, plural, one {# elementas} few {# elementai} other {# elementÅŗ}} į {albumTotal, plural, one {# albumą} few {# albumus} other {# albumÅŗ}}", + "assets_cannot_be_added_to_album_count": "{count, plural, one {Elementas negali bÅĢti pridėtas} few {Elementai negali bÅĢti pridėti} other {ElementÅŗ negali bÅĢti pridėta}} į albumą", + "assets_cannot_be_added_to_albums": "{count, plural, one {Elementas negali bÅĢti pridėtas} few {Elementai negali bÅĢti pridėti} other {ElementÅŗ negali bÅĢti pridėta}} į nei vieną albumą", "assets_count": "{count, plural, one {# elementas} few {# elementai} other {# elementÅŗ}}", + "assets_deleted_permanently": "{count} elementÅŗ iÅĄtrinta galutinai", + "assets_deleted_permanently_from_server": "{count} elementÅŗ iÅĄtrinta galutinai iÅĄ Immich serverio", + "assets_downloaded_failed": "{count, plural, one {AtsisiÅŗstas # failas - {error} failas nepavyko} few {AtsisiÅŗsti # failai - {error} failai nepavyko} other {AtsisiÅŗsta # failÅŗ - {error} failÅŗ nepavyko}}", + "assets_downloaded_successfully": "{count, plural, one {AtsisiÅŗstas # failas sėkmingai} few {AtsisiÅŗsti # failai sėkmingai} other {AtsisiÅŗsta # failÅŗ sėkmingai}}", "assets_moved_to_trash_count": "{count, plural, one {# elementas perkeltas} few {# elementai perkelti} other {# elementÅŗ perkelta}} į ÅĄiukÅĄliadėŞę", "assets_permanently_deleted_count": "{count, plural, one {# elementas iÅĄtrintas} few {# elementai iÅĄtrinti} other {# elementÅŗ iÅĄtrinta}} visam laikui", "assets_removed_count": "{count, plural, one {PaÅĄalintas # elementas} few {PaÅĄalinti # elementai} other {PaÅĄalinta # elementÅŗ}}", + "assets_removed_permanently_from_device": "{count} elementÅŗ paÅĄalinta galutinai iÅĄ jÅĢsÅŗ įrenginio", "assets_restore_confirmation": "Ar tikrai norite atkurti visus ÅĄiukÅĄliadėŞėje esančius perkeltus elementus? Å io veiksmo atÅĄaukti negalėsite! Pastaba: nepasiekiami elementai tokiu bÅĢdu atkurti nebus.", "assets_restored_count": "{count, plural, one {Atkurtas # elementas} few {Atkurti # elementai} other {Atkurta # elementÅŗ}}", + "assets_restored_successfully": "{count} element(as, ai, Åŗ) atkurta sėkmingai", + "assets_trashed": "{count} element(ai,Åŗ,as) perkelta į ÅĄiukÅĄliadėŞę", + "assets_trashed_count": "Perkelta į ÅĄiukÅĄliadėŞę {count, plural, one {# elementas} few {# elementai} other {# elementÅŗ}}", + "assets_trashed_from_server": "{count} element(as, ai, Åŗ) perkelta į ÅĄiukÅĄliadėŞę iÅĄ Immich serverio", "assets_were_part_of_album_count": "{count, plural, one {# elementas} few {# elementai} other {# elementÅŗ}} jau prieÅĄ tai buvo albume", + "assets_were_part_of_albums_count": "{count, plural, one {Elementas } few {Elementai} other {ElementÅŗ}} jau buvo albumuose", "authorized_devices": "Autorizuoti įrenginiai", + "automatic_endpoint_switching_subtitle": "Prisijungti vietoje per priskirtą Wi-Fi kai įmanoma ir naudoti alternatyvÅŗ prisijungimą visur kitur", + "automatic_endpoint_switching_title": "Automatinis URL perjungimas", + "autoplay_slideshow": "AutomatiÅĄkai rodyti skaidriÅŗ demonstraciją", "back": "Atgal", "back_close_deselect": "Atgal, uÅždaryti arba atÅžymėti", + "background_backup_running_error": "Vyksta foninis atsarginis kopijavimas, negalima pradėti rankinio kopijavimo", + "background_location_permission": "Foninis vietovės leidimas", + "background_location_permission_content": "Veikiant fone tinklo perjungimui Immich privalo *visada* turėti prieigą prie tikslios vietovės, kad programa galėtÅŗ perskaityti Wi-Fi tinklo pavadinimą", + "background_options": "Fono nuostatos", + "backup": "Atsarginė kopija", + "backup_album_selection_page_albums_device": "AlbumÅŗ įrenginyje ({count})", + "backup_album_selection_page_albums_tap": "Palieskite įtraukti, du kart palieskite neįtraukti", + "backup_album_selection_page_assets_scatter": "Elementai gali iÅĄsibarstyti per kelis albumus. Todėl albumai gali bÅĢti įtraukti arba neįtraukti per atsarginio kopijavimo procesą.", + "backup_album_selection_page_select_albums": "PaÅžymėti albumai", + "backup_album_selection_page_selection_info": "PaÅžymėjimo informacija", + "backup_album_selection_page_total_assets": "Viso unikaliÅŗ elementÅŗ", + "backup_albums_sync": "Atsarginio kopijavimo albumÅŗ sinchronizacija", + "backup_all": "Visi", "backup_background_service_backup_failed_message": "Nepavyko sukurti atsarginiÅŗ kopijÅŗ. Bandoma dar kartąâ€Ļ", "backup_background_service_connection_failed_message": "Nepavyko prisijungti prie serverio. Bandoma dar kartąâ€Ļ", "backup_background_service_current_upload_notification": "ÄŽkeliamas {filename}", + "backup_background_service_default_notification": "IeÅĄkoma naujÅŗ elementÅŗâ€Ļ", + "backup_background_service_error_title": "Atsarginio kopijavimo klaida", + "backup_background_service_in_progress_notification": "Kuriama elementÅŗ atsarginė kopijaâ€Ļ", "backup_background_service_upload_failure_notification": "Nepavyko įkelti {filename}", - "backup_controller_page_background_wifi": "Only on WiFi", + "backup_controller_page_albums": "Atsarginės kopijos albumai", + "backup_controller_page_background_app_refresh_disabled_title": "Foninis programos atnaujinimas iÅĄjungtas", + "backup_controller_page_background_app_refresh_enable_button_text": "Eiti į nustatymus", + "backup_controller_page_background_battery_info_link": "Parodyk man kaip", + "backup_controller_page_background_battery_info_message": "Norint geriausiÅŗ foninio atsarginio kopijavimo rezultatÅŗ, praÅĄome iÅĄjungti akumuliatoriaus optimizavimą ribojantį foninį Immich veikimą.\n\nKadangi tai priklauso nuo įrenginio, praÅĄome susirasti reikiamą informaciją pas įrenginio gamintoją.", + "backup_controller_page_background_battery_info_ok": "OK", + "backup_controller_page_background_battery_info_title": "Akumuliatoriaus optimizavimai", + "backup_controller_page_background_charging": "Tik kol kraunasi", + "backup_controller_page_background_configure_error": "Nepavyko sukonfigÅĢruoti foniniÅŗ paslaugÅŗ", + "backup_controller_page_background_delay": "Atidėti naujÅŗ elementÅŗ atsarginį kopijavimą: {duration}", + "backup_controller_page_background_description": "ÄŽjunkite fonines paslaugas, kad galėtumėte automatiÅĄkai kurti atsargines kopijas neatidarant programos", + "backup_controller_page_background_is_off": "Automatinis atsarginis kopijavimas yra iÅĄjungtas", + "backup_controller_page_background_is_on": "Automatinis atsarginis kopijavimas yra įjungtas", + "backup_controller_page_background_turn_off": "IÅĄjungti fonines paslaugas", + "backup_controller_page_background_turn_on": "ÄŽjungti fonines paslaugas", + "backup_controller_page_background_wifi": "Tik su Wi-Fi", + "backup_controller_page_backup": "Atsarginis kopijavimas", + "backup_controller_page_backup_selected": "Pasirinkta: ", + "backup_controller_page_backup_sub": "Perkeltos nuotraukos ir vaizdo įraÅĄai", "backup_controller_page_created": "Sukurta: {date}", + "backup_controller_page_desc_backup": "ÄŽjunkite foninį atsarginį kopijavimą, kad bÅĢtÅŗ automatiÅĄkai perkeliami nauji elementai į serverį kai atidaroma programa.", + "backup_controller_page_excluded": "Neįtraukta: ", + "backup_controller_page_failed": "Nepavyko ({count})", "backup_controller_page_filename": "Failo pavadinimas: {filename}[{size}]", + "backup_controller_page_id": "ID: {id}", + "backup_controller_page_info": "Atsarginio kopijavimo informacija", + "backup_controller_page_none_selected": "Niekas nepasirinkta", + "backup_controller_page_remainder": "Dar liko", + "backup_controller_page_remainder_sub": "Likusios pasirinktos atsarginio kopijavimo nuotraukos ir vaizdo įraÅĄai", "backup_controller_page_server_storage": "Serverio saugykla", + "backup_controller_page_start_backup": "Pradėti atsarginį kopijavimą", + "backup_controller_page_status_off": "Automatinis foninis atsarginis kopijavimas yra iÅĄjungtas", + "backup_controller_page_status_on": "Automatinis foninis atsarginis kopijavimas yra įjungtas", "backup_controller_page_storage_format": "{used} iÅĄ {total} panaudota", + "backup_controller_page_to_backup": "Albumai kuriÅŗ atsarginis kopijavimas bus atliktas", + "backup_controller_page_total_sub": "Visos unikalios nuotraukos ir video įraÅĄai iÅĄ paÅžymėtÅŗ albumÅŗ", + "backup_controller_page_turn_off": "IÅĄjungti foninį atsarginį kopijavimą", + "backup_controller_page_turn_on": "ÄŽjungti foninį atsarginį kopijavimą", "backup_controller_page_uploading_file_info": "ÄŽkeliama failo info", + "backup_err_only_album": "Negalima paÅĄalinti vienintelio albumo", + "backup_info_card_assets": "elementai", + "backup_manual_cancelled": "AtÅĄaukta", "backup_manual_in_progress": "Jau įkeliama, bandykite dar kartą vėliau", + "backup_manual_success": "Pavyko", + "backup_manual_title": "ÄŽkėlimo bÅĢklė", + "backup_options": "Atsarginio kopijavimo nustatymai", + "backup_options_page_title": "Atsarginio kopijavimo nustatymai", + "backup_setting_subtitle": "Tvarkyti foninio ir priekinio plano įkėlimo nustatymus", + "backup_settings_subtitle": "Tvarkyti įkėlimo nustatymus", + "backward": "Atgalinis", + "biometric_auth_enabled": "Biometrinis autentifikavimas įgalintas", + "biometric_locked_out": "JÅĢs esate uÅžblokuotas biometrinio autentifikavimo funkcijai", + "biometric_no_options": "Nėra galimÅŗ biometriniÅŗ nustatymÅŗ", + "biometric_not_available": "Biometrinis autentifikavimas ÅĄiame įrenginyje negalimas", "birthdate_saved": "Sėkmingai iÅĄsaugota gimimo data", "birthdate_set_description": "Gimimo data naudojama apskaičiuoti asmens amÅžiÅŗ nuotraukos darymo metu.", "blurred_background": "NeryÅĄkus fonas", @@ -416,42 +619,106 @@ "bulk_keep_duplicates_confirmation": "Ar tikrai norite palikti visus {count, plural, one {# besidubliuojantį elementą} few {# besidubliuojančius elementus} other {# besidubliuojančiÅŗ elementÅŗ}}? Tokiu bÅĢdu nieko netrinant bus sutvarkytos visos dublikatÅŗ grupės.", "bulk_trash_duplicates_confirmation": "Ar tikrai norite perkelti į ÅĄiukÅĄliadėŞę visus {count, plural, one {# besidubliuojantį elementą} few {# besidubliuojančius elementus} other {# besidubliuojančiÅŗ elementÅŗ}}? Bus paliktas didÅžiausias kiekvienos grupės elementas ir į ÅĄiukÅĄliadėŞę perkelti kiti besidubliuojantys elementai.", "buy": "ÄŽsigyti Immich", + "cache_settings_clear_cache_button": "IÅĄvalyti laikiną talpyklą", + "cache_settings_clear_cache_button_title": "IÅĄvalo programos laikiną talpyklą. Tai gali smarkiai paveikti programos greitį, kol bus sukurta nauja laikinoji talpykla.", + "cache_settings_duplicated_assets_clear_button": "IÅ VALYTI", + "cache_settings_duplicated_assets_subtitle": "Nuotraukos ir video įraÅĄai kurie yra programos ignoruojamÅŗ sąraÅĄe", + "cache_settings_duplicated_assets_title": "Sudubliuoti elementai ({count})", + "cache_settings_statistics_album": "Bibliotekos miniatiÅĢros", + "cache_settings_statistics_full": "Pilno dydÅžio nuotraukos", + "cache_settings_statistics_shared": "BendrinamÅŗ albumÅŗ miniatiÅĢros", + "cache_settings_statistics_thumbnail": "MiniatiÅĢros", + "cache_settings_statistics_title": "Laikinos talpyklos naudojimas", + "cache_settings_subtitle": "Valdykite Immich mobiliosios programos laikinosios talpyklos elgesį", + "cache_settings_tile_subtitle": "Valdykite vietinės talpyklos elgesį", + "cache_settings_tile_title": "Vietinė talpykla", + "cache_settings_title": "Laikinosios talpyklos nustatymai", "camera": "Fotoaparatas", "camera_brand": "Fotoaparato prekės Åženklas", "camera_model": "Fotoaparato modelis", "cancel": "AtÅĄaukti", "cancel_search": "AtÅĄaukti paieÅĄką", + "canceled": "AtÅĄaukta", + "canceling": "AtÅĄaukiama", "cannot_merge_people": "Negalima sujungti asmenÅŗ", + "cannot_undo_this_action": "JÅĢs negalėsite atkurti po ÅĄio veiksmo!", "cannot_update_the_description": "Negalima atnaujinti apraÅĄymo", + "cast": "Transliuoti", + "cast_description": "Valdyti galimas transliavimo kryptis", "change_date": "Pakeisti datą", + "change_description": "Pakeisti apraÅĄymus", + "change_display_order": "Pakeisti atvaizdavimo tvarką", "change_expiration_time": "Pakeisti galiojimo trukmę", "change_location": "Pakeisti vietovę", "change_name": "Pakeisti vardą", + "change_name_successfully": "Vardas pakeistas sėkmingai", "change_password": "Pakeisti slaptaÅžodį", "change_password_description": "Tai arba pirmas kartas, kai jungiatės prie sistemos, arba buvo pateikta uÅžklausa pakeisti jÅĢsÅŗ slaptaÅžodį. PraÅĄome įvesti naują slaptaÅžodį Åžemiau.", + "change_password_form_confirm_password": "Patvirtinti slaptaÅžodį", + "change_password_form_description": "Labas {name},\n\nTai yra pirmas kartas kai tu prisijungei prie sistemos arba buvo praÅĄymas pakeisti slaptaÅžodį. PraÅĄome įvesti naują slaptaÅžodį Åžemiau.", + "change_password_form_new_password": "Naujas slaptaÅžodis", + "change_password_form_password_mismatch": "SlaptaÅžodÅžiai nesutampa", + "change_password_form_reenter_new_password": "Pakartotinai įveskite naują slaptaÅžodį", + "change_pin_code": "Pakeisti PIN kodą", "change_your_password": "Pakeisti slaptaÅžodį", "changed_visibility_successfully": "Matomumas pakeistas sėkmingai", + "charging": "Kraunasi", + "charging_requirement_mobile_backup": "Foninis kopijavimas reikalauja, kad įrenginys bÅĢtÅŗ prijungtas pakrovimui", + "check_corrupt_asset_backup": "Patikrinti sugadintÅŗ elementÅŗ atsarginę kopiją", + "check_corrupt_asset_backup_button": "Atlikti patikrinimą", + "check_corrupt_asset_backup_description": "Paleiskite ÅĄÄ¯ patikrinimą tik per Wi-Fi ir tik kai visi elementai buvo perkopijuoti. Å i procedÅĢra uÅžtruks kelias minutes.", "check_logs": "Tikrinti Åžurnalus", + "choose_matching_people_to_merge": "Pasirinkite atitinkančius Åžmones sujungimui", "city": "Miestas", "clear": "IÅĄvalyti", "clear_all": "IÅĄvalyti viską", + "clear_all_recent_searches": "IÅĄvalyti visas naujausias paieÅĄkas", + "clear_file_cache": "IÅĄvalyti failÅŗ laikiną talpyklą", "clear_message": "IÅĄvalyti praneÅĄimą", "clear_value": "IÅĄvalyti reikÅĄmę", + "client_cert_dialog_msg_confirm": "OK", + "client_cert_enter_password": "ÄŽveskite slaptaÅžodį", + "client_cert_import": "Importuoti", + "client_cert_import_success_msg": "Kliento sertifikatas yra importuotas", "client_cert_invalid_msg": "Netinkamas sertifikato failas arba neteisingas slaptaÅžodis", + "client_cert_remove_msg": "Kliento sertifikatas yra paÅĄalintas", + "client_cert_subtitle": "Palaikomi tik PKCS12 (.p12, .pfx) formatai. Sertifikato importavimas/paÅĄalinimas galimas tik prieÅĄ prisijungimą", + "client_cert_title": "SSL kliento sertifikatas", + "clockwise": "Pagal laikrodÅžio rodykles", "close": "UÅždaryti", "collapse": "Suskleisti", "collapse_all": "Suskleisti viską", + "color": "Spalva", "color_theme": "Temos spalva", "comment_deleted": "Komentaras iÅĄtrintas", "comment_options": "KomentarÅŗ parinktys", "comments_and_likes": "Komentarai ir patiktukai", "comments_are_disabled": "Komentarai yra iÅĄjungti", + "common_create_new_album": "Sukurti naują albumą", + "common_server_error": "PraÅĄome patikrinti tinklo prisijungimą ir įsitikinti, kad serveris pasiekiamas ir programos/serverio versija sutampa.", + "completed": "UÅžbaigta", "confirm": "Patvirtinti", "confirm_admin_password": "Patvirtinti administratoriaus slaptaÅžodį", + "confirm_delete_face": "Ar tikrai norite iÅĄtrinti {name} veidą iÅĄ elementÅŗ?", "confirm_delete_shared_link": "Ar tikrai norite iÅĄtrinti ÅĄią bendrinimo nuorodą?", + "confirm_keep_this_delete_others": "Visi kiti elementai iÅĄ krÅĢvos bus iÅĄtrinti iÅĄskyrus ÅĄÄ¯ elementą. Ar tikrai norite tęsti?", + "confirm_new_pin_code": "Patvirtinkite naują PIN kodą", "confirm_password": "Patvirtinti slaptaÅžodį", + "confirm_tag_face": "Ar norite priskirti ÅĄÄ¯ veidą kaip {name}?", + "confirm_tag_face_unnamed": "Ar norite priskirti ÅĄÄ¯ veidą?", + "connected_device": "Prijungtas įrenginys", + "connected_to": "Prisijungta prie", + "contain": "Tilpti", "context": "Kontekstas", "continue": "Tęsti", + "control_bottom_app_bar_create_new_album": "Sukurti naują albumą", + "control_bottom_app_bar_delete_from_immich": "IÅĄtrinti iÅĄ Immich", + "control_bottom_app_bar_delete_from_local": "IÅĄtrinti iÅĄ įrenginio", + "control_bottom_app_bar_edit_location": "Redaguoti vietovę", + "control_bottom_app_bar_edit_time": "Redaguoti datą ir laiką", + "control_bottom_app_bar_share_link": "Dalintis nuoroda", + "control_bottom_app_bar_share_to": "Dalintis su", + "control_bottom_app_bar_trash_from_immich": "Perkelti į ÅĄiukÅĄliadėŞę", "copied_image_to_clipboard": "Nuotrauka nukopijuota į iÅĄkarpinę.", "copied_to_clipboard": "Nukopijuota į iÅĄkapinę!", "copy_error": "Kopijavimo klaida", @@ -462,6 +729,8 @@ "copy_password": "Kopijuoti slaptaÅžodį", "copy_to_clipboard": "Kopijuoti į iÅĄkarpinę", "country": "Å alis", + "cover": "UÅžpildyti", + "covers": "VirÅĄeliai", "create": "Sukurti", "create_album": "Sukurti albumą", "create_album_page_untitled": "Be pavadinimo", @@ -469,57 +738,116 @@ "create_link": "Sukurti nuorodą", "create_link_to_share": "Sukurti bendrinimo nuorodą", "create_link_to_share_description": "Leisti bet kam su nuoroda matyti paÅžymėtą(-as) nuotrauką(-as)", + "create_new": "SUKURTI NAUJĄ", "create_new_person": "Sukurti naują ÅžmogÅŗ", "create_new_person_hint": "Priskirti pasirinktus elementus naujam Åžmogui", "create_new_user": "Sukurti naują varotoją", + "create_shared_album_page_share_add_assets": "PRIDĖTI ELEMENTŞ", + "create_shared_album_page_share_select_photos": "PaÅžymėti nuotraukas", + "create_shared_link": "Sukurti dalijimosi nuorodą", "create_tag": "Sukurti Åžymą", "create_tag_description": "Sukurti naują Åžymą. ÄŽdėtinėms Åžymoms įveskite pilną kelią, įskaitant pasviruosius brÅĢkÅĄnius.", "create_user": "Sukurti naudotoją", "created": "Sukurta", + "created_at": "Sukurta", + "creating_linked_albums": "Kuriami susieti albumai...", + "crop": "Apkirpti", + "curated_object_page_title": "Daiktai", "current_device": "Dabartinis įrenginys", + "current_pin_code": "Dabartinis PIN kodas", + "current_server_address": "Dabartinis serverio adresas", + "custom_locale": "Pasirinktinė vietovė", "custom_locale_description": "Formatuoti datas ir skaičius pagal kalbą ir regioną", + "custom_url": "Pasirinktinis URL", + "daily_title_text_date": "E, MMM dd", + "daily_title_text_date_year": "E, MMM dd, yyyy", + "dark": "Tamsi", + "dark_theme": "Perjungti tamsią temą", "date_after": "Data po", "date_and_time": "Data ir laikas", "date_before": "Data prieÅĄ", + "date_format": "E, LLL d, y â€ĸ h:mm", "date_of_birth_saved": "Gimimo data sėkmingai iÅĄsaugota", + "date_range": "DatÅŗ intervalas", "day": "Diena", + "days": "DienÅŗ", "deduplicate_all": "Å alinti visus dublikatus", "deduplication_criteria_1": "Failo dydis baitais", "deduplication_criteria_2": "EXIF metaduomenÅŗ įraÅĄÅŗ skaičius", "deduplication_info": "DublikatÅŗ ÅĄalinimo informacija", "deduplication_info_description": "Automatinis elementÅŗ parinkimas ir masinis dublikatÅŗ ÅĄalinimas atliekamas atsiÅžvelgiant į:", + "default_locale": "Pradinė vietovė", "default_locale_description": "Formatuoti datas ir skaičius pagal jÅĢsÅŗ narÅĄyklės lokalę", "delete": "IÅĄtrinti", + "delete_action_confirmation_message": "Ar tikrai norite iÅĄtrinti ÅĄÄ¯ elementą? Å is veiksmas perkels elementą į serverio ÅĄiukÅĄliadėŞę ir paklaus ar norite iÅĄtrinti vietiniame įrenginyje", + "delete_action_prompt": "{count} iÅĄtrinta", "delete_album": "IÅĄtrinti albumą", "delete_api_key_prompt": "Ar tikrai norite iÅĄtrinti ÅĄÄ¯ API raktą?", + "delete_dialog_alert": "Å ie elementai bus galutinai iÅĄtrinti iÅĄ Immich ir iÅĄ jÅĢsÅŗ įrenginio", + "delete_dialog_alert_local": "Å ie elementai bus galutinai paÅĄalinti iÅĄ jÅĢsÅŗ įrenginio, bet bus prieinami Immich serveryje", + "delete_dialog_alert_local_non_backed_up": "Kai kurie elementai be Immich atsarginės kopijos ir bus galutinai paÅĄalinti iÅĄ jÅĢsÅŗ įrenginio", + "delete_dialog_alert_remote": "Å ie elementai bus galutinai iÅĄtrinti iÅĄ Immich serverio", + "delete_dialog_ok_force": "Vis tiek iÅĄtrinti", + "delete_dialog_title": "IÅĄtrinti galutinai", "delete_duplicates_confirmation": "Ar tikrai norite visam laikui iÅĄtrinti ÅĄiuos dublikatus?", + "delete_face": "IÅĄtrinti veidą", "delete_key": "IÅĄtrinti raktą", "delete_library": "IÅĄtrinti biblioteką", "delete_link": "IÅĄtrinti nuorodą", + "delete_local_action_prompt": "{count} iÅĄtrinti vietiniame įrenginyje", + "delete_local_dialog_ok_backed_up_only": "IÅĄtrinti tik turinčius atsarginę kopiją", + "delete_local_dialog_ok_force": "Vis tiek iÅĄtrinti", + "delete_others": "IÅĄtrinti kitus", + "delete_permanently": "IÅĄtrinti galutinai", + "delete_permanently_action_prompt": "{count} iÅĄtrinta galutinai", "delete_shared_link": "IÅĄtrinti bendrinimo nuorodą", + "delete_shared_link_dialog_title": "IÅĄtrinti dalijimosi nuorodą", "delete_tag": "IÅĄtrinti Åžymą", "delete_tag_confirmation_prompt": "Ar tikrai norite iÅĄtrinti Åžymą {tagName}?", "delete_user": "IÅĄtrinti naudotoją", "deleted_shared_link": "Bendrinimo nuoroda iÅĄtrinta", + "deletes_missing_assets": "IÅĄtrinti diske trÅĢkstamus elementus", "description": "ApraÅĄymas", + "description_input_hint_text": "Pridėti apraÅĄymą...", + "description_input_submit_error": "Klaida atnaujinant apraÅĄymą, pasitikrinkite Åžurnalą norint detalesnės informacijos", + "deselect_all": "AtÅžymėti visus", "details": "Detalės", "direction": "Kryptis", "disabled": "IÅĄjungta", "disallow_edits": "Neleisti redaguoti", + "discord": "Discord", "discover": "Atrasti", + "discovered_devices": "Aptikti įrenginiai", "dismiss_all_errors": "Nepaisyti visÅŗ klaidÅŗ", "dismiss_error": "Nepaisyti klaidos", + "display_options": "Atvaizdavimo parinktys", "display_order": "Atvaizdavimo tvarka", "display_original_photos": "Rodyti originalias nuotraukas", + "display_original_photos_setting_description": "Pirmenybė rodyti originalią nuotrauką vietoje miniatiÅĢros kai originalo elementas yra palaikomas narÅĄyklės. Tai gali lemti lėtesnį nuotraukos rodymo greitį.", "do_not_show_again": "Daugiau nerodyti ÅĄio praneÅĄimo", "documentation": "Dokumentacija", + "done": "Atlikta", "download": "AtsisiÅŗsti", + "download_action_prompt": "Atsisiunčiami {count} elementai", + "download_canceled": "Atsisiuntimas atÅĄauktas", + "download_complete": "Atsisiuntimas pabaigtas", + "download_enqueue": "Atsisiuntimai įtraukti į eilę", + "download_error": "Atsisiuntimo klaida", "download_failed": "Nepavyko parsisiÅŗsti", + "download_finished": "Atsisiuntimas pabaigtas", + "download_include_embedded_motion_videos": "ÄŽterpti vaizdo įraÅĄai", "download_include_embedded_motion_videos_description": "Pridėti prie judesio nuotraukÅŗ įterptus video kaip atskirą failą", + "download_notfound": "Atsisiuntimas nerastas", "download_paused": "Atsisiuntimas pristabdytas", "download_settings": "AtsisiÅŗsti", + "download_settings_description": "Tvarkyti elementÅŗ atsisiuntimo nustatymus", + "download_started": "Atsisiuntimas pradėtas", + "download_sucess": "Atsisiuntimas pavyko", + "download_sucess_android": "Medija buvo atsiÅŗsta į DCIM/Immich", + "download_waiting_to_retry": "Laukiama bandymo iÅĄ naujo", "downloading": "Siunčiama", "downloading_asset_filename": "Parsisiunčiamas resursas {filename}", + "downloading_media": "Atsisiunčiama medija", "drop_files_to_upload": "UÅžkelkite failus bet kurioje vietoje kad įkeltumėte", "duplicates": "Dublikatai", "duplicates_description": "Sutvarkykite kiekvieną elementÅŗ grupę nurodydami elementus, kurie yra dublikatai (jei tokiÅŗ yra)", @@ -527,8 +855,14 @@ "edit": "Redaguoti", "edit_album": "Redaguoti albumą", "edit_avatar": "Redaguoti avatarą", + "edit_birthday": "Redaguoti gimtadienį", "edit_date": "Redaguoti datą", "edit_date_and_time": "Redaguoti datą ir laiką", + "edit_date_and_time_action_prompt": "{count} data ir laikas redaguotas", + "edit_date_and_time_by_offset": "Keisti datą pagal poslinkį", + "edit_date_and_time_by_offset_interval": "Naujas datos intervalas: {from} - {to}", + "edit_description": "Redaguoti apraÅĄymą", + "edit_description_prompt": "PraÅĄome pasirinkti naują apraÅĄymą:", "edit_exclusion_pattern": "Redaguoti iÅĄimčiÅŗ ÅĄabloną", "edit_faces": "Redaguoti veidus", "edit_import_path": "Redaguoti importavimo kelią", @@ -536,41 +870,81 @@ "edit_key": "Redaguoti raktą", "edit_link": "Redaguoti nuorodą", "edit_location": "Redaguoti vietovę", + "edit_location_action_prompt": "{count} vietovės pakeistos", + "edit_location_dialog_title": "Vietovė", "edit_name": "Redaguoti vardą", "edit_people": "Redaguoti Åžmones", "edit_tag": "Redaguoti Åžymą", "edit_title": "Redaguoti antraÅĄtę", "edit_user": "Redaguoti naudotoją", "edited": "Redaguota", + "editor": "Redaktorius", + "editor_close_without_save_prompt": "Pakeitimai nebus iÅĄsaugoti", + "editor_close_without_save_title": "UÅždaryti redaktoriÅŗ?", + "editor_crop_tool_h2_aspect_ratios": "Vaizdo santykis", + "editor_crop_tool_h2_rotation": "Pasukimas", "email": "El. paÅĄtas", + "email_notifications": "El. paÅĄto praneÅĄimai", + "empty_folder": "Å is katalogas yra tuÅĄÄias", "empty_trash": "IÅĄtuÅĄtinti ÅĄiukÅĄliadėŞę", + "empty_trash_confirmation": "Ar tikrai norite iÅĄtuÅĄtinti ÅĄiukÅĄliadėŞę? Tai galutinai paÅĄalins elementus iÅĄ Immich.\nJÅĢs negalėsite atkurti ÅĄio veiksmo!", "enable": "ÄŽgalinti", + "enable_backup": "ÄŽgalinti atsargines kopijas", + "enable_biometric_auth_description": "ÄŽveskite savo PIN kodą biometrinės autentifikacijos įjungimui", "enabled": "ÄŽgalintas", "end_date": "Pabaigos data", - "enter_wifi_name": "Enter WiFi name", + "enqueued": "ÄŽtraukta į eilę", + "enter_wifi_name": "ÄŽveskite Wi-Fi pavadinimą", + "enter_your_pin_code": "ÄŽveskite savo PIN kodą", "enter_your_pin_code_subtitle": "ÄŽveskite savo PIN kodą, kad pasiektumėte uÅžrakintą aplanką", "error": "Klaida", + "error_change_sort_album": "Nepavyko pakeisti albumo rÅĢÅĄiavimo tvarkos", + "error_delete_face": "Klaida trinant veidą iÅĄ elementÅŗ", + "error_getting_places": "Klaida gaunant vietoves", "error_loading_image": "Klaida įkeliant vaizdą", + "error_loading_partners": "Klaida uÅžkraunant partnerius: {error}", + "error_saving_image": "Klaida: {error}", + "error_tag_face_bounding_box": "Klaida apraÅĄant veidą - nepavyko gauti veido vietos koordinačiÅŗ", "error_title": "Klaida - KaÅžkas nutiko ne taip", "errors": { + "cannot_navigate_next_asset": "Negalima pereiti prie sekančio elemento", + "cannot_navigate_previous_asset": "Negalima pereiti prie buvusio elemento", "cant_apply_changes": "Negalima taikyti pakeitimÅŗ", + "cant_change_activity": "Negalima {enabled, select, true {iÅĄjungti} other {įjungti}} veiklos", + "cant_change_asset_favorite": "Elementui negalima pakeisti mėgstamiausio", + "cant_change_metadata_assets_count": "Negalima pakeisti {count, plural, one {# elemento} other {# elementÅŗ}} metadata", + "cant_get_faces": "Nepavyko gauti veidus", + "cant_get_number_of_comments": "Nepavyko gauti komentarÅŗ skaičiaus", + "cant_search_people": "Negalima ieÅĄkoti ÅžmoniÅŗ", + "cant_search_places": "Negalima ieÅĄkoti vietoviÅŗ", "error_adding_assets_to_album": "Klaida pridedant elementus į albumą", "error_adding_users_to_album": "Klaida pridedant naudotojus prie albumo", + "error_deleting_shared_user": "Klaida trinant pasidalintą naudotoją", "error_downloading": "Klaida atsisiunčiant {filename}", "error_hiding_buy_button": "Klaida slepiant pirkimo mygtuką", "error_removing_assets_from_album": "Klaida ÅĄalinant elementus iÅĄ albumo, patikrinkite konsolę dėl iÅĄsamesnės informacijos", + "error_selecting_all_assets": "Klaida pasirenkant visus elementus", "exclusion_pattern_already_exists": "Å is iÅĄimčiÅŗ ÅĄablonas jau egzistuoja.", "failed_to_create_album": "Nepavyko sukurti albumo", "failed_to_create_shared_link": "Nepavyko sukurti bendrinimo nuorodos", "failed_to_edit_shared_link": "Nepavyko redaguoti bendrinimo nuorodos", + "failed_to_get_people": "Nepavyko gauti ÅžmoniÅŗ", + "failed_to_keep_this_delete_others": "Nepavyko palikti ÅĄÄ¯ elementą ir iÅĄtrinti kitus elementus", + "failed_to_load_asset": "Nepavyko uÅžkrauti elemento", + "failed_to_load_assets": "Nepavyko uÅžrauti elementÅŗ", + "failed_to_load_notifications": "Nepavyko uÅžkrauti praneÅĄimÅŗ", "failed_to_load_people": "Nepavyko uÅžkrauti ÅžmoniÅŗ", "failed_to_remove_product_key": "Nepavyko paÅĄalinti produkto rakto", + "failed_to_reset_pin_code": "Nepavyko atkurti PIN kodo", "failed_to_stack_assets": "Nepavyko sugrupuoti elementÅŗ", "failed_to_unstack_assets": "Nepavyko iÅĄgrupuoti elementÅŗ", + "failed_to_update_notification_status": "Nepavyko atnaujinti praneÅĄimo statuso", "import_path_already_exists": "Å is importavimo kelias jau egzistuoja.", "incorrect_email_or_password": "Neteisingas el. paÅĄto adresas arba slaptaÅžodis", + "paths_validation_failed": "Nepavyko {paths, plural, one {# kelio} other {# keliÅŗ}} patvirtinimas", "profile_picture_transparent_pixels": "Profilio nuotrauka negali turėti permatomÅŗ pikseliÅŗ. PraÅĄome priartinti ir/arba perkelkite nuotrauką.", "quota_higher_than_disk_size": "Nustatyta kvota, virÅĄija disko dydį", + "something_went_wrong": "KaÅžkas nepavyko", "unable_to_add_album_users": "Nepavyksta pridėti naudotojÅŗ prie albumo", "unable_to_add_assets_to_shared_link": "Nepavyko į bendrinimo nuorodą pridėti elementÅŗ", "unable_to_add_comment": "Nepavyksta pridėti komentaro", @@ -578,11 +952,15 @@ "unable_to_add_import_path": "Nepavyksta pridėti importavimo kelio", "unable_to_add_partners": "Nepavyksta pridėti partneriÅŗ", "unable_to_add_remove_archive": "Nepavyko {archived, select, true {iÅĄtraukti iÅĄ} other {pridėti prie}} arcyhvo", + "unable_to_add_remove_favorites": "Nepavyko {favorite, select, true {įtraukti elemento į mėgstamiausius} other {paÅĄalinti elemento iÅĄ mėgstamiausiÅŗ}}", "unable_to_archive_unarchive": "Nepavyko {archived, select, true {archyvuoti} other {iÅĄarchyvuoti}}", "unable_to_change_album_user_role": "Nepavyksta pakeisti albumo naudotojo rolės", "unable_to_change_date": "Negalima pakeisti datos", + "unable_to_change_description": "Nepavyko pakeisti apraÅĄymo", + "unable_to_change_favorite": "Nepavyko pakeisti elementui mėgstamiausio", "unable_to_change_location": "Negalima pakeisti vietos", "unable_to_change_password": "Negalima pakeisti slaptaÅžodÅžio", + "unable_to_change_visibility": "Nepavyko pakeisti matomumo {count, plural, one {# asmeniui} few {#asmenims} other {# asmenÅŗ}}", "unable_to_complete_oauth_login": "Nepavyko prisijungti su OAuth", "unable_to_connect": "Nepavyko prisijungti", "unable_to_copy_to_clipboard": "Negalima kopijuoti į iÅĄkarpinę, įsitikinkite, kad prie puslapio prieinate per https", @@ -591,6 +969,8 @@ "unable_to_create_library": "Nepavyko sukurti bibliotekos", "unable_to_create_user": "Nepavyko sukurti naudotojo", "unable_to_delete_album": "Nepavyksta iÅĄtrinti albumo", + "unable_to_delete_asset": "Nepavyko iÅĄtrinti elemento", + "unable_to_delete_assets": "Klaida trinant elementus", "unable_to_delete_exclusion_pattern": "Nepavyksta iÅĄtrinti iÅĄimčiÅŗ ÅĄablono", "unable_to_delete_import_path": "Nepavyksta iÅĄtrinti importavimo kelio", "unable_to_delete_shared_link": "Nepavyko iÅĄtrinti bendrinimo nuorodos", @@ -598,22 +978,37 @@ "unable_to_download_files": "Nepavyksta atsisiÅŗsti failÅŗ", "unable_to_edit_exclusion_pattern": "Nepavyksta redaguoti iÅĄimčiÅŗ ÅĄablono", "unable_to_edit_import_path": "Nepavyksta redaguoti iÅĄimčiÅŗ kelio", + "unable_to_empty_trash": "Nepavyko iÅĄtrinti ÅĄiukÅĄliadėŞės", "unable_to_enter_fullscreen": "Nepavyksta pereiti į viso ekrano reÅžimą", "unable_to_exit_fullscreen": "Nepavyksta iÅĄeiti iÅĄ viso ekrano reÅžimo", + "unable_to_get_comments_number": "Nepavyko gauti komentarÅŗ skaičiaus", "unable_to_get_shared_link": "Nepavyko gauti bendrinimo nuorodos", "unable_to_hide_person": "Nepavyksta paslėpti Åžmogaus", + "unable_to_link_motion_video": "Nepavyko susieti judesio video", "unable_to_link_oauth_account": "Nepavyko susieti su OAuth paskyra", "unable_to_log_out_all_devices": "Nepavyksta atjungti visÅŗ įrenginiÅŗ", "unable_to_log_out_device": "Nepavyksta atjungti įrenginio", "unable_to_login_with_oauth": "Nepavyko prisijungti su OAuth", "unable_to_play_video": "Nepavyksta paleisti vaizdo įraÅĄo", + "unable_to_reassign_assets_existing_person": "Nepavyko priskirti elementÅŗ {name, select, null {egzistuojančiam asmeniui} other {{name}}}", + "unable_to_reassign_assets_new_person": "Nepavyko priskirti elementÅŗ naujam asmeniui", "unable_to_refresh_user": "Nepavyksta atnaujinti naudotojo", + "unable_to_remove_album_users": "Nepavyko paÅĄalinti naudotojÅŗ iÅĄ albumo", "unable_to_remove_api_key": "Nepavyko paÅĄalinti API rakto", "unable_to_remove_assets_from_shared_link": "Nepavyko iÅĄ bendrinimo nuorodos paÅĄalinti elementÅŗ", "unable_to_remove_library": "Nepavyksta paÅĄalinti bibliotekos", "unable_to_remove_partner": "Nepavyksta paÅĄalinti partnerio", "unable_to_remove_reaction": "Nepavyksta paÅĄalinti reakcijos", + "unable_to_reset_password": "Nepavyko atnaujinti slaptaÅžodÅžio", + "unable_to_reset_pin_code": "Nepavyko atnaujinti PIN kodo", "unable_to_resolve_duplicate": "Nepavyko sutvarkyti dublikatÅŗ", + "unable_to_restore_assets": "Nepavyko atstatyti elementÅŗ", + "unable_to_restore_trash": "Nepavyko atstatyti iÅĄ ÅĄiukÅĄliadėŞės", + "unable_to_restore_user": "Nepavyko atstatyti naudotojo", + "unable_to_save_album": "Nepavyko iÅĄsaugoti albumo", + "unable_to_save_api_key": "Nepavyko iÅĄsaugoti API rakto", + "unable_to_save_date_of_birth": "Nepavyko iÅĄsaugoti gimimo datos", + "unable_to_save_name": "Nepavyko iÅĄsaugoti vardo", "unable_to_save_profile": "Nepavyko iÅĄsaugoti profilio", "unable_to_save_settings": "Nepavyksta iÅĄsaugoti nustatymÅŗ", "unable_to_scan_libraries": "Nepavyksta nuskaityti bibliotekÅŗ", @@ -622,39 +1017,105 @@ "unable_to_set_profile_picture": "Nepavyksta nustatyti profilio nuotraukos", "unable_to_submit_job": "Napvyko sukurti uÅžduoties", "unable_to_trash_asset": "Nepavyko perkelti į ÅĄiukÅĄliadėŞę", + "unable_to_unlink_account": "Nepavyko atsieti paskyrÅŗ", + "unable_to_unlink_motion_video": "Nepavyko atsieti judesio video", + "unable_to_update_album_cover": "Nepavyko atnaujinti albumo virÅĄelio", + "unable_to_update_album_info": "Nepavyko atnaujinti albumo informacijos", + "unable_to_update_library": "Nepavyko atnaujinti bibliotekos", + "unable_to_update_location": "Nepavyko atnaujinti vietovės", + "unable_to_update_settings": "Nepavyko atnaujinti nustatymÅŗ", + "unable_to_update_timeline_display_status": "Nepavyko atnaujinti laiko juostos rodymo statuso", + "unable_to_update_user": "Nepavyko atnaujinti naudotoją", "unable_to_upload_file": "Nepavyksta įkelti failo" }, + "exif": "Exif", + "exif_bottom_sheet_description": "Pridėti apraÅĄymą...", + "exif_bottom_sheet_description_error": "Klaida atnaujinant apraÅĄymą", + "exif_bottom_sheet_details": "DETALĖS", + "exif_bottom_sheet_location": "VIETOVĖ", + "exif_bottom_sheet_people": "ÅŊMONĖS", + "exif_bottom_sheet_person_add_person": "Pridėti vardą", "exit_slideshow": "IÅĄeiti iÅĄ skaidriÅŗ perÅžiÅĢros", "expand_all": "IÅĄskleisti viską", + "experimental_settings_new_asset_list_subtitle": "Dirbama", + "experimental_settings_new_asset_list_title": "ÄŽgalinti eksperimentinį nuotraukÅŗ tinklelį", + "experimental_settings_subtitle": "Naudokite savo pačiÅŗ rizika!", + "experimental_settings_title": "Eksperimentinis", + "expire_after": "Galiojimas baigiasi", "expired": "Nebegalioja", "expires_date": "Nebegalios uÅž {date}", "explore": "NarÅĄyti", + "explorer": "NarÅĄyklė", "export": "Eksportuoti", "export_as_json": "Eksportuoti kaip JSON", + "export_database": "Eksportuoti duomenÅŗ bazę", + "export_database_description": "Eksportuoti SQLite duomenÅŗ bazę", "extension": "Plėtinys", "external": "IÅĄorinis", "external_libraries": "IÅĄorinės bibliotekos", - "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": "IÅĄorinis tinklas", + "external_network_sheet_info": "Kai neprisijungta prie pageidaujamo Wi-Fi tinklo, programa jungsis prie serverio per pirmą URL nuorodą, kurią galės pasiekti, pradedant nuo virÅĄaus į apačią", "face_unassigned": "Nepriskirta", "failed": "ÄŽvyko klaida", + "failed_to_authenticate": "Nepavyko autentifikuoti", + "failed_to_load_assets": "Nepavyko įkelti elementÅŗ", + "failed_to_load_folder": "Nepavyko įkelti katalogą", "favorite": "Mėgstamiausias", + "favorite_action_prompt": "{count} pridėta prie mėgstamiausiÅŗ", "favorite_or_unfavorite_photo": "ÄŽtraukti prie arba paÅĄalinti iÅĄ mėgstamiausiÅŗ", "favorites": "Mėgstamiausi", + "favorites_page_no_favorites": "Nerasta mėgstamiausiÅŗ elementÅŗ", + "feature_photo_updated": "Pageidaujama nuotrauka atnaujinta", "features": "Funkcijos", + "features_in_development": "KÅĢrimo funkcijos", "features_setting_description": "Valdyti aplikacijos funkcijas", "file_name": "Failo pavadinimas", "file_name_or_extension": "Failo pavadinimas arba plėtinys", "filename": "Failopavadinimas", "filetype": "Failo tipas", + "filter": "Filtras", "filter_people": "Filtruoti Åžmones", + "filter_places": "Filtruoti vietoves", + "find_them_fast": "Raskite greitai paieÅĄkoje pagal vardą", + "first": "Pirmas", + "fix_incorrect_match": "Pataisyti neteisingą porą", + "folder": "Katalogas", + "folder_not_found": "Katalogas nerastas", "folders": "Aplankai", "folders_feature_description": "PerÅžiÅĢrėkite failÅŗ sistemoje esančias nuotraukas ir vaizdo įraÅĄus aplankÅŗ rodinyje", + "forgot_pin_code_question": "PamirÅĄote savo PIN?", + "forward": "Pirmyn", + "gcast_enabled": "Google Cast", + "gcast_enabled_description": "Kad veiktÅŗ, ÅĄi funkcija įkelia iÅĄorinius „Google“ iÅĄteklius.", + "general": "Bendri", + "geolocation_instruction_location": "Paspauskite ant elemento su GPS koordinatėmis norint naudoti tą vietovę arba pasirinkite vietovę tiesiogiai Åžemėlapyje", "get_help": "Gauti pagalbos", + "get_wifiname_error": "Nepavyko gauti Wi-Fi pavadinimo. ÄŽsitikinkite, kad suteikti bÅĢtini leidimai ir esate prisijungę prie Wi-Fi tinklo", + "getting_started": "Pradedama", + "go_back": "Eiti atgal", + "go_to_folder": "Eiti į katalogą", + "go_to_search": "Eiti į paieÅĄką", + "gps": "GPS", + "gps_missing": "Be GPS", + "grant_permission": "Suteikti leidimą", "group_albums_by": "Grupuoti albumus pagal...", + "group_country": "Grupuoti pagal ÅĄalis", "group_no": "Negrupuoti", "group_owner": "Grupuoti pagal savininką", + "group_places_by": "Grupuoti vietoves pagal...", "group_year": "Grupuoti pagal metus", + "haptic_feedback_switch": "ÄŽjungti haptinį grįŞtamąjį ryÅĄÄ¯", + "haptic_feedback_title": "Haptinis grįŞtamasis ryÅĄys", "has_quota": "Turi kvotą", + "hash_asset": "Kurti bylos paraÅĄÄ… elementui", + "hashed_assets": "Elementai su bylÅŗ paraÅĄais", + "hashing": "BylÅŗ paraÅĄo kÅĢrimas", + "header_settings_add_header_tip": "Pridėti antraÅĄtę", + "header_settings_field_validator_msg": "ReikÅĄmė negali bÅĢti tuÅĄÄia", + "header_settings_header_name_input": "AntraÅĄtės pavadinimas", + "header_settings_header_value_input": "AntraÅĄtės reikÅĄmė", + "headers_settings_tile_subtitle": "ApibrÄ—Åžkite tarpinio serverio antraÅĄtes, kurias programa turėtÅŗ siÅŗsti su kiekviena tinklo uÅžklausa", + "headers_settings_tile_title": "Pasirinktinės tarpinio serverio antraÅĄtės", "hi_user": "Labas {name} ({email})", "hide_all_people": "Slėpti visus asmenis", "hide_gallery": "Slėpti galeriją", @@ -662,63 +1123,167 @@ "hide_password": "Slėpti slaptaÅžodį", "hide_person": "Slėpti asmenį", "hide_unnamed_people": "Slėpti neįvardintus asmenis", - "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_add_to_album_conflicts": "Pridėta {added} elementÅŗ į albumą {album}. {failed} elementai jau yra albume.", + "home_page_add_to_album_err_local": "Kol kas negalima pridėti vietiniÅŗ elementÅŗ į albumus, praleidÅžiama", + "home_page_add_to_album_success": "Pridėta {added} elementÅŗ į albumą {album}.", + "home_page_album_err_partner": "Kol kas negalima pridėti partnerio elementÅŗ į albumą, praleidÅžiama", + "home_page_archive_err_local": "Kol kas negalima archyvuoti vietiniÅŗ elementÅŗ, praleidÅžiama", + "home_page_archive_err_partner": "Negalima archyvuoti partnerio elementÅŗ, praleidÅžiama", + "home_page_building_timeline": "Kuriama laiko juosta", + "home_page_delete_err_partner": "Negalima iÅĄtrinti partnerio elementÅŗ, praleidÅžiama", + "home_page_delete_remote_err_local": "Vietiniai elementai iÅĄtrinant nuotolinį pasirinkimą, praleidÅžiami", + "home_page_favorite_err_local": "Kol kas negalima priskirti mėgstamiausiÅŗ vietiniÅŗ elementÅŗ, praleidÅžiama", + "home_page_favorite_err_partner": "Kol kas negalima priskirti mėgstamiausiÅŗ partnerio elementÅŗ, praleidÅžiama", + "home_page_first_time_notice": "Jei jÅĢs naudojate programą pirmą kartą, tai praÅĄome pasirinkti atsarginės kopijos albumą, kad laiko juosta galėtÅŗ tvarkyti albumo nuotraukas ir vaizdo įraÅĄus", "home_page_locked_error_local": "Nepavyko perkelti lokaliÅŗ failÅŗ į uÅžrakintą aplanką, praleidÅžiama", "home_page_locked_error_partner": "Nepavyko perkelti partnerio failÅŗ į uÅžrakintą aplanką, praleidÅžiama", + "home_page_share_err_local": "Negalima dalinti vietiniÅŗ elementÅŗ per nuorodą, praleidÅžiama", + "home_page_upload_err_limit": "Galima įkelti tik iki 30 elementÅŗ vienu metu, praleidÅžiama", + "host": "Å eimininkas", "hour": "Valanda", + "hours": "Valandos", + "id": "ID", + "idle": "Laisva", + "ignore_icloud_photos": "Ignoruoti iCloud nuotraukas", + "ignore_icloud_photos_description": "Nuotraukos laikomos iCloud nebus įkeltos į Immich serverį", "image": "Nuotrauka", + "image_alt_text_date": "{isVideo, select, true {Filmuota} other {Fotografuota}} {date}", + "image_alt_text_date_1_person": "{isVideo, select, true {Filmuota} other {Fotografuota}} su {person1} {date}", + "image_alt_text_date_2_people": "{isVideo, select, true {Filmuota} other {Fotografuota}} su {person1} ir {person2} {date}", + "image_alt_text_date_3_people": "{isVideo, select, true {Filmuota} other {Fotografuota}} {date} su {person1}, {person2} ir{person3}", + "image_alt_text_date_4_or_more_people": "{isVideo, select, true {Filmuota} other {Fotografuota}} {date} su {person1}, {person2} ir {additionalCount, number} kitais", + "image_alt_text_date_place": "{isVideo, select, true {Filmuota} other {Fotografuota}} {city}, {country} {date}", + "image_alt_text_date_place_1_person": "{isVideo, select, true {Filmuota} other {Fotografuota}} su {person1} - {city}, {country} {date}", + "image_alt_text_date_place_2_people": "{isVideo, select, true {Filmuota} other {Fotografuota}} su {person1} ir {person2} - {city}, {country} {date}", + "image_alt_text_date_place_3_people": "{isVideo, select, true {Filmuota} other {Fotografuota}} su {person1}, {person2}, ir {person3} - {city}, {country} {date}", + "image_alt_text_date_place_4_or_more_people": "{isVideo, select, true {Filmuota} other {Fotografuota}} su {person1}, {person2}, ir {additionalCount, number} kitais - {city}, {country} {date}", + "image_saved_successfully": "Nuotrauka iÅĄsaugota", + "image_viewer_page_state_provider_download_started": "Atsisiuntimas pradėtas", + "image_viewer_page_state_provider_download_success": "Atsisiuntimas pavyko", + "image_viewer_page_state_provider_share_error": "Dalinimosi klaida", "immich_logo": "Immich logotipas", + "immich_web_interface": "Immich Web sąsaja", "import_from_json": "Importuoti iÅĄ JSON", "import_path": "Importavimo kelias", + "in_albums": "{count, plural, one {# Albume} few {#Albumuose} other {# AlbumÅŗ}}", "in_archive": "Archyve", "include_archived": "ÄŽtraukti archyvuotus", "include_shared_albums": "ÄŽtraukti bendrinamus albumus", "include_shared_partner_assets": "ÄŽtraukti partnerio pasidalintus elementus", + "individual_share": "Pavienis pasidalinimas", + "individual_shares": "Pavieniai pasidalinimai", "info": "Informacija", "interval": { "day_at_onepm": "Kiekvieną dieną 13:00", + "hours": "Kas{hours, plural, one {valandą} few {#valandas} other {{hours, number} valandÅŗ}}", "night_at_midnight": "Kiekvieną vidurnaktį", "night_at_twoam": "Kiekvieną naktį 02:00" }, + "invalid_date": "Netinkama data", + "invalid_date_format": "Netinkamas datos formatas", "invite_people": "Kviesti Åžmones", "invite_to_album": "Pakviesti į albumą", + "ios_debug_info_fetch_ran_at": "UÅžkrovimas vyko {dateTime}", + "ios_debug_info_last_sync_at": "Paskutinė sinchronizacija {dateTime}", + "ios_debug_info_no_processes_queued": "Eilėje nėra foniniÅŗ procesÅŗ", "ios_debug_info_no_sync_yet": "Jokia background sync uÅžduotis dar nebuvo paleista", + "ios_debug_info_processes_queued": "{count, plural, one {Eilėje {count} foninis procesas} few {Eilėje {count} foniniai procesai} other {Eilėje {count} foniniÅŗ procesÅŗ}}", + "ios_debug_info_processing_ran_at": "Apdorojimas vyko {dateTime}", "items_count": "{count, plural, one {# elementas} few {# elementai} other {# elementÅŗ}}", "jobs": "UÅžduotys", "keep": "Palikti", "keep_all": "Palikti visus", + "keep_this_delete_others": "IÅĄsaugoti ÅĄÄ¯, kitus iÅĄtrinti", + "kept_this_deleted_others": "IÅĄsaugotas ÅĄis elementas ir {count, plural, one {iÅĄtrintas # elementas} few {iÅĄtrinti # elementai} other {iÅĄtrinta # elementÅŗ}}", "keyboard_shortcuts": "Spartieji klaviatÅĢros klaviÅĄai", "language": "Kalba", + "language_no_results_subtitle": "Bandykite pakoreguoti paieÅĄkos terminą", + "language_no_results_title": "Kalbos nerastos", + "language_search_hint": "IeÅĄkoti kalbÅŗ...", "language_setting_description": "Pasirinkti pageidaujamą kalbą", + "large_files": "Dideli failai", + "last": "Paskutinis", "last_seen": "Paskutinį kartą matytas", "latest_version": "Naujausia versija", "latitude": "Platuma", "leave": "IÅĄeiti", + "leave_album": "Palikti albumą", + "lens_model": "LÄ™ÅĄiÅŗ modelis", "let_others_respond": "Leisti kitiems reaguoti", "level": "Lygis", "library": "Biblioteka", "library_options": "Bibliotekos pasirinktys", + "library_page_device_albums": "Albumai įrenginyje", + "library_page_new_album": "Naujas albumas", "library_page_sort_asset_count": "ElementÅŗ skaičius", "library_page_sort_created": "KÅĢrimo data", "library_page_sort_last_modified": "Paskutinį kartą modifikuota", "library_page_sort_title": "Albumo pavadinimas", + "licenses": "Licencijos", + "light": "Å viesi", + "like": "Kaip", + "like_deleted": "Kaip iÅĄtrintas", + "link_motion_video": "Susieti judesio vaizdo įraÅĄÄ…", "link_to_oauth": "Susieti su OAuth", "linked_oauth_account": "Susieta OAuth paskyra", "list": "SąraÅĄas", "loading": "Kraunama", "loading_search_results_failed": "Nepavyko uÅžkrauti paieÅĄkos rezultatÅŗ", - "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": "Vietinis", + "local_asset_cast_failed": "Negalima transliuoti elemento kuris neįkeltas į serverį", + "local_assets": "Vietiniai elementai", + "local_media_summary": "Vietinės medijos santrauka", + "local_network": "Vietinis tinklas", + "local_network_sheet_info": "Programa jungsis prie serverio per ÅĄÄ¯ URL kai naudos pasirinktą Wi-Fi tinklą", + "location_permission": "Vietovės leidimai", + "location_permission_content": "Norint naudoti automatinio persijungimo opciją, Immich reikia tikslios vietovės leidimo, kad galėtÅŗ nuskaityti Wi-Fi tinklo pavadinimą", + "location_picker_choose_on_map": "Pasirinkite Åžemėlapyje", + "location_picker_latitude_error": "ÄŽveskite tinkamą platumą", + "location_picker_latitude_hint": "ÄŽveskite platumą čia", + "location_picker_longitude_error": "ÄŽveskite tinkamą ilgumą", + "location_picker_longitude_hint": "ÄŽveskite ilgumą čia", + "lock": "UÅžrakinti", "locked_folder": "UÅžrakintas aplankas", + "log_detail_title": "ÅŊurnalo detalės", "log_out": "Atsijungti", "log_out_all_devices": "Atsijungti iÅĄ visÅŗ įrenginiÅŗ", + "logged_in_as": "Prisijungta kaip {user}", "logged_out_all_devices": "Atsijungta iÅĄ visÅŗ įrenginiÅŗ", + "logged_out_device": "Atsijungta nuo įrenginio", "login": "Prisijungti", + "login_disabled": "Prisijungimas neįgalintas", + "login_form_api_exception": "API iÅĄimtis. Patikrinkite serverio URL ir bandykite dar kartą.", + "login_form_back_button_text": "Atgal", + "login_form_email_hint": "jusupastas@email.com", + "login_form_endpoint_hint": "http://jusu-serverio-ip:port", + "login_form_endpoint_url": "Serverio galutinio taÅĄko URL", + "login_form_err_http": "PraÅĄome nurodyti http:// arba https://", + "login_form_err_invalid_email": "Neteisingas el. paÅĄtas", + "login_form_err_invalid_url": "Neteisingas URL", + "login_form_err_leading_whitespace": "Pradinis tarpas", + "login_form_err_trailing_whitespace": "Galinis tarpas", + "login_form_failed_get_oauth_server_config": "Klaida prisijungiant su OAuth, patikrinkite serverio URL", + "login_form_failed_get_oauth_server_disable": "Serveryje OAuth funkcija negalima", + "login_form_failed_login": "Klaida prisijungiant, patikrinkite serverio URL, el. paÅĄtą ir slaptaÅžodį", + "login_form_handshake_exception": "ÄŽvyko serverio patvirtinimo iÅĄimtis. Jei naudojate savarankiÅĄkai pasiraÅĄytą sertifikatą, nustatymuose įjunkite savarankiÅĄkai pasiraÅĄyto sertifikato palaikymą.", + "login_form_password_hint": "slaptaÅžodis", + "login_form_save_login": "Likti prisijungus", + "login_form_server_empty": "ÄŽveskite serverio URL.", + "login_form_server_error": "Nepavyko prisijungti prie serverio.", "login_has_been_disabled": "Prisijungimas iÅĄjungtas.", + "login_password_changed_error": "ÄŽvyko klaida atnaujinant jÅĢsÅŗ slaptaÅžodį", + "login_password_changed_success": "SlaptaÅžodis sėkmingai atnaujintas", "logout_all_device_confirmation": "Ar tikrai norite atsijungti iÅĄ visÅŗ įrenginiÅŗ?", "logout_this_device_confirmation": "Ar tikrai norite atsijungti iÅĄ ÅĄio prietaiso?", + "logs": "ÅŊurnalas", "longitude": "Ilguma", + "look": "IÅĄvaizda", "loop_videos": "Kartoti vaizdo įraÅĄus", + "loop_videos_description": "ÄŽgalinti automatinį vaizdo įraÅĄo rodymą iÅĄ naujo detaliÅŗ perÅžiÅĢroje.", + "main_branch_warning": "JÅĢs naudojate kÅĢrėjo versiją, mes stipriai rekomenduojame naudoti galutinę versiją!", + "main_menu": "Pagrindinis meniu", "make": "Gamintojas", + "manage_geolocation": "Tvarkyti vietovę", "manage_shared_links": "Bendrinimo nuorodÅŗ tvarkymas", "manage_sharing_with_partners": "Valdyti dalijimąsi su partneriais", "manage_the_app_settings": "Valdyti programos nustatymus", @@ -727,13 +1292,42 @@ "manage_your_devices": "Valdyti prijungtus įrenginius", "manage_your_oauth_connection": "Tvarkyti OAuth prisijungimą", "map": "ÅŊemėlapis", + "map_assets_in_bounds": "{count, plural, =0 {NuotraukÅŗ nėra} one {# nuotrauka} other {# nuotraukos}}", + "map_cannot_get_user_location": "Negalime gauti naudotojo vietovės", + "map_location_dialog_yes": "Taip", + "map_location_picker_page_use_location": "Naudoti ÅĄią vietovę", + "map_location_service_disabled_content": "Vietovės servisas turi bÅĢti įjungtas, kad rodytÅŗ elementus iÅĄ dabartinės vietovės. ÄŽjungti vietovės servisą?", + "map_location_service_disabled_title": "Vietovės servisas iÅĄjungtas", + "map_marker_for_images": "ÅŊemėlapio Åžymeklis nuotraukoms yra {city}, {country}", + "map_marker_with_image": "ÅŊemėlapio Åžymeklis su nuotrauka", + "map_no_location_permission_content": "Reikalingas vietovės leidimas, kad rodytÅŗ elementus iÅĄ dabartinės vietovės. Ar norite suteikti leidimą?", + "map_no_location_permission_title": "Vietovės leidimas atmestas", "map_settings": "ÅŊemėlapio nustatymai", + "map_settings_dark_mode": "Tamsi tema", + "map_settings_date_range_option_day": "Pastarosios 24 valandos", + "map_settings_date_range_option_days": "Pastarąsias {days} dienas", + "map_settings_date_range_option_year": "Pastarieji metai", + "map_settings_date_range_option_years": "Pastaruosius {years} metus", + "map_settings_dialog_title": "ÅŊemėlapio nustatymai", "map_settings_include_show_archived": "ÄŽtraukti archyvuotus", + "map_settings_include_show_partners": "Pridėti partneriai", + "map_settings_only_show_favorites": "Rodyti tik mėgstamiausius", + "map_settings_theme_settings": "ÅŊemėlapio tema", + "map_zoom_to_see_photos": "Atitolinkite, kad matytumėte nuotraukas", + "mark_all_as_read": "PaÅžymėti viską kaip perskaitytą", + "mark_as_read": "PaÅžymėti kaip perskaitytą", + "marked_all_as_read": "Viskas paÅžymėta kaip perskaityta", "matches": "Atitikmenys", + "matching_assets": "Atitinkantys elementai", "media_type": "Laikmenos tipas", "memories": "Atsiminimai", + "memories_all_caught_up": "Jau viskas perÅžiÅĢrėta", + "memories_check_back_tomorrow": "UÅžsukite rytoj, kad pamatytumėte daugiau prisiminimÅŗ", "memories_setting_description": "Valdyti tai, ką matote savo prisiminimuose", - "memory": "Atmintis", + "memories_start_over": "Pradėti iÅĄ naujo", + "memories_swipe_to_close": "Perbraukite į virÅĄÅŗ norėdami uÅždaryti", + "memory": "Prisiminimai", + "memory_lane_title": "PrisiminimÅŗ juosta {title}", "menu": "Meniu", "merge": "Sujungti", "merge_people": "Sujungti asmenis", @@ -743,24 +1337,40 @@ "merged_people_count": "{count, plural, one {Sujungtas # asmuo} few {Sujungti # asmenys} other {Sujungta # asmenÅŗ}}", "minimize": "SumaÅžinti", "minute": "Minutė", + "minutes": "Minutės", "missing": "TrÅĢkstami", "model": "Modelis", "month": "Mėnesis", + "monthly_title_text_date_format": "MMMM y", "more": "Daugiau", + "move": "Perkelti", "move_off_locked_folder": "IÅĄtraukti iÅĄ uÅžrakinto aplanko", "move_to_lock_folder_action_prompt": "{count} įkelta į uÅžrakintą aplanką", "move_to_locked_folder": "ÄŽtraukti į uÅžrakintą aplanką", "move_to_locked_folder_confirmation": "Å ios nuotraukos ir vaizdo įraÅĄai bus paÅĄalinti iÅĄ visÅŗ albumÅŗ ir bus matomi tik uÅžrakintame aplanke", + "moved_to_archive": "{count, plural, one {# Elementas perkeltas} few {# Elementai perkelti} other {# ElementÅŗ perkelta}} į archyvą", + "moved_to_library": "{count, plural, one {# Elementas perkeltas} few {# Elementai perkelti} other {# ElementÅŗ perkelta}} į biblioteką", "moved_to_trash": "Perkelta į ÅĄiukÅĄliadėŞę", + "multiselect_grid_edit_date_time_err_read_only": "Negalima redaguoti tik skaitomo elemento datos, praleidÅžiama", + "multiselect_grid_edit_gps_err_read_only": "Negalima redaguoti tik skaitomo elemento vietovės, praleidÅžiama", + "mute_memories": "UÅžtildyti prisiminimus", "my_albums": "Mano albumai", "name": "Vardas", "name_or_nickname": "Vardas arba slapyvardis", + "network_requirement_photos_upload": "Naudoti mobilÅŗ internetą atsarginėms nuotraukÅŗ kopijoms", + "network_requirement_videos_upload": "Naudoti mobilÅŗ internetą atsarginėms vaizdo įraÅĄÅŗ kopijoms", + "network_requirements": "Tinklo reikalavimai", + "network_requirements_updated": "Tinklo reikalavimai pakeisti, atstatoma atsarginio kopijavimo eilė", + "networking_settings": "Tinklai", + "networking_subtitle": "Tvarkyti serverio galutinio taÅĄko nustatymus", "never": "Niekada", "new_album": "Naujas albumas", "new_api_key": "Naujas API raktas", "new_password": "Naujas slaptaÅžodis", "new_person": "Naujas asmuo", + "new_pin_code": "Naujas PIN kodas", "new_pin_code_subtitle": "Tai pirmas kartas, kai naudojate uÅžrakinto aplanko funkciją. Nustatykite PIN kodą savo uÅžrakintam aplankui", + "new_timeline": "Nauja laiko juosta", "new_user_created": "Naujas naudotojas sukurtas", "new_version_available": "PRIEINAMA NAUJA VERSIJA", "newest_first": "Pirmiausia naujausi", @@ -772,32 +1382,68 @@ "no_albums_yet": "Atrodo, kad dar neturite albumÅŗ.", "no_archived_assets_message": "Suarchyvuokite nuotraukas ir vaizdo įraÅĄus, kad jie nebÅĢtÅŗ rodomi nuotraukÅŗ rodinyje", "no_assets_message": "SPUSTELĖKITE NORĖDAMI ÄŽKELTI PIRMĄJĄ NUOTRAUKĄ", + "no_assets_to_show": "Nėra rodomÅŗ elementÅŗ", + "no_cast_devices_found": "Nerasta transliavimo įrenginiÅŗ", + "no_checksum_local": "Kontrolinė suma nepasiekiama – negalima gauti vietiniÅŗ elementÅŗ", + "no_checksum_remote": "Kontrolinė suma nepasiekiama – negalima gauti nuotoliniÅŗ elementÅŗ", "no_duplicates_found": "DublikatÅŗ nerasta.", + "no_exif_info_available": "Nėra Exif informacijos", "no_explore_results_message": "ÄŽkelkite daugiau nuotraukÅŗ ir tyrinėkite savo kolekciją.", + "no_favorites_message": "Pridėti į mėgstamiausius, kad greitai rastum geriausias nuotraukas ir vaizdo įraÅĄus", "no_libraries_message": "Sukurkite iÅĄorinę biblioteką nuotraukoms ir vaizdo įraÅĄams perÅžiÅĢrėti", + "no_local_assets_found": "Nerasta jokiÅŗ vietiniÅŗ elementÅŗ su ÅĄia kontroline suma", "no_locked_photos_message": "UÅžrakintame aplanke esančios nuotraukos ir vaizdo įraÅĄai yra paslėpti ir nematomi narÅĄant ir ieÅĄkant.", "no_name": "Be vardo", - "no_results": "Nerasta", + "no_notifications": "PraneÅĄimÅŗ nėra", + "no_people_found": "IeÅĄkomÅŗ ÅžmoniÅŗ nerasta", + "no_places": "VietoviÅŗ nėra", + "no_remote_assets_found": "Nerasta jokiÅŗ nuotoliniÅŗ elementÅŗ su ÅĄia kontroline suma", + "no_results": "RezultatÅŗ nerasta", "no_results_description": "Pabandykite sinonimą arba bendresnį raktaÅžodį", + "no_shared_albums_message": "Sukurkite nuotraukÅŗ ar vaizdo įraÅĄÅŗ albumą dalinimuisi su Åžmonėmis jÅĢsÅŗ tinkle", + "no_uploads_in_progress": "Nėra vykstančiÅŗ įkėlimÅŗ", + "not_available": "Nepasiekiamas", "not_in_any_album": "Nė viename albume", - "note_apply_storage_label_to_previously_uploaded assets": "Pastaba: Priskirti Saugyklos ÅŊymą prie ankčiau įkeltÅŗ iÅĄtekliu, paleiskite ÅĄÄ¯", + "not_selected": "Nepasirinkta", + "note_apply_storage_label_to_previously_uploaded assets": "Pastaba: Priskirti Saugyklos ÅŊymą prie anksčiau įkeltÅŗ iÅĄtekliu, paleiskite ÅĄÄ¯", "notes": "Pastabos", + "nothing_here_yet": "Kol kas tuÅĄÄia", + "notification_permission_dialog_content": "PraneÅĄimÅŗ įgalinimui eikite į Nustatymus ir pasirinkite Leisti.", + "notification_permission_list_tile_content": "Suteikti leidimą praneÅĄimÅŗ įgalinimui.", + "notification_permission_list_tile_enable_button": "ÄŽgalinti praneÅĄimus", + "notification_permission_list_tile_title": "PraneÅĄimÅŗ leidimai", "notification_toggle_setting_description": "ÄŽjungti el. paÅĄto praneÅĄimus", "notifications": "PraneÅĄimai", "notifications_setting_description": "Tvarkyti praneÅĄimus", + "oauth": "OAuth", "official_immich_resources": "OficialÅĢs Immich iÅĄtekliai", "offline": "Neprisijungęs", + "offset": "Ofsetas", + "ok": "Ok", "oldest_first": "Seniausias pirmas", "on_this_device": "Å iame įrenginyje", + "onboarding": "ÄŽdarbinimas", + "onboarding_locale_description": "Pasirinkite pageidaujamą kalbą. Vėliau ją galėsite pakeisti nustatymuose.", + "onboarding_privacy_description": "Sekančios (neprivalomos) funkcijos remiasi iÅĄorinėmis paslaugomis ir gali bÅĢti bet kada iÅĄjungtos nustatymuose.", + "onboarding_server_welcome_description": "Nustatykime jÅĢsÅŗ programą su daÅžniausiai naudojamais nustatymais.", + "onboarding_theme_description": "Pasirinkite temos spalvą. Vėliau galite pasikeisti ją nustatymuose.", + "onboarding_user_welcome_description": "Pradėkime!", "onboarding_welcome_user": "Sveiki atvykę, {user}", "online": "Prisijungęs", "only_favorites": "Tik mėgstamiausi", + "open": "Atverti", + "open_in_map_view": "Atverti Åžemėlapio perÅžiÅĢroje", + "open_in_openstreetmap": "Atverti per OpenStreetMap", "open_the_search_filters": "Atidaryti paieÅĄkos filtrus", "options": "Pasirinktys", "or": "arba", + "organize_into_albums": "Sutvarkyti į albumus", + "organize_into_albums_description": "Sukelti egzistuojančias nuotraukas į albumus naudojant dabartinius sinchronizavimo nustatymus", "organize_your_library": "Tvarkykite savo biblioteką", "original": "Originalas", + "other": "Kiti", "other_devices": "Kiti įrenginiai", + "other_entities": "Kiti subjektai", "other_variables": "Kiti kintamieji", "owned": "Nuosavi", "owner": "Savininkas", @@ -805,12 +1451,27 @@ "partner_can_access": "{partner} gali naudotis", "partner_can_access_assets": "Visos jÅĢsÅŗ nuotraukos ir vaizdo įraÅĄai, iÅĄskyrus archyvuotus ir iÅĄtrintus", "partner_can_access_location": "Vieta, kurioje darytos nuotraukos", + "partner_list_user_photos": "{user} nuotraukos", + "partner_list_view_all": "ÅŊiÅĢrėti viską", + "partner_page_empty_message": "JÅĢsÅŗ nuotraukomis dar nesidalinama su jokiu partneriu.", + "partner_page_no_more_users": "Nėra daugiau naudotojÅŗ pridėjimui", + "partner_page_partner_add_failed": "Nepavyko pridėti partnerio", + "partner_page_select_partner": "Pasirinkite partnerį", + "partner_page_shared_to_title": "Dalinamasi su", + "partner_page_stop_sharing_content": "{partner} daugiau nebegalės pasiekti jÅĢsÅŗ nuotraukÅŗ.", + "partner_sharing": "Dalinimasis su partneriu", "partners": "Partneriai", "password": "SlaptaÅžodis", "password_does_not_match": "SlaptaÅžodis nesutampa", "password_required": "Reikalingas slaptaÅžodis", "password_reset_success": "SlaptaÅžodis sėkmingai atkurtas", + "past_durations": { + "days": "Per {days, plural, one {pastarąją dieną} few {# pastarąsias dienas} other {# pastarÅŗjÅŗ dienÅŗ}}", + "hours": "Per {hours, plural, one {pastarąją valandą} few{# pastarąsias valandas} other {# pastarÅŗjÅŗ valandÅŗ}}", + "years": "Per {years, plural, one {pastaruosius metus} few{# pastaruosius metus} other {# pastarÅŗjÅŗ metÅŗ}}" + }, "path": "Kelias", + "pattern": "RaÅĄtas", "pause": "Sustabdyti", "pause_memories": "Pristabdyti atsiminimus", "paused": "Sustabdyta", @@ -819,27 +1480,73 @@ "people_edits_count": "{count, plural, one {Redaguotas # asmuo} few {Redaguoti # asmenys} other {Redaguota # asmenÅŗ}}", "people_feature_description": "PerÅžiÅĢrėkite nuotraukas ir vaizdo įraÅĄus sugrupuotus pagal asmenis", "people_sidebar_description": "Rodyti asmenÅŗ rodinio nuorodą ÅĄoninėje juostoje", + "permanent_deletion_warning": "IÅĄtrynimo visam laikui perspėjimas", + "permanent_deletion_warning_setting_description": "Rodyti perspėjimą kai elementas iÅĄtrinamas visam laikui", "permanently_delete": "IÅĄtrinti visam laikui", "permanently_delete_assets_count": "Visam laikui iÅĄtrinti {count, plural, one {# elementą} few {# elementus} other {# elementÅŗ}}", + "permanently_delete_assets_prompt": "Ar tikrai norite visam laikui iÅĄtrinti {count, plural, one {ÅĄitą elementą?} few {ÅĄituos # elementus?} other {ÅĄitÅŗ # elementÅŗ?}} Tuo pačiu {count, plural, one {jis bus paÅĄalintas} other {jie bus paÅĄalinti}} iÅĄ albumo.", + "permanently_deleted_asset": "VisiÅĄkai iÅĄtrinti elementai", "permanently_deleted_assets_count": "Visam laikui {count, plural, one {iÅĄtrintas # elementas} few {iÅĄtrinti # elementai} other {iÅĄtrinta # elementÅŗ}}", + "permission": "Leidimas", + "permission_empty": "JÅĢsÅŗ leidimas neturėtÅŗ bÅĢti tuÅĄÄias", + "permission_onboarding_back": "Atgal", + "permission_onboarding_continue_anyway": "Vis tiek tęsti", + "permission_onboarding_get_started": "Pradėkite", + "permission_onboarding_go_to_settings": "Eiti į nustatymus", + "permission_onboarding_permission_denied": "Leidimas nesuteiktas. Norėdami naudoti Immich, suteikite nuotraukÅŗ ir vaizdo įraÅĄÅŗ leidimus nustatymuose.", + "permission_onboarding_permission_granted": "Leidimas suteiktas! jÅĢs pasiruoÅĄÄ™.", + "permission_onboarding_permission_limited": "Leidimai apriboti. Norėdami leisti Immich kurti atsargines kopijas ir tvarkyti visą jÅĢsÅŗ galerijos kolekciją, suteikite nuotraukÅŗ ir vaizdo įraÅĄÅŗ leidimus nustatymuose.", + "permission_onboarding_request": "Immich reikalingas leidimas perÅžiÅĢrėti jÅĢsÅŗ nuotraukas ir vaizdo įraÅĄus.", + "person": "Asmuo", + "person_age_months": "{months, plural, one {# mėnesio} other {# mėnesiÅŗ}} amÅžiaus", + "person_age_year_months": "1 metÅŗ ir {months, plural, one {# mėnesio} other {# mėnesiÅŗ}} amÅžiaus", + "person_age_years": "{years, plural, other {# metÅŗ}} amÅžiaus", + "person_birthdate": "Gimė {date}", + "person_hidden": "{name}{hidden, select, true { (paslėptas)} other {}}", + "photo_shared_all_users": "PanaÅĄu, kad savo nuotraukomis pasidalijote su visais naudotojais arba neturite naudotojÅŗ, su kuriais galėtumėte jomis pasidalyti.", "photos": "Nuotraukos", "photos_and_videos": "Nuotraukos ir vaizdo įraÅĄai", "photos_count": "{count, plural, one {{count, number} nuotrauka} few {{count, number} nuotraukos} other {{count, number} nuotraukÅŗ}}", "photos_from_previous_years": "AnkstesniÅŗ metÅŗ nuotraukos", + "pick_a_location": "IÅĄsirinkite vietovę", + "pin_code_changed_successfully": "PIN kodas pakeistas sėkmingai", + "pin_code_reset_successfully": "PIN kodas sėkmingai atstatytas", + "pin_code_setup_successfully": "PIN kodas sėkmingai nustatytas", + "pin_verification": "PIN kodo patvirtinimas", "place": "Vieta", "places": "Vietos", + "places_count": "{count, plural, one {{count, number} Vieta} few{{count, number} Vietos} other {{count, number} VietÅŗ}}", + "play": "Paleisti", "play_memories": "Leisti atsiminimus", + "play_motion_photo": "Rodyti judančias nuotraukas", + "play_or_pause_video": "Rodyti arba sustabdyti vaizdo įraÅĄÄ…", + "please_auth_to_access": "PraÅĄome patvirtinti prisijungimą", + "port": "Portas", + "preferences_settings_subtitle": "Tvarkyti programos nuostatas", + "preferences_settings_title": "Nuostatos", + "preset": "Å ablonas", + "preview": "PerÅžiÅĢra", + "previous": "Buvęs", + "previous_memory": "Buvęs prisiminimas", + "previous_or_next_day": "Dieną pirmyn/atgal", + "previous_or_next_month": "Mėnesį pirmyn/atgal", + "previous_or_next_photo": "Nuotrauką pirmyn/atgal", + "previous_or_next_year": "Metus pirmyn/atgal", + "primary": "Pirminis", + "privacy": "Privatumas", "profile": "Profilis", "profile_drawer_app_logs": "Logai", "profile_drawer_client_out_of_date_major": "Mobili aplikacija jau pasenusios versijos. PraÅĄome atsinaujinti į paskutinę didÅžiąją versiją.", "profile_drawer_client_out_of_date_minor": "Mobili aplikacija jau pasenusios versijos. PraÅĄome atsinaujinti į paskutinę maŞąją versiją.", "profile_drawer_client_server_up_to_date": "Klientas ir Serveris yra atnaujinti", "profile_drawer_github": "GitHub", + "profile_drawer_readonly_mode": "Tik skaitymo rÄ—Åžimas įgalintas. Ilgai paspauskite vartotojo ikoną iÅĄÄ—jimui.", "profile_drawer_server_out_of_date_major": "Serveris jau yra pasenusios versijos. PraÅĄome atsinaujinti į paskutinę didÅžiąją versiją.", "profile_drawer_server_out_of_date_minor": "Serveris jau yra pasenusios versijos. PraÅĄome atsinaujinti į paskutinę maŞąją versiją.", "profile_image_of_user": "{user} profilio nuotrauka", "profile_picture_set": "Profilio nuotrauka nustatyta.", "public_album": "VieÅĄas albumas", + "public_share": "VieÅĄas dilinimasis", "purchase_account_info": "Rėmėjas", "purchase_activated_subtitle": "Dėkojame, kad remiate Immich ir atviro kodo programinę įrangą", "purchase_activated_time": "Suaktyvinta {date}", @@ -854,12 +1561,13 @@ "purchase_failed_activation": "Nepavyko suaktyvinti! Patikrinkite el. paÅĄtą, ar turite teisingo produkto koda!", "purchase_individual_description_1": "Asmeniui", "purchase_individual_description_2": "Rėmėjo statusas", + "purchase_individual_title": "Asmeninis", "purchase_input_suggestion": "Turite produkto raktą? ÄŽveskite jį Åžemiau", "purchase_license_subtitle": "ÄŽsigykite „Immich“, kad palaikytumėte tolesnį paslaugos vystymą", "purchase_lifetime_description": "Pirkimas visam gyvenimui", "purchase_option_title": "PIRKIMO PASIRINKIMAS", "purchase_panel_info_1": "„Immich“ kÅĢrimas uÅžima daug laiko ir pastangÅŗ, o visą darbo dieną dirba inÅžinieriai, kad jis bÅĢtÅŗ kuo geresnis. MÅĢsÅŗ misija yra, kad atvirojo kodo programinė įranga ir etiÅĄka verslo praktika taptÅŗ tvariu kÅĢrėjÅŗ pajamÅŗ ÅĄaltiniu ir sukurtÅŗ privatumą gerbiančią ekosistemą su realiomis alternatyvomis iÅĄnaudojamoms debesijos paslaugoms.", - "purchase_panel_info_2": "Kadangi esame įsipareigoję nepridėti mokamÅŗ sienÅŗ, ÅĄis pirkinys nesuteiks jums jokiÅŗ papildomÅŗ „Immich“ funkcijÅŗ. Mes tikime, kad tokie naudotojai kaip jÅĢs palaikys nuolatinį „Immich“ vystymąsi.", + "purchase_panel_info_2": "Kadangi esame įsipareigoję nepridėti mokamÅŗ sienÅŗ, ÅĄis pirkinys nesuteiks jums jokiÅŗ papildomÅŗ Immich funkcijÅŗ. Mes tikime, kad tokie naudotojai kaip jÅĢs palaikys nuolatinį Immich vystymąsi.", "purchase_panel_title": "Palaikykite projektą", "purchase_per_server": "Vienam serveriui", "purchase_per_user": "Vienam naudotojui", @@ -998,7 +1706,11 @@ "setting_image_viewer_preview_title": "UÅžkrauti perÅžiÅĢros nuotrauką", "setting_image_viewer_title": "Nuotraukos", "setting_languages_apply": "Pritaikyti", + "setting_notifications_notify_failures_grace_period": "Informuoti apie foninio atsarginio kopijavimo nesėkmes: {duration}", + "setting_notifications_notify_hours": "{count} valandÅŗ", + "setting_notifications_notify_minutes": "{count} minučiÅŗ", "setting_notifications_notify_never": "niekada", + "setting_notifications_notify_seconds": "{count} sekundÅžiÅŗ", "setting_notifications_single_progress_subtitle": "Detali įkėlimo progreso informacija kiekvienam elementui", "settings": "Nustatymai", "settings_require_restart": "PraÅĄome perkrauti Immich, siekiant pritaikyti ÅĄÄ¯ nustatymą", @@ -1006,13 +1718,29 @@ "setup_pin_code": "Nustatyti PIN kodą", "share": "Dalintis", "share_add_photos": "ÄŽtraukti nuotraukÅŗ", + "share_assets_selected": "{count} paÅžymėta", "share_dialog_preparing": "RuoÅĄiama...", "share_link": "Bendrinti nuorodą", "shared": "Bendrinami", "shared_by_user": "Bendrina {user}", "shared_by_you": "Bendrinama jÅĢsÅŗ", "shared_from_partner": "Nuotraukos iÅĄ {partner}", + "shared_intent_upload_button_progress_text": "{current} / {total} ÄŽkelta", "shared_link_clipboard_copied_massage": "Nukopijuota į iÅĄkarpinę", + "shared_link_clipboard_text": "Nuoroda: {link}\nSlaptaÅžodis: {password}", + "shared_link_edit_expire_after_option_days": "{count} dienÅŗ", + "shared_link_edit_expire_after_option_hours": "{count} valandÅŗ", + "shared_link_edit_expire_after_option_minutes": "{count} minučiÅŗ", + "shared_link_edit_expire_after_option_months": "{count} mėnesiÅŗ", + "shared_link_edit_expire_after_option_year": "{count} metÅŗ", + "shared_link_expires_day": "Galiojimas baigsis uÅž {count} dienos", + "shared_link_expires_days": "Galiojimas baigsis uÅž {count} dienÅŗ", + "shared_link_expires_hour": "Galiojimas baigsis uÅž {count} valandos", + "shared_link_expires_hours": "Galiojimas baigsis uÅž {count} valandÅŗ", + "shared_link_expires_minute": "Galiojimas baigsis uÅž {count} minutės", + "shared_link_expires_minutes": "Galiojimas baigsis uÅž {count} minučiÅŗ", + "shared_link_expires_second": "Galiojimas baigsis uÅž {count} sekundės", + "shared_link_expires_seconds": "Galiojimas baigsis uÅž {count} sekundÅžiÅŗ", "shared_link_options": "Bendrinimo nuorodos parametrai", "shared_links": "Bendrinimo nuorodos", "shared_photos_and_videos_count": "{assetCount, plural, one {# bendrinama nuotrauka ir vaizdo įraÅĄas} few {# bendrinamos nuotraukos ir vaizdo įraÅĄai} other {# bendrinamÅŗ nuotraukÅŗ ir vaizdo įraÅĄÅŗ}}", @@ -1092,6 +1820,7 @@ "template": "Å ablonas", "theme": "Tema", "theme_selection": "Temos pasirinkimas", + "theme_setting_asset_list_tiles_per_row_title": "ElementÅŗ per eilutę ({count})", "theme_setting_primary_color_title": "Pagrindinė spalva", "theme_setting_system_primary_color_title": "Naudoti sistemos spalvą", "theme_setting_system_theme_switch": "Automatinė (Naudoti sistemos nustatymus)", @@ -1110,8 +1839,10 @@ "trash_no_results_message": "ÄŽ ÅĄiukÅĄliadėŞę perkeltos nuotraukos ir vaizdo įraÅĄai bus rodomi čia.", "trash_page_delete_all": "IÅĄtrinti Visus", "trash_page_empty_trash_dialog_content": "Ar norite iÅĄtrinti iÅĄmestus elementus? Å ie elementai bus visam laikui paÅĄalinti iÅĄ Immich", + "trash_page_info": "Å iukÅĄliadėŞės elementai bus galutinai iÅĄtrinti uÅž {days} dienÅŗ", "trash_page_no_assets": "Nėra iÅĄmestÅŗ elementÅŗ", "trash_page_restore_all": "Atkurti Visus", + "trash_page_title": "Å iukÅĄliÅŗ ({count})", "trashed_items_will_be_permanently_deleted_after": "ÄŽ ÅĄiukÅĄliadėŞę perkelti elementai bus visam laikui iÅĄtrinti po {days, plural, one {# dienos} other {# dienÅŗ}}.", "type": "Tipas", "unarchive": "IÅĄarchyvuoti", @@ -1146,7 +1877,8 @@ "upload_success": "ÄŽkėlimas pavyko, norėdami pamatyti naujai įkeltus elementus perkraukite puslapį.", "upload_to_immich": "ÄŽkelti į Immich ({count})", "uploading": "ÄŽkeliama", - "usage": "Naudojymas", + "url": "URL", + "usage": "Naudojimas", "use_biometric": "Naudoti biometriją", "use_current_connection": "naudoti dabartinį ryÅĄÄ¯", "user": "Naudotojas", diff --git a/i18n/lv.json b/i18n/lv.json index 909c2a05d5..053a156a17 100644 --- a/i18n/lv.json +++ b/i18n/lv.json @@ -23,15 +23,17 @@ "add_partner": "Pievienot partneri", "add_path": "Pievienot ceÄŧu", "add_photos": "Pievienot fotoattēlus", - "add_tag": "Pievienot AtzÄĢmi", + "add_tag": "Pievienot atzÄĢmi", "add_to": "Pievienotâ€Ļ", "add_to_album": "Pievienot albumam", "add_to_album_bottom_sheet_added": "Pievienots {album}", "add_to_album_bottom_sheet_already_exists": "Jau pievienots {album}", + "add_to_album_bottom_sheet_some_local_assets": "DaÅžus lokālos failus albumam nevarēja pievienot", "add_to_album_toggle": "Pārslēgt izvēli {album}", "add_to_albums": "Pievienot albumiem", "add_to_albums_count": "Pievienot albumiem ({count})", "add_to_shared_album": "Pievienot koplietotam albumam", + "add_upload_to_stack": "Pievienot augÅĄupielādi kaudzei", "add_url": "Pievienot URL", "added_to_archive": "Pievienots arhÄĢvam", "added_to_favorites": "Pievienots izlasei", @@ -44,14 +46,19 @@ "authentication_settings_description": "ParoÄŧu, OAuth un citu autentifikācijas iestatÄĢjumu pārvaldÄĢba", "authentication_settings_disable_all": "Vai tieÅĄÄm vēlaties atspējot visas pieteikÅĄanās metodes? PieteikÅĄanās tiks pilnÄĢbā atspējota.", "authentication_settings_reenable": "Lai atkārtoti iespējotu, izmantojiet Servera Komandu.", - "background_task_job": "Fona Uzdevumi", - "backup_database": "Izveidot datu bāzes izgāztuvi", - "backup_database_enable_description": "Iespējot datu bāzes izgāztuvi", - "backup_keep_last_amount": "IepriekÅĄÄ“jo izgāztuvju daudzums, kas jāsaglabā", - "backup_onboarding_1_description": "ārpussaites kopÄ“ÅĄana mākonÄĢ vai citā fiziskā vietā.", - "backup_onboarding_2_description": "lokālas kopijas citās ierÄĢcēs. Å is iekÄŧauj galvenos failus kā arÄĢ dublētu kōpiju ar tiem failiem lokāli.", + "background_task_job": "Fona uzdevumi", + "backup_database": "Izveidot datu bāzes izrakstu", + "backup_database_enable_description": "Iespējot datu bāzes izrakstus", + "backup_keep_last_amount": "IepriekÅĄÄ“jo izrakstu daudzums, kas jāsaglabā", + "backup_onboarding_1_description": "ārēja kopija mākonÄĢ vai citā fiziskā atraÅĄanās vietā.", + "backup_onboarding_2_description": "lokālās kopijas citās ierÄĢcēs. Tas ietver galvenos failus un ÅĄo failu lokālo rezerves kopiju.", + "backup_onboarding_3_description": "kopiju skaits, ieskaitot oriÄŖinālos failus. Tas ietver 1 ārējo kopiju un 2 lokālās kopijas.", + "backup_onboarding_description": "Lai aizsargātu savus datus, ieteicams izmantot 3-2-1 rezerves kopiju stratēĪiju. Lai nodroÅĄinātu visaptveroÅĄu dublÄ“ÅĄanas risinājumu, vajadzētu veidot kopijas saviem augÅĄupielādētajiem fotoattēliem/videoklipiem, kā arÄĢ Immich datubāzei.", + "backup_onboarding_footer": "Lai iegÅĢtu vairāk informācijas par Immich rezerves kopiju veidoÅĄanu, lÅĢdzu, apskatiet dokumentāciju.", + "backup_onboarding_parts_title": "3-2-1 rezerves kopija ietver:", "backup_onboarding_title": "Rezerves kopijas", - "backup_settings_description": "Datubāzes dublÄ“ÅĄanas iestatÄĢjumu pārvaldÄĢba", + "backup_settings": "Datubāzes izrakstu iestatÄĢjumi", + "backup_settings_description": "Datubāzes izrakstu iestatÄĢjumu pārvaldÄĢba", "cleared_jobs": "NotÄĢrÄĢti uzdevumi priekÅĄ: {job}", "config_set_by_file": "Konfigurāciju paÅĄlaik iestata konfigurācijas fails", "confirm_delete_library": "Vai tieÅĄÄm vēlaties dzēst {library} bibliotēku?", @@ -60,52 +67,78 @@ "confirm_user_password_reset": "Vai tieÅĄÄm vēlaties atiestatÄĢt lietotāja {user} paroli?", "create_job": "Izveidot uzdevumu", "cron_expression": "Cron izteiksme", + "cron_expression_description": "Iestatiet skenÄ“ÅĄanas intervālu, izmantojot cron formātu. Papildu informācijai skatiet, piemēram, Crontab Guru", + "cron_expression_presets": "Cron izteiksmju sagataves", "disable_login": "Atspējot pieteikÅĄanos", - "duplicate_detection_job_description": "Palaidiet maÅĄÄĢnmācÄĢÅĄanos uz failiem, lai noteiktu lÄĢdzÄĢgus attēlus. PaÄŧaujas uz viedo meklÄ“ÅĄanu", + "duplicate_detection_job_description": "Analizēt failus ar maÅĄÄĢnmācÄĢÅĄanos, lai noteiktu lÄĢdzÄĢgus attēlus. Å ÄĢ funkcija izmanto viedo meklÄ“ÅĄanu", "external_library_management": "Ārējo bibliotēku pārvaldÄĢba", "face_detection": "Seju noteikÅĄana", + "face_detection_description": "AtpazÄĢt attēlos sejas, izmantojot maÅĄÄĢnmācÄĢÅĄanos. Video gadÄĢjumā tiek ņemta vērā tikai sÄĢktēls. \"Atsvaidzināt\" atkārtoti apstrādā visus attēlus. \"AtiestatÄĢt\" izdzÄ“ÅĄ visus paÅĄreizējos seju datus. \"TrÅĢkstoÅĄie\" ierindo attēlus, kas vēl nav apstrādāti. Pēc seju noteikÅĄanas pabeigÅĄanas atrastās sejas tiek ierindotas seju atpazÄĢÅĄanai, grupējot tās pēc esoÅĄas vai jauns personas.", + "facial_recognition_job_description": "Grupēt atpazÄĢtās sejas pēc cilvēkiem. Å is solis tiek veikts pēc seju noteikÅĄanas pabeigÅĄanas. \"AtiestatÄĢt\" atkārtoti sagrupē visas sejas. \"TrÅĢkstoÅĄie\" ierindo sejas, kurām nav pieÅĄÄˇirta persona.", + "force_delete_user_warning": "BRÄĒDINĀJUMS: Tas uzreiz izdzēsÄĢs lietotāju ar visiem failiem. Å o darbÄĢbu nevar atcelt, un failus nevarēs atgÅĢt.", "image_format": "Formāts", "image_format_description": "WebP veido mazākus failus nekā JPEG, taču to kodÄ“ÅĄana ir lēnāka.", - "image_fullsize_enabled_description": "Äĸenerēt pilna izmēra attēlu formātiem, kas nav piemēroti izmantoÅĄanai tÄĢmeklÄĢ. Ja ir iespējota opcija \"PriekÅĄroka iegultajam priekÅĄskatÄĢjumam\", tiks izmantoti iegultie priekÅĄskatÄĢjumi bez konvertÄ“ÅĄanas. Neietekmē tÄĢmeklim draudzÄĢgus formātus, piemēram, JPEG.", + "image_fullsize_description": "Pilnizmēra attēls ar noņemtiem metadatiem, ko izmanto, kad attēls ir tuvināts", + "image_fullsize_enabled": "Iespējot pilnizmēra attēlu ÄŖenerÄ“ÅĄanu", + "image_fullsize_enabled_description": "Äĸenerēt pilnizmēra attēlu formātiem, kas nav piemēroti izmantoÅĄanai tÄĢmeklÄĢ. Ja ir iespējota opcija \"PriekÅĄroka iegultajam priekÅĄskatÄĢjumam\", tiks izmantoti iegultie priekÅĄskatÄĢjumi bez konvertÄ“ÅĄanas. Neietekmē tÄĢmeklim draudzÄĢgus formātus, piemēram, JPEG.", "image_fullsize_quality_description": "Pilnizmēra attēlu kvalitāte no 1-100. Augstāka vērtÄĢba dos labāku kvalitāti, taču faili bÅĢs lielāka izmēra.", "image_fullsize_title": "Pilnizmēra attēlu iestatÄĢjumi", "image_prefer_embedded_preview": "PriekÅĄroka iegultajam priekÅĄskatÄĢjumam", "image_prefer_embedded_preview_setting_description": "Izmanto RAW fotoattēlos iestrādātos priekÅĄskatÄĢjumus, ja tādi ir pieejami, kā ievades datus attēlu apstrādei. Tādējādi daÅžiem attēliem var iegÅĢt precÄĢzākas krāsas, taču priekÅĄskatÄĢjuma kvalitāte ir atkarÄĢga no fotokameras un attēlam var bÅĢt vairāk saspieÅĄanas artefaktu.", + "image_prefer_wide_gamut": "Dot priekÅĄroku plaÅĄai krāsu gammai", "image_prefer_wide_gamut_setting_description": "SÄĢktēliem izmanto Display P3. Tas labāk saglabā attēlu dzÄĢvÄĢgumu ar plaÅĄu krāsu gammu, bet attēli var izskatÄĢties atÅĄÄˇirÄĢgi vecās ierÄĢcēs ar vecu pārlÅĢka versiju. sRGB attēli tiek saglabāti kā sRGB, lai izvairÄĢtos no krāsu izmaiņām.", + "image_preview_quality_description": "PriekÅĄskatÄĢjuma kvalitāte no 1 lÄĢdz 100. Augstāka kvalitāte ir labāka, bet veido lielākus failus un var samazināt lietotnes reaÄŖÄ“ÅĄanas ātrumu. Zemas vērtÄĢbas iestatÄĢÅĄana var ietekmēt maÅĄÄĢnmācÄĢÅĄanās kvalitāti.", "image_preview_title": "PriekÅĄskatÄĢjuma iestatÄĢjumi", "image_quality": "Kvalitāte", "image_resolution": "IzÅĄÄˇirtspēja", + "image_resolution_description": "Augstāka izÅĄÄˇirtspēja Äŧauj saglabāt vairāk detaÄŧu, taču kodÄ“ÅĄana aizņem vairāk laika, failu izmērs ir lielāks un var samazināties lietotnes reaÄŖÄ“ÅĄanas ātrums.", "image_settings": "Attēlu iestatÄĢjumi", "image_settings_description": "Äĸenerēto attēlu kvalitātes un izÅĄÄˇirtspējas pārvaldÄĢba", "image_thumbnail_description": "Neliels sÄĢktēls bez metadatiem, ko izmanto, lai apskatÄĢtu vairākus fotoattēlus, piemēram, galvenajā laika skalā", + "image_thumbnail_quality_description": "SÄĢktēlu kvalitāte no 1 lÄĢdz 100. Augstāka kvalitāte ir labāka, bet veido lielākus failus un var samazināt lietotnes reaÄŖÄ“ÅĄanas ātrumu.", "image_thumbnail_title": "SÄĢktēlu iestatÄĢjumi", "job_concurrency": "{job} vienlaicÄĢgi", "job_created": "Uzdevums izveidots", + "job_not_concurrency_safe": "Å is uzdevums nav droÅĄs vienlaicÄĢgai izpildei.", "job_settings": "Uzdevumu iestatÄĢjumi", "job_settings_description": "Uzdevumu izpildes vienlaicÄĢguma pārvaldÄĢba", "job_status": "Uzdevumu statuss", "library_created": "Izveidoja bibliotēku: {library}", "library_deleted": "Bibliotēka dzēsta", + "library_import_path_description": "Norādi importējamo mapi. Å ÄĢ mape un tās apakÅĄmapes tiks pārbaudÄĢta, lai atrastu attēlus un videoklipus.", "library_scanning": "Periodiska skenÄ“ÅĄana", "library_scanning_description": "Konfigurē periodisku bibliotēku skenÄ“ÅĄanu", "library_scanning_enable_description": "Iespējot periodisku bibliotēku skenÄ“ÅĄanu", - "library_settings": "Ārējā bibliotēka", + "library_settings": "Ārējās bibliotēkas", "library_settings_description": "Ārējo bibliotēku iestatÄĢjumu pārvaldÄĢba", + "library_tasks_description": "PārbaudÄĢt ārējās bibliotēkas, lai atrastu jaunus un/vai mainÄĢtus failus", + "library_watching_enable_description": "UzraudzÄĢt ārējo bibliotēku failu izmaiņas", "library_watching_settings": "Bibliotēku uzraudzÄĢÅĄana (EKSPERIMENTĀLA)", "library_watching_settings_description": "Automātiski uzraudzÄĢt, vai ir mainÄĢti faili", + "machine_learning_availability_checks": "PieejamÄĢbas pārbaudes", + "machine_learning_availability_checks_enabled": "Iespējot pieejamÄĢbas pārbaudes", "machine_learning_clip_model": "CLIP modelis", "machine_learning_duplicate_detection": "Dublikātu noteikÅĄana", + "machine_learning_duplicate_detection_enabled": "Iespējot dublikātu noteikÅĄanu", + "machine_learning_duplicate_detection_enabled_description": "Ja ÅĄÄĢ funkcija ir atspējota, joprojām tiks izlaisti identiski faili.", + "machine_learning_enabled": "Iespējot maÅĄÄĢnmācÄĢÅĄanos", + "machine_learning_enabled_description": "Ja funkcija ir atspējota, tiks atspējotas visas ML funkcijas neatkarÄĢgi no zemāk esoÅĄajiem iestatÄĢjumiem.", "machine_learning_facial_recognition": "Seju atpazÄĢÅĄana", "machine_learning_facial_recognition_model": "Seju atpazÄĢÅĄanas modelis", + "machine_learning_facial_recognition_model_description": "ModeÄŧi ir uzskaitÄĢti pēc to izmēra dilstoÅĄÄ secÄĢbā. Lielāki modeÄŧi ir lēnāki un izmanto vairāk atmiņas, bet nodroÅĄina labākus rezultātus. Ņem vērā, ka, mainot modeli, ir atkārtoti jāpalaiÅž sejas atpazÄĢÅĄanas uzdevums visiem attēliem.", + "machine_learning_facial_recognition_setting": "Iespējot seju atpazÄĢÅĄanu", "machine_learning_settings": "MaÅĄÄĢnmācÄĢÅĄanās iestatÄĢjumi", "machine_learning_settings_description": "MaÅĄÄĢnmācÄĢÅĄanās funkciju un iestatÄĢjumu pārvaldÄĢba", "machine_learning_smart_search": "Viedā meklÄ“ÅĄana", + "machine_learning_smart_search_enabled": "Iespējot viedo meklÄ“ÅĄanu", + "machine_learning_smart_search_enabled_description": "Ja funkcija ir atspējota, attēli netiks kodēti viedai meklÄ“ÅĄanai.", "machine_learning_url_description": "MaÅĄÄĢnmācÄĢÅĄanās servera URL. Ja ir norādÄĢts vairāk nekā viens URL, katrs serveris, sākot no pirmā lÄĢdz pēdējam, tiks pārbaudÄĢts pa vienam, lÄĢdz kāds no tiem atbildēs veiksmÄĢgi. Serveri, kas neatbild, tiks ÄĢslaicÄĢgi ignorēti, lÄĢdz tie atkal bÅĢs pieejami tieÅĄsaistē.", "manage_concurrency": "VienlaicÄĢgas darbÄĢbas pārvaldÄĢba", "manage_log_settings": "ÅŊurnāla iestatÄĢjumu pārvaldÄĢba", "map_dark_style": "TumÅĄais stils", "map_gps_settings": "Kartes un GPS iestatÄĢjumi", "map_gps_settings_description": "KarÅĄu un GPS (apgrieztās ÄŖeokodÄ“ÅĄanas) iestatÄĢjumu pārvaldÄĢba", + "map_implications": "Kartes funkcija izmanto ārējo kartes fragmentu pakalpojumu (tiles.immich.cloud)", "map_light_style": "GaiÅĄais stils", "map_manage_reverse_geocoding_settings": "Reversās ÄŖeokodÄ“ÅĄanas iestatÄĢjumu pārvaldÄĢba", "map_reverse_geocoding": "Reversā ÄŖeokodÄ“ÅĄana", @@ -113,10 +146,15 @@ "map_settings": "Karte", "map_settings_description": "Kartes iestatÄĢjumu pārvaldÄĢba", "map_style_description": "URL uz style.json kartes tēmu", + "memory_generate_job": "Atmiņu ÄŖenerÄ“ÅĄana", "metadata_extraction_job": "Metadatu iegÅĢÅĄana", + "metadata_extraction_job_description": "iegÅĢt metadatu informāciju no katra faila, piemēram, GPS, sejas un izÅĄÄˇirtspēju", + "metadata_faces_import_setting": "Iespējot seju importÄ“ÅĄanu", + "metadata_faces_import_setting_description": "Importēt sejas no attēla EXIF datiem un blakusfailiem", "metadata_settings": "Metadatu iestatÄĢjumi", "metadata_settings_description": "Metadatu iestatÄĢjumu pārvaldÄĢba", "migration_job": "Migrācija", + "migration_job_description": "Pārvietot failu un seju sÄĢktēlus uz jaunāko mapju struktÅĢru", "nightly_tasks_cluster_faces_setting_description": "Veikt sejas atpazÄĢÅĄanu jaunatklātajām sejām", "nightly_tasks_cluster_new_faces_setting": "Sagrupēt jaunās sejas", "nightly_tasks_database_cleanup_setting": "Datubāzes apkopes uzdevumi", @@ -133,6 +171,7 @@ "nightly_tasks_sync_quota_usage_setting_description": "Pārrēķināt lietotāja uzglabÄÅĄanas kvotu, pamatojoties uz paÅĄreizējo izmantoÅĄanu", "no_paths_added": "Nav pievienots neviens ceÄŧÅĄ", "no_pattern_added": "Nav pievienots neviens izslēgÅĄanas ÅĄablons", + "note_apply_storage_label_previous_assets": "PiezÄĢme: Lai piemērotu glabātuves nosaukumu iepriekÅĄ augÅĄupielādētiem failiem, izpildiet", "note_cannot_be_changed_later": "PIEZÄĒME: Vēlāk to vairs nevar mainÄĢt!", "notification_email_from_address": "No adreses", "notification_email_from_address_description": "SÅĢtÄĢtāja e-pasta adrese, piemēram: “Immich foto serveris ”", @@ -140,7 +179,9 @@ "notification_email_ignore_certificate_errors_description": "Ignorēt TLS sertifikāta apstiprinÄÅĄanas kÄŧÅĢdas (nav ieteicams)", "notification_email_port_description": "e-pasta servera ports (piemēram, 25, 465 vai 587)", "notification_email_sent_test_email_button": "NosÅĢtÄĢt testa e-pastu un saglabāt", + "notification_email_setting_description": "E-pasta paziņojumu sÅĢtÄĢÅĄanas iestatÄĢjumi", "notification_email_test_email": "NosÅĢtÄĢt testa e-pastu", + "notification_email_test_email_failed": "Neizdevās nosÅĢtÄĢt pārbaudes e-pastu, pārbaudi ievadÄĢtās vērtÄĢbas", "notification_email_test_email_sent": "Uz {email} ir nosÅĢtÄĢts testa e-pasts. LÅĢdzu, pārbaudi savu iesÅĢtni.", "notification_settings": "Paziņojumu iestatÄĢjumi", "notification_settings_description": "Paziņojumu iestatÄĢjumu, tostarp e-pasta, pārvaldÄĢba", @@ -152,6 +193,8 @@ "oauth_enable_description": "Pieslēgties ar OAuth", "oauth_settings": "OAuth", "oauth_settings_description": "OAuth pieteikÅĄanās iestatÄĢjumu pārvaldÄĢba", + "oauth_storage_label_claim": "Glabātuves nosaukuma pieteikums", + "oauth_storage_label_claim_description": "Automātiski iestatÄĢt lietotāja glabātuves nosaukumu uz ÅĄÄĢ pieteikuma vērtÄĢbu.", "oauth_storage_quota_default": "Noklusējuma krātuves kvota (GiB)", "password_enable_description": "PieteikÅĄanās ar e-pasta adresi un paroli", "password_settings": "PieteikÅĄanās ar paroli", @@ -175,11 +218,18 @@ "server_settings_description": "Servera iestatÄĢjumu pārvaldÄĢba", "server_welcome_message": "Sveiciena ziņa", "server_welcome_message_description": "Ziņojums, kas tiek parādÄĢts pieslēgÅĄanās lapā.", + "sidecar_job": "Blakusfailu metadati", + "sidecar_job_description": "Atklāt vai sinhronizēt blakusfailu metadatus no failu sistēmas", + "slideshow_duration_description": "Katra attēla rādÄĢÅĄanas ilgums sekundēs", + "smart_search_job_description": "Analizēt failus ar maÅĄÄĢnmācÄĢÅĄanos lai sagatavotu datus viedajai meklÄ“ÅĄanai", "storage_template_date_time_sample": "Laika paraugs {date}", "storage_template_migration": "Krātuves veidņu migrācija", - "storage_template_migration_job": "Krātuves veidņu migrācijas uzdevums", + "storage_template_migration_description": "Piemēro paÅĄreizējo {template} iepriekÅĄ augÅĄupielādētajiem failiem", + "storage_template_migration_info": "Krātuves veidne pārveidos visus failu paplaÅĄinājumus uz mazajiem burtiem. Veidnes izmaiņas attieksies tikai uz jauniem failiem. Lai veidni piemērotu ar atpakaÄŧejoÅĄu efektu iepriekÅĄ augÅĄupielādētiem failiem, palaidiet {job}.", + "storage_template_migration_job": "Krātuves veidņu migrācijas uzdevumu", "storage_template_path_length": "Aptuvenais ceÄŧa garuma ierobeÅžojums: {length, number}/{limit, number}", "storage_template_settings": "Krātuves veidne", + "storage_template_user_label": "{label} ir lietotāja glabātuves nosaukums", "system_settings": "Sistēmas iestatÄĢjumi", "template_email_available_tags": "Sagatavē var izmantot ÅĄos mainÄĢgos: {tags}", "template_email_if_empty": "Ja sagatave ir tukÅĄa, tiks izmantots noklusējuma e-pasts.", @@ -198,15 +248,19 @@ "transcoding_acceleration_qsv": "Quick Sync (nepiecieÅĄams 7. paaudzes vai jaunāks Intel procesors)", "transcoding_acceleration_rkmpp": "RKMPP (tikai Rockchip SOC)", "transcoding_acceleration_vaapi": "VAAPI", + "transcoding_accepted_video_codecs": "Akceptētie video kodeki", "transcoding_advanced_options_description": "Lielākajai daÄŧai lietotāju nevajadzētu mainÄĢt ÅĄÄĢs opcijas", "transcoding_audio_codec": "Audio kodeks", + "transcoding_audio_codec_description": "Opus ir augstākās kvalitātes izvēle, bet tā ir mazāk saderÄĢga ar vecām ierÄĢcēm vai programmatÅĢru.", "transcoding_codecs_learn_more": "Lai uzzinātu vairāk par ÅĄeit lietoto terminoloÄŖiju, skatiet FFmpeg dokumentāciju par H.264 kodeku, HEVC kodeku un VP9 kodeku.", + "transcoding_constant_quality_mode": "NemainÄĢgas kvalitātes reÅžÄĢms", "transcoding_constant_quality_mode_description": "ICQ ir labāks nekā CQP, bet daÅžas aparatÅĢras paātrinājuma ierÄĢces neatbalsta ÅĄo reÅžÄĢmu. Iestatot ÅĄo opciju, tiks izmantots norādÄĢtais reÅžÄĢms, ja tiek izmantota kvalitātē balstÄĢta kodÄ“ÅĄana. NVENC to ignorē, jo neatbalsta ICQ.", "transcoding_constant_rate_factor_description": "Video kvalitātes lÄĢmenis. Tipiskās vērtÄĢbas ir 23 priekÅĄ H.264, 28 priekÅĄ HEVC, 31 priekÅĄ VP9 un 35 priekÅĄ AV1. Zemāka vērtÄĢba ir labāka, bet rada lielākus failus.", "transcoding_hardware_acceleration": "AparatÅĢras paātrinājums", "transcoding_required_description": "Tikai video, kas nav atbalstÄĢtā formātā", "transcoding_settings": "Video transkodÄ“ÅĄanas iestatÄĢjumi", "transcoding_threads": "Pavedieni", + "transcoding_threads_description": "Augstākas vērtÄĢbas nodroÅĄina ātrāku kodÄ“ÅĄanu, bet atstāj mazāk jaudas serverim, lai apstrādātu citus aktÄĢvos uzdevumus. Å ai vērtÄĢbai nevajadzētu pārsniegt CPU kodolu skaitu. Ja iestatÄĢta uz 0, maksimizē izmantoÅĄanu.", "transcoding_video_codec": "Video kodeks", "trash_number_of_days": "Dienu skaits", "trash_settings": "Atkritnes iestatÄĢjumi", @@ -224,16 +278,15 @@ "user_settings_description": "Lietotāju iestatÄĢjumu pārvaldÄĢba", "version_check_enabled_description": "Ieslēgt versijas pārbaudi", "version_check_implications": "Versiju pārbaudes funkcija ir atkarÄĢga no periodiskas saziņas ar github.com", - "version_check_settings": "Versijas pārbaude" + "version_check_settings": "Versijas pārbaude", + "version_check_settings_description": "Ieslēgt/izslēgt paziņojumus par jaunu versiju" }, "admin_email": "Administratora e-pasts", "admin_password": "Administratora parole", "administration": "AdministrÄ“ÅĄana", "advanced": "Papildu", - "advanced_settings_beta_timeline_subtitle": "IzmēĪini jauno lietotnes pieredzi", - "advanced_settings_beta_timeline_title": "Bēta laika skala", "advanced_settings_log_level_title": "ÅŊurnalÄ“ÅĄanas lÄĢmenis: {level}", - "advanced_settings_prefer_remote_subtitle": "DaŞās ierÄĢcēs sÄĢktēli no ierÄĢcē esoÅĄajiem resursiem tiek ielādēti Äŧoti lēni. Aktivizējiet ÅĄo iestatÄĢjumu, lai tā vietā ielādētu attālus attēlus.", + "advanced_settings_prefer_remote_subtitle": "DaŞās ierÄĢcēs sÄĢktēli no ierÄĢces atmiņas ielādējas Äŧoti lēni. Aktivizējiet ÅĄo iestatÄĢjumu, lai tā vietā ielādētu attālus attēlus.", "advanced_settings_prefer_remote_title": "Dot priekÅĄroku attāliem attēliem", "advanced_settings_proxy_headers_title": "Starpniekservera galvenes", "advanced_settings_self_signed_ssl_subtitle": "IzlaiÅž servera galapunkta SSL sertifikātu verifikāciju. NepiecieÅĄams paÅĄparakstÄĢtajiem sertifikātiem.", @@ -246,7 +299,7 @@ "age_years": "{years, plural, zero {# gadu} one {# gads} other {# gadi}}", "album_added": "Albums pievienots", "album_added_notification_setting_description": "Saņemt e-pasta paziņojumu, kad tevi pievieno kopÄĢgam albumam", - "album_cover_updated": "Albuma attēls atjaunināts", + "album_cover_updated": "Albuma vāciÅ†ÅĄ atjaunināts", "album_delete_confirmation_description": "Ja ÅĄis albums tiek kopÄĢgots, citi lietotāji vairs nevarēs tam piekÄŧÅĢt.", "album_deleted": "Albums dzēsts", "album_info_card_backup_album_excluded": "NEIEKÄģAUTS", @@ -271,7 +324,7 @@ "albums_default_sort_order_description": "Sākotnējā failu kārtoÅĄanas secÄĢba, veidojot jaunus albumus.", "albums_feature_description": "Failu kolekcijas, kuras var koplietot ar citiem lietotājiem.", "albums_on_device_count": "Albumi ierÄĢcē ({count})", - "all": "Viss", + "all": "Visi", "all_albums": "Visi albumi", "all_people": "Visas personas", "all_videos": "Visi video", @@ -304,7 +357,7 @@ "asset_list_group_by_sub_title": "Grupēt pēc", "asset_list_layout_settings_dynamic_layout_title": "Dinamiskais izkārtojums", "asset_list_layout_settings_group_automatically": "Automātiski", - "asset_list_layout_settings_group_by": "Grupēt aktÄĢvus pēc", + "asset_list_layout_settings_group_by": "Grupēt failus pēc", "asset_list_layout_settings_group_by_month_day": "Mēnesis + diena", "asset_list_layout_sub_title": "Izvietojums", "asset_list_settings_subtitle": "FotoreÅžÄŖa izkārtojuma iestatÄĢjumi", @@ -313,7 +366,7 @@ "asset_skipped_in_trash": "Atkritnē", "asset_uploaded": "AugÅĄupielādēts", "asset_uploading": "AugÅĄupielādēâ€Ļ", - "asset_viewer_settings_title": "AktÄĢvu SkatÄĢtājs", + "asset_viewer_settings_title": "Failu skatÄĢtājs", "assets": "Faili", "assets_added_count": "Pievienoja {count, plural, one {# failu} other {# failus}}", "assets_added_to_album_count": "Pievienoja albumam {count, plural, one {# failu} other {# failus}}", @@ -327,6 +380,8 @@ "automatic_endpoint_switching_title": "Automātiska URL pārslēgÅĄana", "autoplay_slideshow": "Automātiska slaidrādes atskaņoÅĄana", "back": "AtpakaÄŧ", + "background_backup_running_error": "PaÅĄlaik darbojas dublÄ“ÅĄana fonā, nevar uzsākt manuālu dublÄ“ÅĄanu", + "background_options": "Fona opcijas", "backup": "DublÄ“ÅĄana", "backup_album_selection_page_albums_device": "Albumi ierÄĢcē ({count})", "backup_album_selection_page_albums_tap": "Pieskarieties, lai iekÄŧautu, veiciet dubultskārienu, lai izslēgtu", @@ -334,6 +389,7 @@ "backup_album_selection_page_select_albums": "AtlasÄĢt albumus", "backup_album_selection_page_selection_info": "Atlases informācija", "backup_album_selection_page_total_assets": "Unikālo failu kopsumma", + "backup_albums_sync": "DublÄ“ÅĄanas albumu sinhronizācija", "backup_all": "Viss", "backup_background_service_backup_failed_message": "Neizdevās dublēt lÄĢdzekÄŧus. Notiek atkārtota mēĪinÄÅĄanaâ€Ļ", "backup_background_service_connection_failed_message": "Neizdevās izveidot savienojumu ar serveri. Notiek atkārtota mēĪinÄÅĄanaâ€Ļ", @@ -373,7 +429,7 @@ "backup_controller_page_remainder": "Atlikums", "backup_controller_page_remainder_sub": "AtlikuÅĄie fotoattēli un videoklipi, kurus dublēt no atlases", "backup_controller_page_server_storage": "Servera krātuve", - "backup_controller_page_start_backup": "Sākt DublÄ“ÅĄanu", + "backup_controller_page_start_backup": "Sākt dublÄ“ÅĄanu", "backup_controller_page_status_off": "Automātiskā priekÅĄplāna dublÄ“ÅĄana ir izslēgta", "backup_controller_page_status_on": "Automātiskā priekÅĄplāna dublÄ“ÅĄana ir ieslēgta", "backup_controller_page_storage_format": "{used} no {total} tiek izmantots", @@ -383,6 +439,7 @@ "backup_controller_page_turn_on": "Ieslēgt priekÅĄplāna dublÄ“ÅĄanu", "backup_controller_page_uploading_file_info": "Faila informācijas augÅĄupielāde", "backup_err_only_album": "Nevar noņemt vienÄĢgo albumu", + "backup_error_sync_failed": "Sinhronizācija neizdevās. Nevar apstrādāt rezerves kopiju.", "backup_info_card_assets": "faili", "backup_manual_cancelled": "Atcelts", "backup_manual_in_progress": "AugÅĄupielāde jau notiek. MēĪiniet pēc kāda laika atkārtoti", @@ -390,22 +447,22 @@ "backup_manual_title": "AugÅĄupielādes statuss", "backup_options_page_title": "DublÄ“ÅĄanas iestatÄĢjumi", "backup_settings_subtitle": "PārvaldÄĢt augÅĄupielādes iestatÄĢjumus", - "backward": "AtpakaÄŧejoÅĄi", - "beta_sync": "Beta Sinhronizācijas statuss", - "beta_sync_subtitle": "PārvaldÄĢt jauno sinhronizācijas sistēmu", + "backward": "AtpakaÄŧejoÅĄa", "biometric_auth_enabled": "Ieslēgta biometriskā autentifikācija", "biometric_locked_out": "Biometriskā autentifikācija tev ir bloķēta", "biometric_no_options": "Nav pieejamas biometriskās autentifikācijas iespējas", "biometric_not_available": "Biometriskā autentifikācija ÅĄajā ierÄĢcē nav pieejama", "birthdate_saved": "DzimÅĄanas datums veiksmÄĢgi saglabāts", "birthdate_set_description": "DzimÅĄanas datums tiek izmantots, lai aprēķinātu ÅĄÄĢs personas vecumu fotogrāfijas uzņemÅĄanas brÄĢdÄĢ.", + "blurred_background": "Izpludināts fons", "bugs_and_feature_requests": "KÄŧÅĢdas un funkciju pieprasÄĢjumi", "build": "BÅĢvējums", "build_image": "BÅĢvējuma attēls", + "buy": "Iegādāties Immich", "cache_settings_clear_cache_button": "IztÄĢrÄĢt keÅĄatmiņu", "cache_settings_clear_cache_button_title": "IztÄĢra aplikācijas keÅĄatmiņu. Tas bÅĢtiski ietekmēs lietotnes veiktspēju, lÄĢdz keÅĄatmiņa bÅĢs pārbÅĢvēta.", "cache_settings_duplicated_assets_clear_button": "NOTÄĒRÄĒT", - "cache_settings_duplicated_assets_subtitle": "Fotoattēli un videoklipi, kurus lietotne ir iekÄŧāvusi melnajā sarakstā", + "cache_settings_duplicated_assets_subtitle": "Fotoattēli un videoklipi, kurus lietotne ir iekÄŧāvusi ignorējamo sarakstā", "cache_settings_duplicated_assets_title": "Dublicētie faili ({count})", "cache_settings_statistics_album": "Bibliotēkas sÄĢktēli", "cache_settings_statistics_full": "Pilni attēli", @@ -414,13 +471,17 @@ "cache_settings_statistics_title": "KeÅĄatmiņas lietojums", "cache_settings_subtitle": "Kontrolēt Immich mobilās lietotnes keÅĄdarbi", "cache_settings_tile_subtitle": "Kontrolēt lokālās krātuves uzvedÄĢbu", - "cache_settings_tile_title": "Lokālā Krātuve", + "cache_settings_tile_title": "Lokālā krātuve", "cache_settings_title": "KeÅĄdarbes iestatÄĢjumi", "camera": "Fotokamera", + "camera_brand": "Fotokameras zÄĢmols", + "camera_model": "Fotokameras modelis", "cancel": "Atcelt", + "cancel_search": "Atcelt meklÄ“ÅĄanu", "canceled": "Atcelts", "canceling": "AtceÄŧ", "cannot_merge_people": "Nevar apvienot personas", + "cannot_undo_this_action": "Å o darbÄĢbu nevar atcelt!", "cast": "PārraidÄĢt", "cast_description": "Konfigurēt pieejamos pārraides galamērġus", "change_date": "MainÄĢt datumu", @@ -431,18 +492,23 @@ "change_name": "MainÄĢt nosaukumu", "change_name_successfully": "Vārds veiksmÄĢgi nomainÄĢts", "change_password": "NomainÄĢt paroli", + "change_password_description": "Vai nu ÅĄÄĢ ir pirmā reize, kad pieslēdzaties sistēmai, vai arÄĢ ir iesniegts pieprasÄĢjums mainÄĢt paroli. LÅĢdzu, ievadiet jauno paroli zemāk.", "change_password_form_confirm_password": "Apstiprināt Paroli", "change_password_form_description": "Sveiki {name},\n\nÅ ÄĢ ir pirmā reize, kad pierakstāties sistēmā, vai arÄĢ ir iesniegts pieprasÄĢjums mainÄĢt paroli. LÅĢdzu, zemāk ievadiet jauno paroli.", "change_password_form_new_password": "Jauna Parole", "change_password_form_password_mismatch": "Paroles nesakrÄĢt", "change_password_form_reenter_new_password": "Atkārtoti ievadÄĢt jaunu paroli", "change_pin_code": "NomainÄĢt PIN kodu", + "charging": "Lādē", + "charging_requirement_mobile_backup": "Fona dublÄ“ÅĄanai nepiecieÅĄams, lai ierÄĢce tiktu lādēta", "check_corrupt_asset_backup_button": "Veikt pārbaudi", "choose_matching_people_to_merge": "Izvēlies atbilstoÅĄas personas apvienoÅĄanai", "city": "Pilsēta", "clear": "NotÄĢrÄĢt", "clear_all": "NotÄĢrÄĢt visu", + "clear_all_recent_searches": "NotÄĢrÄĢt visas pēdējās meklÄ“ÅĄanas", "clear_file_cache": "NotÄĢrÄĢt failu keÅĄatmiņu", + "clear_message": "NotÄĢrÄĢt paziņojumu", "clear_value": "NotÄĢrÄĢt vērtÄĢbu", "client_cert_dialog_msg_confirm": "Labi", "client_cert_enter_password": "Ievadi paroli", @@ -459,10 +525,14 @@ "color": "Krāsa", "color_theme": "Krāsu tēma", "comment_deleted": "Komentārs dzēsts", + "comment_options": "Komentāru iespējas", + "comments_and_likes": "Komentāri un tÄĢkÅĄÄˇi", + "comments_are_disabled": "Komentāri ir atslēgti", "common_create_new_album": "Izveidot jaunu albumu", "common_server_error": "LÅĢdzu, pārbaudiet tÄĢkla savienojumu, pārliecinieties, vai serveris ir sasniedzams un aplikācijas/servera versijas ir saderÄĢgas.", "completed": "Pabeigts", "confirm": "Apstiprināt", + "confirm_admin_password": "Administratora paroles apstiprinājums", "confirm_new_pin_code": "Apstiprināt jauno PIN kodu", "confirm_password": "Apstiprināt paroli", "confirm_tag_face": "Vai vēlies atzÄĢmēt ÅĄo seju kā {name}?", @@ -472,12 +542,15 @@ "control_bottom_app_bar_create_new_album": "Izveidot jaunu albumu", "control_bottom_app_bar_delete_from_immich": "Dzēst no Immich", "control_bottom_app_bar_delete_from_local": "Dzēst no ierÄĢces", - "control_bottom_app_bar_edit_location": "RediÄŖÄ“t AtraÅĄanās Vietu", - "control_bottom_app_bar_edit_time": "RediÄŖÄ“t Datumu un Laiku", - "control_bottom_app_bar_share_to": "KopÄĢgot Uz", + "control_bottom_app_bar_edit_location": "RediÄŖÄ“t atraÅĄanās vietu", + "control_bottom_app_bar_edit_time": "RediÄŖÄ“t datumu un laiku", + "control_bottom_app_bar_share_to": "KopÄĢgot uz", "control_bottom_app_bar_trash_from_immich": "Pārvietot uz Atkritni", "copy_error": "KopÄ“ÅĄanas kÄŧÅĢda", + "copy_to_clipboard": "Kopēt starpliktuvē", "country": "Valsts", + "cover": "AizpildÄĢts ekrāns", + "covers": "Vāciņi", "create": "Izveidot", "create_album": "Izveidot albumu", "create_album_page_untitled": "Bez nosaukuma", @@ -486,6 +559,7 @@ "create_link_to_share": "Izveidot kopÄĢgoÅĄanas saiti", "create_new": "IZVEIDOT JAUNU", "create_new_person": "Izveidot jaunu personu", + "create_new_person_hint": "PiesaistÄĢt izvēlētos failus jaunai personai", "create_new_user": "Izveidot jaunu lietotāju", "create_shared_album_page_share_add_assets": "PIEVIENOT AKTÄĒVUS", "create_shared_album_page_share_select_photos": "Fotoattēlu Izvēle", @@ -498,6 +572,7 @@ "custom_locale_description": "Formatēt datumus un skaitÄŧus atbilstoÅĄi valodai un reÄŖionam", "custom_url": "Pielāgots URL", "daily_title_text_date_year": "E, MMM dd, gggg", + "dark_theme": "Pārslēgt tumÅĄo tēmu", "date_after": "Datums pēc", "date_and_time": "Datums un Laiks", "date_before": "Datums pirms", @@ -526,7 +601,7 @@ "delete_library": "Dzēst bibliotēku", "delete_link": "Dzēst saiti", "delete_local_action_prompt": "{count} dzēsti lokāli", - "delete_local_dialog_ok_backed_up_only": "Dzēst tikai Dublētos", + "delete_local_dialog_ok_backed_up_only": "Dzēst tikai dublētos", "delete_local_dialog_ok_force": "Tā pat dzēst", "delete_others": "Dzēst citus", "delete_shared_link": "Dzēst KopÄĢgoÅĄanas saiti", @@ -539,8 +614,11 @@ "details": "INFORMĀCIJA", "direction": "SecÄĢba", "discord": "Discord", + "discover": "Atklāt", + "discovered_devices": "Atrastās ierÄĢces", "display_order": "AttēloÅĄanas secÄĢba", "display_original_photos": "RādÄĢt oriÄŖinālās fotogrāfijas", + "do_not_show_again": "Vairs nerādÄĢt ÅĄo ziņojumu", "documentation": "Dokumentācija", "done": "Gatavs", "download": "Lejupielādēt", @@ -551,6 +629,8 @@ "download_error": "Lejupielādes kÄŧÅĢda", "download_failed": "Lejupielāde neizdevās", "download_finished": "Lejupielāde pabeigta", + "download_include_embedded_motion_videos": "Iegultie videoklipi", + "download_include_embedded_motion_videos_description": "IekÄŧaut video, kas iebÅĢvēti kustÄĢgos fotoattēlos, kā atseviÅĄÄˇu failu", "download_notfound": "Lejupielāde nav atrasta", "download_paused": "Lejupielāde nopauzēta", "download_settings": "Lejupielāde", @@ -571,6 +651,7 @@ "edit_birthday": "Labot dzimÅĄanas dienu", "edit_date": "Labot datumu", "edit_date_and_time": "Labot datumu un laiku", + "edit_date_and_time_action_prompt": "{count} datums un laiks labots", "edit_description": "Labot aprakstu", "edit_description_prompt": "LÅĢdzu, izvēlies jaunu aprakstu:", "edit_faces": "Labot sejas", @@ -602,8 +683,14 @@ "enter_your_pin_code_subtitle": "Ievadi savu PIN kodu, lai piekÄŧÅĢtu slēgtajai mapei", "error": "KÄŧÅĢda", "error_change_sort_album": "Neizdevās nomainÄĢt albuma kārtoÅĄanas secÄĢbu", + "error_loading_image": "KÄŧÅĢda, ielādējot attēlu", + "error_loading_partners": "KÄŧÅĢda, ielādējot partnerus: {error}", "error_saving_image": "KÄŧÅĢda: {error}", + "error_title": "KÄŧÅĢda - kaut kas nogāja greizi", "errors": { + "cannot_navigate_next_asset": "Nevar pāriet uz nākamo resursu", + "cannot_navigate_previous_asset": "Nevar pāriet uz iepriekÅĄÄ“jo resursu", + "cant_apply_changes": "Nevar piemērot izmaiņas", "cant_get_faces": "Nevar iegÅĢt sejas", "cant_search_people": "Neizdevās veikt peronu meklÄ“ÅĄanu", "exclusion_pattern_already_exists": "Šāds izslēgÅĄanas paraugs jau pastāv.", @@ -626,7 +713,12 @@ "profile_picture_transparent_pixels": "Profila attēlos nevar bÅĢt caurspÄĢdÄĢgi pikseÄŧi. LÅĢdzu, palielini un/vai pārvieto attēlu.", "something_went_wrong": "Kaut kas nogāja greizi", "unable_to_change_description": "Neizdevās nomainÄĢt aprakstu", + "unable_to_create_admin_account": "Nevar izveidot administratora kontu", + "unable_to_create_api_key": "Nevar izveidot jaunu API atslēgu", + "unable_to_create_library": "Nevar izveidot bibliotēku", "unable_to_create_user": "Neizdevās izveidot lietotāju", + "unable_to_delete_album": "Nevar izdzēst albumu", + "unable_to_delete_asset": "Nevar izdzēst failu", "unable_to_delete_user": "Neizdevās dzēst lietotāju", "unable_to_empty_trash": "Neizdevās iztukÅĄot atkritni", "unable_to_hide_person": "Neizdevās paslēpt personu", @@ -634,7 +726,8 @@ "unable_to_save_date_of_birth": "Neizdevās saglabāt dzimÅĄanas datumu", "unable_to_scan_libraries": "Bibliotēku skenÄ“ÅĄana neizdevās", "unable_to_scan_library": "Bibliotēkas skenÄ“ÅĄana neizdevās", - "unable_to_trash_asset": "Neizdevās pārvietot failu uz atkritni" + "unable_to_trash_asset": "Neizdevās pārvietot failu uz atkritni", + "unable_to_update_album_cover": "Nevar atjaunināt albuma vāciņu" }, "exif": "Exif", "exif_bottom_sheet_description": "Pievienot Aprakstu...", @@ -651,12 +744,14 @@ "expired": "DerÄĢguma termiÅ†ÅĄ beidzās", "explore": "IzpētÄĢt", "export": "Eksportēt", + "export_as_json": "Eksportēt kā JSON", "export_database": "Eksportēt datubāzi", "export_database_description": "Eksportēt SQLite datubāzi", "extension": "PaplaÅĄinājums", "external": "Ārējs", + "external_libraries": "Ārējas bibliotēkas", "external_network": "Ārējs tÄĢkls", - "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": "Kad nav pieejams izvēlētais Wi-Fi tÄĢkls, aplikācija pieslēgsies serverim lietojot pirmo strādājoÅĄo URL no saraksta, sākot ar augÅĄÄ“jo", "face_unassigned": "NepieÅĄÄˇirts", "failed": "Neizdevās", "failed_to_authenticate": "Neizdevās autentificēties", @@ -665,6 +760,7 @@ "favorite": "Izlase", "favorites": "Izlase", "favorites_page_no_favorites": "Nav atrasti iecienÄĢtākie faili", + "features_in_development": "Izstrādes stadijā esoÅĄas funkcijas", "features_setting_description": "Lietotnes funkciju pārvaldÄĢba", "file_name": "Faila nosaukums", "file_name_or_extension": "Faila nosaukums vai paplaÅĄinājums", @@ -696,13 +792,17 @@ "group_owner": "Grupēt pēc ÄĢpaÅĄnieka", "group_places_by": "Grupēt vietas pēc...", "group_year": "Grupēt pēc gada", - "haptic_feedback_switch": "IestatÄĢt haptisku reakciju", + "haptic_feedback_switch": "Iespējot haptisku reakciju", "haptic_feedback_title": "Haptiska Reakcija", - "has_quota": "Ir kvota", + "has_quota": "Kvota", "hash_asset": "Veidot faila jaucējvērtÄĢbu", - "hashed_assets": "Faili ar izveidotām jaucējvērtÄĢbām", + "hashed_assets": "Faili ar jaucējvērtÄĢbām", "hashing": "Veido jaucējvērtÄĢbas", "header_settings_field_validator_msg": "VērtÄĢba nevar bÅĢt tukÅĄa", + "header_settings_header_name_input": "Galvenes lauks", + "header_settings_header_value_input": "Galvenes vērtÄĢba", + "headers_settings_tile_subtitle": "Norādiet starpniekservera galvenes, kuras lietotnei jānosÅĢta ar katru tÄĢkla pieprasÄĢjumu", + "headers_settings_tile_title": "Pielāgotas starpniekservera galvenes", "hide_all_people": "Paslēpt visas personas", "hide_gallery": "Paslēpt galeriju", "hide_named_person": "Paslēpt personu {name}", @@ -710,20 +810,20 @@ "hide_person": "Paslēpt personu", "hide_unnamed_people": "Paslēpt nenosauktas personas", "home_page_add_to_album_conflicts": "Pievienoja {added} failus albumam {album}. {failed} faili jau ir albumā.", - "home_page_add_to_album_err_local": "Albumiem vēl nevar pievienot lokālos aktÄĢvus, notiek izlaiÅĄana", + "home_page_add_to_album_err_local": "Albumiem vēl nevar pievienot lokālos failus, izlaiÅž", "home_page_add_to_album_success": "Pievienoja {added} aktÄĢvus albumam {album}.", "home_page_album_err_partner": "Pagaidām nevar pievienot partnera aktÄĢvus albumam, notiek izlaiÅĄana", - "home_page_archive_err_local": "Vēl nevar arhivēt lokālos aktÄĢvus, notiek izlaiÅĄana", + "home_page_archive_err_local": "Vēl nevar arhivēt lokālos aktÄĢvus, izlaiÅž", "home_page_archive_err_partner": "Nevarēja arhivēt partnera aktÄĢvus, notiek izlaiÅĄana", "home_page_building_timeline": "Tiek izveidota laika skala", "home_page_delete_err_partner": "Nevarēja dzēst partnera aktÄĢvus, notiek izlaiÅĄana", - "home_page_delete_remote_err_local": "Lokālie faili dzÄ“ÅĄanai attālinātajā izvēlē, tiek izlaists", - "home_page_favorite_err_local": "Vēl nevar pievienot izlasei vietējos failus, izlaiÅž", + "home_page_delete_remote_err_local": "Lokālie faili dzÄ“ÅĄanai attālinātajā izvēlē, izlaiÅž", + "home_page_favorite_err_local": "Vēl nevar pievienot izlasei lokālos failus, izlaiÅž", "home_page_favorite_err_partner": "Pagaidām nevar ievietot izlasē partnera failus, izlaiÅž", "home_page_first_time_notice": "Ja ÅĄÄĢ ir pirmā reize, kad izmanto lietotni, lÅĢdzu, izvēlies dublējamo albumu, lai laika skalā varētu aizpildÄĢt fotoattēlus un videoklipus", - "home_page_locked_error_local": "Nevar pārvietot vietējos failus uz slēgto mapi, izlaiÅž", + "home_page_locked_error_local": "Nevar pārvietot lokālos failus uz slēgto mapi, izlaiÅž", "home_page_locked_error_partner": "Nevar pārvietot partneru failus uz slēgto mapi, izlaiÅž", - "home_page_share_err_local": "Caur saiti nevarēja kopÄĢgot lokālos aktÄĢvus, notiek izlaiÅĄana", + "home_page_share_err_local": "Caur saiti nevarēja kopÄĢgot lokālos aktÄĢvus, izlaiÅž", "home_page_upload_err_limit": "Vienlaikus var augÅĄupielādēt ne vairāk kā 30 aktÄĢvus, notiek izlaiÅĄana", "hour": "Stunda", "hours": "Stundas", @@ -733,7 +833,7 @@ "ignore_icloud_photos_description": "iCloud uzglabātās fotogrāfijas netiks augÅĄupielādētas Immich serverÄĢ", "image": "Attēls", "image_saved_successfully": "Attēls saglabāts", - "image_viewer_page_state_provider_download_started": "Lejupielāde Uzsākta", + "image_viewer_page_state_provider_download_started": "Lejupielāde uzsākta", "image_viewer_page_state_provider_download_success": "Lejupielāde izdevās", "image_viewer_page_state_provider_share_error": "KopÄĢgoÅĄanas KÄŧÅĢda", "immich_logo": "Immich logo", @@ -744,6 +844,7 @@ "in_archive": "ArhÄĢvā", "include_archived": "IekÄŧaut arhivētos", "include_shared_albums": "IekÄŧaut koplietotos albumus", + "include_shared_partner_assets": "IekÄŧaut partneru koplietotos failus", "info": "Informācija", "interval": { "day_at_onepm": "Katru dienu 13.00", @@ -758,6 +859,7 @@ "ios_debug_info_last_sync_at": "Pēdējā sinhronizācija {dateTime}", "ios_debug_info_no_processes_queued": "Nav ierindotu fona procesu", "ios_debug_info_processing_ran_at": "Apstrāde notika {dateTime}", + "items_count": "{count, plural, one {# vienums} other {# vienumi}}", "jobs": "Uzdevumi", "keep": "Paturēt", "keep_all": "Paturēt visus", @@ -779,6 +881,7 @@ "let_others_respond": "Äģaut citiem atbildēt", "level": "LÄĢmenis", "library": "Bibliotēka", + "library_options": "Bibliotēkas opcijas", "library_page_device_albums": "Albumi ierÄĢcē", "library_page_new_album": "Jauns albums", "library_page_sort_asset_count": "Failu skaits", @@ -786,9 +889,16 @@ "library_page_sort_last_modified": "Pēdējās izmaiņas", "library_page_sort_title": "Albuma virsraksts", "licenses": "Licences", + "link_to_oauth": "PiesaistÄĢt OAuth", + "linked_oauth_account": "PiesaistÄĢtais OAuth konts", "list": "Saraksts", "loading": "Ielādē", + "local": "Lokāli", + "local_asset_cast_failed": "Nav iespējams pārraidÄĢt resursu, kas nav augÅĄupielādēts serverÄĢ", + "local_assets": "Lokālie faili", + "local_media_summary": "Lokālo mediju kopsavilkums", "local_network": "Lokālais tÄĢkls", + "local_network_sheet_info": "Izmantojot norādÄĢto Wi-Fi tÄĢklu, lietotne veidos savienojumu ar serveri, izmantojot ÅĄo URL", "location_permission": "AtraÅĄanās vietas atÄŧauja", "location_permission_content": "Lai izmantotu automātiskās pārslēgÅĄanās funkciju, Immich ir nepiecieÅĄama precÄĢzas atraÅĄanās vietas atÄŧauja, lai varētu nolasÄĢt paÅĄreizējā Wi-Fi tÄĢkla nosaukumu", "location_picker_choose_on_map": "Izvēlēties uz kartes", @@ -843,11 +953,11 @@ "map_marker_with_image": "Kartes marġieris ar attēlu", "map_no_location_permission_content": "AtraÅĄanās vietas atÄŧauja ir nepiecieÅĄama, lai parādÄĢtu jÅĢsu paÅĄreizējās atraÅĄanās vietas aktÄĢvus. Vai vēlaties to atÄŧaut tagad?", "map_no_location_permission_title": "AtraÅĄanās vietas AtÄŧaujas liegtas", - "map_settings": "Kartes IestatÄĢjumi", + "map_settings": "Kartes iestatÄĢjumi", "map_settings_dark_mode": "TumÅĄais reÅžÄĢms", "map_settings_date_range_option_day": "Pēdējās 24 stundas", "map_settings_date_range_option_days": "Pēdējās {days} dienas", - "map_settings_date_range_option_year": "Pēdējo gadu", + "map_settings_date_range_option_year": "Pēdējais gads", "map_settings_date_range_option_years": "Pēdējie {years} gadi", "map_settings_dialog_title": "Kartes IestatÄĢjumi", "map_settings_include_show_archived": "IekÄŧaut Arhivētos", @@ -856,7 +966,7 @@ "map_settings_theme_settings": "Kartes Dizains", "map_zoom_to_see_photos": "Attāliniet, lai redzētu fotoattēlus", "matches": "AtbilstÄĢbas", - "media_type": "Multivides veids", + "media_type": "Faila veids", "memories": "Atmiņas", "memories_all_caught_up": "Å obrÄĢd, tas arÄĢ viss", "memories_check_back_tomorrow": "Atgriezies rÄĢt, lai skatÄĢtu vairāk atmiņu", @@ -892,6 +1002,9 @@ "name_or_nickname": "Vārds vai iesauka", "network_requirement_photos_upload": "Izmantot mobilo datu pārraidi, lai dublētu fotoattēlus", "network_requirement_videos_upload": "Izmantot mobilo datu pārraidi, lai dublētu video", + "network_requirements": "TÄĢkla prasÄĢbas", + "network_requirements_updated": "TÄĢkla prasÄĢbas ir mainÄĢjuÅĄÄs, atiestata dublÄ“ÅĄanas rindu", + "networking_settings": "TÄĢkla iestatÄĢjumi", "networking_subtitle": "PārvaldÄĢt servera galapunktu iestatÄĢjumus", "never": "nekad", "new_album": "Jauns albums", @@ -899,6 +1012,7 @@ "new_password": "Jaunā parole", "new_person": "Jauna persona", "new_pin_code": "Jaunais PIN kods", + "new_timeline": "Jaunā laikjosla", "new_user_created": "Izveidots jauns lietotājs", "new_version_available": "PIEEJAMA JAUNA VERSIJA", "next": "Nākamais", @@ -910,8 +1024,13 @@ "no_archived_assets_message": "Arhivē fotoattēlus un videoklipus, lai paslēptu tos no Fotoattēli skata", "no_assets_message": "NOKLIKÅ ÄļINIET, LAI AUGÅ UPIELĀDĒTU SAVU PIRMO FOTOATTĒLU", "no_assets_to_show": "Nav uzrādāmo aktÄĢvu", + "no_cast_devices_found": "Nav atrasta neviena pārraides ierÄĢce", + "no_checksum_local": "Nav pieejama kontrolsumma - nevar iegÅĢt lokālos failus", + "no_checksum_remote": "Nav pieejama kontrolsumma - nevar iegÅĢt attālo failu", "no_duplicates_found": "Dublikāti netika atrasti.", "no_exif_info_available": "Nav pieejama exif informācija", + "no_explore_results_message": "AugÅĄupielādē vairāk fotogrāfiju, lai iepazÄĢtu savu kolekciju.", + "no_local_assets_found": "Ar ÅĄo kontrolsummu nav atrasts neviens lokālais fails", "no_name": "Nav nosaukuma", "no_notifications": "Nav paziņojumu", "no_places": "Nav atraÅĄanās vietu", @@ -919,12 +1038,13 @@ "no_results_description": "IzmēĪiniet sinonÄĢmu vai vispārÄĢgāku atslēgvārdu", "not_in_any_album": "Nav nevienā albumā", "not_selected": "Nav izvēlēts", + "note_apply_storage_label_to_previously_uploaded assets": "PiezÄĢme: Lai piemērotu glabātuves nosaukumu iepriekÅĄ augÅĄupielādētiem failiem, izpildiet", "notes": "PiezÄĢmes", "nothing_here_yet": "Å eit vēl nekā nav", "notification_permission_dialog_content": "Lai iespējotu paziņojumus, atveriet IestatÄĢjumi un atlasiet AtÄŧaut.", "notification_permission_list_tile_content": "PieÅĄÄˇirt atÄŧauju, lai iespējotu paziņojumus.", - "notification_permission_list_tile_enable_button": "Iespējot Paziņojumus", - "notification_permission_list_tile_title": "Paziņojumu AtÄŧaujas", + "notification_permission_list_tile_enable_button": "Iespējot paziņojumus", + "notification_permission_list_tile_title": "Paziņojumu atÄŧaujas", "notification_toggle_setting_description": "Ieslēgt e-pasta paziņojumus", "notifications": "Paziņojumi", "notifications_setting_description": "Paziņojumu pārvaldÄĢba", @@ -945,6 +1065,8 @@ "open_the_search_filters": "Atvērt meklÄ“ÅĄanas filtrus", "options": "IestatÄĢjumi", "or": "vai", + "organize_into_albums": "Sakārtot albumos", + "organize_into_albums_description": "Ievietot esoÅĄÄs fotogrāfijas albumos, izmantojot paÅĄreizējos sinhronizācijas iestatÄĢjumus", "organize_your_library": "Bibliotēkas organizÄ“ÅĄana", "original": "oriÄŖināls", "other": "Citi", @@ -963,6 +1085,7 @@ "partner_page_select_partner": "Izvēlēties partneri", "partner_page_shared_to_title": "KopÄĢgots uz", "partner_page_stop_sharing_content": "{partner} vairs nevarēs piekÄŧÅĢt jÅĢsu fotoattēliem.", + "partner_sharing": "KoplietoÅĄana ar partneriem", "partners": "Partneri", "password": "Parole", "password_does_not_match": "Parole nesakrÄĢt", @@ -1050,6 +1173,7 @@ "rating_description": "RādÄĢt EXIF vērtējumu informācijas panelÄĢ", "reaction_options": "Reakcijas iespējas", "read_changelog": "LasÄĢt izmaiņu sarakstu", + "ready_for_upload": "Gatavs augÅĄupielādei", "recently_added_page_title": "Nesen Pievienotais", "refresh": "Atsvaidzināt", "refresh_faces": "Atsvaidzināt sejas", @@ -1059,8 +1183,10 @@ "refreshes_every_file": "Vēlreiz nolasa esoÅĄos un jaunos failus", "refreshing_faces": "Atsvaidzina sejas", "refreshing_metadata": "Atsvaidzina metadatus", + "remote": "Attāli", "remove": "Noņemt", "remove_assets_title": "Izņemt failus?", + "remove_custom_date_range": "Novākt pielāgoto datuma intervālu", "remove_deleted_assets": "Izņemt dzēstos failus", "remove_from_album": "Noņemt no albuma", "remove_from_album_action_prompt": "No albuma izņemti {count} faili", @@ -1075,6 +1201,8 @@ "removed_from_archive": "Noņēma no arhÄĢva", "removed_from_favorites": "Noņēma no izlases", "removed_from_favorites_count": "{count, plural, other {Izņēma #}} no izlases", + "removed_memory": "Noņēma atmiņu", + "removed_photo_from_memory": "Noņēma fotogrāfiju no atmiņas", "rename": "Pārsaukt", "repair": "Remonts", "replace_with_upload": "Aizstāt ar augÅĄupielādi", @@ -1085,6 +1213,7 @@ "reset_password": "AtiestatÄĢt paroli", "reset_people_visibility": "AtiestatÄĢt personu redzamÄĢbu", "reset_pin_code": "AtiestatÄĢt PIN kodu", + "reset_sqlite": "AtiestatÄĢt SQLite datubāzi", "reset_to_default": "AtiestatÄĢt noklusējuma iestatÄĢjumus", "resolve_duplicates": "Atrisināt dublÄ“ÅĄanās gadÄĢjumus", "resolved_all_duplicates": "Visi dublikāti ir atrisināti", @@ -1133,6 +1262,7 @@ "search_for_existing_person": "Meklēt esoÅĄu personu", "search_no_people": "Nav personu", "search_no_people_named": "Nav personas ar vārdu \"{name}\"", + "search_options": "MeklÄ“ÅĄanas iespējas", "search_page_categories": "Kategorijas", "search_page_motion_photos": "KustÄĢbu Fotoattēli", "search_page_no_objects": "Informācija par Objektiem nav pieejama", @@ -1144,11 +1274,15 @@ "search_page_your_activity": "JÅĢsu aktivitāte", "search_page_your_map": "JÅĢsu Karte", "search_people": "Meklēt personas", + "search_rating": "Meklēt pēc vērtējuma...", "search_result_page_new_search_hint": "Jauns Meklējums", + "search_settings": "Meklēt iestatÄĢjumos", + "search_state": "Meklēt pēc ÅĄtata...", "search_suggestion_list_smart_search_hint_1": "Viedā meklÄ“ÅĄana pēc noklusējuma ir iespējota, lai meklētu metadatos, izmanto sintaksi ", "search_suggestion_list_smart_search_hint_2": "m:jÅĢsu-meklÄ“ÅĄanas-frāze", "search_type": "MeklÄ“ÅĄanas veids", - "search_your_photos": "Meklēt JÅĢsu fotoattēlus", + "search_your_photos": "Meklēt fotoattēlos", + "searching_locales": "Meklē lokalizācijas...", "second": "Sekunde", "see_all_people": "SkatÄĢt visas personas", "select_album_cover": "Izvēlieties albuma vāciņu", @@ -1163,13 +1297,15 @@ "select_trash_all": "AtzÄĢmēt visus dzÄ“ÅĄanai", "select_user_for_sharing_page_err_album": "Neizdevās izveidot albumu", "selected": "Izvēlētie", - "selected_gps_coordinates": "izvēlētās ÄŖeogrāfiskās koordinātas", + "selected_gps_coordinates": "Izvēlētās ÄŖeogrāfiskās koordinātas", "server_info_box_app_version": "Aplikācijas Versija", "server_info_box_server_url": "Servera URL", "server_online": "Serveris tieÅĄsaistē", "server_privacy": "Servera privātums", "server_stats": "Servera statistika", "server_version": "Servera versija", + "set_as_album_cover": "IestatÄĢt kā albuma vāciņu", + "set_as_profile_picture": "IestatÄĢt kā profila attēlu", "set_date_of_birth": "IestatÄĢt dzimÅĄanas datumu", "setting_image_viewer_help": "DetaÄŧu skatÄĢtājs vispirms ielādē mazo sÄĢktēlu, pēc tam ielādē vidēja lieluma priekÅĄskatÄĢjumu (ja iespējots), visbeidzot ielādē oriÄŖinālu (ja iespējots).", "setting_image_viewer_original_subtitle": "Iespējot sākotnējā pilnas izÅĄÄˇirtspējas attēla (liels!) ielādi. Atspējot, lai samazinātu datu lietojumu (gan tÄĢklā, gan ierÄĢces keÅĄatmiņā).", @@ -1184,18 +1320,20 @@ "setting_notifications_notify_minutes": "{count} minÅĢtes", "setting_notifications_notify_never": "nekad", "setting_notifications_notify_seconds": "{count} sekundes", - "setting_notifications_single_progress_subtitle": "Detalizēta augÅĄupielādes progresa informācija par katru aktÄĢvu", + "setting_notifications_single_progress_subtitle": "Detalizēta augÅĄupielādes progresa informācija par katru failu", "setting_notifications_single_progress_title": "RādÄĢt fona dublējuma detalizēto progresu", "setting_notifications_subtitle": "Paziņojumu preferenču pielāgoÅĄana", "setting_notifications_total_progress_subtitle": "Kopējais augÅĄupielādes progress (pabeigti/kopējie faili)", "setting_notifications_total_progress_title": "RādÄĢt fona dublējuma kopējo progresu", "setting_video_viewer_looping_title": "Cikliski", + "setting_video_viewer_original_video_subtitle": "Straumējot video no servera, izmantot oriÄŖinālu, pat ja ir pieejama pārkodÄ“ÅĄana. Tas var izraisÄĢt buferÄ“ÅĄanu. Lokāli pieejamie video tiek atskaņoti oriÄŖinālajā kvalitātē, neatkarÄĢgi no ÅĄÄĢs iestatÄĢjuma.", + "setting_video_viewer_original_video_title": "Vienmēr izmantot oriÄŖinālo video", "settings": "IestatÄĢjumi", "settings_require_restart": "LÅĢdzu, restartējiet Immich, lai lietotu ÅĄo iestatÄĢjumu", "setup_pin_code": "UzstādÄĢt PIN kodu", "share": "KopÄĢgot", "share_add_photos": "Pievienot fotoattēlus", - "share_assets_selected": "{count} izvēlēti", + "share_assets_selected": "{count} atlasÄĢti", "share_dialog_preparing": "Notiek sagatavoÅĄana...", "shared": "KopÄĢgots", "shared_album_activities_input_disable": "Komentāri atslēgti", @@ -1245,7 +1383,6 @@ "sharing_silver_appbar_share_partner": "DalÄĢties ar partneri", "show_album_options": "RādÄĢt albuma iespējas", "show_albums": "RādÄĢt albumus", - "show_all_assets": "RādÄĢt visus failus", "show_all_people": "RādÄĢt visas personas", "show_and_hide_people": "RādÄĢt un slēpt personas", "show_file_location": "RādÄĢt faila atraÅĄanās vietu", @@ -1264,6 +1401,7 @@ "show_slideshow_transition": "RādÄĢt slÄĢdrādes pāreju", "show_supporter_badge": "AtbalstÄĢtāja nozÄĢmÄĢte", "show_supporter_badge_description": "RādÄĢt atbalstÄĢtāja nozÄĢmÄĢti", + "show_text_search_menu": "RādÄĢt teksta meklÄ“ÅĄanas izvēlni", "shuffle": "Jaukta", "sidebar": "Sānu josla", "sidebar_display_description": "ParādÄĢt saiti uz skatu sānu joslā", @@ -1276,7 +1414,7 @@ "slideshow_settings": "SlÄĢdrādes iestatÄĢjumi", "sort_albums_by": "Kārtot albumus pēc...", "sort_created": "Izveides datums", - "sort_items": "VienÄĢbu skaits", + "sort_items": "Vienumu skaits", "sort_modified": "Izmaiņu datums", "sort_newest": "Jaunākā fotogrāfija", "sort_oldest": "Vecākā fotogrāfija", @@ -1285,22 +1423,29 @@ "sort_title": "Nosaukums", "source": "Pirmkods", "stack": "Apvienot kaudzē", + "start": "Sākt", "start_date": "Sākuma datums", + "start_date_before_end_date": "Sākuma datumam jābÅĢt pirms beigu datuma", "state": "Å tats", "status": "Statuss", "stop_photo_sharing": "Beigt kopÄĢgot jÅĢsu fotogrāfijas?", "stop_photo_sharing_description": "{partner} vairs nevarēs piekÄŧÅĢt tavām fotogrāfijām.", "stop_sharing_photos_with_user": "Pārtraukt dalÄĢties ar fotogrāfijām ar ÅĄo lietotāju", "storage": "Vieta krātuvē", + "storage_label": "Glabātuves nosaukums", "storage_usage": "{used} no {available} izmantoti", "submit": "Iesniegt", "suggestions": "Ieteikumi", "sunrise_on_the_beach": "Saullēkts pludmalē", "support": "Atbalsts", "support_and_feedback": "Atbalsts un atsauksmes", + "support_third_party_description": "Tavu Immich instalāciju ir sagatavojusi treÅĄÄ puse. Problēmas, ar kurām sastopies, var bÅĢt saistÄĢtas ar ÅĄo pakotni, tāpēc lÅĢdzu vispirms ziņo par tām, izmantojot zemāk norādÄĢtās saites.", "sync": "Sinhronizēt", + "sync_local": "Sinhronizēt lokāli", + "sync_status": "Sinhronizācijas statuss", + "sync_status_subtitle": "SkatÄĢt un pārvaldÄĢt sinhronizācijas sistēmu", "theme": "Dizains", - "theme_setting_asset_list_storage_indicator_title": "RādÄĢt krātuves indikatoru uz aktÄĢvu elementiem", + "theme_setting_asset_list_storage_indicator_title": "RādÄĢt krātuves indikatoru uz attēliem reÅžga skatā", "theme_setting_asset_list_tiles_per_row_title": "Failu skaits rindā ({count})", "theme_setting_colorful_interface_subtitle": "Piemērot pamatkrāsu fona virsmām.", "theme_setting_colorful_interface_title": "Krāsaina saskarne", @@ -1332,13 +1477,14 @@ "trash_emptied": "Atkritne iztukÅĄota", "trash_no_results_message": "Å eit parādÄĢsies uz atkritni pārvietotās fotogrāfijas un video.", "trash_page_delete_all": "Dzēst Visu", - "trash_page_empty_trash_dialog_content": "Vai vēlaties iztukÅĄot savus izmestos aktÄĢvus? Tie tiks neatgriezeniski izņemti no Immich", + "trash_page_empty_trash_dialog_content": "Vai vēlaties iztukÅĄot savus izmestos failus? Tie tiks neatgriezeniski izņemti no Immich", "trash_page_info": "Atkritnes vienumi tiks neatgriezeniski dzēsti pēc {days} dienām", "trash_page_no_assets": "Atkritnē nav aktÄĢvu", "trash_page_restore_all": "Atjaunot Visu", "trash_page_select_assets_btn": "AtlasÄĢt aktÄĢvus", "trash_page_title": "Atkritne ({count})", "trashed_items_will_be_permanently_deleted_after": "Faili no atkritnes tiks neatgriezeniski dzēsti pēc {days, plural, one {# dienas} other {# dienām}}.", + "troubleshoot": "Problēmu novērÅĄana", "type": "Veids", "unable_to_change_pin_code": "Neizdevās nomainÄĢt PIN kodu", "unable_to_setup_pin_code": "Neizdevās uzstādÄĢt PIN kodu", @@ -1351,6 +1497,7 @@ "unlimited": "NeierobeÅžots", "unnamed_album": "Albums bez nosaukuma", "unsaved_change": "Nesaglabāta izmaiņa", + "unselect_all": "Atcelt visu atlasi", "unstack": "At-Stekot", "updated_at": "Atjaunināts", "updated_password": "Parole ir atjaunināta", @@ -1391,6 +1538,7 @@ "version_history": "Versiju vēsture", "version_history_item": "{version} uzstādÄĢta {date}", "video": "Videoklips", + "video_hover_setting_description": "Atskaņot video sÄĢktēlu, kad peles kursors atrodas virs objekta. Pat ja funkcija ir atspējota, atskaņoÅĄanu var sākt, uzvirzot kursoru uz atskaņoÅĄanas ikonas.", "videos": "Videoklipi", "view": "ApskatÄĢt", "view_album": "SkatÄĢt Albumu", @@ -1404,6 +1552,7 @@ "view_next_asset": "SkatÄĢt nākamo failu", "view_previous_asset": "SkatÄĢt iepriekÅĄÄ“jo failu", "view_qr_code": "SkatÄĢt QR kodu", + "view_similar_photos": "SkatÄĢt lÄĢdzÄĢgas fotogrāfijas", "view_stack": "ApskatÄĢt kaudzi", "view_user": "ApskatÄĢt lietotāju", "viewer_remove_from_stack": "Noņemt no Steka", diff --git a/i18n/mk.json b/i18n/mk.json index 75951405e8..8430ae117e 100644 --- a/i18n/mk.json +++ b/i18n/mk.json @@ -14,6 +14,8 @@ "add_a_location": "Додади ĐģĐžĐēĐ°Ņ†Đ¸Ņ˜Đ°", "add_a_name": "Додади иĐŧĐĩ", "add_a_title": "Додади ĐŊĐ°ŅĐģОв", + "add_birthday": "Додади Ņ€ĐžĐ´ĐĩĐŊĐ´ĐĩĐŊ", + "add_endpoint": "Додади ĐēŅ€Đ°Ņ˜ĐŊа Ņ‚ĐžŅ‡Đēа", "add_exclusion_pattern": "Додади ŅˆĐ°ĐąĐģĐžĐŊ Са Đ¸ŅĐēĐģŅƒŅ‡ŅƒĐ˛Đ°ŅšĐĩ", "add_import_path": "Додади ĐŋĐ°Ņ‚ĐĩĐēа Са иĐŧĐŋĐžŅ€Ņ‚Đ¸Ņ€Đ°ŅšĐĩ", "add_location": "Додади ĐģĐžĐēĐ°Ņ†Đ¸Ņ˜Đ°", @@ -21,8 +23,15 @@ "add_partner": "Додади ĐŋĐ°Ņ€Ņ‚ĐŊĐĩŅ€", "add_path": "Додади ĐŋĐ°Ņ‚ĐĩĐēа", "add_photos": "Додади ҁĐģиĐēи", + "add_tag": "Додади ОСĐŊаĐēа", "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_some_local_assets": "НĐĩĐēОи ĐģĐžĐēаĐģĐŊи Ņ€ĐĩŅŅƒŅ€ŅĐ¸ ĐŊĐĩ ĐŧĐžĐļĐĩа да ҁĐĩ Đ´ĐžĐ´Đ°Đ´Đ°Ņ‚ вО аĐģĐąŅƒĐŧĐžŅ‚", + "add_to_album_toggle": "ĐŸŅ€ĐžĐŧĐĩĐŊи Ņ˜Đ° ҁĐĩĐģĐĩĐēŅ†Đ¸Ņ˜Đ°Ņ‚Đ° Са {album}", + "add_to_albums": "Додади вО аĐģĐąŅƒĐŧи", + "add_to_albums_count": "Додади вО аĐģĐąŅƒĐŧи ({count})", "add_to_shared_album": "Додади вО ҁĐŋОдĐĩĐģĐĩĐŊ аĐģĐąŅƒĐŧ", "add_url": "Додади URL", "added_to_archive": "ДодадĐĩĐŊĐž вО Đ°Ņ€Ņ…Đ¸Đ˛Đ°", @@ -30,17 +39,25 @@ "added_to_favorites_count": "ДодадĐĩĐŊи {count, number} вО ĐžĐŧиĐģĐĩĐŊи", "admin": { "add_exclusion_pattern_description": "Додади ŅˆĐ°ĐąĐģĐžĐŊи Са Đ¸ŅĐēĐģŅƒŅ‡ŅƒĐ˛Đ°ŅšĐĩ. ĐŸĐžĐ´Đ´Ņ€ĐļаĐŊĐž Đĩ ĐēĐžŅ€Đ¸ŅŅ‚ĐĩҚĐĩ ĐŊа glob ŅĐž *, **, и ?. За да ҁĐĩ Đ¸ĐŗĐŊĐžŅ€Đ¸Ņ€Đ°Đ°Ņ‚ ŅĐ¸Ņ‚Đĩ Đ´Đ°Ņ‚ĐžŅ‚ĐĩĐēи вО ĐēĐžŅ˜ йиĐģĐž Đ´Đ¸Ņ€ĐĩĐēŅ‚ĐžŅ€Đ¸ŅƒĐŧ иĐŧĐĩĐŊŅƒĐ˛Đ°ĐŊ \"Raw\", ĐēĐžŅ€Đ¸ŅŅ‚Đ¸ \"**/Raw/**\". За да ҁĐĩ Đ¸ĐŗĐŊĐžŅ€Đ¸Ņ€Đ°Đ°Ņ‚ ŅĐ¸Ņ‚Đĩ Đ´Đ°Ņ‚ĐžŅ‚ĐĩĐēи ŅˆŅ‚Đž ĐˇĐ°Đ˛Ņ€ŅˆŅƒĐ˛Đ°Đ°Ņ‚ ŅĐž \".tif\", ĐēĐžŅ€Đ¸ŅŅ‚Đ¸ \"**/*.tif\". За да ҁĐĩ Đ¸ĐŗĐŊĐžŅ€Đ¸Ņ€Đ° аĐŋŅĐžĐģŅƒŅ‚ĐŊа ĐŋĐ°Ņ‚ĐĩĐēа, ĐēĐžŅ€Đ¸ŅŅ‚Đ¸ \"/path/to/ignore/**\".", + "admin_user": "АдĐŧиĐŊĐ¸ŅŅ‚Ņ€Đ°Ņ‚Đ¸Đ˛ĐĩĐŊ ĐšĐžŅ€Đ¸ŅĐŊиĐē", "asset_offline_description": "Ова ҁҀĐĩĐ´ŅŅ‚Đ˛Đž Од ĐĩĐēҁ҂ĐĩŅ€ĐŊа йийĐģĐ¸ĐžŅ‚ĐĩĐēа вĐĩҜĐĩ ĐŊĐĩ Đĩ ĐŋŅ€ĐžĐŊĐ°Ņ˜Đ´ĐĩĐŊĐž ĐŊа Đ´Đ¸ŅĐēĐžŅ‚ и Đĩ ĐŋŅ€ĐĩĐŧĐĩҁ҂ĐĩĐŊĐž вО Ņ“ŅƒĐąŅ€Đĩ. АĐēĐž Đ´Đ°Ņ‚ĐžŅ‚ĐĩĐēĐ°Ņ‚Đ° йиĐģа ĐŋŅ€ĐĩĐŧĐĩҁ҂ĐĩĐŊа вО Ņ€Đ°ĐŧĐēĐ¸Ņ‚Đĩ ĐŊа йийĐģĐ¸ĐžŅ‚ĐĩĐēĐ°Ņ‚Đ°, ĐŋŅ€ĐžĐ˛ĐĩŅ€ĐĩŅ‚Đĩ Ņ˜Đ° Đ˛Đ°ŅˆĐ°Ņ‚Đ° Đ˛Ņ€ĐĩĐŧĐĩĐŊҁĐēа ĐģиĐŊĐ¸Ņ˜Đ° Са ĐŊĐžĐ˛ĐžŅ‚Đž ŅĐžĐžĐ´Đ˛ĐĩŅ‚ĐŊĐž ҁҀĐĩĐ´ŅŅ‚Đ˛Đž. За да ĐŗĐž Đ˛Ņ€Đ°Ņ‚Đ¸Ņ‚Đĩ Ова ҁҀĐĩĐ´ŅŅ‚Đ˛Đž, ĐžŅĐ¸ĐŗŅƒŅ€Đ°Ņ˜Ņ‚Đĩ ҁĐĩ Đ´ĐĩĐēа Đ´ĐžĐģ҃ĐŊавĐĩĐ´ĐĩĐŊĐ°Ņ‚Đ° ĐŋĐ°Ņ‚ĐĩĐēа ĐŧĐžĐļĐĩ да йидĐĩ ĐŋŅ€Đ¸ŅŅ‚Đ°ĐŋĐĩĐŊа Од Immich и ҁĐēĐĩĐŊĐ¸Ņ€Đ°Ņ˜Ņ‚Đĩ Ņ˜Đ° йийĐģĐ¸ĐžŅ‚ĐĩĐēĐ°Ņ‚Đ°.", "authentication_settings": "ĐŸĐžŅŅ‚Đ°Đ˛Đēи Са Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸ĐēĐ°Ņ†Đ¸Ņ˜Đ°", "authentication_settings_description": "ĐŖĐŋŅ€Đ°Đ˛ŅƒĐ˛Đ°Ņ˜ ŅĐž ĐģОСиĐŊĐēи, OAuth, и Đ´Ņ€ŅƒĐŗĐ¸ ĐŋĐžŅŅ‚Đ°Đ˛Đēи Са Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸ĐēĐ°Ņ†Đ¸Ņ˜Đ°", "authentication_settings_disable_all": "ДаĐģи ҁ҂Đĩ ŅĐ¸ĐŗŅƒŅ€ĐŊи Đ´ĐĩĐēа ŅĐ°ĐēĐ°Ņ‚Đĩ да ĐŗĐ¸ Đ¸ŅĐēĐģŅƒŅ‡Đ¸Ņ‚Đĩ ŅĐ¸Ņ‚Đĩ ĐŧĐĩŅ‚ĐžĐ´Đ¸ Са ĐŊĐ°Ņ˜Đ°Đ˛Đ°? ĐĻĐĩĐģĐžŅĐŊĐž ҜĐĩ йидĐĩ ĐžĐŊĐĩвОСĐŧĐžĐļĐĩĐŊĐž ĐŊĐ°Ņ˜Đ°Đ˛ŅƒĐ˛Đ°ŅšĐĩ.", "authentication_settings_reenable": "За ĐŋĐžĐ˛Ņ‚ĐžŅ€ĐŊĐž да ОвОСĐŧĐžĐļĐ¸Ņ‚Đĩ, Đ¸ŅĐēĐžŅ€Đ¸ŅŅ‚ĐĩŅ‚Đĩ ĐĄĐĩŅ€Đ˛ĐĩŅ€ ĐēĐžĐŧаĐŊда.", "background_task_job": "ПозадиĐŊҁĐēи ĐˇĐ°Đ´Đ°Ņ‡Đ¸", - "backup_database": "Đ ĐĩСĐĩŅ€Đ˛ĐŊа ĐēĐžĐŋĐ¸Ņ˜Đ° Од ĐąĐ°ĐˇĐ°Ņ‚Đ° ĐŊа ĐŋĐžĐ´Đ°Ņ‚ĐžŅ†Đ¸", + "backup_database": "ĐšŅ€ĐĩĐ¸Ņ€Đ°Ņ˜ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊа ĐēĐžĐŋĐ¸Ņ˜Đ° Од ĐąĐ°ĐˇĐ°Ņ‚Đ° ĐŊа ĐŋĐžĐ´Đ°Ņ‚ĐžŅ†Đ¸", "backup_database_enable_description": "ОвозĐŧĐžĐļи Ņ€ĐĩСĐĩŅ€Đ˛ĐŊи ĐēĐžĐŋии Од ĐąĐ°ĐˇĐ°Ņ‚Đ° ĐŊа ĐŋĐžĐ´Đ°Ņ‚ĐžŅ†Đ¸", "backup_keep_last_amount": "КоĐģĐ¸Ņ‡Đ¸ĐŊа ĐŊа ĐŋŅ€ĐĩŅ‚Ņ…ĐžĐ´ĐŊи Ņ€ĐĩСĐĩŅ€Đ˛ĐŊи ĐēĐžĐŋии Са Ņ‡ŅƒĐ˛Đ°ŅšĐĩ", - "backup_settings": "ĐŸĐžŅŅ‚Đ°Đ˛Đēи Са Ņ€ĐĩСĐĩŅ€Đ˛ĐŊи ĐēĐžĐŋии", - "backup_settings_description": "ĐŖĐŋŅ€Đ°Đ˛ŅƒĐ˛Đ°Ņ˜ ŅĐž ĐŋĐžŅŅ‚Đ°Đ˛Đēи Са Ņ€ĐĩСĐĩŅ€Đ˛ĐŊи ĐēĐžĐŋии ĐŊа ĐąĐ°ĐˇĐ°Ņ‚Đ° ĐŊа ĐŋĐžĐ´Đ°Ņ‚ĐžŅ†Đ¸", + "backup_onboarding_1_description": "ĐŊĐ°Đ´Đ˛ĐžŅ€Đĩ҈ĐŊа ĐēĐžĐŋĐ¸Ņ˜Đ° вО ОйĐģаĐēĐžŅ‚ иĐģи ĐŊа Đ´Ņ€ŅƒĐŗĐ° Ņ„Đ¸ĐˇĐ¸Ņ‡Đēа ĐģĐžĐēĐ°Ņ†Đ¸Ņ˜Đ°.", + "backup_onboarding_2_description": "ĐģĐžĐēаĐģĐŊи ĐēĐžĐŋии ĐŊа Ņ€Đ°ĐˇĐģĐ¸Ņ‡ĐŊи ŅƒŅ€Đĩди. Ова ĐŗĐ¸ вĐēĐģŅƒŅ‡ŅƒĐ˛Đ° и ĐžŅĐŊОвĐŊĐ¸Ņ‚Đĩ Ņ„Ņ˜Đ°ĐģОви и Ņ€ĐĩСĐĩŅ€Đ˛ĐŊа ĐēĐžĐŋĐ¸Ņ˜Đ° Од Đ¸ŅŅ‚Đ¸Ņ‚Đĩ Ņ„Đ°Ņ˜ĐģОви ĐģĐžĐēаĐģĐŊĐž.", + "backup_onboarding_3_description": "ŅĐ¸Ņ‚Đĩ ĐēĐžĐŋии Од Ņ‚Đ˛ĐžĐ¸Ņ‚Đĩ ĐŋĐžĐ´Đ°Ņ‚ĐžŅ†Đ¸, вĐēĐģŅƒŅ‡ŅƒĐ˛Đ°Ņ˜ŅœĐ¸ и ĐžŅ€ĐŗĐ¸ĐŊаĐģĐŊĐ¸Ņ‚Đĩ Ņ„Đ°Ņ˜ĐģОви. Ова вĐēĐģŅƒŅ‡ŅƒĐ˛Đ° и 1 ĐŊĐ°Đ´Đ˛ĐžŅ€Đĩ҈ĐŊа ĐēĐžĐŋĐ¸Ņ˜Đ° и 2 ĐģĐžĐēаĐģĐŊи ĐēĐžĐŋии.", + "backup_onboarding_description": "3-2-1 ŅŅ‚Ņ€Đ°Ņ‚ĐĩĐŗĐ¸Ņ˜Đ° Са Ņ€ĐĩСĐĩŅ€Đ˛ĐŊа ĐēĐžĐŋĐ¸Ņ˜Đ° Đĩ ĐŋŅ€ĐĩĐŋĐžŅ€Đ°Ņ‡Đ°ĐŊĐž Са да ĐŗĐ¸ ĐˇĐ°ŅˆŅ‚Đ¸Ņ‚Đ¸ Ņ‚Đ˛ĐžĐ¸Ņ‚Đĩ ĐŋĐžĐ´Đ°Ņ‚ĐžŅ†Đ¸. ĐŸĐžŅ‚Ņ€ĐĩĐąĐŊĐž Đĩ да Ņ‡ŅƒĐ˛Đ°Ņˆ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊи ĐēĐžĐŋии Од Ņ‚Đ˛ĐžĐ¸Ņ‚Đĩ ĐŋŅ€Đ¸ĐēĐ°Ņ‡ĐĩĐŊи Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đ¸/видĐĩа ĐēаĐēĐž и ĐąĐ°ĐˇĐ°Ņ‚Đ° Са ĐŋĐžĐ´Đ°Ņ‚ĐžŅ†Đ¸ ĐŊа Immich Са ҆ĐĩĐģĐžŅĐŊĐž Ņ€Đĩ҈ĐĩĐŊиĐĩ Са ĐˇĐ°Ņ‡ŅƒĐ˛ŅƒĐ˛Đ°ŅšĐĩ ĐŊа Ņ€ĐĩСĐĩŅ€Đ˛ĐŊа ĐēĐžĐŋĐ¸Ņ˜Đ°", + "backup_onboarding_footer": "ПовĐĩҜĐĩ иĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Đ¸ ĐžĐēĐžĐģ҃ ĐŋŅ€Đ°Đ˛ĐĩҚĐĩ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊи ĐēĐžĐŋии Са Immich, вĐĩ ĐŧĐžĐģаĐŧ да ҁĐĩ Ņ€ĐĩŅ„ĐĩŅ€ĐĩĐŊŅ†Đ¸Ņ€Đ°Ņ‚Đĩ ĐŊа Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸Ņ˜Đ°Ņ‚Đ°", + "backup_onboarding_parts_title": "3-2-1 Ņ€ĐĩСĐĩŅ€Đ˛ĐŊа ĐēĐžĐŋĐ¸Ņ˜Đ° вĐēĐģŅƒŅ‡ŅƒĐ˛Đ°:", + "backup_onboarding_title": "Đ ĐĩСĐĩŅ€Đ˛ĐŊи ĐēĐžĐŋии", + "backup_settings": "ĐŸĐžŅŅ‚Đ°Đ˛Đēи иСвĐĩĐˇŅƒĐ˛Đ°ŅšĐĩ йаСа ĐŊа ĐŋĐžĐ´Đ°Ņ‚ĐžŅ†Đ¸", + "backup_settings_description": "ĐŖĐŋŅ€Đ°Đ˛ŅƒĐ˛Đ°Ņ˜ ŅĐž ĐŋĐžŅŅ‚Đ°Đ˛Đēи Са иСвĐĩĐˇŅƒĐ˛Đ°ŅšĐĩ ĐŊа ĐąĐ°ĐˇĐ°Ņ‚Đ° ĐŊа ĐŋĐžĐ´Đ°Ņ‚ĐžŅ†Đ¸", "cleared_jobs": "Đ˜ŅŅ‡Đ¸ŅŅ‚ĐĩĐŊи ĐˇĐ°Đ´Đ°Ņ‡Đ¸ Са: {job}", "config_set_by_file": "КоĐŊĐŗĐ¸ĐŗŅƒŅ€Đ°Ņ†Đ¸Ņ˜Đ°Ņ‚Đ° Đĩ ĐŧĐžĐŧĐĩĐŊŅ‚Đ°ĐģĐŊĐž ĐŋĐžŅŅ‚Đ°Đ˛ĐĩĐŊа Од ĐēĐžĐŊŅ„Đ¸ĐŗŅƒŅ€Đ°Ņ†Đ¸ŅĐēа Đ´Đ°Ņ‚ĐžŅ‚ĐĩĐēа", "confirm_delete_library": "ДаĐģи ҁ҂Đĩ ŅĐ¸ĐŗŅƒŅ€ĐŊи Đ´ĐĩĐēа ŅĐ°ĐēĐ°Ņ‚Đĩ да Ņ˜Đ° Đ¸ĐˇĐąŅ€Đ¸ŅˆĐĩŅ‚Đĩ йийĐģĐ¸ĐžŅ‚ĐĩĐēĐ°Ņ‚Đ° {library}?", @@ -48,19 +65,40 @@ "confirm_email_below": "За да ĐŋĐžŅ‚Đ˛Ņ€Đ´Đ¸Ņ‚Đĩ, вĐŊĐĩҁĐĩŅ‚Đĩ \"{email}\" Đ´ĐžĐģĐĩ", "confirm_reprocess_all_faces": "ДаĐģи ҁ҂Đĩ ŅĐ¸ĐŗŅƒŅ€ĐŊи Đ´ĐĩĐēа ŅĐ°ĐēĐ°Ņ‚Đĩ да ҁĐĩ ĐžĐąŅ€Đ°ĐąĐžŅ‚Đ°Ņ‚ ОдĐŊОвО ŅĐ¸Ņ‚Đĩ ĐģĐ¸Ņ†Đ°? Ова ҜĐĩ ĐŗĐ¸ Đ¸ĐˇĐąŅ€Đ¸ŅˆĐĩ и ŅĐ¸Ņ‚Đĩ иĐŧĐĩĐŊŅƒĐ˛Đ°ĐŊи ĐģŅƒŅ“Đĩ.", "confirm_user_password_reset": "ДаĐģи ҁ҂Đĩ ŅĐ¸ĐŗŅƒŅ€ĐŊи Đ´ĐĩĐēа ŅĐ°ĐēĐ°Ņ‚Đĩ да ҁĐĩ ĐŋĐžĐŊĐ¸ŅˆŅ‚Đ¸ ĐģОСиĐŊĐēĐ°Ņ‚Đ° ĐŊа {user}?", + "confirm_user_pin_code_reset": "ДаĐģи ŅĐ¸ĐŗŅƒŅ€ĐŊĐž ŅĐ°ĐēĐ°Ņˆ да ĐŗĐž ҁĐŧĐĩĐŊĐ¸Ņ‚Đĩ ПИН ĐēĐžĐ´ĐžŅ‚ Са {user}", "create_job": "ХОСдади ĐˇĐ°Đ´Đ°Ņ‡Đ°", "cron_expression": "Cron Đ¸ĐˇŅ€Đ°Đˇ", "cron_expression_description": "ПодĐĩŅĐ¸ ĐŗĐž иĐŊŅ‚ĐĩŅ€Đ˛Đ°ĐģĐžŅ‚ ĐŊа ҁĐēĐĩĐŊĐ¸Ņ€Đ°ŅšĐĩ ĐēĐžŅ€Đ¸ŅŅ‚ĐĩŅ˜ŅœĐ¸ ĐŗĐž cron Ņ„ĐžŅ€ĐŧĐ°Ņ‚ĐžŅ‚. За ĐŋОвĐĩҜĐĩ иĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Đ¸ ĐŋĐžĐŗĐģĐĩĐ´ĐŊĐĩŅ‚Đĩ ĐŊа ĐŋŅ€. Crontab Guru", "cron_expression_presets": "ĐŸŅ€ĐĩĐ´ĐĩŅ„Đ¸ĐŊĐ¸Ņ€Đ°ĐŊи Cron Đ¸ĐˇŅ€Đ°ĐˇĐ¸", "disable_login": "ОĐŊĐĩвОСĐŧĐžĐļи ĐŊĐ°Ņ˜Đ°Đ˛Đ°", "duplicate_detection_job_description": "ĐŸŅƒŅˆŅ‚Đ¸ ĐŧĐ°ŅˆĐ¸ĐŊҁĐēĐž ŅƒŅ‡ĐĩҚĐĩ ĐŊа ҁҀĐĩĐ´ŅŅ‚Đ˛Đ°Ņ‚Đ° Са да ҁĐĩ ĐžŅ‚ĐēŅ€Đ¸Ņ˜Đ°Ņ‚ ҁĐģĐ¸Ņ‡ĐŊи ҁĐģиĐēи. ĐĄĐĩ ĐŋĐžŅ‚ĐŋĐ¸Ņ€Đ° ĐŊа Smart Search", + "external_library_management": "МĐĩĐŊĐ°ŅŸĐŧĐĩĐŊŅ‚ ĐŊа ĐĐ°Đ´Đ˛ĐžŅ€Đĩ҈ĐŊа БибĐģĐ¸ĐžŅ‚ĐĩĐēа", + "face_detection": "ДĐĩŅ‚ĐĩĐēŅ†Đ¸Ņ˜Đ° ĐŊа ĐģĐ¸Ņ†Đĩ", "force_delete_user_warning": "ĐŸĐ Đ•Đ”ĐŖĐŸĐ Đ•Đ”ĐŖĐ’ĐĐŠĐ•: Ова вĐĩĐ´ĐŊĐ°Ņˆ ҜĐĩ ĐŗĐž ĐžŅ‚ŅŅ‚Ņ€Đ°ĐŊи ĐēĐžŅ€Đ¸ŅĐŊиĐēĐžŅ‚ и ŅĐ¸Ņ‚Đĩ ҁҀĐĩĐ´ŅŅ‚Đ˛Đ°. Оваа аĐēŅ†Đ¸Ņ˜Đ° ĐŊĐĩ ĐŧĐžĐļĐĩ да ҁĐĩ ĐŋĐžĐŊĐ¸ŅˆŅ‚Đ¸ и Đ´Đ°Ņ‚ĐžŅ‚ĐĩĐēĐ¸Ņ‚Đĩ ĐŊĐĩĐŧа да ĐŧĐžĐļĐĩ да ҁĐĩ Đ˛Ņ€Đ°Ņ‚Đ°Ņ‚ ĐŊаСад.", "image_format": "Đ¤ĐžŅ€ĐŧĐ°Ņ‚", + "image_format_description": "WebP ŅĐžĐˇĐ´Đ°Đ˛Đ° ĐŋĐžĐŧаĐģи Ņ„Đ°Ņ˜Đģви ĐžŅ‚ĐēĐžĐģĐē҃ JPEG, ĐŊĐž Đĩ ĐŋĐž ҁĐŋĐžŅ€ ĐŋŅ€Đ¸ ĐĩĐŊĐēĐžĐ´Đ¸Ņ€Đ°ŅšĐĩ.", + "image_fullsize_enabled": "ОвозĐŧĐžĐļи ҆ĐĩĐģĐžŅĐŊа-ĐŗĐžĐģĐĩĐŧиĐŊа ĐŊа ĐŗĐĩĐŊĐĩŅ€Đ¸Ņ€Đ°ŅšĐĩ ĐŊа ҁĐģиĐēа", + "image_fullsize_quality_description": "ĐĻĐĩĐģĐžŅĐŊа-ĐŗĐžĐģĐĩĐŧиĐŊа ĐŊа ҁĐģиĐēа ŅĐž ĐēваĐģĐ¸Ņ‚ĐĩŅ‚ Од 1-100. ĐŸĐžĐ˛Đ¸ŅĐžĐēŅ‚Đž Đĩ ĐŋĐžĐ´ĐžĐąŅ€Đž, ĐŊĐž ŅĐžĐˇĐ´Đ°Đ˛Đ° ĐŋĐžĐŗĐžĐģĐĩĐŧи Ņ„Đ°Ņ˜ĐģОви.", + "image_fullsize_title": "ĐŸĐžŅŅ‚Đ°Đ˛Đēи Са ĐĻĐĩĐģĐžŅĐŊа-ĐŗĐžĐģĐĩĐŧиĐŊа ĐŊа ĐĄĐģиĐēа", + "image_prefer_embedded_preview": "ĐŸŅ€ĐĩŅ‚ĐŋĐžŅ‡Đ¸Ņ‚Đ°ĐŊ Đ˛ĐŗŅ€Đ°Đ´ĐĩĐŊ ĐŋŅ€ĐĩĐŗĐģĐĩĐ´", + "image_preview_title": "ĐŸĐžŅŅ‚Đ°Đ˛Đēи Са ĐŸŅ€ĐĩĐŗĐģĐĩĐ´", "image_quality": "КваĐģĐ¸Ņ‚ĐĩŅ‚", "image_resolution": "Đ ĐĩСОĐģŅƒŅ†Đ¸Ņ˜Đ°", "image_settings": "ĐŸĐžŅŅ‚Đ°Đ˛Đēи Са ҁĐģиĐēи", + "job_concurrency": "{job} ĐēĐžĐŊĐēŅƒŅ€ĐĩĐŊŅ‚ĐŊĐžŅŅ‚", + "job_created": "ĐšŅ€ĐĩĐ¸Ņ€Đ°ĐŊа ĐˇĐ°Đ´Đ°Ņ‡Đ°", + "job_not_concurrency_safe": "Оваа ĐˇĐ°Đ´Đ°Ņ‡Đ° ĐŊĐĩ Đĩ ĐēĐžĐŊĐēŅƒŅ€ĐĩŅ‚ĐŊĐž-ĐąĐĩСйĐĩĐ´ĐŊа.", + "job_settings": "ĐŸĐžŅŅ‚Đ°Đ˛Đēи Са ĐˇĐ°Đ´Đ°Ņ‡Đ°", + "job_settings_description": "ĐŖĐŋŅ€Đ°Đ˛ŅƒĐ˛Đ°Ņ˜ ŅĐž ĐēĐžĐŊĐēŅƒŅ€ĐĩĐŊŅ‚ĐŊĐžŅŅ‚ ĐŊа ĐˇĐ°Đ´Đ°Ņ‡Đ¸", + "job_status": "ĐĄŅ‚Đ°Ņ‚ŅƒŅ ĐŊа ĐˇĐ°Đ´Đ°Ņ‡Đ¸", + "library_created": "ĐšŅ€ĐĩĐ¸Ņ€Đ°ĐŊа йийĐģĐ¸ĐžŅ‚ĐĩĐēа: {library}", + "library_deleted": "БибĐģĐ¸ĐžŅ‚ĐĩĐēĐ°Ņ‚Đ° Đĩ Đ¸ĐˇĐąŅ€Đ¸ŅˆĐ°ĐŊа", + "library_import_path_description": "ĐŸŅ€ĐĩĐ´ĐģĐžĐļи ĐŋаĐŋĐēа Са вĐŊĐĩҁ. Оваа ĐŋаĐŋĐēа, вĐēĐģŅƒŅ‡ŅƒĐ˛Đ° и ĐŋОд ĐŋаĐŋĐēи, ҜĐĩ йидĐĩ ҁĐēĐĩĐŊĐ¸Ņ€Đ°ĐŊа Са ҁĐģиĐēи и видĐĩа.", "library_scanning": "ПĐĩŅ€Đ¸ĐžĐ´Đ¸Ņ‡ĐŊĐž ҁĐēĐĩĐŊĐ¸Ņ€Đ°ŅšĐĩ", + "library_scanning_description": "ПодĐĩŅĐ¸ ĐŋĐĩŅ€Đ¸ĐžĐ´Đ¸Ņ‡ĐŊĐž ҁĐēĐĩĐŊĐ¸Ņ€Đ°ĐŊҘĐĩ ĐŊа йийĐģĐ¸ĐžŅ‚ĐĩĐēĐ°Ņ‚Đ°", + "library_scanning_enable_description": "ОвозĐŧĐžĐļи ĐŋĐĩŅ€Đ¸ĐžĐ´Đ¸Ņ‡ĐŊĐž ҁĐēĐĩĐŊĐ¸Ņ€Đ°ĐŊҘĐĩ ĐŊа йийĐģĐ¸ĐžŅ‚ĐĩĐēĐ°Ņ‚Đ°", "library_settings": "ЕĐēҁ҂ĐĩŅ€ĐŊа йийĐģĐ¸ĐžŅ‚ĐĩĐēа", + "library_settings_description": "ĐŖĐŋŅ€Đ°Đ˛ŅƒĐ˛Đ°Ņ˜ ŅĐž ĐŋОдĐĩŅŅƒĐ˛Đ°ŅšĐ°Ņ‚Đ° Са ĐŊĐ°Đ´Đ˛ĐžŅ€Đĩ҈ĐŊĐ°Ņ‚Đ° йийĐģĐ¸ĐžŅ‚ĐĩĐēа", "logging_enable_description": "ВĐēĐģŅƒŅ‡Đ¸ ĐĩвидĐĩĐŊŅ‚Đ¸Ņ€Đ°ŅšĐĩ", "logging_settings": "ЕвидĐĩĐŊŅ‚Đ¸Ņ€Đ°ŅšĐĩ", "map_dark_style": "ĐĸĐĩĐŧĐĩĐŊ ŅŅ‚Đ¸Đģ", diff --git a/i18n/ml.json b/i18n/ml.json index 1ef0b46e66..0c85d53bd3 100644 --- a/i18n/ml.json +++ b/i18n/ml.json @@ -1,87 +1,2135 @@ { - "about": "ā´ĩā´ŋⴎⴝⴤāĩā´¤āĩ†ā´•āĩā´•āĩā´ąā´ŋⴚāĩā´šāĩ", + "about": "ā´•āĩā´ąā´ŋⴚāĩā´šāĩ", "account": "ā´…ā´•āĩā´•āĩ—ā´Ŗāĩā´Ÿāĩ", - "account_settings": "ā´…ā´•āĩā´•āĩ—ā´Ŗāĩā´Ÿāĩ ā´¸āĩ†ā´ąāĩā´ąā´ŋā´‚ā´—āĩā´¸āĩ", + "account_settings": "ā´…ā´•āĩā´•āĩ—ā´Ŗāĩā´Ÿāĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", "acknowledge": "ā´…ā´‚ā´—āĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´•", - "action": "ⴆⴕāĩā´ˇā´¨āĩâ€", - "action_common_update": "ā´Ēāĩā´¤āĩā´•āĩā´•āĩā´•", + "action": "ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´‚", + "action_common_update": "ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", "actions": "ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋā´•āĩž", - "active": "ⴏⴜāĩ€ā´ĩā´Žā´žā´¯ā´ĩ", - "activity": "ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´™āĩā´™āĩž", + "active": "ⴏⴜāĩ€ā´ĩā´‚", + "activity": "ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´‚", + "activity_changed": "ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´‚ {enabled, select, true {ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•ā´ŋ} other {ā´¨ā´ŋāĩŧⴜāĩā´œāĩ€ā´ĩā´Žā´žā´•āĩā´•ā´ŋ}}", "add": "ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", - "add_a_description": "ā´’ā´°āĩ ā´ĩā´ŋā´ĩā´°ā´Ŗā´‚ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", - "add_a_location": "ā´’ā´°āĩ ā´¸āĩā´Ĩⴞⴂ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", - "add_a_name": "ā´’ā´°āĩ ā´Ēāĩ‡ā´°āĩ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", - "add_a_title": "ā´’ā´°āĩ ā´ļāĩ€āĩŧⴎⴕⴂ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", + "add_a_description": "ā´ĩā´ŋā´ĩā´°ā´Ŗā´‚ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", + "add_a_location": "ā´¸āĩā´Ĩā´žā´¨ā´‚ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", + "add_a_name": "ā´Ēāĩ‡ā´°āĩ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", + "add_a_title": "ā´ļāĩ€āĩŧⴎⴕⴂ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", "add_birthday": "ⴜⴍāĩā´Žā´Ļā´ŋⴍⴂ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", - "add_endpoint": "ā´Žāĩģā´Ąāĩā´Ēāĩ‹ā´¯ā´ŋā´¨āĩā´ąāĩ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", - "add_exclusion_pattern": "ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•ā´žā´¨āĩā´ŗāĩā´ŗ ā´Žā´žā´¤āĩƒā´• ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", - "add_import_path": "ā´‡ā´ąā´•āĩā´•āĩā´Žā´¤ā´ŋ ⴚāĩ†ā´¯āĩā´¯āĩā´•", - "add_location": "ā´¸āĩā´Ĩā´˛ā´¨ā´žā´Žā´‚ ⴚāĩ‡ā´°āĩâ€ā´•āĩā´•āĩā´•", - "add_more_users": "ā´•āĩ‚ā´Ÿāĩā´¤ā´˛āĩâ€ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´•āĩā´•ā´ŗāĩ† ⴚāĩ‡ā´°āĩâ€ā´•āĩā´•āĩā´•", - "add_partner": "ā´Ēā´™āĩā´•ā´žā´ŗā´ŋā´¯āĩ† ⴚāĩ‡ā´°āĩâ€ā´•āĩā´•āĩā´•", - "add_path": "ā´Ēā´žā´¤ ⴚāĩ‡ā´°āĩâ€ā´•āĩā´•āĩā´•", - "add_photos": "ⴚā´ŋā´¤āĩā´°ā´™āĩā´™ā´ŗāĩâ€ ⴚāĩ‡ā´°āĩâ€ā´•āĩā´•āĩā´•", - "add_tag": "ā´Ÿā´žā´—āĩ ⴚāĩ‡ā´°āĩâ€ā´•āĩā´•āĩā´•", - "add_to": "ⴚāĩ‡ā´°āĩâ€ā´•āĩā´•āĩā´•â€Ļ", - "add_to_album": "ⴆⴞāĩâ€ā´Ŧā´¤āĩā´¤ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ⴚāĩ‡ā´°āĩâ€ā´•āĩā´•āĩā´•", - "add_to_album_bottom_sheet_added": "{album} - ā´˛āĩ‡ā´•āĩā´•āĩ ⴚāĩ‡ā´°āĩâ€ā´¤āĩā´¤āĩ", - "add_to_album_bottom_sheet_already_exists": "{album} ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋāĩŊ ā´‡ā´Ēāĩā´Ēāĩ‹ā´ŗāĩâ€ ⴤⴍāĩā´¨āĩ† ⴉ⴪āĩā´Ÿāĩ", - "add_to_albums": "ā´†āĩŊā´Ŧā´™āĩā´™ā´ŗā´ŋāĩŊ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", - "add_to_albums_count": "ā´†āĩŊā´Ŧā´™āĩā´™ā´ŗā´ŋāĩŊ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´• ({count})", + "add_endpoint": "ā´Žāĩģā´Ąāĩâ€Œā´Ēāĩ‹ā´¯ā´ŋā´¨āĩā´ąāĩ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", + "add_exclusion_pattern": "ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•āĩŊ ā´Ēā´žā´ąāĩā´ąāĩ‡āĩē ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", + "add_import_path": "ā´‡ā´Žāĩā´Ēāĩ‹āĩŧⴟāĩā´Ÿāĩ ā´Ēā´žā´¤āĩā´¤āĩ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", + "add_location": "ā´¸āĩā´Ĩā´žā´¨ā´‚ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", + "add_more_users": "ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´•āĩā´•ā´ŗāĩ† ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", + "add_partner": "ā´Ēā´™āĩā´•ā´žā´ŗā´ŋā´¯āĩ† ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", + "add_path": "ā´Ēā´žā´¤āĩā´¤āĩ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", + "add_photos": "ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", + "add_tag": "ā´Ÿā´žā´—āĩ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", + "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_some_local_assets": "ⴚā´ŋā´˛ ā´Ēāĩā´°ā´žā´Ļāĩ‡ā´ļā´ŋā´• ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ⴚāĩ‡āĩŧā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´žāĩā´žā´ŋā´˛āĩā´˛", + "add_to_album_toggle": "{album}-ā´¨āĩā´ŗāĩā´ŗ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´Ēāĩā´Ēāĩ ⴟāĩ‹ā´—ā´ŋāĩž ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "add_to_albums": "ā´†āĩŊā´Ŧā´™āĩā´™ā´ŗā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", + "add_to_albums_count": "ā´†āĩŊā´Ŧā´™āĩā´™ā´ŗā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´• ({count})", "add_to_shared_album": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", - "add_url": "URL ⴚāĩ‡ā´°āĩâ€ā´•āĩā´•āĩā´•", - "added_to_archive": "ⴚⴰā´ŋā´¤āĩā´°ā´°āĩ‡ā´–ā´¯ā´žā´¯ā´ŋ (ⴆⴰāĩâ€ā´•āĩā´•āĩˆā´ĩāĩ) ⴚāĩ‡ā´°āĩâ€ā´¤āĩā´¤ā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ", - "added_to_favorites": "ⴇⴎāĩā´Ÿā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿā´ĩā´¯ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ⴚāĩ‡ā´°āĩâ€ā´¤āĩā´¤āĩ", - "added_to_favorites_count": "{count, number} ⴇⴎāĩā´Ÿā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿā´ĩā´¯ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ⴚāĩ‡ā´°āĩâ€ā´¤āĩā´¤āĩ", + "add_url": "URL ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", + "added_to_archive": "ā´†āĩŧā´•āĩā´•āĩˆā´ĩā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ⴚāĩ‡āĩŧā´¤āĩā´¤āĩ", + "added_to_favorites": "ā´Ēāĩā´°ā´ŋā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿā´ĩā´¯ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ⴚāĩ‡āĩŧā´¤āĩā´¤āĩ", + "added_to_favorites_count": "{count, number} ā´Žā´Ŗāĩā´Ŗā´‚ ā´Ēāĩā´°ā´ŋā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿā´ĩā´¯ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ⴚāĩ‡āĩŧā´¤āĩā´¤āĩ", "admin": { - "add_exclusion_pattern_description": "ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•āĩŊ ⴚā´ŋā´šāĩā´¨ā´™āĩā´™ā´ŗāĩâ€ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•. *, **, ? ā´Žā´¨āĩā´¨ā´ŋā´ĩ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩā´ŗāĩā´ŗ ā´—āĩā´˛āĩ‹ā´Ŧā´ŋā´‚ā´—āĩ ā´Ēā´ŋā´¨āĩā´¤āĩā´Ŗā´¯āĩā´•āĩā´•āĩā´¨āĩā´¨āĩ. \"Raw\" ā´Žā´¨āĩā´¨āĩ ā´Ēāĩ‡ā´°āĩā´ŗāĩā´ŗ ā´ā´¤āĩ†ā´™āĩā´•ā´ŋā´˛āĩā´‚ ā´Ąā´¯ā´ąā´•āĩā´Ÿā´ąā´ŋā´¯ā´ŋā´˛āĩ† ā´Žā´˛āĩā´˛ā´ž ā´Ģⴝⴞāĩā´•ā´ŗāĩā´‚ ā´…ā´ĩā´—ā´Ŗā´ŋā´•āĩā´•ā´žāĩģ, \"**/Raw/**\" ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•. \".tif\" āĩŊ ā´…ā´ĩā´¸ā´žā´¨ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ ā´Žā´˛āĩā´˛ā´ž ā´Ģⴝⴞāĩā´•ā´ŗāĩā´‚ ā´…ā´ĩā´—ā´Ŗā´ŋā´•āĩā´•ā´žāĩģ, \"**/*.tif\" ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•. ā´’ā´°āĩ ā´Ēā´°ā´ŋā´Ēāĩ‚āĩŧā´Ŗāĩā´Ŗā´Žā´žā´¯ ā´Ēā´žā´¤ ā´…ā´ĩā´—ā´Ŗā´ŋā´•āĩā´•ā´žāĩģ, \"/path/to/ignore/**\" ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•.", - "admin_user": "ā´­ā´°ā´Ŗā´žā´§ā´ŋā´•ā´žā´°ā´ŋ", - "asset_offline_description": "ⴈ ā´Ēāĩā´ąā´¤āĩā´¤āĩā´ŗāĩā´ŗ ā´ļāĩ‡ā´–ā´°ā´¤āĩā´¤ā´ŋā´˛āĩ† ā´ĩā´¸āĩā´¤āĩā´•āĩā´•ā´ŗāĩâ€ ⴇⴍā´ŋ ā´Ąā´ŋā´¸āĩā´•ā´ŋāĩŊ ā´•ā´žā´Ŗāĩā´¨āĩā´¨ā´ŋā´˛āĩā´˛, ā´…ā´ĩā´¯āĩ† ⴟāĩā´°ā´žā´ˇā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´¨āĩ€ā´•āĩā´•ā´ŋā´¯ā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ. ā´Ģā´¯āĩŊ ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋā´•āĩā´•āĩā´ŗāĩā´ŗā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´¨āĩ€ā´•āĩā´•ā´ŋā´¯ā´ŋⴟāĩā´Ÿāĩā´Ŗāĩā´Ÿāĩ†ā´™āĩā´•ā´ŋāĩŊ, ā´Ēāĩā´¤ā´ŋā´¯ ā´…ā´¨āĩā´Ŧā´¨āĩā´§ ā´ĩā´¸āĩā´¤āĩā´ĩā´ŋā´¨ā´žā´¯ā´ŋ ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´¸ā´Žā´¯ā´•āĩā´°ā´Žā´‚ (ⴟāĩˆā´‚ā´˛āĩˆā´¨āĩâ€) ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´ŋā´•āĩā´•āĩā´•. ⴈ ā´ĩā´¸āĩā´¤āĩ ā´Ēāĩā´¨ā´ƒā´¸āĩā´Ĩā´žā´Ēā´ŋā´•āĩā´•ā´žāĩģ, ā´¤ā´žā´´āĩ†ā´¯āĩā´ŗāĩā´ŗ ā´Ģā´¯āĩŊ ā´Ēā´žā´¤āĩā´¤āĩ ā´‡ā´Žāĩā´Žā´ŋⴚāĩā´šā´ŋā´¨āĩ ā´Žā´¤āĩā´¤ā´ŋā´Ēāĩā´Ēāĩ†ā´Ÿā´žā´¨āĩâ€ ā´•ā´´ā´ŋā´¯āĩā´Žāĩ†ā´¨āĩā´¨āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´•āĩā´•āĩā´•ā´¯āĩā´‚ ā´ļāĩ‡ā´–ā´°ā´‚ ā´Ēāĩā´¨ā´ƒā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´ŋā´•āĩā´•āĩā´•ā´¯āĩā´‚ (ā´¸āĩā´•ā´žāĩģ) ⴚāĩ†ā´¯āĩā´¯āĩā´•.", - "authentication_settings": "ⴆⴧā´ŋā´•ā´žā´°ā´ŋā´•ā´¤ā´ž ⴏⴜāĩā´œāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", - "authentication_settings_description": "ā´Ēā´žā´¸āĩā´¸āĩâ€Œā´ĩāĩ‡ā´°āĩâ€ā´Ąāĩâ€Œ, OAuth ā´¤āĩā´Ÿā´™āĩā´™ā´ŋā´¯ ⴏⴜāĩā´œāĩ€ā´•ā´°ā´Ŗā´™āĩā´™ā´ŗāĩâ€", - "authentication_settings_disable_all": "ā´Žā´˛āĩā´˛ā´ž ā´Ēāĩā´°ā´ĩāĩ‡ā´ļā´¨ (ā´˛āĩ‹ā´—ā´ŋāĩģ) ā´°āĩ€ā´¤ā´ŋā´•ā´ŗāĩā´‚ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹? ā´Ēāĩā´°ā´ĩāĩ‡ā´ļⴍⴙāĩā´™ā´ŗāĩâ€ ā´Ēāĩ‚āĩŧā´Ŗāĩā´Ŗā´Žā´žā´¯āĩā´‚ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´‚.", - "background_task_job": "ā´Ēā´ļāĩā´šā´žā´¤āĩā´¤ā´˛ ā´Ēāĩā´°ā´ĩā´°āĩâ€ā´¤āĩā´¤ā´ŋā´•ā´ŗāĩâ€", - "backup_database": "ā´Ąā´žā´ąāĩā´ąā´žā´Ŧāĩ‡ā´¸āĩ ā´Ąā´‚ā´Žāĩā´Ēāĩ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´•", - "backup_database_enable_description": "ā´Ąā´žā´ąāĩā´ąā´žā´Ŧāĩ‡ā´¸āĩ ā´Ąā´Žāĩā´Ēāĩā´•āĩž ā´Ēāĩā´°ā´žā´Ēāĩā´¤ā´Žā´žā´•āĩā´•āĩā´•", - "backup_keep_last_amount": "ā´Ēā´´ā´¯ ā´Ąā´žā´ąāĩā´ąā´žā´Ŧāĩ‡ā´¸āĩ ā´Ąā´Žāĩā´Ēāĩā´•āĩž ā´Žā´¤āĩā´°ā´¯āĩ†ā´Ŗāĩā´Ŗā´‚ ā´¸āĩ‚ā´•āĩā´ˇā´ŋā´•āĩā´•ā´Ŗā´‚", - "backup_settings": "ā´Ąā´žā´ąāĩā´ąā´žā´Ŧāĩ‡ā´¸āĩ ā´Ąā´Žāĩā´Ēāĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™ā´ŗāĩâ€", - "backup_settings_description": "ā´Ąā´žā´ąāĩā´ąā´žā´Ŧāĩ‡ā´¸āĩ ā´Ąā´Žāĩā´Ēāĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•.", - "cleared_jobs": "{job} - ā´¨āĩâ€ā´ąāĩ† ⴜāĩ‹ā´˛ā´ŋā´•ā´ŗāĩâ€ ā´Žā´žā´¯āĩā´šāĩā´šā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ", - "config_set_by_file": "ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™ā´ŗāĩâ€ ā´‡ā´Ēāĩā´Ēāĩ‹ā´ŗāĩâ€ ā´’ā´°āĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗ ā´Ģⴝⴞāĩâ€ ā´ĩā´´ā´ŋā´¯ā´žā´Ŗāĩ ā´¨ā´ŋā´ļāĩā´šā´¯ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤āĩ", - "confirm_delete_library": "{library} ā´Žā´žā´¯āĩā´šāĩā´šāĩ ⴕⴺⴝ⴪ⴂ ā´Žā´¨āĩā´¨āĩā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹?", - "confirm_delete_library_assets": "ⴈ ā´ļāĩ‡ā´–ā´°ā´‚ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´Ŗā´‚ ā´Žā´¨āĩā´¨āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹? ⴇⴤāĩ ā´‡ā´Žāĩā´Žā´ŋⴚāĩā´šā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ {count, plural, one {# contained asset} other {all # contained assets}} ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´‚, ⴇⴤāĩ ā´Ēā´´ā´¯ā´Ēⴟā´ŋā´¯ā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛. ā´Ģⴝⴞāĩā´•āĩž ā´Ąā´ŋā´¸āĩā´•ā´ŋāĩŊ ⴤⴍāĩā´¨āĩ† ā´¤āĩā´Ÿā´°āĩā´‚.", - "confirm_email_below": "ā´¤āĩ€ā´°āĩâ€ā´šāĩā´šā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¤āĩā´¤ā´žā´¨āĩâ€ {email} ā´¤ā´žā´´āĩ† ā´•āĩŠā´Ÿāĩā´•āĩā´•āĩā´•", - "confirm_reprocess_all_faces": "ā´Žā´˛āĩā´˛ā´ž ā´Žāĩā´–ā´™āĩā´™ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩā´‚ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´Ŗā´‚ ā´Žā´¨āĩā´¨āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹? ⴇⴤāĩ ⴇⴤā´ŋⴍⴕⴂ ā´Ēāĩ‡ā´°āĩ ⴚāĩ‡ā´°āĩâ€ā´¤āĩā´¤ ā´Žāĩā´–ā´™āĩā´™ā´ŗāĩ†ā´¯āĩā´‚ ⴆⴺāĩā´•ā´ŗāĩ†ā´¯āĩā´‚ ā´Žā´žā´¯āĩā´•āĩā´•āĩā´‚.", - "confirm_user_password_reset": "{user} ā´Žā´¨āĩā´¨ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩâ€ā´ąāĩ† ā´Ēā´žā´¸āĩā´¸āĩâ€Œā´ĩāĩ‡ā´°āĩâ€ā´Ąāĩâ€Œ ā´Ēāĩā´¨ā´ƒā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´ŋā´•āĩā´•ā´Ŗā´‚ ā´Žā´¨āĩā´¨āĩā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹?", - "confirm_user_pin_code_reset": "{user} ā´Žā´¨āĩā´¨ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩâ€ā´ąāĩ† PIN ā´Ēāĩā´¨ā´ƒā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´ŋā´•āĩā´•ā´Ŗā´‚ ā´Žā´¨āĩā´¨āĩā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹?", - "create_job": "ⴜāĩ‹ā´˛ā´ŋ ā´¸āĩƒā´ˇāĩā´Ÿā´ŋā´•āĩā´•āĩā´•", - "cron_expression": "ā´•āĩā´°āĩ‹ā´Ŗāĩâ€ (cron) ā´Ēāĩā´°ā´¯āĩ‹ā´—ā´ļāĩˆā´˛ā´ŋ", - "cron_expression_description": "ā´•āĩā´°āĩ‹āĩē ā´Ģāĩ‹āĩŧā´Žā´žā´ąāĩā´ąāĩ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ā´¸āĩā´•ā´žā´¨ā´ŋā´‚ā´—āĩ ā´‡ā´Ÿā´ĩāĩ‡ā´ŗ ⴏⴜāĩā´œā´Žā´žā´•āĩā´•āĩā´•. ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ ā´ĩā´ŋā´ĩā´°ā´™āĩā´™āĩžā´•āĩā´•āĩ Crontab Guru ⴏⴍāĩā´Ļā´°āĩâ€ā´ļā´ŋā´•āĩā´•āĩā´•", - "cron_expression_presets": "ā´Žāĩā´¨āĩâ€ā´•āĩ‚ā´Ÿāĩā´Ÿā´ŋ ⴤⴝāĩā´¯ā´žā´°āĩâ€ ⴚāĩ†ā´¯āĩā´¤ ā´•āĩā´°āĩ‹ā´Ŗāĩâ€ ā´Ēāĩā´°ā´ĩā´°āĩâ€ā´¤āĩā´¤ā´¨ā´ļāĩˆā´˛ā´ŋā´•ā´ŗāĩâ€", - "disable_login": "ā´˛āĩ‹ā´—ā´ŋā´¨āĩâ€ ⴤⴟⴝāĩā´•", - "duplicate_detection_job_description": "ā´¸ā´Žā´žā´¨ā´Žā´žā´¯ ⴚā´ŋā´¤āĩā´°ā´™āĩā´™āĩž ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´žāĩģ ā´ĩā´¸āĩā´¤āĩā´ĩā´šā´•ā´ŗā´ŋā´˛āĩâ€ ⴝⴍāĩā´¤āĩā´°ā´Ēⴠⴍⴂ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´•. ⴇⴤāĩ ā´¸āĩā´Žā´žāĩŧⴟāĩā´Ÿāĩ ⴏⴰāĩâ€ā´šāĩā´šā´ŋā´¨āĩ† ā´†ā´ļāĩā´°ā´¯ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ", - "exclusion_pattern_description": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ ā´¸āĩā´•ā´žāĩģ ⴚāĩ†ā´¯āĩā´¯āĩā´Žāĩā´Ēāĩ‹āĩž ā´Ģⴝⴞāĩā´•ā´ŗāĩā´‚ ā´Ģāĩ‹āĩžā´Ąā´ąāĩā´•ā´ŗāĩā´‚ ā´…ā´ĩā´—ā´Ŗā´ŋā´•āĩā´•ā´žāĩģ ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•ā´˛āĩâ€ ā´Žā´žā´¤āĩƒā´•ā´•ā´ŗāĩâ€ ā´¨ā´ŋā´™āĩā´™ā´ŗāĩ† ā´…ā´¨āĩā´ĩā´Ļā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ. RAW ā´Ģⴝⴞāĩā´•āĩž ā´Ēāĩ‹ā´˛āĩā´ŗāĩā´ŗ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‡ā´ąā´•āĩā´•āĩā´Žā´¤ā´ŋ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´¤ā´žāĩŊā´Ēāĩā´Ēā´°āĩā´¯ā´Žā´ŋā´˛āĩā´˛ā´žā´¤āĩā´¤ ā´Ģⴝⴞāĩā´•āĩž ā´…ā´Ÿā´™āĩā´™ā´ŋā´¯ ā´Ģāĩ‹āĩžā´Ąā´ąāĩā´•āĩž ⴉ⴪āĩā´Ÿāĩ†ā´™āĩā´•ā´ŋāĩŊ ⴇⴤāĩ ā´‰ā´Ēā´¯āĩ‹ā´—ā´Ēāĩā´°ā´Ļā´Žā´žā´Ŗāĩ.", - "external_library_management": "ā´Ŧā´žā´šāĩā´¯ā´Žā´žā´¯ā´ļāĩ‡ā´–ā´°ā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´¨ā´ŋⴝⴍāĩā´¤āĩā´°ā´Ŗā´‚", - "face_detection": "ā´Žāĩā´–ā´™āĩā´™ā´ŗāĩâ€ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤āĩā´•", - "face_detection_description": "ⴝⴍāĩā´¤āĩā´°ā´Ēⴠⴍⴂ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ā´ĩā´¸āĩā´¤āĩā´•āĩā´•ā´ŗā´ŋā´˛āĩ† ā´Žāĩā´–ā´™āĩā´™āĩž ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤āĩā´•. ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•āĩžā´•āĩā´•āĩ, ⴤⴂā´Ŧāĩâ€Œā´¨āĩ†ā´¯ā´ŋāĩŊ ā´Žā´žā´¤āĩā´°ā´Žāĩ‡ ā´Ēā´°ā´ŋā´—ā´Ŗā´ŋā´•āĩā´•āĩ‚. \"Refresh\" ā´Žā´˛āĩā´˛ā´ž ā´ĩā´¸āĩā´¤āĩā´•āĩā´•ā´ŗāĩā´‚ (ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩā´‚) ā´Ēāĩā´°āĩ‹ā´¸ā´¸āĩā´¸āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ. ā´•āĩ‚ā´Ÿā´žā´¤āĩ† \"Reset\" ā´¨ā´ŋā´˛ā´ĩā´ŋā´˛āĩā´ŗāĩā´ŗ ā´Žā´˛āĩā´˛ā´ž ā´Žāĩā´–ā´ŗāĩā´‚ ā´ĩā´ŋā´ĩā´°ā´™āĩā´™ā´ŗāĩā´‚ ā´Žā´žā´¯āĩâ€Œā´•āĩā´•āĩā´¨āĩā´¨āĩ. \"Missing\" ⴇⴤāĩā´ĩā´°āĩ† ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´ŋā´•āĩā´•ā´žā´¤āĩā´¤ ā´ĩā´¸āĩā´¤āĩā´•āĩā´•ā´ŗāĩ† ā´ĩā´°ā´ŋā´¯ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´¨ā´ŋāĩŧā´¤āĩā´¤āĩā´¨āĩā´¨āĩ. ā´Žāĩā´–ā´‚ ā´¤ā´ŋā´°ā´ŋⴚāĩā´šā´ąā´ŋā´¯āĩŊ ā´Ēāĩ‚āĩŧā´¤āĩā´¤ā´ŋā´¯ā´žā´¯ ā´ļāĩ‡ā´ˇā´‚ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´ŋā´¯ ā´Žāĩā´–ā´™āĩā´™āĩž ā´Žāĩā´–ā´‚ ā´¤ā´ŋā´°ā´ŋⴚāĩā´šā´ąā´ŋⴝⴞā´ŋā´¨ā´žā´¯ā´ŋ ā´•āĩā´¯āĩ‚ā´ĩā´ŋāĩŊ ā´¨ā´ŋāĩŧā´¤āĩā´¤āĩā´‚, ā´…ā´ĩā´¯āĩ† ā´¨ā´ŋā´˛ā´ĩā´ŋā´˛āĩā´ŗāĩā´ŗā´¤āĩ‹ ā´Ēāĩā´¤ā´ŋⴝⴤāĩ‹ ⴆⴝ ⴆⴺāĩā´•ā´ŗā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´—āĩā´°āĩ‚ā´Ēāĩā´Ēāĩā´šāĩ†ā´¯āĩā´¯āĩā´‚.", - "facial_recognition_job_description": "ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´ŋā´¯ ā´Žāĩā´–ā´™āĩā´™ā´ŗāĩ† ⴆⴺāĩā´•ā´ŗāĩā´Ÿāĩ† ā´•āĩ‚ā´Ÿāĩā´Ÿā´‚ ⴆⴕāĩā´•āĩā´•. ā´Žāĩā´–ā´‚ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´˛āĩâ€ ⴘⴟāĩā´Ÿā´¤āĩā´¤ā´ŋā´¨āĩ ā´ļāĩ‡ā´ˇā´Žāĩ‡ ⴇⴤāĩ ⴉ⴪āĩā´Ÿā´žā´•āĩ‚. \"Reset\" ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩā´‚ ā´•āĩ‚ā´Ÿāĩā´Ÿā´™āĩā´™ā´ŗāĩ† ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´‚. \"Missing\" ⴆⴺāĩ† ā´¨ā´ŋā´¯āĩ‹ā´—ā´ŋā´•āĩā´•ā´žā´¤āĩā´¤ ā´Žāĩā´–ā´™āĩā´™ā´ŗāĩ† ā´ĩā´°ā´ŋā´¯ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ⴚāĩ‡ā´°āĩâ€ā´•āĩā´•āĩā´¨āĩā´¨āĩ.", - "failed_job_command": "{job} ā´Žā´¨āĩā´¨ ⴜāĩ‹ā´˛ā´ŋā´•āĩā´•āĩ ā´ĩāĩ‡ā´Ŗāĩā´Ÿā´ŋā´¯āĩā´ŗāĩā´ŗ ā´†ā´œāĩā´ž {command} ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ", - "force_delete_user_warning": "ā´Žāĩā´¨āĩā´¨ā´ąā´ŋā´¯ā´ŋā´Ēāĩā´Ēāĩ: ⴇⴤāĩ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ†ā´¯āĩā´‚ ā´Žā´˛āĩā´˛ā´ž ā´ĩā´¸āĩā´¤āĩā´•āĩā´•ā´ŗāĩ‡ā´¯āĩā´‚ ā´‰ā´Ÿā´¨ā´Ÿā´ŋ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´‚. ⴇⴤāĩ ā´Ēā´´ā´¯ā´Ēⴟā´ŋā´¯ā´žā´•āĩā´•ā´žā´¨āĩ‹ ā´Ģⴝⴞāĩā´•āĩž ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩ†ā´Ÿāĩā´•āĩā´•ā´žā´¨āĩ‹ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛.", - "image_format": "ⴘⴟⴍ", - "image_format_description": "WebP ⴉ⴪āĩā´Ÿā´žā´•āĩā´•ā´žā´¨āĩâ€ ā´¸ā´Žā´¯ā´‚ ā´Žā´Ÿāĩā´•āĩā´•āĩā´‚ ā´Žā´™āĩā´•ā´ŋā´˛āĩā´‚ JPEG ā´Ģⴝⴞāĩā´•ā´ŗāĩ†ā´•āĩā´•ā´žā´ŗāĩâ€ ⴚāĩ†ā´ąāĩā´¤ā´žā´¯ā´ŋā´°ā´ŋā´•āĩā´•āĩā´‚.", - "image_fullsize_description": "ā´…ā´§ā´ŋā´•ā´ĩā´ŋā´ĩā´°ā´™āĩā´™ā´ŗāĩâ€ ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•ā´ŋā´¯ ⴚā´ŋā´¤āĩā´°ā´‚, ā´ĩā´˛āĩā´¤ā´žā´•āĩā´•ā´ŋ ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´Žāĩā´Ēāĩ‹ā´ŗāĩâ€ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¨āĩā´¨āĩ", - "image_fullsize_enabled": "ā´Ēāĩ‚ā´°āĩâ€ā´Ŗ ā´ĩā´˛āĩā´Ēāĩā´Ēā´¤āĩā´¤ā´ŋā´˛āĩâ€ ⴉⴺāĩā´ŗ ⴚā´ŋā´¤āĩā´°ā´™āĩā´™ā´ŗāĩâ€ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•ā´žā´¨āĩâ€ā´Ēāĩā´°ā´žā´Ēāĩā´¤ā´Žā´žā´•āĩā´•āĩā´•", - "image_fullsize_quality_description": "1 ā´Žāĩā´¤āĩŊ 100 ā´ĩā´°āĩ†ā´¯āĩā´ŗāĩā´ŗ ā´Ēāĩ‚āĩŧā´Ŗāĩā´Ŗ ā´ĩā´˛āĩā´Ēāĩā´Ēā´¤āĩā´¤ā´ŋā´˛āĩā´ŗāĩā´ŗ ā´‡ā´Žāĩ‡ā´œāĩ ā´¨ā´ŋā´˛ā´ĩā´žā´°ā´‚. ⴉⴝāĩŧā´¨āĩā´¨ā´¤ā´žā´Ŗāĩ ⴍⴞāĩā´˛ā´¤āĩ, ā´Ēā´•āĩā´ˇāĩ‡ ā´ĩā´˛ā´ŋā´¯ ā´Ģⴝⴞāĩā´•āĩž ⴉⴤāĩā´Ēā´žā´Ļā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ.", - "image_fullsize_title": "ā´Ēāĩ‚āĩŧā´Ŗāĩā´Ŗ ā´ĩā´˛āĩā´Ēāĩā´Ēā´¤āĩā´¤ā´ŋā´˛āĩā´ŗāĩā´ŗ ā´‡ā´Žāĩ‡ā´œāĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", - "image_quality": "ā´—āĩā´Ŗā´¨ā´ŋā´˛ā´ĩā´žā´°ā´‚", + "add_exclusion_pattern_description": "ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•āĩŊ ā´Ēā´žā´ąāĩā´ąāĩ‡ā´Ŗāĩā´•āĩž ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•. *, **, ? ā´Žā´¨āĩā´¨ā´ŋā´ĩ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩā´ŗāĩā´ŗ ā´—āĩā´˛āĩ‹ā´Ŧā´ŋā´‚ā´—āĩ ā´Ēā´ŋā´¨āĩā´¤āĩā´Ŗā´¯āĩā´•āĩā´•āĩā´¨āĩā´¨āĩ. \"Raw\" ā´Žā´¨āĩā´¨āĩ ā´Ēāĩ‡ā´°āĩā´ŗāĩā´ŗ ā´ā´¤āĩ†ā´™āĩā´•ā´ŋā´˛āĩā´‚ ā´Ąā´¯ā´ąā´•āĩā´Ÿā´ąā´ŋā´¯ā´ŋā´˛āĩ† ā´Žā´˛āĩā´˛ā´ž ā´Ģⴝⴞāĩā´•ā´ŗāĩā´‚ ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•ā´žāĩģ, \"**/Raw/**\" ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•. \".tif\"-āĩŊ ā´…ā´ĩā´¸ā´žā´¨ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ ā´Žā´˛āĩā´˛ā´ž ā´Ģⴝⴞāĩā´•ā´ŗāĩā´‚ ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•ā´žāĩģ, \"**/*.tif\" ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•. ā´’ā´°āĩ ā´•āĩ‡ā´ĩā´˛ ā´Ēā´žā´¤āĩā´¤āĩ ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•ā´žāĩģ, \"/path/to/ignore/**\" ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•.", + "admin_user": "ā´…ā´Ąāĩā´Žā´ŋāĩģ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩāĩ", + "asset_offline_description": "ⴈ ā´Žā´•āĩā´¸āĩā´ąāĩā´ąāĩ‡ā´ŖāĩŊ ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ ā´…ā´¸ā´ąāĩā´ąāĩ ā´‡ā´Ēāĩā´Ēāĩ‹āĩž ā´Ąā´ŋā´¸āĩā´•ā´ŋāĩŊ ⴞⴭāĩā´¯ā´Žā´˛āĩā´˛, ā´…ā´¤āĩ ⴟāĩā´°ā´žā´ˇā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Žā´žā´ąāĩā´ąā´ŋā´¯ā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ. ā´Ģā´¯āĩŊ ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋā´•āĩā´•āĩā´ŗāĩā´ŗā´ŋāĩŊ ā´¨āĩ€ā´•āĩā´•ā´ŋā´¯ā´ŋⴟāĩā´Ÿāĩā´Ŗāĩā´Ÿāĩ†ā´™āĩā´•ā´ŋāĩŊ, ā´Ēāĩā´¤ā´ŋā´¯ ā´…ā´¨āĩā´Ŧā´¨āĩā´§ ā´…ā´¸ā´ąāĩā´ąā´ŋā´¨ā´žā´¯ā´ŋ ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ⴟāĩˆā´‚ā´˛āĩˆāĩģ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´ŋā´•āĩā´•āĩā´•. ⴈ ā´…ā´¸ā´ąāĩā´ąāĩ ā´Ēāĩā´¨ā´ƒā´¸āĩā´Ĩā´žā´Ēā´ŋā´•āĩā´•ā´žāĩģ, ā´¤ā´žā´´āĩ†ā´¯āĩā´ŗāĩā´ŗ ā´Ģā´¯āĩŊ ā´Ēā´žā´¤ Immich-ā´¨āĩ ⴆⴕāĩā´¸ā´¸āĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯āĩā´Žāĩ†ā´¨āĩā´¨āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´•āĩā´•āĩā´•ā´¯āĩā´‚ ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ ā´¸āĩā´•ā´žāĩģ ⴚāĩ†ā´¯āĩā´¯āĩā´•ā´¯āĩā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•.", + "authentication_settings": "ā´Ēāĩā´°ā´žā´Žā´žā´Ŗāĩ€ā´•ā´°ā´Ŗ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "authentication_settings_description": "ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ, OAuth, ā´Žā´ąāĩā´ąāĩ ā´Ēāĩā´°ā´žā´Žā´žā´Ŗāĩ€ā´•ā´°ā´Ŗ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´Žā´¨āĩā´¨ā´ŋā´ĩ ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "authentication_settings_disable_all": "ā´Žā´˛āĩā´˛ā´ž ā´˛āĩ‹ā´—ā´ŋāĩģ ā´°āĩ€ā´¤ā´ŋā´•ā´ŗāĩā´‚ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹? ā´˛āĩ‹ā´—ā´ŋāĩģ ā´Ēāĩ‚āĩŧā´Ŗāĩā´Ŗā´Žā´žā´¯āĩā´‚ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´‚.", + "authentication_settings_reenable": "ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩā´‚ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•ā´žāĩģ, ā´’ā´°āĩ ā´¸āĩ†āĩŧā´ĩāĩŧ ā´•ā´Žā´žāĩģā´Ąāĩ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•.", + "background_task_job": "ā´Ēā´ļāĩā´šā´žā´¤āĩā´¤ā´˛ ⴜāĩ‹ā´˛ā´ŋā´•āĩž", + "backup_database": "ā´Ąā´žā´ąāĩā´ąā´žā´Ŧāĩ‡ā´¸āĩ ā´Ąā´‚ā´Ēāĩ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´•", + "backup_database_enable_description": "ā´Ąā´žā´ąāĩā´ąā´žā´Ŧāĩ‡ā´¸āĩ ā´Ąā´‚ā´Ēāĩā´•āĩž ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´•", + "backup_keep_last_amount": "ā´¸āĩ‚ā´•āĩā´ˇā´ŋā´•āĩā´•āĩ‡ā´Ŗāĩā´Ÿ ā´Ēā´´ā´¯ ā´Ąā´‚ā´Ēāĩā´•ā´ŗāĩā´Ÿāĩ† ā´Žā´Ŗāĩā´Ŗā´‚", + "backup_onboarding_1_description": "ā´•āĩā´˛āĩ—ā´Ąā´ŋā´˛āĩ‹ ā´Žā´ąāĩā´ąāĩŠā´°āĩ ā´­āĩ—ā´¤ā´ŋā´• ā´¸āĩā´Ĩā´žā´¨ā´¤āĩā´¤āĩ‹ ⴉⴺāĩā´ŗ ā´“ā´Ģāĩâ€Œā´¸āĩˆā´ąāĩā´ąāĩ ā´Ēā´•āĩŧā´Ēāĩā´Ēāĩ.", + "backup_onboarding_2_description": "ā´ĩā´ŋā´ĩā´ŋā´§ ā´‰ā´Ēā´•ā´°ā´Ŗā´™āĩā´™ā´ŗā´ŋā´˛āĩ† ā´Ēāĩā´°ā´žā´Ļāĩ‡ā´ļā´ŋā´• ā´Ēā´•āĩŧā´Ēāĩā´Ēāĩā´•āĩž. ⴇⴤā´ŋāĩŊ ā´Ēāĩā´°ā´§ā´žā´¨ ā´Ģⴝⴞāĩā´•ā´ŗāĩā´‚ ā´† ā´Ģⴝⴞāĩā´•ā´ŗāĩā´Ÿāĩ† ā´Ēāĩā´°ā´žā´Ļāĩ‡ā´ļā´ŋā´• ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩā´‚ ā´‰āĩžā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¨āĩā´¨āĩ.", + "backup_onboarding_3_description": "ā´¯ā´Ĩā´žāĩŧā´¤āĩā´Ĩ ā´Ģⴝⴞāĩā´•āĩž ā´‰āĩžā´Ēāĩā´Ēāĩ†ā´Ÿāĩ† ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ąā´žā´ąāĩā´ąā´¯āĩā´Ÿāĩ† ⴆⴕāĩ† ā´Ēā´•āĩŧā´Ēāĩā´Ēāĩā´•āĩž. ⴇⴤā´ŋāĩŊ 1 ā´“ā´Ģāĩâ€Œā´¸āĩˆā´ąāĩā´ąāĩ ā´Ēā´•āĩŧā´Ēāĩā´Ēāĩā´‚ 2 ā´Ēāĩā´°ā´žā´Ļāĩ‡ā´ļā´ŋā´• ā´Ēā´•āĩŧā´Ēāĩā´Ēāĩā´•ā´ŗāĩā´‚ ā´‰āĩžā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¨āĩā´¨āĩ.", + "backup_onboarding_description": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ąā´žā´ąāĩā´ą ā´Ēā´°ā´ŋā´°ā´•āĩā´ˇā´ŋā´•āĩā´•ā´žāĩģ 3-2-1 ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ⴤⴍāĩā´¤āĩā´°ā´‚ ā´ļāĩā´Ēā´žāĩŧā´ļ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ. ā´¸ā´Žā´—āĩā´°ā´Žā´žā´¯ ā´’ā´°āĩ ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ā´Ēā´°ā´ŋā´šā´žā´°ā´¤āĩā´¤ā´ŋā´¨ā´žā´¯ā´ŋ, ā´¨ā´ŋā´™āĩā´™āĩž ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¤ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´Ÿāĩ†/ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´Ÿāĩ† ā´Ēā´•āĩŧā´Ēāĩā´Ēāĩā´•ā´ŗāĩā´‚ Immich ā´Ąā´žā´ąāĩā´ąā´žā´Ŧāĩ‡ā´¸āĩā´‚ ā´¸āĩ‚ā´•āĩā´ˇā´ŋā´•āĩā´•āĩ‡ā´Ŗāĩā´Ÿā´¤ā´žā´Ŗāĩ.", + "backup_onboarding_footer": "Immich ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ†ā´•āĩā´•āĩā´ąā´ŋⴚāĩā´šāĩā´ŗāĩā´ŗ ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ ā´ĩā´ŋā´ĩā´°ā´™āĩā´™āĩžā´•āĩā´•ā´žā´¯ā´ŋ, ā´Ļā´¯ā´ĩā´žā´¯ā´ŋ ā´Ąāĩ‹ā´•āĩā´¯āĩā´Žāĩ†ā´¨āĩā´ąāĩ‡ā´ˇāĩģ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´ŋā´•āĩā´•āĩā´•.", + "backup_onboarding_parts_title": "ā´’ā´°āĩ 3-2-1 ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēā´ŋāĩŊ ā´‰āĩžā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¨āĩā´¨ā´ĩ:", + "backup_onboarding_title": "ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩā´•āĩž", + "backup_settings": "ā´Ąā´žā´ąāĩā´ąā´žā´Ŧāĩ‡ā´¸āĩ ā´Ąā´‚ā´Ēāĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "backup_settings_description": "ā´Ąā´žā´ąāĩā´ąā´žā´Ŧāĩ‡ā´¸āĩ ā´Ąā´‚ā´Ēāĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•.", + "cleared_jobs": "{job}-ā´¨āĩā´ŗāĩā´ŗ ⴜāĩ‹ā´˛ā´ŋā´•āĩž ā´•āĩā´˛ā´ŋā´¯āĩŧ ⴚāĩ†ā´¯āĩā´¤āĩ", + "config_set_by_file": "ā´•āĩ‹āĩēā´Ģā´ŋā´—ā´ąāĩ‡ā´ˇāĩģ ā´¨ā´ŋā´˛ā´ĩā´ŋāĩŊ ā´’ā´°āĩ ā´•āĩ‹āĩēā´Ģā´ŋā´—ā´ąāĩ‡ā´ˇāĩģ ā´Ģā´¯āĩŊ ā´ĩā´´ā´ŋā´¯ā´žā´Ŗāĩ ⴏⴜāĩā´œāĩ€ā´•ā´°ā´ŋⴚāĩā´šā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤āĩ", + "confirm_delete_library": "{library} ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹?", + "confirm_delete_library_assets": "ⴈ ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹? ⴇⴤāĩ Immich-āĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ {count, plural, one {ā´…ā´¤ā´ŋā´˛āĩā´ŗāĩā´ŗ ā´’ā´°āĩ ā´…ā´¸ā´ąāĩā´ąāĩ} other {ā´…ā´¤ā´ŋā´˛āĩā´ŗāĩā´ŗ ā´Žā´˛āĩā´˛ā´ž # ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩā´‚}} ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´‚, ⴇⴤāĩ ā´Ēā´´ā´¯ā´Ēⴟā´ŋā´¯ā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛. ā´Ģⴝⴞāĩā´•āĩž ā´Ąā´ŋā´¸āĩā´•ā´ŋāĩŊ ⴤⴍāĩā´¨āĩ† ā´¤āĩā´Ÿā´°āĩā´‚.", + "confirm_email_below": "ā´¸āĩā´Ĩā´ŋā´°āĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ, ā´¤ā´žā´´āĩ† \"{email}\" ā´Žā´¨āĩā´¨āĩ ⴟāĩˆā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "confirm_reprocess_all_faces": "ā´Žā´˛āĩā´˛ā´ž ā´Žāĩā´–ā´™āĩā´™ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩā´‚ ā´Ēāĩā´°āĩ‹ā´¸ā´¸āĩā´¸āĩ ⴚāĩ†ā´¯āĩā´¯ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹? ⴇⴤāĩ ā´Ēāĩ‡ā´°āĩā´ŗāĩā´ŗ ⴆⴺāĩā´•ā´ŗāĩ†ā´¯āĩā´‚ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´‚.", + "confirm_user_password_reset": "{user}-ā´¨āĩā´ąāĩ† ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´ąāĩ€ā´¸āĩ†ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹?", + "confirm_user_pin_code_reset": "{user}-ā´¨āĩā´ąāĩ† ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ ā´ąāĩ€ā´¸āĩ†ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹?", + "create_job": "ⴜāĩ‹ā´˛ā´ŋ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´•", + "cron_expression": "ā´•āĩā´°āĩ‹āĩē ā´Žā´•āĩā´¸āĩā´Ēāĩā´°ā´ˇāĩģ", + "cron_expression_description": "ā´•āĩā´°āĩ‹āĩē ā´Ģāĩ‹āĩŧā´Žā´žā´ąāĩā´ąāĩ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ā´¸āĩā´•ā´žā´¨ā´ŋā´‚ā´—āĩ ā´‡ā´Ÿā´ĩāĩ‡ā´ŗ ⴏⴜāĩā´œāĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´•. ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ ā´ĩā´ŋā´ĩā´°ā´™āĩā´™āĩžā´•āĩā´•ā´žā´¯ā´ŋ ā´Ļā´¯ā´ĩā´žā´¯ā´ŋ ā´•āĩā´°āĩ‹āĩēā´Ÿā´žā´Ŧāĩ ā´—āĩā´°āĩ ā´Ēāĩ‹ā´˛āĩā´ŗāĩā´ŗā´ĩ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´ŋā´•āĩā´•āĩā´•", + "cron_expression_presets": "ā´•āĩā´°āĩ‹āĩē ā´Žā´•āĩā´¸āĩā´Ēāĩā´°ā´ˇāĩģ ā´Ēāĩā´°āĩ€ā´¸āĩ†ā´ąāĩā´ąāĩā´•āĩž", + "disable_login": "ā´˛āĩ‹ā´—ā´ŋāĩģ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•āĩā´•", + "duplicate_detection_job_description": "ā´¸ā´Žā´žā´¨ ⴚā´ŋā´¤āĩā´°ā´™āĩā´™āĩž ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´žāĩģ ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗā´ŋāĩŊ ā´Žāĩ†ā´ˇāĩ€āĩģ ā´˛āĩ‡ā´Ŗā´ŋā´‚ā´—āĩ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´•. ⴇⴤāĩ ā´¸āĩā´Žā´žāĩŧⴟāĩā´Ÿāĩ ā´¸āĩ†āĩŧⴚāĩā´šā´ŋā´¨āĩ† ā´†ā´ļāĩā´°ā´¯ā´ŋⴚāĩā´šā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "exclusion_pattern_description": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ ā´¸āĩā´•ā´žāĩģ ⴚāĩ†ā´¯āĩā´¯āĩā´Žāĩā´Ēāĩ‹āĩž ā´Ģⴝⴞāĩā´•ā´ŗāĩā´‚ ā´Ģāĩ‹āĩžā´Ąā´ąāĩā´•ā´ŗāĩā´‚ ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•ā´žāĩģ ā´Žā´•āĩā´¸āĩā´•āĩā´˛āĩ‚ā´ˇāĩģ ā´Ēā´žā´ąāĩā´ąāĩ‡ā´Ŗāĩā´•āĩž ā´¨ā´ŋā´™āĩā´™ā´ŗāĩ† ā´¸ā´šā´žā´¯ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ. ā´¨ā´ŋā´™āĩā´™āĩž ā´‡ā´Žāĩā´Ēāĩ‹āĩŧⴟāĩā´Ÿāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ⴆⴗāĩā´°ā´šā´ŋā´•āĩā´•ā´žā´¤āĩā´¤ ā´Ģⴝⴞāĩā´•āĩž ā´…ā´Ÿā´™āĩā´™ā´ŋā´¯ ā´Ģāĩ‹āĩžā´Ąā´ąāĩā´•āĩž (ā´‰ā´Ļā´žā´šā´°ā´Ŗā´¤āĩā´¤ā´ŋā´¨āĩ RAW ā´Ģⴝⴞāĩā´•āĩž) ⴉ⴪āĩā´Ÿāĩ†ā´™āĩā´•ā´ŋāĩŊ ⴇⴤāĩ ā´‰ā´Ēā´¯āĩ‹ā´—ā´Ēāĩā´°ā´Ļā´Žā´žā´Ŗāĩ.", + "external_library_management": "ā´Žā´•āĩā´¸āĩā´ąāĩā´ąāĩ‡ā´ŖāĩŊ ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ ā´Žā´žā´¨āĩ‡ā´œāĩā´Žāĩ†ā´¨āĩā´ąāĩ", + "face_detection": "ā´Žāĩā´–ā´‚ ā´¤ā´ŋā´°ā´ŋⴚāĩā´šā´ąā´ŋā´¯āĩŊ", + "face_detection_description": "ā´Žāĩ†ā´ˇāĩ€āĩģ ā´˛āĩ‡ā´Ŗā´ŋā´‚ā´—āĩ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗā´ŋā´˛āĩ† ā´Žāĩā´–ā´™āĩā´™āĩž ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤āĩā´•. ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•āĩžā´•āĩā´•ā´žā´¯ā´ŋ, ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋāĩŊ ā´Žā´žā´¤āĩā´°ā´Žāĩ‡ ā´Ēā´°ā´ŋā´—ā´Ŗā´ŋā´•āĩā´•āĩ‚. \"ā´ąā´ŋā´Ģāĩā´°ā´ˇāĩ\" ā´Žā´˛āĩā´˛ā´ž ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩā´‚ ā´Ēāĩā´°āĩ‹ā´¸ā´¸āĩā´¸āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ. \"ā´ąāĩ€ā´¸āĩ†ā´ąāĩā´ąāĩ\" ā´¨ā´ŋā´˛ā´ĩā´ŋā´˛āĩā´ŗāĩā´ŗ ā´Žā´˛āĩā´˛ā´ž ā´Žāĩā´– ā´Ąā´žā´ąāĩā´ąā´¯āĩā´‚ ā´¨āĩ€ā´•āĩā´•ā´‚ā´šāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ. \"ā´Žā´ŋā´¸āĩā´¸ā´ŋā´‚ā´—āĩ\" ⴇⴤāĩā´ĩā´°āĩ† ā´Ēāĩā´°āĩ‹ā´¸ā´¸āĩā´¸āĩ ⴚāĩ†ā´¯āĩā´¯ā´žā´¤āĩā´¤ ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩ† ā´•āĩā´¯āĩ‚ā´ĩā´ŋā´˛ā´žā´•āĩā´•āĩā´¨āĩā´¨āĩ. ā´Žāĩā´–ā´‚ ā´¤ā´ŋā´°ā´ŋⴚāĩā´šā´ąā´ŋā´¯āĩŊ ā´Ēāĩ‚āĩŧā´¤āĩā´¤ā´ŋā´¯ā´žā´¯ ā´ļāĩ‡ā´ˇā´‚, ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´ŋā´¯ ā´Žāĩā´–ā´™āĩā´™āĩž ā´Ģāĩ‡ā´ˇāĩā´¯āĩŊ ā´ąāĩ†ā´•āĩā´•ā´—āĩā´¨ā´ŋā´ˇā´¨ā´žā´¯ā´ŋ ā´•āĩā´¯āĩ‚ ⴚāĩ†ā´¯āĩā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´‚, ā´…ā´ĩā´¯āĩ† ā´¨ā´ŋā´˛ā´ĩā´ŋā´˛āĩā´ŗāĩā´ŗā´¤āĩ‹ ā´Ēāĩā´¤ā´ŋⴝⴤāĩ‹ ⴆⴝ ⴆⴺāĩā´•ā´ŗā´žā´¯ā´ŋ ⴤⴰⴂⴤā´ŋā´°ā´ŋā´•āĩā´•āĩā´‚.", + "facial_recognition_job_description": "ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´ŋā´¯ ā´Žāĩā´–ā´™āĩā´™ā´ŗāĩ† ⴆⴺāĩā´•ā´ŗā´žā´¯ā´ŋ ā´—āĩā´°āĩ‚ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•. ā´Žāĩā´–ā´‚ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤āĩŊ ā´Ēāĩ‚āĩŧā´¤āĩā´¤ā´ŋā´¯ā´žā´¯ā´¤ā´ŋā´¨āĩ ā´ļāĩ‡ā´ˇā´Žā´žā´Ŗāĩ ⴈ ⴘⴟāĩā´Ÿā´‚ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤āĩ. \"ā´ąāĩ€ā´¸āĩ†ā´ąāĩā´ąāĩ\" ā´Žā´˛āĩā´˛ā´ž ā´Žāĩā´–ā´™āĩā´™ā´ŗāĩ†ā´¯āĩā´‚ ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩā´‚ ā´•āĩā´˛ā´¸āĩā´ąāĩā´ąāĩŧ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ. \"ā´Žā´ŋā´¸āĩā´¸ā´ŋā´‚ā´—āĩ\" ā´’ā´°āĩ ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´¯āĩ†ā´¯āĩā´‚ ā´…ā´¸āĩˆāĩģ ⴚāĩ†ā´¯āĩā´¯ā´žā´¤āĩā´¤ ā´Žāĩā´–ā´™āĩā´™ā´ŗāĩ† ā´•āĩā´¯āĩ‚ā´ĩā´ŋā´˛ā´žā´•āĩā´•āĩā´¨āĩā´¨āĩ.", + "failed_job_command": "{job} ā´Žā´¨āĩā´¨ ⴜāĩ‹ā´˛ā´ŋā´•āĩā´•āĩā´ŗāĩā´ŗ ā´•ā´Žā´žāĩģā´Ąāĩ {command} ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "force_delete_user_warning": "ā´Žāĩā´¨āĩā´¨ā´ąā´ŋā´¯ā´ŋā´Ēāĩā´Ēāĩ: ⴇⴤāĩ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ†ā´¯āĩā´‚ ā´Žā´˛āĩā´˛ā´ž ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩ†ā´¯āĩā´‚ ā´‰ā´Ÿā´¨ā´Ÿā´ŋ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´‚. ⴇⴤāĩ ā´Ēā´´ā´¯ā´Ēⴟā´ŋā´¯ā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛, ā´Ģⴝⴞāĩā´•āĩž ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩ†ā´Ÿāĩā´•āĩā´•ā´žā´¨āĩā´‚ ā´¸ā´žā´§ā´ŋā´•āĩā´•ā´ŋā´˛āĩā´˛.", + "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": "ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋā´˛āĩā´•āĩžā´•āĩā´•ā´žā´¯ā´ŋ ā´Ąā´ŋā´¸āĩā´Ēāĩā´˛āĩ‡ P3 ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•. ⴇⴤāĩ ā´ĩāĩˆā´Ąāĩ ā´•ā´ŗāĩŧā´¸āĩā´Ēāĩ‡ā´¸āĩā´•ā´ŗāĩā´ŗāĩā´ŗ ⴚā´ŋā´¤āĩā´°ā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Žā´ŋā´´ā´ŋā´ĩāĩ ⴍⴍāĩā´¨ā´žā´¯ā´ŋ ⴏⴂⴰⴕāĩā´ˇā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ, ā´Ēā´•āĩā´ˇāĩ‡ ā´Ēā´´ā´¯ ā´Ŧāĩā´°āĩ—ā´¸āĩŧ ā´Ēā´¤ā´ŋā´Ēāĩā´Ēāĩā´ŗāĩā´ŗ ā´Ēā´´ā´¯ ā´‰ā´Ēā´•ā´°ā´Ŗā´™āĩā´™ā´ŗā´ŋāĩŊ ⴚā´ŋā´¤āĩā´°ā´™āĩā´™āĩž ā´ĩāĩā´¯ā´¤āĩā´¯ā´¸āĩā´¤ā´Žā´žā´¯ā´ŋ ā´•ā´žā´Ŗā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ‡ā´•āĩā´•ā´žā´‚. ā´•ā´ŗāĩŧ ā´ˇā´ŋā´Ģāĩā´ąāĩā´ąāĩā´•āĩž ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•ā´žāĩģ sRGB ⴚā´ŋā´¤āĩā´°ā´™āĩā´™āĩž sRGB ⴆⴝā´ŋ ⴤⴍāĩā´¨āĩ† ā´¨ā´ŋⴞⴍā´ŋāĩŧā´¤āĩā´¤āĩā´¨āĩā´¨āĩ.", + "image_preview_description": "ā´Žāĩ†ā´ąāĩā´ąā´žā´Ąā´žā´ąāĩā´ą ā´¨āĩ€ā´•āĩā´•ā´‚ā´šāĩ†ā´¯āĩā´¤ ā´‡ā´Ÿā´¤āĩā´¤ā´°ā´‚ ā´ĩā´˛āĩā´Ēāĩā´Ēā´Žāĩā´ŗāĩā´ŗ ⴚā´ŋā´¤āĩā´°ā´‚, ā´’ā´°āĩŠā´ąāĩā´ą ā´…ā´¸ā´ąāĩā´ąāĩ ā´•ā´žā´Ŗāĩā´Žāĩā´Ēāĩ‹ā´´āĩā´‚ ā´Žāĩ†ā´ˇāĩ€āĩģ ā´˛āĩ‡ā´Ŗā´ŋā´‚ā´—ā´ŋā´¨āĩā´‚ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "image_preview_quality_description": "ā´Ēāĩā´°ā´ŋā´ĩāĩā´¯āĩ‚ ā´—āĩā´Ŗā´Žāĩ‡ā´¨āĩā´Ž 1-100 ā´ĩā´°āĩ†. ⴉⴝāĩŧā´¨āĩā´¨ ā´Žāĩ‚ā´˛āĩā´¯ā´‚ ā´Žā´ŋā´•ā´šāĩā´šā´¤ā´žā´Ŗāĩ, ā´Ēā´•āĩā´ˇāĩ‡ ā´ĩā´˛ā´ŋā´¯ ā´Ģⴝⴞāĩā´•āĩž ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´•ā´¯āĩā´‚ ā´†ā´Ēāĩā´Ēā´ŋā´¨āĩā´ąāĩ† ā´Ēāĩā´°ā´¤ā´ŋā´•ā´°ā´Ŗā´ļāĩ‡ā´ˇā´ŋ ā´•āĩā´ąā´¯āĩā´•āĩā´•āĩā´•ā´¯āĩā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´‚. ā´•āĩā´ąā´žāĩā´ž ā´Žāĩ‚ā´˛āĩā´¯ā´‚ ⴏⴜāĩā´œāĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤āĩ ā´Žāĩ†ā´ˇāĩ€āĩģ ā´˛āĩ‡ā´Ŗā´ŋā´‚ā´—āĩ ā´—āĩā´Ŗā´Žāĩ‡ā´¨āĩā´Žā´¯āĩ† ā´Ŧā´žā´§ā´ŋⴚāĩā´šāĩ‡ā´•āĩā´•ā´žā´‚.", + "image_preview_title": "ā´Ēāĩā´°ā´ŋā´ĩāĩā´¯āĩ‚ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "image_quality": "ā´—āĩā´Ŗā´Žāĩ‡ā´¨āĩā´Ž", + "image_resolution": "ā´ąāĩ†ā´¸ā´˛āĩā´¯āĩ‚ā´ˇāĩģ", + "image_resolution_description": "ⴉⴝāĩŧā´¨āĩā´¨ ā´ąāĩ†ā´¸ā´˛āĩā´¯āĩ‚ⴎⴍāĩā´•āĩžā´•āĩā´•āĩ ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ ā´ĩā´ŋā´ļā´Ļā´žā´‚ā´ļā´™āĩā´™āĩž ⴏⴂⴰⴕāĩā´ˇā´ŋā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯āĩā´‚, ā´Ēā´•āĩā´ˇāĩ‡ ā´Žāĩģā´•āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ ā´¸ā´Žā´¯ā´Žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´‚, ā´ĩā´˛ā´ŋā´¯ ā´Ģā´¯āĩŊ ā´ĩā´˛āĩā´Ēāĩā´Ēā´Žāĩā´Ŗāĩā´Ÿā´žā´•āĩā´‚, ā´•āĩ‚ā´Ÿā´žā´¤āĩ† ā´†ā´Ēāĩā´Ēā´ŋā´¨āĩā´ąāĩ† ā´Ēāĩā´°ā´¤ā´ŋā´•ā´°ā´Ŗā´ļāĩ‡ā´ˇā´ŋ ā´•āĩā´ąā´¯āĩā´•āĩā´•āĩā´•ā´¯āĩā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´‚.", + "image_settings": "ⴚā´ŋā´¤āĩā´° ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "image_settings_description": "ā´¨ā´ŋāĩŧā´Žāĩā´Žā´ŋⴚāĩā´š ⴚā´ŋā´¤āĩā´°ā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´—āĩā´Ŗā´Žāĩ‡ā´¨āĩā´Žā´¯āĩā´‚ ā´ąāĩ†ā´¸ā´˛āĩā´¯āĩ‚ⴎⴍāĩā´‚ ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "image_thumbnail_description": "ā´Žāĩ†ā´ąāĩā´ąā´žā´Ąā´žā´ąāĩā´ą ā´¨āĩ€ā´•āĩā´•ā´‚ā´šāĩ†ā´¯āĩā´¤ ⴚāĩ†ā´ąā´ŋā´¯ ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋāĩŊ, ā´Ēāĩā´°ā´§ā´žā´¨ ⴟāĩˆā´‚ā´˛āĩˆāĩģ ā´Ēāĩ‹ā´˛āĩā´ŗāĩā´ŗ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´Ÿāĩ† ā´—āĩā´°āĩ‚ā´Ēāĩā´Ēāĩā´•āĩž ā´•ā´žā´Ŗāĩā´Žāĩā´Ēāĩ‹āĩž ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "image_thumbnail_quality_description": "ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋā´˛ā´ŋā´¨āĩā´ąāĩ† ā´—āĩā´Ŗā´Žāĩ‡ā´¨āĩā´Ž 1-100 ā´ĩā´°āĩ†. ⴉⴝāĩŧā´¨āĩā´¨ ā´Žāĩ‚ā´˛āĩā´¯ā´‚ ā´Žā´ŋā´•ā´šāĩā´šā´¤ā´žā´Ŗāĩ, ā´Ēā´•āĩā´ˇāĩ‡ ā´ĩā´˛ā´ŋā´¯ ā´Ģⴝⴞāĩā´•āĩž ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´•ā´¯āĩā´‚ ā´†ā´Ēāĩā´Ēā´ŋā´¨āĩā´ąāĩ† ā´Ēāĩā´°ā´¤ā´ŋā´•ā´°ā´Ŗā´ļāĩ‡ā´ˇā´ŋ ā´•āĩā´ąā´¯āĩā´•āĩā´•āĩā´•ā´¯āĩā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´‚.", + "image_thumbnail_title": "ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋāĩŊ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "job_concurrency": "{job} ā´•āĩ‹āĩēā´•ā´ąāĩģā´¸ā´ŋ", "job_created": "ⴜāĩ‹ā´˛ā´ŋ ā´¸āĩƒā´ˇāĩā´Ÿā´ŋⴚāĩā´šāĩ", - "job_status": "ⴜāĩ‹ā´˛ā´ŋ ā´¨ā´ŋā´˛" + "job_not_concurrency_safe": "ⴈ ⴜāĩ‹ā´˛ā´ŋ ā´•āĩ‹āĩēā´•ā´ąāĩģā´¸ā´ŋ-ā´¸āĩ‡ā´Ģāĩ ā´…ā´˛āĩā´˛.", + "job_settings": "ⴜāĩ‹ā´˛ā´ŋ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "job_settings_description": "ⴜāĩ‹ā´˛ā´ŋ ā´•āĩ‹āĩēā´•ā´ąāĩģā´¸ā´ŋ ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "job_status": "ⴜāĩ‹ā´˛ā´ŋā´¯āĩā´Ÿāĩ† ā´¨ā´ŋā´˛", + "jobs_delayed": "{jobCount, plural, one {# ⴜāĩ‹ā´˛ā´ŋ ā´ĩāĩˆā´•ā´ŋ} other {# ⴜāĩ‹ā´˛ā´ŋā´•āĩž ā´ĩāĩˆā´•ā´ŋ}}", + "jobs_failed": "{jobCount, plural, one {# ⴜāĩ‹ā´˛ā´ŋ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ} other {# ⴜāĩ‹ā´˛ā´ŋā´•āĩž ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ}}", + "library_created": "{library} ā´Žā´¨āĩā´¨ ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ ā´¸āĩƒā´ˇāĩā´Ÿā´ŋⴚāĩā´šāĩ", + "library_deleted": "ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´ŋ", + "library_import_path_description": "ā´‡ā´Žāĩā´Ēāĩ‹āĩŧⴟāĩā´Ÿāĩā´šāĩ†ā´¯āĩā´¯ā´žāĩģ ā´’ā´°āĩ ā´Ģāĩ‹āĩžā´Ąāĩŧ ā´ĩāĩā´¯ā´•āĩā´¤ā´Žā´žā´•āĩā´•āĩā´•. ā´¸ā´Ŧāĩā´Ģāĩ‹āĩžā´Ąā´ąāĩā´•āĩž ā´‰āĩžā´Ēāĩā´Ēāĩ†ā´Ÿāĩ† ⴈ ā´Ģāĩ‹āĩžā´Ąāĩŧ ⴚā´ŋā´¤āĩā´°ā´™āĩā´™āĩžā´•āĩā´•āĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•āĩžā´•āĩā´•āĩā´Žā´žā´¯ā´ŋ ā´¸āĩā´•ā´žāĩģ ⴚāĩ†ā´¯āĩā´¯āĩā´‚.", + "library_scanning": "ⴆⴍāĩā´•ā´žā´˛ā´ŋā´• ā´¸āĩā´•ā´žā´¨ā´ŋā´‚ā´—āĩ", + "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": "ā´˛āĩ‹ā´—ā´ŋā´‚ā´—āĩ", + "machine_learning_availability_checks": "ⴞⴭāĩā´¯ā´¤ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´¨ā´•āĩž", + "machine_learning_availability_checks_description": "ⴞⴭāĩā´¯ā´Žā´žā´¯ ā´Žāĩ†ā´ˇāĩ€āĩģ ā´˛āĩ‡ā´Ŗā´ŋā´‚ā´—āĩ ā´¸āĩ†āĩŧā´ĩā´ąāĩā´•āĩž ā´¯ā´žā´¨āĩā´¤āĩā´°ā´ŋā´•ā´Žā´žā´¯ā´ŋ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤āĩā´•ā´¯āĩā´‚ ā´Žāĩāĩģā´—ā´Ŗā´¨ ā´¨āĩŊā´•āĩā´•ā´¯āĩā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "machine_learning_availability_checks_enabled": "ⴞⴭāĩā´¯ā´¤ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´¨ā´•āĩž ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´•", + "machine_learning_availability_checks_interval": "ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´¨ ā´‡ā´Ÿā´ĩāĩ‡ā´ŗ", + "machine_learning_availability_checks_interval_description": "ⴞⴭāĩā´¯ā´¤ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´¨ā´•āĩžā´•āĩā´•ā´ŋⴟⴝā´ŋā´˛āĩā´ŗāĩā´ŗ ā´‡ā´Ÿā´ĩāĩ‡ā´ŗ (ā´Žā´ŋā´˛āĩā´˛ā´ŋā´¸āĩ†ā´•āĩā´•āĩģā´Ąā´ŋāĩŊ)", + "machine_learning_availability_checks_timeout": "ā´…ā´­āĩā´¯āĩŧā´¤āĩā´Ĩⴍⴝāĩā´Ÿāĩ† ā´¸ā´Žā´¯ā´Ēā´°ā´ŋā´§ā´ŋ", + "machine_learning_availability_checks_timeout_description": "ⴞⴭāĩā´¯ā´¤ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´¨ā´•āĩžā´•āĩā´•āĩā´ŗāĩā´ŗ ā´¸ā´Žā´¯ā´Ēā´°ā´ŋā´§ā´ŋ (ā´Žā´ŋā´˛āĩā´˛ā´ŋā´¸āĩ†ā´•āĩā´•āĩģā´Ąā´ŋāĩŊ)", + "machine_learning_clip_model": "CLIP ā´Žāĩ‹ā´ĄāĩŊ", + "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_setting_description": "ā´¸ā´Žā´žā´¨ā´Žā´žā´¯ ā´Ąāĩā´¯āĩ‚ā´Ēāĩā´˛ā´ŋā´•āĩā´•āĩ‡ā´ąāĩā´ąāĩā´•āĩž ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´žāĩģ CLIP ā´Žā´‚ā´Ŧāĩ†ā´Ąāĩā´Ąā´ŋā´‚ā´—āĩâ€Œā´¸āĩ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•", + "machine_learning_enabled": "ā´Žāĩ†ā´ˇāĩ€āĩģ ā´˛āĩ‡ā´Ŗā´ŋā´‚ā´—āĩ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´•", + "machine_learning_enabled_description": "ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•ā´ŋā´¯ā´žāĩŊ, ā´¤ā´žā´´āĩ†ā´¯āĩā´ŗāĩā´ŗ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´Ēā´°ā´ŋā´—ā´Ŗā´ŋā´•āĩā´•ā´žā´¤āĩ† ā´Žā´˛āĩā´˛ā´ž ML ā´Ģāĩ€ā´šāĩā´šā´ąāĩā´•ā´ŗāĩā´‚ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´‚.", + "machine_learning_facial_recognition": "ā´Žāĩā´–ā´‚ ā´¤ā´ŋā´°ā´ŋⴚāĩā´šā´ąā´ŋā´¯āĩŊ", + "machine_learning_facial_recognition_description": "ⴚā´ŋā´¤āĩā´°ā´™āĩā´™ā´ŗā´ŋā´˛āĩ† ā´Žāĩā´–ā´™āĩā´™āĩž ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤āĩā´•, ā´¤ā´ŋā´°ā´ŋⴚāĩā´šā´ąā´ŋā´¯āĩā´•, ā´—āĩā´°āĩ‚ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "machine_learning_facial_recognition_model": "ā´Žāĩā´–ā´‚ ā´¤ā´ŋā´°ā´ŋⴚāĩā´šā´ąā´ŋā´¯āĩŊ ā´Žāĩ‹ā´ĄāĩŊ", + "machine_learning_facial_recognition_model_description": "ā´Žāĩ‹ā´Ąā´˛āĩā´•āĩž ā´ĩā´˛āĩā´Ēāĩā´Ēā´¤āĩā´¤ā´ŋā´¨āĩā´ąāĩ† ā´…ā´ĩā´°āĩ‹ā´šā´Ŗ ā´•āĩā´°ā´Žā´¤āĩā´¤ā´ŋā´˛ā´žā´Ŗāĩ ā´˛ā´ŋā´¸āĩā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¤ā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤āĩ. ā´ĩā´˛ā´ŋā´¯ ā´Žāĩ‹ā´Ąā´˛āĩā´•āĩž ā´ĩāĩ‡ā´—ā´¤ ā´•āĩā´ąā´žāĩā´žā´¤āĩā´‚ ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ ā´Žāĩ†ā´Žāĩā´Žā´ąā´ŋ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´ĩā´¯āĩā´Žā´žā´Ŗāĩ, ā´Ēā´•āĩā´ˇāĩ‡ ā´Žā´ŋā´•ā´šāĩā´š ā´Ģⴞⴙāĩā´™āĩž ā´¨āĩŊā´•āĩā´¨āĩā´¨āĩ. ā´’ā´°āĩ ā´Žāĩ‹ā´ĄāĩŊ ā´Žā´žā´ąāĩā´ąāĩā´Žāĩā´Ēāĩ‹āĩž ā´Žā´˛āĩā´˛ā´ž ⴚā´ŋā´¤āĩā´°ā´™āĩā´™āĩžā´•āĩā´•āĩā´Žā´žā´¯ā´ŋ 'ā´Žāĩā´–ā´‚ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤āĩŊ' ⴜāĩ‹ā´˛ā´ŋ ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩā´‚ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩ‡ā´Ŗāĩā´Ÿā´¤āĩā´Ŗāĩā´Ÿāĩ†ā´¨āĩā´¨āĩ ā´“āĩŧā´Žāĩā´Žā´ŋā´•āĩā´•āĩā´•.", + "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_recognition_distance": "ā´Ēā´°ā´Žā´žā´ĩā´§ā´ŋ ā´¤ā´ŋā´°ā´ŋⴚāĩā´šā´ąā´ŋā´¯āĩŊ ā´Ļāĩ‚ā´°ā´‚", + "machine_learning_max_recognition_distance_description": "ā´°ā´Ŗāĩā´Ÿāĩ ā´Žāĩā´–ā´™āĩā´™ā´ŗāĩ† ā´’ā´°āĩ‡ ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´¯ā´žā´¯ā´ŋ ā´•ā´Ŗā´•āĩā´•ā´žā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩā´ŗāĩā´ŗ ā´Ēā´°ā´Žā´žā´ĩā´§ā´ŋ ā´Ļāĩ‚ā´°ā´‚, 0-2 ā´ĩā´°āĩ†. ⴇⴤāĩ ā´•āĩā´ąā´¯āĩā´•āĩā´•āĩā´¨āĩā´¨ā´¤āĩ ā´°ā´Ŗāĩā´Ÿāĩ ā´Ēāĩ‡ā´°āĩ† ā´’ā´°āĩ‡ ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´¯ā´žā´¯ā´ŋ ā´˛āĩ‡ā´ŦāĩŊ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤āĩ ā´¤ā´Ÿā´¯ā´žāĩģ ā´¸ā´šā´žā´¯ā´ŋā´•āĩā´•āĩā´‚, ā´…ā´¤āĩ‡ā´¸ā´Žā´¯ā´‚ ⴇⴤāĩ ā´•āĩ‚ā´Ÿāĩā´Ÿāĩā´¨āĩā´¨ā´¤āĩ ā´’ā´°āĩ‡ ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´¯āĩ† ā´°ā´Ŗāĩā´Ÿāĩ ā´ĩāĩā´¯ā´¤āĩā´¯ā´¸āĩā´¤ ⴆⴺāĩā´•ā´ŗā´žā´¯ā´ŋ ā´˛āĩ‡ā´ŦāĩŊ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤āĩ ā´¤ā´Ÿā´¯ā´žā´¨āĩā´‚ ā´¸ā´šā´žā´¯ā´ŋā´•āĩā´•āĩā´‚. ā´’ā´°ā´žā´ŗāĩ† ā´°ā´Ŗāĩā´Ÿā´žā´¯ā´ŋ ā´ĩā´ŋⴭⴜā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ‡ā´•āĩā´•ā´žāĩž ā´Žā´ŗāĩā´Ēāĩā´Ēā´Žā´žā´Ŗāĩ ā´°ā´Ŗāĩā´Ÿāĩā´Ēāĩ‡ā´°āĩ† ā´’ā´¨āĩā´¨ā´žā´•āĩā´•āĩā´¨āĩā´¨ā´¤āĩ ā´Žā´¨āĩā´¨ā´¤āĩ ā´ļāĩā´°ā´Ļāĩā´§ā´ŋā´•āĩā´•āĩā´•, ā´…ā´¤ā´ŋā´¨ā´žāĩŊ ā´¸ā´žā´§āĩā´¯ā´Žā´žā´•āĩā´Žāĩā´Ēāĩ‹āĩž ā´•āĩā´ąā´žāĩā´ž ā´Ēā´°ā´ŋā´§ā´ŋ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´žā´Ŗāĩ ā´‰ā´šā´ŋⴤⴂ.", + "machine_learning_min_detection_score": "ā´•āĩā´ąā´žāĩā´ž ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤āĩŊ ā´¸āĩā´•āĩ‹āĩŧ", + "machine_learning_min_detection_score_description": "ā´’ā´°āĩ ā´Žāĩā´–ā´‚ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩā´ŗāĩā´ŗ ā´ā´ąāĩā´ąā´ĩāĩā´‚ ā´•āĩā´ąā´žāĩā´ž ā´•āĩ‹āĩēā´Ģā´ŋā´Ąāĩģā´¸āĩ ā´¸āĩā´•āĩ‹āĩŧ 0-1 ā´ĩā´°āĩ†. ā´•āĩā´ąā´žāĩā´ž ā´Žāĩ‚ā´˛āĩā´¯ā´™āĩā´™āĩž ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ ā´Žāĩā´–ā´™āĩā´™ā´ŗāĩ† ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤āĩā´‚, ā´Ēā´•āĩā´ˇāĩ‡ ā´¤āĩ†ā´ąāĩā´ąā´žā´¯ ā´Ģⴞⴙāĩā´™ā´ŗā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ⴍⴝā´ŋⴚāĩā´šāĩ‡ā´•āĩā´•ā´žā´‚.", + "machine_learning_min_recognized_faces": "ā´¤ā´ŋā´°ā´ŋⴚāĩā´šā´ąā´ŋā´žāĩā´ž ā´Žāĩā´–ā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´•āĩā´ąā´žāĩā´ž ā´Žā´Ŗāĩā´Ŗā´‚", + "machine_learning_min_recognized_faces_description": "ā´’ā´°āĩ ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´¯āĩ† ā´¸āĩƒā´ˇāĩā´Ÿā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ ā´†ā´ĩā´ļāĩā´¯ā´Žā´žā´¯ ā´¤ā´ŋā´°ā´ŋⴚāĩā´šā´ąā´ŋā´žāĩā´ž ā´Žāĩā´–ā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´ā´ąāĩā´ąā´ĩāĩā´‚ ā´•āĩā´ąā´žāĩā´ž ā´Žā´Ŗāĩā´Ŗā´‚. ⴇⴤāĩ ā´ĩāĩŧā´Ļāĩā´§ā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤āĩ ā´Žāĩā´–ā´‚ ā´¤ā´ŋā´°ā´ŋⴚāĩā´šā´ąā´ŋā´¯āĩŊ ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ ā´•āĩƒā´¤āĩā´¯ā´Žā´žā´•āĩā´•āĩā´¨āĩā´¨āĩ, ā´Žā´¨āĩā´¨ā´žāĩŊ ā´’ā´°āĩ ā´Žāĩā´–ā´‚ ā´’ā´°āĩ ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´•āĩā´•āĩ ā´¨āĩŊā´•ā´žā´¤ā´ŋā´°ā´ŋā´•āĩā´•ā´žā´¨āĩā´ŗāĩā´ŗ ā´¸ā´žā´§āĩā´¯ā´¤ā´¯āĩā´‚ ā´ĩāĩŧā´Ļāĩā´§ā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ.", + "machine_learning_settings": "ā´Žāĩ†ā´ˇāĩ€āĩģ ā´˛āĩ‡ā´Ŗā´ŋā´‚ā´—āĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "machine_learning_settings_description": "ā´Žāĩ†ā´ˇāĩ€āĩģ ā´˛āĩ‡ā´Ŗā´ŋā´‚ā´—āĩ ā´Ģāĩ€ā´šāĩā´šā´ąāĩā´•ā´ŗāĩā´‚ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™ā´ŗāĩā´‚ ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "machine_learning_smart_search": "ā´¸āĩā´Žā´žāĩŧⴟāĩā´Ÿāĩ ā´¸āĩ†āĩŧⴚāĩā´šāĩ", + "machine_learning_smart_search_description": "CLIP ā´Žā´‚ā´Ŧāĩ†ā´Ąāĩā´Ąā´ŋā´‚ā´—āĩâ€Œā´¸āĩ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ⴚā´ŋā´¤āĩā´°ā´™āĩā´™āĩžā´•āĩā´•ā´žā´¯ā´ŋ ā´…āĩŧā´¤āĩā´Ĩā´Ēāĩ‚āĩŧā´ĩāĩā´ĩā´‚ ā´¤ā´ŋā´°ā´¯āĩā´•", + "machine_learning_smart_search_enabled": "ā´¸āĩā´Žā´žāĩŧⴟāĩā´Ÿāĩ ā´¸āĩ†āĩŧⴚāĩā´šāĩ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´•", + "machine_learning_smart_search_enabled_description": "ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•ā´ŋā´¯ā´žāĩŊ, ā´¸āĩā´Žā´žāĩŧⴟāĩā´Ÿāĩ ā´¸āĩ†āĩŧⴚāĩā´šā´ŋā´¨ā´žā´¯ā´ŋ ⴚā´ŋā´¤āĩā´°ā´™āĩā´™āĩž ā´Žāĩģā´•āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿā´ŋā´˛āĩā´˛.", + "machine_learning_url_description": "ā´Žāĩ†ā´ˇāĩ€āĩģ ā´˛āĩ‡ā´Ŗā´ŋā´‚ā´—āĩ ā´¸āĩ†āĩŧā´ĩā´ąā´ŋā´¨āĩā´ąāĩ† URL. ā´’ā´¨āĩā´¨ā´ŋāĩŊ ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ URL-ā´•āĩž ā´¨āĩŊā´•ā´ŋā´¯ā´ŋⴟāĩā´Ÿāĩā´Ŗāĩā´Ÿāĩ†ā´™āĩā´•ā´ŋāĩŊ, ā´“ā´°āĩ‹ ā´¸āĩ†āĩŧā´ĩā´ąāĩā´‚ ā´’ā´¨āĩā´¨ā´ŋā´¨āĩ ā´Ēāĩā´ąā´•āĩ† ā´’ā´¨āĩā´¨ā´žā´¯ā´ŋ ā´ĩā´ŋā´œā´¯ā´•ā´°ā´Žā´žā´¯ā´ŋ ā´Ēāĩā´°ā´¤ā´ŋā´•ā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤āĩā´ĩā´°āĩ† ā´ļāĩā´°ā´Žā´ŋā´•āĩā´•āĩā´‚. ā´Ēāĩā´°ā´¤ā´ŋā´•ā´°ā´ŋā´•āĩā´•ā´žā´¤āĩā´¤ ā´¸āĩ†āĩŧā´ĩā´ąāĩā´•āĩž ā´“āĩēā´˛āĩˆā´¨ā´ŋāĩŊ ā´¤ā´ŋā´°ā´ŋā´•āĩ† ā´ĩā´°āĩā´¨āĩā´¨ā´¤āĩā´ĩā´°āĩ† ā´¤ā´žāĩŊā´•āĩā´•ā´žā´˛ā´ŋā´•ā´Žā´žā´¯ā´ŋ ā´…ā´ĩā´—ā´Ŗā´ŋā´•āĩā´•ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´‚.", + "manage_concurrency": "ā´•āĩ‹āĩēā´•ā´ąāĩģā´¸ā´ŋ ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "manage_log_settings": "ā´˛āĩ‹ā´—āĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "map_dark_style": "ā´Ąā´žāĩŧā´•āĩā´•āĩ ā´¸āĩā´ąāĩā´ąāĩˆāĩŊ", + "map_enable_description": "ā´Žā´žā´Ēāĩā´Ēāĩ ā´Ģāĩ€ā´šāĩā´šā´ąāĩā´•āĩž ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´•", + "map_gps_settings": "ā´Žā´žā´Ēāĩā´Ēāĩ & GPS ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "map_gps_settings_description": "ā´Žā´žā´Ēāĩā´Ēāĩ & GPS (ā´ąā´ŋā´ĩāĩ‡ā´´āĩā´¸āĩ ⴜā´ŋā´¯āĩ‹ā´•āĩ‹ā´Ąā´ŋā´‚ā´—āĩ) ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "map_implications": "ā´Žā´žā´Ēāĩā´Ēāĩ ā´Ģāĩ€ā´šāĩā´šāĩŧ ā´’ā´°āĩ ā´Ŧā´žā´šāĩā´¯ ⴟāĩˆāĩŊ ā´¸āĩ‡ā´ĩⴍⴤāĩā´¤āĩ† (tiles.immich.cloud) ā´†ā´ļāĩā´°ā´¯ā´ŋⴚāĩā´šā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "map_light_style": "ā´˛āĩˆā´ąāĩā´ąāĩ ā´¸āĩā´ąāĩā´ąāĩˆāĩŊ", + "map_manage_reverse_geocoding_settings": "ā´ąā´ŋā´ĩāĩ‡ā´´āĩā´¸āĩ ⴜā´ŋā´¯āĩ‹ā´•āĩ‹ā´Ąā´ŋā´‚ā´—āĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "map_reverse_geocoding": "ā´ąā´ŋā´ĩāĩ‡ā´´āĩā´¸āĩ ⴜā´ŋā´¯āĩ‹ā´•āĩ‹ā´Ąā´ŋā´‚ā´—āĩ", + "map_reverse_geocoding_enable_description": "ā´ąā´ŋā´ĩāĩ‡ā´´āĩā´¸āĩ ⴜā´ŋā´¯āĩ‹ā´•āĩ‹ā´Ąā´ŋā´‚ā´—āĩ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´•", + "map_reverse_geocoding_settings": "ā´ąā´ŋā´ĩāĩ‡ā´´āĩā´¸āĩ ⴜā´ŋā´¯āĩ‹ā´•āĩ‹ā´Ąā´ŋā´‚ā´—āĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "map_settings": "ā´Žā´žā´Ēāĩā´Ēāĩ", + "map_settings_description": "ā´Žā´žā´Ēāĩā´Ēāĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "map_style_description": "ā´’ā´°āĩ style.json ā´Žā´žā´Ēāĩā´Ēāĩ ā´¤āĩ€ā´Žā´ŋā´˛āĩ‡ā´•āĩā´•āĩā´ŗāĩā´ŗ URL", + "memory_cleanup_job": "ā´Žāĩ†ā´Žāĩā´Žā´ąā´ŋ ā´•āĩā´˛āĩ€ā´¨ā´Ēāĩā´Ēāĩ", + "memory_generate_job": "ā´Žāĩ†ā´Žāĩā´Žā´ąā´ŋ ā´œā´¨ā´ąāĩ‡ā´ˇāĩģ", + "metadata_extraction_job": "ā´Žāĩ†ā´ąāĩā´ąā´žā´Ąā´žā´ąāĩā´ą ā´Žā´•āĩâ€Œā´¸āĩâ€Œā´Ÿāĩā´°ā´žā´•āĩā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "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": "ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩā´Ÿāĩ†ā´¯āĩā´‚ ā´Žāĩā´–ā´™āĩā´™ā´ŗāĩā´Ÿāĩ†ā´¯āĩā´‚ ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋā´˛āĩā´•āĩž ā´ā´ąāĩā´ąā´ĩāĩā´‚ ā´Ēāĩā´¤ā´ŋā´¯ ā´Ģāĩ‹āĩžā´Ąāĩŧ ⴘⴟⴍⴝā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Žāĩˆā´—āĩā´°āĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "nightly_tasks_cluster_faces_setting_description": "ā´Ēāĩā´¤āĩā´¤ā´žā´¯ā´ŋ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´ŋā´¯ ā´Žāĩā´–ā´™āĩā´™ā´ŗā´ŋāĩŊ ā´Ģāĩ‡ā´ˇāĩā´¯āĩŊ ā´ąāĩ†ā´•āĩā´•ā´—āĩā´¨ā´ŋā´ˇāĩģ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´•", + "nightly_tasks_cluster_new_faces_setting": "ā´Ēāĩā´¤ā´ŋā´¯ ā´Žāĩā´–ā´™āĩā´™ā´ŗāĩ† ā´•āĩā´˛ā´¸āĩā´ąāĩā´ąāĩŧ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "nightly_tasks_database_cleanup_setting": "ā´Ąā´žā´ąāĩā´ąā´žā´Ŧāĩ‡ā´¸āĩ ā´•āĩā´˛āĩ€ā´¨ā´Ēāĩā´Ēāĩ ā´Ÿā´žā´¸āĩā´•āĩā´•āĩā´•āĩž", + "nightly_tasks_database_cleanup_setting_description": "ā´Ąā´žā´ąāĩā´ąā´žā´Ŧāĩ‡ā´¸ā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´Ēⴴⴝⴤāĩā´‚ ā´•ā´žā´˛ā´šā´°ā´Ŗā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿā´¤āĩā´Žā´žā´¯ ā´Ąā´žā´ąāĩā´ą ā´ĩāĩƒā´¤āĩā´¤ā´ŋā´¯ā´žā´•āĩā´•āĩā´•", + "nightly_tasks_generate_memories_setting": "ā´Žāĩ†ā´Žāĩā´Žā´ąā´ŋā´•āĩž ā´¨ā´ŋāĩŧā´Žāĩā´Žā´ŋā´•āĩā´•āĩā´•", + "nightly_tasks_generate_memories_setting_description": "ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´Ēāĩā´¤ā´ŋā´¯ ā´Žāĩ†ā´Žāĩā´Žā´ąā´ŋā´•āĩž ā´¸āĩƒā´ˇāĩā´Ÿā´ŋā´•āĩā´•āĩā´•", + "nightly_tasks_missing_thumbnails_setting": "ⴍⴎāĩā´Ÿā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿ ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋā´˛āĩā´•āĩž ā´¨ā´ŋāĩŧā´Žāĩā´Žā´ŋā´•āĩā´•āĩā´•", + "nightly_tasks_missing_thumbnails_setting_description": "ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋā´˛āĩā´•āĩž ⴇⴞāĩā´˛ā´žā´¤āĩā´¤ ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩ† ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋāĩŊ ā´¨ā´ŋāĩŧā´Žāĩā´Žā´žā´Ŗā´¤āĩā´¤ā´ŋā´¨ā´žā´¯ā´ŋ ā´•āĩā´¯āĩ‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "nightly_tasks_settings": "ā´°ā´žā´¤āĩā´°ā´ŋā´¯ā´ŋā´˛āĩ† ā´Ÿā´žā´¸āĩā´•āĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "nightly_tasks_settings_description": "ā´°ā´žā´¤āĩā´°ā´ŋā´¯ā´ŋā´˛āĩ† ā´Ÿā´žā´¸āĩā´•āĩā´•āĩā´•āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "nightly_tasks_start_time_setting": "ā´¤āĩā´Ÿā´™āĩā´™āĩā´¨āĩā´¨ ā´¸ā´Žā´¯ā´‚", + "nightly_tasks_start_time_setting_description": "ā´¸āĩ†āĩŧā´ĩāĩŧ ā´°ā´žā´¤āĩā´°ā´ŋā´¯ā´ŋā´˛āĩ† ā´Ÿā´žā´¸āĩā´•āĩā´•āĩā´•āĩž ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•ā´žāĩģ ā´¤āĩā´Ÿā´™āĩā´™āĩā´¨āĩā´¨ ā´¸ā´Žā´¯ā´‚", + "nightly_tasks_sync_quota_usage_setting": "ā´•āĩā´ĩā´žā´Ÿāĩā´Ÿ ā´‰ā´Ēā´¯āĩ‹ā´—ā´‚ ā´¸ā´ŋā´™āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "nightly_tasks_sync_quota_usage_setting_description": "ā´¨ā´ŋā´˛ā´ĩā´ŋā´˛āĩ† ā´‰ā´Ēā´¯āĩ‹ā´—ā´¤āĩā´¤āĩ† ā´…ā´Ÿā´ŋā´¸āĩā´Ĩā´žā´¨ā´Žā´žā´•āĩā´•ā´ŋ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩā´ąāĩ† ā´¸āĩā´ąāĩā´ąāĩ‹ā´ąāĩ‡ā´œāĩ ā´•āĩā´ĩā´žā´Ÿāĩā´Ÿ ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "no_paths_added": "ā´Ēā´žā´¤āĩā´¤āĩā´•āĩž ā´’ā´¨āĩā´¨āĩā´‚ ⴚāĩ‡āĩŧā´¤āĩā´¤ā´ŋⴟāĩā´Ÿā´ŋā´˛āĩā´˛", + "no_pattern_added": "ā´Ēā´žā´ąāĩā´ąāĩ‡āĩē ā´’ā´¨āĩā´¨āĩā´‚ ⴚāĩ‡āĩŧā´¤āĩā´¤ā´ŋⴟāĩā´Ÿā´ŋā´˛āĩā´˛", + "note_apply_storage_label_previous_assets": "ā´•āĩā´ąā´ŋā´Ēāĩā´Ēāĩ: ā´Žāĩā´Žāĩā´Ēāĩ ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¤ ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗā´ŋāĩŊ ā´¸āĩā´ąāĩā´ąāĩ‹ā´ąāĩ‡ā´œāĩ ā´˛āĩ‡ā´ŦāĩŊ ā´Ēāĩā´°ā´¯āĩ‹ā´—ā´ŋā´•āĩā´•ā´žāĩģ, ⴇⴤāĩ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´•", + "note_cannot_be_changed_later": "ā´•āĩā´ąā´ŋā´Ēāĩā´Ēāĩ: ⴇⴤāĩ ā´Ēā´ŋā´¨āĩā´¨āĩ€ā´Ÿāĩ ā´Žā´žā´ąāĩā´ąā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛!", + "notification_email_from_address": "ⴅⴝⴝāĩā´•āĩā´•āĩā´¨āĩā´¨ā´¯ā´žā´ŗāĩā´Ÿāĩ† ā´ĩā´ŋā´˛ā´žā´¸ā´‚", + "notification_email_from_address_description": "ⴅⴝⴝāĩā´•āĩā´•āĩā´¨āĩā´¨ā´¯ā´žā´ŗāĩā´Ÿāĩ† ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ ā´ĩā´ŋā´˛ā´žā´¸ā´‚, ā´‰ā´Ļā´žā´šā´°ā´Ŗā´¤āĩā´¤ā´ŋā´¨āĩ: \"Immich Photo Server \". ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‡ā´Žāĩ†ā´¯ā´ŋā´˛āĩā´•āĩž ⴅⴝⴝāĩā´•āĩā´•ā´žāĩģ ā´…ā´¨āĩā´ĩā´žā´Ļā´Žāĩā´ŗāĩā´ŗ ā´’ā´°āĩ ā´ĩā´ŋā´˛ā´žā´¸ā´‚ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩā´ĩāĩ†ā´¨āĩā´¨āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´•āĩā´•āĩā´•.", + "notification_email_host_description": "ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ ā´¸āĩ†āĩŧā´ĩā´ąā´ŋā´¨āĩā´ąāĩ† ā´šāĩ‹ā´¸āĩā´ąāĩā´ąāĩ (ā´‰ā´Ļā´ž. smtp.immich.app)", + "notification_email_ignore_certificate_errors": "ā´¸āĩŧⴟāĩā´Ÿā´ŋā´Ģā´ŋā´•āĩā´•ā´ąāĩā´ąāĩ ā´Ēā´ŋā´ļā´•āĩā´•āĩž ā´…ā´ĩā´—ā´Ŗā´ŋā´•āĩā´•āĩā´•", + "notification_email_ignore_certificate_errors_description": "TLS ā´¸āĩŧⴟāĩā´Ÿā´ŋā´Ģā´ŋā´•āĩā´•ā´ąāĩā´ąāĩ ā´¸ā´žā´§āĩā´¤ā´ž ā´Ēā´ŋā´ļā´•āĩā´•āĩž ā´…ā´ĩā´—ā´Ŗā´ŋā´•āĩā´•āĩā´• (ā´ļāĩā´Ēā´žāĩŧā´ļ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´ŋā´˛āĩā´˛)", + "notification_email_password_description": "ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ ā´¸āĩ†āĩŧā´ĩā´ąāĩā´Žā´žā´¯ā´ŋ ā´Ēāĩā´°ā´žā´Žā´žā´Ŗāĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´Žāĩā´Ēāĩ‹āĩž ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩ‡ā´Ŗāĩā´Ÿ ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ", + "notification_email_port_description": "ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ ā´¸āĩ†āĩŧā´ĩā´ąā´ŋā´¨āĩā´ąāĩ† ā´Ēāĩ‹āĩŧⴟāĩā´Ÿāĩ (ā´‰ā´Ļā´ž. 25, 465, ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ 587)", + "notification_email_sent_test_email_button": "ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´¨ā´ž ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ ā´…ā´¯ā´šāĩā´šāĩ ā´¸āĩ‡ā´ĩāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "notification_email_setting_description": "ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ ā´…ā´ąā´ŋā´¯ā´ŋā´Ēāĩā´Ēāĩā´•āĩž ⴅⴝⴕāĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩā´ŗāĩā´ŗ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "notification_email_test_email": "ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´¨ā´ž ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ ⴅⴝⴕāĩā´•āĩā´•", + "notification_email_test_email_failed": "ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´¨ā´ž ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ ⴅⴝⴕāĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ, ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Žāĩ‚ā´˛āĩā´¯ā´™āĩā´™āĩž ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´ŋā´•āĩā´•āĩā´•", + "notification_email_test_email_sent": "{email} ā´Žā´¨āĩā´¨ ā´ĩā´ŋā´˛ā´žā´¸ā´¤āĩā´¤ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´’ā´°āĩ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´¨ā´ž ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ ā´…ā´¯ā´šāĩā´šā´ŋⴟāĩā´Ÿāĩā´Ŗāĩā´Ÿāĩ. ā´Ļā´¯ā´ĩā´žā´¯ā´ŋ ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´‡āĩģā´Ŧāĩ‹ā´•āĩā´¸āĩ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´ŋā´•āĩā´•āĩā´•.", + "notification_email_username_description": "ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ ā´¸āĩ†āĩŧā´ĩā´ąāĩā´Žā´žā´¯ā´ŋ ā´Ēāĩā´°ā´žā´Žā´žā´Ŗāĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´Žāĩā´Ēāĩ‹āĩž ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩ‡ā´Ŗāĩā´Ÿ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤āĩƒā´¨ā´žā´Žā´‚", + "notification_enable_email_notifications": "ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ ā´…ā´ąā´ŋā´¯ā´ŋā´Ēāĩā´Ēāĩā´•āĩž ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´•", + "notification_settings": "ā´…ā´ąā´ŋā´¯ā´ŋā´Ēāĩā´Ēāĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "notification_settings_description": "ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ ā´‰āĩžā´Ēāĩā´Ēāĩ†ā´Ÿāĩ†ā´¯āĩā´ŗāĩā´ŗ ā´…ā´ąā´ŋā´¯ā´ŋā´Ēāĩā´Ēāĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "oauth_auto_launch": "ā´¯ā´žā´¨āĩā´¤āĩā´°ā´ŋā´•ā´Žā´žā´¯ā´ŋ ā´¤āĩā´Ÿā´™āĩā´™āĩā´•", + "oauth_auto_launch_description": "ā´˛āĩ‹ā´—ā´ŋāĩģ ā´Ēāĩ‡ā´œā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Ēāĩ‹ā´•āĩā´Žāĩā´Ēāĩ‹āĩž OAuth ā´˛āĩ‹ā´—ā´ŋāĩģ ā´Ģāĩā´˛āĩ‹ ā´¯ā´žā´¨āĩā´¤āĩā´°ā´ŋā´•ā´Žā´žā´¯ā´ŋ ⴆⴰⴂⴭā´ŋā´•āĩā´•āĩā´•", + "oauth_auto_register": "ā´¯ā´žā´¨āĩā´¤āĩā´°ā´ŋā´•ā´Žā´žā´¯ā´ŋ ⴰⴜā´ŋā´¸āĩā´ąāĩā´ąāĩŧ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "oauth_auto_register_description": "OAuth ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ā´¸āĩˆāĩģ ā´‡āĩģ ⴚāĩ†ā´¯āĩā´¤ ā´ļāĩ‡ā´ˇā´‚ ā´Ēāĩā´¤ā´ŋā´¯ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´•āĩā´•ā´ŗāĩ† ā´¯ā´žā´¨āĩā´¤āĩā´°ā´ŋā´•ā´Žā´žā´¯ā´ŋ ⴰⴜā´ŋā´¸āĩā´ąāĩā´ąāĩŧ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "oauth_button_text": "ā´Ŧⴟāĩā´Ÿā´Ŗā´ŋā´˛āĩ† ā´ĩā´žā´šā´•ā´‚", + "oauth_client_secret_description": "OAuth ā´Ļā´žā´¤ā´žā´ĩāĩ PKCE (ā´Ēāĩā´°āĩ‚ā´Ģāĩ ā´•āĩ€ ā´Ģāĩ‹āĩŧ ā´•āĩ‹ā´Ąāĩ ā´Žā´•āĩā´¸āĩā´šāĩ‡ā´žāĩā´šāĩ) ā´Ēā´ŋā´¨āĩā´¤āĩā´Ŗā´¯āĩā´•āĩā´•āĩā´¨āĩā´¨ā´ŋā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ ā´†ā´ĩā´ļāĩā´¯ā´Žā´žā´Ŗāĩ", + "oauth_enable_description": "OAuth ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ā´˛āĩ‹ā´—ā´ŋāĩģ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "oauth_mobile_redirect_uri": "ā´ŽāĩŠā´ŦāĩˆāĩŊ ā´ąāĩ€ā´Ąā´¯ā´ąā´•āĩā´Ÿāĩ URI", + "oauth_mobile_redirect_uri_override": "ā´ŽāĩŠā´ŦāĩˆāĩŊ ā´ąāĩ€ā´Ąā´¯ā´ąā´•āĩā´Ÿāĩ URI ā´“ā´ĩāĩŧā´ąāĩˆā´Ąāĩ", + "oauth_mobile_redirect_uri_override_description": "OAuth ā´Ļā´žā´¤ā´žā´ĩāĩ \"{callback}\" ā´Ēāĩ‹ā´˛āĩā´ŗāĩā´ŗ ā´’ā´°āĩ ā´ŽāĩŠā´ŦāĩˆāĩŊ URI ā´…ā´¨āĩā´ĩā´Ļā´ŋā´•āĩā´•ā´žā´¤āĩā´¤ā´Ēāĩā´Ēāĩ‹āĩž ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´•", + "oauth_role_claim": "ā´ąāĩ‹āĩž ā´•āĩā´˛āĩ†ā´¯ā´ŋā´‚", + "oauth_role_claim_description": "ⴈ ā´•āĩā´˛āĩ†ā´¯ā´ŋā´Žā´ŋā´¨āĩā´ąāĩ† ā´¸ā´žā´¨āĩā´¨ā´ŋā´§āĩā´¯ā´¤āĩā´¤āĩ† ā´…ā´Ÿā´ŋā´¸āĩā´Ĩā´žā´¨ā´Žā´žā´•āĩā´•ā´ŋ ā´¯ā´žā´¨āĩā´¤āĩā´°ā´ŋā´•ā´Žā´žā´¯ā´ŋ ā´…ā´Ąāĩā´Žā´ŋāĩģ ⴆⴕāĩā´¸ā´¸āĩ ā´¨āĩŊā´•āĩā´•. ā´•āĩā´˛āĩ†ā´¯ā´ŋā´Žā´ŋā´¨āĩ 'user' ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ 'admin' ā´Žā´¨āĩā´¨āĩ ⴉ⴪āĩā´Ÿā´žā´•ā´žā´‚.", + "oauth_settings": "OAuth", + "oauth_settings_description": "OAuth ā´˛āĩ‹ā´—ā´ŋāĩģ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "oauth_settings_more_details": "ⴈ ā´Ģāĩ€ā´šāĩā´šā´ąā´ŋā´¨āĩ†ā´•āĩā´•āĩā´ąā´ŋⴚāĩā´šāĩā´ŗāĩā´ŗ ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ ā´ĩā´ŋā´ĩā´°ā´™āĩā´™āĩžā´•āĩā´•āĩ, ā´Ąāĩ‹ā´•āĩā´¸āĩ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´ŋā´•āĩā´•āĩā´•.", + "oauth_storage_label_claim": "ā´¸āĩā´ąāĩā´ąāĩ‹ā´ąāĩ‡ā´œāĩ ā´˛āĩ‡ā´ŦāĩŊ ā´•āĩā´˛āĩ†ā´¯ā´ŋā´‚", + "oauth_storage_label_claim_description": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩā´ąāĩ† ā´¸āĩā´ąāĩā´ąāĩ‹ā´ąāĩ‡ā´œāĩ ā´˛āĩ‡ā´ŦāĩŊ ⴈ ā´•āĩā´˛āĩ†ā´¯ā´ŋā´Žā´ŋā´¨āĩā´ąāĩ† ā´Žāĩ‚ā´˛āĩā´¯ā´¤āĩā´¤ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´¯ā´žā´¨āĩā´¤āĩā´°ā´ŋā´•ā´Žā´žā´¯ā´ŋ ⴏⴜāĩā´œā´Žā´žā´•āĩā´•āĩā´•.", + "oauth_storage_quota_claim": "ā´¸āĩā´ąāĩā´ąāĩ‹ā´ąāĩ‡ā´œāĩ ā´•āĩā´ĩā´žā´Ÿāĩā´Ÿ ā´•āĩā´˛āĩ†ā´¯ā´ŋā´‚", + "oauth_storage_quota_claim_description": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩā´ąāĩ† ā´¸āĩā´ąāĩā´ąāĩ‹ā´ąāĩ‡ā´œāĩ ā´•āĩā´ĩā´žā´Ÿāĩā´Ÿ ⴈ ā´•āĩā´˛āĩ†ā´¯ā´ŋā´Žā´ŋā´¨āĩā´ąāĩ† ā´Žāĩ‚ā´˛āĩā´¯ā´¤āĩā´¤ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´¯ā´žā´¨āĩā´¤āĩā´°ā´ŋā´•ā´Žā´žā´¯ā´ŋ ⴏⴜāĩā´œā´Žā´žā´•āĩā´•āĩā´•.", + "oauth_storage_quota_default": "ā´Ąā´ŋā´Ģāĩ‹āĩžā´Ÿāĩā´Ÿāĩ ā´¸āĩā´ąāĩā´ąāĩ‹ā´ąāĩ‡ā´œāĩ ā´•āĩā´ĩā´žā´Ÿāĩā´Ÿ (GiB)", + "oauth_storage_quota_default_description": "ā´•āĩā´˛āĩ†ā´¯ā´ŋā´‚ ā´’ā´¨āĩā´¨āĩā´‚ ā´¨āĩŊā´•ā´žā´¤āĩā´¤ā´Ēāĩā´Ēāĩ‹āĩž ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩ‡ā´Ŗāĩā´Ÿ ā´•āĩā´ĩā´žā´Ÿāĩā´Ÿ (GiB-ā´¯ā´ŋāĩŊ).", + "oauth_timeout": "ā´…ā´­āĩā´¯āĩŧā´¤āĩā´Ĩⴍⴝāĩā´Ÿāĩ† ā´¸ā´Žā´¯ā´Ēā´°ā´ŋā´§ā´ŋ", + "oauth_timeout_description": "ā´…ā´­āĩā´¯āĩŧā´¤āĩā´Ĩⴍⴕāĩžā´•āĩā´•āĩā´ŗāĩā´ŗ ā´¸ā´Žā´¯ā´Ēā´°ā´ŋā´§ā´ŋ (ā´Žā´ŋā´˛āĩā´˛ā´ŋā´¸āĩ†ā´•āĩā´•āĩģā´Ąā´ŋāĩŊ)", + "password_enable_description": "ā´‡ā´Žāĩ†ā´¯ā´ŋā´˛āĩā´‚ ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩā´‚ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ā´˛āĩ‹ā´—ā´ŋāĩģ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "password_settings": "ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´˛āĩ‹ā´—ā´ŋāĩģ", + "password_settings_description": "ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´˛āĩ‹ā´—ā´ŋāĩģ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "paths_validated_successfully": "ā´Žā´˛āĩā´˛ā´ž ā´Ēā´žā´¤āĩā´¤āĩā´•ā´ŗāĩā´‚ ā´ĩā´ŋā´œā´¯ā´•ā´°ā´Žā´žā´¯ā´ŋ ā´¸ā´žā´§āĩ‚ā´•ā´°ā´ŋⴚāĩā´šāĩ", + "person_cleanup_job": "ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋ ā´•āĩā´˛āĩ€ā´¨ā´Ēāĩā´Ēāĩ", + "quota_size_gib": "ā´•āĩā´ĩā´žā´Ÿāĩā´Ÿ ā´ĩā´˛āĩā´Ēāĩā´Ēā´‚ (GiB)", + "refreshing_all_libraries": "ā´Žā´˛āĩā´˛ā´ž ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋā´•ā´ŗāĩā´‚ ā´Ēāĩā´¤āĩā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "registration": "ā´…ā´Ąāĩā´Žā´ŋāĩģ ⴰⴜā´ŋā´¸āĩā´Ÿāĩā´°āĩ‡ā´ˇāĩģ", + "registration_description": "ā´¨ā´ŋā´™āĩā´™ā´ŗā´žā´Ŗāĩ ā´¸ā´ŋā´¸āĩā´ąāĩā´ąā´¤āĩā´¤ā´ŋā´˛āĩ† ā´†ā´Ļāĩā´¯ā´¤āĩā´¤āĩ† ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩāĩ ā´Žā´¨āĩā´¨ā´¤ā´ŋā´¨ā´žāĩŊ, ā´¨ā´ŋā´™āĩā´™ā´ŗāĩ† ā´…ā´Ąāĩā´Žā´ŋāĩģ ⴆⴝā´ŋ ā´¨ā´ŋā´¯ā´Žā´ŋā´•āĩā´•āĩā´‚. ā´­ā´°ā´Ŗā´Ēā´°ā´Žā´žā´¯ ⴜāĩ‹ā´˛ā´ŋā´•āĩžā´•āĩā´•āĩ ā´¨ā´ŋā´™āĩā´™āĩž ⴉⴤāĩā´¤ā´°ā´ĩā´žā´Ļā´ŋā´¯ā´žā´¯ā´ŋā´°ā´ŋā´•āĩā´•āĩā´‚, ā´•āĩ‚ā´Ÿā´žā´¤āĩ† ā´…ā´§ā´ŋā´• ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´•āĩā´•ā´ŗāĩ† ā´¸āĩƒā´ˇāĩā´Ÿā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤āĩ ā´¨ā´ŋā´™āĩā´™ā´ŗā´žā´¯ā´ŋā´°ā´ŋā´•āĩā´•āĩā´‚.", + "require_password_change_on_login": "ā´†ā´Ļāĩā´¯ ā´˛āĩ‹ā´—ā´ŋāĩģ ⴚāĩ†ā´¯āĩā´¯āĩā´Žāĩā´Ēāĩ‹āĩž ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´Žā´žā´ąāĩā´ąā´žāĩģ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ‹ā´Ÿāĩ ā´†ā´ĩā´ļāĩā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´•", + "reset_settings_to_default": "ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´Ąā´ŋā´Ģāĩ‹āĩžā´Ÿāĩā´Ÿā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Ēāĩā´¨ā´ƒā´¸ā´œāĩā´œā´Žā´žā´•āĩā´•āĩā´•", + "reset_settings_to_recent_saved": "ā´…ā´Ÿāĩā´¤āĩā´¤ā´ŋⴟāĩ† ā´¸āĩ‡ā´ĩāĩ ⴚāĩ†ā´¯āĩā´¤ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™ā´ŗā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Ēāĩā´¨ā´ƒā´¸ā´œāĩā´œā´Žā´žā´•āĩā´•āĩā´•", + "scanning_library": "ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ ā´¸āĩā´•ā´žāĩģ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ", + "search_jobs": "ⴜāĩ‹ā´˛ā´ŋā´•āĩžā´•āĩā´•ā´žā´¯ā´ŋ ā´¤ā´ŋā´°ā´¯āĩā´•â€Ļ", + "send_welcome_email": "ā´¸āĩā´ĩā´žā´—ā´¤ ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ ⴅⴝⴕāĩā´•āĩā´•", + "server_external_domain_settings": "ā´Ŧā´žā´šāĩā´¯ ā´ĄāĩŠā´Žāĩ†ā´¯āĩāĩģ", + "server_external_domain_settings_description": "ā´ĒāĩŠā´¤āĩā´ĩā´žā´¯ā´ŋ ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´˛ā´ŋā´™āĩā´•āĩā´•āĩžā´•āĩā´•āĩā´ŗāĩā´ŗ ā´ĄāĩŠā´Žāĩ†ā´¯āĩāĩģ, http(s):// ā´‰āĩžā´Ēāĩā´Ēāĩ†ā´Ÿāĩ†", + "server_public_users": "ā´ĒāĩŠā´¤āĩ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´•āĩā´•āĩž", + "server_public_users_description": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´†āĩŊā´Ŧā´™āĩā´™ā´ŗā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´’ā´°āĩ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ† ⴚāĩ‡āĩŧā´•āĩā´•āĩā´Žāĩā´Ēāĩ‹āĩž ā´Žā´˛āĩā´˛ā´ž ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´•āĩā´•ā´ŗāĩ†ā´¯āĩā´‚ (ā´Ēāĩ‡ā´°āĩā´‚ ā´‡ā´Žāĩ†ā´¯ā´ŋā´˛āĩā´‚) ā´˛ā´ŋā´¸āĩā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´‚. ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•āĩā´Žāĩā´Ēāĩ‹āĩž, ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤āĩƒ ā´˛ā´ŋā´¸āĩā´ąāĩā´ąāĩ ā´…ā´Ąāĩā´Žā´ŋāĩģ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´•āĩā´•āĩžā´•āĩā´•āĩ ā´Žā´žā´¤āĩā´°ā´Žāĩ‡ ⴞⴭāĩā´¯ā´Žā´žā´•āĩ‚.", + "server_settings": "ā´¸āĩ†āĩŧā´ĩāĩŧ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "server_settings_description": "ā´¸āĩ†āĩŧā´ĩāĩŧ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "server_welcome_message": "ā´¸āĩā´ĩā´žā´—ā´¤ ⴏⴍāĩā´Ļāĩ‡ā´ļā´‚", + "server_welcome_message_description": "ā´˛āĩ‹ā´—ā´ŋāĩģ ā´Ēāĩ‡ā´œā´ŋāĩŊ ā´Ēāĩā´°ā´Ļāĩŧā´ļā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´¨āĩā´¨ ā´’ā´°āĩ ⴏⴍāĩā´Ļāĩ‡ā´ļā´‚.", + "sidecar_job": "ā´¸āĩˆā´Ąāĩâ€Œā´•ā´žāĩŧ ā´Žāĩ†ā´ąāĩā´ąā´žā´Ąā´žā´ąāĩā´ą", + "sidecar_job_description": "ā´Ģā´¯āĩŊā´¸ā´ŋā´¸āĩā´ąāĩā´ąā´¤āĩā´¤ā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´¸āĩˆā´Ąāĩâ€Œā´•ā´žāĩŧ ā´Žāĩ†ā´ąāĩā´ąā´žā´Ąā´žā´ąāĩā´ą ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤āĩā´•ā´¯āĩ‹ ā´¸ā´ŋāĩģā´•āĩā´°āĩŠā´Ŗāĩˆā´¸āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•ā´¯āĩ‹ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "slideshow_duration_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_job": "ā´¸āĩā´ąāĩā´ąāĩ‹ā´ąāĩ‡ā´œāĩ ⴟāĩ†ā´‚ā´Ēāĩā´˛āĩ‡ā´ąāĩā´ąāĩ ā´Žāĩˆā´—āĩā´°āĩ‡ā´ˇāĩģ ⴜāĩ‹ā´˛ā´ŋ", + "storage_template_more_details": "ⴈ ā´Ģāĩ€ā´šāĩā´šā´ąā´ŋā´¨āĩ†ā´•āĩā´•āĩā´ąā´ŋⴚāĩā´šāĩā´ŗāĩā´ŗ ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ ā´ĩā´ŋā´ĩā´°ā´™āĩā´™āĩžā´•āĩā´•āĩ, ā´¸āĩā´ąāĩā´ąāĩ‹ā´ąāĩ‡ā´œāĩ ⴟāĩ†ā´‚ā´Ēāĩā´˛āĩ‡ā´ąāĩā´ąāĩ-ⴉⴂ ā´…ā´¤ā´ŋāĩģāĩā´ąāĩ† ā´Ēāĩā´°ā´¤āĩā´¯ā´žā´˜ā´žā´¤ā´™āĩā´™ā´ŗāĩā´‚ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´ŋā´•āĩā´•āĩā´•", + "storage_template_onboarding_description_v2": "ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´Žāĩā´Ēāĩ‹āĩž, ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩāĩ ā´¨ā´ŋāĩŧā´ĩⴚā´ŋⴚāĩā´š ⴟāĩ†ā´‚ā´Ēāĩā´˛āĩ‡ā´ąāĩā´ąāĩ ā´…ā´Ÿā´ŋā´¸āĩā´Ĩā´žā´¨ā´Žā´žā´•āĩā´•ā´ŋ ⴈ ā´Ģāĩ€ā´šāĩā´šāĩŧ ā´Ģⴝⴞāĩā´•āĩž ā´¯ā´žā´¨āĩā´¤āĩā´°ā´ŋā´•ā´Žā´žā´¯ā´ŋ ā´“āĩŧā´—ā´¨āĩˆā´¸āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´‚. ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ ā´ĩā´ŋā´ĩā´°ā´™āĩā´™āĩžā´•āĩā´•āĩ, ā´Ļā´¯ā´ĩā´žā´¯ā´ŋ ā´Ąāĩ‹ā´•āĩā´¯āĩā´Žāĩ†ā´¨āĩā´ąāĩ‡ā´ˇāĩģ ā´•ā´žā´Ŗāĩā´•.", + "storage_template_path_length": "ā´ā´•ā´Ļāĩ‡ā´ļ ā´Ēā´žā´¤āĩā´¤āĩ ā´Ļāĩˆāĩŧⴘāĩā´¯ ā´Ēā´°ā´ŋā´§ā´ŋ: {length, number}/{limit, number}", + "storage_template_settings": "ā´¸āĩā´ąāĩā´ąāĩ‹ā´ąāĩ‡ā´œāĩ ⴟāĩ†ā´‚ā´Ēāĩā´˛āĩ‡ā´ąāĩā´ąāĩ", + "storage_template_settings_description": "ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ ā´…ā´¸ā´ąāĩā´ąā´ŋā´¨āĩā´ąāĩ† ā´Ģāĩ‹āĩžā´Ąāĩŧ ⴘⴟⴍⴝāĩā´‚ ā´Ģā´¯āĩŊ ā´¨ā´žā´Žā´ĩāĩā´‚ ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "storage_template_user_label": "{label} ā´Žā´¨āĩā´¨ā´¤āĩ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩā´ąāĩ† ā´¸āĩā´ąāĩā´ąāĩ‹ā´ąāĩ‡ā´œāĩ ā´˛āĩ‡ā´Ŧā´˛ā´žā´Ŗāĩ", + "system_settings": "ā´¸ā´ŋā´¸āĩā´ąāĩā´ąā´‚ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "tag_cleanup_job": "ā´Ÿā´žā´—āĩ ā´•āĩā´˛āĩ€ā´¨ā´Ēāĩā´Ēāĩ", + "template_email_available_tags": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ⴟāĩ†ā´‚ā´Ēāĩā´˛āĩ‡ā´ąāĩā´ąā´ŋāĩŊ ⴇⴍā´ŋā´Ēāĩā´Ēā´ąā´¯āĩā´¨āĩā´¨ ā´ĩāĩ‡ā´°ā´ŋā´¯ā´Ŧā´ŋā´ŗāĩā´•āĩž ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•ā´žā´‚: {tags}", + "template_email_if_empty": "ⴟāĩ†ā´‚ā´Ēāĩā´˛āĩ‡ā´ąāĩā´ąāĩ ā´ļāĩ‚ā´¨āĩā´¯ā´Žā´žā´Ŗāĩ†ā´™āĩā´•ā´ŋāĩŊ, ā´Ąā´ŋā´Ģāĩ‹āĩžā´Ÿāĩā´Ÿāĩ ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´‚.", + "template_email_invite_album": "ā´†āĩŊā´Ŧā´‚ ā´•āĩā´ˇā´Ŗā´ŋā´•āĩā´•ā´žā´¨āĩā´ŗāĩā´ŗ ⴟāĩ†ā´‚ā´Ēāĩā´˛āĩ‡ā´ąāĩā´ąāĩ", + "template_email_preview": "ā´Ēāĩā´°ā´ŋā´ĩāĩā´¯āĩ‚", + "template_email_settings": "ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ ⴟāĩ†ā´‚ā´Ēāĩā´˛āĩ‡ā´ąāĩā´ąāĩā´•āĩž", + "template_email_update_album": "ā´†āĩŊā´Ŧā´‚ ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴟāĩ†ā´‚ā´Ēāĩā´˛āĩ‡ā´ąāĩā´ąāĩ", + "template_email_welcome": "ā´¸āĩā´ĩā´žā´—ā´¤ ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ ⴟāĩ†ā´‚ā´Ēāĩā´˛āĩ‡ā´ąāĩā´ąāĩ", + "template_settings": "ā´…ā´ąā´ŋā´¯ā´ŋā´Ēāĩā´Ēāĩ ⴟāĩ†ā´‚ā´Ēāĩā´˛āĩ‡ā´ąāĩā´ąāĩā´•āĩž", + "template_settings_description": "ā´…ā´ąā´ŋā´¯ā´ŋā´Ēāĩā´Ēāĩā´•āĩžā´•āĩā´•ā´žā´¯ā´ŋ ⴇⴎāĩā´Ÿā´žā´¨āĩā´¸āĩƒā´¤ ⴟāĩ†ā´‚ā´Ēāĩā´˛āĩ‡ā´ąāĩā´ąāĩā´•āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "theme_custom_css_settings": "ā´•ā´¸āĩā´ąāĩā´ąā´‚ CSS", + "theme_custom_css_settings_description": "ā´•ā´žā´¸āĩā´•āĩ‡ā´Ąā´ŋā´‚ā´—āĩ ā´¸āĩā´ąāĩā´ąāĩˆāĩŊ ā´ˇāĩ€ā´ąāĩā´ąāĩā´•āĩž (CSS) Immich-ā´¨āĩā´ąāĩ† ā´Ąā´ŋā´¸āĩˆāĩģ ⴇⴎāĩā´Ÿā´žā´¨āĩā´¸āĩƒā´¤ā´Žā´žā´•āĩā´•ā´žāĩģ ā´…ā´¨āĩā´ĩā´Ļā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ.", + "theme_settings": "ā´¤āĩ€ā´‚ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "theme_settings_description": "Immich ā´ĩāĩ†ā´Ŧāĩ ⴇⴍāĩā´ąāĩŧā´Ģāĩ‡ā´¸ā´ŋā´¨āĩā´ąāĩ† ā´•ā´¸āĩā´ąāĩā´ąā´Žāĩˆā´¸āĩ‡ā´ˇāĩģ ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "thumbnail_generation_job": "ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋā´˛āĩā´•āĩž ā´¨ā´ŋāĩŧā´Žāĩā´Žā´ŋā´•āĩā´•āĩā´•", + "thumbnail_generation_job_description": "ā´“ā´°āĩ‹ ā´…ā´¸ā´ąāĩā´ąā´ŋā´¨āĩā´‚ ā´ĩā´˛āĩā´¤āĩā´‚ ⴚāĩ†ā´ąāĩā´¤āĩā´‚ ā´Žā´™āĩā´™ā´ŋⴝⴤāĩā´Žā´žā´¯ ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋā´˛āĩā´•ā´ŗāĩā´‚ ā´“ā´°āĩ‹ ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´•āĩā´•āĩā´‚ ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋā´˛āĩā´•ā´ŗāĩā´‚ ā´¨ā´ŋāĩŧā´Žāĩā´Žā´ŋā´•āĩā´•āĩā´•", + "transcoding_acceleration_api": "ⴆⴕāĩā´¸ā´ŋā´˛ā´ąāĩ‡ā´ˇāĩģ API", + "transcoding_acceleration_api_description": "ⴟāĩā´°ā´žāĩģā´¸āĩâ€Œā´•āĩ‹ā´Ąā´ŋā´‚ā´—āĩ ā´¤āĩā´ĩā´°ā´ŋā´¤ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¤āĩā´¤āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´‰ā´Ēā´•ā´°ā´Ŗā´ĩāĩā´Žā´žā´¯ā´ŋ ⴏⴂā´ĩā´Ļā´ŋā´•āĩā´•āĩā´¨āĩā´¨ API. ⴈ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´‚ 'ā´Ŧāĩ†ā´¸āĩā´ąāĩā´ąāĩ ā´Žā´Ģāĩ‡āĩŧⴟāĩā´Ÿāĩ' ⴆ⴪āĩ: ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿā´žāĩŊ ā´¸āĩ‹ā´Ģāĩā´ąāĩā´ąāĩâ€Œā´ĩāĩ†ā´¯āĩŧ ⴟāĩā´°ā´žāĩģā´¸āĩâ€Œā´•āĩ‹ā´Ąā´ŋā´‚ā´—ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Žā´žā´ąāĩā´‚. ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´šā´žāĩŧā´Ąāĩâ€Œā´ĩāĩ†ā´¯āĩŧ ā´…ā´¨āĩā´¸ā´°ā´ŋⴚāĩā´šāĩ VP9 ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋā´•āĩā´•āĩā´•ā´¯āĩ‹ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋā´•āĩā´•ā´žā´¤ā´ŋā´°ā´ŋā´•āĩā´•āĩā´•ā´¯āĩ‹ ⴚāĩ†ā´¯āĩā´¯ā´žā´‚.", + "transcoding_acceleration_nvenc": "NVENC (NVIDIA GPU ā´†ā´ĩā´ļāĩā´¯ā´Žā´žā´Ŗāĩ)", + "transcoding_acceleration_qsv": "ā´•āĩā´ĩā´ŋā´•āĩā´•āĩ ā´¸ā´ŋā´™āĩā´•āĩ (7-ā´žā´‚ ā´¤ā´˛ā´Žāĩā´ą ⴇⴍāĩā´ąāĩŊ ā´¸ā´ŋā´Ēā´ŋā´¯āĩ ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ ā´…ā´¤ā´ŋā´¨āĩā´ļāĩ‡ā´ˇā´Žāĩā´ŗāĩā´ŗā´¤āĩ ā´†ā´ĩā´ļāĩā´¯ā´Žā´žā´Ŗāĩ)", + "transcoding_acceleration_rkmpp": "RKMPP (Rockchip SOC-ā´•ā´ŗā´ŋāĩŊ ā´Žā´žā´¤āĩā´°ā´‚)", + "transcoding_acceleration_vaapi": "VAAPI", + "transcoding_accepted_audio_codecs": "ā´…ā´‚ā´—āĩ€ā´•āĩƒā´¤ ā´“ā´Ąā´ŋā´¯āĩ‹ ā´•āĩ‹ā´Ąāĩ†ā´•āĩā´•āĩā´•āĩž", + "transcoding_accepted_audio_codecs_description": "ⴟāĩā´°ā´žāĩģā´¸āĩâ€Œā´•āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩ‡ā´Ŗāĩā´Ÿā´žā´¤āĩā´¤ ā´“ā´Ąā´ŋā´¯āĩ‹ ā´•āĩ‹ā´Ąāĩ†ā´•āĩā´•āĩā´•āĩž ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•. ⴚā´ŋā´˛ ⴟāĩā´°ā´žāĩģā´¸āĩâ€Œā´•āĩ‹ā´Ąāĩ ⴍⴝⴙāĩā´™āĩžā´•āĩā´•āĩ ā´ĩāĩ‡ā´Ŗāĩā´Ÿā´ŋ ā´Žā´žā´¤āĩā´°ā´‚ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ.", + "transcoding_accepted_containers": "ā´…ā´‚ā´—āĩ€ā´•āĩƒā´¤ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¯āĩâ€Œā´¨ā´ąāĩā´•āĩž", + "transcoding_accepted_containers_description": "MP4-ā´˛āĩ‡ā´•āĩā´•āĩ ā´ąāĩ€ā´Žā´•āĩā´¸āĩ ⴚāĩ†ā´¯āĩā´¯āĩ‡ā´Ŗāĩā´Ÿā´žā´¤āĩā´¤ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¯āĩâ€Œā´¨āĩŧ ā´Ģāĩ‹āĩŧā´Žā´žā´ąāĩā´ąāĩā´•āĩž ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•. ⴚā´ŋā´˛ ⴟāĩā´°ā´žāĩģā´¸āĩâ€Œā´•āĩ‹ā´Ąāĩ ⴍⴝⴙāĩā´™āĩžā´•āĩā´•āĩ ā´ĩāĩ‡ā´Ŗāĩā´Ÿā´ŋ ā´Žā´žā´¤āĩā´°ā´‚ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ.", + "transcoding_accepted_video_codecs": "ā´…ā´‚ā´—āĩ€ā´•āĩƒā´¤ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ ā´•āĩ‹ā´Ąāĩ†ā´•āĩā´•āĩā´•āĩž", + "transcoding_accepted_video_codecs_description": "ⴟāĩā´°ā´žāĩģā´¸āĩâ€Œā´•āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩ‡ā´Ŗāĩā´Ÿā´žā´¤āĩā´¤ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ ā´•āĩ‹ā´Ąāĩ†ā´•āĩā´•āĩā´•āĩž ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•. ⴚā´ŋā´˛ ⴟāĩā´°ā´žāĩģā´¸āĩâ€Œā´•āĩ‹ā´Ąāĩ ⴍⴝⴙāĩā´™āĩžā´•āĩā´•āĩ ā´ĩāĩ‡ā´Ŗāĩā´Ÿā´ŋ ā´Žā´žā´¤āĩā´°ā´‚ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ.", + "transcoding_advanced_options_description": "ā´Žā´ŋā´•āĩā´• ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´•āĩā´•ā´ŗāĩā´‚ ā´Žā´žā´ąāĩā´ąā´‚ ā´ĩā´°āĩā´¤āĩā´¤āĩ‡ā´Ŗāĩā´Ÿā´¤ā´ŋā´˛āĩā´˛ā´žā´¤āĩā´¤ ā´“ā´Ēāĩā´ˇā´¨āĩā´•āĩž", + "transcoding_audio_codec": "ā´“ā´Ąā´ŋā´¯āĩ‹ ā´•āĩ‹ā´Ąāĩ†ā´•āĩ", + "transcoding_audio_codec_description": "Opus ā´ā´ąāĩā´ąā´ĩāĩā´‚ ⴉⴝāĩŧā´¨āĩā´¨ ā´¨ā´ŋā´˛ā´ĩā´žā´°ā´Žāĩā´ŗāĩā´ŗ ā´“ā´Ēāĩā´ˇā´¨ā´žā´Ŗāĩ, ā´Ēā´•āĩā´ˇāĩ‡ ā´Ēā´´ā´¯ ā´‰ā´Ēā´•ā´°ā´Ŗā´™āĩā´™ā´ŗāĩā´Žā´žā´¯āĩ‹ ā´¸āĩ‹ā´Ģāĩā´ąāĩā´ąāĩâ€Œā´ĩāĩ†ā´¯ā´ąāĩā´Žā´žā´¯āĩ‹ ⴇⴤā´ŋā´¨āĩ ā´•āĩā´ąā´žāĩā´ž ā´…ā´¨āĩā´¯āĩ‹ā´œāĩā´¯ā´¤ā´¯āĩ‡ ⴉⴺāĩā´ŗāĩ‚.", + "transcoding_bitrate_description": "ā´Ēā´°ā´Žā´žā´ĩā´§ā´ŋ ā´Ŧā´ŋā´ąāĩā´ąāĩā´ąāĩ‡ā´ąāĩā´ąā´ŋā´¨āĩ‡ā´•āĩā´•ā´žāĩž ⴉⴝāĩŧā´¨āĩā´¨ā´¤āĩ‹ ā´…ā´‚ā´—āĩ€ā´•āĩƒā´¤ ā´Ģāĩ‹āĩŧā´Žā´žā´ąāĩā´ąā´ŋāĩŊ ā´…ā´˛āĩā´˛ā´žā´¤āĩā´¤ā´¤āĩ‹ ⴆⴝ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•āĩž", + "transcoding_codecs_learn_more": "ā´‡ā´ĩā´ŋⴟāĩ† ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ ā´Ēā´Ļā´™āĩā´™ā´ŗāĩ†ā´•āĩā´•āĩā´ąā´ŋⴚāĩā´šāĩ ā´•āĩ‚ā´Ÿāĩā´¤ā´˛ā´ąā´ŋā´¯ā´žāĩģ, H.264 ā´•āĩ‹ā´Ąāĩ†ā´•āĩ, HEVC ā´•āĩ‹ā´Ąāĩ†ā´•āĩ, VP9 ā´•āĩ‹ā´Ąāĩ†ā´•āĩ ā´Žā´¨āĩā´¨ā´ŋā´ĩā´¯āĩā´Ÿāĩ† FFmpeg ā´Ąāĩ‹ā´•āĩā´¯āĩā´Žāĩ†ā´¨āĩā´ąāĩ‡ā´ˇāĩģ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´ŋā´•āĩā´•āĩā´•.", + "transcoding_constant_quality_mode": "ā´¸āĩā´Ĩā´ŋā´°ā´Žā´žā´¯ ā´—āĩā´Ŗā´Žāĩ‡ā´¨āĩā´Ž ā´Žāĩ‹ā´Ąāĩ", + "transcoding_constant_quality_mode_description": "CQP-ā´¯āĩ†ā´•āĩā´•ā´žāĩž ā´Žā´ŋā´•ā´šāĩā´šā´¤ā´žā´Ŗāĩ ICQ, ā´Žā´¨āĩā´¨ā´žāĩŊ ⴚā´ŋā´˛ ā´šā´žāĩŧā´Ąāĩâ€Œā´ĩāĩ†ā´¯āĩŧ ⴆⴕāĩā´¸ā´ŋā´˛ā´ąāĩ‡ā´ˇāĩģ ā´‰ā´Ēā´•ā´°ā´Ŗā´™āĩā´™āĩž ⴈ ā´Žāĩ‹ā´Ąā´ŋā´¨āĩ† ā´Ēā´ŋā´¨āĩā´¤āĩā´Ŗā´¯āĩā´•āĩā´•āĩā´¨āĩā´¨ā´ŋā´˛āĩā´˛. ā´—āĩā´Ŗā´Žāĩ‡ā´¨āĩā´Ž ā´…ā´Ÿā´ŋā´¸āĩā´Ĩā´žā´¨ā´Žā´žā´•āĩā´•ā´ŋā´¯āĩā´ŗāĩā´ŗ ā´Žāĩģā´•āĩ‹ā´Ąā´ŋā´‚ā´—āĩ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´Žāĩā´Ēāĩ‹āĩž ⴈ ā´“ā´Ēāĩā´ˇāĩģ ⴏⴜāĩā´œāĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤āĩ ā´¨ā´ŋāĩŧā´Ļāĩā´Ļā´ŋā´ˇāĩā´Ÿ ā´Žāĩ‹ā´Ąā´ŋā´¨āĩ ā´Žāĩāĩģā´—ā´Ŗā´¨ ā´¨āĩŊā´•āĩā´‚. ICQ ā´Ēā´ŋā´¨āĩā´¤āĩā´Ŗā´¯āĩā´•āĩā´•ā´žā´¤āĩā´¤ā´¤ā´ŋā´¨ā´žāĩŊ NVENC ⴇⴤāĩ ā´…ā´ĩā´—ā´Ŗā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ.", + "transcoding_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_hardware_acceleration": "ā´šā´žāĩŧā´Ąāĩâ€Œā´ĩāĩ†ā´¯āĩŧ ⴆⴕāĩā´¸ā´ŋā´˛ā´ąāĩ‡ā´ˇāĩģ", + "transcoding_hardware_acceleration_description": "ā´Ēā´°āĩ€ā´•āĩā´ˇā´Ŗā´žā´Ÿā´ŋā´¸āĩā´Ĩā´žā´¨ā´¤āĩā´¤ā´ŋā´˛āĩā´ŗāĩā´ŗā´¤āĩ: ā´ĩāĩ‡ā´—ⴤⴝāĩ‡ā´ąā´ŋā´¯ ⴟāĩā´°ā´žāĩģā´¸āĩâ€Œā´•āĩ‹ā´Ąā´ŋā´‚ā´—āĩ, ā´Žā´¨āĩā´¨ā´žāĩŊ ā´’ā´°āĩ‡ ā´Ŧā´ŋā´ąāĩā´ąāĩā´ąāĩ‡ā´ąāĩā´ąā´ŋāĩŊ ā´—āĩā´Ŗā´Žāĩ‡ā´¨āĩā´Ž ā´•āĩā´ąā´šāĩā´šāĩ‡ā´•āĩā´•ā´žā´‚", + "transcoding_hardware_decoding": "ā´šā´žāĩŧā´Ąāĩâ€Œā´ĩāĩ†ā´¯āĩŧ ā´Ąāĩ€ā´•āĩ‹ā´Ąā´ŋā´‚ā´—āĩ", + "transcoding_hardware_decoding_setting_description": "ā´Žāĩģā´•āĩ‹ā´Ąā´ŋā´‚ā´—āĩ ā´Žā´žā´¤āĩā´°ā´‚ ā´¤āĩā´ĩā´°ā´ŋā´¤ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¤āĩā´¤āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ ā´Ēā´•ā´°ā´‚ ā´Žāĩģā´Ąāĩ-ⴟāĩ-ā´Žāĩģā´Ąāĩ ⴆⴕāĩā´¸ā´ŋā´˛ā´ąāĩ‡ā´ˇāĩģ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´¨āĩā´¨āĩ. ā´Žā´˛āĩā´˛ā´ž ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗā´ŋā´˛āĩā´‚ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋⴚāĩā´šāĩ‡ā´•āĩā´•ā´ŋā´˛āĩā´˛.", + "transcoding_max_b_frames": "ā´Ēā´°ā´Žā´žā´ĩā´§ā´ŋ ā´Ŧā´ŋ-ā´Ģāĩā´°āĩ†ā´¯ā´ŋā´Žāĩā´•āĩž", + "transcoding_max_b_frames_description": "ⴉⴝāĩŧā´¨āĩā´¨ ā´Žāĩ‚ā´˛āĩā´¯ā´™āĩā´™āĩž ā´•ā´‚ā´Ēāĩā´°ā´ˇāĩģ ā´•ā´žā´°āĩā´¯ā´•āĩā´ˇā´Žā´¤ ā´Žāĩ†ā´šāĩā´šā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¤āĩā´¤āĩā´¨āĩā´¨āĩ, ā´Ēā´•āĩā´ˇāĩ‡ ā´Žāĩģā´•āĩ‹ā´Ąā´ŋā´‚ā´—āĩ ā´ĩāĩ‡ā´—ā´¤ ā´•āĩā´ąā´¯āĩā´•āĩā´•āĩā´¨āĩā´¨āĩ. ā´Ēā´´ā´¯ ā´‰ā´Ēā´•ā´°ā´Ŗā´™āĩā´™ā´ŗā´ŋā´˛āĩ† ā´šā´žāĩŧā´Ąāĩâ€Œā´ĩāĩ†ā´¯āĩŧ ⴆⴕāĩā´¸ā´ŋā´˛ā´ąāĩ‡ā´ˇā´¨āĩā´Žā´žā´¯ā´ŋ ā´ĒāĩŠā´°āĩā´¤āĩā´¤ā´Ēāĩā´Ēāĩ†ā´Ÿā´Ŗā´Žāĩ†ā´¨āĩā´¨ā´ŋā´˛āĩā´˛. 0 ā´Ŧā´ŋ-ā´Ģāĩā´°āĩ†ā´¯ā´ŋā´Žāĩā´•āĩž ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•āĩā´¨āĩā´¨āĩ, ā´…ā´¤āĩ‡ā´¸ā´Žā´¯ā´‚ -1 ⴈ ā´Žāĩ‚ā´˛āĩā´¯ā´‚ ā´¯ā´žā´¨āĩā´¤āĩā´°ā´ŋā´•ā´Žā´žā´¯ā´ŋ ⴏⴜāĩā´œāĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ.", + "transcoding_max_bitrate": "ā´Ēā´°ā´Žā´žā´ĩā´§ā´ŋ ā´Ŧā´ŋā´ąāĩā´ąāĩā´ąāĩ‡ā´ąāĩā´ąāĩ", + "transcoding_max_bitrate_description": "ā´’ā´°āĩ ā´Ēā´°ā´Žā´žā´ĩā´§ā´ŋ ā´Ŧā´ŋā´ąāĩā´ąāĩā´ąāĩ‡ā´ąāĩā´ąāĩ ⴏⴜāĩā´œāĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤āĩ ā´—āĩā´Ŗā´Žāĩ‡ā´¨āĩā´Žā´¯ā´ŋāĩŊ ⴚāĩ†ā´ąā´ŋā´¯āĩŠā´°āĩ ā´ĩā´ŋⴟāĩā´Ÿāĩā´ĩāĩ€ā´´āĩā´šā´¯āĩ‹ā´Ÿāĩ† ā´Ģā´¯āĩŊ ā´ĩā´˛āĩā´Ēāĩā´Ēā´™āĩā´™āĩž ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ ā´Ēāĩā´°ā´ĩā´šā´¨ā´žā´¤āĩ€ā´¤ā´Žā´žā´•āĩā´•āĩā´‚. 720p-āĩŊ, ā´¸ā´žā´§ā´žā´°ā´Ŗ ā´Žāĩ‚ā´˛āĩā´¯ā´™āĩā´™āĩž VP9 ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ HEVC-ā´•āĩā´•āĩ 2600 kbit/s, ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ H.264-ā´¨āĩ 4500 kbit/s ⴆ⴪āĩ. 0 ⴆⴝā´ŋ ⴏⴜāĩā´œāĩ€ā´•ā´°ā´ŋⴚāĩā´šā´žāĩŊ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´‚.", + "transcoding_max_keyframe_interval": "ā´Ēā´°ā´Žā´žā´ĩā´§ā´ŋ ā´•āĩ€ā´Ģāĩā´°āĩ†ā´¯ā´ŋā´‚ ā´‡ā´Ÿā´ĩāĩ‡ā´ŗ", + "transcoding_max_keyframe_interval_description": "ā´•āĩ€ā´Ģāĩā´°āĩ†ā´¯ā´ŋā´Žāĩā´•āĩžā´•āĩā´•ā´ŋⴟⴝā´ŋā´˛āĩā´ŗāĩā´ŗ ā´Ēā´°ā´Žā´žā´ĩā´§ā´ŋ ā´Ģāĩā´°āĩ†ā´¯ā´ŋā´‚ ā´Ļāĩ‚ā´°ā´‚ ⴏⴜāĩā´œā´Žā´žā´•āĩā´•āĩā´¨āĩā´¨āĩ. ā´•āĩā´ąā´žāĩā´ž ā´Žāĩ‚ā´˛āĩā´¯ā´™āĩā´™āĩž ā´•ā´‚ā´Ēāĩā´°ā´ˇāĩģ ā´•ā´žā´°āĩā´¯ā´•āĩā´ˇā´Žā´¤ ā´•āĩā´ąā´¯āĩā´•āĩā´•āĩā´¨āĩā´¨āĩ, ā´Ēā´•āĩā´ˇāĩ‡ ā´¸āĩ€ā´•āĩā´•āĩ ā´¸ā´Žā´¯ā´‚ ā´Žāĩ†ā´šāĩā´šā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¤āĩā´¤āĩā´•ā´¯āĩā´‚ ā´ĩāĩ‡ā´—ⴤⴝāĩ‡ā´ąā´ŋā´¯ ā´šā´˛ā´¨ā´Žāĩā´ŗāĩā´ŗ ā´°ā´‚ā´—ā´™āĩā´™ā´ŗā´ŋāĩŊ ā´—āĩā´Ŗā´Žāĩ‡ā´¨āĩā´Ž ā´Žāĩ†ā´šāĩā´šā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¤āĩā´¤āĩā´•ā´¯āĩā´‚ ⴚāĩ†ā´¯āĩā´¤āĩ‡ā´•āĩā´•ā´žā´‚. 0 ⴈ ā´Žāĩ‚ā´˛āĩā´¯ā´‚ ā´¯ā´žā´¨āĩā´¤āĩā´°ā´ŋā´•ā´Žā´žā´¯ā´ŋ ⴏⴜāĩā´œāĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ.", + "transcoding_optimal_description": "ⴞⴕāĩā´ˇāĩā´¯ā´Žā´ŋⴟāĩā´Ÿ ā´ąāĩ†ā´¸ā´˛āĩā´¯āĩ‚ⴎⴍāĩ‡ā´•āĩā´•ā´žāĩž ⴉⴝāĩŧā´¨āĩā´¨ā´¤āĩ‹ ā´…ā´‚ā´—āĩ€ā´•āĩƒā´¤ ā´Ģāĩ‹āĩŧā´Žā´žā´ąāĩā´ąā´ŋāĩŊ ā´…ā´˛āĩā´˛ā´žā´¤āĩā´¤ā´¤āĩ‹ ⴆⴝ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•āĩž", + "transcoding_policy": "ⴟāĩā´°ā´žāĩģā´¸āĩâ€Œā´•āĩ‹ā´Ąāĩ ⴍⴝⴂ", + "transcoding_policy_description": "ā´’ā´°āĩ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ ā´Žā´Ēāĩā´Ēāĩ‹āĩž ⴟāĩā´°ā´žāĩģā´¸āĩâ€Œā´•āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ⴏⴜāĩā´œā´Žā´žā´•āĩā´•āĩā´•", + "transcoding_preferred_hardware_device": "ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´¨āĩā´¨ ā´šā´žāĩŧā´Ąāĩâ€Œā´ĩāĩ†ā´¯āĩŧ ā´‰ā´Ēā´•ā´°ā´Ŗā´‚", + "transcoding_preferred_hardware_device_description": "VAAPI, QSV ā´Žā´¨āĩā´¨ā´ŋā´ĩā´¯āĩā´•āĩā´•āĩ ā´Žā´žā´¤āĩā´°ā´‚ ā´Ŧā´žā´§ā´•ā´‚. ā´šā´žāĩŧā´Ąāĩâ€Œā´ĩāĩ†ā´¯āĩŧ ⴟāĩā´°ā´žāĩģā´¸āĩâ€Œā´•āĩ‹ā´Ąā´ŋā´‚ā´—ā´ŋā´¨ā´žā´¯ā´ŋ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ dri ā´¨āĩ‹ā´Ąāĩ ⴏⴜāĩā´œā´Žā´žā´•āĩā´•āĩā´¨āĩā´¨āĩ.", + "transcoding_preset_preset": "ā´Ēāĩā´°āĩ€ā´¸āĩ†ā´ąāĩā´ąāĩ (-preset)", + "transcoding_preset_preset_description": "ā´•ā´‚ā´Ēāĩā´°ā´ˇāĩģ ā´ĩāĩ‡ā´—ā´¤. ā´ĩāĩ‡ā´—ā´¤ ā´•āĩā´ąā´žāĩā´ž ā´Ēāĩā´°āĩ€ā´¸āĩ†ā´ąāĩā´ąāĩā´•āĩž ⴚāĩ†ā´ąā´ŋā´¯ ā´Ģⴝⴞāĩā´•āĩž ā´¨ā´ŋāĩŧā´Žāĩā´Žā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ, ā´’ā´°āĩ ā´¨ā´ŋā´ļāĩā´šā´ŋā´¤ ā´Ŧā´ŋā´ąāĩā´ąāĩā´ąāĩ‡ā´ąāĩā´ąāĩ ⴞⴕāĩā´ˇāĩā´¯ā´Žā´ŋⴟāĩā´Žāĩā´Ēāĩ‹āĩž ā´—āĩā´Ŗā´Žāĩ‡ā´¨āĩā´Ž ā´ĩāĩŧā´Ļāĩā´§ā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ. 'faster'-ā´¨āĩ‡ā´•āĩā´•ā´žāĩž ⴉⴝāĩŧā´¨āĩā´¨ ā´ĩāĩ‡ā´—ā´¤ VP9 ā´…ā´ĩā´—ā´Ŗā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ.", + "transcoding_reference_frames": "ā´ąā´Ģā´ąāĩģā´¸āĩ ā´Ģāĩā´°āĩ†ā´¯ā´ŋā´Žāĩā´•āĩž", + "transcoding_reference_frames_description": "ā´¨āĩŊā´•ā´ŋā´¯ā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ ā´’ā´°āĩ ā´Ģāĩā´°āĩ†ā´¯ā´ŋā´‚ ā´•ā´‚ā´Ēāĩā´°ā´¸āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´Žāĩā´Ēāĩ‹āĩž ā´ąā´Ģā´ąāĩģā´¸āĩ ⴚāĩ†ā´¯āĩā´¯āĩ‡ā´Ŗāĩā´Ÿ ā´Ģāĩā´°āĩ†ā´¯ā´ŋā´Žāĩā´•ā´ŗāĩā´Ÿāĩ† ā´Žā´Ŗāĩā´Ŗā´‚. ⴉⴝāĩŧā´¨āĩā´¨ ā´Žāĩ‚ā´˛āĩā´¯ā´™āĩā´™āĩž ā´•ā´‚ā´Ēāĩā´°ā´ˇāĩģ ā´•ā´žā´°āĩā´¯ā´•āĩā´ˇā´Žā´¤ ā´Žāĩ†ā´šāĩā´šā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¤āĩā´¤āĩā´¨āĩā´¨āĩ, ā´Ēā´•āĩā´ˇāĩ‡ ā´Žāĩģā´•āĩ‹ā´Ąā´ŋā´‚ā´—āĩ ā´ĩāĩ‡ā´—ā´¤ ā´•āĩā´ąā´¯āĩā´•āĩā´•āĩā´¨āĩā´¨āĩ. 0 ⴈ ā´Žāĩ‚ā´˛āĩā´¯ā´‚ ā´¯ā´žā´¨āĩā´¤āĩā´°ā´ŋā´•ā´Žā´žā´¯ā´ŋ ⴏⴜāĩā´œāĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ.", + "transcoding_required_description": "ā´…ā´‚ā´—āĩ€ā´•āĩƒā´¤ ā´Ģāĩ‹āĩŧā´Žā´žā´ąāĩā´ąā´ŋāĩŊ ā´…ā´˛āĩā´˛ā´žā´¤āĩā´¤ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•āĩž ā´Žā´žā´¤āĩā´°ā´‚", + "transcoding_settings": "ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ ⴟāĩā´°ā´žāĩģā´¸āĩā´•āĩ‹ā´Ąā´ŋā´‚ā´—āĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "transcoding_settings_description": "ā´ā´¤āĩŠā´•āĩā´•āĩ† ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗā´žā´Ŗāĩ ⴟāĩā´°ā´žāĩģā´¸āĩâ€Œā´•āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩ‡ā´Ŗāĩā´Ÿā´¤āĩ†ā´¨āĩā´¨āĩā´‚ ā´…ā´ĩ ā´Žā´™āĩā´™ā´¨āĩ† ā´Ēāĩā´°āĩ‹ā´¸ā´¸āĩā´¸āĩ ⴚāĩ†ā´¯āĩā´¯ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩā´‚ ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "transcoding_target_resolution": "ⴞⴕāĩā´ˇāĩā´¯ā´Žā´ŋⴟāĩā´¨āĩā´¨ ā´ąāĩ†ā´¸ā´˛āĩā´¯āĩ‚ā´ˇāĩģ", + "transcoding_target_resolution_description": "ⴉⴝāĩŧā´¨āĩā´¨ ā´ąāĩ†ā´¸ā´˛āĩā´¯āĩ‚ⴎⴍāĩā´•āĩžā´•āĩā´•āĩ ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ ā´ĩā´ŋā´ļā´Ļā´žā´‚ā´ļā´™āĩā´™āĩž ⴏⴂⴰⴕāĩā´ˇā´ŋā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯āĩā´‚, ā´Ēā´•āĩā´ˇāĩ‡ ā´Žāĩģā´•āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ ā´¸ā´Žā´¯ā´Žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´‚, ā´ĩā´˛ā´ŋā´¯ ā´Ģā´¯āĩŊ ā´ĩā´˛āĩā´Ēāĩā´Ēā´Žāĩā´Ŗāĩā´Ÿā´žā´•āĩā´‚, ā´•āĩ‚ā´Ÿā´žā´¤āĩ† ā´†ā´Ēāĩā´Ēā´ŋā´¨āĩā´ąāĩ† ā´Ēāĩā´°ā´¤ā´ŋā´•ā´°ā´Ŗā´ļāĩ‡ā´ˇā´ŋ ā´•āĩā´ąā´¯āĩā´•āĩā´•āĩā´•ā´¯āĩā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´‚.", + "transcoding_temporal_aq": "ⴟāĩ†ā´Žāĩā´Ēā´ąāĩŊ AQ", + "transcoding_temporal_aq_description": "NVENC-ā´•āĩā´•āĩ ā´Žā´žā´¤āĩā´°ā´‚ ā´Ŧā´žā´§ā´•ā´‚. ⴉⴝāĩŧā´¨āĩā´¨ ā´ĩā´ŋā´ļā´Ļā´žā´‚ā´ļā´™āĩā´™ā´ŗāĩā´‚ ā´•āĩā´ąā´žāĩā´ž ⴚⴞⴍā´ĩāĩā´Žāĩā´ŗāĩā´ŗ ā´°ā´‚ā´—ā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´—āĩā´Ŗā´Žāĩ‡ā´¨āĩā´Ž ā´ĩāĩŧā´Ļāĩā´§ā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ. ā´Ēā´´ā´¯ ā´‰ā´Ēā´•ā´°ā´Ŗā´™āĩā´™ā´ŗāĩā´Žā´žā´¯ā´ŋ ā´ĒāĩŠā´°āĩā´¤āĩā´¤ā´Ēāĩā´Ēāĩ†ā´Ÿā´Ŗā´Žāĩ†ā´¨āĩā´¨ā´ŋā´˛āĩā´˛.", + "transcoding_threads": "ā´¤āĩā´°āĩ†ā´Ąāĩā´•āĩž", + "transcoding_threads_description": "ⴉⴝāĩŧā´¨āĩā´¨ ā´Žāĩ‚ā´˛āĩā´¯ā´™āĩā´™āĩž ā´ĩāĩ‡ā´—ⴤⴝāĩ‡ā´ąā´ŋā´¯ ā´Žāĩģā´•āĩ‹ā´Ąā´ŋā´‚ā´—ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ⴍⴝā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ, ā´Ēā´•āĩā´ˇāĩ‡ ā´¸āĩ†āĩŧā´ĩā´ąā´ŋā´¨āĩ ā´Žā´ąāĩā´ąāĩ ⴜāĩ‹ā´˛ā´ŋā´•āĩž ā´Ēāĩā´°āĩ‹ā´¸ā´¸āĩā´¸āĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•āĩā´ąā´šāĩā´šāĩ ā´‡ā´Ÿā´‚ ā´¨āĩŊā´•āĩā´¨āĩā´¨āĩ. ⴈ ā´Žāĩ‚ā´˛āĩā´¯ā´‚ ā´¸ā´ŋā´Ēā´ŋā´¯āĩ ā´•āĩ‹ā´ąāĩā´•ā´ŗāĩā´Ÿāĩ† ā´Žā´Ŗāĩā´Ŗā´¤āĩā´¤āĩ‡ā´•āĩā´•ā´žāĩž ā´•āĩ‚ā´Ÿāĩā´¤ā´˛ā´žā´•ā´°āĩā´¤āĩ. 0 ⴆⴝā´ŋ ⴏⴜāĩā´œāĩ€ā´•ā´°ā´ŋⴚāĩā´šā´žāĩŊ ā´‰ā´Ēā´¯āĩ‹ā´—ā´‚ ā´Ēā´°ā´Žā´žā´ĩā´§ā´ŋā´¯ā´žā´•āĩā´•āĩā´¨āĩā´¨āĩ.", + "transcoding_tone_mapping": "ⴟāĩ‹āĩē-ā´Žā´žā´Ēāĩā´Ēā´ŋā´‚ā´—āĩ", + "transcoding_tone_mapping_description": "HDR ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•āĩž SDR-ā´˛āĩ‡ā´•āĩā´•āĩ ā´Ēā´°ā´ŋā´ĩāĩŧā´¤āĩā´¤ā´¨ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´Žāĩā´Ēāĩ‹āĩž ā´…ā´ĩā´¯āĩā´Ÿāĩ† ā´°āĩ‚ā´Ēā´‚ ā´¨ā´ŋⴞⴍā´ŋāĩŧā´¤āĩā´¤ā´žāĩģ ā´ļāĩā´°ā´Žā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ. ā´“ā´°āĩ‹ ā´…āĩŊā´—āĩ‹ā´°ā´ŋā´¤ā´ĩāĩā´‚ ā´¨ā´ŋā´ąā´‚, ā´ĩā´ŋā´ļā´Ļā´žā´‚ā´ļā´™āĩā´™āĩž, ā´¤āĩ†ā´ŗā´ŋⴚāĩā´šā´‚ ā´Žā´¨āĩā´¨ā´ŋā´ĩā´¯āĩā´•āĩā´•ā´žā´¯ā´ŋ ā´ĩāĩā´¯ā´¤āĩā´¯ā´¸āĩā´¤ ā´ĩā´ŋⴟāĩā´Ÿāĩā´ĩāĩ€ā´´āĩā´šā´•āĩž ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ. Hable ā´ĩā´ŋā´ļā´Ļā´žā´‚ā´ļā´™āĩā´™āĩž ⴏⴂⴰⴕāĩā´ˇā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ, Mobius ā´¨ā´ŋā´ąā´‚ ⴏⴂⴰⴕāĩā´ˇā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ, Reinhard ā´¤āĩ†ā´ŗā´ŋⴚāĩā´šā´‚ ⴏⴂⴰⴕāĩā´ˇā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ.", + "transcoding_transcode_policy": "ⴟāĩā´°ā´žāĩģā´¸āĩâ€Œā´•āĩ‹ā´Ąāĩ ⴍⴝⴂ", + "transcoding_transcode_policy_description": "ā´’ā´°āĩ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ ā´Žā´Ēāĩā´Ēāĩ‹āĩž ⴟāĩā´°ā´žāĩģā´¸āĩâ€Œā´•āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´Ŗā´‚ ā´Žā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ†ā´•āĩā´•āĩā´ąā´ŋⴚāĩā´šāĩā´ŗāĩā´ŗ ⴍⴝⴂ. HDR ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•āĩž ā´Žā´˛āĩā´˛ā´žā´¯āĩā´Ēāĩā´Ēāĩ‹ā´´āĩā´‚ ⴟāĩā´°ā´žāĩģā´¸āĩâ€Œā´•āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´‚ (ⴟāĩā´°ā´žāĩģā´¸āĩâ€Œā´•āĩ‹ā´Ąā´ŋā´‚ā´—āĩ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•ā´ŋā´¯ā´ŋⴟāĩā´Ÿā´ŋā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ).", + "transcoding_two_pass_encoding": "ⴟāĩ-ā´Ēā´žā´¸āĩ ā´Žāĩģā´•āĩ‹ā´Ąā´ŋā´‚ā´—āĩ", + "transcoding_two_pass_encoding_setting_description": "ā´Žāĩ†ā´šāĩā´šā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿ ā´Žāĩģā´•āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¤ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•āĩž ā´¨ā´ŋāĩŧā´Žāĩā´Žā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ ā´°ā´Ŗāĩā´Ÿāĩ ā´Ēā´žā´¸āĩā´•ā´ŗā´ŋā´˛ā´žā´¯ā´ŋ ⴟāĩā´°ā´žāĩģā´¸āĩâ€Œā´•āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•. ā´Ēā´°ā´Žā´žā´ĩā´§ā´ŋ ā´Ŧā´ŋā´ąāĩā´ąāĩā´ąāĩ‡ā´ąāĩā´ąāĩ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´Žāĩā´Ēāĩ‹āĩž (H.264, HEVC ā´Žā´¨āĩā´¨ā´ŋā´ĩā´¯āĩâ€Œā´•āĩā´•āĩŠā´Ēāĩā´Ēā´‚ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋā´•āĩā´•ā´žāĩģ ⴇⴤāĩ ā´†ā´ĩā´ļāĩā´¯ā´Žā´žā´Ŗāĩ), ⴈ ā´Žāĩ‹ā´Ąāĩ ā´Ēā´°ā´Žā´žā´ĩā´§ā´ŋ ā´Ŧā´ŋā´ąāĩā´ąāĩā´ąāĩ‡ā´ąāĩā´ąā´ŋā´¨āĩ† ā´…ā´Ÿā´ŋā´¸āĩā´Ĩā´žā´¨ā´Žā´žā´•āĩā´•ā´ŋ ā´’ā´°āĩ ā´Ŧā´ŋā´ąāĩā´ąāĩā´ąāĩ‡ā´ąāĩā´ąāĩ ā´ļāĩā´°āĩ‡ā´Ŗā´ŋ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•ā´¯āĩā´‚ CRF ā´…ā´ĩā´—ā´Ŗā´ŋā´•āĩā´•āĩā´•ā´¯āĩā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ. VP9-ā´¨ā´žā´¯ā´ŋ, ā´Ēā´°ā´Žā´žā´ĩā´§ā´ŋ ā´Ŧā´ŋā´ąāĩā´ąāĩā´ąāĩ‡ā´ąāĩā´ąāĩ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•ā´ŋā´¯ā´ŋⴟāĩā´Ÿāĩā´Ŗāĩā´Ÿāĩ†ā´™āĩā´•ā´ŋāĩŊ CRF ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•ā´žā´‚.", + "transcoding_video_codec": "ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ ā´•āĩ‹ā´Ąāĩ†ā´•āĩ", + "transcoding_video_codec_description": "VP9-ā´¨āĩ ⴉⴝāĩŧā´¨āĩā´¨ ā´•ā´žā´°āĩā´¯ā´•āĩā´ˇā´Žā´¤ā´¯āĩā´‚ ā´ĩāĩ†ā´Ŧāĩ ā´…ā´¨āĩā´¯āĩ‹ā´œāĩā´¯ā´¤ā´¯āĩā´Žāĩā´Ŗāĩā´Ÿāĩ, ā´Ēā´•āĩā´ˇāĩ‡ ⴟāĩā´°ā´žāĩģā´¸āĩâ€Œā´•āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ ā´¸ā´Žā´¯ā´Žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´‚. HEVC ā´¸ā´Žā´žā´¨ā´Žā´žā´¯ā´ŋ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ, ā´Ēā´•āĩā´ˇāĩ‡ ā´ĩāĩ†ā´Ŧāĩ ā´…ā´¨āĩā´¯āĩ‹ā´œāĩā´¯ā´¤ ā´•āĩā´ąā´ĩā´žā´Ŗāĩ. H.264 ā´ĩāĩā´¯ā´žā´Ēā´•ā´Žā´žā´¯ā´ŋ ā´…ā´¨āĩā´¯āĩ‹ā´œāĩā´¯ā´ĩāĩā´‚ ā´ĩāĩ‡ā´—ā´¤āĩā´¤ā´ŋāĩŊ ⴟāĩā´°ā´žāĩģā´¸āĩâ€Œā´•āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯āĩā´¨āĩā´¨ā´¤āĩā´Žā´žā´Ŗāĩ, ā´Ēā´•āĩā´ˇāĩ‡ ā´ĩā´ŗā´°āĩ† ā´ĩā´˛ā´ŋā´¯ ā´Ģⴝⴞāĩā´•āĩž ā´¨ā´ŋāĩŧā´Žāĩā´Žā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ. AV1 ā´ā´ąāĩā´ąā´ĩāĩā´‚ ā´•ā´žā´°āĩā´¯ā´•āĩā´ˇā´Žā´Žā´žā´¯ ā´•āĩ‹ā´Ąāĩ†ā´•āĩā´•ā´žā´Ŗāĩ, ā´Ēā´•āĩā´ˇāĩ‡ ā´Ēā´´ā´¯ ā´‰ā´Ēā´•ā´°ā´Ŗā´™āĩā´™ā´ŗā´ŋāĩŊ ⴇⴤā´ŋā´¨āĩ ā´Ēā´ŋā´¨āĩā´¤āĩā´Ŗā´¯ā´ŋā´˛āĩā´˛.", + "trash_enabled_description": "ⴟāĩā´°ā´žā´ˇāĩ ā´Ģāĩ€ā´šāĩā´šā´ąāĩā´•āĩž ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´•", + "trash_number_of_days": "ā´Ļā´ŋā´ĩⴏⴙāĩā´™ā´ŗāĩā´Ÿāĩ† ā´Žā´Ŗāĩā´Ŗā´‚", + "trash_number_of_days_description": "ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´ļā´žā´ļāĩā´ĩā´¤ā´Žā´žā´¯ā´ŋ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩā´Žāĩā´Žāĩā´Ēāĩ ⴟāĩā´°ā´žā´ˇā´ŋāĩŊ ā´¸āĩ‚ā´•āĩā´ˇā´ŋā´•āĩā´•āĩ‡ā´Ŗāĩā´Ÿ ā´Ļā´ŋā´ĩⴏⴙāĩā´™ā´ŗāĩā´Ÿāĩ† ā´Žā´Ŗāĩā´Ŗā´‚", + "trash_settings": "ⴟāĩā´°ā´žā´ˇāĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "trash_settings_description": "ⴟāĩā´°ā´žā´ˇāĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "unlink_all_oauth_accounts": "ā´Žā´˛āĩā´˛ā´ž OAuth ā´…ā´•āĩā´•āĩ—ā´Ŗāĩā´Ÿāĩā´•ā´ŗāĩā´‚ ā´…āĩēā´˛ā´ŋā´™āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "unlink_all_oauth_accounts_description": "ā´’ā´°āĩ ā´Ēāĩā´¤ā´ŋā´¯ ā´Ļā´žā´¤ā´žā´ĩā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Žā´žā´ąāĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ ā´Žāĩā´Žāĩā´Ēāĩ ā´Žā´˛āĩā´˛ā´ž OAuth ā´…ā´•āĩā´•āĩ—ā´Ŗāĩā´Ÿāĩā´•ā´ŗāĩā´‚ ā´…āĩēā´˛ā´ŋā´™āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´“āĩŧā´Žāĩā´Žā´ŋā´•āĩā´•āĩā´•.", + "unlink_all_oauth_accounts_prompt": "ā´Žā´˛āĩā´˛ā´ž OAuth ā´…ā´•āĩā´•āĩ—ā´Ŗāĩā´Ÿāĩā´•ā´ŗāĩā´‚ ā´…āĩēā´˛ā´ŋā´™āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹? ⴇⴤāĩ ā´“ā´°āĩ‹ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩā´ąāĩ†ā´¯āĩā´‚ OAuth ā´ā´Ąā´ŋ ā´ąāĩ€ā´¸āĩ†ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´‚, ⴇⴤāĩ ā´Ēā´´ā´¯ā´Ēⴟā´ŋā´¯ā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛.", + "user_cleanup_job": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤āĩƒ ā´•āĩā´˛āĩ€ā´¨ā´Ēāĩā´Ēāĩ", + "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_details": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤āĩƒ ā´ĩā´ŋā´ļā´Ļā´žā´‚ā´ļā´™āĩā´™āĩž", + "user_management": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤āĩƒ ā´Žā´žā´¨āĩ‡ā´œāĩā´Žāĩ†ā´¨āĩā´ąāĩ", + "user_password_has_been_reset": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩā´ąāĩ† ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´ąāĩ€ā´¸āĩ†ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¤āĩ:", + "user_password_reset_description": "ā´Ļā´¯ā´ĩā´žā´¯ā´ŋ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ ā´¤ā´žāĩŊā´•āĩā´•ā´žā´˛ā´ŋā´• ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´¨āĩŊā´•āĩā´•, ā´…ā´Ÿāĩā´¤āĩā´¤ ā´˛āĩ‹ā´—ā´ŋāĩģ ⴚāĩ†ā´¯āĩā´¯āĩā´Žāĩā´Ēāĩ‹āĩž ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´Žā´žā´ąāĩā´ąāĩ‡ā´Ŗāĩā´Ÿā´ŋā´ĩā´°āĩā´Žāĩ†ā´¨āĩā´¨āĩ ā´…ā´ĩā´°āĩ† ā´…ā´ąā´ŋā´¯ā´ŋā´•āĩā´•āĩā´•.", + "user_restore_description": "{user}-ā´¨āĩā´ąāĩ† ā´…ā´•āĩā´•āĩ—ā´Ŗāĩā´Ÿāĩ ā´Ēāĩā´¨ā´ƒā´¸āĩā´Ĩā´žā´Ēā´ŋā´•āĩā´•āĩā´‚.", + "user_restore_scheduled_removal": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ† ā´Ēāĩā´¨ā´ƒā´¸āĩā´Ĩā´žā´Ēā´ŋā´•āĩā´•āĩā´• - {date, date, long}-ā´¨āĩ ā´¨āĩ€ā´•āĩā´•ā´‚ā´šāĩ†ā´¯āĩā´¯ā´žāĩģ ā´ˇāĩ†ā´Ąāĩā´¯āĩ‚āĩž ⴚāĩ†ā´¯āĩâ€Œā´¤ā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "user_settings": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩā´ąāĩ† ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "user_settings_description": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤āĩƒ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "user_successfully_removed": "{email} ā´Žā´¨āĩā´¨ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ† ā´ĩā´ŋā´œā´¯ā´•ā´°ā´Žā´žā´¯ā´ŋ ā´¨āĩ€ā´•āĩā´•ā´‚ā´šāĩ†ā´¯āĩā´¤āĩ.", + "version_check_enabled_description": "ā´Ēā´¤ā´ŋā´Ēāĩā´Ēāĩ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´¨ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´•", + "version_check_implications": "ā´Ēā´¤ā´ŋā´Ēāĩā´Ēāĩ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´¨ ā´Ģāĩ€ā´šāĩā´šāĩŧ github.com-ā´Žā´žā´¯ā´ŋ ⴆⴍāĩā´•ā´žā´˛ā´ŋā´• ā´†ā´ļā´¯ā´ĩā´ŋā´¨ā´ŋā´Žā´¯ā´¤āĩā´¤āĩ† ā´†ā´ļāĩā´°ā´¯ā´ŋⴚāĩā´šā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "version_check_settings": "ā´Ēā´¤ā´ŋā´Ēāĩā´Ēāĩ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´¨", + "version_check_settings_description": "ā´Ēāĩā´¤ā´ŋā´¯ ā´Ēā´¤ā´ŋā´Ēāĩā´Ēā´ŋā´¨āĩā´ąāĩ† ā´…ā´ąā´ŋā´¯ā´ŋā´Ēāĩā´Ēāĩ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´•/ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•āĩā´•", + "video_conversion_job": "ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•āĩž ⴟāĩā´°ā´žāĩģā´¸āĩâ€Œā´•āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "video_conversion_job_description": "ā´Ŧāĩā´°āĩ—ā´¸ā´ąāĩā´•ā´ŗāĩā´Žā´žā´¯āĩā´‚ ā´‰ā´Ēā´•ā´°ā´Ŗā´™āĩā´™ā´ŗāĩā´Žā´žā´¯āĩā´‚ ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ ā´…ā´¨āĩā´¯āĩ‹ā´œāĩā´¯ā´¤ā´¯āĩā´•āĩā´•ā´žā´¯ā´ŋ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•āĩž ⴟāĩā´°ā´žāĩģā´¸āĩâ€Œā´•āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•" }, + "admin_email": "ā´…ā´Ąāĩā´Žā´ŋāĩģ ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ", + "admin_password": "ā´…ā´Ąāĩā´Žā´ŋāĩģ ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ", + "administration": "ā´…ā´Ąāĩā´Žā´ŋā´¨ā´ŋā´¸āĩā´Ÿāĩā´°āĩ‡ā´ˇāĩģ", + "advanced": "ā´ĩā´ŋā´Ēāĩā´˛ā´Žā´žā´¯ā´¤āĩ", + "advanced_settings_enable_alternate_media_filter_subtitle": "ⴇⴤⴰ ā´Žā´žā´¨ā´Ļā´Ŗāĩā´Ąā´™āĩā´™ā´ŗāĩ† ā´…ā´Ÿā´ŋā´¸āĩā´Ĩā´žā´¨ā´Žā´žā´•āĩā´•ā´ŋ ā´¸ā´ŋā´™āĩā´•āĩ ā´¸ā´Žā´¯ā´¤āĩā´¤āĩ ā´Žāĩ€ā´Ąā´ŋā´¯ ā´Ģā´ŋāĩŊⴟāĩā´Ÿāĩŧ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ⴈ ā´“ā´Ēāĩā´ˇāĩģ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•. ā´Žā´˛āĩā´˛ā´ž ā´†āĩŊā´Ŧā´™āĩā´™ā´ŗāĩā´‚ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´†ā´Ēāĩā´Ēā´ŋā´¨āĩ ā´Ēāĩā´°ā´ļāĩā´¨ā´™āĩā´™ā´ŗāĩā´Ŗāĩā´Ÿāĩ†ā´™āĩā´•ā´ŋāĩŊ ā´Žā´žā´¤āĩā´°ā´‚ ⴇⴤāĩ ā´Ēā´°āĩ€ā´•āĩā´ˇā´ŋā´•āĩā´•āĩā´•.", + "advanced_settings_enable_alternate_media_filter_title": "[ā´Ēā´°āĩ€ā´•āĩā´ˇā´Ŗā´žā´Ÿā´ŋā´¸āĩā´Ĩā´žā´¨ā´¤āĩā´¤ā´ŋāĩŊ] ⴇⴤⴰ ā´‰ā´Ēā´•ā´°ā´Ŗ ā´†āĩŊā´Ŧā´‚ ā´¸ā´ŋā´™āĩā´•āĩ ā´Ģā´ŋāĩŊⴟāĩā´Ÿāĩŧ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•", + "advanced_settings_log_level_title": "ā´˛āĩ‹ā´—āĩ ā´˛āĩ†ā´ĩāĩŊ: {level}", + "advanced_settings_prefer_remote_subtitle": "ⴚā´ŋā´˛ ā´‰ā´Ēā´•ā´°ā´Ŗā´™āĩā´™ā´ŗā´ŋāĩŊ ā´Ēāĩā´°ā´žā´Ļāĩ‡ā´ļā´ŋā´• ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋā´˛āĩā´•āĩž ā´˛āĩ‹ā´Ąāĩā´šāĩ†ā´¯āĩā´¯ā´žāĩģ ā´ĩā´ŗā´°āĩ† ā´ĩāĩ‡ā´—ā´¤ ā´•āĩā´ąā´ĩā´žā´Ŗāĩ. ā´Ēā´•ā´°ā´‚ ā´ąā´ŋā´Žāĩ‹ā´Ÿāĩā´Ÿāĩ ⴚā´ŋā´¤āĩā´°ā´™āĩā´™āĩž ā´˛āĩ‹ā´Ąāĩā´šāĩ†ā´¯āĩā´¯ā´žāĩģ ⴈ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´‚ ⴏⴜāĩ€ā´ĩā´Žā´žā´•āĩā´•āĩā´•.", + "advanced_settings_prefer_remote_title": "ā´ąā´ŋā´Žāĩ‹ā´Ÿāĩā´Ÿāĩ ⴚā´ŋā´¤āĩā´°ā´™āĩā´™āĩžā´•āĩā´•āĩ ā´Žāĩāĩģā´—ā´Ŗā´¨ ā´¨āĩŊā´•āĩā´•", + "advanced_settings_proxy_headers_subtitle": "ā´“ā´°āĩ‹ ā´¨āĩ†ā´ąāĩā´ąāĩâ€Œā´ĩāĩŧā´•āĩā´•āĩ ā´…ā´­āĩā´¯āĩŧā´¤āĩā´Ĩⴍⴝāĩâ€Œā´•āĩā´•āĩŠā´Ēāĩā´Ēā´ĩāĩā´‚ Immich ⴅⴝⴝāĩâ€Œā´•āĩā´•āĩ‡ā´Ŗāĩā´Ÿ ā´Ēāĩā´°āĩ‹ā´•āĩā´¸ā´ŋ ā´šāĩ†ā´Ąā´ąāĩā´•āĩž ā´¨ā´ŋāĩŧā´ĩⴚā´ŋā´•āĩā´•āĩā´•", + "advanced_settings_proxy_headers_title": "ā´Ēāĩā´°āĩ‹ā´•āĩā´¸ā´ŋ ā´šāĩ†ā´Ąā´ąāĩā´•āĩž", + "advanced_settings_readonly_mode_subtitle": "ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž ā´Žā´žā´¤āĩā´°ā´‚ ā´•ā´žā´Ŗā´žāĩģ ā´•ā´´ā´ŋā´¯āĩā´¨āĩā´¨ ā´ąāĩ€ā´Ąāĩ-ā´“āĩēā´˛ā´ŋ ā´Žāĩ‹ā´Ąāĩ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´¨āĩā´¨āĩ. ā´’ā´¨āĩā´¨ā´ŋⴞⴧā´ŋā´•ā´‚ ⴚā´ŋā´¤āĩā´°ā´™āĩā´™āĩž ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩŊ, ā´Ēā´™āĩā´•ā´ŋⴟāĩŊ, ā´•ā´žā´¸āĩā´ąāĩā´ąā´ŋā´‚ā´—āĩ, ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩŊ ā´Žā´¨āĩā´¨ā´ŋā´ĩā´¯āĩ†ā´˛āĩā´˛ā´žā´‚ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´‚. ā´Ēāĩā´°ā´§ā´žā´¨ ā´¸āĩā´•āĩā´°āĩ€ā´¨ā´ŋā´˛āĩ† ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤āĩƒ ā´…ā´ĩā´¤ā´žāĩŧ ā´ĩā´´ā´ŋ ā´ąāĩ€ā´Ąāĩ-ā´“āĩēā´˛ā´ŋ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´•/ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•āĩā´•.", + "advanced_settings_readonly_mode_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": "ⴟāĩā´°ā´Ŧā´ŋāĩžā´ˇāĩ‚ā´Ÿāĩā´Ÿā´ŋā´‚ā´—āĩ", + "age_months": "ā´Ēāĩā´°ā´žā´¯ā´‚ {months, plural, one {# ā´Žā´žā´¸ā´‚} other {# ā´Žā´žā´¸ā´‚}}", + "age_year_months": "ā´Ēāĩā´°ā´žā´¯ā´‚ 1 ā´ĩāĩŧⴎⴂ, {months, plural, one {# ā´Žā´žā´¸ā´‚} other {# ā´Žā´žā´¸ā´‚}}", + "age_years": "{years, plural, other {ā´Ēāĩā´°ā´žā´¯ā´‚ #}}", + "album_added": "ā´†āĩŊā´Ŧā´‚ ⴚāĩ‡āĩŧā´¤āĩā´¤āĩ", + "album_added_notification_setting_description": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩ† ā´’ā´°āĩ ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´Žāĩā´Ēāĩ‹āĩž ā´’ā´°āĩ ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ ā´…ā´ąā´ŋā´¯ā´ŋā´Ēāĩā´Ēāĩ ā´¸āĩā´ĩāĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´•", + "album_cover_updated": "ā´†āĩŊā´Ŧā´‚ ā´•ā´ĩāĩŧ ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "album_delete_confirmation": "ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ {album} ā´†āĩŊā´Ŧā´‚ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹?", + "album_delete_confirmation_description": "ⴈ ā´†āĩŊā´Ŧā´‚ ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿā´¤ā´žā´Ŗāĩ†ā´™āĩā´•ā´ŋāĩŊ, ā´Žā´ąāĩā´ąāĩ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´•āĩā´•āĩžā´•āĩā´•āĩ ⴇⴍā´ŋ ⴇⴤāĩ ⴆⴕāĩâ€Œā´¸ā´¸āĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛.", + "album_deleted": "ā´†āĩŊā´Ŧā´‚ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´ŋ", + "album_info_card_backup_album_excluded": "ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•ā´ŋ", + "album_info_card_backup_album_included": "ā´‰āĩžā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¤āĩā´¤ā´ŋ", + "album_info_updated": "ā´†āĩŊā´Ŧā´‚ ā´ĩā´ŋā´ĩā´°ā´™āĩā´™āĩž ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "album_leave": "ā´†āĩŊā´Ŧā´‚ ā´ĩā´ŋⴟāĩā´•ā´¯ā´žā´Ŗāĩ‹?", + "album_leave_confirmation": "{album} ā´ĩā´ŋⴟāĩā´Ÿāĩā´Ēāĩ‹ā´•ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹?", + "album_name": "ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋā´¨āĩā´ąāĩ† ā´Ēāĩ‡ā´°āĩ", + "album_options": "ā´†āĩŊā´Ŧā´‚ ā´“ā´Ēāĩā´ˇā´¨āĩā´•āĩž", + "album_remove_user": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ† ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯ā´Ŗāĩ‹?", + "album_remove_user_confirmation": "{user}-ā´¨āĩ† ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹?", + "album_search_not_found": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´¤ā´ŋⴰⴝⴞāĩā´Žā´žā´¯ā´ŋ ā´ĒāĩŠā´°āĩā´¤āĩā´¤ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¨āĩā´¨ ā´†āĩŊā´Ŧā´™āĩā´™ā´ŗāĩŠā´¨āĩā´¨āĩā´‚ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "album_share_no_users": "ā´¨ā´ŋā´™āĩā´™āĩž ⴈ ā´†āĩŊā´Ŧā´‚ ā´Žā´˛āĩā´˛ā´ž ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´•āĩā´•ā´ŗāĩā´Žā´žā´¯āĩā´‚ ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿāĩ, ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´Ēā´™āĩā´•ā´ŋā´Ÿā´žāĩģ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´•āĩā´•ā´ŗā´žā´°āĩā´‚ ⴇⴞāĩā´˛āĩ†ā´¨āĩā´¨āĩ ā´¤āĩ‹ā´¨āĩā´¨āĩā´¨āĩā´¨āĩ.", + "album_summary": "ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋā´¨āĩā´ąāĩ† ⴏⴂⴗāĩā´°ā´šā´‚", + "album_updated": "ā´†āĩŊā´Ŧā´‚ ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "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_title": "ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋā´¨āĩā´ąāĩ† ā´ļāĩ€āĩŧⴎⴕⴂ ā´Žā´žā´ąāĩā´ąāĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "album_viewer_appbar_share_leave": "ā´†āĩŊā´Ŧā´‚ ā´ĩā´ŋⴟāĩā´•", + "album_viewer_appbar_share_to": "ⴇⴤā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Ēā´™āĩā´•ā´ŋⴟāĩā´•", + "album_viewer_page_share_add_users": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´•āĩā´•ā´ŗāĩ† ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", + "album_with_link_access": "ā´˛ā´ŋā´™āĩā´•āĩā´ŗāĩā´ŗ ā´†āĩŧā´•āĩā´•āĩā´‚ ⴈ ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋā´˛āĩ† ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´‚ ⴆⴺāĩā´•ā´ŗāĩ†ā´¯āĩā´‚ ā´•ā´žā´Ŗā´žāĩģ ā´…ā´¨āĩā´ĩā´Ļā´ŋā´•āĩā´•āĩā´•.", + "albums": "ā´†āĩŊā´Ŧā´™āĩā´™āĩž", + "albums_count": "{count, plural, one {{count, number} ā´†āĩŊā´Ŧā´‚} other {{count, number} ā´†āĩŊā´Ŧā´™āĩā´™āĩž}}", + "albums_default_sort_order": "ā´Ąā´ŋā´Ģāĩ‹āĩžā´Ÿāĩā´Ÿāĩ ā´†āĩŊā´Ŧā´‚ ā´¸āĩ‹āĩŧⴟāĩā´Ÿāĩ ā´“āĩŧā´Ąāĩŧ", + "albums_default_sort_order_description": "ā´Ēāĩā´¤ā´ŋā´¯ ā´†āĩŊā´Ŧā´™āĩā´™āĩž ā´¸āĩƒā´ˇāĩā´Ÿā´ŋā´•āĩā´•āĩā´Žāĩā´Ēāĩ‹āĩž ā´Ēāĩā´°ā´žā´°ā´‚ā´­ ā´…ā´¸ā´ąāĩā´ąāĩ ā´¸āĩ‹āĩŧⴟāĩā´Ÿāĩ ā´“āĩŧā´Ąāĩŧ.", + "albums_feature_description": "ā´Žā´ąāĩā´ąāĩ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´•āĩā´•ā´ŗāĩā´Žā´žā´¯ā´ŋ ā´Ēā´™āĩā´•ā´ŋā´Ÿā´žāĩģ ā´•ā´´ā´ŋā´¯āĩā´¨āĩā´¨ ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩā´Ÿāĩ† ā´ļāĩ‡ā´–ā´°ā´‚.", + "albums_on_device_count": "ā´‰ā´Ēā´•ā´°ā´Ŗā´¤āĩā´¤ā´ŋā´˛āĩ† ā´†āĩŊā´Ŧā´™āĩā´™āĩž ({count})", + "all": "ā´Žā´˛āĩā´˛ā´žā´‚", + "all_albums": "ā´Žā´˛āĩā´˛ā´ž ā´†āĩŊā´Ŧā´™āĩā´™ā´ŗāĩā´‚", + "all_people": "ā´Žā´˛āĩā´˛ā´ž ⴆⴺāĩā´•ā´ŗāĩā´‚", + "all_videos": "ā´Žā´˛āĩā´˛ā´ž ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´‚", + "allow_dark_mode": "ā´Ąā´žāĩŧā´•āĩā´•āĩ ā´Žāĩ‹ā´Ąāĩ ā´…ā´¨āĩā´ĩā´Ļā´ŋā´•āĩā´•āĩā´•", + "allow_edits": "ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´•āĩž ā´…ā´¨āĩā´ĩā´Ļā´ŋā´•āĩā´•āĩā´•", + "allow_public_user_to_download": "ā´ĒāĩŠā´¤āĩ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ† ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´…ā´¨āĩā´ĩā´Ļā´ŋā´•āĩā´•āĩā´•", + "allow_public_user_to_upload": "ā´ĒāĩŠā´¤āĩ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ† ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´…ā´¨āĩā´ĩā´Ļā´ŋā´•āĩā´•āĩā´•", + "alt_text_qr_code": "QR ā´•āĩ‹ā´Ąāĩ ⴚā´ŋā´¤āĩā´°ā´‚", + "anti_clockwise": "ā´…ā´Ēāĩā´°ā´Ļā´•āĩā´ˇā´ŋā´Ŗā´Žā´žā´¯ā´ŋ", + "api_key": "API ā´•āĩ€", + "api_key_description": "ⴈ ā´Žāĩ‚ā´˛āĩā´¯ā´‚ ā´’ā´°āĩ ā´¤ā´ĩā´Ŗ ā´Žā´žā´¤āĩā´°ā´Žāĩ‡ ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩ‚. ā´ĩā´ŋāĩģā´Ąāĩ‹ ā´…ā´Ÿā´¯āĩā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ ā´Žāĩā´Žāĩā´Ēāĩ ⴇⴤāĩ ā´Ēā´•āĩŧā´¤āĩā´¤āĩā´¨āĩā´¨ā´¤āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´•āĩā´•āĩā´•.", + "api_key_empty": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† API ā´•āĩ€ā´¯āĩā´Ÿāĩ† ā´Ēāĩ‡ā´°āĩ ā´ļāĩ‚ā´¨āĩā´¯ā´Žā´žā´•ā´°āĩā´¤āĩ", + "api_keys": "API ā´•āĩ€ā´•āĩž", + "app_bar_signout_dialog_content": "ā´¸āĩˆāĩģ ā´”ā´Ÿāĩā´Ÿāĩ ⴚāĩ†ā´¯āĩā´¯ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹?", + "app_bar_signout_dialog_ok": "ā´…ā´¤āĩ†", + "app_bar_signout_dialog_title": "ā´¸āĩˆāĩģ ā´”ā´Ÿāĩā´Ÿāĩ", + "app_settings": "ā´†ā´Ēāĩā´Ēāĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "appears_in": "ⴇⴤā´ŋāĩŊ ā´•ā´žā´Ŗā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¨āĩā´¨āĩ", + "apply_count": "ā´Ēāĩā´°ā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´• ({count, number})", + "archive": "ā´†āĩŧā´•āĩā´•āĩˆā´ĩāĩ", + "archive_action_prompt": "{count} ā´Žā´Ŗāĩā´Ŗā´‚ ā´†āĩŧā´•āĩā´•āĩˆā´ĩā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ⴚāĩ‡āĩŧā´¤āĩā´¤āĩ", + "archive_or_unarchive_photo": "ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ ā´†āĩŧā´•āĩā´•āĩˆā´ĩāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´• ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ ā´…āĩēā´†āĩŧā´•āĩā´•āĩˆā´ĩāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "archive_page_no_archived_assets": "ā´†āĩŧā´•āĩā´•āĩˆā´ĩāĩā´šāĩ†ā´¯āĩâ€Œā´¤ ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩŠā´¨āĩā´¨āĩā´‚ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "archive_page_title": "ā´†āĩŧā´•āĩā´•āĩˆā´ĩāĩ ({count})", + "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_added_to_album": "ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ⴚāĩ‡āĩŧā´¤āĩā´¤āĩ", + "asset_adding_to_album": "ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ⴚāĩ‡āĩŧā´¤āĩā´¤āĩā´•āĩŠā´Ŗāĩā´Ÿā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩâ€Ļ", + "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_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_skipped": "ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•ā´ŋ", + "asset_skipped_in_trash": "ⴟāĩā´°ā´žā´ˇā´ŋāĩŊ", + "asset_trashed": "ā´…ā´¸ā´ąāĩā´ąāĩ ⴟāĩā´°ā´žā´ˇāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "asset_troubleshoot": "ā´…ā´¸ā´ąāĩā´ąāĩ ⴟāĩā´°ā´Ŧā´ŋāĩžā´ˇāĩ‚ā´Ÿāĩā´Ÿāĩ", + "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_albums_count": "{albumTotal, plural, one {# ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ} other {# ā´†āĩŊā´Ŧā´™āĩā´™ā´ŗā´ŋā´˛āĩ‡ā´•āĩā´•āĩ}} {assetTotal, plural, one {# ā´…ā´¸ā´ąāĩā´ąāĩ ⴚāĩ‡āĩŧā´¤āĩā´¤āĩ} other {# ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ⴚāĩ‡āĩŧā´¤āĩā´¤āĩ}}", + "assets_cannot_be_added_to_album_count": "{count, plural, one {ā´…ā´¸ā´ąāĩā´ąāĩ} other {ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž}} ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ⴚāĩ‡āĩŧā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "assets_cannot_be_added_to_albums": "{count, plural, one {ā´…ā´¸ā´ąāĩā´ąāĩ} other {ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž}} ā´’ā´°āĩ ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋā´˛āĩ‡ā´•āĩā´•āĩā´‚ ⴚāĩ‡āĩŧā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "assets_count": "{count, plural, one {# ā´…ā´¸ā´ąāĩā´ąāĩ} other {# ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž}}", + "assets_deleted_permanently": "{count} ā´…ā´¸ā´ąāĩā´ąāĩ(ā´•āĩž) ā´ļā´žā´ļāĩā´ĩā´¤ā´Žā´žā´¯ā´ŋ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´ŋ", + "assets_deleted_permanently_from_server": "{count} ā´…ā´¸ā´ąāĩā´ąāĩ(ā´•āĩž) Immich ā´¸āĩ†āĩŧā´ĩā´ąā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´ļā´žā´ļāĩā´ĩā´¤ā´Žā´žā´¯ā´ŋ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´ŋ", + "assets_downloaded_failed": "{count, plural, one {# ā´Ģā´¯āĩŊ ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¤āĩ - {error} ā´Ģā´¯āĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ} other {# ā´Ģⴝⴞāĩā´•āĩž ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¤āĩ - {error} ā´Ģⴝⴞāĩā´•āĩž ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ}}", + "assets_downloaded_successfully": "{count, plural, one {# ā´Ģā´¯āĩŊ ā´ĩā´ŋā´œā´¯ā´•ā´°ā´Žā´žā´¯ā´ŋ ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¤āĩ} other {# ā´Ģⴝⴞāĩā´•āĩž ā´ĩā´ŋā´œā´¯ā´•ā´°ā´Žā´žā´¯ā´ŋ ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¤āĩ}}", + "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": "{count} ā´…ā´¸ā´ąāĩā´ąāĩ(ā´•āĩž) ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´‰ā´Ēā´•ā´°ā´Ŗā´¤āĩā´¤ā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´ļā´žā´ļāĩā´ĩā´¤ā´Žā´žā´¯ā´ŋ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¤āĩ", + "assets_restore_confirmation": "ⴟāĩā´°ā´žā´ˇāĩ ⴚāĩ†ā´¯āĩā´¤ ā´Žā´˛āĩā´˛ā´ž ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩā´‚ ā´Ēāĩā´¨ā´ƒā´¸āĩā´Ĩā´žā´Ēā´ŋā´•āĩā´•ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹? ⴈ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´‚ ā´Ēā´´ā´¯ā´Ēⴟā´ŋā´¯ā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛! ā´“ā´Ģāĩâ€Œā´˛āĩˆāĩģ ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩŠā´¨āĩā´¨āĩā´‚ ⴈ ā´°āĩ€ā´¤ā´ŋā´¯ā´ŋāĩŊ ā´Ēāĩā´¨ā´ƒā´¸āĩā´Ĩā´žā´Ēā´ŋā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛āĩ†ā´¨āĩā´¨ ā´•ā´žā´°āĩā´¯ā´‚ ā´ļāĩā´°ā´Ļāĩā´§ā´ŋā´•āĩā´•āĩā´•.", + "assets_restored_count": "{count, plural, one {# ā´…ā´¸ā´ąāĩā´ąāĩ ā´Ēāĩā´¨ā´ƒā´¸āĩā´Ĩā´žā´Ēā´ŋⴚāĩā´šāĩ} other {# ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´Ēāĩā´¨ā´ƒā´¸āĩā´Ĩā´žā´Ēā´ŋⴚāĩā´šāĩ}}", + "assets_restored_successfully": "{count} ā´…ā´¸ā´ąāĩā´ąāĩ(ā´•āĩž) ā´ĩā´ŋā´œā´¯ā´•ā´°ā´Žā´žā´¯ā´ŋ ā´Ēāĩā´¨ā´ƒā´¸āĩā´Ĩā´žā´Ēā´ŋⴚāĩā´šāĩ", + "assets_trashed": "{count} ā´…ā´¸ā´ąāĩā´ąāĩ(ā´•āĩž) ⴟāĩā´°ā´žā´ˇāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "assets_trashed_count": "{count, plural, one {# ā´…ā´¸ā´ąāĩā´ąāĩ ⴟāĩā´°ā´žā´ˇāĩ ⴚāĩ†ā´¯āĩā´¤āĩ} other {# ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ⴟāĩā´°ā´žā´ˇāĩ ⴚāĩ†ā´¯āĩā´¤āĩ}}", + "assets_trashed_from_server": "{count} ā´…ā´¸ā´ąāĩā´ąāĩ(ā´•āĩž) Immich ā´¸āĩ†āĩŧā´ĩā´ąā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ⴟāĩā´°ā´žā´ˇāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "assets_were_part_of_album_count": "{count, plural, one {ā´…ā´¸ā´ąāĩā´ąāĩ ⴇⴤā´ŋⴍⴕⴂ} other {ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ⴇⴤā´ŋⴍⴕⴂ}} ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋā´¨āĩā´ąāĩ† ā´­ā´žā´—ā´Žā´žā´¯ā´ŋā´°āĩā´¨āĩā´¨āĩ", + "assets_were_part_of_albums_count": "{count, plural, one {ā´…ā´¸ā´ąāĩā´ąāĩ ⴇⴤā´ŋⴍⴕⴂ} other {ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ⴇⴤā´ŋⴍⴕⴂ}} ā´†āĩŊā´Ŧā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´­ā´žā´—ā´Žā´žā´¯ā´ŋā´°āĩā´¨āĩā´¨āĩ", + "authorized_devices": "ā´…ā´‚ā´—āĩ€ā´•āĩƒā´¤ ā´‰ā´Ēā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "automatic_endpoint_switching_subtitle": "ⴞⴭāĩā´¯ā´Žā´žā´•āĩā´Žāĩā´Ēāĩ‹āĩž ā´¨ā´ŋā´ļāĩā´šā´ŋā´¤ ā´ĩāĩˆ-ā´Ģāĩˆ ā´ĩā´´ā´ŋ ā´Ēāĩā´°ā´žā´Ļāĩ‡ā´ļā´ŋā´•ā´Žā´žā´¯ā´ŋ ā´•ā´Ŗā´•āĩā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´•, ā´Žā´ąāĩā´ąāĩ ā´¸āĩā´Ĩⴞⴙāĩā´™ā´ŗā´ŋāĩŊ ⴇⴤⴰ ā´•ā´Ŗā´•āĩā´ˇā´¨āĩā´•āĩž ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•", + "automatic_endpoint_switching_title": "ā´¯ā´žā´¨āĩā´¤āĩā´°ā´ŋā´• URL ā´¸āĩā´ĩā´ŋⴚāĩā´šā´ŋā´‚ā´—āĩ", + "autoplay_slideshow": "ā´¸āĩā´˛āĩˆā´Ąāĩâ€Œā´ˇāĩ‹ ā´¯ā´žā´¨āĩā´¤āĩā´°ā´ŋā´•ā´Žā´žā´¯ā´ŋ ā´Ēāĩā´˛āĩ‡ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "back": "ā´¤ā´ŋā´°ā´ŋā´•āĩ†", + "back_close_deselect": "ā´Ēāĩā´ąā´•āĩ‹ā´Ÿāĩā´Ÿāĩ, ā´…ā´Ÿā´¯āĩā´•āĩā´•āĩā´•, ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´¤āĩā´¤ā´¤āĩ ā´Žā´žā´ąāĩā´ąāĩā´•", + "background_backup_running_error": "ā´Ēā´ļāĩā´šā´žā´¤āĩā´¤ā´˛ ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ā´‡ā´Ēāĩā´Ēāĩ‹āĩž ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ, ā´Žā´žā´¨āĩā´ĩāĩŊ ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ⴆⴰⴂⴭā´ŋā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "background_location_permission": "ā´Ēā´ļāĩā´šā´žā´¤āĩā´¤ā´˛ ā´˛āĩŠā´•āĩā´•āĩ‡ā´ˇāĩģ ā´…ā´¨āĩā´Žā´¤ā´ŋ", + "background_location_permission_content": "ā´Ēā´ļāĩā´šā´žā´¤āĩā´¤ā´˛ā´¤āĩā´¤ā´ŋāĩŊ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋā´•āĩā´•āĩā´Žāĩā´Ēāĩ‹āĩž ā´¨āĩ†ā´ąāĩā´ąāĩâ€Œā´ĩāĩŧā´•āĩā´•āĩā´•āĩž ā´Žā´žā´ąāĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ, Immich-ā´¨āĩ ā´Žā´Ēāĩā´Ēāĩ‹ā´´āĩā´‚ ā´•āĩƒā´¤āĩā´¯ā´Žā´žā´¯ ā´˛āĩŠā´•āĩā´•āĩ‡ā´ˇāĩģ ⴆⴕāĩâ€Œā´¸ā´¸āĩ ⴉ⴪āĩā´Ÿā´žā´¯ā´ŋā´°ā´ŋā´•āĩā´•ā´Ŗā´‚, ā´…ā´¤āĩā´ĩā´´ā´ŋ ā´†ā´Ēāĩā´Ēā´ŋā´¨āĩ ā´ĩāĩˆ-ā´Ģāĩˆ ā´¨āĩ†ā´ąāĩā´ąāĩâ€Œā´ĩāĩŧā´•āĩā´•ā´ŋā´¨āĩā´ąāĩ† ā´Ēāĩ‡ā´°āĩ ā´ĩā´žā´¯ā´ŋā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯āĩā´‚", + "background_options": "ā´Ēā´ļāĩā´šā´žā´¤āĩā´¤ā´˛ ā´“ā´Ēāĩā´ˇā´¨āĩā´•āĩž", + "backup": "ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ", + "backup_album_selection_page_albums_device": "ā´‰ā´Ēā´•ā´°ā´Ŗā´¤āĩā´¤ā´ŋā´˛āĩ† ā´†āĩŊā´Ŧā´™āĩā´™āĩž ({count})", + "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_albums_sync": "ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ā´†āĩŊā´Ŧā´‚ ā´¸ā´ŋāĩģā´•āĩā´°āĩŠā´Ŗāĩˆā´¸āĩ‡ā´ˇāĩģ", + "backup_all": "ā´Žā´˛āĩā´˛ā´žā´‚ ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "backup_background_service_backup_failed_message": "ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ. ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩā´‚ ā´ļāĩā´°ā´Žā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩâ€Ļ", + "backup_background_service_connection_failed_message": "ā´¸āĩ†āĩŧā´ĩā´ąā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´•ā´Ŗā´•āĩā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ. ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩā´‚ ā´ļāĩā´°ā´Žā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩâ€Ļ", + "backup_background_service_current_upload_notification": "{filename} ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ", + "backup_background_service_default_notification": "ā´Ēāĩā´¤ā´ŋā´¯ ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩžā´•āĩā´•ā´žā´¯ā´ŋ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩâ€Ļ", + "backup_background_service_error_title": "ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ā´Ēā´ŋā´ļā´•āĩ", + "backup_background_service_in_progress_notification": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩâ€Ļ", + "backup_background_service_upload_failure_notification": "{filename} ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "backup_controller_page_albums": "ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ā´†āĩŊā´Ŧā´™āĩā´™āĩž", + "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": "ā´Žā´™āĩā´™ā´¨āĩ†ā´¯āĩ†ā´¨āĩā´¨āĩ ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•", + "backup_controller_page_background_battery_info_message": "ā´Žā´ŋā´•ā´šāĩā´š ā´Ēā´ļāĩā´šā´žā´¤āĩā´¤ā´˛ ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ā´…ā´¨āĩā´­ā´ĩā´¤āĩā´¤ā´ŋā´¨ā´žā´¯ā´ŋ, Immich-ā´¨āĩā´ąāĩ† ā´Ēā´ļāĩā´šā´žā´¤āĩā´¤ā´˛ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´‚ ā´¨ā´ŋⴝⴍāĩā´¤āĩā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ ā´ā´¤āĩ†ā´™āĩā´•ā´ŋā´˛āĩā´‚ ā´Ŧā´žā´ąāĩā´ąā´ąā´ŋ ā´’ā´Ēāĩā´ąāĩā´ąā´ŋā´Žāĩˆā´¸āĩ‡ā´ˇā´¨āĩā´•āĩž ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•āĩā´•.\n\nⴇⴤāĩ ā´‰ā´Ēā´•ā´°ā´Ŗā´¤āĩā´¤āĩ† ā´†ā´ļāĩā´°ā´¯ā´ŋⴚāĩā´šā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋā´¨ā´žāĩŊ, ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´‰ā´Ēā´•ā´°ā´Ŗ ā´¨ā´ŋāĩŧā´Žāĩā´Žā´žā´¤ā´žā´ĩā´ŋā´¨āĩā´ŗāĩā´ŗ ā´†ā´ĩā´ļāĩā´¯ā´Žā´žā´¯ ā´ĩā´ŋā´ĩā´°ā´™āĩā´™āĩž ā´Ļā´¯ā´ĩā´žā´¯ā´ŋ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤āĩā´•.", + "backup_controller_page_background_battery_info_ok": "ā´ļā´°ā´ŋ", + "backup_controller_page_background_battery_info_title": "ā´Ŧā´žā´ąāĩā´ąā´ąā´ŋ ā´’ā´Ēāĩā´ąāĩā´ąā´ŋā´Žāĩˆā´¸āĩ‡ā´ˇā´¨āĩā´•āĩž", + "backup_controller_page_background_charging": "ā´šā´žāĩŧⴜāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´Žāĩā´Ēāĩ‹āĩž ā´Žā´žā´¤āĩā´°ā´‚", + "backup_controller_page_background_configure_error": "ā´Ēā´ļāĩā´šā´žā´¤āĩā´¤ā´˛ ā´¸āĩ‡ā´ĩⴍⴂ ā´•āĩ‹āĩēā´Ģā´ŋā´—āĩŧ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "backup_controller_page_background_delay": "ā´Ēāĩā´¤ā´ŋā´¯ ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩā´Ÿāĩ† ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ā´ĩāĩˆā´•ā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´•: {duration}", + "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": "ā´ĩāĩˆ-ā´Ģāĩˆā´¯ā´ŋāĩŊ ā´Žā´žā´¤āĩā´°ā´‚", + "backup_controller_page_backup": "ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ", + "backup_controller_page_backup_selected": "ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´¤āĩā´¤ā´ĩ: ", + "backup_controller_page_backup_sub": "ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¤ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´‚", + "backup_controller_page_created": "ā´¸āĩƒā´ˇāĩā´Ÿā´ŋⴚāĩā´šā´¤āĩ: {date}", + "backup_controller_page_desc_backup": "ā´†ā´Ēāĩā´Ēāĩ ā´¤āĩā´ąā´•āĩā´•āĩā´Žāĩā´Ēāĩ‹āĩž ā´Ēāĩā´¤ā´ŋā´¯ ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´¯ā´žā´¨āĩā´¤āĩā´°ā´ŋā´•ā´Žā´žā´¯ā´ŋ ā´¸āĩ†āĩŧā´ĩā´ąā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´Ģāĩ‹āĩŧā´—āĩā´°āĩ—ā´Ŗāĩā´Ÿāĩ ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ā´“ā´Ŗā´žā´•āĩā´•āĩā´•.", + "backup_controller_page_excluded": "ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•ā´ŋā´¯ā´ĩ: ", + "backup_controller_page_failed": "ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ ({count})", + "backup_controller_page_filename": "ā´Ģⴝⴞā´ŋā´¨āĩā´ąāĩ† ā´Ēāĩ‡ā´°āĩ: {filename}[{size}]", + "backup_controller_page_id": "ā´ā´Ąā´ŋ: {id}", + "backup_controller_page_info": "ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ā´ĩā´ŋā´ĩā´°ā´™āĩā´™āĩž", + "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_storage_format": "{total}-āĩŊ {used} ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ", + "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_error_sync_failed": "ā´¸ā´ŋā´™āĩā´•āĩ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ. ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ā´Ēāĩā´°āĩ‹ā´¸ā´¸āĩā´¸āĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛.", + "backup_info_card_assets": "ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž", + "backup_manual_cancelled": "ā´ąā´Ļāĩā´Ļā´žā´•āĩā´•ā´ŋ", + "backup_manual_in_progress": "ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴇⴤā´ŋⴍⴕⴂ ā´Ēāĩā´°āĩ‹ā´—ā´Žā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ. ā´•āĩā´ąā´šāĩā´šāĩ ā´¸ā´Žā´¯ā´¤āĩā´¤ā´ŋā´¨āĩ ā´ļāĩ‡ā´ˇā´‚ ā´ļāĩā´°ā´Žā´ŋā´•āĩā´•āĩā´•", + "backup_manual_success": "ā´ĩā´ŋā´œā´¯ā´‚", + "backup_manual_title": "ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ā´¨ā´ŋā´˛", + "backup_options": "ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ā´“ā´Ēāĩā´ˇā´¨āĩā´•āĩž", + "backup_options_page_title": "ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ā´“ā´Ēāĩā´ˇā´¨āĩā´•āĩž", + "backup_setting_subtitle": "ā´Ēā´ļāĩā´šā´žā´¤āĩā´¤ā´˛, ā´Žāĩāĩģā´¨ā´ŋā´° ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "backup_settings_subtitle": "ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "backward": "ā´Ēā´ŋā´¨āĩā´¨āĩ‹ā´Ÿāĩā´Ÿāĩ", + "biometric_auth_enabled": "ā´Ŧā´¯āĩ‹ā´Žāĩ†ā´Ÿāĩā´°ā´ŋā´•āĩ ā´Ēāĩā´°ā´žā´Žā´žā´Ŗāĩ€ā´•ā´°ā´Ŗā´‚ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•ā´ŋ", + "biometric_locked_out": "ā´Ŧā´¯āĩ‹ā´Žāĩ†ā´Ÿāĩā´°ā´ŋā´•āĩ ā´Ēāĩā´°ā´žā´Žā´žā´Ŗāĩ€ā´•ā´°ā´Ŗā´¤āĩā´¤ā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™ā´ŗāĩ† ā´˛āĩ‹ā´•āĩā´•āĩ ā´”ā´Ÿāĩā´Ÿāĩ ⴚāĩ†ā´¯āĩā´¤ā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "biometric_no_options": "ā´Ŧā´¯āĩ‹ā´Žāĩ†ā´Ÿāĩā´°ā´ŋā´•āĩ ā´“ā´Ēāĩā´ˇā´¨āĩā´•ā´ŗāĩŠā´¨āĩā´¨āĩā´‚ ⴞⴭāĩā´¯ā´Žā´˛āĩā´˛", + "biometric_not_available": "ⴈ ā´‰ā´Ēā´•ā´°ā´Ŗā´¤āĩā´¤ā´ŋāĩŊ ā´Ŧā´¯āĩ‹ā´Žāĩ†ā´Ÿāĩā´°ā´ŋā´•āĩ ā´Ēāĩā´°ā´žā´Žā´žā´Ŗāĩ€ā´•ā´°ā´Ŗā´‚ ⴞⴭāĩā´¯ā´Žā´˛āĩā´˛", + "birthdate_saved": "ⴜⴍⴍⴤāĩā´¤āĩ€ā´¯ā´¤ā´ŋ ā´ĩā´ŋā´œā´¯ā´•ā´°ā´Žā´žā´¯ā´ŋ ā´¸āĩ‡ā´ĩāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "birthdate_set_description": "ā´’ā´°āĩ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ ā´Žā´Ÿāĩā´•āĩā´•āĩā´Žāĩā´Ēāĩ‹ā´´āĩā´ŗāĩā´ŗ ⴈ ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´¯āĩā´Ÿāĩ† ā´Ēāĩā´°ā´žā´¯ā´‚ ā´•ā´Ŗā´•āĩā´•ā´žā´•āĩā´•ā´žāĩģ ⴜⴍⴍⴤāĩā´¤āĩ€ā´¯ā´¤ā´ŋ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ.", + "blurred_background": "ā´Žā´™āĩā´™ā´ŋā´¯ ā´Ēā´ļāĩā´šā´žā´¤āĩā´¤ā´˛ā´‚", + "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 {# ā´Ąāĩā´¯āĩ‚ā´Ēāĩā´˛ā´ŋā´•āĩā´•āĩ‡ā´ąāĩā´ąāĩ ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž}} ā´Ŧāĩžā´•āĩā´•ā´žā´¯ā´ŋ ⴟāĩā´°ā´žā´ˇāĩ ⴚāĩ†ā´¯āĩā´¯ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹? ⴇⴤāĩ ā´“ā´°āĩ‹ ā´—āĩā´°āĩ‚ā´Ēāĩā´Ēā´ŋā´˛āĩ†ā´¯āĩā´‚ ā´ā´ąāĩā´ąā´ĩāĩā´‚ ā´ĩā´˛ā´ŋā´¯ ā´…ā´¸ā´ąāĩā´ąāĩ ā´¨ā´ŋⴞⴍā´ŋāĩŧā´¤āĩā´¤āĩā´•ā´¯āĩā´‚ ā´Žā´ąāĩā´ąāĩ ā´Žā´˛āĩā´˛ā´ž ā´Ąāĩā´¯āĩ‚ā´Ēāĩā´˛ā´ŋā´•āĩā´•āĩ‡ā´ąāĩā´ąāĩā´•ā´ŗāĩā´‚ ⴟāĩā´°ā´žā´ˇāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•ā´¯āĩā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´‚.", + "buy": "Immich ā´ĩā´žā´™āĩā´™āĩā´•", + "cache_settings_clear_cache_button": "ā´•ā´žā´ˇāĩ† ā´•āĩā´˛ā´ŋā´¯āĩŧ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "cache_settings_clear_cache_button_title": "ā´†ā´Ēāĩā´Ēā´ŋā´¨āĩā´ąāĩ† ā´•ā´žā´ˇāĩ† ā´•āĩā´˛ā´ŋā´¯āĩŧ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ. ā´•ā´žā´ˇāĩ† ā´Ēāĩā´¨āĩŧā´¨ā´ŋāĩŧā´Žāĩā´Žā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤āĩā´ĩā´°āĩ† ⴇⴤāĩ ā´†ā´Ēāĩā´Ēā´ŋā´¨āĩā´ąāĩ† ā´Ēāĩā´°ā´•ā´Ÿā´¨ā´¤āĩā´¤āĩ† ā´¸ā´žā´°ā´Žā´žā´¯ā´ŋ ā´Ŧā´žā´§ā´ŋā´•āĩā´•āĩā´‚.", + "cache_settings_duplicated_assets_clear_button": "ā´•āĩā´˛ā´ŋā´¯āĩŧ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "cache_settings_duplicated_assets_subtitle": "ā´†ā´Ēāĩā´Ēāĩ ā´…ā´ĩā´—ā´Ŗā´ŋⴚāĩā´š ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´‚", + "cache_settings_duplicated_assets_title": "ā´Ąāĩā´¯āĩ‚ā´Ēāĩā´˛ā´ŋā´•āĩā´•āĩ‡ā´ąāĩā´ąāĩ ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ({count})", + "cache_settings_statistics_album": "ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋā´˛āĩā´•āĩž", + "cache_settings_statistics_full": "ā´Ēāĩ‚āĩŧā´Ŗāĩā´Ŗ ⴚā´ŋā´¤āĩā´°ā´™āĩā´™āĩž", + "cache_settings_statistics_shared": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´†āĩŊā´Ŧā´‚ ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋā´˛āĩā´•āĩž", + "cache_settings_statistics_thumbnail": "ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋā´˛āĩā´•āĩž", + "cache_settings_statistics_title": "ā´•ā´žā´ˇāĩ† ā´‰ā´Ēā´¯āĩ‹ā´—ā´‚", + "cache_settings_subtitle": "Immich ā´ŽāĩŠā´ŦāĩˆāĩŊ ā´†ā´Ēāĩā´˛ā´ŋā´•āĩā´•āĩ‡ā´ˇā´¨āĩā´ąāĩ† ā´•ā´žā´ˇā´ŋā´‚ā´—āĩ ā´¸āĩā´ĩā´­ā´žā´ĩā´‚ ā´¨ā´ŋⴝⴍāĩā´¤āĩā´°ā´ŋā´•āĩā´•āĩā´•", + "cache_settings_tile_subtitle": "ā´Ēāĩā´°ā´žā´Ļāĩ‡ā´ļā´ŋā´• ā´¸āĩā´ąāĩā´ąāĩ‹ā´ąāĩ‡ā´œāĩ ā´¸āĩā´ĩā´­ā´žā´ĩā´‚ ā´¨ā´ŋⴝⴍāĩā´¤āĩā´°ā´ŋā´•āĩā´•āĩā´•", + "cache_settings_tile_title": "ā´Ēāĩā´°ā´žā´Ļāĩ‡ā´ļā´ŋā´• ā´¸āĩā´ąāĩā´ąāĩ‹ā´ąāĩ‡ā´œāĩ", + "cache_settings_title": "ā´•ā´žā´ˇā´ŋā´‚ā´—āĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "camera": "ā´•āĩā´¯ā´žā´Žā´ą", + "camera_brand": "ā´•āĩā´¯ā´žā´Žā´ą ā´Ŧāĩā´°ā´žāĩģā´Ąāĩ", + "camera_model": "ā´•āĩā´¯ā´žā´Žā´ą ā´Žāĩ‹ā´ĄāĩŊ", + "cancel": "ā´ąā´Ļāĩā´Ļā´žā´•āĩā´•āĩā´•", + "cancel_search": "ā´¤ā´ŋā´°ā´¯āĩŊ ā´ąā´Ļāĩā´Ļā´žā´•āĩā´•āĩā´•", + "canceled": "ā´ąā´Ļāĩā´Ļā´žā´•āĩā´•ā´ŋ", + "canceling": "ā´ąā´Ļāĩā´Ļā´žā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "cannot_merge_people": "ⴆⴺāĩā´•ā´ŗāĩ† ⴞⴝā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "cannot_undo_this_action": "ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ⴈ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´‚ ā´Ēā´´ā´¯ā´Ēⴟā´ŋā´¯ā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛!", + "cannot_update_the_description": "ā´ĩā´ŋā´ĩā´°ā´Ŗā´‚ ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "cast": "ā´•ā´žā´¸āĩā´ąāĩā´ąāĩ", + "cast_description": "ⴞⴭāĩā´¯ā´Žā´žā´¯ ā´•ā´žā´¸āĩā´ąāĩā´ąāĩ ā´Ąāĩ†ā´¸āĩā´ąāĩā´ąā´ŋā´¨āĩ‡ā´ˇā´¨āĩā´•āĩž ā´•āĩ‹āĩēā´Ģā´ŋā´—āĩŧ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "change_date": "ā´¤āĩ€ā´¯ā´¤ā´ŋ ā´Žā´žā´ąāĩā´ąāĩā´•", + "change_description": "ā´ĩā´ŋā´ĩā´°ā´Ŗā´‚ ā´Žā´žā´ąāĩā´ąāĩā´•", + "change_display_order": "ā´Ēāĩā´°ā´Ļāĩŧā´ļā´¨ ā´•āĩā´°ā´Žā´‚ ā´Žā´žā´ąāĩā´ąāĩā´•", + "change_expiration_time": "ā´•ā´žā´˛ā´šā´°ā´Ŗā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¨āĩā´¨ ā´¸ā´Žā´¯ā´‚ ā´Žā´žā´ąāĩā´ąāĩā´•", + "change_location": "ā´¸āĩā´Ĩā´žā´¨ā´‚ ā´Žā´žā´ąāĩā´ąāĩā´•", + "change_name": "ā´Ēāĩ‡ā´°āĩ ā´Žā´žā´ąāĩā´ąāĩā´•", + "change_name_successfully": "ā´Ēāĩ‡ā´°āĩ ā´ĩā´ŋā´œā´¯ā´•ā´°ā´Žā´žā´¯ā´ŋ ā´Žā´žā´ąāĩā´ąā´ŋ", + "change_password": "ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´Žā´žā´ąāĩā´ąāĩā´•", + "change_password_description": "ⴇⴤāĩ ā´¨ā´ŋā´™āĩā´™āĩž ā´†ā´Ļāĩā´¯ā´Žā´žā´¯ā´ŋ ā´¸ā´ŋā´¸āĩā´ąāĩā´ąā´¤āĩā´¤ā´ŋāĩŊ ā´¸āĩˆāĩģ ā´‡āĩģ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤āĩā´•āĩŠā´Ŗāĩā´Ÿāĩ‹ ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´Žā´žā´ąāĩā´ąā´žāĩģ ā´’ā´°āĩ ā´…ā´­āĩā´¯āĩŧā´¤āĩā´Ĩā´¨ ⴍⴟⴤāĩā´¤ā´ŋⴝⴤāĩā´•āĩŠā´Ŗāĩā´Ÿāĩ‹ ā´†ā´•ā´žā´‚. ā´Ļā´¯ā´ĩā´žā´¯ā´ŋ ā´¤ā´žā´´āĩ† ā´Ēāĩā´¤ā´ŋā´¯ ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´¨āĩŊā´•āĩā´•.", + "change_password_form_confirm_password": "ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´¸āĩā´Ĩā´ŋā´°āĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´•", + "change_password_form_description": "ā´¨ā´Žā´¸āĩā´•ā´žā´°ā´‚ {name},\n\nⴇⴤāĩ ā´¨ā´ŋā´™āĩā´™āĩž ā´†ā´Ļāĩā´¯ā´Žā´žā´¯ā´ŋ ā´¸ā´ŋā´¸āĩā´ąāĩā´ąā´¤āĩā´¤ā´ŋāĩŊ ā´¸āĩˆāĩģ ā´‡āĩģ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤āĩā´•āĩŠā´Ŗāĩā´Ÿāĩ‹ ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´Žā´žā´ąāĩā´ąā´žāĩģ ā´’ā´°āĩ ā´…ā´­āĩā´¯āĩŧā´¤āĩā´Ĩā´¨ ⴍⴟⴤāĩā´¤ā´ŋⴝⴤāĩā´•āĩŠā´Ŗāĩā´Ÿāĩ‹ ā´†ā´•ā´žā´‚. ā´Ļā´¯ā´ĩā´žā´¯ā´ŋ ā´¤ā´žā´´āĩ† ā´Ēāĩā´¤ā´ŋā´¯ ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´¨āĩŊā´•āĩā´•.", + "change_password_form_new_password": "ā´Ēāĩā´¤ā´ŋā´¯ ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ", + "change_password_form_password_mismatch": "ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩā´•āĩž ā´ĒāĩŠā´°āĩā´¤āĩā´¤ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¨āĩā´¨ā´ŋā´˛āĩā´˛", + "change_password_form_reenter_new_password": "ā´Ēāĩā´¤ā´ŋā´¯ ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩā´‚ ā´¨āĩŊā´•āĩā´•", + "change_pin_code": "ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ ā´Žā´žā´ąāĩā´ąāĩā´•", + "change_your_password": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´Žā´žā´ąāĩā´ąāĩā´•", + "changed_visibility_successfully": "ā´Ļāĩƒā´ļāĩā´¯ā´¤ ā´ĩā´ŋā´œā´¯ā´•ā´°ā´Žā´žā´¯ā´ŋ ā´Žā´žā´ąāĩā´ąā´ŋ", + "charging": "ā´šā´žāĩŧⴜāĩā´œāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ", + "charging_requirement_mobile_backup": "ā´Ēā´ļāĩā´šā´žā´¤āĩā´¤ā´˛ ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēā´ŋā´¨āĩ ā´‰ā´Ēā´•ā´°ā´Ŗā´‚ ā´šā´žāĩŧⴜāĩ ⴚāĩ†ā´¯āĩā´¯āĩ‡ā´Ŗāĩā´Ÿā´¤āĩā´Ŗāĩā´Ÿāĩ", + "check_corrupt_asset_backup": "ā´•āĩ‡ā´Ÿā´žā´¯ ā´…ā´¸ā´ąāĩā´ąāĩ ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩā´•āĩž ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´ŋā´•āĩā´•āĩā´•", + "check_corrupt_asset_backup_button": "ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´¨ ⴍⴟⴤāĩā´¤āĩā´•", + "check_corrupt_asset_backup_description": "ā´Žā´˛āĩā´˛ā´ž ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩā´‚ ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¤ ā´ļāĩ‡ā´ˇā´‚, ā´ĩāĩˆ-ā´Ģāĩˆā´¯ā´ŋāĩŊ ā´Žā´žā´¤āĩā´°ā´‚ ⴈ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´¨ ⴍⴟⴤāĩā´¤āĩā´•. ⴍⴟā´Ēⴟā´ŋā´•āĩā´°ā´Žā´¤āĩā´¤ā´ŋā´¨āĩ ā´•āĩā´ąā´šāĩā´šāĩ ā´Žā´ŋā´¨ā´ŋā´ąāĩā´ąāĩā´•āĩž ā´Žā´Ÿāĩā´¤āĩā´¤āĩ‡ā´•āĩā´•ā´žā´‚.", + "check_logs": "ā´˛āĩ‹ā´—āĩā´•āĩž ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´ŋā´•āĩā´•āĩā´•", + "choose_matching_people_to_merge": "ⴞⴝā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•ā´žāĩģ ā´ĒāĩŠā´°āĩā´¤āĩā´¤ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¨āĩā´¨ ⴆⴺāĩā´•ā´ŗāĩ† ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "city": "ⴍⴗⴰⴂ", + "clear": "ā´•āĩā´˛ā´ŋā´¯āĩŧ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "clear_all": "ā´Žā´˛āĩā´˛ā´žā´‚ ā´•āĩā´˛ā´ŋā´¯āĩŧ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "clear_all_recent_searches": "ā´…ā´Ÿāĩā´¤āĩā´¤ā´ŋⴟāĩ† ⴍⴟⴤāĩā´¤ā´ŋā´¯ ā´Žā´˛āĩā´˛ā´ž ā´¤ā´ŋⴰⴝⴞāĩā´•ā´ŗāĩā´‚ ā´•āĩā´˛ā´ŋā´¯āĩŧ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "clear_file_cache": "ā´Ģā´¯āĩŊ ā´•ā´žā´ˇāĩ† ā´•āĩā´˛ā´ŋā´¯āĩŧ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "clear_message": "ⴏⴍāĩā´Ļāĩ‡ā´ļā´‚ ā´•āĩā´˛ā´ŋā´¯āĩŧ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "clear_value": "ā´Žāĩ‚ā´˛āĩā´¯ā´‚ ā´•āĩā´˛ā´ŋā´¯āĩŧ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "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_title": "SSL ā´•āĩā´˛ā´¯ā´ŋā´¨āĩā´ąāĩ ā´¸āĩŧⴟāĩā´Ÿā´ŋā´Ģā´ŋā´•āĩā´•ā´ąāĩā´ąāĩ", + "clockwise": "ā´Ēāĩā´°ā´Ļā´•āĩā´ˇā´ŋā´Ŗā´Žā´žā´¯ā´ŋ", + "close": "ā´…ā´Ÿā´¯āĩā´•āĩā´•āĩā´•", + "collapse": "ⴚāĩā´°āĩā´•āĩā´•āĩā´•", + "collapse_all": "ā´Žā´˛āĩā´˛ā´žā´‚ ⴚāĩā´°āĩā´•āĩā´•āĩā´•", + "color": "ā´¨ā´ŋā´ąā´‚", + "color_theme": "ā´•ā´ŗāĩŧ ā´¤āĩ€ā´‚", + "comment_deleted": "ā´…ā´­ā´ŋā´Ēāĩā´°ā´žā´¯ā´‚ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´ŋ", + "comment_options": "ā´…ā´­ā´ŋā´Ēāĩā´°ā´žā´¯ā´¤āĩā´¤ā´ŋā´¨āĩā´ŗāĩā´ŗ ā´“ā´Ēāĩā´ˇā´¨āĩā´•āĩž", + "comments_and_likes": "ā´…ā´­ā´ŋā´Ēāĩā´°ā´žā´¯ā´™āĩā´™ā´ŗāĩā´‚ ā´˛āĩˆā´•āĩā´•āĩā´•ā´ŗāĩā´‚", + "comments_are_disabled": "ā´…ā´­ā´ŋā´Ēāĩā´°ā´žā´¯ā´™āĩā´™āĩž ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•ā´ŋ", + "common_create_new_album": "ā´Ēāĩā´¤ā´ŋā´¯ ā´†āĩŊā´Ŧā´‚ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´•", + "common_server_error": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´¨āĩ†ā´ąāĩā´ąāĩâ€Œā´ĩāĩŧā´•āĩā´•āĩ ā´•ā´Ŗā´•āĩā´ˇāĩģ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´ŋā´•āĩā´•āĩā´•, ā´¸āĩ†āĩŧā´ĩāĩŧ ⴞⴭāĩā´¯ā´Žā´žā´Ŗāĩ†ā´¨āĩā´¨āĩā´‚ ā´†ā´Ēāĩā´Ēāĩ/ā´¸āĩ†āĩŧā´ĩāĩŧ ā´Ēā´¤ā´ŋā´Ēāĩā´Ēāĩā´•āĩž ā´…ā´¨āĩā´¯āĩ‹ā´œāĩā´¯ā´Žā´žā´Ŗāĩ†ā´¨āĩā´¨āĩā´‚ ā´‰ā´ąā´Ēāĩā´Ēā´žā´•āĩā´•āĩā´•.", + "completed": "ā´Ēāĩ‚āĩŧā´¤āĩā´¤ā´ŋā´¯ā´žā´¯ā´ŋ", + "confirm": "ā´¸āĩā´Ĩā´ŋā´°āĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´•", + "confirm_admin_password": "ā´…ā´Ąāĩā´Žā´ŋāĩģ ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´¸āĩā´Ĩā´ŋā´°āĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´•", + "confirm_delete_face": "{name} ā´Žā´¨āĩā´¨ ā´Žāĩā´–ā´‚ ā´…ā´¸ā´ąāĩā´ąā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹?", + "confirm_delete_shared_link": "ⴈ ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´˛ā´ŋā´™āĩā´•āĩ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹?", + "confirm_keep_this_delete_others": "ⴈ ā´…ā´¸ā´ąāĩā´ąāĩ ā´’ā´´ā´ŋā´•āĩ† ā´¸āĩā´ąāĩā´ąā´žā´•āĩā´•ā´ŋā´˛āĩ† ā´Žā´ąāĩā´ąāĩ†ā´˛āĩā´˛ā´ž ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩā´‚ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´‚. ā´¤āĩā´Ÿā´°ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹?", + "confirm_new_pin_code": "ā´Ēāĩā´¤ā´ŋā´¯ ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ ā´¸āĩā´Ĩā´ŋā´°āĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´•", + "confirm_password": "ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´¸āĩā´Ĩā´ŋā´°āĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´•", + "confirm_tag_face": "ⴈ ā´Žāĩā´–ā´‚ {name} ā´Žā´¨āĩā´¨āĩ ā´Ÿā´žā´—āĩ ⴚāĩ†ā´¯āĩā´¯ā´Ŗāĩ‹?", + "confirm_tag_face_unnamed": "ⴈ ā´Žāĩā´–ā´‚ ā´Ÿā´žā´—āĩ ⴚāĩ†ā´¯āĩā´¯ā´Ŗāĩ‹?", + "connected_device": "ā´Ŧā´¨āĩā´§ā´ŋā´Ēāĩā´Ēā´ŋⴚāĩā´š ā´‰ā´Ēā´•ā´°ā´Ŗā´‚", + "connected_to": "ⴇⴤāĩā´Žā´žā´¯ā´ŋ ā´Ŧā´¨āĩā´§ā´ŋā´Ēāĩā´Ēā´ŋⴚāĩā´šāĩ", + "contain": "ā´‰āĩžā´•āĩā´•āĩŠā´ŗāĩā´ŗāĩā´•", + "context": "ⴏⴍāĩā´Ļāĩŧā´­ā´‚", + "continue": "ā´¤āĩā´Ÿā´°āĩā´•", + "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": "ā´˛ā´ŋā´™āĩā´•āĩ ā´Ēā´™āĩā´•ā´ŋⴟāĩā´•", + "control_bottom_app_bar_share_to": "ⴇⴤā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Ēā´™āĩā´•ā´ŋⴟāĩā´•", + "control_bottom_app_bar_trash_from_immich": "ⴟāĩā´°ā´žā´ˇā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Žā´žā´ąāĩā´ąāĩā´•", + "copied_image_to_clipboard": "ⴚā´ŋā´¤āĩā´°ā´‚ ā´•āĩā´˛ā´ŋā´Ēāĩā´Ēāĩā´Ŧāĩ‹āĩŧā´Ąā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Ēā´•āĩŧā´¤āĩā´¤ā´ŋ.", + "copied_to_clipboard": "ā´•āĩā´˛ā´ŋā´Ēāĩā´Ēāĩā´Ŧāĩ‹āĩŧā´Ąā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Ēā´•āĩŧā´¤āĩā´¤ā´ŋ!", + "copy_error": "ā´Ēā´•āĩŧā´¤āĩā´¤āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´ŋā´ļā´•āĩ", + "copy_file_path": "ā´Ģā´¯āĩŊ ā´Ēā´žā´¤āĩā´¤āĩ ā´Ēā´•āĩŧā´¤āĩā´¤āĩā´•", + "copy_image": "ⴚā´ŋā´¤āĩā´°ā´‚ ā´Ēā´•āĩŧā´¤āĩā´¤āĩā´•", + "copy_link": "ā´˛ā´ŋā´™āĩā´•āĩ ā´Ēā´•āĩŧā´¤āĩā´¤āĩā´•", + "copy_link_to_clipboard": "ā´˛ā´ŋā´™āĩā´•āĩ ā´•āĩā´˛ā´ŋā´Ēāĩā´Ēāĩā´Ŧāĩ‹āĩŧā´Ąā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Ēā´•āĩŧā´¤āĩā´¤āĩā´•", + "copy_password": "ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´Ēā´•āĩŧā´¤āĩā´¤āĩā´•", + "copy_to_clipboard": "ā´•āĩā´˛ā´ŋā´Ēāĩā´Ēāĩā´Ŧāĩ‹āĩŧā´Ąā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Ēā´•āĩŧā´¤āĩā´¤āĩā´•", + "country": "ā´°ā´žā´œāĩā´¯ā´‚", + "cover": "ā´•ā´ĩāĩŧ", + "covers": "ā´•ā´ĩā´ąāĩā´•āĩž", + "create": "ā´¸āĩƒā´ˇāĩā´Ÿā´ŋā´•āĩā´•āĩā´•", + "create_album": "ā´†āĩŊā´Ŧā´‚ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´•", + "create_album_page_untitled": "ā´Ēāĩ‡ā´°ā´ŋā´˛āĩā´˛ā´žā´¤āĩā´¤ā´¤āĩ", + "create_library": "ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´•", + "create_link": "ā´˛ā´ŋā´™āĩā´•āĩ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´•", + "create_link_to_share": "ā´Ēā´™āĩā´•ā´ŋā´Ÿā´žāĩģ ā´˛ā´ŋā´™āĩā´•āĩ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´•", + "create_link_to_share_description": "ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´¤āĩā´¤ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹(ā´•āĩž) ā´•ā´žā´Ŗā´žāĩģ ā´˛ā´ŋā´™āĩā´•āĩā´ŗāĩā´ŗ ā´†āĩŧā´•āĩā´•āĩā´‚ ā´…ā´¨āĩā´ĩā´žā´Ļā´‚ ā´¨āĩŊā´•āĩā´•", + "create_new": "ā´Ēāĩā´¤ā´ŋⴝⴤāĩ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´•", + "create_new_person": "ā´Ēāĩā´¤ā´ŋā´¯ ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´¯āĩ† ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´•", + "create_new_person_hint": "ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´¤āĩā´¤ ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´’ā´°āĩ ā´Ēāĩā´¤ā´ŋā´¯ ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´•āĩā´•āĩ ā´¨āĩŊā´•āĩā´•", + "create_new_user": "ā´Ēāĩā´¤ā´ŋā´¯ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ† ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´•", + "create_shared_album_page_share_add_assets": "ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", + "create_shared_album_page_share_select_photos": "ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "create_shared_link": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´˛ā´ŋā´™āĩā´•āĩ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´•", + "create_tag": "ā´Ÿā´žā´—āĩ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´•", + "create_tag_description": "ā´’ā´°āĩ ā´Ēāĩā´¤ā´ŋā´¯ ā´Ÿā´žā´—āĩ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´•. ā´¨āĩ†ā´¸āĩā´ąāĩā´ąā´Ąāĩ ā´Ÿā´žā´—āĩā´•āĩžā´•āĩā´•ā´žā´¯ā´ŋ, ā´Ģāĩ‹āĩŧā´ĩāĩ‡ā´Ąāĩ ā´¸āĩā´˛ā´žā´ˇāĩā´•āĩž ā´‰āĩžā´Ēāĩā´Ēāĩ†ā´Ÿāĩ† ā´Ÿā´žā´—ā´ŋā´¨āĩā´ąāĩ† ā´Ēāĩ‚āĩŧā´Ŗāĩā´Ŗ ā´Ēā´žā´¤ ā´¨āĩŊā´•āĩā´•.", + "create_user": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ† ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´•", + "created": "ā´¸āĩƒā´ˇāĩā´Ÿā´ŋⴚāĩā´šā´¤āĩ", + "created_at": "ā´¸āĩƒā´ˇāĩā´Ÿā´ŋⴚāĩā´šā´¤āĩ", + "creating_linked_albums": "ā´Ŧā´¨āĩā´§ā´ŋā´Ēāĩā´Ēā´ŋⴚāĩā´š ā´†āĩŊā´Ŧā´™āĩā´™āĩž ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´¨āĩā´¨āĩ...", + "crop": "ā´•āĩā´°āĩ‹ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "curated_object_page_title": "ā´ĩā´¸āĩā´¤āĩā´•āĩā´•āĩž", + "current_device": "ā´¨ā´ŋā´˛ā´ĩā´ŋā´˛āĩ† ā´‰ā´Ēā´•ā´°ā´Ŗā´‚", + "current_pin_code": "ā´¨ā´ŋā´˛ā´ĩā´ŋā´˛āĩ† ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ", + "current_server_address": "ā´¨ā´ŋā´˛ā´ĩā´ŋā´˛āĩ† ā´¸āĩ†āĩŧā´ĩāĩŧ ā´ĩā´ŋā´˛ā´žā´¸ā´‚", + "custom_locale": "ā´•ā´¸āĩā´ąāĩā´ąā´‚ ā´˛āĩŠā´•āĩā´•āĩ‡āĩŊ", + "custom_locale_description": "ā´­ā´žā´ˇā´¯āĩ†ā´¯āĩā´‚ ā´Ēāĩā´°ā´Ļāĩ‡ā´ļā´¤āĩā´¤āĩ†ā´¯āĩā´‚ ā´…ā´Ÿā´ŋā´¸āĩā´Ĩā´žā´¨ā´Žā´žā´•āĩā´•ā´ŋ ā´¤āĩ€ā´¯ā´¤ā´ŋā´•ā´ŗāĩā´‚ ā´…ā´•āĩā´•ā´™āĩā´™ā´ŗāĩā´‚ ā´Ģāĩ‹āĩŧā´Žā´žā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "custom_url": "ā´•ā´¸āĩā´ąāĩā´ąā´‚ URL", + "daily_title_text_date": "E, MMM dd", + "daily_title_text_date_year": "E, MMM dd, yyyy", + "dark": "ⴇⴰāĩā´Ŗāĩā´Ÿā´¤āĩ", + "dark_theme": "ā´Ąā´žāĩŧā´•āĩā´•āĩ ā´¤āĩ€ā´‚ ⴟāĩ‹ā´—ā´ŋāĩž ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "date_after": "ⴇⴤā´ŋā´¨āĩ ā´ļāĩ‡ā´ˇā´Žāĩā´ŗāĩā´ŗ ā´¤āĩ€ā´¯ā´¤ā´ŋ", + "date_and_time": "ā´¤āĩ€ā´¯ā´¤ā´ŋā´¯āĩā´‚ ā´¸ā´Žā´¯ā´ĩāĩā´‚", + "date_before": "ⴇⴤā´ŋā´¨āĩ ā´Žāĩā´Žāĩā´Ēāĩā´ŗāĩā´ŗ ā´¤āĩ€ā´¯ā´¤ā´ŋ", + "date_format": "E, LLL d, y â€ĸ h:mm a", + "date_of_birth_saved": "ⴜⴍⴍⴤāĩā´¤āĩ€ā´¯ā´¤ā´ŋ ā´ĩā´ŋā´œā´¯ā´•ā´°ā´Žā´žā´¯ā´ŋ ā´¸āĩ‡ā´ĩāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "date_range": "ā´¤āĩ€ā´¯ā´¤ā´ŋ ā´Ēā´°ā´ŋā´§ā´ŋ", + "day": "ā´Ļā´ŋā´ĩⴏⴂ", + "days": "ā´Ļā´ŋā´ĩⴏⴙāĩā´™āĩž", + "deduplicate_all": "ā´Žā´˛āĩā´˛ā´ž ā´Ąāĩā´¯āĩ‚ā´Ēāĩā´˛ā´ŋā´•āĩā´•āĩ‡ā´ąāĩā´ąāĩā´•ā´ŗāĩā´‚ ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•āĩā´•", + "deduplication_criteria_1": "ⴚā´ŋā´¤āĩā´°ā´¤āĩā´¤ā´ŋā´¨āĩā´ąāĩ† ā´ĩā´˛āĩā´Ēāĩā´Ēā´‚ (ā´Ŧāĩˆā´ąāĩā´ąāĩā´•ā´ŗā´ŋāĩŊ)", + "deduplication_criteria_2": "EXIF ā´Ąā´žā´ąāĩā´ąā´¯āĩā´Ÿāĩ† ā´Žā´Ŗāĩā´Ŗā´‚", + "deduplication_info": "ā´Ąāĩā´¯āĩ‚ā´Ēāĩā´˛ā´ŋā´•āĩā´•āĩ‡ā´ˇāĩģ ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•āĩŊ ā´ĩā´ŋā´ĩā´°ā´‚", + "deduplication_info_description": "ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´¯ā´žā´¨āĩā´¤āĩā´°ā´ŋā´•ā´Žā´žā´¯ā´ŋ ā´Žāĩāĩģā´•āĩ‚ā´Ÿāĩā´Ÿā´ŋ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩā´‚ ā´Ąāĩā´¯āĩ‚ā´Ēāĩā´˛ā´ŋā´•āĩā´•āĩ‡ā´ąāĩā´ąāĩā´•āĩž ā´Ŧāĩžā´•āĩā´•ā´žā´¯ā´ŋ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩā´‚, ā´žā´™āĩā´™āĩž ā´‡ā´ĩ ā´Ēā´°ā´ŋā´—ā´Ŗā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ:", + "default_locale": "ā´Ąā´ŋā´Ģāĩ‹āĩžā´Ÿāĩā´Ÿāĩ ā´˛āĩŠā´•āĩā´•āĩ‡āĩŊ", + "default_locale_description": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ŧāĩā´°āĩ—ā´¸āĩŧ ā´˛āĩŠā´•āĩā´•āĩ‡ā´˛ā´ŋā´¨āĩ† ā´…ā´Ÿā´ŋā´¸āĩā´Ĩā´žā´¨ā´Žā´žā´•āĩā´•ā´ŋ ā´¤āĩ€ā´¯ā´¤ā´ŋā´•ā´ŗāĩā´‚ ā´…ā´•āĩā´•ā´™āĩā´™ā´ŗāĩā´‚ ā´Ģāĩ‹āĩŧā´Žā´žā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "delete": "ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´•", + "delete_action_confirmation_message": "ⴈ ā´…ā´¸ā´ąāĩā´ąāĩ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹? ⴈ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´‚ ā´…ā´¸ā´ąāĩā´ąā´ŋā´¨āĩ† ā´¸āĩ†āĩŧā´ĩā´ąā´ŋā´¨āĩā´ąāĩ† ⴟāĩā´°ā´žā´ˇā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Žā´žā´ąāĩā´ąāĩā´‚, ā´•āĩ‚ā´Ÿā´žā´¤āĩ† ⴇⴤāĩ ā´Ēāĩā´°ā´žā´Ļāĩ‡ā´ļā´ŋā´•ā´Žā´žā´¯ā´ŋ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´Ŗāĩ‹ ā´Žā´¨āĩā´¨āĩ ⴚāĩ‹ā´Ļā´ŋā´•āĩā´•āĩā´•ā´¯āĩā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´‚", + "delete_action_prompt": "{count} ā´Žā´Ŗāĩā´Ŗā´‚ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´ŋ", + "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_remote": "ⴈ ⴇⴍⴙāĩā´™āĩž Immich ā´¸āĩ†āĩŧā´ĩā´ąā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´ļā´žā´ļāĩā´ĩā´¤ā´Žā´žā´¯ā´ŋ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´‚", + "delete_dialog_ok_force": "ā´Žā´¨āĩā´¤ā´žā´¯ā´žā´˛āĩā´‚ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´•", + "delete_dialog_title": "ā´ļā´žā´ļāĩā´ĩā´¤ā´Žā´žā´¯ā´ŋ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´•", + "delete_duplicates_confirmation": "ⴈ ā´Ąāĩā´¯āĩ‚ā´Ēāĩā´˛ā´ŋā´•āĩā´•āĩ‡ā´ąāĩā´ąāĩā´•āĩž ā´ļā´žā´ļāĩā´ĩā´¤ā´Žā´žā´¯ā´ŋ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹?", + "delete_face": "ā´Žāĩā´–ā´‚ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´•", + "delete_key": "ā´•āĩ€ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´•", + "delete_library": "ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´•", + "delete_link": "ā´˛ā´ŋā´™āĩā´•āĩ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´•", + "delete_local_action_prompt": "{count} ā´Žā´Ŗāĩā´Ŗā´‚ ā´Ēāĩā´°ā´žā´Ļāĩ‡ā´ļā´ŋā´•ā´Žā´žā´¯ā´ŋ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´ŋ", + "delete_local_dialog_ok_backed_up_only": "ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¤ā´ĩ ā´Žā´žā´¤āĩā´°ā´‚ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´•", + "delete_local_dialog_ok_force": "ā´Žā´¨āĩā´¤ā´žā´¯ā´žā´˛āĩā´‚ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´•", + "delete_others": "ā´Žā´ąāĩā´ąāĩā´ŗāĩā´ŗā´ĩ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´•", + "delete_permanently": "ā´ļā´žā´ļāĩā´ĩā´¤ā´Žā´žā´¯ā´ŋ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´•", + "delete_permanently_action_prompt": "{count} ā´Žā´Ŗāĩā´Ŗā´‚ ā´ļā´žā´ļāĩā´ĩā´¤ā´Žā´žā´¯ā´ŋ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´ŋ", + "delete_shared_link": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´˛ā´ŋā´™āĩā´•āĩ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´•", + "delete_shared_link_dialog_title": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´˛ā´ŋā´™āĩā´•āĩ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´•", + "delete_tag": "ā´Ÿā´žā´—āĩ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´•", + "delete_tag_confirmation_prompt": "{tagName} ā´Žā´¨āĩā´¨ ā´Ÿā´žā´—āĩ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹?", + "delete_user": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ† ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´•", + "deleted_shared_link": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´˛ā´ŋā´™āĩā´•āĩ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´ŋ", + "deletes_missing_assets": "ā´Ąā´ŋā´¸āĩā´•ā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´•ā´žā´Ŗā´žā´¤ā´žā´¯ ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "description": "ā´ĩā´ŋā´ĩā´°ā´Ŗā´‚", + "description_input_hint_text": "ā´ĩā´ŋā´ĩā´°ā´Ŗā´‚ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•...", + "description_input_submit_error": "ā´ĩā´ŋā´ĩā´°ā´Ŗā´‚ ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´ŋā´ļā´•āĩ, ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ ā´ĩā´ŋā´ĩā´°ā´™āĩā´™āĩžā´•āĩā´•āĩ ā´˛āĩ‹ā´—āĩ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´ŋā´•āĩā´•āĩā´•", + "deselect_all": "ā´Žā´˛āĩā´˛ā´žā´‚ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´¤āĩā´¤ā´¤āĩ ā´Žā´žā´ąāĩā´ąāĩā´•", + "details": "ā´ĩā´ŋā´ļā´Ļā´žā´‚ā´ļā´™āĩā´™āĩž", + "direction": "ā´Ļā´ŋā´ļ", + "disabled": "ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋⴤⴂ", + "disallow_edits": "ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´•āĩž ā´…ā´¨āĩā´ĩā´Ļā´ŋā´•āĩā´•ā´°āĩā´¤āĩ", + "discord": "ā´Ąā´ŋā´¸āĩā´•āĩ‹āĩŧā´Ąāĩ", + "discover": "ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤āĩā´•", + "discovered_devices": "ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´ŋā´¯ ā´‰ā´Ēā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "dismiss_all_errors": "ā´Žā´˛āĩā´˛ā´ž ā´Ēā´ŋā´ļā´•āĩā´•ā´ŗāĩā´‚ ⴤⴺāĩā´ŗā´ŋā´•āĩā´•ā´ŗā´¯āĩā´•", + "dismiss_error": "ā´Ēā´ŋā´ļā´•āĩ ⴤⴺāĩā´ŗā´ŋā´•āĩā´•ā´ŗā´¯āĩā´•", + "display_options": "ā´Ēāĩā´°ā´Ļāĩŧā´ļā´¨ ā´“ā´Ēāĩā´ˇā´¨āĩā´•āĩž", + "display_order": "ā´Ēāĩā´°ā´Ļāĩŧā´ļā´¨ ā´•āĩā´°ā´Žā´‚", + "display_original_photos": "ā´¯ā´Ĩā´žāĩŧā´¤āĩā´Ĩ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž ā´Ēāĩā´°ā´Ļāĩŧā´ļā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´•", + "display_original_photos_setting_description": "ā´¯ā´Ĩā´žāĩŧā´¤āĩā´Ĩ ā´…ā´¸ā´ąāĩā´ąāĩ ā´ĩāĩ†ā´Ŧāĩ-ā´…ā´¨āĩā´¯āĩ‹ā´œāĩā´¯ā´Žā´žā´•āĩā´Žāĩā´Ēāĩ‹āĩž, ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋā´˛āĩā´•āĩžā´•āĩā´•āĩ ā´Ēā´•ā´°ā´‚ ā´¯ā´Ĩā´žāĩŧā´¤āĩā´Ĩ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ ā´Ēāĩā´°ā´Ļāĩŧā´ļā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•ā´žāĩģ ā´Žāĩāĩģā´—ā´Ŗā´¨ ā´¨āĩŊā´•āĩā´•. ⴇⴤāĩ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ ā´Ēāĩā´°ā´Ļāĩŧā´ļā´¨ ā´ĩāĩ‡ā´—ā´¤ ā´•āĩā´ąā´¯āĩā´•āĩā´•ā´žāĩģ ā´‡ā´Ÿā´¯ā´žā´•āĩā´•āĩā´‚.", + "do_not_show_again": "ⴈ ⴏⴍāĩā´Ļāĩ‡ā´ļā´‚ ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩā´‚ ā´•ā´žā´Ŗā´ŋā´•āĩā´•ā´°āĩā´¤āĩ", + "documentation": "ā´Ąāĩ‹ā´•āĩā´¯āĩā´Žāĩ†ā´¨āĩā´ąāĩ‡ā´ˇāĩģ", + "done": "ā´Ēāĩ‚āĩŧā´¤āĩā´¤ā´ŋā´¯ā´žā´¯ā´ŋ", + "download": "ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ", + "download_action_prompt": "{count} ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ", + "download_canceled": "ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ā´ąā´Ļāĩā´Ļā´žā´•āĩā´•ā´ŋ", + "download_complete": "ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ā´Ēāĩ‚āĩŧā´¤āĩā´¤ā´ŋā´¯ā´žā´¯ā´ŋ", + "download_enqueue": "ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ā´•āĩā´¯āĩ‚ā´ĩā´ŋāĩŊ ⴚāĩ‡āĩŧā´¤āĩā´¤āĩ", + "download_error": "ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ā´Ēā´ŋā´ļā´•āĩ", + "download_failed": "ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "download_finished": "ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ā´•ā´´ā´ŋā´žāĩā´žāĩ", + "download_include_embedded_motion_videos": "ā´‰āĩžā´šāĩā´šāĩ‡āĩŧā´¤āĩā´¤ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•āĩž", + "download_include_embedded_motion_videos_description": "ⴚⴞā´ŋā´•āĩā´•āĩā´¨āĩā´¨ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗā´ŋāĩŊ ā´‰āĩžā´šāĩā´šāĩ‡āĩŧā´¤āĩā´¤ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•āĩž ā´’ā´°āĩ ā´Ēāĩā´°ā´¤āĩā´¯āĩ‡ā´• ā´Ģā´¯ā´˛ā´žā´¯ā´ŋ ā´‰āĩžā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¤āĩā´¤āĩā´•", + "download_notfound": "ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "download_paused": "ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ā´¤ā´žāĩŊā´•āĩā´•ā´žā´˛ā´ŋā´•ā´Žā´žā´¯ā´ŋ ā´¨ā´ŋāĩŧā´¤āĩā´¤ā´ŋ", + "download_settings": "ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "download_settings_description": "ā´…ā´¸ā´ąāĩā´ąāĩ ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩā´Žā´žā´¯ā´ŋ ā´Ŧā´¨āĩā´§ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "download_started": "ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ⴆⴰⴂⴭā´ŋⴚāĩā´šāĩ", + "download_sucess": "ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ā´ĩā´ŋⴜⴝā´ŋⴚāĩā´šāĩ", + "download_sucess_android": "ā´Žāĩ€ā´Ąā´ŋā´¯ DCIM/Immich ā´Žā´¨āĩā´¨ā´¤ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¤ā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "download_waiting_to_retry": "ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩā´‚ ā´ļāĩā´°ā´Žā´ŋā´•āĩā´•ā´žāĩģ ā´•ā´žā´¤āĩā´¤ā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "downloading": "ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ", + "downloading_asset_filename": "{filename} ā´Žā´¨āĩā´¨ ā´…ā´¸ā´ąāĩā´ąāĩ ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ", + "downloading_media": "ā´Žāĩ€ā´Ąā´ŋā´¯ ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ", + "drop_files_to_upload": "ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´Ģⴝⴞāĩā´•āĩž ā´Žā´ĩā´ŋⴟāĩ†ā´¯āĩā´‚ ā´Ąāĩā´°āĩ‹ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "duplicates": "ā´Ąāĩā´¯āĩ‚ā´Ēāĩā´˛ā´ŋā´•āĩā´•āĩ‡ā´ąāĩā´ąāĩā´•āĩž", + "duplicates_description": "ā´ā´¤ā´žā´Ŗāĩ ā´Ąāĩā´¯āĩ‚ā´Ēāĩā´˛ā´ŋā´•āĩā´•āĩ‡ā´ąāĩā´ąāĩ ā´Žā´¨āĩā´¨āĩ ā´¸āĩ‚ā´šā´ŋā´Ēāĩā´Ēā´ŋⴚāĩā´šāĩ ā´“ā´°āĩ‹ ā´—āĩā´°āĩ‚ā´Ēāĩā´Ēāĩā´‚ ā´Ēā´°ā´ŋā´šā´°ā´ŋā´•āĩā´•āĩā´•", + "duration": "ā´Ļāĩˆāĩŧⴘāĩā´¯ā´‚", + "edit": "ā´¤ā´ŋā´°āĩā´¤āĩā´¤āĩā´•", + "edit_album": "ā´†āĩŊā´Ŧā´‚ ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "edit_avatar": "ā´…ā´ĩā´¤ā´žāĩŧ ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "edit_birthday": "ⴜⴍāĩā´Žā´Ļā´ŋⴍⴂ ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "edit_date": "ā´¤āĩ€ā´¯ā´¤ā´ŋ ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "edit_date_and_time": "ā´¤āĩ€ā´¯ā´¤ā´ŋā´¯āĩā´‚ ā´¸ā´Žā´¯ā´ĩāĩā´‚ ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "edit_date_and_time_action_prompt": "{count} ā´Žā´Ŗāĩā´Ŗā´¤āĩā´¤ā´ŋā´¨āĩā´ąāĩ† ā´¤āĩ€ā´¯ā´¤ā´ŋā´¯āĩā´‚ ā´¸ā´Žā´¯ā´ĩāĩā´‚ ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¤āĩ", + "edit_date_and_time_by_offset": "ā´“ā´Ģāĩā´¸āĩ†ā´ąāĩā´ąāĩ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ā´¤āĩ€ā´¯ā´¤ā´ŋ ā´Žā´žā´ąāĩā´ąāĩā´•", + "edit_date_and_time_by_offset_interval": "ā´Ēāĩā´¤ā´ŋā´¯ ā´¤āĩ€ā´¯ā´¤ā´ŋ ā´Ēā´°ā´ŋā´§ā´ŋ: {from}-{to}", + "edit_description": "ā´ĩā´ŋā´ĩā´°ā´Ŗā´‚ ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "edit_description_prompt": "ā´Ļā´¯ā´ĩā´žā´¯ā´ŋ ā´’ā´°āĩ ā´Ēāĩā´¤ā´ŋā´¯ ā´ĩā´ŋā´ĩā´°ā´Ŗā´‚ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•:", + "edit_exclusion_pattern": "ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•āĩŊ ā´Ēā´žā´ąāĩā´ąāĩ‡āĩē ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "edit_faces": "ā´Žāĩā´–ā´™āĩā´™āĩž ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "edit_import_path": "ā´‡ā´Žāĩā´Ēāĩ‹āĩŧⴟāĩā´Ÿāĩ ā´Ēā´žā´¤āĩā´¤āĩ ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "edit_import_paths": "ā´‡ā´Žāĩā´Ēāĩ‹āĩŧⴟāĩā´Ÿāĩ ā´Ēā´žā´¤āĩā´¤āĩā´•āĩž ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "edit_key": "ā´•āĩ€ ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "edit_link": "ā´˛ā´ŋā´™āĩā´•āĩ ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "edit_location": "ā´¸āĩā´Ĩā´žā´¨ā´‚ ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "edit_location_action_prompt": "{count} ā´Žā´Ŗāĩā´Ŗā´¤āĩā´¤ā´ŋā´¨āĩā´ąāĩ† ā´¸āĩā´Ĩā´žā´¨ā´‚ ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¤āĩ", + "edit_location_dialog_title": "ā´¸āĩā´Ĩā´žā´¨ā´‚", + "edit_name": "ā´Ēāĩ‡ā´°āĩ ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "edit_people": "ⴆⴺāĩā´•ā´ŗāĩ† ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "edit_tag": "ā´Ÿā´žā´—āĩ ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "edit_title": "ā´ļāĩ€āĩŧⴎⴕⴂ ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "edit_user": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ† ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "edited": "ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¤āĩ", + "editor": "ā´Žā´Ąā´ŋā´ąāĩā´ąāĩŧ", + "editor_close_without_save_prompt": "ā´Žā´žā´ąāĩā´ąā´™āĩā´™āĩž ā´¸āĩ‡ā´ĩāĩ ⴚāĩ†ā´¯āĩā´¯ā´ŋā´˛āĩā´˛", + "editor_close_without_save_title": "ā´Žā´Ąā´ŋā´ąāĩā´ąāĩŧ ā´…ā´Ÿā´¯āĩā´•āĩā´•ā´Ŗāĩ‹?", + "editor_crop_tool_h2_aspect_ratios": "ā´ĩāĩ€ā´•āĩā´ˇā´Ŗā´žā´¨āĩā´Ēā´žā´¤ā´‚", + "editor_crop_tool_h2_rotation": "ā´ąāĩŠā´Ÿāĩā´Ÿāĩ‡ā´ˇāĩģ", + "email": "ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ", + "email_notifications": "ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ ā´…ā´ąā´ŋā´¯ā´ŋā´Ēāĩā´Ēāĩā´•āĩž", + "empty_folder": "ⴈ ā´Ģāĩ‹āĩžā´Ąāĩŧ ā´ļāĩ‚ā´¨āĩā´¯ā´Žā´žā´Ŗāĩ", + "empty_trash": "ⴟāĩā´°ā´žā´ˇāĩ ā´ļāĩ‚ā´¨āĩā´¯ā´Žā´žā´•āĩā´•āĩā´•", + "empty_trash_confirmation": "ⴟāĩā´°ā´žā´ˇāĩ ā´ļāĩ‚ā´¨āĩā´¯ā´Žā´žā´•āĩā´•ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹? ⴇⴤāĩ ⴟāĩā´°ā´žā´ˇā´ŋā´˛āĩ† ā´Žā´˛āĩā´˛ā´ž ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩā´‚ Immich-āĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´ļā´žā´ļāĩā´ĩā´¤ā´Žā´žā´¯ā´ŋ ā´¨āĩ€ā´•āĩā´•ā´‚ā´šāĩ†ā´¯āĩā´¯āĩā´‚.\nā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ⴈ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´‚ ā´Ēā´´ā´¯ā´Ēⴟā´ŋā´¯ā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛!", + "enable": "ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´•", + "enable_backup": "ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´•", + "enable_biometric_auth_description": "ā´Ŧā´¯āĩ‹ā´Žāĩ†ā´Ÿāĩā´°ā´ŋā´•āĩ ā´Ēāĩā´°ā´žā´Žā´žā´Ŗāĩ€ā´•ā´°ā´Ŗā´‚ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•ā´žāĩģ ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ ā´¨āĩŊā´•āĩā´•", + "enabled": "ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•ā´ŋ", + "end_date": "ā´…ā´ĩā´¸ā´žā´¨ ā´¤āĩ€ā´¯ā´¤ā´ŋ", + "enqueued": "ā´•āĩā´¯āĩ‚ā´ĩā´ŋāĩŊ ⴚāĩ‡āĩŧā´¤āĩā´¤āĩ", + "enter_wifi_name": "ā´ĩāĩˆ-ā´Ģāĩˆā´¯āĩā´Ÿāĩ† ā´Ēāĩ‡ā´°āĩ ā´¨āĩŊā´•āĩā´•", + "enter_your_pin_code": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ ā´¨āĩŊā´•āĩā´•", + "enter_your_pin_code_subtitle": "ā´˛āĩ‹ā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¤ ā´Ģāĩ‹āĩžā´Ąāĩŧ ⴆⴕāĩâ€Œā´¸ā´¸āĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ ā´¨āĩŊā´•āĩā´•", + "error": "ā´Ēā´ŋā´ļā´•āĩ", + "error_change_sort_album": "ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋā´¨āĩā´ąāĩ† ā´¸āĩ‹āĩŧⴟāĩā´Ÿāĩ ā´“āĩŧā´Ąāĩŧ ā´Žā´žā´ąāĩā´ąāĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "error_delete_face": "ā´…ā´¸ā´ąāĩā´ąā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´Žāĩā´–ā´‚ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´ŋā´ļā´•āĩ", + "error_getting_places": "ā´¸āĩā´Ĩⴞⴙāĩā´™āĩž ⴞⴭā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´ŋā´ļā´•āĩ", + "error_loading_image": "ⴚā´ŋā´¤āĩā´°ā´‚ ā´˛āĩ‹ā´Ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´ŋā´ļā´•āĩ", + "error_loading_partners": "ā´Ēā´™āĩā´•ā´žā´ŗā´ŋā´•ā´ŗāĩ† ā´˛āĩ‹ā´Ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´ŋā´ļā´•āĩ: {error}", + "error_saving_image": "ā´Ēā´ŋā´ļā´•āĩ: {error}", + "error_tag_face_bounding_box": "ā´Žāĩā´–ā´‚ ā´Ÿā´žā´—āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´ŋā´ļā´•āĩ - ā´Ŧāĩ—ā´Ŗāĩā´Ÿā´ŋā´‚ā´—āĩ ā´Ŧāĩ‹ā´•āĩā´¸āĩ ā´•āĩ‹āĩŧā´Ąā´ŋā´¨āĩ‡ā´ąāĩā´ąāĩā´•āĩž ⴞⴭā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´ŋā´˛āĩā´˛", + "error_title": "ā´Ēā´ŋā´ļā´•āĩ - ā´Žā´¨āĩā´¤āĩ‹ ā´•āĩā´´ā´Ēāĩā´Ēā´‚ ⴏⴂⴭā´ĩā´ŋⴚāĩā´šāĩ", + "errors": { + "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_get_faces": "ā´Žāĩā´–ā´™āĩā´™āĩž ⴞⴭā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´ŋā´˛āĩā´˛", + "cant_get_number_of_comments": "ā´…ā´­ā´ŋā´Ēāĩā´°ā´žā´¯ā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Žā´Ŗāĩā´Ŗā´‚ ⴞⴭā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´ŋā´˛āĩā´˛", + "cant_search_people": "ⴆⴺāĩā´•ā´ŗāĩ† ā´¤ā´ŋā´°ā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "cant_search_places": "ā´¸āĩā´Ĩⴞⴙāĩā´™āĩž ā´¤ā´ŋā´°ā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "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": "ā´Žā´˛āĩā´˛ā´ž ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩā´‚ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´ŋā´ļā´•āĩ", + "exclusion_pattern_already_exists": "ⴈ ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•āĩŊ ā´Ēā´žā´ąāĩā´ąāĩ‡āĩē ⴇⴤā´ŋⴍⴕⴂ ā´¨ā´ŋā´˛ā´ĩā´ŋā´˛āĩā´Ŗāĩā´Ÿāĩ.", + "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_load_notifications": "ā´…ā´ąā´ŋā´¯ā´ŋā´Ēāĩā´Ēāĩā´•āĩž ā´˛āĩ‹ā´Ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "failed_to_load_people": "ⴆⴺāĩā´•ā´ŗāĩ† ā´˛āĩ‹ā´Ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "failed_to_remove_product_key": "ā´Ēāĩā´°āĩŠā´Ąā´•āĩā´ąāĩā´ąāĩ ā´•āĩ€ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "failed_to_reset_pin_code": "ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ ā´ąāĩ€ā´¸āĩ†ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "failed_to_stack_assets": "ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´¸āĩā´ąāĩā´ąā´žā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "failed_to_unstack_assets": "ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´…āĩē-ā´¸āĩā´ąāĩā´ąā´žā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "failed_to_update_notification_status": "ā´…ā´ąā´ŋā´¯ā´ŋā´Ēāĩā´Ēā´ŋā´¨āĩā´ąāĩ† ā´¨ā´ŋā´˛ ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "import_path_already_exists": "ⴈ ā´‡ā´Žāĩā´Ēāĩ‹āĩŧⴟāĩā´Ÿāĩ ā´Ēā´žā´¤āĩā´¤āĩ ⴇⴤā´ŋⴍⴕⴂ ā´¨ā´ŋā´˛ā´ĩā´ŋā´˛āĩā´Ŗāĩā´Ÿāĩ.", + "incorrect_email_or_password": "ā´¤āĩ†ā´ąāĩā´ąā´žā´¯ ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ", + "paths_validation_failed": "{paths, plural, one {# ā´Ēā´žā´¤āĩā´¤āĩ} other {# ā´Ēā´žā´¤āĩā´¤āĩā´•āĩž}} ā´¸ā´žā´§āĩ‚ā´•ā´°ā´Ŗā´¤āĩā´¤ā´ŋāĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "profile_picture_transparent_pixels": "ā´Ēāĩā´°āĩŠā´ĢāĩˆāĩŊ ⴚā´ŋā´¤āĩā´°ā´™āĩā´™āĩžā´•āĩā´•āĩ ā´¸āĩā´¤ā´žā´°āĩā´¯ā´Žā´žā´¯ ā´Ēā´ŋā´•āĩā´¸ā´˛āĩā´•āĩž ⴉ⴪āĩā´Ÿā´žā´•ā´°āĩā´¤āĩ. ā´Ļā´¯ā´ĩā´žā´¯ā´ŋ ā´¸āĩ‚ā´‚ ā´‡āĩģ ⴚāĩ†ā´¯āĩā´¯āĩā´• ā´•āĩ‚ā´Ÿā´žā´¤āĩ†/ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ ⴚā´ŋā´¤āĩā´°ā´‚ ā´¨āĩ€ā´•āĩā´•āĩā´•.", + "quota_higher_than_disk_size": "ā´Ąā´ŋā´¸āĩā´•āĩ ā´ĩā´˛āĩā´Ēāĩā´Ēā´¤āĩā´¤āĩ‡ā´•āĩā´•ā´žāĩž ⴉⴝāĩŧā´¨āĩā´¨ ā´•āĩā´ĩā´žā´Ÿāĩā´Ÿ ā´¨ā´ŋā´™āĩā´™āĩž ⴏⴜāĩā´œā´Žā´žā´•āĩā´•ā´ŋā´¯ā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "something_went_wrong": "ā´Žā´¨āĩā´¤āĩ‹ ā´•āĩā´´ā´Ēāĩā´Ēā´‚ ⴏⴂⴭā´ĩā´ŋⴚāĩā´šāĩ", + "unable_to_add_album_users": "ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´•āĩā´•ā´ŗāĩ† ⴚāĩ‡āĩŧā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "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_archive_unarchive": "{archived, select, true {ā´†āĩŧā´•āĩā´•āĩˆā´ĩāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ} other {ā´…āĩēā´†āĩŧā´•āĩā´•āĩˆā´ĩāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ}} ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_change_album_user_role": "ā´†āĩŊā´Ŧā´‚ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩā´ąāĩ† ā´ąāĩ‹āĩž ā´Žā´žā´ąāĩā´ąā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_change_date": "ā´¤āĩ€ā´¯ā´¤ā´ŋ ā´Žā´žā´ąāĩā´ąā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_change_description": "ā´ĩā´ŋā´ĩā´°ā´Ŗā´‚ ā´Žā´žā´ąāĩā´ąā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_change_favorite": "ā´…ā´¸ā´ąāĩā´ąā´ŋā´¨āĩā´ąāĩ† ā´Ēāĩā´°ā´ŋā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿā´ĩ ā´Žā´žā´ąāĩā´ąā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_change_location": "ā´¸āĩā´Ĩā´žā´¨ā´‚ ā´Žā´žā´ąāĩā´ąā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_change_password": "ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´Žā´žā´ąāĩā´ąā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_change_visibility": "{count, plural, one {# ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´¯āĩā´Ÿāĩ†} other {# ⴆⴺāĩā´•ā´ŗāĩā´Ÿāĩ†}} ā´Ļāĩƒā´ļāĩā´¯ā´¤ ā´Žā´žā´ąāĩā´ąā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_complete_oauth_login": "OAuth ā´˛āĩ‹ā´—ā´ŋāĩģ ā´Ēāĩ‚āĩŧā´¤āĩā´¤ā´ŋā´¯ā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_connect": "ā´Ŧā´¨āĩā´§ā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_copy_to_clipboard": "ā´•āĩā´˛ā´ŋā´Ēāĩā´Ēāĩā´Ŧāĩ‹āĩŧā´Ąā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Ēā´•āĩŧā´¤āĩā´¤ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛, ā´¨ā´ŋā´™āĩā´™āĩž https ā´ĩā´´ā´ŋā´¯ā´žā´Ŗāĩ ā´Ēāĩ‡ā´œāĩ ⴆⴕāĩâ€Œā´¸ā´¸āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤āĩ†ā´¨āĩā´¨āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´•āĩā´•āĩā´•", + "unable_to_create_admin_account": "ā´…ā´Ąāĩā´Žā´ŋāĩģ ā´…ā´•āĩā´•āĩ—ā´Ŗāĩā´Ÿāĩ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_create_api_key": "ā´Ēāĩā´¤ā´ŋā´¯ API ā´•āĩ€ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_create_library": "ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_create_user": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ† ⴉ⴪āĩā´Ÿā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_delete_album": "ā´†āĩŊā´Ŧā´‚ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_delete_asset": "ā´…ā´¸ā´ąāĩā´ąāĩ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_delete_assets": "ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´ŋā´ļā´•āĩ", + "unable_to_delete_exclusion_pattern": "ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•āĩŊ ā´Ēā´žā´ąāĩā´ąāĩ‡āĩē ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_delete_import_path": "ā´‡ā´Žāĩā´Ēāĩ‹āĩŧⴟāĩā´Ÿāĩ ā´Ēā´žā´¤āĩā´¤āĩ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_delete_shared_link": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´˛ā´ŋā´™āĩā´•āĩ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_delete_user": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ† ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_download_files": "ā´Ģⴝⴞāĩā´•āĩž ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_edit_exclusion_pattern": "ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•āĩŊ ā´Ēā´žā´ąāĩā´ąāĩ‡āĩē ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_edit_import_path": "ā´‡ā´Žāĩā´Ēāĩ‹āĩŧⴟāĩā´Ÿāĩ ā´Ēā´žā´¤āĩā´¤āĩ ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_empty_trash": "ⴟāĩā´°ā´žā´ˇāĩ ā´ļāĩ‚ā´¨āĩā´¯ā´Žā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_enter_fullscreen": "ā´Ģāĩāĩžā´¸āĩā´•āĩā´°āĩ€ā´¨ā´ŋāĩŊ ā´Ēāĩā´°ā´ĩāĩ‡ā´ļā´ŋā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_exit_fullscreen": "ā´Ģāĩāĩžā´¸āĩā´•āĩā´°āĩ€ā´¨ā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´Ēāĩā´ąā´¤āĩā´¤āĩā´•ā´Ÿā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_get_comments_number": "ā´…ā´­ā´ŋā´Ēāĩā´°ā´žā´¯ā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Žā´Ŗāĩā´Ŗā´‚ ⴞⴭā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´ŋā´˛āĩā´˛", + "unable_to_get_shared_link": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´˛ā´ŋā´™āĩā´•āĩ ⴞⴭā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "unable_to_hide_person": "ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´¯āĩ† ā´Žā´ąā´¯āĩā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_link_motion_video": "ⴚⴞā´ŋā´•āĩā´•āĩā´¨āĩā´¨ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ ā´˛ā´ŋā´™āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_link_oauth_account": "OAuth ā´…ā´•āĩā´•āĩ—ā´Ŗāĩā´Ÿāĩ ā´˛ā´ŋā´™āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "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_refresh_user": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ† ā´Ēāĩā´¤āĩā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_remove_album_users": "ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´•āĩā´•ā´ŗāĩ† ā´¨āĩ€ā´•āĩā´•ā´‚ā´šāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_remove_api_key": "API ā´•āĩ€ ā´¨āĩ€ā´•āĩā´•ā´‚ā´šāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_remove_assets_from_shared_link": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´˛ā´ŋā´™āĩā´•ā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´¨āĩ€ā´•āĩā´•ā´‚ā´šāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_remove_library": "ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ ā´¨āĩ€ā´•āĩā´•ā´‚ā´šāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_remove_partner": "ā´Ēā´™āĩā´•ā´žā´ŗā´ŋā´¯āĩ† ā´¨āĩ€ā´•āĩā´•ā´‚ā´šāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_remove_reaction": "ā´Ēāĩā´°ā´¤ā´ŋā´•ā´°ā´Ŗā´‚ ā´¨āĩ€ā´•āĩā´•ā´‚ā´šāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_reset_password": "ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´ąāĩ€ā´¸āĩ†ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_reset_pin_code": "ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ ā´ąāĩ€ā´¸āĩ†ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_resolve_duplicate": "ā´Ąāĩā´¯āĩ‚ā´Ēāĩā´˛ā´ŋā´•āĩā´•āĩ‡ā´ąāĩā´ąāĩ ā´Ēā´°ā´ŋā´šā´°ā´ŋā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_restore_assets": "ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´Ēāĩā´¨ā´ƒā´¸āĩā´Ĩā´žā´Ēā´ŋā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_restore_trash": "ⴟāĩā´°ā´žā´ˇāĩ ā´Ēāĩā´¨ā´ƒā´¸āĩā´Ĩā´žā´Ēā´ŋā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_restore_user": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ† ā´Ēāĩā´¨ā´ƒā´¸āĩā´Ĩā´žā´Ēā´ŋā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_save_album": "ā´†āĩŊā´Ŧā´‚ ā´¸āĩ‡ā´ĩāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_save_api_key": "API ā´•āĩ€ ā´¸āĩ‡ā´ĩāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_save_date_of_birth": "ⴜⴍⴍⴤāĩā´¤āĩ€ā´¯ā´¤ā´ŋ ā´¸āĩ‡ā´ĩāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_save_name": "ā´Ēāĩ‡ā´°āĩ ā´¸āĩ‡ā´ĩāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_save_profile": "ā´Ēāĩā´°āĩŠā´ĢāĩˆāĩŊ ā´¸āĩ‡ā´ĩāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_save_settings": "ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´¸āĩ‡ā´ĩāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_scan_libraries": "ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋā´•āĩž ā´¸āĩā´•ā´žāĩģ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_scan_library": "ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ ā´¸āĩā´•ā´žāĩģ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_set_feature_photo": "ā´Ģāĩ€ā´šāĩā´šāĩŧ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ ⴏⴜāĩā´œā´Žā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_set_profile_picture": "ā´Ēāĩā´°āĩŠā´ĢāĩˆāĩŊ ⴚā´ŋā´¤āĩā´°ā´‚ ⴏⴜāĩā´œā´Žā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_submit_job": "ⴜāĩ‹ā´˛ā´ŋ ā´¸ā´Žāĩŧā´Ēāĩā´Ēā´ŋā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_trash_asset": "ā´…ā´¸ā´ąāĩā´ąāĩ ⴟāĩā´°ā´žā´ˇāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_unlink_account": "ā´…ā´•āĩā´•āĩ—ā´Ŗāĩā´Ÿāĩ ā´…āĩēā´˛ā´ŋā´™āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_unlink_motion_video": "ⴚⴞā´ŋā´•āĩā´•āĩā´¨āĩā´¨ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ ā´…āĩēā´˛ā´ŋā´™āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_update_album_cover": "ā´†āĩŊā´Ŧā´‚ ā´•ā´ĩāĩŧ ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_update_album_info": "ā´†āĩŊā´Ŧā´‚ ā´ĩā´ŋā´ĩā´°ā´™āĩā´™āĩž ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_update_library": "ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_update_location": "ā´¸āĩā´Ĩā´žā´¨ā´‚ ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_update_settings": "ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_update_timeline_display_status": "ⴟāĩˆā´‚ā´˛āĩˆāĩģ ā´Ēāĩā´°ā´Ļāĩŧā´ļā´¨ ā´¨ā´ŋā´˛ ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_update_user": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ† ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_upload_file": "ā´Ģā´¯āĩŊ ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛" + }, + "exif": "Exif", + "exif_bottom_sheet_description": "ā´ĩā´ŋā´ĩā´°ā´Ŗā´‚ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•...", + "exif_bottom_sheet_description_error": "ā´ĩā´ŋā´ĩā´°ā´Ŗā´‚ ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´ŋā´ļā´•āĩ", + "exif_bottom_sheet_details": "ā´ĩā´ŋā´ļā´Ļā´žā´‚ā´ļā´™āĩā´™āĩž", + "exif_bottom_sheet_location": "ā´¸āĩā´Ĩā´žā´¨ā´‚", + "exif_bottom_sheet_people": "ⴆⴺāĩā´•āĩž", + "exif_bottom_sheet_person_add_person": "ā´Ēāĩ‡ā´°āĩ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", + "exit_slideshow": "ā´¸āĩā´˛āĩˆā´Ąāĩâ€Œā´ˇāĩ‹ā´¯ā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´Ēāĩā´ąā´¤āĩā´¤āĩā´•ā´Ÿā´•āĩā´•āĩā´•", + "expand_all": "ā´Žā´˛āĩā´˛ā´žā´‚ ā´ĩā´ŋā´•ā´¸ā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´•", + "experimental_settings_new_asset_list_subtitle": "ā´Ēāĩā´°āĩ‹ā´—ā´¤ā´ŋā´¯ā´ŋā´˛ā´žā´Ŗāĩ", + "experimental_settings_new_asset_list_title": "ā´Ēā´°āĩ€ā´•āĩā´ˇā´Ŗā´žā´Ÿā´ŋā´¸āĩā´Ĩā´žā´¨ā´¤āĩā´¤ā´ŋā´˛āĩā´ŗāĩā´ŗ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ ā´—āĩā´°ā´ŋā´Ąāĩ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´•", + "experimental_settings_subtitle": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´¸āĩā´ĩā´¨āĩā´¤ā´‚ ⴉⴤāĩā´¤ā´°ā´ĩā´žā´Ļā´ŋā´¤āĩā´ĩā´¤āĩā´¤ā´ŋāĩŊ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•!", + "experimental_settings_title": "ā´Ēā´°āĩ€ā´•āĩā´ˇā´Ŗā´žā´Ÿā´ŋā´¸āĩā´Ĩā´žā´¨ā´¤āĩā´¤ā´ŋā´˛āĩā´ŗāĩā´ŗā´¤āĩ", + "expire_after": "ⴇⴤā´ŋā´¨āĩ ā´ļāĩ‡ā´ˇā´‚ ā´•ā´žā´˛ā´šā´°ā´Ŗā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´‚", + "expired": "ā´•ā´žā´˛ā´šā´°ā´Ŗā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "expires_date": "{date}-ā´¨āĩ ā´•ā´žā´˛ā´šā´°ā´Ŗā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´‚", + "explore": "ā´Ēā´°āĩā´¯ā´ĩāĩ‡ā´•āĩā´ˇā´Ŗā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "explorer": "ā´Žā´•āĩā´¸āĩā´Ēāĩā´˛āĩ‹ā´ąāĩŧ", + "export": "ā´•ā´¯ā´ąāĩā´ąāĩā´Žā´¤ā´ŋ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "export_as_json": "JSON ⴆⴝā´ŋ ā´•ā´¯ā´ąāĩā´ąāĩā´Žā´¤ā´ŋ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "export_database": "ā´Ąā´žā´ąāĩā´ąā´žā´Ŧāĩ‡ā´¸āĩ ā´•ā´¯ā´ąāĩā´ąāĩā´Žā´¤ā´ŋ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "export_database_description": "SQLite ā´Ąā´žā´ąāĩā´ąā´žā´Ŧāĩ‡ā´¸āĩ ā´•ā´¯ā´ąāĩā´ąāĩā´Žā´¤ā´ŋ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "extension": "ā´Žā´•āĩā´¸āĩā´ąāĩā´ąāĩģā´ˇāĩģ", + "external": "ā´Ŧā´žā´šāĩā´¯ā´‚", + "external_libraries": "ā´Ŧā´žā´šāĩā´¯ ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋā´•āĩž", + "external_network": "ā´Ŧā´žā´šāĩā´¯ ā´¨āĩ†ā´ąāĩā´ąāĩâ€Œā´ĩāĩŧā´•āĩā´•āĩ", + "external_network_sheet_info": "ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´¤āĩā´¤ ā´ĩāĩˆ-ā´Ģāĩˆ ā´¨āĩ†ā´ąāĩā´ąāĩâ€Œā´ĩāĩŧā´•āĩā´•ā´ŋāĩŊ ā´…ā´˛āĩā´˛ā´žā´¤āĩā´¤ā´Ēāĩā´Ēāĩ‹āĩž, ā´¤ā´žā´´āĩ† ā´¨āĩŊā´•ā´ŋā´¯ā´ŋⴟāĩā´Ÿāĩā´ŗāĩā´ŗ URL-ā´•ā´ŗā´ŋāĩŊ ā´†ā´Ļāĩā´¯ā´‚ ⴞⴭāĩā´¯ā´Žā´žā´•āĩā´¨āĩā´¨ ā´’ā´¨āĩā´¨ā´ŋā´˛āĩ‚ā´Ÿāĩ†, ā´Žāĩā´•ā´ŗā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´¤ā´žā´´āĩ‡ā´•āĩā´•āĩā´ŗāĩā´ŗ ā´•āĩā´°ā´Žā´¤āĩā´¤ā´ŋāĩŊ, ā´†ā´Ēāĩā´Ēāĩ ā´¸āĩ†āĩŧā´ĩā´ąāĩā´Žā´žā´¯ā´ŋ ā´Ŧā´¨āĩā´§ā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´‚", + "face_unassigned": "ā´…ā´¸āĩˆāĩģ ⴚāĩ†ā´¯āĩā´¤ā´ŋⴟāĩā´Ÿā´ŋā´˛āĩā´˛", + "failed": "ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "failed_to_authenticate": "ā´Ēāĩā´°ā´žā´Žā´žā´Ŗāĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "failed_to_load_assets": "ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´˛āĩ‹ā´Ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "failed_to_load_folder": "ā´Ģāĩ‹āĩžā´Ąāĩŧ ā´˛āĩ‹ā´Ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "favorite": "ā´Ēāĩā´°ā´ŋⴝⴂ", + "favorite_action_prompt": "{count} ā´Žā´Ŗāĩā´Ŗā´‚ ā´Ēāĩā´°ā´ŋā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿā´ĩā´¯ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ⴚāĩ‡āĩŧā´¤āĩā´¤āĩ", + "favorite_or_unfavorite_photo": "ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ ā´Ēāĩā´°ā´ŋā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿā´¤ā´žā´•āĩā´•āĩā´• ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ ā´Žā´žā´ąāĩā´ąāĩā´•", + "favorites": "ā´Ēāĩā´°ā´ŋⴝⴙāĩā´™āĩž", + "favorites_page_no_favorites": "ā´Ēāĩā´°ā´ŋā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿ ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩŠā´¨āĩā´¨āĩā´‚ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "feature_photo_updated": "ā´Ģāĩ€ā´šāĩā´šāĩŧ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "features": "ā´Ģāĩ€ā´šāĩā´šā´ąāĩā´•āĩž", + "features_in_development": "ā´ĩā´ŋā´•ā´¸ā´ŋā´Ēāĩā´Ēā´ŋⴚāĩā´šāĩā´•āĩŠā´Ŗāĩā´Ÿā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ ā´Ģāĩ€ā´šāĩā´šā´ąāĩā´•āĩž", + "features_setting_description": "ā´†ā´Ēāĩā´Ēāĩ ā´Ģāĩ€ā´šāĩā´šā´ąāĩā´•āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "file_name": "ā´Ģⴝⴞā´ŋā´¨āĩā´ąāĩ† ā´Ēāĩ‡ā´°āĩ", + "file_name_or_extension": "ā´Ģⴝⴞā´ŋā´¨āĩā´ąāĩ† ā´Ēāĩ‡ā´°āĩ ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ ā´Žā´•āĩā´¸āĩā´ąāĩā´ąāĩģā´ˇāĩģ", + "filename": "ā´Ģā´¯āĩŊā´¨ā´žā´Žā´‚", + "filetype": "ā´Ģā´¯āĩŊ ⴤⴰⴂ", + "filter": "ā´Ģā´ŋāĩŊⴟāĩā´Ÿāĩŧ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "filter_people": "ⴆⴺāĩā´•ā´ŗāĩ† ā´Ģā´ŋāĩŊⴟāĩā´Ÿāĩŧ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "filter_places": "ā´¸āĩā´Ĩⴞⴙāĩā´™āĩž ā´Ģā´ŋāĩŊⴟāĩā´Ÿāĩŧ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "find_them_fast": "ā´¤ā´ŋⴰⴝⴞā´ŋā´˛āĩ‚ā´Ÿāĩ† ā´Ēāĩ‡ā´°āĩ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ā´…ā´ĩā´°āĩ† ā´ĩāĩ‡ā´—ā´¤āĩā´¤ā´ŋāĩŊ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤āĩā´•", + "first": "ā´†ā´Ļāĩā´¯ā´‚", + "fix_incorrect_match": "ā´¤āĩ†ā´ąāĩā´ąā´žā´¯ ā´ĒāĩŠā´°āĩā´¤āĩā´¤ā´‚ ā´ļā´°ā´ŋā´¯ā´žā´•āĩā´•āĩā´•", + "folder": "ā´Ģāĩ‹āĩžā´Ąāĩŧ", + "folder_not_found": "ā´Ģāĩ‹āĩžā´Ąāĩŧ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "folders": "ā´Ģāĩ‹āĩžā´Ąā´ąāĩā´•āĩž", + "folders_feature_description": "ā´Ģā´¯āĩŊ ā´¸ā´ŋā´¸āĩā´ąāĩā´ąā´¤āĩā´¤ā´ŋā´˛āĩ† ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩžā´•āĩā´•āĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•āĩžā´•āĩā´•āĩā´Žā´žā´¯ā´ŋ ā´Ģāĩ‹āĩžā´Ąāĩŧ ā´•ā´žā´´āĩâ€Œā´š ā´Ŧāĩā´°āĩ—ā´¸āĩā´šāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ", + "forgot_pin_code_question": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ēā´ŋāĩģ ā´Žā´ąā´¨āĩā´¨āĩ‹?", + "forward": "ā´Žāĩā´¨āĩā´¨āĩ‹ā´Ÿāĩā´Ÿāĩ", + "gcast_enabled": "ā´—āĩ‚ā´—ā´ŋāĩž ā´•ā´žā´¸āĩā´ąāĩā´ąāĩ", + "gcast_enabled_description": "ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋā´¨ā´žā´¯ā´ŋ ⴈ ā´Ģāĩ€ā´šāĩā´šāĩŧ ā´—āĩ‚ā´—ā´ŋā´ŗā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´Ŧā´žā´šāĩā´¯ ā´‰ā´ąā´ĩā´ŋā´Ÿā´™āĩā´™āĩž ā´˛āĩ‹ā´Ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ.", + "general": "ā´ĒāĩŠā´¤āĩā´ĩā´žā´¯ā´¤āĩ", + "geolocation_instruction_location": "ā´˛āĩŠā´•āĩā´•āĩ‡ā´ˇāĩģ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ GPS ā´•āĩ‹āĩŧā´Ąā´ŋā´¨āĩ‡ā´ąāĩā´ąāĩā´•ā´ŗāĩā´ŗāĩā´ŗ ā´’ā´°āĩ ā´…ā´¸ā´ąāĩā´ąā´ŋāĩŊ ā´•āĩā´˛ā´ŋā´•āĩā´•āĩā´šāĩ†ā´¯āĩā´¯āĩā´•, ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ ā´Žā´žā´Ēāĩā´Ēā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´¨āĩ‡ā´°ā´ŋⴟāĩā´Ÿāĩ ā´’ā´°āĩ ā´¸āĩā´Ĩⴞⴂ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "get_help": "ā´¸ā´šā´žā´¯ā´‚ ā´¨āĩ‡ā´Ÿāĩā´•", + "get_wifiname_error": "ā´ĩāĩˆ-ā´Ģāĩˆā´¯āĩā´Ÿāĩ† ā´Ēāĩ‡ā´°āĩ ⴞⴭā´ŋⴚāĩā´šā´ŋā´˛āĩā´˛. ā´¨ā´ŋā´™āĩā´™āĩž ā´†ā´ĩā´ļāĩā´¯ā´Žā´žā´¯ ā´…ā´¨āĩā´Žā´¤ā´ŋā´•āĩž ā´¨āĩŊā´•ā´ŋā´¯ā´ŋⴟāĩā´Ÿāĩā´Ŗāĩā´Ÿāĩ†ā´¨āĩā´¨āĩā´‚ ā´’ā´°āĩ ā´ĩāĩˆ-ā´Ģāĩˆ ā´¨āĩ†ā´ąāĩā´ąāĩâ€Œā´ĩāĩŧā´•āĩā´•ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´•ā´Ŗā´•āĩā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩâ€Œā´¤ā´ŋⴟāĩā´Ÿāĩā´Ŗāĩā´Ÿāĩ†ā´¨āĩā´¨āĩā´‚ ā´‰ā´ąā´Ēāĩā´Ēā´žā´•āĩā´•āĩā´•", + "getting_started": "ⴆⴰⴂⴭā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "go_back": "ā´Ēā´ŋā´¨āĩā´¨āĩ‹ā´Ÿāĩā´Ÿāĩ ā´Ēāĩ‹ā´•āĩā´•", + "go_to_folder": "ā´Ģāĩ‹āĩžā´Ąā´ąā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Ēāĩ‹ā´•āĩā´•", + "go_to_search": "ā´¤ā´ŋⴰⴝⴞā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Ēāĩ‹ā´•āĩā´•", + "gps": "ⴜā´ŋā´Ēā´ŋā´Žā´¸āĩ", + "gps_missing": "GPS ⴇⴞāĩā´˛", + "grant_permission": "ā´…ā´¨āĩā´Žā´¤ā´ŋ ā´¨āĩŊā´•āĩā´•", + "group_albums_by": "ā´†āĩŊā´Ŧā´™āĩā´™ā´ŗāĩ† ⴇⴤⴍāĩā´¸ā´°ā´ŋⴚāĩā´šāĩ ā´—āĩā´°āĩ‚ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•...", + "group_country": "ā´°ā´žā´œāĩā´¯ā´‚ ā´…ā´¨āĩā´¸ā´°ā´ŋⴚāĩā´šāĩ ā´—āĩā´°āĩ‚ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "group_no": "ā´—āĩā´°āĩ‚ā´Ēāĩā´Ēā´ŋā´‚ā´—āĩ ⴇⴞāĩā´˛", + "group_owner": "ā´‰ā´Ÿā´Ž ā´…ā´¨āĩā´¸ā´°ā´ŋⴚāĩā´šāĩ ā´—āĩā´°āĩ‚ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "group_places_by": "ā´¸āĩā´Ĩⴞⴙāĩā´™ā´ŗāĩ† ⴇⴤⴍāĩā´¸ā´°ā´ŋⴚāĩā´šāĩ ā´—āĩā´°āĩ‚ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•...", + "group_year": "ā´ĩāĩŧⴎⴂ ā´…ā´¨āĩā´¸ā´°ā´ŋⴚāĩā´šāĩ ā´—āĩā´°āĩ‚ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "haptic_feedback_switch": "ā´šā´žā´Ēāĩā´ąāĩā´ąā´ŋā´•āĩ ā´Ģāĩ€ā´Ąāĩâ€Œā´Ŧā´žā´•āĩā´•āĩ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´•", + "haptic_feedback_title": "ā´šā´žā´Ēāĩā´ąāĩā´ąā´ŋā´•āĩ ā´Ģāĩ€ā´Ąāĩâ€Œā´Ŧā´žā´•āĩā´•āĩ", + "has_quota": "ā´•āĩā´ĩā´žā´Ÿāĩā´Ÿā´¯āĩā´Ŗāĩā´Ÿāĩ", + "hash_asset": "ā´…ā´¸ā´ąāĩā´ąāĩ ā´šā´žā´ˇāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "hashed_assets": "ā´šā´žā´ˇāĩ ⴚāĩ†ā´¯āĩā´¤ ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž", + "hashing": "ā´šā´žā´ˇā´ŋā´‚ā´—āĩ", + "header_settings_add_header_tip": "ā´šāĩ†ā´Ąāĩŧ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", + "header_settings_field_validator_msg": "ā´Žāĩ‚ā´˛āĩā´¯ā´‚ ā´ļāĩ‚ā´¨āĩā´¯ā´Žā´žā´•ā´°āĩā´¤āĩ", + "header_settings_header_name_input": "ā´šāĩ†ā´Ąā´ąā´ŋā´¨āĩā´ąāĩ† ā´Ēāĩ‡ā´°āĩ", + "header_settings_header_value_input": "ā´šāĩ†ā´Ąā´ąā´ŋā´¨āĩā´ąāĩ† ā´Žāĩ‚ā´˛āĩā´¯ā´‚", + "headers_settings_tile_subtitle": "ā´“ā´°āĩ‹ ā´¨āĩ†ā´ąāĩā´ąāĩâ€Œā´ĩāĩŧā´•āĩā´•āĩ ā´…ā´­āĩā´¯āĩŧā´¤āĩā´Ĩⴍⴝāĩâ€Œā´•āĩā´•āĩŠā´Ēāĩā´Ēā´ĩāĩā´‚ ā´†ā´Ēāĩā´Ēāĩ ⴅⴝⴝāĩâ€Œā´•āĩā´•āĩ‡ā´Ŗāĩā´Ÿ ā´Ēāĩā´°āĩ‹ā´•āĩā´¸ā´ŋ ā´šāĩ†ā´Ąā´ąāĩā´•āĩž ā´¨ā´ŋāĩŧā´ĩⴚā´ŋā´•āĩā´•āĩā´•", + "headers_settings_tile_title": "ā´•ā´¸āĩā´ąāĩā´ąā´‚ ā´Ēāĩā´°āĩ‹ā´•āĩā´¸ā´ŋ ā´šāĩ†ā´Ąā´ąāĩā´•āĩž", + "hi_user": "ā´¨ā´Žā´¸āĩā´•ā´žā´°ā´‚ {name} ({email})", + "hide_all_people": "ā´Žā´˛āĩā´˛ā´ž ⴆⴺāĩā´•ā´ŗāĩ†ā´¯āĩā´‚ ā´Žā´ąā´¯āĩā´•āĩā´•āĩā´•", + "hide_gallery": "ā´—ā´žā´˛ā´ąā´ŋ ā´Žā´ąā´¯āĩā´•āĩā´•āĩā´•", + "hide_named_person": "{name} ā´Žā´¨āĩā´¨ ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´¯āĩ† ā´Žā´ąā´¯āĩā´•āĩā´•āĩā´•", + "hide_password": "ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´Žā´ąā´¯āĩā´•āĩā´•āĩā´•", + "hide_person": "ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´¯āĩ† ā´Žā´ąā´¯āĩā´•āĩā´•āĩā´•", + "hide_unnamed_people": "ā´Ēāĩ‡ā´°ā´ŋā´˛āĩā´˛ā´žā´¤āĩā´¤ ⴆⴺāĩā´•ā´ŗāĩ† ā´Žā´ąā´¯āĩā´•āĩā´•āĩā´•", + "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_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_first_time_notice": "ā´¨ā´ŋā´™āĩā´™āĩž ā´†ā´Ļāĩā´¯ā´Žā´žā´¯ā´ŋⴟāĩā´Ÿā´žā´Ŗāĩ ⴈ ā´†ā´Ēāĩā´Ēāĩ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤āĩ†ā´™āĩā´•ā´ŋāĩŊ, ā´’ā´°āĩ ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ā´†āĩŊā´Ŧā´‚ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´¨āĩā´¨ā´¤āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´•āĩā´•āĩā´•, ā´…ā´¤āĩā´ĩā´´ā´ŋ ⴟāĩˆā´‚ā´˛āĩˆā´¨ā´ŋāĩŊ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´‚ ⴚāĩ‡āĩŧā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯āĩā´‚", + "home_page_locked_error_local": "ā´Ēāĩā´°ā´žā´Ļāĩ‡ā´ļā´ŋā´• ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´˛āĩ‹ā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¤ ā´Ģāĩ‹āĩžā´Ąā´ąā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Žā´žā´ąāĩā´ąā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛, ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "home_page_locked_error_partner": "ā´Ēā´™āĩā´•ā´žā´ŗā´ŋā´¯āĩā´Ÿāĩ† ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´˛āĩ‹ā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¤ ā´Ģāĩ‹āĩžā´Ąā´ąā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Žā´žā´ąāĩā´ąā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛, ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "home_page_share_err_local": "ā´Ēāĩā´°ā´žā´Ļāĩ‡ā´ļā´ŋā´• ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´˛ā´ŋā´™āĩā´•āĩ ā´ĩā´´ā´ŋ ā´Ēā´™āĩā´•ā´ŋā´Ÿā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛, ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "home_page_upload_err_limit": "ā´’ā´°āĩ ā´¸ā´Žā´¯ā´‚ ā´Ēā´°ā´Žā´žā´ĩā´§ā´ŋ 30 ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´Žā´žā´¤āĩā´°ā´Žāĩ‡ ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯āĩ‚, ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "host": "ā´šāĩ‹ā´¸āĩā´ąāĩā´ąāĩ", + "hour": "ā´Žā´Ŗā´ŋā´•āĩā´•āĩ‚āĩŧ", + "hours": "ā´Žā´Ŗā´ŋā´•āĩā´•āĩ‚ā´ąāĩā´•āĩž", + "id": "ā´ā´Ąā´ŋ", + "idle": "ā´¨ā´ŋā´ˇāĩâ€Œā´•āĩā´°ā´ŋⴝⴂ", + "ignore_icloud_photos": "iCloud ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž ā´…ā´ĩā´—ā´Ŗā´ŋā´•āĩā´•āĩā´•", + "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 {ⴚā´ŋā´¤āĩā´°ā´‚}}", + "image_alt_text_date_2_people": "{date}-ā´¨āĩ {person1}, {person2} ā´Žā´¨āĩā´¨ā´ŋā´ĩāĩŧā´•āĩā´•āĩŠā´Ēāĩā´Ēā´‚ ā´Žā´Ÿāĩā´¤āĩā´¤ {isVideo, select, true {ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹} other {ⴚā´ŋā´¤āĩā´°ā´‚}}", + "image_alt_text_date_3_people": "{date}-ā´¨āĩ {person1}, {person2}, {person3} ā´Žā´¨āĩā´¨ā´ŋā´ĩāĩŧā´•āĩā´•āĩŠā´Ēāĩā´Ēā´‚ ā´Žā´Ÿāĩā´¤āĩā´¤ {isVideo, select, true {ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹} other {ⴚā´ŋā´¤āĩā´°ā´‚}}", + "image_alt_text_date_4_or_more_people": "{date}-ā´¨āĩ {person1}, {person2}, ā´•āĩ‚ā´Ÿā´žā´¤āĩ† ā´Žā´ąāĩā´ąāĩ {additionalCount, number} ā´Ēāĩ‡āĩŧā´•āĩā´•āĩā´ŽāĩŠā´Ēāĩā´Ēā´‚ ā´Žā´Ÿāĩā´¤āĩā´¤ {isVideo, select, true {ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹} other {ⴚā´ŋā´¤āĩā´°ā´‚}}", + "image_alt_text_date_place": "{date}-ā´¨āĩ {city}, {country} ā´Žā´¨āĩā´¨ā´ŋā´ĩā´ŋā´Ÿā´™āĩā´™ā´ŗā´ŋāĩŊ ā´ĩāĩ†ā´šāĩā´šāĩ ā´Žā´Ÿāĩā´¤āĩā´¤ {isVideo, select, true {ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹} other {ⴚā´ŋā´¤āĩā´°ā´‚}}", + "image_alt_text_date_place_1_person": "{date}-ā´¨āĩ {city}, {country} ā´Žā´¨āĩā´¨ā´ŋā´ĩā´ŋā´Ÿā´™āĩā´™ā´ŗā´ŋāĩŊ ā´ĩāĩ†ā´šāĩā´šāĩ {person1}-ā´¨āĩŠā´Ēāĩā´Ēā´‚ ā´Žā´Ÿāĩā´¤āĩā´¤ {isVideo, select, true {ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹} other {ⴚā´ŋā´¤āĩā´°ā´‚}}", + "image_alt_text_date_place_2_people": "{date}-ā´¨āĩ {city}, {country} ā´Žā´¨āĩā´¨ā´ŋā´ĩā´ŋā´Ÿā´™āĩā´™ā´ŗā´ŋāĩŊ ā´ĩāĩ†ā´šāĩā´šāĩ {person1}, {person2} ā´Žā´¨āĩā´¨ā´ŋā´ĩāĩŧā´•āĩā´•āĩŠā´Ēāĩā´Ēā´‚ ā´Žā´Ÿāĩā´¤āĩā´¤ {isVideo, select, true {ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹} other {ⴚā´ŋā´¤āĩā´°ā´‚}}", + "image_alt_text_date_place_3_people": "{date}-ā´¨āĩ {city}, {country} ā´Žā´¨āĩā´¨ā´ŋā´ĩā´ŋā´Ÿā´™āĩā´™ā´ŗā´ŋāĩŊ ā´ĩāĩ†ā´šāĩā´šāĩ {person1}, {person2}, {person3} ā´Žā´¨āĩā´¨ā´ŋā´ĩāĩŧā´•āĩā´•āĩŠā´Ēāĩā´Ēā´‚ ā´Žā´Ÿāĩā´¤āĩā´¤ {isVideo, select, true {ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹} other {ⴚā´ŋā´¤āĩā´°ā´‚}}", + "image_alt_text_date_place_4_or_more_people": "{date}-ā´¨āĩ {city}, {country} ā´Žā´¨āĩā´¨ā´ŋā´ĩā´ŋā´Ÿā´™āĩā´™ā´ŗā´ŋāĩŊ ā´ĩāĩ†ā´šāĩā´šāĩ {person1}, {person2}, ā´•āĩ‚ā´Ÿā´žā´¤āĩ† ā´Žā´ąāĩā´ąāĩ {additionalCount, number} ā´Ēāĩ‡āĩŧā´•āĩā´•āĩā´ŽāĩŠā´Ēāĩā´Ēā´‚ ā´Žā´Ÿāĩā´¤āĩā´¤ {isVideo, select, true {ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹} other {ⴚā´ŋā´¤āĩā´°ā´‚}}", + "image_saved_successfully": "ⴚā´ŋā´¤āĩā´°ā´‚ ā´¸āĩ‡ā´ĩāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "image_viewer_page_state_provider_download_started": "ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ⴆⴰⴂⴭā´ŋⴚāĩā´šāĩ", + "image_viewer_page_state_provider_download_success": "ā´Ąāĩ—āĩēā´˛āĩ‹ā´Ąāĩ ā´ĩā´ŋⴜⴝā´ŋⴚāĩā´šāĩ", + "image_viewer_page_state_provider_share_error": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´ŋā´ļā´•āĩ", + "immich_logo": "Immich ā´˛āĩ‹ā´—āĩ‹", + "immich_web_interface": "Immich ā´ĩāĩ†ā´Ŧāĩ ⴇⴍāĩā´ąāĩŧā´Ģāĩ‡ā´¸āĩ", + "import_from_json": "JSON-āĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´‡ā´Žāĩā´Ēāĩ‹āĩŧⴟāĩā´Ÿāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "import_path": "ā´‡ā´Žāĩā´Ēāĩ‹āĩŧⴟāĩā´Ÿāĩ ā´Ēā´žā´¤āĩā´¤āĩ", + "in_albums": "{count, plural, one {# ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋāĩŊ} other {# ā´†āĩŊā´Ŧā´™āĩā´™ā´ŗā´ŋāĩŊ}}", + "in_archive": "ā´†āĩŧā´•āĩā´•āĩˆā´ĩā´ŋāĩŊ", + "include_archived": "ā´†āĩŧā´•āĩā´•āĩˆā´ĩāĩā´šāĩ†ā´¯āĩâ€Œā´¤ā´ĩ ā´‰āĩžā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¤āĩā´¤āĩā´•", + "include_shared_albums": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´†āĩŊā´Ŧā´™āĩā´™āĩž ā´‰āĩžā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¤āĩā´¤āĩā´•", + "include_shared_partner_assets": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´Ēā´™āĩā´•ā´žā´ŗā´ŋā´¯āĩā´Ÿāĩ† ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´‰āĩžā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¤āĩā´¤āĩā´•", + "individual_share": "ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´—ā´¤ ā´Ēā´™āĩā´•ā´ŋⴟāĩŊ", + "individual_shares": "ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´—ā´¤ ā´Ēā´™āĩā´•ā´ŋⴟⴞāĩā´•āĩž", + "info": "ā´ĩā´ŋā´ĩā´°ā´™āĩā´™āĩž", + "interval": { + "day_at_onepm": "ā´Žā´˛āĩā´˛ā´ž ā´Ļā´ŋā´ĩā´¸ā´ĩāĩā´‚ ā´‰ā´šāĩā´šā´¯āĩā´•āĩā´•āĩ 1 ā´Žā´Ŗā´ŋā´•āĩā´•āĩ", + "hours": "{hours, plural, one {ā´“ā´°āĩ‹ ā´Žā´Ŗā´ŋā´•āĩā´•āĩ‚ā´ąā´ŋā´˛āĩā´‚} other {ā´“ā´°āĩ‹ {hours, number} ā´Žā´Ŗā´ŋā´•āĩā´•āĩ‚ā´ąā´ŋā´˛āĩā´‚}}", + "night_at_midnight": "ā´Žā´˛āĩā´˛ā´ž ā´°ā´žā´¤āĩā´°ā´ŋā´¯āĩā´‚ ā´…āĩŧā´Ļāĩā´§ā´°ā´žā´¤āĩā´°ā´ŋā´•āĩā´•āĩ", + "night_at_twoam": "ā´Žā´˛āĩā´˛ā´ž ā´°ā´žā´¤āĩā´°ā´ŋā´¯āĩā´‚ ā´Ēāĩā´˛āĩŧⴚāĩā´šāĩ† 2 ā´Žā´Ŗā´ŋā´•āĩā´•āĩ" + }, + "invalid_date": "ā´…ā´¸ā´žā´§āĩā´ĩā´žā´¯ ā´¤āĩ€ā´¯ā´¤ā´ŋ", + "invalid_date_format": "ā´…ā´¸ā´žā´§āĩā´ĩā´žā´¯ ā´¤āĩ€ā´¯ā´¤ā´ŋ ā´Ģāĩ‹āĩŧā´Žā´žā´ąāĩā´ąāĩ", + "invite_people": "ⴆⴺāĩā´•ā´ŗāĩ† ā´•āĩā´ˇā´Ŗā´ŋā´•āĩā´•āĩā´•", + "invite_to_album": "ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´•āĩā´ˇā´Ŗā´ŋā´•āĩā´•āĩā´•", + "ios_debug_info_fetch_ran_at": "ā´Ģāĩ†ā´šāĩā´šāĩ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋⴚāĩā´šā´¤āĩ {dateTime}", + "ios_debug_info_last_sync_at": "ā´…ā´ĩā´¸ā´žā´¨ ā´¸ā´ŋā´™āĩā´•āĩ {dateTime}", + "ios_debug_info_no_processes_queued": "ā´Ēā´ļāĩā´šā´žā´¤āĩā´¤ā´˛ ā´Ēāĩā´°āĩ‹ā´¸ā´¸āĩā´¸āĩā´•ā´ŗāĩŠā´¨āĩā´¨āĩā´‚ ā´•āĩā´¯āĩ‚ā´ĩā´ŋāĩŊ ⴇⴞāĩā´˛", + "ios_debug_info_no_sync_yet": "ā´Ēā´ļāĩā´šā´žā´¤āĩā´¤ā´˛ ā´¸ā´ŋā´™āĩā´•āĩ ⴜāĩ‹ā´˛ā´ŋ ⴇⴤāĩā´ĩā´°āĩ† ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋⴚāĩā´šā´ŋⴟāĩā´Ÿā´ŋā´˛āĩā´˛", + "ios_debug_info_processes_queued": "{count, plural, one {{count} ā´Ēā´ļāĩā´šā´žā´¤āĩā´¤ā´˛ ā´Ēāĩā´°āĩ‹ā´¸ā´¸āĩā´¸āĩ ā´•āĩā´¯āĩ‚ā´ĩā´ŋā´˛āĩā´Ŗāĩā´Ÿāĩ} other {{count} ā´Ēā´ļāĩā´šā´žā´¤āĩā´¤ā´˛ ā´Ēāĩā´°āĩ‹ā´¸ā´¸āĩā´¸āĩā´•āĩž ā´•āĩā´¯āĩ‚ā´ĩā´ŋā´˛āĩā´Ŗāĩā´Ÿāĩ}}", + "ios_debug_info_processing_ran_at": "ā´Ēāĩā´°āĩ‹ā´¸ā´¸āĩā´¸ā´ŋā´‚ā´—āĩ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋⴚāĩā´šā´¤āĩ {dateTime}", + "items_count": "{count, plural, one {# ⴇⴍⴂ} other {# ⴇⴍⴙāĩā´™āĩž}}", + "jobs": "ⴜāĩ‹ā´˛ā´ŋā´•āĩž", + "keep": "ā´¸āĩ‚ā´•āĩā´ˇā´ŋā´•āĩā´•āĩā´•", + "keep_all": "ā´Žā´˛āĩā´˛ā´žā´‚ ā´¸āĩ‚ā´•āĩā´ˇā´ŋā´•āĩā´•āĩā´•", + "keep_this_delete_others": "ⴇⴤāĩ ā´¸āĩ‚ā´•āĩā´ˇā´ŋⴚāĩā´šāĩ ā´Žā´ąāĩā´ąāĩā´ŗāĩā´ŗā´ĩ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´•", + "kept_this_deleted_others": "ⴈ ā´…ā´¸ā´ąāĩā´ąāĩ ā´¸āĩ‚ā´•āĩā´ˇā´ŋā´•āĩā´•āĩā´•ā´¯āĩā´‚ {count, plural, one {# ā´…ā´¸ā´ąāĩā´ąāĩ} other {# ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž}} ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´•ā´¯āĩā´‚ ⴚāĩ†ā´¯āĩā´¤āĩ", + "keyboard_shortcuts": "ā´•āĩ€ā´Ŧāĩ‹āĩŧā´Ąāĩ ā´•āĩā´ąāĩā´•āĩā´•āĩā´ĩā´´ā´ŋā´•āĩž", + "language": "ā´­ā´žā´ˇ", + "language_no_results_subtitle": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´¤ā´ŋā´°ā´¯āĩŊ ā´Ēā´Ļā´‚ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´ŋⴚāĩā´šāĩ ā´ļāĩā´°ā´Žā´ŋā´•āĩā´•āĩā´•", + "language_no_results_title": "ā´­ā´žā´ˇā´•ā´ŗāĩŠā´¨āĩā´¨āĩā´‚ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "language_search_hint": "ā´­ā´žā´ˇā´•āĩžā´•āĩā´•ā´žā´¯ā´ŋ ā´¤ā´ŋā´°ā´¯āĩā´•...", + "language_setting_description": "ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•ā´ŋā´ˇāĩā´Ÿā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿ ā´­ā´žā´ˇ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "large_files": "ā´ĩā´˛ā´ŋā´¯ ā´Ģⴝⴞāĩā´•āĩž", + "last": "ā´…ā´ĩā´¸ā´žā´¨ā´¤āĩā´¤āĩ‡ā´¤āĩ", + "last_seen": "ā´…ā´ĩā´¸ā´žā´¨ā´‚ ā´•ā´Ŗāĩā´Ÿā´¤āĩ", + "latest_version": "ā´ā´ąāĩā´ąā´ĩāĩā´‚ ā´Ēāĩā´¤ā´ŋā´¯ ā´Ēā´¤ā´ŋā´Ēāĩā´Ēāĩ", + "latitude": "ā´…ā´•āĩā´ˇā´žā´‚ā´ļā´‚", + "leave": "ā´ĩā´ŋⴟāĩā´•", + "leave_album": "ā´†āĩŊā´Ŧā´‚ ā´ĩā´ŋⴟāĩā´•", + "lens_model": "ā´˛āĩ†āĩģā´¸āĩ ā´Žāĩ‹ā´ĄāĩŊ", + "let_others_respond": "ā´Žā´ąāĩā´ąāĩā´ŗāĩā´ŗā´ĩā´°āĩ† ā´Ēāĩā´°ā´¤ā´ŋā´•ā´°ā´ŋā´•āĩā´•ā´žāĩģ ā´…ā´¨āĩā´ĩā´Ļā´ŋā´•āĩā´•āĩā´•", + "level": "ⴤⴞⴂ", + "library": "ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ", + "library_options": "ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ ā´“ā´Ēāĩā´ˇā´¨āĩā´•āĩž", + "library_page_device_albums": "ā´‰ā´Ēā´•ā´°ā´Ŗā´¤āĩā´¤ā´ŋā´˛āĩ† ā´†āĩŊā´Ŧā´™āĩā´™āĩž", + "library_page_new_album": "ā´Ēāĩā´¤ā´ŋā´¯ ā´†āĩŊā´Ŧā´‚", + "library_page_sort_asset_count": "ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩā´Ÿāĩ† ā´Žā´Ŗāĩā´Ŗā´‚", + "library_page_sort_created": "ā´¸āĩƒā´ˇāĩā´Ÿā´ŋⴚāĩā´š ā´¤āĩ€ā´¯ā´¤ā´ŋ", + "library_page_sort_last_modified": "ā´…ā´ĩā´¸ā´žā´¨ā´‚ ā´Žā´žā´ąāĩā´ąā´‚ ā´ĩā´°āĩā´¤āĩā´¤ā´ŋⴝⴤāĩ", + "library_page_sort_title": "ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋā´¨āĩā´ąāĩ† ā´ļāĩ€āĩŧⴎⴕⴂ", + "licenses": "ā´˛āĩˆā´¸āĩģā´¸āĩā´•āĩž", + "light": "ā´˛āĩˆā´ąāĩā´ąāĩ", + "like": "ⴇⴎāĩā´Ÿā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "like_deleted": "ⴇⴎāĩā´Ÿā´‚ ā´¨āĩ€ā´•āĩā´•ā´‚ā´šāĩ†ā´¯āĩā´¤āĩ", + "link_motion_video": "ⴚⴞā´ŋā´•āĩā´•āĩā´¨āĩā´¨ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ ā´˛ā´ŋā´™āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "link_to_oauth": "OAuth-ā´˛āĩ‡ā´•āĩā´•āĩ ā´˛ā´ŋā´™āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "linked_oauth_account": "ā´˛ā´ŋā´™āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¤ OAuth ā´…ā´•āĩā´•āĩ—ā´Ŗāĩā´Ÿāĩ", + "list": "ā´˛ā´ŋā´¸āĩā´ąāĩā´ąāĩ", + "loading": "ā´˛āĩ‹ā´Ąā´ŋā´‚ā´—āĩ", + "loading_search_results_failed": "ā´¤ā´ŋā´°ā´¯āĩŊ ā´Ģⴞⴙāĩā´™āĩž ā´˛āĩ‹ā´Ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "local": "ā´Ēāĩā´°ā´žā´Ļāĩ‡ā´ļā´ŋā´•ā´‚", + "local_asset_cast_failed": "ā´¸āĩ†āĩŧā´ĩā´ąā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žā´¤āĩā´¤ ā´’ā´°āĩ ā´…ā´¸ā´ąāĩā´ąāĩ ā´•ā´žā´¸āĩā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "local_assets": "ā´Ēāĩā´°ā´žā´Ļāĩ‡ā´ļā´ŋā´• ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž", + "local_media_summary": "ā´Ēāĩā´°ā´žā´Ļāĩ‡ā´ļā´ŋā´• ā´Žāĩ€ā´Ąā´ŋā´¯ ⴏⴂⴗāĩā´°ā´šā´‚", + "local_network": "ā´Ēāĩā´°ā´žā´Ļāĩ‡ā´ļā´ŋā´• ā´¨āĩ†ā´ąāĩā´ąāĩâ€Œā´ĩāĩŧā´•āĩā´•āĩ", + "local_network_sheet_info": "ā´¨ā´ŋāĩŧā´Ļāĩā´Ļā´ŋā´ˇāĩâ€Œā´Ÿ ā´ĩāĩˆ-ā´Ģāĩˆ ā´¨āĩ†ā´ąāĩā´ąāĩâ€Œā´ĩāĩŧā´•āĩā´•āĩ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´Žāĩā´Ēāĩ‹āĩž ⴈ URL ā´ĩā´´ā´ŋ ā´†ā´Ēāĩā´Ēāĩ ā´¸āĩ†āĩŧā´ĩā´ąāĩā´Žā´žā´¯ā´ŋ ā´Ŧā´¨āĩā´§ā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´‚", + "location_permission": "ā´˛āĩŠā´•āĩā´•āĩ‡ā´ˇāĩģ ā´…ā´¨āĩā´Žā´¤ā´ŋ", + "location_permission_content": "ā´¯ā´žā´¨āĩā´¤āĩā´°ā´ŋā´•-ā´¸āĩā´ĩā´ŋⴚāĩā´šā´ŋā´‚ā´—āĩ ā´Ģāĩ€ā´šāĩā´šāĩŧ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ, Immich-ā´¨āĩ ā´•āĩƒā´¤āĩā´¯ā´Žā´žā´¯ ā´˛āĩŠā´•āĩā´•āĩ‡ā´ˇāĩģ ā´…ā´¨āĩā´Žā´¤ā´ŋ ā´†ā´ĩā´ļāĩā´¯ā´Žā´žā´Ŗāĩ, ā´…ā´¤āĩā´ĩā´´ā´ŋ ā´¨ā´ŋā´˛ā´ĩā´ŋā´˛āĩ† ā´ĩāĩˆ-ā´Ģāĩˆ ā´¨āĩ†ā´ąāĩā´ąāĩâ€Œā´ĩāĩŧā´•āĩā´•ā´ŋā´¨āĩā´ąāĩ† ā´Ēāĩ‡ā´°āĩ ā´ĩā´žā´¯ā´ŋā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯āĩā´‚", + "location_picker_choose_on_map": "ā´Žā´žā´Ēāĩā´Ēā´ŋāĩŊ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "location_picker_latitude_error": "ā´¸ā´žā´§āĩā´ĩā´žā´¯ ā´…ā´•āĩā´ˇā´žā´‚ā´ļā´‚ ā´¨āĩŊā´•āĩā´•", + "location_picker_latitude_hint": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´…ā´•āĩā´ˇā´žā´‚ā´ļā´‚ ā´‡ā´ĩā´ŋⴟāĩ† ā´¨āĩŊā´•āĩā´•", + "location_picker_longitude_error": "ā´¸ā´žā´§āĩā´ĩā´žā´¯ ā´°āĩ‡ā´–ā´žā´‚ā´ļā´‚ ā´¨āĩŊā´•āĩā´•", + "location_picker_longitude_hint": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´°āĩ‡ā´–ā´žā´‚ā´ļā´‚ ā´‡ā´ĩā´ŋⴟāĩ† ā´¨āĩŊā´•āĩā´•", + "lock": "ā´˛āĩ‹ā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "locked_folder": "ā´˛āĩ‹ā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¤ ā´Ģāĩ‹āĩžā´Ąāĩŧ", + "log_detail_title": "ā´˛āĩ‹ā´—āĩ ā´ĩā´ŋā´ļā´Ļā´žā´‚ā´ļā´‚", + "log_out": "ā´˛āĩ‹ā´—āĩ ā´”ā´Ÿāĩā´Ÿāĩ", + "log_out_all_devices": "ā´Žā´˛āĩā´˛ā´ž ā´‰ā´Ēā´•ā´°ā´Ŗā´™āĩā´™ā´ŗā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩā´‚ ā´˛āĩ‹ā´—āĩ ā´”ā´Ÿāĩā´Ÿāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "logged_in_as": "{user} ⴆⴝā´ŋ ā´˛āĩ‹ā´—ā´ŋāĩģ ⴚāĩ†ā´¯āĩā´¤āĩ", + "logged_out_all_devices": "ā´Žā´˛āĩā´˛ā´ž ā´‰ā´Ēā´•ā´°ā´Ŗā´™āĩā´™ā´ŗā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩā´‚ ā´˛āĩ‹ā´—āĩ ā´”ā´Ÿāĩā´Ÿāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "logged_out_device": "ā´‰ā´Ēā´•ā´°ā´Ŗā´¤āĩā´¤ā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´˛āĩ‹ā´—āĩ ā´”ā´Ÿāĩā´Ÿāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "login": "ā´˛āĩ‹ā´—ā´ŋāĩģ", + "login_disabled": "ā´˛āĩ‹ā´—ā´ŋāĩģ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•ā´ŋ", + "login_form_api_exception": "API ā´Žā´•āĩā´¸āĩ†ā´Ēāĩā´ˇāĩģ. ā´Ļā´¯ā´ĩā´žā´¯ā´ŋ ā´¸āĩ†āĩŧā´ĩāĩŧ URL ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´ŋⴚāĩā´šāĩ ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩā´‚ ā´ļāĩā´°ā´Žā´ŋā´•āĩā´•āĩā´•.", + "login_form_back_button_text": "ā´¤ā´ŋā´°ā´ŋā´•āĩ†", + "login_form_email_hint": "youremail@email.com", + "login_form_endpoint_hint": "http://your-server-ip:port", + "login_form_endpoint_url": "ā´¸āĩ†āĩŧā´ĩāĩŧ ā´Žāĩģā´Ąāĩâ€Œā´Ēāĩ‹ā´¯ā´ŋā´¨āĩā´ąāĩ URL", + "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_failed_get_oauth_server_disable": "ⴈ ā´¸āĩ†āĩŧā´ĩā´ąā´ŋāĩŊ OAuth ā´Ģāĩ€ā´šāĩā´šāĩŧ ⴞⴭāĩā´¯ā´Žā´˛āĩā´˛", + "login_form_failed_login": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩ† ā´˛āĩ‹ā´—ā´ŋāĩģ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´ŋā´ļā´•āĩ, ā´¸āĩ†āĩŧā´ĩāĩŧ URL, ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ, ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´Žā´¨āĩā´¨ā´ŋā´ĩ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´ŋā´•āĩā´•āĩā´•", + "login_form_handshake_exception": "ā´¸āĩ†āĩŧā´ĩā´ąāĩā´Žā´žā´¯ā´ŋ ā´’ā´°āĩ ā´šā´žāĩģā´Ąāĩâ€Œā´ˇāĩ‡ā´•āĩā´•āĩ ā´Žā´•āĩā´¸āĩ†ā´Ēāĩā´ˇāĩģ ⴉ⴪āĩā´Ÿā´žā´¯ā´ŋ. ā´¨ā´ŋā´™āĩā´™āĩž ā´’ā´°āĩ ā´¸āĩā´ĩⴝⴂ ā´’ā´Ēāĩā´Ēā´ŋⴟāĩā´Ÿ ā´¸āĩŧⴟāĩā´Ÿā´ŋā´Ģā´ŋā´•āĩā´•ā´ąāĩā´ąā´žā´Ŗāĩ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤āĩ†ā´™āĩā´•ā´ŋāĩŊ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™ā´ŗā´ŋāĩŊ ā´¸āĩā´ĩⴝⴂ ā´’ā´Ēāĩā´Ēā´ŋⴟāĩā´Ÿ ā´¸āĩŧⴟāĩā´Ÿā´ŋā´Ģā´ŋā´•āĩā´•ā´ąāĩā´ąāĩ ā´Ēā´ŋā´¨āĩā´¤āĩā´Ŗ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´•.", + "login_form_password_hint": "ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ", + "login_form_save_login": "ā´˛āĩ‹ā´—ā´ŋāĩģ ⴆⴝā´ŋ ā´¤āĩā´Ÿā´°āĩā´•", + "login_form_server_empty": "ā´’ā´°āĩ ā´¸āĩ†āĩŧā´ĩāĩŧ URL ā´¨āĩŊā´•āĩā´•.", + "login_form_server_error": "ā´¸āĩ†āĩŧā´ĩā´ąā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´•ā´Ŗā´•āĩā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´žāĩā´žā´ŋā´˛āĩā´˛.", + "login_has_been_disabled": "ā´˛āĩ‹ā´—ā´ŋāĩģ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•ā´ŋ.", + "login_password_changed_error": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´’ā´°āĩ ā´Ēā´ŋā´ļā´•āĩā´Ŗāĩā´Ÿā´žā´¯ā´ŋ", + "login_password_changed_success": "ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´ĩā´ŋā´œā´¯ā´•ā´°ā´Žā´žā´¯ā´ŋ ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "logout_all_device_confirmation": "ā´Žā´˛āĩā´˛ā´ž ā´‰ā´Ēā´•ā´°ā´Ŗā´™āĩā´™ā´ŗā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩā´‚ ā´˛āĩ‹ā´—āĩ ā´”ā´Ÿāĩā´Ÿāĩ ⴚāĩ†ā´¯āĩā´¯ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹?", + "logout_this_device_confirmation": "ⴈ ā´‰ā´Ēā´•ā´°ā´Ŗā´¤āĩā´¤ā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´˛āĩ‹ā´—āĩ ā´”ā´Ÿāĩā´Ÿāĩ ⴚāĩ†ā´¯āĩā´¯ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹?", + "logs": "ā´˛āĩ‹ā´—āĩā´•āĩž", + "longitude": "ā´°āĩ‡ā´–ā´žā´‚ā´ļā´‚", + "look": "ā´•ā´žā´´āĩā´š", + "loop_videos": "ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•āĩž ā´˛āĩ‚ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "loop_videos_description": "ā´ĩā´ŋā´ļā´Ļā´žā´‚ā´ļ ā´ĩāĩā´¯āĩ‚ā´ĩā´ąā´ŋāĩŊ ā´’ā´°āĩ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ ā´¯ā´žā´¨āĩā´¤āĩā´°ā´ŋā´•ā´Žā´žā´¯ā´ŋ ā´˛āĩ‚ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´•.", + "main_branch_warning": "ā´¨ā´ŋā´™āĩā´™āĩž ā´’ā´°āĩ ā´Ąāĩ†ā´ĩā´˛ā´Ēāĩâ€Œā´Žāĩ†ā´¨āĩā´ąāĩ ā´Ēā´¤ā´ŋā´Ēāĩā´Ēā´žā´Ŗāĩ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤āĩ; ā´’ā´°āĩ ā´ąā´ŋā´˛āĩ€ā´¸āĩ ā´Ēā´¤ā´ŋā´Ēāĩā´Ēāĩ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•ā´žāĩģ ā´žā´™āĩā´™āĩž ā´ļā´•āĩā´¤ā´Žā´žā´¯ā´ŋ ā´ļāĩā´Ēā´žāĩŧā´ļ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ!", + "main_menu": "ā´Ēāĩā´°ā´§ā´žā´¨ ā´Žāĩ†ā´¨āĩ", + "make": "ā´¨ā´ŋāĩŧā´Žāĩā´Žā´žā´¤ā´žā´ĩāĩ", + "manage_geolocation": "ā´¸āĩā´Ĩā´žā´¨ā´‚ ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "manage_shared_links": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´˛ā´ŋā´™āĩā´•āĩā´•āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "manage_sharing_with_partners": "ā´Ēā´™āĩā´•ā´žā´ŗā´ŋā´•ā´ŗāĩā´Žā´žā´¯āĩā´ŗāĩā´ŗ ā´Ēā´™āĩā´•ā´ŋⴟāĩŊ ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "manage_the_app_settings": "ā´†ā´Ēāĩā´Ēāĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "manage_your_account": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´…ā´•āĩā´•āĩ—ā´Ŗāĩā´Ÿāĩ ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "manage_your_api_keys": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† API ā´•āĩ€ā´•āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "manage_your_devices": "ā´¨ā´ŋā´™āĩā´™āĩž ā´˛āĩ‹ā´—ā´ŋāĩģ ⴚāĩ†ā´¯āĩā´¤ ā´‰ā´Ēā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "manage_your_oauth_connection": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† OAuth ā´•ā´Ŗā´•āĩā´ˇāĩģ ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "map": "ā´Žā´žā´Ēāĩā´Ēāĩ", + "map_assets_in_bounds": "{count, plural, =0 {ⴈ ā´Ēāĩā´°ā´Ļāĩ‡ā´ļā´¤āĩā´¤āĩ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩŠā´¨āĩā´¨āĩā´Žā´ŋā´˛āĩā´˛} one {# ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹} other {# ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž}}", + "map_cannot_get_user_location": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩā´ąāĩ† ā´¸āĩā´Ĩā´žā´¨ā´‚ ⴞⴭā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´ŋā´˛āĩā´˛", + "map_location_dialog_yes": "ā´…ā´¤āĩ†", + "map_location_picker_page_use_location": "ⴈ ā´¸āĩā´Ĩⴞⴂ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•", + "map_location_service_disabled_content": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´¨ā´ŋā´˛ā´ĩā´ŋā´˛āĩ† ā´¸āĩā´Ĩā´žā´¨ā´¤āĩā´¤āĩ ā´¨ā´ŋā´¨āĩā´¨āĩā´ŗāĩā´ŗ ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´Ēāĩā´°ā´Ļāĩŧā´ļā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ ā´˛āĩŠā´•āĩā´•āĩ‡ā´ˇāĩģ ā´¸āĩ‡ā´ĩⴍⴂ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩ‡ā´Ŗāĩā´Ÿā´¤āĩā´Ŗāĩā´Ÿāĩ. ā´‡ā´Ēāĩā´Ēāĩ‹āĩž ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•ā´Ŗāĩ‹?", + "map_location_service_disabled_title": "ā´˛āĩŠā´•āĩā´•āĩ‡ā´ˇāĩģ ā´¸āĩ‡ā´ĩⴍⴂ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•ā´ŋ", + "map_marker_for_images": "{city}, {country} ā´Žā´¨āĩā´¨ā´ŋā´ĩā´ŋā´Ÿā´™āĩā´™ā´ŗā´ŋāĩŊ ā´Žā´Ÿāĩā´¤āĩā´¤ ⴚā´ŋā´¤āĩā´°ā´™āĩā´™āĩžā´•āĩā´•āĩā´ŗāĩā´ŗ ā´Žā´žā´Ēāĩā´Ēāĩ ā´Žā´žāĩŧā´•āĩā´•āĩŧ", + "map_marker_with_image": "ⴚā´ŋā´¤āĩā´°ā´¤āĩā´¤āĩ‹ā´Ÿāĩā´•āĩ‚ā´Ÿā´ŋā´¯ ā´Žā´žā´Ēāĩā´Ēāĩ ā´Žā´žāĩŧā´•āĩā´•āĩŧ", + "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": "ā´•ā´´ā´ŋā´žāĩā´ž {days} ā´Ļā´ŋā´ĩⴏⴙāĩā´™āĩž", + "map_settings_date_range_option_year": "ā´•ā´´ā´ŋā´žāĩā´ž ā´ĩāĩŧⴎⴂ", + "map_settings_date_range_option_years": "ā´•ā´´ā´ŋā´žāĩā´ž {years} ā´ĩāĩŧⴎⴙāĩā´™āĩž", + "map_settings_dialog_title": "ā´Žā´žā´Ēāĩā´Ēāĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "map_settings_include_show_archived": "ā´†āĩŧā´•āĩā´•āĩˆā´ĩāĩā´šāĩ†ā´¯āĩâ€Œā´¤ā´ĩ ā´‰āĩžā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¤āĩā´¤āĩā´•", + "map_settings_include_show_partners": "ā´Ēā´™āĩā´•ā´žā´ŗā´ŋā´•ā´ŗāĩ† ā´‰āĩžā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¤āĩā´¤āĩā´•", + "map_settings_only_show_favorites": "ā´Ēāĩā´°ā´ŋā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿā´ĩ ā´Žā´žā´¤āĩā´°ā´‚ ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•", + "map_settings_theme_settings": "ā´Žā´žā´Ēāĩā´Ēāĩ ā´¤āĩ€ā´‚", + "map_zoom_to_see_photos": "ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž ā´•ā´žā´Ŗā´žāĩģ ā´¸āĩ‚ā´‚ ā´”ā´Ÿāĩā´Ÿāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "mark_all_as_read": "ā´Žā´˛āĩā´˛ā´žā´‚ ā´ĩā´žā´¯ā´ŋⴚāĩā´šā´¤ā´žā´¯ā´ŋ ā´…ā´Ÿā´¯ā´žā´ŗā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¤āĩā´¤āĩā´•", + "mark_as_read": "ā´ĩā´žā´¯ā´ŋⴚāĩā´šā´¤ā´žā´¯ā´ŋ ā´…ā´Ÿā´¯ā´žā´ŗā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¤āĩā´¤āĩā´•", + "marked_all_as_read": "ā´Žā´˛āĩā´˛ā´žā´‚ ā´ĩā´žā´¯ā´ŋⴚāĩā´šā´¤ā´žā´¯ā´ŋ ā´…ā´Ÿā´¯ā´žā´ŗā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¤āĩā´¤ā´ŋ", + "matches": "ⴚāĩ‡āĩŧⴚāĩā´šā´•āĩž", + "matching_assets": "ⴚāĩ‡āĩŧⴚāĩā´šā´¯āĩā´ŗāĩā´ŗ ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž", + "media_type": "ā´Žāĩ€ā´Ąā´ŋā´¯ ⴤⴰⴂ", + "memories": "ā´“āĩŧā´Žāĩā´Žā´•āĩž", + "memories_all_caught_up": "ā´Žā´˛āĩā´˛ā´žā´‚ ā´•ā´Ŗāĩā´Ÿāĩā´¤āĩ€āĩŧā´¤āĩā´¤āĩ", + "memories_check_back_tomorrow": "ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ ā´“āĩŧā´Žāĩā´Žā´•āĩžā´•āĩā´•ā´žā´¯ā´ŋ ā´¨ā´žā´ŗāĩ† ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩā´‚ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´ŋā´•āĩā´•āĩā´•", + "memories_setting_description": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´“āĩŧā´Žāĩā´Žā´•ā´ŗā´ŋāĩŊ ā´¨ā´ŋā´™āĩā´™āĩž ā´•ā´žā´Ŗāĩā´¨āĩā´¨ā´¤āĩ ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "memories_start_over": "ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩā´‚ ā´¤āĩā´Ÿā´™āĩā´™āĩā´•", + "memories_swipe_to_close": "ā´…ā´Ÿā´¯āĩā´•āĩā´•ā´žāĩģ ā´Žāĩā´•ā´ŗā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´¸āĩā´ĩāĩˆā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "memory": "ā´Žāĩ†ā´Žāĩā´Žā´ąā´ŋ", + "memory_lane_title": "ā´“āĩŧā´Žāĩā´Žā´•ā´ŗāĩā´Ÿāĩ† ā´Ēā´žā´¤ {title}", + "menu": "ā´Žāĩ†ā´¨āĩ", + "merge": "ⴞⴝā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´•", + "merge_people": "ⴆⴺāĩā´•ā´ŗāĩ† ⴞⴝā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´•", + "merge_people_limit": "ā´’ā´°āĩ ā´¸ā´Žā´¯ā´‚ 5 ā´Žāĩā´–ā´™āĩā´™āĩž ā´ĩā´°āĩ† ā´Žā´žā´¤āĩā´°ā´Žāĩ‡ ⴞⴝā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯āĩ‚", + "merge_people_prompt": "ⴈ ⴆⴺāĩā´•ā´ŗāĩ† ⴞⴝā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•ā´Ŗāĩ‹? ⴈ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´‚ ā´Ēā´´ā´¯ā´Ēⴟā´ŋā´¯ā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛.", + "merge_people_successfully": "ⴆⴺāĩā´•ā´ŗāĩ† ā´ĩā´ŋā´œā´¯ā´•ā´°ā´Žā´žā´¯ā´ŋ ⴞⴝā´ŋā´Ēāĩā´Ēā´ŋⴚāĩā´šāĩ", + "merged_people_count": "{count, plural, one {# ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´¯āĩ† ⴞⴝā´ŋā´Ēāĩā´Ēā´ŋⴚāĩā´šāĩ} other {# ⴆⴺāĩā´•ā´ŗāĩ† ⴞⴝā´ŋā´Ēāĩā´Ēā´ŋⴚāĩā´šāĩ}}", + "minimize": "ⴚāĩ†ā´ąāĩā´¤ā´žā´•āĩā´•āĩā´•", + "minute": "ā´Žā´ŋā´¨ā´ŋā´ąāĩā´ąāĩ", + "minutes": "ā´Žā´ŋā´¨ā´ŋā´ąāĩā´ąāĩā´•āĩž", + "missing": "ā´•ā´žā´Ŗā´žā´¨ā´ŋā´˛āĩā´˛", + "model": "ā´Žāĩ‹ā´ĄāĩŊ", + "month": "ā´Žā´žā´¸ā´‚", + "monthly_title_text_date_format": "MMMM y", + "more": "ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ", + "move": "ā´¨āĩ€ā´•āĩā´•āĩā´•", + "move_off_locked_folder": "ā´˛āĩ‹ā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¤ ā´Ģāĩ‹āĩžā´Ąā´ąā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´Žā´žā´ąāĩā´ąāĩā´•", + "move_to_lock_folder_action_prompt": "{count} ā´Žā´Ŗāĩā´Ŗā´‚ ā´˛āĩ‹ā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¤ ā´Ģāĩ‹āĩžā´Ąā´ąā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ⴚāĩ‡āĩŧā´¤āĩā´¤āĩ", + "move_to_locked_folder": "ā´˛āĩ‹ā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¤ ā´Ģāĩ‹āĩžā´Ąā´ąā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Žā´žā´ąāĩā´ąāĩā´•", + "move_to_locked_folder_confirmation": "ⴈ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´¯āĩā´‚ ā´Žā´˛āĩā´˛ā´ž ā´†āĩŊā´Ŧā´™āĩā´™ā´ŗā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩā´‚ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´‚, ā´˛āĩ‹ā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¤ ā´Ģāĩ‹āĩžā´Ąā´ąā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´Žā´žā´¤āĩā´°ā´Žāĩ‡ ā´•ā´žā´Ŗā´žāĩģ ā´•ā´´ā´ŋā´¯āĩ‚", + "moved_to_archive": "{count, plural, one {# ā´…ā´¸ā´ąāĩā´ąāĩ} other {# ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž}} ā´†āĩŧā´•āĩā´•āĩˆā´ĩā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Žā´žā´ąāĩā´ąā´ŋ", + "moved_to_library": "{count, plural, one {# ā´…ā´¸ā´ąāĩā´ąāĩ} other {# ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž}} ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋā´¯ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Žā´žā´ąāĩā´ąā´ŋ", + "moved_to_trash": "ⴟāĩā´°ā´žā´ˇā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Žā´žā´ąāĩā´ąā´ŋ", + "multiselect_grid_edit_date_time_err_read_only": "ā´ĩā´žā´¯ā´ŋā´•āĩā´•ā´žāĩģ ā´Žā´žā´¤āĩā´°ā´Žāĩā´ŗāĩā´ŗ ā´…ā´¸ā´ąāĩā´ąā´ŋ(ā´•ā´ŗāĩ)ⴟāĩ† ā´¤āĩ€ā´¯ā´¤ā´ŋ ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛, ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "multiselect_grid_edit_gps_err_read_only": "ā´ĩā´žā´¯ā´ŋā´•āĩā´•ā´žāĩģ ā´Žā´žā´¤āĩā´°ā´Žāĩā´ŗāĩā´ŗ ā´…ā´¸ā´ąāĩā´ąā´ŋ(ā´•ā´ŗāĩ)ⴟāĩ† ā´¸āĩā´Ĩā´žā´¨ā´‚ ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛, ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "mute_memories": "ā´“āĩŧā´Žāĩā´Žā´•āĩž ā´¨ā´ŋā´ļāĩā´ļā´Ŧāĩā´Ļā´Žā´žā´•āĩā´•āĩā´•", + "my_albums": "ā´Žā´¨āĩā´ąāĩ† ā´†āĩŊā´Ŧā´™āĩā´™āĩž", + "name": "ā´Ēāĩ‡ā´°āĩ", + "name_or_nickname": "ā´Ēāĩ‡ā´°āĩ ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ ā´ĩā´ŋā´ŗā´ŋā´Ēāĩā´Ēāĩ‡ā´°āĩ", + "network_requirement_photos_upload": "ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´¸āĩ†ā´˛āĩā´˛āĩā´˛ā´žāĩŧ ā´Ąā´žā´ąāĩā´ą ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•", + "network_requirement_videos_upload": "ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•āĩž ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´¸āĩ†ā´˛āĩā´˛āĩā´˛ā´žāĩŧ ā´Ąā´žā´ąāĩā´ą ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•", + "network_requirements": "ā´¨āĩ†ā´ąāĩā´ąāĩâ€Œā´ĩāĩŧā´•āĩā´•āĩ ā´†ā´ĩā´ļāĩā´¯ā´•ⴤⴕāĩž", + "network_requirements_updated": "ā´¨āĩ†ā´ąāĩā´ąāĩâ€Œā´ĩāĩŧā´•āĩā´•āĩ ā´†ā´ĩā´ļāĩā´¯ā´•ⴤⴕāĩž ā´Žā´žā´ąā´ŋ, ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ā´•āĩā´¯āĩ‚ ā´Ēāĩā´¨ā´ƒā´¸ā´œāĩā´œā´Žā´žā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "networking_settings": "ā´¨āĩ†ā´ąāĩā´ąāĩâ€Œā´ĩāĩŧā´•āĩā´•ā´ŋā´‚ā´—āĩ", + "networking_subtitle": "ā´¸āĩ†āĩŧā´ĩāĩŧ ā´Žāĩģā´Ąāĩâ€Œā´Ēāĩ‹ā´¯ā´ŋā´¨āĩā´ąāĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "never": "ā´’ā´°ā´ŋā´•āĩā´•ā´˛āĩā´‚ ⴇⴞāĩā´˛", + "new_album": "ā´Ēāĩā´¤ā´ŋā´¯ ā´†āĩŊā´Ŧā´‚", + "new_api_key": "ā´Ēāĩā´¤ā´ŋā´¯ API ā´•āĩ€", + "new_password": "ā´Ēāĩā´¤ā´ŋā´¯ ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ", + "new_person": "ā´Ēāĩā´¤ā´ŋā´¯ ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋ", + "new_pin_code": "ā´Ēāĩā´¤ā´ŋā´¯ ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ", + "new_pin_code_subtitle": "ā´¨ā´ŋā´™āĩā´™āĩž ā´†ā´Ļāĩā´¯ā´Žā´žā´¯ā´ŋⴟāĩā´Ÿā´žā´Ŗāĩ ā´˛āĩ‹ā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¤ ā´Ģāĩ‹āĩžā´Ąāĩŧ ⴆⴕāĩâ€Œā´¸ā´¸āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤āĩ. ⴈ ā´Ēāĩ‡ā´œāĩ ā´¸āĩā´°ā´•āĩā´ˇā´ŋā´¤ā´Žā´žā´¯ā´ŋ ⴆⴕāĩâ€Œā´¸ā´¸āĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´’ā´°āĩ ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´•", + "new_timeline": "ā´Ēāĩā´¤ā´ŋā´¯ ⴟāĩˆā´‚ā´˛āĩˆāĩģ", + "new_user_created": "ā´Ēāĩā´¤ā´ŋā´¯ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ† ⴉ⴪āĩā´Ÿā´žā´•āĩā´•ā´ŋ", + "new_version_available": "ā´Ēāĩā´¤ā´ŋā´¯ ā´Ēā´¤ā´ŋā´Ēāĩā´Ēāĩ ⴞⴭāĩā´¯ā´Žā´žā´Ŗāĩ", + "newest_first": "ā´ā´ąāĩā´ąā´ĩāĩā´‚ ā´Ēāĩā´¤ā´ŋⴝⴤāĩ ā´†ā´Ļāĩā´¯ā´‚", + "next": "ā´…ā´Ÿāĩā´¤āĩā´¤ā´¤āĩ", + "next_memory": "ā´…ā´Ÿāĩā´¤āĩā´¤ ā´“āĩŧā´Žāĩā´Ž", + "no": "ⴇⴞāĩā´˛", + "no_albums_message": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´‚ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´ŋā´•āĩā´•ā´žāĩģ ā´’ā´°āĩ ā´†āĩŊā´Ŧā´‚ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´•", + "no_albums_with_name_yet": "ⴈ ā´Ēāĩ‡ā´°ā´ŋāĩŊ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ⴇⴤāĩā´ĩā´°āĩ† ā´†āĩŊā´Ŧā´™āĩā´™ā´ŗāĩŠā´¨āĩā´¨āĩā´‚ ⴇⴞāĩā´˛āĩ†ā´¨āĩā´¨āĩ ā´¤āĩ‹ā´¨āĩā´¨āĩā´¨āĩā´¨āĩ.", + "no_albums_yet": "ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ⴇⴤāĩā´ĩā´°āĩ† ā´†āĩŊā´Ŧā´™āĩā´™ā´ŗāĩŠā´¨āĩā´¨āĩā´‚ ⴇⴞāĩā´˛āĩ†ā´¨āĩā´¨āĩ ā´¤āĩ‹ā´¨āĩā´¨āĩā´¨āĩā´¨āĩ.", + "no_archived_assets_message": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ ā´•ā´žā´´āĩâ€Œā´šā´¯ā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´Žā´ąā´¯āĩā´•āĩā´•ā´žāĩģ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´‚ ā´†āĩŧā´•āĩā´•āĩˆā´ĩāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "no_assets_message": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´†ā´Ļāĩā´¯ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•āĩā´˛ā´ŋā´•āĩā´•āĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "no_assets_to_show": "ā´•ā´žā´Ŗā´ŋā´•āĩā´•ā´žāĩģ ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩŠā´¨āĩā´¨āĩā´Žā´ŋā´˛āĩā´˛", + "no_cast_devices_found": "ā´•ā´žā´¸āĩā´ąāĩā´ąāĩ ā´‰ā´Ēā´•ā´°ā´Ŗā´™āĩā´™ā´ŗāĩŠā´¨āĩā´¨āĩā´‚ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "no_checksum_local": "ⴚāĩ†ā´•āĩā´•āĩā´¸ā´‚ ⴞⴭāĩā´¯ā´Žā´˛āĩā´˛ - ā´Ēāĩā´°ā´žā´Ļāĩ‡ā´ļā´ŋā´• ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ⴞⴭāĩā´¯ā´Žā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "no_checksum_remote": "ⴚāĩ†ā´•āĩā´•āĩā´¸ā´‚ ⴞⴭāĩā´¯ā´Žā´˛āĩā´˛ - ā´ąā´ŋā´Žāĩ‹ā´Ÿāĩā´Ÿāĩ ā´…ā´¸ā´ąāĩā´ąāĩ ⴞⴭāĩā´¯ā´Žā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "no_duplicates_found": "ā´Ąāĩā´¯āĩ‚ā´Ēāĩā´˛ā´ŋā´•āĩā´•āĩ‡ā´ąāĩā´ąāĩā´•ā´ŗāĩŠā´¨āĩā´¨āĩā´‚ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´ŋā´¯ā´ŋā´˛āĩā´˛.", + "no_exif_info_available": "Exif ā´ĩā´ŋā´ĩā´°ā´™āĩā´™āĩž ⴞⴭāĩā´¯ā´Žā´˛āĩā´˛", + "no_explore_results_message": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´ļāĩ‡ā´–ā´°ā´‚ ā´Ēā´°āĩā´¯ā´ĩāĩ‡ā´•āĩā´ˇā´Ŗā´‚ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•.", + "no_favorites_message": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Žā´ŋā´•ā´šāĩā´š ⴚā´ŋā´¤āĩā´°ā´™āĩā´™ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´‚ ā´ĩāĩ‡ā´—ā´¤āĩā´¤ā´ŋāĩŊ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´žāĩģ ā´Ēāĩā´°ā´ŋā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿā´ĩ ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", + "no_libraries_message": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´‚ ā´•ā´žā´Ŗāĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ ā´’ā´°āĩ ā´Ŧā´žā´šāĩā´¯ ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´•", + "no_local_assets_found": "ⴈ ⴚāĩ†ā´•āĩā´•āĩā´¸ā´‚ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ā´Ēāĩā´°ā´žā´Ļāĩ‡ā´ļā´ŋā´• ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩŠā´¨āĩā´¨āĩā´‚ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "no_locked_photos_message": "ā´˛āĩ‹ā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩâ€Œā´¤ ā´Ģāĩ‹āĩžā´Ąā´ąā´ŋā´˛āĩ† ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´‚ ā´Žā´ąā´šāĩā´šā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ, ā´¨ā´ŋā´™āĩā´™āĩž ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ ā´Ŧāĩā´°āĩ—ā´¸āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´Žāĩā´Ēāĩ‹ā´´āĩ‹ ā´¤ā´ŋā´°ā´¯āĩā´Žāĩā´Ēāĩ‹ā´´āĩ‹ ā´…ā´ĩ ā´Ļāĩƒā´ļāĩā´¯ā´Žā´žā´•ā´ŋā´˛āĩā´˛.", + "no_name": "ā´Ēāĩ‡ā´°ā´ŋā´˛āĩā´˛", + "no_notifications": "ā´…ā´ąā´ŋā´¯ā´ŋā´Ēāĩā´Ēāĩā´•ā´ŗāĩŠā´¨āĩā´¨āĩā´Žā´ŋā´˛āĩā´˛", + "no_people_found": "ⴚāĩ‡āĩŧⴚāĩā´šā´¯āĩā´ŗāĩā´ŗ ⴆⴺāĩā´•ā´ŗāĩ† ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "no_places": "ā´¸āĩā´Ĩⴞⴙāĩā´™ā´ŗā´ŋā´˛āĩā´˛", + "no_remote_assets_found": "ⴈ ⴚāĩ†ā´•āĩā´•āĩā´¸ā´‚ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ā´ąā´ŋā´Žāĩ‹ā´Ÿāĩā´Ÿāĩ ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩŠā´¨āĩā´¨āĩā´‚ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "no_results": "ā´Ģⴞⴙāĩā´™ā´ŗāĩŠā´¨āĩā´¨āĩā´Žā´ŋā´˛āĩā´˛", + "no_results_description": "ā´’ā´°āĩ ā´Ēā´°āĩā´¯ā´žā´¯ā´Ēā´Ļā´Žāĩ‹ ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ ā´ĒāĩŠā´¤āĩā´ĩā´žā´¯ ā´•āĩ€ā´ĩāĩ‡ā´Ąāĩ‹ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ā´ļāĩā´°ā´Žā´ŋā´•āĩā´•āĩā´•", + "no_shared_albums_message": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´¨āĩ†ā´ąāĩā´ąāĩâ€Œā´ĩāĩŧā´•āĩā´•ā´ŋā´˛āĩ† ⴆⴺāĩā´•ā´ŗāĩā´Žā´žā´¯ā´ŋ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´‚ ā´Ēā´™āĩā´•ā´ŋā´Ÿā´žāĩģ ā´’ā´°āĩ ā´†āĩŊā´Ŧā´‚ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´•", + "no_uploads_in_progress": "ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩā´•ā´ŗāĩŠā´¨āĩā´¨āĩā´‚ ā´Ēāĩā´°āĩ‹ā´—ā´Žā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´ŋā´˛āĩā´˛", + "not_available": "ⴞⴭāĩā´¯ā´Žā´˛āĩā´˛", + "not_in_any_album": "ā´’ā´°āĩ ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋā´˛āĩā´Žā´ŋā´˛āĩā´˛", + "not_selected": "ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´¤āĩā´¤ā´ŋⴟāĩā´Ÿā´ŋā´˛āĩā´˛", + "note_apply_storage_label_to_previously_uploaded assets": "ā´•āĩā´ąā´ŋā´Ēāĩā´Ēāĩ: ā´Žāĩā´Žāĩā´Ēāĩ ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¤ ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗā´ŋāĩŊ ā´¸āĩā´ąāĩā´ąāĩ‹ā´ąāĩ‡ā´œāĩ ā´˛āĩ‡ā´ŦāĩŊ ā´Ēāĩā´°ā´¯āĩ‹ā´—ā´ŋā´•āĩā´•ā´žāĩģ, ⴇⴤāĩ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´•", + "notes": "ā´•āĩā´ąā´ŋā´Ēāĩā´Ēāĩā´•āĩž", + "nothing_here_yet": "ā´‡ā´ĩā´ŋⴟāĩ† ⴇⴤāĩā´ĩā´°āĩ† ā´’ā´¨āĩā´¨āĩā´Žā´ŋā´˛āĩā´˛", + "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-ā´¨āĩā´ąāĩ† ā´”ā´Ļāĩā´¯āĩ‹ā´—ā´ŋā´• ā´‰ā´ąā´ĩā´ŋā´Ÿā´™āĩā´™āĩž", + "offline": "ā´“ā´Ģāĩâ€Œā´˛āĩˆāĩģ", + "offset": "ā´“ā´Ģāĩā´¸āĩ†ā´ąāĩā´ąāĩ", + "ok": "ā´ļā´°ā´ŋ", + "oldest_first": "ā´ā´ąāĩā´ąā´ĩāĩā´‚ ā´Ēⴴⴝⴤāĩ ā´†ā´Ļāĩā´¯ā´‚", + "on_this_device": "ⴈ ā´‰ā´Ēā´•ā´°ā´Ŗā´¤āĩā´¤ā´ŋāĩŊ", + "onboarding": "ā´“āĩēā´Ŧāĩ‹āĩŧā´Ąā´ŋā´‚ā´—āĩ", + "onboarding_locale_description": "ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•ā´ŋā´ˇāĩā´Ÿā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿ ā´­ā´žā´ˇ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•. ⴇⴤāĩ ā´Ēā´ŋā´¨āĩā´¨āĩ€ā´Ÿāĩ ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™ā´ŗā´ŋāĩŊ ā´Žā´žā´ąāĩā´ąā´žā´ĩāĩā´¨āĩā´¨ā´¤ā´žā´Ŗāĩ.", + "onboarding_privacy_description": "ⴇⴍā´ŋā´Ēāĩā´Ēā´ąā´¯āĩā´¨āĩā´¨ (ā´“ā´Ēāĩā´ˇā´ŖāĩŊ) ā´Ģāĩ€ā´šāĩā´šā´ąāĩā´•āĩž ā´Ŧā´žā´šāĩā´¯ ā´¸āĩ‡ā´ĩⴍⴙāĩā´™ā´ŗāĩ† ā´†ā´ļāĩā´°ā´¯ā´ŋⴚāĩā´šā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ, ā´…ā´ĩ ā´Žā´Ēāĩā´Ēāĩ‹āĩž ā´ĩāĩ‡ā´Ŗā´Žāĩ†ā´™āĩā´•ā´ŋā´˛āĩā´‚ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™ā´ŗā´ŋāĩŊ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•ā´žā´‚.", + "onboarding_server_welcome_description": "ⴚā´ŋā´˛ ā´¸ā´žā´§ā´žā´°ā´Ŗ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´‡āĩģā´¸āĩā´ąāĩā´ąāĩģā´¸āĩ ⴏⴜāĩā´œā´Žā´žā´•āĩā´•ā´žā´‚.", + "onboarding_theme_description": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´‡āĩģā´¸āĩā´ąāĩā´ąāĩģā´¸ā´ŋā´¨ā´žā´¯ā´ŋ ā´’ā´°āĩ ā´•ā´ŗāĩŧ ā´¤āĩ€ā´‚ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•. ⴇⴤāĩ ā´Ēā´ŋā´¨āĩā´¨āĩ€ā´Ÿāĩ ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™ā´ŗā´ŋāĩŊ ā´Žā´žā´ąāĩā´ąā´žā´ĩāĩā´¨āĩā´¨ā´¤ā´žā´Ŗāĩ.", + "onboarding_user_welcome_description": "ā´¨ā´Žāĩā´•āĩā´•āĩ ⴆⴰⴂⴭā´ŋā´•āĩā´•ā´žā´‚!", + "onboarding_welcome_user": "ā´¸āĩā´ĩā´žā´—ā´¤ā´‚, {user}", + "online": "ā´“āĩēā´˛āĩˆāĩģ", + "only_favorites": "ā´Ēāĩā´°ā´ŋā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿā´ĩ ā´Žā´žā´¤āĩā´°ā´‚", + "open": "ā´¤āĩā´ąā´•āĩā´•āĩā´•", + "open_in_map_view": "ā´Žā´žā´Ēāĩā´Ēāĩ ā´•ā´žā´´āĩâ€Œā´šā´¯ā´ŋāĩŊ ā´¤āĩā´ąā´•āĩā´•āĩā´•", + "open_in_openstreetmap": "OpenStreetMap-āĩŊ ā´¤āĩā´ąā´•āĩā´•āĩā´•", + "open_the_search_filters": "ā´¤ā´ŋā´°ā´¯āĩŊ ā´Ģā´ŋāĩŊⴟāĩā´Ÿā´ąāĩā´•āĩž ā´¤āĩā´ąā´•āĩā´•āĩā´•", + "options": "ā´“ā´Ēāĩā´ˇā´¨āĩā´•āĩž", + "or": "ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ", + "organize_into_albums": "ā´†āĩŊā´Ŧā´™āĩā´™ā´ŗā´žā´¯ā´ŋ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´•", + "organize_into_albums_description": "ā´¨ā´ŋā´˛ā´ĩā´ŋā´˛āĩ† ā´¸ā´ŋā´™āĩā´•āĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ā´¨ā´ŋā´˛ā´ĩā´ŋā´˛āĩā´ŗāĩā´ŗ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž ā´†āĩŊā´Ŧā´™āĩā´™ā´ŗā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Žā´žā´ąāĩā´ąāĩā´•", + "organize_your_library": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´•", + "original": "ā´¯ā´Ĩā´žāĩŧā´¤āĩā´Ĩā´‚", + "other": "ā´Žā´ąāĩā´ąāĩā´ŗāĩā´ŗā´ĩ", + "other_devices": "ā´Žā´ąāĩā´ąāĩ ā´‰ā´Ēā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "other_entities": "ā´Žā´ąāĩā´ąāĩ ā´Žā´¨āĩā´ąā´ŋā´ąāĩā´ąā´ŋā´•āĩž", + "other_variables": "ā´Žā´ąāĩā´ąāĩ ā´ĩāĩ‡ā´°ā´ŋā´¯ā´Ŧā´ŋā´ŗāĩā´•āĩž", + "owned": "ā´¸āĩā´ĩā´¨āĩā´¤ā´Žā´žā´¯āĩā´ŗāĩā´ŗā´¤āĩ", + "owner": "ā´‰ā´Ÿā´Ž", + "partner": "ā´Ēā´™āĩā´•ā´žā´ŗā´ŋ", + "partner_can_access": "{partner}-ā´•āĩā´•āĩ ⴆⴕāĩā´¸ā´¸āĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯āĩā´‚", + "partner_can_access_assets": "ā´†āĩŧā´•āĩā´•āĩˆā´ĩāĩā´šāĩ†ā´¯āĩâ€Œā´¤ā´¤āĩā´‚ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´ŋⴝⴤāĩā´Žā´žā´¯ā´ĩ ā´’ā´´ā´ŋā´•āĩ† ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Žā´˛āĩā´˛ā´ž ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´‚", + "partner_can_access_location": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž ā´Žā´Ÿāĩā´¤āĩā´¤ ā´¸āĩā´Ĩⴞⴂ", + "partner_list_user_photos": "{user}-ā´¨āĩā´ąāĩ† ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž", + "partner_list_view_all": "ā´Žā´˛āĩā´˛ā´žā´‚ ā´•ā´žā´Ŗāĩā´•", + "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}-ā´•āĩā´•āĩ ⴇⴍā´ŋ ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž ⴆⴕāĩâ€Œā´¸ā´¸āĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛.", + "partner_sharing": "ā´Ēā´™āĩā´•ā´žā´ŗā´ŋā´¯āĩā´Žā´žā´¯ā´ŋ ā´Ēā´™āĩā´•ā´ŋⴟāĩŊ", + "partners": "ā´Ēā´™āĩā´•ā´žā´ŗā´ŋā´•āĩž", + "password": "ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡āĩŧā´Ąāĩ", + "password_does_not_match": "ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´ĒāĩŠā´°āĩā´¤āĩā´¤ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´¨āĩā´¨ā´ŋā´˛āĩā´˛", + "password_required": "ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´†ā´ĩā´ļāĩā´¯ā´Žā´žā´Ŗāĩ", + "password_reset_success": "ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´ąāĩ€ā´¸āĩ†ā´ąāĩā´ąāĩ ā´ĩā´ŋⴜⴝā´ŋⴚāĩā´šāĩ", + "past_durations": { + "days": "ā´•ā´´ā´ŋā´žāĩā´ž {days, plural, one {ā´Ļā´ŋā´ĩⴏⴂ} other {# ā´Ļā´ŋā´ĩⴏⴙāĩā´™āĩž}}", + "hours": "ā´•ā´´ā´ŋā´žāĩā´ž {hours, plural, one {ā´Žā´Ŗā´ŋā´•āĩā´•āĩ‚āĩŧ} other {# ā´Žā´Ŗā´ŋā´•āĩā´•āĩ‚ā´ąāĩā´•āĩž}}", + "years": "ā´•ā´´ā´ŋā´žāĩā´ž {years, plural, one {ā´ĩāĩŧⴎⴂ} other {# ā´ĩāĩŧⴎⴙāĩā´™āĩž}}" + }, + "path": "ā´Ēā´žā´¤āĩā´¤āĩ", + "pattern": "ā´Ēā´žā´ąāĩā´ąāĩ‡āĩē", + "pause": "ā´¤ā´žāĩŊā´•āĩā´•ā´žā´˛ā´ŋā´•ā´Žā´žā´¯ā´ŋ ā´¨ā´ŋāĩŧā´¤āĩā´¤āĩā´•", + "pause_memories": "ā´“āĩŧā´Žāĩā´Žā´•āĩž ā´¤ā´žāĩŊā´•āĩā´•ā´žā´˛ā´ŋā´•ā´Žā´žā´¯ā´ŋ ā´¨ā´ŋāĩŧā´¤āĩā´¤āĩā´•", + "paused": "ā´¤ā´žāĩŊā´•āĩā´•ā´žā´˛ā´ŋā´•ā´Žā´žā´¯ā´ŋ ā´¨ā´ŋāĩŧā´¤āĩā´¤ā´ŋ", + "pending": "ā´•ā´žā´¤āĩā´¤ā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "people": "ⴆⴺāĩā´•āĩž", + "people_edits_count": "{count, plural, one {# ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´¯āĩ† ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¤āĩ} other {# ⴆⴺāĩā´•ā´ŗāĩ† ā´Žā´Ąā´ŋā´ąāĩā´ąāĩā´šāĩ†ā´¯āĩā´¤āĩ}}", + "people_feature_description": "ⴆⴺāĩā´•ā´ŗā´¨āĩā´¸ā´°ā´ŋⴚāĩā´šāĩ ā´—āĩā´°āĩ‚ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¤ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´‚ ā´Ŧāĩā´°āĩ—ā´¸āĩā´šāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ", + "people_sidebar_description": "ā´¸āĩˆā´Ąāĩâ€Œā´Ŧā´žā´ąā´ŋāĩŊ 'ⴆⴺāĩā´•āĩž' ā´Žā´¨āĩā´¨ā´¤ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´’ā´°āĩ ā´˛ā´ŋā´™āĩā´•āĩ ā´Ēāĩā´°ā´Ļāĩŧā´ļā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´•", + "permanent_deletion_warning": "ā´ļā´žā´ļāĩā´ĩā´¤ā´Žā´žā´¯ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩŊ ā´Žāĩā´¨āĩā´¨ā´ąā´ŋā´¯ā´ŋā´Ēāĩā´Ēāĩ", + "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 {# ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž}} ā´ļā´žā´ļāĩā´ĩā´¤ā´Žā´žā´¯ā´ŋ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´ŋ", + "permission": "ā´…ā´¨āĩā´Žā´¤ā´ŋ", + "permission_empty": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´…ā´¨āĩā´Žā´¤ā´ŋ ā´ļāĩ‚ā´¨āĩā´¯ā´Žā´žā´•ā´°āĩā´¤āĩ", + "permission_onboarding_back": "ā´¤ā´ŋā´°ā´ŋā´•āĩ†", + "permission_onboarding_continue_anyway": "ā´Žā´¨āĩā´¤ā´žā´¯ā´žā´˛āĩā´‚ ā´¤āĩā´Ÿā´°āĩā´•", + "permission_onboarding_get_started": "ā´¤āĩā´Ÿā´™āĩā´™ā´žā´‚", + "permission_onboarding_go_to_settings": "ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™ā´ŗā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Ēāĩ‹ā´•āĩā´•", + "permission_onboarding_permission_denied": "ā´…ā´¨āĩā´Žā´¤ā´ŋ ā´¨ā´ŋā´ˇāĩ‡ā´§ā´ŋⴚāĩā´šāĩ. Immich ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ, ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™ā´ŗā´ŋāĩŊ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹, ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ ā´…ā´¨āĩā´Žā´¤ā´ŋā´•āĩž ā´¨āĩŊā´•āĩā´•.", + "permission_onboarding_permission_granted": "ā´…ā´¨āĩā´Žā´¤ā´ŋ ⴞⴭā´ŋⴚāĩā´šāĩ! ā´¨ā´ŋā´™āĩā´™āĩž ⴤⴝāĩā´¯ā´žā´ąā´žā´Ŗāĩ.", + "permission_onboarding_permission_limited": "ā´…ā´¨āĩā´Žā´¤ā´ŋ ā´Ēā´°ā´ŋā´Žā´ŋā´¤ā´Žā´žā´Ŗāĩ. Immich-ā´¨āĩ ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Žāĩā´´āĩā´ĩāĩģ ā´—ā´žā´˛ā´ąā´ŋ ā´ļāĩ‡ā´–ā´°ā´ĩāĩā´‚ ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¯ā´žā´¨āĩā´‚ ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯ā´žā´¨āĩā´‚ ā´…ā´¨āĩā´ĩā´Ļā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ, ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™ā´ŗā´ŋāĩŊ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹, ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ ā´…ā´¨āĩā´Žā´¤ā´ŋā´•āĩž ā´¨āĩŊā´•āĩā´•.", + "permission_onboarding_request": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´‚ ā´•ā´žā´Ŗāĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ Immich-ā´¨āĩ ā´…ā´¨āĩā´Žā´¤ā´ŋ ā´†ā´ĩā´ļāĩā´¯ā´Žā´žā´Ŗāĩ.", + "person": "ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋ", + "person_age_months": "{months, plural, one {# ā´Žā´žā´¸ā´‚} other {# ā´Žā´žā´¸ā´‚}} ā´Ēāĩā´°ā´žā´¯ā´‚", + "person_age_year_months": "1 ā´ĩāĩŧā´ˇā´ĩāĩā´‚ {months, plural, one {# ā´Žā´žā´¸ā´ĩāĩā´‚} other {# ā´Žā´žā´¸ā´ĩāĩā´‚}} ā´Ēāĩā´°ā´žā´¯ā´‚", + "person_age_years": "{years, plural, other {# ā´ĩⴝⴏāĩā´¸āĩ}}", + "person_birthdate": "{date}-ā´¨āĩ ⴜⴍā´ŋⴚāĩā´šāĩ", + "person_hidden": "{name}{hidden, select, true { (ā´Žā´ąā´šāĩā´šā´¤āĩ)} other {}}", + "photo_shared_all_users": "ā´¨ā´ŋā´™āĩā´™āĩž ā´Žā´˛āĩā´˛ā´ž ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´•āĩā´•ā´ŗāĩā´Žā´žā´¯āĩā´‚ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿāĩ, ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´Ēā´™āĩā´•ā´ŋā´Ÿā´žāĩģ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´•āĩā´•ā´ŗā´žā´°āĩā´‚ ⴇⴞāĩā´˛āĩ†ā´¨āĩā´¨āĩ ā´¤āĩ‹ā´¨āĩā´¨āĩā´¨āĩā´¨āĩ.", + "photos": "ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž", + "photos_and_videos": "ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´‚", + "photos_count": "{count, plural, one {{count, number} ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹} other {{count, number} ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž}}", + "photos_from_previous_years": "ā´Žāĩāĩģ ā´ĩāĩŧⴎⴙāĩā´™ā´ŗā´ŋā´˛āĩ† ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž", + "pick_a_location": "ā´’ā´°āĩ ā´¸āĩā´Ĩⴞⴂ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "pin_code_changed_successfully": "ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ ā´ĩā´ŋā´œā´¯ā´•ā´°ā´Žā´žā´¯ā´ŋ ā´Žā´žā´ąāĩā´ąā´ŋ", + "pin_code_reset_successfully": "ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ ā´ĩā´ŋā´œā´¯ā´•ā´°ā´Žā´žā´¯ā´ŋ ā´ąāĩ€ā´¸āĩ†ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "pin_code_setup_successfully": "ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ ā´ĩā´ŋā´œā´¯ā´•ā´°ā´Žā´žā´¯ā´ŋ ⴏⴜāĩā´œāĩ€ā´•ā´°ā´ŋⴚāĩā´šāĩ", + "pin_verification": "ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´¨", + "place": "ā´¸āĩā´Ĩⴞⴂ", + "places": "ā´¸āĩā´Ĩⴞⴙāĩā´™āĩž", + "places_count": "{count, plural, one {{count, number} ā´¸āĩā´Ĩⴞⴂ} other {{count, number} ā´¸āĩā´Ĩⴞⴙāĩā´™āĩž}}", + "play": "ā´Ēāĩā´˛āĩ‡ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "play_memories": "ā´“āĩŧā´Žāĩā´Žā´•āĩž ā´Ēāĩā´˛āĩ‡ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "play_motion_photo": "ⴚⴞā´ŋā´•āĩā´•āĩā´¨āĩā´¨ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ ā´Ēāĩā´˛āĩ‡ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "play_or_pause_video": "ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ ā´Ēāĩā´˛āĩ‡ ⴚāĩ†ā´¯āĩā´¯āĩā´• ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ ā´¤ā´žāĩŊā´•āĩā´•ā´žā´˛ā´ŋā´•ā´Žā´žā´¯ā´ŋ ā´¨ā´ŋāĩŧā´¤āĩā´¤āĩā´•", + "please_auth_to_access": "ⴆⴕāĩâ€Œā´¸ā´¸āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ ā´Ļā´¯ā´ĩā´žā´¯ā´ŋ ā´Ēāĩā´°ā´žā´Žā´žā´Ŗāĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´•", + "port": "ā´Ēāĩ‹āĩŧⴟāĩā´Ÿāĩ", + "preferences_settings_subtitle": "ā´†ā´Ēāĩā´Ēā´ŋā´¨āĩā´ąāĩ† ā´Žāĩāĩģⴗ⴪ⴍⴕāĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "preferences_settings_title": "ā´Žāĩāĩģⴗ⴪ⴍⴕāĩž", + "preparing": "ⴤⴝāĩā´¯ā´žā´ąā´žā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "preset": "ā´Ēāĩā´°āĩ€ā´¸āĩ†ā´ąāĩā´ąāĩ", + "preview": "ā´Ēāĩā´°ā´ŋā´ĩāĩā´¯āĩ‚", + "previous": "ā´Žāĩā´Žāĩā´Ēā´¤āĩā´¤āĩ†", + "previous_memory": "ā´Žāĩā´Žāĩā´Ēā´¤āĩā´¤āĩ† ā´“āĩŧā´Žāĩā´Ž", + "previous_or_next_day": "ā´Ļā´ŋā´ĩⴏⴂ ā´Žāĩā´¨āĩā´¨āĩ‹ā´Ÿāĩā´Ÿāĩ/ā´Ēāĩā´ąā´•āĩ‹ā´Ÿāĩā´Ÿāĩ", + "previous_or_next_month": "ā´Žā´žā´¸ā´‚ ā´Žāĩā´¨āĩā´¨āĩ‹ā´Ÿāĩā´Ÿāĩ/ā´Ēāĩā´ąā´•āĩ‹ā´Ÿāĩā´Ÿāĩ", + "previous_or_next_photo": "ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ ā´Žāĩā´¨āĩā´¨āĩ‹ā´Ÿāĩā´Ÿāĩ/ā´Ēāĩā´ąā´•āĩ‹ā´Ÿāĩā´Ÿāĩ", + "previous_or_next_year": "ā´ĩāĩŧⴎⴂ ā´Žāĩā´¨āĩā´¨āĩ‹ā´Ÿāĩā´Ÿāĩ/ā´Ēāĩā´ąā´•āĩ‹ā´Ÿāĩā´Ÿāĩ", + "primary": "ā´Ēāĩā´°ā´§ā´žā´¨ā´Žā´žā´¯ā´¤āĩ", + "privacy": "ā´¸āĩā´ĩā´•ā´žā´°āĩā´¯ā´¤", + "profile": "ā´Ēāĩā´°āĩŠā´ĢāĩˆāĩŊ", + "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_github": "ā´—ā´ŋā´ąāĩā´ąāĩā´šā´Ŧāĩ", + "profile_drawer_readonly_mode": "ā´ąāĩ€ā´Ąāĩ-ā´“āĩēā´˛ā´ŋ ā´Žāĩ‹ā´Ąāĩ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•ā´ŋ. ā´Ēāĩā´ąā´¤āĩā´¤āĩā´•ā´Ÿā´•āĩā´•ā´žāĩģ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤āĩƒ ā´…ā´ĩā´¤ā´žāĩŧ ⴐⴕāĩā´•ā´Ŗā´ŋāĩŊ ā´Ļāĩ€āĩŧⴘⴍāĩ‡ā´°ā´‚ ā´…ā´Žāĩŧā´¤āĩā´¤āĩā´•.", + "profile_drawer_server_out_of_date_major": "ā´¸āĩ†āĩŧā´ĩāĩŧ ā´•ā´žā´˛ā´šā´°ā´Ŗā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ. ā´Ļā´¯ā´ĩā´žā´¯ā´ŋ ā´ā´ąāĩā´ąā´ĩāĩā´‚ ā´Ēāĩā´¤ā´ŋā´¯ ā´Ēāĩā´°ā´§ā´žā´¨ ā´Ēā´¤ā´ŋā´Ēāĩā´Ēā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•.", + "profile_drawer_server_out_of_date_minor": "ā´¸āĩ†āĩŧā´ĩāĩŧ ā´•ā´žā´˛ā´šā´°ā´Ŗā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ. ā´Ļā´¯ā´ĩā´žā´¯ā´ŋ ā´ā´ąāĩā´ąā´ĩāĩā´‚ ā´Ēāĩā´¤ā´ŋā´¯ ā´Žāĩˆā´¨āĩŧ ā´Ēā´¤ā´ŋā´Ēāĩā´Ēā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•.", + "profile_image_of_user": "{user}-ā´¨āĩā´ąāĩ† ā´Ēāĩā´°āĩŠā´ĢāĩˆāĩŊ ⴚā´ŋā´¤āĩā´°ā´‚", + "profile_picture_set": "ā´Ēāĩā´°āĩŠā´ĢāĩˆāĩŊ ⴚā´ŋā´¤āĩā´°ā´‚ ⴏⴜāĩā´œāĩ€ā´•ā´°ā´ŋⴚāĩā´šāĩ.", + "public_album": "ā´ĒāĩŠā´¤āĩ ā´†āĩŊā´Ŧā´‚", + "public_share": "ā´ĒāĩŠā´¤āĩ ā´Ēā´™āĩā´•ā´ŋⴟāĩŊ", + "purchase_account_info": "ā´¸ā´šā´žā´¯ā´ŋ", + "purchase_activated_subtitle": "Immich-ā´¨āĩ†ā´¯āĩā´‚ ā´“ā´Ēāĩā´Ēāĩē ā´¸āĩ‹ā´´āĩâ€Œā´¸āĩ ā´¸āĩ‹ā´Ģāĩā´ąāĩā´ąāĩâ€Œā´ĩāĩ†ā´¯ā´ąā´ŋā´¨āĩ†ā´¯āĩā´‚ ā´Ēā´ŋā´¨āĩā´¤āĩā´Ŗā´šāĩā´šā´¤ā´ŋā´¨āĩ ⴍⴍāĩā´Ļā´ŋ", + "purchase_activated_time": "{date}-ā´¨āĩ ⴏⴜāĩ€ā´ĩā´Žā´žā´•āĩā´•ā´ŋ", + "purchase_activated_title": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´•āĩ€ ā´ĩā´ŋā´œā´¯ā´•ā´°ā´Žā´žā´¯ā´ŋ ⴏⴜāĩ€ā´ĩā´Žā´žā´•āĩā´•ā´ŋ", + "purchase_button_activate": "ⴏⴜāĩ€ā´ĩā´Žā´žā´•āĩā´•āĩā´•", + "purchase_button_buy": "ā´ĩā´žā´™āĩā´™āĩā´•", + "purchase_button_buy_immich": "Immich ā´ĩā´žā´™āĩā´™āĩā´•", + "purchase_button_never_show_again": "ⴇⴍā´ŋ ā´•ā´žā´Ŗā´ŋā´•āĩā´•ā´°āĩā´¤āĩ", + "purchase_button_reminder": "30 ā´Ļā´ŋā´ĩⴏⴤāĩā´¤ā´ŋā´¨āĩā´ŗāĩā´ŗā´ŋāĩŊ ā´“āĩŧā´Žāĩā´Žā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´•", + "purchase_button_remove_key": "ā´•āĩ€ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "purchase_button_select": "ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "purchase_failed_activation": "ⴏⴜāĩ€ā´ĩā´Žā´žā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ! ā´ļā´°ā´ŋā´¯ā´žā´¯ ā´Ēāĩā´°āĩŠā´Ąā´•āĩā´ąāĩā´ąāĩ ā´•āĩ€ā´•āĩā´•ā´žā´¯ā´ŋ ā´Ļā´¯ā´ĩā´žā´¯ā´ŋ ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ ā´Ēā´°ā´ŋā´ļāĩ‹ā´§ā´ŋā´•āĩā´•āĩā´•!", + "purchase_individual_description_1": "ā´’ā´°āĩ ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´•āĩā´•āĩ", + "purchase_individual_description_2": "ā´¸ā´šā´žā´¯ā´ŋā´¯āĩā´Ÿāĩ† ā´¨ā´ŋā´˛", + "purchase_individual_title": "ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋⴗⴤⴂ", + "purchase_input_suggestion": "ā´Ēāĩā´°āĩŠā´Ąā´•āĩā´ąāĩā´ąāĩ ā´•āĩ€ ⴉ⴪āĩā´Ÿāĩ‹? ā´¤ā´žā´´āĩ† ā´•āĩ€ ā´¨āĩŊā´•āĩā´•", + "purchase_license_subtitle": "ā´¸āĩ‡ā´ĩⴍⴤāĩā´¤ā´ŋā´¨āĩā´ąāĩ† ā´¤āĩā´Ÿāĩŧ ā´ĩā´ŋⴕⴏⴍⴤāĩā´¤āĩ† ā´Ēā´ŋā´¨āĩā´¤āĩā´Ŗā´¯āĩā´•āĩā´•ā´žāĩģ Immich ā´ĩā´žā´™āĩā´™āĩā´•", + "purchase_lifetime_description": "ā´†ā´œāĩ€ā´ĩā´¨ā´žā´¨āĩā´¤ ā´ĩā´žā´™āĩā´™āĩŊ", + "purchase_option_title": "ā´ĩā´žā´™āĩā´™ā´žā´¨āĩā´ŗāĩā´ŗ ā´“ā´Ēāĩā´ˇā´¨āĩā´•āĩž", + "purchase_panel_info_1": "Immich ā´¨ā´ŋāĩŧā´Žāĩā´Žā´ŋā´•āĩā´•ā´žāĩģ ā´§ā´žā´°ā´žā´ŗā´‚ ā´¸ā´Žā´¯ā´ĩāĩā´‚ ā´Ēāĩā´°ā´¯ā´¤āĩā´¨ā´ĩāĩā´‚ ā´†ā´ĩā´ļāĩā´¯ā´Žā´žā´Ŗāĩ, ā´…ā´¤āĩ ā´•ā´´ā´ŋā´¯āĩā´¨āĩā´¨ā´¤āĩā´° ā´Žā´ŋā´•ā´šāĩā´šā´¤ā´žā´•āĩā´•ā´žāĩģ ā´Žāĩā´´āĩā´ĩāĩģ ā´¸ā´Žā´¯ ā´Žā´žāĩā´šā´ŋā´¨āĩ€ā´¯āĩŧā´Žā´žāĩŧ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ. ā´“ā´Ēāĩā´Ēāĩē ā´¸āĩ‹ā´´āĩâ€Œā´¸āĩ ā´¸āĩ‹ā´Ģāĩā´ąāĩā´ąāĩâ€Œā´ĩāĩ†ā´¯ā´ąāĩā´‚ ā´§ā´žāĩŧā´Žāĩā´Žā´ŋā´•ā´Žā´žā´¯ ā´Ŧā´ŋā´¸ā´ŋⴍⴏāĩā´¸āĩ ā´°āĩ€ā´¤ā´ŋā´•ā´ŗāĩā´‚ ā´Ąāĩ†ā´ĩā´˛ā´Ēāĩā´Ēāĩŧā´Žā´žāĩŧā´•āĩā´•āĩ ā´¸āĩā´¸āĩā´Ĩā´ŋā´°ā´Žā´žā´¯ ā´ĩā´°āĩā´Žā´žā´¨ ā´Žā´žāĩŧā´—āĩā´—ā´Žā´žā´•āĩā´•āĩā´•, ⴚāĩ‚ⴎ⴪ā´Ēā´°ā´Žā´žā´¯ ā´•āĩā´˛āĩ—ā´Ąāĩ ā´¸āĩ‡ā´ĩⴍⴙāĩā´™āĩžā´•āĩā´•āĩ ā´¯ā´Ĩā´žāĩŧā´¤āĩā´Ĩ ā´Ŧā´Ļā´˛āĩā´•ā´ŗāĩā´ŗāĩā´ŗ ā´¸āĩā´ĩā´•ā´žā´°āĩā´¯ā´¤ā´¯āĩ† ā´Žā´žā´¨ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ ā´’ā´°āĩ ā´†ā´ĩā´žā´¸ā´ĩāĩā´¯ā´ĩā´¸āĩā´Ĩ ā´¸āĩƒā´ˇāĩā´Ÿā´ŋā´•āĩā´•āĩā´• ā´Žā´¨āĩā´¨ā´¤ā´žā´Ŗāĩ ā´žā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ļāĩ—ā´¤āĩā´¯ā´‚.", + "purchase_panel_info_2": "ā´Ēāĩ‡ā´ĩā´žā´ŗāĩā´•āĩž ⴚāĩ‡āĩŧā´•āĩā´•ā´ŋā´˛āĩā´˛āĩ†ā´¨āĩā´¨āĩ ā´žā´™āĩā´™āĩž ā´Ēāĩā´°ā´¤ā´ŋⴜāĩā´žā´žā´Ŧā´Ļāĩā´§ā´°ā´žā´¯ā´¤ā´ŋā´¨ā´žāĩŊ, ⴈ ā´ĩā´žā´™āĩā´™āĩŊ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ Immich-āĩŊ ā´…ā´§ā´ŋā´• ā´Ģāĩ€ā´šāĩā´šā´ąāĩā´•ā´ŗāĩŠā´¨āĩā´¨āĩā´‚ ā´¨āĩŊā´•ā´ŋā´˛āĩā´˛. Immich-ā´¨āĩā´ąāĩ† ā´¤āĩā´Ÿāĩŧ ā´ĩā´ŋⴕⴏⴍⴤāĩā´¤āĩ† ā´Ēā´ŋā´¨āĩā´¤āĩā´Ŗā´¯āĩā´•āĩā´•ā´žāĩģ ā´¨ā´ŋā´™āĩā´™ā´ŗāĩ†ā´Ēāĩā´Ēāĩ‹ā´˛āĩā´ŗāĩā´ŗ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´•āĩā´•ā´ŗāĩ†ā´¯ā´žā´Ŗāĩ ā´žā´™āĩā´™āĩž ā´†ā´ļāĩā´°ā´¯ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤āĩ.", + "purchase_panel_title": "ā´Ēā´Ļāĩā´§ā´¤ā´ŋā´¯āĩ† ā´Ēā´ŋā´¨āĩā´¤āĩā´Ŗā´¯āĩā´•āĩā´•āĩā´•", + "purchase_per_server": "ā´“ā´°āĩ‹ ā´¸āĩ†āĩŧā´ĩā´ąā´ŋā´¨āĩā´‚", + "purchase_per_user": "ā´“ā´°āĩ‹ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩā´‚", + "purchase_remove_product_key": "ā´Ēāĩā´°āĩŠā´Ąā´•āĩā´ąāĩā´ąāĩ ā´•āĩ€ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "purchase_remove_product_key_prompt": "ā´Ēāĩā´°āĩŠā´Ąā´•āĩā´ąāĩā´ąāĩ ā´•āĩ€ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹?", + "purchase_remove_server_product_key": "ā´¸āĩ†āĩŧā´ĩāĩŧ ā´Ēāĩā´°āĩŠā´Ąā´•āĩā´ąāĩā´ąāĩ ā´•āĩ€ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "purchase_remove_server_product_key_prompt": "ā´¸āĩ†āĩŧā´ĩāĩŧ ā´Ēāĩā´°āĩŠā´Ąā´•āĩā´ąāĩā´ąāĩ ā´•āĩ€ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹?", + "purchase_server_description_1": "ā´Žāĩā´´āĩā´ĩāĩģ ā´¸āĩ†āĩŧā´ĩā´ąā´ŋā´¨āĩā´‚", + "purchase_server_description_2": "ā´¸ā´šā´žā´¯ā´ŋā´¯āĩā´Ÿāĩ† ā´¨ā´ŋā´˛", + "purchase_server_title": "ā´¸āĩ†āĩŧā´ĩāĩŧ", + "purchase_settings_server_activated": "ā´¸āĩ†āĩŧā´ĩāĩŧ ā´Ēāĩā´°āĩŠā´Ąā´•āĩā´ąāĩā´ąāĩ ā´•āĩ€ ā´…ā´Ąāĩā´Žā´ŋāĩģ ⴆ⴪āĩ ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤āĩ", + "query_asset_id": "ā´…ā´¸ā´ąāĩā´ąāĩ ā´ā´Ąā´ŋ ā´…ā´¨āĩā´ĩāĩ‡ā´ˇā´ŋā´•āĩā´•āĩā´•", + "queue_status": "ā´•āĩā´¯āĩ‚ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ {count}/{total}", + "rating": "ā´¸āĩā´ąāĩā´ąā´žāĩŧ ā´ąāĩ‡ā´ąāĩā´ąā´ŋā´‚ā´—āĩ", + "rating_clear": "ā´ąāĩ‡ā´ąāĩā´ąā´ŋā´‚ā´—āĩ ā´•āĩā´˛ā´ŋā´¯āĩŧ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "rating_count": "{count, plural, one {# ā´¸āĩā´ąāĩā´ąā´žāĩŧ} other {# ā´¸āĩā´ąāĩā´ąā´žā´ąāĩā´•āĩž}}", + "rating_description": "ā´ĩā´ŋā´ĩā´° ā´Ēā´žā´¨ā´˛ā´ŋāĩŊ EXIF ā´ąāĩ‡ā´ąāĩā´ąā´ŋā´‚ā´—āĩ ā´Ēāĩā´°ā´Ļāĩŧā´ļā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´•", + "reaction_options": "ā´Ēāĩā´°ā´¤ā´ŋā´•ā´°ā´Ŗ ā´“ā´Ēāĩā´ˇā´¨āĩā´•āĩž", + "read_changelog": "ā´Žā´žā´ąāĩā´ąā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´˛āĩ‹ā´—āĩ ā´ĩā´žā´¯ā´ŋā´•āĩā´•āĩā´•", + "readonly_mode_disabled": "ā´ąāĩ€ā´Ąāĩ-ā´“āĩēā´˛ā´ŋ ā´Žāĩ‹ā´Ąāĩ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•ā´ŋ", + "readonly_mode_enabled": "ā´ąāĩ€ā´Ąāĩ-ā´“āĩēā´˛ā´ŋ ā´Žāĩ‹ā´Ąāĩ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•ā´ŋ", + "ready_for_upload": "ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąā´ŋā´¨ā´žā´¯ā´ŋ ⴤⴝāĩā´¯ā´žā´ąā´žā´Ŗāĩ", + "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": "ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´¤āĩā´¤ ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´¨ā´ŋā´˛ā´ĩā´ŋā´˛āĩā´ŗāĩā´ŗ ā´’ā´°āĩ ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´•āĩā´•āĩ ā´¨āĩŊā´•āĩā´•", + "recent": "ā´¸ā´Žāĩ€ā´Ēā´•ā´žā´˛ā´‚", + "recent-albums": "ā´¸ā´Žāĩ€ā´Ēā´•ā´žā´˛ ā´†āĩŊā´Ŧā´™āĩā´™āĩž", + "recent_searches": "ā´¸ā´Žāĩ€ā´Ēā´•ā´žā´˛ ā´¤ā´ŋⴰⴝⴞāĩā´•āĩž", + "recently_added": "ā´…ā´Ÿāĩā´¤āĩā´¤ā´ŋⴟāĩ† ⴚāĩ‡āĩŧā´¤āĩā´¤ā´¤āĩ", + "recently_added_page_title": "ā´…ā´Ÿāĩā´¤āĩā´¤ā´ŋⴟāĩ† ⴚāĩ‡āĩŧā´¤āĩā´¤ā´¤āĩ", + "recently_taken": "ā´…ā´Ÿāĩā´¤āĩā´¤ā´ŋⴟāĩ† ā´Žā´Ÿāĩā´¤āĩā´¤ā´¤āĩ", + "recently_taken_page_title": "ā´…ā´Ÿāĩā´¤āĩā´¤ā´ŋⴟāĩ† ā´Žā´Ÿāĩā´¤āĩā´¤ā´¤āĩ", + "refresh": "ā´Ēāĩā´¤āĩā´•āĩā´•āĩā´•", + "refresh_encoded_videos": "ā´Žāĩģā´•āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¤ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•āĩž ā´Ēāĩā´¤āĩā´•āĩā´•āĩā´•", + "refresh_faces": "ā´Žāĩā´–ā´™āĩā´™āĩž ā´Ēāĩā´¤āĩā´•āĩā´•āĩā´•", + "refresh_metadata": "ā´Žāĩ†ā´ąāĩā´ąā´žā´Ąā´žā´ąāĩā´ą ā´Ēāĩā´¤āĩā´•āĩā´•āĩā´•", + "refresh_thumbnails": "ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋā´˛āĩā´•āĩž ā´Ēāĩā´¤āĩā´•āĩā´•āĩā´•", + "refreshed": "ā´Ēāĩā´¤āĩā´•āĩā´•ā´ŋ", + "refreshes_every_file": "ā´¨ā´ŋā´˛ā´ĩā´ŋā´˛āĩā´ŗāĩā´ŗā´¤āĩā´‚ ā´Ēāĩā´¤ā´ŋⴝⴤāĩā´Žā´žā´¯ ā´Žā´˛āĩā´˛ā´ž ā´Ģⴝⴞāĩā´•ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩā´‚ ā´ĩā´žā´¯ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "refreshing_encoded_video": "ā´Žāĩģā´•āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¤ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ ā´Ēāĩā´¤āĩā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "refreshing_faces": "ā´Žāĩā´–ā´™āĩā´™āĩž ā´Ēāĩā´¤āĩā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "refreshing_metadata": "ā´Žāĩ†ā´ąāĩā´ąā´žā´Ąā´žā´ąāĩā´ą ā´Ēāĩā´¤āĩā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "regenerating_thumbnails": "ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋā´˛āĩā´•āĩž ā´Ēāĩā´¨āĩŧā´¨ā´ŋāĩŧā´Žāĩā´Žā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "remote": "ā´ąā´ŋā´Žāĩ‹ā´Ÿāĩā´Ÿāĩ", + "remote_assets": "ā´ąā´ŋā´Žāĩ‹ā´Ÿāĩā´Ÿāĩ ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž", + "remote_media_summary": "ā´ąā´ŋā´Žāĩ‹ā´Ÿāĩā´Ÿāĩ ā´Žāĩ€ā´Ąā´ŋā´¯ ⴏⴂⴗāĩā´°ā´šā´‚", + "remove": "ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "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": "ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "remove_from_album_action_prompt": "{count} ā´Žā´Ŗāĩā´Ŗā´‚ ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¤āĩ", + "remove_from_favorites": "ā´Ēāĩā´°ā´ŋā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿā´ĩā´¯ā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "remove_from_lock_folder_action_prompt": "{count} ā´Žā´Ŗāĩā´Ŗā´‚ ā´˛āĩ‹ā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¤ ā´Ģāĩ‹āĩžā´Ąā´ąā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¤āĩ", + "remove_from_locked_folder": "ā´˛āĩ‹ā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¤ ā´Ģāĩ‹āĩžā´Ąā´ąā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "remove_from_locked_folder_confirmation": "ⴈ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´‚ ā´˛āĩ‹ā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¤ ā´Ģāĩ‹āĩžā´Ąā´ąā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´Žā´žā´ąāĩā´ąā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹? ā´…ā´ĩ ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋā´¯ā´ŋāĩŊ ā´Ļāĩƒā´ļāĩā´¯ā´Žā´žā´•āĩā´‚.", + "remove_from_shared_link": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´˛ā´ŋā´™āĩā´•ā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "remove_memory": "ā´“āĩŧā´Žāĩā´Ž ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "remove_photo_from_memory": "ⴈ ā´“āĩŧā´Žāĩā´Žā´¯ā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "remove_tag": "ā´Ÿā´žā´—āĩ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "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_tagged_assets": "{count, plural, one {# ā´…ā´¸ā´ąāĩā´ąā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ} other {# ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ}} ā´Ÿā´žā´—āĩ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¤āĩ", + "rename": "ā´Ēāĩā´¨āĩŧā´¨ā´žā´Žā´•ā´°ā´Ŗā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "repair": "ā´ąā´ŋā´Ēāĩā´Ēā´¯āĩŧ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "repair_no_results_message": "ⴟāĩā´°ā´žā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯ā´žā´¤āĩā´¤ā´¤āĩā´‚ ā´•ā´žā´Ŗā´žā´¤ā´žā´¯ā´¤āĩā´Žā´žā´¯ ā´Ģⴝⴞāĩā´•āĩž ā´‡ā´ĩā´ŋⴟāĩ† ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´‚", + "replace_with_upload": "ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ā´Žā´žā´ąāĩā´ąā´ŋā´¸āĩā´Ĩā´žā´Ēā´ŋā´•āĩā´•āĩā´•", + "repository": "ā´ąāĩ†ā´Ēāĩā´Ēāĩ‹ā´¸ā´ŋā´ąāĩā´ąā´ąā´ŋ", + "require_password": "ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´†ā´ĩā´ļāĩā´¯ā´Žā´žā´Ŗāĩ", + "require_user_to_change_password_on_first_login": "ā´†ā´Ļāĩā´¯ ā´˛āĩ‹ā´—ā´ŋāĩģ ⴚāĩ†ā´¯āĩā´¯āĩā´Žāĩā´Ēāĩ‹āĩž ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´Žā´žā´ąāĩā´ąā´žāĩģ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ‹ā´Ÿāĩ ā´†ā´ĩā´ļāĩā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´•", + "rescan": "ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩā´‚ ā´¸āĩā´•ā´žāĩģ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "reset": "ā´ąāĩ€ā´¸āĩ†ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "reset_password": "ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´ąāĩ€ā´¸āĩ†ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "reset_people_visibility": "ⴆⴺāĩā´•ā´ŗāĩā´Ÿāĩ† ā´Ļāĩƒā´ļāĩā´¯ā´¤ ā´Ēāĩā´¨ā´ƒā´¸ā´œāĩā´œā´Žā´žā´•āĩā´•āĩā´•", + "reset_pin_code": "ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ ā´ąāĩ€ā´¸āĩ†ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "reset_pin_code_description": "ā´¨ā´ŋā´™āĩā´™āĩž ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ ā´Žā´ąā´¨āĩā´¨āĩ†ā´™āĩā´•ā´ŋāĩŊ, ā´…ā´¤āĩ ā´Ēāĩā´¨ā´ƒā´¸ā´œāĩā´œā´Žā´žā´•āĩā´•ā´žāĩģ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´¸āĩ†āĩŧā´ĩāĩŧ ā´…ā´Ąāĩā´Žā´ŋā´¨ā´ŋā´¸āĩā´Ÿāĩā´°āĩ‡ā´ąāĩā´ąā´ąāĩā´Žā´žā´¯ā´ŋ ā´Ŧā´¨āĩā´§ā´Ēāĩā´Ēāĩ†ā´Ÿā´žā´‚", + "reset_pin_code_success": "ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ ā´ĩā´ŋā´œā´¯ā´•ā´°ā´Žā´žā´¯ā´ŋ ā´ąāĩ€ā´¸āĩ†ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "reset_pin_code_with_password": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´Žā´Ēāĩā´Ēāĩ‹ā´´āĩā´‚ ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ ā´ąāĩ€ā´¸āĩ†ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´žā´‚", + "reset_sqlite": "SQLite ā´Ąā´žā´ąāĩā´ąā´žā´Ŧāĩ‡ā´¸āĩ ā´ąāĩ€ā´¸āĩ†ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "reset_sqlite_confirmation": "SQLite ā´Ąā´žā´ąāĩā´ąā´žā´Ŧāĩ‡ā´¸āĩ ā´ąāĩ€ā´¸āĩ†ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹? ā´Ąā´žā´ąāĩā´ą ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩā´‚ ā´¸ā´ŋā´™āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩž ā´˛āĩ‹ā´—āĩ ā´”ā´Ÿāĩā´Ÿāĩ ⴚāĩ†ā´¯āĩā´¤āĩ ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩā´‚ ā´˛āĩ‹ā´—ā´ŋāĩģ ⴚāĩ†ā´¯āĩā´¯āĩ‡ā´Ŗāĩā´Ÿā´ŋā´ĩā´°āĩā´‚", + "reset_sqlite_success": "SQLite ā´Ąā´žā´ąāĩā´ąā´žā´Ŧāĩ‡ā´¸āĩ ā´ĩā´ŋā´œā´¯ā´•ā´°ā´Žā´žā´¯ā´ŋ ā´ąāĩ€ā´¸āĩ†ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "reset_to_default": "ā´Ąā´ŋā´Ģāĩ‹āĩžā´Ÿāĩā´Ÿā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Ēāĩā´¨ā´ƒā´¸ā´œāĩā´œā´Žā´žā´•āĩā´•āĩā´•", + "resolve_duplicates": "ā´Ąāĩā´¯āĩ‚ā´Ēāĩā´˛ā´ŋā´•āĩā´•āĩ‡ā´ąāĩā´ąāĩā´•āĩž ā´Ēā´°ā´ŋā´šā´°ā´ŋā´•āĩā´•āĩā´•", + "resolved_all_duplicates": "ā´Žā´˛āĩā´˛ā´ž ā´Ąāĩā´¯āĩ‚ā´Ēāĩā´˛ā´ŋā´•āĩā´•āĩ‡ā´ąāĩā´ąāĩā´•ā´ŗāĩā´‚ ā´Ēā´°ā´ŋā´šā´°ā´ŋⴚāĩā´šāĩ", + "restore": "ā´Ēāĩā´¨ā´ƒā´¸āĩā´Ĩā´žā´Ēā´ŋā´•āĩā´•āĩā´•", + "restore_all": "ā´Žā´˛āĩā´˛ā´žā´‚ ā´Ēāĩā´¨ā´ƒā´¸āĩā´Ĩā´žā´Ēā´ŋā´•āĩā´•āĩā´•", + "restore_trash_action_prompt": "{count} ā´Žā´Ŗāĩā´Ŗā´‚ ⴟāĩā´°ā´žā´ˇā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´Ēāĩā´¨ā´ƒā´¸āĩā´Ĩā´žā´Ēā´ŋⴚāĩā´šāĩ", + "restore_user": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ† ā´Ēāĩā´¨ā´ƒā´¸āĩā´Ĩā´žā´Ēā´ŋā´•āĩā´•āĩā´•", + "restored_asset": "ā´…ā´¸ā´ąāĩā´ąāĩ ā´Ēāĩā´¨ā´ƒā´¸āĩā´Ĩā´žā´Ēā´ŋⴚāĩā´šāĩ", + "resume": "ā´Ēāĩā´¨ā´°ā´žā´°ā´‚ā´­ā´ŋā´•āĩā´•āĩā´•", + "resume_paused_jobs": "{count, plural, one {ā´¤ā´žāĩŊā´•āĩā´•ā´žā´˛ā´ŋā´•ā´Žā´žā´¯ā´ŋ ā´¨ā´ŋāĩŧā´¤āĩā´¤ā´ŋā´¯ # ⴜāĩ‹ā´˛ā´ŋ} other {ā´¤ā´žāĩŊā´•āĩā´•ā´žā´˛ā´ŋā´•ā´Žā´žā´¯ā´ŋ ā´¨ā´ŋāĩŧā´¤āĩā´¤ā´ŋā´¯ # ⴜāĩ‹ā´˛ā´ŋā´•āĩž}} ā´Ēāĩā´¨ā´°ā´žā´°ā´‚ā´­ā´ŋā´•āĩā´•āĩā´•", + "retry_upload": "ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ā´ĩāĩ€ā´Ŗāĩā´Ÿāĩā´‚ ā´ļāĩā´°ā´Žā´ŋā´•āĩā´•āĩā´•", + "review_duplicates": "ā´Ąāĩā´¯āĩ‚ā´Ēāĩā´˛ā´ŋā´•āĩā´•āĩ‡ā´ąāĩā´ąāĩā´•āĩž ā´…ā´ĩā´˛āĩ‹ā´•ⴍⴂ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "review_large_files": "ā´ĩā´˛ā´ŋā´¯ ā´Ģⴝⴞāĩā´•āĩž ā´…ā´ĩā´˛āĩ‹ā´•ⴍⴂ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "role": "ā´ąāĩ‹āĩž", + "role_editor": "ā´Žā´Ąā´ŋā´ąāĩā´ąāĩŧ", + "role_viewer": "ā´•ā´žā´Ŗāĩā´¨āĩā´¨ā´¯ā´žāĩž", + "running": "ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ", + "save": "ā´¸āĩ‡ā´ĩāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "save_to_gallery": "ā´—ā´žā´˛ā´ąā´ŋā´¯ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´¸āĩ‡ā´ĩāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "saved_api_key": "API ā´•āĩ€ ā´¸āĩ‡ā´ĩāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "saved_profile": "ā´Ēāĩā´°āĩŠā´ĢāĩˆāĩŊ ā´¸āĩ‡ā´ĩāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "saved_settings": "ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´¸āĩ‡ā´ĩāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "say_something": "ā´Žā´¨āĩā´¤āĩ†ā´™āĩā´•ā´ŋā´˛āĩā´‚ ā´Ēā´ąā´¯āĩ‚", + "scaffold_body_error_occurred": "ā´Ēā´ŋā´ļā´•āĩ ⴏⴂⴭā´ĩā´ŋⴚāĩā´šāĩ", + "scan_all_libraries": "ā´Žā´˛āĩā´˛ā´ž ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋā´•ā´ŗāĩā´‚ ā´¸āĩā´•ā´žāĩģ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "scan_library": "ā´¸āĩā´•ā´žāĩģ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "scan_settings": "ā´¸āĩā´•ā´žāĩģ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "scanning_for_album": "ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋā´¨ā´žā´¯ā´ŋ ā´¸āĩā´•ā´žāĩģ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ...", + "search": "ā´¤ā´ŋā´°ā´¯āĩā´•", + "search_albums": "ā´†āĩŊā´Ŧā´™āĩā´™āĩžā´•āĩā´•ā´žā´¯ā´ŋ ā´¤ā´ŋā´°ā´¯āĩā´•", + "search_by_context": "ⴏⴍāĩā´Ļāĩŧā´­ā´‚ ā´…ā´¨āĩā´¸ā´°ā´ŋⴚāĩā´šāĩ ā´¤ā´ŋā´°ā´¯āĩā´•", + "search_by_description": "ā´ĩā´ŋā´ĩā´°ā´Ŗā´‚ ā´…ā´¨āĩā´¸ā´°ā´ŋⴚāĩā´šāĩ ā´¤ā´ŋā´°ā´¯āĩā´•", + "search_by_description_example": "ā´¸ā´Ēāĩā´Ēā´¯ā´ŋā´˛āĩ† ā´šāĩˆā´•āĩā´•ā´ŋā´‚ā´—āĩ ā´Ļā´ŋⴍⴂ", + "search_by_filename": "ā´Ģā´¯āĩŊ ā´¨ā´žā´Žā´‚ ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ ā´Žā´•āĩā´¸āĩā´ąāĩā´ąāĩģā´ˇāĩģ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ā´¤ā´ŋā´°ā´¯āĩā´•", + "search_by_filename_example": "ā´‰ā´Ļā´ž. IMG_1234.JPG ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ PNG", + "search_camera_make": "ā´•āĩā´¯ā´žā´Žā´ą ā´¨ā´ŋāĩŧā´Žāĩā´Žā´žā´¤ā´žā´ĩā´ŋā´¨ā´žā´¯ā´ŋ ā´¤ā´ŋā´°ā´¯āĩā´•...", + "search_camera_model": "ā´•āĩā´¯ā´žā´Žā´ą ā´Žāĩ‹ā´Ąā´˛ā´ŋā´¨ā´žā´¯ā´ŋ ā´¤ā´ŋā´°ā´¯āĩā´•...", + "search_city": "ⴍⴗⴰⴤāĩā´¤ā´ŋā´¨ā´žā´¯ā´ŋ ā´¤ā´ŋā´°ā´¯āĩā´•...", + "search_country": "ā´°ā´žā´œāĩā´¯ā´¤āĩā´¤ā´ŋā´¨ā´žā´¯ā´ŋ ā´¤ā´ŋā´°ā´¯āĩā´•...", + "search_filter_apply": "ā´Ģā´ŋāĩŊⴟāĩā´Ÿāĩŧ ā´Ēāĩā´°ā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•", + "search_filter_camera_title": "ā´•āĩā´¯ā´žā´Žā´ą ⴤⴰⴂ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "search_filter_date": "ā´¤āĩ€ā´¯ā´¤ā´ŋ", + "search_filter_date_interval": "{start} ā´Žāĩā´¤āĩŊ {end} ā´ĩā´°āĩ†", + "search_filter_date_title": "ā´’ā´°āĩ ā´¤āĩ€ā´¯ā´¤ā´ŋ ā´Ēā´°ā´ŋā´§ā´ŋ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "search_filter_display_option_not_in_album": "ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋāĩŊ ⴇⴞāĩā´˛", + "search_filter_display_options": "ā´Ēāĩā´°ā´Ļāĩŧā´ļā´¨ ā´“ā´Ēāĩā´ˇā´¨āĩā´•āĩž", + "search_filter_filename": "ā´Ģā´¯āĩŊ ā´¨ā´žā´Žā´‚ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ā´¤ā´ŋā´°ā´¯āĩā´•", + "search_filter_location": "ā´¸āĩā´Ĩā´žā´¨ā´‚", + "search_filter_location_title": "ā´¸āĩā´Ĩā´žā´¨ā´‚ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "search_filter_media_type": "ā´Žāĩ€ā´Ąā´ŋā´¯ ⴤⴰⴂ", + "search_filter_media_type_title": "ā´Žāĩ€ā´Ąā´ŋā´¯ ⴤⴰⴂ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "search_filter_people_title": "ⴆⴺāĩā´•ā´ŗāĩ† ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "search_for": "ⴇⴤā´ŋā´¨ā´žā´¯ā´ŋ ā´¤ā´ŋā´°ā´¯āĩā´•", + "search_for_existing_person": "ā´¨ā´ŋā´˛ā´ĩā´ŋā´˛āĩā´ŗāĩā´ŗ ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´•āĩā´•ā´žā´¯ā´ŋ ā´¤ā´ŋā´°ā´¯āĩā´•", + "search_no_more_result": "ā´•āĩ‚ā´Ÿāĩā´¤āĩŊ ā´Ģⴞⴙāĩā´™ā´ŗā´ŋā´˛āĩā´˛", + "search_no_people": "ⴆⴺāĩā´•ā´ŗā´ŋā´˛āĩā´˛", + "search_no_people_named": "\"{name}\" ā´Žā´¨āĩā´¨āĩ ā´Ēāĩ‡ā´°āĩā´ŗāĩā´ŗ ⴆⴺāĩā´•ā´ŗā´ŋā´˛āĩā´˛", + "search_no_result": "ā´Ģⴞⴙāĩā´™ā´ŗāĩŠā´¨āĩā´¨āĩā´‚ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´ŋā´¯ā´ŋā´˛āĩā´˛, ā´Žā´ąāĩā´ąāĩŠā´°āĩ ā´¤ā´ŋā´°ā´¯āĩŊ ā´Ēā´Ļā´Žāĩ‹ ⴏⴂⴝāĩ‹ā´œā´¨ā´Žāĩ‹ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ā´ļāĩā´°ā´Žā´ŋā´•āĩā´•āĩā´•", + "search_options": "ā´¤ā´ŋā´°ā´¯āĩŊ ā´“ā´Ēāĩā´ˇā´¨āĩā´•āĩž", + "search_page_categories": "ā´ĩā´ŋā´­ā´žā´—ā´™āĩā´™āĩž", + "search_page_motion_photos": "ⴚⴞā´ŋā´•āĩā´•āĩā´¨āĩā´¨ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž", + "search_page_no_objects": "ā´ĩā´¸āĩā´¤āĩā´•āĩā´•ā´ŗāĩā´Ÿāĩ† ā´ĩā´ŋā´ĩā´°ā´™āĩā´™āĩž ⴞⴭāĩā´¯ā´Žā´˛āĩā´˛", + "search_page_no_places": "ā´¸āĩā´Ĩⴞⴙāĩā´™ā´ŗāĩā´Ÿāĩ† ā´ĩā´ŋā´ĩā´°ā´™āĩā´™āĩž ⴞⴭāĩā´¯ā´Žā´˛āĩā´˛", + "search_page_screenshots": "ā´¸āĩā´•āĩā´°āĩ€āĩģā´ˇāĩ‹ā´Ÿāĩā´Ÿāĩā´•āĩž", + "search_page_search_photos_videos": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩžā´•āĩā´•āĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•āĩžā´•āĩā´•āĩā´Žā´žā´¯ā´ŋ ā´¤ā´ŋā´°ā´¯āĩā´•", + "search_page_selfies": "ā´¸āĩ†āĩŊā´Ģā´ŋā´•āĩž", + "search_page_things": "ā´ĩā´¸āĩā´¤āĩā´•āĩā´•āĩž", + "search_page_view_all_button": "ā´Žā´˛āĩā´˛ā´žā´‚ ā´•ā´žā´Ŗāĩā´•", + "search_page_your_activity": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´‚", + "search_page_your_map": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Žā´žā´Ēāĩā´Ēāĩ", + "search_people": "ⴆⴺāĩā´•ā´ŗāĩ† ā´¤ā´ŋā´°ā´¯āĩā´•", + "search_places": "ā´¸āĩā´Ĩⴞⴙāĩā´™āĩž ā´¤ā´ŋā´°ā´¯āĩā´•", + "search_rating": "ā´ąāĩ‡ā´ąāĩā´ąā´ŋā´‚ā´—āĩ ā´…ā´¨āĩā´¸ā´°ā´ŋⴚāĩā´šāĩ ā´¤ā´ŋā´°ā´¯āĩā´•...", + "search_result_page_new_search_hint": "ā´Ēāĩā´¤ā´ŋā´¯ ā´¤ā´ŋā´°ā´¯āĩŊ", + "search_settings": "ā´¤ā´ŋā´°ā´¯āĩŊ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "search_state": "ⴏⴂⴏāĩā´Ĩā´žā´¨ā´‚ ā´¤ā´ŋā´°ā´¯āĩā´•...", + "search_suggestion_list_smart_search_hint_1": "ā´¸āĩā´Žā´žāĩŧⴟāĩā´Ÿāĩ ā´¸āĩ†āĩŧⴚāĩā´šāĩ ā´Ąā´ŋā´Ģāĩ‹āĩžā´Ÿāĩā´Ÿā´žā´¯ā´ŋ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•ā´ŋā´¯ā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ, ā´Žāĩ†ā´ąāĩā´ąā´žā´Ąā´žā´ąāĩā´ąā´¯āĩā´•āĩā´•ā´žā´¯ā´ŋ ā´¤ā´ŋā´°ā´¯ā´žāĩģ ⴈ ā´ĩā´žā´•āĩā´¯ā´˜ā´Ÿā´¨ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´• ", + "search_suggestion_list_smart_search_hint_2": "m:ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ†-ā´¤ā´ŋā´°ā´¯āĩŊ-ā´Ēā´Ļā´‚", + "search_tags": "ā´Ÿā´žā´—āĩā´•āĩžā´•āĩā´•ā´žā´¯ā´ŋ ā´¤ā´ŋā´°ā´¯āĩā´•...", + "search_timezone": "ā´¸ā´Žā´¯ā´Žāĩ‡ā´–ⴞⴝāĩā´•āĩā´•ā´žā´¯ā´ŋ ā´¤ā´ŋā´°ā´¯āĩā´•...", + "search_type": "ā´¤ā´ŋā´°ā´¯āĩŊ ⴤⴰⴂ", + "search_your_photos": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž ā´¤ā´ŋā´°ā´¯āĩā´•", + "searching_locales": "ā´˛āĩŠā´•āĩā´•āĩ‡ā´˛āĩā´•āĩžā´•āĩā´•ā´žā´¯ā´ŋ ā´¤ā´ŋā´°ā´¯āĩā´¨āĩā´¨āĩ...", + "second": "ā´¸āĩ†ā´•āĩā´•ā´¨āĩā´ąāĩ", + "see_all_people": "ā´Žā´˛āĩā´˛ā´ž ⴆⴺāĩā´•ā´ŗāĩ†ā´¯āĩā´‚ ā´•ā´žā´Ŗāĩā´•", + "select": "ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "select_album_cover": "ā´†āĩŊā´Ŧā´‚ ā´•ā´ĩāĩŧ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "select_all": "ā´Žā´˛āĩā´˛ā´žā´‚ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "select_all_duplicates": "ā´Žā´˛āĩā´˛ā´ž ā´Ąāĩā´¯āĩ‚ā´Ēāĩā´˛ā´ŋā´•āĩā´•āĩ‡ā´ąāĩā´ąāĩā´•ā´ŗāĩā´‚ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "select_all_in": "{group}-ā´˛āĩ† ā´Žā´˛āĩā´˛ā´žā´‚ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "select_avatar_color": "ā´…ā´ĩā´¤ā´žāĩŧ ā´¨ā´ŋā´ąā´‚ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "select_face": "ā´Žāĩā´–ā´‚ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "select_featured_photo": "ā´Ģāĩ€ā´šāĩā´šāĩŧ ⴚāĩ†ā´¯āĩā´¤ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "select_from_computer": "ā´•ā´Žāĩā´Ēāĩā´¯āĩ‚ā´Ÿāĩā´Ÿā´ąā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "select_keep_all": "ā´Žā´˛āĩā´˛ā´žā´‚ ā´¸āĩ‚ā´•āĩā´ˇā´ŋā´•āĩā´•ā´žāĩģ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "select_library_owner": "ā´˛āĩˆā´Ŧāĩā´°ā´ąā´ŋ ā´‰ā´Ÿā´Žā´¯āĩ† ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "select_new_face": "ā´Ēāĩā´¤ā´ŋā´¯ ā´Žāĩā´–ā´‚ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "select_person_to_tag": "ā´Ÿā´žā´—āĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´’ā´°āĩ ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´¯āĩ† ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "select_photos": "ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "select_trash_all": "ā´Žā´˛āĩā´˛ā´žā´‚ ⴟāĩā´°ā´žā´ˇāĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "select_user_for_sharing_page_err_album": "ā´†āĩŊā´Ŧā´‚ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´°ā´žā´œā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "selected": "ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´¤āĩā´¤āĩ", + "selected_count": "{count, plural, other {# ā´Žā´Ŗāĩā´Ŗā´‚ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´¤āĩā´¤āĩ}}", + "selected_gps_coordinates": "ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´¤āĩā´¤ GPS ā´•āĩ‹āĩŧā´Ąā´ŋā´¨āĩ‡ā´ąāĩā´ąāĩā´•āĩž", + "send_message": "ⴏⴍāĩā´Ļāĩ‡ā´ļā´‚ ⴅⴝⴕāĩā´•āĩā´•", + "send_welcome_email": "ā´¸āĩā´ĩā´žā´—ā´¤ ā´‡ā´Žāĩ†ā´¯ā´ŋāĩŊ ⴅⴝⴕāĩā´•āĩā´•", + "server_endpoint": "ā´¸āĩ†āĩŧā´ĩāĩŧ ā´Žāĩģā´Ąāĩâ€Œā´Ēāĩ‹ā´¯ā´ŋā´¨āĩā´ąāĩ", + "server_info_box_app_version": "ā´†ā´Ēāĩā´Ēāĩ ā´Ēā´¤ā´ŋā´Ēāĩā´Ēāĩ", + "server_info_box_server_url": "ā´¸āĩ†āĩŧā´ĩāĩŧ URL", + "server_offline": "ā´¸āĩ†āĩŧā´ĩāĩŧ ā´“ā´Ģāĩâ€Œā´˛āĩˆāĩģ", + "server_online": "ā´¸āĩ†āĩŧā´ĩāĩŧ ā´“āĩēā´˛āĩˆāĩģ", + "server_privacy": "ā´¸āĩ†āĩŧā´ĩāĩŧ ā´¸āĩā´ĩā´•ā´žā´°āĩā´¯ā´¤", + "server_stats": "ā´¸āĩ†āĩŧā´ĩāĩŧ ā´¸āĩā´Ĩā´ŋā´¤ā´ŋā´ĩā´ŋā´ĩā´°ā´•āĩā´•ā´Ŗā´•āĩā´•āĩā´•āĩž", + "server_version": "ā´¸āĩ†āĩŧā´ĩāĩŧ ā´Ēā´¤ā´ŋā´Ēāĩā´Ēāĩ", + "set": "ⴏⴜāĩā´œā´Žā´žā´•āĩā´•āĩā´•", + "set_as_album_cover": "ā´†āĩŊā´Ŧā´‚ ā´•ā´ĩā´ąā´žā´¯ā´ŋ ⴏⴜāĩā´œā´Žā´žā´•āĩā´•āĩā´•", + "set_as_featured_photo": "ā´Ģāĩ€ā´šāĩā´šāĩŧ ⴚāĩ†ā´¯āĩā´¤ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´¯ā´žā´¯ā´ŋ ⴏⴜāĩā´œā´Žā´žā´•āĩā´•āĩā´•", + "set_as_profile_picture": "ā´Ēāĩā´°āĩŠā´ĢāĩˆāĩŊ ⴚā´ŋā´¤āĩā´°ā´Žā´žā´¯ā´ŋ ⴏⴜāĩā´œā´Žā´žā´•āĩā´•āĩā´•", + "set_date_of_birth": "ⴜⴍⴍⴤāĩā´¤āĩ€ā´¯ā´¤ā´ŋ ⴏⴜāĩā´œā´Žā´žā´•āĩā´•āĩā´•", + "set_profile_picture": "ā´Ēāĩā´°āĩŠā´ĢāĩˆāĩŊ ⴚā´ŋā´¤āĩā´°ā´‚ ⴏⴜāĩā´œā´Žā´žā´•āĩā´•āĩā´•", + "set_slideshow_to_fullscreen": "ā´¸āĩā´˛āĩˆā´Ąāĩâ€Œā´ˇāĩ‹ ā´Ģāĩāĩžā´¸āĩā´•āĩā´°āĩ€ā´¨ā´žā´¯ā´ŋ ⴏⴜāĩā´œā´Žā´žā´•āĩā´•āĩā´•", + "set_stack_primary_asset": "ā´Ēāĩā´°ā´§ā´žā´¨ ā´…ā´¸ā´ąāĩā´ąā´žā´¯ā´ŋ ⴏⴜāĩā´œā´Žā´žā´•āĩā´•āĩā´•", + "setting_image_viewer_help": "ā´ĩā´ŋā´ļā´Ļā´žā´‚ā´ļ ā´ĩāĩā´¯āĩ‚ā´ĩāĩŧ ā´†ā´Ļāĩā´¯ā´‚ ⴚāĩ†ā´ąā´ŋā´¯ ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋāĩŊ ā´˛āĩ‹ā´Ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ, ā´¤āĩā´Ÿāĩŧā´¨āĩā´¨āĩ ā´‡ā´Ÿā´¤āĩā´¤ā´°ā´‚ ā´Ēāĩā´°ā´ŋā´ĩāĩā´¯āĩ‚ (ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•ā´ŋā´¯ā´ŋⴟāĩā´Ÿāĩā´Ŗāĩā´Ÿāĩ†ā´™āĩā´•ā´ŋāĩŊ), ā´’ā´Ÿāĩā´ĩā´ŋāĩŊ ā´¯ā´Ĩā´žāĩŧā´¤āĩā´Ĩ ⴚā´ŋā´¤āĩā´°ā´‚ (ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•ā´ŋā´¯ā´ŋⴟāĩā´Ÿāĩā´Ŗāĩā´Ÿāĩ†ā´™āĩā´•ā´ŋāĩŊ) ā´˛āĩ‹ā´Ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ.", + "setting_image_viewer_original_subtitle": "ā´¯ā´Ĩā´žāĩŧā´¤āĩā´Ĩ ā´Ēāĩ‚āĩŧā´Ŗāĩā´Ŗ-ā´ąāĩ†ā´¸ā´˛āĩā´¯āĩ‚ā´ˇāĩģ ⴚā´ŋā´¤āĩā´°ā´‚ (ā´ĩā´˛āĩā´¤āĩ!) ā´˛āĩ‹ā´Ąāĩā´šāĩ†ā´¯āĩā´¯ā´žāĩģ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´•. ā´Ąā´žā´ąāĩā´ą ā´‰ā´Ēā´¯āĩ‹ā´—ā´‚ (ā´¨āĩ†ā´ąāĩā´ąāĩâ€Œā´ĩāĩŧā´•āĩā´•āĩā´‚ ā´‰ā´Ēā´•ā´°ā´Ŗ ā´•ā´žā´ˇāĩ†ā´¯āĩā´‚) ā´•āĩā´ąā´¯āĩā´•āĩā´•ā´žāĩģ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•āĩā´•.", + "setting_image_viewer_original_title": "ā´¯ā´Ĩā´žāĩŧā´¤āĩā´Ĩ ⴚā´ŋā´¤āĩā´°ā´‚ ā´˛āĩ‹ā´Ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "setting_image_viewer_preview_subtitle": "ā´‡ā´Ÿā´¤āĩā´¤ā´°ā´‚ ā´ąāĩ†ā´¸ā´˛āĩā´¯āĩ‚ⴎⴍāĩā´ŗāĩā´ŗ ⴚā´ŋā´¤āĩā´°ā´‚ ā´˛āĩ‹ā´Ąāĩā´šāĩ†ā´¯āĩā´¯ā´žāĩģ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´•. ā´’ā´¨āĩā´¨āĩā´•ā´ŋāĩŊ ā´¯ā´Ĩā´žāĩŧā´¤āĩā´Ĩ ⴚā´ŋā´¤āĩā´°ā´‚ ā´¨āĩ‡ā´°ā´ŋⴟāĩā´Ÿāĩ ā´˛āĩ‹ā´Ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ‹ ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋāĩŊ ā´Žā´žā´¤āĩā´°ā´‚ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ‹ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•āĩā´•.", + "setting_image_viewer_preview_title": "ā´Ēāĩā´°ā´ŋā´ĩāĩā´¯āĩ‚ ⴚā´ŋā´¤āĩā´°ā´‚ ā´˛āĩ‹ā´Ąāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "setting_image_viewer_title": "ⴚā´ŋā´¤āĩā´°ā´™āĩā´™āĩž", + "setting_languages_apply": "ā´Ēāĩā´°ā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•", + "setting_languages_subtitle": "ā´†ā´Ēāĩā´Ēā´ŋā´¨āĩā´ąāĩ† ā´­ā´žā´ˇ ā´Žā´žā´ąāĩā´ąāĩā´•", + "setting_notifications_notify_failures_grace_period": "ā´Ēā´ļāĩā´šā´žā´¤āĩā´¤ā´˛ ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ā´Ēā´°ā´žā´œā´¯ā´™āĩā´™āĩž ā´…ā´ąā´ŋā´¯ā´ŋā´•āĩā´•āĩā´•: {duration}", + "setting_notifications_notify_hours": "{count} ā´Žā´Ŗā´ŋā´•āĩā´•āĩ‚āĩŧ", + "setting_notifications_notify_immediately": "ā´‰ā´Ÿā´¨ā´Ÿā´ŋ", + "setting_notifications_notify_minutes": "{count} ā´Žā´ŋā´¨ā´ŋā´ąāĩā´ąāĩ", + "setting_notifications_notify_never": "ā´’ā´°ā´ŋā´•āĩā´•ā´˛āĩā´‚", + "setting_notifications_notify_seconds": "{count} ā´¸āĩ†ā´•āĩā´•āĩģā´Ąāĩ", + "setting_notifications_single_progress_subtitle": "ā´“ā´°āĩ‹ ā´…ā´¸ā´ąāĩā´ąā´ŋā´¨āĩā´ąāĩ†ā´¯āĩā´‚ ā´ĩā´ŋā´ļā´Ļā´Žā´žā´¯ ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ā´Ēāĩā´°āĩ‹ā´—ā´¤ā´ŋ ā´ĩā´ŋā´ĩā´°ā´‚", + "setting_notifications_single_progress_title": "ā´Ēā´ļāĩā´šā´žā´¤āĩā´¤ā´˛ ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēā´ŋā´¨āĩā´ąāĩ† ā´ĩā´ŋā´ļā´Ļā´Žā´žā´¯ ā´Ēāĩā´°āĩ‹ā´—ā´¤ā´ŋ ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•", + "setting_notifications_subtitle": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´…ā´ąā´ŋā´¯ā´ŋā´Ēāĩā´Ēāĩ ā´Žāĩāĩģⴗ⴪ⴍⴕāĩž ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´•", + "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_title": "ā´¯ā´Ĩā´žāĩŧā´¤āĩā´Ĩ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ ā´¨ā´ŋāĩŧā´Ŧā´¨āĩā´§ā´Žā´žā´•āĩā´•āĩā´•", + "settings": "ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "settings_require_restart": "ⴈ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´‚ ā´Ēāĩā´°ā´¯āĩ‹ā´—ā´ŋā´•āĩā´•ā´žāĩģ ā´Ļā´¯ā´ĩā´žā´¯ā´ŋ Immich ā´Ēāĩā´¨ā´°ā´žā´°ā´‚ā´­ā´ŋā´•āĩā´•āĩā´•", + "settings_saved": "ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ā´¸āĩ‡ā´ĩāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "setup_pin_code": "ā´’ā´°āĩ ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ ⴏⴜāĩā´œāĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´•", + "share": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´•", + "share_action_prompt": "{count} ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿāĩ", + "share_add_photos": "ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž ⴚāĩ‡āĩŧā´•āĩā´•āĩā´•", + "share_assets_selected": "{count} ā´Žā´Ŗāĩā´Ŗā´‚ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´¤āĩā´¤āĩ", + "share_dialog_preparing": "ⴤⴝāĩā´¯ā´žā´ąā´žā´•āĩā´•āĩā´¨āĩā´¨āĩ...", + "share_link": "ā´˛ā´ŋā´™āĩā´•āĩ ā´Ēā´™āĩā´•ā´ŋⴟāĩā´•", + "shared": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿā´¤āĩ", + "shared_album_activities_input_disable": "ā´…ā´­ā´ŋā´Ēāĩā´°ā´žā´¯ā´‚ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•ā´ŋ", + "shared_album_activity_remove_content": "ⴈ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´‚ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´Ŗāĩ‹?", + "shared_album_activity_remove_title": "ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´‚ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´•", + "shared_album_section_people_action_error": "ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´ĩā´ŋⴟāĩā´Ÿāĩā´Ēāĩ‹ā´•āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ‹/ā´¨āĩ€ā´•āĩā´•ā´‚ā´šāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ‹ ā´Ēā´ŋā´ļā´•āĩ", + "shared_album_section_people_action_leave": "ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ† ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "shared_album_section_people_action_remove_user": "ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ† ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "shared_album_section_people_title": "ⴆⴺāĩā´•āĩž", + "shared_by": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿā´¤āĩ", + "shared_by_user": "{user} ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿāĩ", + "shared_by_you": "ā´¨ā´ŋā´™āĩā´™āĩž ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿā´¤āĩ", + "shared_from_partner": "{partner}-āĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩā´ŗāĩā´ŗ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž", + "shared_intent_upload_button_progress_text": "{current}/{total} ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "shared_link_app_bar_title": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´˛ā´ŋā´™āĩā´•āĩā´•āĩž", + "shared_link_clipboard_copied_massage": "ā´•āĩā´˛ā´ŋā´Ēāĩā´Ēāĩā´Ŧāĩ‹āĩŧā´Ąā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Ēā´•āĩŧā´¤āĩā´¤ā´ŋ", + "shared_link_clipboard_text": "ā´˛ā´ŋā´™āĩā´•āĩ: {link}\nā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ: {password}", + "shared_link_create_error": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´˛ā´ŋā´™āĩā´•āĩ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´¨āĩā´¨ā´¤ā´ŋāĩŊ ā´Ēā´ŋā´ļā´•āĩ", + "shared_link_custom_url_description": "ā´’ā´°āĩ ā´•ā´¸āĩā´ąāĩā´ąā´‚ URL ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ⴈ ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´˛ā´ŋā´™āĩā´•āĩ ⴆⴕāĩâ€Œā´¸ā´¸āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "shared_link_edit_description_hint": "ā´Ēā´™āĩā´•ā´ŋⴟⴞā´ŋā´¨āĩā´ąāĩ† ā´ĩā´ŋā´ĩā´°ā´Ŗā´‚ ā´¨āĩŊā´•āĩā´•", + "shared_link_edit_expire_after_option_day": "1 ā´Ļā´ŋā´ĩⴏⴂ", + "shared_link_edit_expire_after_option_days": "{count} ā´Ļā´ŋā´ĩⴏⴙāĩā´™āĩž", + "shared_link_edit_expire_after_option_hour": "1 ā´Žā´Ŗā´ŋā´•āĩā´•āĩ‚āĩŧ", + "shared_link_edit_expire_after_option_hours": "{count} ā´Žā´Ŗā´ŋā´•āĩā´•āĩ‚ā´ąāĩā´•āĩž", + "shared_link_edit_expire_after_option_minute": "1 ā´Žā´ŋā´¨ā´ŋā´ąāĩā´ąāĩ", + "shared_link_edit_expire_after_option_minutes": "{count} ā´Žā´ŋā´¨ā´ŋā´ąāĩā´ąāĩā´•āĩž", + "shared_link_edit_expire_after_option_months": "{count} ā´Žā´žā´¸ā´™āĩā´™āĩž", + "shared_link_edit_expire_after_option_year": "{count} ā´ĩāĩŧⴎⴂ", + "shared_link_edit_password_hint": "ā´Ēā´™āĩā´•ā´ŋⴟⴞā´ŋā´¨āĩā´ąāĩ† ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´¨āĩŊā´•āĩā´•", + "shared_link_edit_submit_button": "ā´˛ā´ŋā´™āĩā´•āĩ ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "shared_link_error_server_url_fetch": "ā´¸āĩ†āĩŧā´ĩāĩŧ url ⴞⴭāĩā´¯ā´Žā´žā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "shared_link_expires_day": "{count} ā´Ļā´ŋā´ĩⴏⴤāĩā´¤ā´ŋā´¨āĩā´ŗāĩā´ŗā´ŋāĩŊ ā´•ā´žā´˛ā´šā´°ā´Ŗā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´‚", + "shared_link_expires_days": "{count} ā´Ļā´ŋā´ĩⴏⴙāĩā´™āĩžā´•āĩā´•āĩā´ŗāĩā´ŗā´ŋāĩŊ ā´•ā´žā´˛ā´šā´°ā´Ŗā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´‚", + "shared_link_expires_hour": "{count} ā´Žā´Ŗā´ŋā´•āĩā´•āĩ‚ā´ąā´ŋā´¨āĩā´ŗāĩā´ŗā´ŋāĩŊ ā´•ā´žā´˛ā´šā´°ā´Ŗā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´‚", + "shared_link_expires_hours": "{count} ā´Žā´Ŗā´ŋā´•āĩā´•āĩ‚ā´ąāĩā´•āĩžā´•āĩā´•āĩā´ŗāĩā´ŗā´ŋāĩŊ ā´•ā´žā´˛ā´šā´°ā´Ŗā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´‚", + "shared_link_expires_minute": "{count} ā´Žā´ŋā´¨ā´ŋā´ąāĩā´ąā´ŋā´¨āĩā´ŗāĩā´ŗā´ŋāĩŊ ā´•ā´žā´˛ā´šā´°ā´Ŗā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´‚", + "shared_link_expires_minutes": "{count} ā´Žā´ŋā´¨ā´ŋā´ąāĩā´ąāĩā´•āĩžā´•āĩā´•āĩā´ŗāĩā´ŗā´ŋāĩŊ ā´•ā´žā´˛ā´šā´°ā´Ŗā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´‚", + "shared_link_expires_never": "ā´•ā´žā´˛ā´šā´°ā´Ŗā´Ēāĩā´Ēāĩ†ā´Ÿā´ŋā´˛āĩā´˛ ∞", + "shared_link_expires_second": "{count} ā´¸āĩ†ā´•āĩā´•āĩģā´Ąā´ŋā´¨āĩā´ŗāĩā´ŗā´ŋāĩŊ ā´•ā´žā´˛ā´šā´°ā´Ŗā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´‚", + "shared_link_expires_seconds": "{count} ā´¸āĩ†ā´•āĩā´•āĩģā´Ąāĩā´•āĩžā´•āĩā´•āĩā´ŗāĩā´ŗā´ŋāĩŊ ā´•ā´žā´˛ā´šā´°ā´Ŗā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´‚", + "shared_link_individual_shared": "ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´—ā´¤ā´Žā´žā´¯ā´ŋ ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿā´¤āĩ", + "shared_link_info_chip_metadata": "EXIF", + "shared_link_manage_links": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´˛ā´ŋā´™āĩā´•āĩā´•āĩž ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "shared_link_options": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´˛ā´ŋā´™āĩā´•āĩ ā´“ā´Ēāĩā´ˇā´¨āĩā´•āĩž", + "shared_link_password_description": "ⴈ ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´˛ā´ŋā´™āĩā´•āĩ ⴆⴕāĩâ€Œā´¸ā´¸āĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´’ā´°āĩ ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´†ā´ĩā´ļāĩā´¯ā´Žā´žā´Ŗāĩ", + "shared_links": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´˛ā´ŋā´™āĩā´•āĩā´•āĩž", + "shared_links_description": "ā´’ā´°āĩ ā´˛ā´ŋā´™āĩā´•āĩ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´‚ ā´Ēā´™āĩā´•ā´ŋⴟāĩā´•", + "shared_photos_and_videos_count": "{assetCount, plural, other {ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ # ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´‚.}}", + "shared_with_me": "ā´Žā´¨ā´ŋā´•āĩā´•ā´žā´¯ā´ŋ ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿā´¤āĩ", + "shared_with_partner": "{partner}-ā´Žā´žā´¯ā´ŋ ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿāĩ", + "sharing": "ā´Ēā´™āĩā´•ā´ŋⴟāĩŊ", + "sharing_enter_password": "ⴈ ā´Ēāĩ‡ā´œāĩ ā´•ā´žā´Ŗāĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ ā´Ļā´¯ā´ĩā´žā´¯ā´ŋ ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´¨āĩŊā´•āĩā´•.", + "sharing_page_album": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´†āĩŊā´Ŧā´™āĩā´™āĩž", + "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": "ā´…ā´¸ā´ąāĩā´ąāĩ ā´ļā´žā´ļāĩā´ĩā´¤ā´Žā´žā´¯ā´ŋ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´žāĩģ ⇧ ā´…ā´Žāĩŧā´¤āĩā´¤āĩā´•", + "show_album_options": "ā´†āĩŊā´Ŧā´‚ ā´“ā´Ēāĩā´ˇā´¨āĩā´•āĩž ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•", + "show_albums": "ā´†āĩŊā´Ŧā´™āĩā´™āĩž ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•", + "show_all_people": "ā´Žā´˛āĩā´˛ā´ž ⴆⴺāĩā´•ā´ŗāĩ†ā´¯āĩā´‚ ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•", + "show_and_hide_people": "ⴆⴺāĩā´•ā´ŗāĩ† ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•ā´¯āĩā´‚ ā´Žā´ąā´¯āĩā´•āĩā´•āĩā´•ā´¯āĩā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "show_file_location": "ā´Ģⴝⴞā´ŋā´¨āĩā´ąāĩ† ā´¸āĩā´Ĩā´žā´¨ā´‚ ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•", + "show_gallery": "ā´—ā´žā´˛ā´ąā´ŋ ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•", + "show_hidden_people": "ā´Žā´ąā´šāĩā´š ⴆⴺāĩā´•ā´ŗāĩ† ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•", + "show_in_timeline": "ⴟāĩˆā´‚ā´˛āĩˆā´¨ā´ŋāĩŊ ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•", + "show_in_timeline_setting_description": "ⴈ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩā´ŗāĩā´ŗ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´‚ ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ⴟāĩˆā´‚ā´˛āĩˆā´¨ā´ŋāĩŊ ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•", + "show_keyboard_shortcuts": "ā´•āĩ€ā´Ŧāĩ‹āĩŧā´Ąāĩ ā´•āĩā´ąāĩā´•āĩā´•āĩā´ĩā´´ā´ŋā´•āĩž ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•", + "show_metadata": "ā´Žāĩ†ā´ąāĩā´ąā´žā´Ąā´žā´ąāĩā´ą ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•", + "show_or_hide_info": "ā´ĩā´ŋā´ĩā´°ā´™āĩā´™āĩž ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´• ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ ā´Žā´ąā´¯āĩā´•āĩā´•āĩā´•", + "show_password": "ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•", + "show_person_options": "ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´¯āĩā´Ÿāĩ† ā´“ā´Ēāĩā´ˇā´¨āĩā´•āĩž ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•", + "show_progress_bar": "ā´Ēāĩā´°āĩ‹ā´—ā´¤ā´ŋ ā´Ŧā´žāĩŧ ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•", + "show_search_options": "ā´¤ā´ŋā´°ā´¯āĩŊ ā´“ā´Ēāĩā´ˇā´¨āĩā´•āĩž ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•", + "show_shared_links": "ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´˛ā´ŋā´™āĩā´•āĩā´•āĩž ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•", + "show_slideshow_transition": "ā´¸āĩā´˛āĩˆā´Ąāĩâ€Œā´ˇāĩ‹ ⴏⴂⴕāĩā´°ā´Žā´Ŗā´‚ ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•", + "show_supporter_badge": "ā´¸ā´šā´žā´¯ā´ŋā´¯āĩā´Ÿāĩ† ā´Ŧā´žā´Ąāĩā´œāĩ", + "show_supporter_badge_description": "ā´’ā´°āĩ ā´¸ā´šā´žā´¯ā´ŋā´¯āĩā´Ÿāĩ† ā´Ŧā´žā´Ąāĩā´œāĩ ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•", + "show_text_search_menu": "ⴟāĩ†ā´•āĩā´¸āĩā´ąāĩā´ąāĩ ā´¤ā´ŋā´°ā´¯āĩŊ ā´Žāĩ†ā´¨āĩ ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•", + "shuffle": "ā´ˇā´Ģā´ŋāĩž ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "sidebar": "ā´¸āĩˆā´Ąāĩâ€Œā´Ŧā´žāĩŧ", + "sidebar_display_description": "ā´¸āĩˆā´Ąāĩâ€Œā´Ŧā´žā´ąā´ŋā´˛āĩ† ā´•ā´žā´´āĩâ€Œā´šā´¯ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´’ā´°āĩ ā´˛ā´ŋā´™āĩā´•āĩ ā´Ēāĩā´°ā´Ļāĩŧā´ļā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´•", + "sign_out": "ā´¸āĩˆāĩģ ā´”ā´Ÿāĩā´Ÿāĩ", + "sign_up": "ā´¸āĩˆāĩģ ā´…ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "size": "ā´ĩā´˛ā´ŋā´Ēāĩā´Ēā´‚", + "skip_to_content": "ⴉⴺāĩā´ŗā´Ÿā´•āĩā´•ā´¤āĩā´¤ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Ēāĩ‹ā´•āĩā´•", + "skip_to_folders": "ā´Ģāĩ‹āĩžā´Ąā´ąāĩā´•ā´ŗā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Ēāĩ‹ā´•āĩā´•", + "skip_to_tags": "ā´Ÿā´žā´—āĩā´•ā´ŗā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Ēāĩ‹ā´•āĩā´•", + "slideshow": "ā´¸āĩā´˛āĩˆā´Ąāĩâ€Œā´ˇāĩ‹", + "slideshow_settings": "ā´¸āĩā´˛āĩˆā´Ąāĩâ€Œā´ˇāĩ‹ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž", + "sort_albums_by": "ā´†āĩŊā´Ŧā´™āĩā´™ā´ŗāĩ† ⴇⴤⴍāĩā´¸ā´°ā´ŋⴚāĩā´šāĩ ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´•...", + "sort_created": "ā´¸āĩƒā´ˇāĩā´Ÿā´ŋⴚāĩā´š ā´¤āĩ€ā´¯ā´¤ā´ŋ", + "sort_items": "ⴇⴍⴙāĩā´™ā´ŗāĩā´Ÿāĩ† ā´Žā´Ŗāĩā´Ŗā´‚", + "sort_modified": "ā´Žā´žā´ąāĩā´ąā´‚ ā´ĩā´°āĩā´¤āĩā´¤ā´ŋā´¯ ā´¤āĩ€ā´¯ā´¤ā´ŋ", + "sort_newest": "ā´ā´ąāĩā´ąā´ĩāĩā´‚ ā´Ēāĩā´¤ā´ŋā´¯ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹", + "sort_oldest": "ā´ā´ąāĩā´ąā´ĩāĩā´‚ ā´Ēā´´ā´¯ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹", + "sort_people_by_similarity": "ā´¸ā´žā´Žāĩā´¯ā´‚ ā´…ā´¨āĩā´¸ā´°ā´ŋⴚāĩā´šāĩ ⴆⴺāĩā´•ā´ŗāĩ† ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´ŋā´•āĩā´•āĩā´•", + "sort_recent": "ā´ā´ąāĩā´ąā´ĩāĩā´‚ ā´Ēāĩā´¤ā´ŋā´¯ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹", + "sort_title": "ā´ļāĩ€āĩŧⴎⴕⴂ", + "source": "ā´‰ā´ąā´ĩā´ŋā´Ÿā´‚", + "stack": "ā´¸āĩā´ąāĩā´ąā´žā´•āĩā´•āĩ", + "stack_action_prompt": "{count} ā´Žā´Ŗāĩā´Ŗā´‚ ā´¸āĩā´ąāĩā´ąā´žā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "stack_duplicates": "ā´Ąāĩā´¯āĩ‚ā´Ēāĩā´˛ā´ŋā´•āĩā´•āĩ‡ā´ąāĩā´ąāĩā´•āĩž ā´¸āĩā´ąāĩā´ąā´žā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "stack_select_one_photo": "ā´¸āĩā´ąāĩā´ąā´žā´•āĩā´•ā´ŋā´¨ā´žā´¯ā´ŋ ā´’ā´°āĩ ā´Ēāĩā´°ā´§ā´žā´¨ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "stack_selected_photos": "ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´¤āĩā´¤ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž ā´¸āĩā´ąāĩā´ąā´žā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "stacked_assets_count": "{count, plural, one {# ā´…ā´¸ā´ąāĩā´ąāĩ} other {# ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž}} ā´¸āĩā´ąāĩā´ąā´žā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "stacktrace": "ā´¸āĩā´ąāĩā´ąā´žā´•āĩā´•āĩā´Ÿāĩā´°āĩ‡ā´¸āĩ", + "start": "ⴆⴰⴂⴭā´ŋā´•āĩā´•āĩā´•", + "start_date": "ⴆⴰⴂⴭ ā´¤āĩ€ā´¯ā´¤ā´ŋ", + "start_date_before_end_date": "ⴆⴰⴂⴭ ā´¤āĩ€ā´¯ā´¤ā´ŋ ā´…ā´ĩā´¸ā´žā´¨ ā´¤āĩ€ā´¯ā´¤ā´ŋā´•āĩā´•āĩ ā´Žāĩā´Žāĩā´Ēā´žā´¯ā´ŋā´°ā´ŋā´•āĩā´•ā´Ŗā´‚", + "state": "ⴏⴂⴏāĩā´Ĩā´žā´¨ā´‚", + "status": "ā´¨ā´ŋā´˛", + "stop_casting": "ā´•ā´žā´¸āĩā´ąāĩā´ąā´ŋā´‚ā´—āĩ ā´¨ā´ŋāĩŧā´¤āĩā´¤āĩā´•", + "stop_motion_photo": "ⴚⴞā´ŋā´•āĩā´•āĩā´¨āĩā´¨ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ ā´¨ā´ŋāĩŧā´¤āĩā´¤āĩā´•", + "stop_photo_sharing": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž ā´Ēā´™āĩā´•ā´ŋⴟāĩā´¨āĩā´¨ā´¤āĩ ā´¨ā´ŋāĩŧā´¤āĩā´¤ā´Ŗāĩ‹?", + "stop_photo_sharing_description": "{partner}-ā´•āĩā´•āĩ ⴇⴍā´ŋ ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž ⴆⴕāĩâ€Œā´¸ā´¸āĩ ⴚāĩ†ā´¯āĩā´¯ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛.", + "stop_sharing_photos_with_user": "ⴈ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩāĩā´Žā´žā´¯ā´ŋ ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž ā´Ēā´™āĩā´•ā´ŋⴟāĩā´¨āĩā´¨ā´¤āĩ ā´¨ā´ŋāĩŧā´¤āĩā´¤āĩā´•", + "storage": "ⴏⴂⴭⴰ⴪ ā´¸āĩā´Ĩⴞⴂ", + "storage_label": "ā´¸āĩā´ąāĩā´ąāĩ‹ā´ąāĩ‡ā´œāĩ ā´˛āĩ‡ā´ŦāĩŊ", + "storage_quota": "ā´¸āĩā´ąāĩā´ąāĩ‹ā´ąāĩ‡ā´œāĩ ā´•āĩā´ĩā´žā´Ÿāĩā´Ÿ", + "storage_usage": "{available}-āĩŊ {used} ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ", + "submit": "ā´¸ā´Žāĩŧā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´•", + "success": "ā´ĩā´ŋā´œā´¯ā´‚", + "suggestions": "ā´¨ā´ŋāĩŧā´Ļāĩā´Ļāĩ‡ā´ļā´™āĩā´™āĩž", + "sunrise_on_the_beach": "ā´Ŧāĩ€ā´šāĩā´šā´ŋā´˛āĩ† ā´¸āĩ‚ā´°āĩā´¯āĩ‹ā´Ļⴝⴂ", + "support": "ā´Ēā´ŋā´¨āĩā´¤āĩā´Ŗ", + "support_and_feedback": "ā´Ēā´ŋā´¨āĩā´¤āĩā´Ŗā´¯āĩā´‚ ā´…ā´­ā´ŋā´Ēāĩā´°ā´žā´¯ā´ĩāĩā´‚", + "support_third_party_description": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† Immich ā´‡āĩģā´¸āĩā´ąāĩā´ąā´žā´ŗāĩ‡ā´ˇāĩģ ā´’ā´°āĩ ā´Žāĩ‚ā´¨āĩā´¨ā´žā´‚ ā´•ā´•āĩā´ˇā´ŋ ā´Ēā´žā´•āĩā´•āĩ‡ā´œāĩ ⴚāĩ†ā´¯āĩā´¤ā´¤ā´žā´Ŗāĩ. ā´¨ā´ŋā´™āĩā´™āĩž ā´…ā´¨āĩā´­ā´ĩā´ŋā´•āĩā´•āĩā´¨āĩā´¨ ā´Ēāĩā´°ā´ļāĩā´¨ā´™āĩā´™āĩž ā´† ā´Ēā´žā´•āĩā´•āĩ‡ā´œāĩ ā´•ā´žā´°ā´Ŗā´Žā´žā´•ā´žā´‚, ā´…ā´¤ā´ŋā´¨ā´žāĩŊ ā´¤ā´žā´´āĩ†ā´¯āĩā´ŗāĩā´ŗ ā´˛ā´ŋā´™āĩā´•āĩā´•āĩž ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ā´†ā´Ļāĩā´¯ā´‚ ā´…ā´ĩā´°āĩā´Žā´žā´¯ā´ŋ ā´Ēāĩā´°ā´ļāĩā´¨ā´™āĩā´™āĩž ⴉⴍāĩā´¨ā´¯ā´ŋā´•āĩā´•āĩā´•.", + "swap_merge_direction": "ⴞⴝā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩŊ ā´Ļā´ŋā´ļ ā´Žā´žā´ąāĩā´ąāĩā´•", + "sync": "ā´¸ā´ŋā´™āĩā´•āĩ", + "sync_albums": "ā´†āĩŊā´Ŧā´™āĩā´™āĩž ā´¸ā´ŋā´™āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "sync_albums_manual_subtitle": "ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¤ ā´Žā´˛āĩā´˛ā´ž ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´‚ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´‚ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´¤āĩā´¤ ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ā´†āĩŊā´Ŧā´™āĩā´™ā´ŗā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´¸ā´ŋā´™āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "sync_local": "ā´Ēāĩā´°ā´žā´Ļāĩ‡ā´ļā´ŋā´•ā´Žā´žā´¯ā´ŋ ā´¸ā´ŋā´™āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "sync_remote": "ā´ąā´ŋā´Žāĩ‹ā´Ÿāĩā´Ÿā´žā´¯ā´ŋ ā´¸ā´ŋā´™āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "sync_status": "ā´¸ā´ŋā´™āĩā´•āĩ ā´¨ā´ŋā´˛", + "sync_status_subtitle": "ā´¸ā´ŋā´™āĩā´•āĩ ā´¸ā´ŋā´¸āĩā´ąāĩā´ąā´‚ ā´•ā´žā´Ŗāĩā´•, ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "sync_upload_album_setting_subtitle": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´‚ Immich-ā´˛āĩ† ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´¤āĩā´¤ ā´†āĩŊā´Ŧā´™āĩā´™ā´ŗā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•ā´ŋ ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "tag": "ā´Ÿā´žā´—āĩ", + "tag_assets": "ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´Ÿā´žā´—āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "tag_created": "{tag} ā´Žā´¨āĩā´¨ ā´Ÿā´žā´—āĩ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•ā´ŋ", + "tag_feature_description": "ā´¯āĩā´•āĩā´¤ā´ŋā´¸ā´šā´Žā´žā´¯ ā´Ÿā´žā´—āĩ ā´ĩā´ŋⴎⴝⴙāĩā´™āĩž ā´…ā´¨āĩā´¸ā´°ā´ŋⴚāĩā´šāĩ ā´—āĩā´°āĩ‚ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¤ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´‚ ā´Ŧāĩā´°āĩ—ā´¸āĩā´šāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ", + "tag_not_found_question": "ā´’ā´°āĩ ā´Ÿā´žā´—āĩ ā´•ā´Ŗāĩā´Ÿāĩ†ā´¤āĩā´¤ā´žāĩģ ā´•ā´´ā´ŋā´¯āĩā´¨āĩā´¨ā´ŋā´˛āĩā´˛āĩ‡? ā´’ā´°āĩ ā´Ēāĩā´¤ā´ŋā´¯ ā´Ÿā´žā´—āĩ ⴉ⴪āĩā´Ÿā´žā´•āĩā´•āĩā´•.", + "tag_people": "ⴆⴺāĩā´•ā´ŗāĩ† ā´Ÿā´žā´—āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "tag_updated": "{tag} ā´Žā´¨āĩā´¨ ā´Ÿā´žā´—āĩ ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "tagged_assets": "{count, plural, one {# ā´…ā´¸ā´ąāĩā´ąāĩ} other {# ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž}} ā´Ÿā´žā´—āĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "tags": "ā´Ÿā´žā´—āĩā´•āĩž", + "tap_to_run_job": "ⴜāĩ‹ā´˛ā´ŋ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•ā´žāĩģ ā´Ÿā´žā´Ēāĩā´Ēāĩā´šāĩ†ā´¯āĩā´¯āĩā´•", + "template": "ⴟāĩ†ā´‚ā´Ēāĩā´˛āĩ‡ā´ąāĩā´ąāĩ", + "theme": "ā´¤āĩ€ā´‚", + "theme_selection": "ā´¤āĩ€ā´‚ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩŊ", + "theme_selection_description": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ŧāĩā´°āĩ—ā´¸ā´ąā´ŋā´¨āĩā´ąāĩ† ā´¸ā´ŋā´¸āĩā´ąāĩā´ąā´‚ ā´Žāĩāĩģā´—ā´Ŗā´¨ ā´…ā´¨āĩā´¸ā´°ā´ŋⴚāĩā´šāĩ ā´¤āĩ€ā´‚ ā´˛āĩˆā´ąāĩā´ąāĩ ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ ā´Ąā´žāĩŧā´•āĩā´•āĩ ⴆⴝā´ŋ ā´¯ā´žā´¨āĩā´¤āĩā´°ā´ŋā´•ā´Žā´žā´¯ā´ŋ ⴏⴜāĩā´œā´Žā´žā´•āĩā´•āĩā´•", + "theme_setting_asset_list_storage_indicator_title": "ā´…ā´¸ā´ąāĩā´ąāĩ ⴟāĩˆā´˛āĩā´•ā´ŗā´ŋāĩŊ ā´¸āĩā´ąāĩā´ąāĩ‹ā´ąāĩ‡ā´œāĩ ā´‡āĩģā´Ąā´ŋā´•āĩā´•āĩ‡ā´ąāĩā´ąāĩŧ ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´•", + "theme_setting_asset_list_tiles_per_row_title": "ā´“ā´°āĩ‹ ā´ĩā´°ā´ŋā´¯ā´ŋā´˛āĩā´‚ ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩā´Ÿāĩ† ā´Žā´Ŗāĩā´Ŗā´‚ ({count})", + "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_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_title": "ā´Žāĩ‚ā´¨āĩā´¨āĩ-ⴘⴟāĩā´Ÿ ā´˛āĩ‹ā´Ąā´ŋā´‚ā´—āĩ ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´•āĩā´ˇā´Žā´Žā´žā´•āĩā´•āĩā´•", + "they_will_be_merged_together": "ā´…ā´ĩā´¯āĩ† ā´’ā´°āĩā´Žā´ŋⴚāĩā´šāĩ ⴞⴝā´ŋā´Ēāĩā´Ēā´ŋā´•āĩā´•āĩā´‚", + "third_party_resources": "ā´Žāĩ‚ā´¨āĩā´¨ā´žā´‚ ā´•ā´•āĩā´ˇā´ŋ ā´‰ā´ąā´ĩā´ŋā´Ÿā´™āĩā´™āĩž", + "time_based_memories": "ā´¸ā´Žā´¯ā´‚ ā´…ā´Ÿā´ŋā´¸āĩā´Ĩā´žā´¨ā´Žā´žā´•āĩā´•ā´ŋā´¯āĩā´ŗāĩā´ŗ ā´“āĩŧā´Žāĩā´Žā´•āĩž", + "timeline": "ⴟāĩˆā´‚ā´˛āĩˆāĩģ", + "timezone": "ā´¸ā´Žā´¯ā´Žāĩ‡ā´–ā´˛", + "to_archive": "ā´†āĩŧā´•āĩā´•āĩˆā´ĩāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "to_change_password": "ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´Žā´žā´ąāĩā´ąāĩā´•", + "to_favorite": "ā´Ēāĩā´°ā´ŋā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿā´¤ā´žā´•āĩā´•āĩā´•", + "to_login": "ā´˛āĩ‹ā´—ā´ŋāĩģ", + "to_multi_select": "ā´’ā´¨āĩā´¨ā´ŋⴞⴧā´ŋā´•ā´‚ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•ā´žāĩģ", + "to_parent": "ā´Ēā´žā´°ā´¨āĩā´ąā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Ēāĩ‹ā´•āĩā´•", + "to_select": "ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•ā´žāĩģ", + "to_trash": "ⴟāĩā´°ā´žā´ˇāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "toggle_settings": "ā´•āĩā´°ā´Žāĩ€ā´•ā´°ā´Ŗā´™āĩā´™āĩž ⴟāĩ‹ā´—ā´ŋāĩž ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "total": "ⴆⴕāĩ†", + "total_usage": "ⴆⴕāĩ† ā´‰ā´Ēā´¯āĩ‹ā´—ā´‚", + "trash": "ⴟāĩā´°ā´žā´ˇāĩ", + "trash_action_prompt": "{count} ā´Žā´Ŗāĩā´Ŗā´‚ ⴟāĩā´°ā´žā´ˇā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Žā´žā´ąāĩā´ąā´ŋ", + "trash_all": "ā´Žā´˛āĩā´˛ā´žā´‚ ⴟāĩā´°ā´žā´ˇāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "trash_count": "ⴟāĩā´°ā´žā´ˇāĩ ({count, number})", + "trash_delete_asset": "ā´…ā´¸ā´ąāĩā´ąāĩ ⴟāĩā´°ā´žā´ˇāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•/ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´•", + "trash_emptied": "ⴟāĩā´°ā´žā´ˇāĩ ā´ļāĩ‚ā´¨āĩā´¯ā´Žā´žā´•āĩā´•ā´ŋ", + "trash_no_results_message": "ⴟāĩā´°ā´žā´ˇāĩ ⴚāĩ†ā´¯āĩā´¤ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•ā´ŗāĩā´‚ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•ā´ŗāĩā´‚ ā´‡ā´ĩā´ŋⴟāĩ† ā´•ā´žā´Ŗā´ŋā´•āĩā´•āĩā´‚.", + "trash_page_delete_all": "ā´Žā´˛āĩā´˛ā´žā´‚ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´•", + "trash_page_empty_trash_dialog_content": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ⴟāĩā´°ā´žā´ˇāĩ ⴚāĩ†ā´¯āĩā´¤ ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´ļāĩ‚ā´¨āĩā´¯ā´Žā´žā´•āĩā´•ā´Ŗāĩ‹? ⴈ ⴇⴍⴙāĩā´™āĩž Immich-āĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´ļā´žā´ļāĩā´ĩā´¤ā´Žā´žā´¯ā´ŋ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´‚", + "trash_page_info": "ⴟāĩā´°ā´žā´ˇāĩ ⴚāĩ†ā´¯āĩā´¤ ⴇⴍⴙāĩā´™āĩž {days} ā´Ļā´ŋā´ĩⴏⴙāĩā´™āĩžā´•āĩā´•āĩ ā´ļāĩ‡ā´ˇā´‚ ā´ļā´žā´ļāĩā´ĩā´¤ā´Žā´žā´¯ā´ŋ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´‚", + "trash_page_no_assets": "ⴟāĩā´°ā´žā´ˇāĩ ⴚāĩ†ā´¯āĩā´¤ ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩŠā´¨āĩā´¨āĩā´Žā´ŋā´˛āĩā´˛", + "trash_page_restore_all": "ā´Žā´˛āĩā´˛ā´žā´‚ ā´Ēāĩā´¨ā´ƒā´¸āĩā´Ĩā´žā´Ēā´ŋā´•āĩā´•āĩā´•", + "trash_page_select_assets_btn": "ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•", + "trash_page_title": "ⴟāĩā´°ā´žā´ˇāĩ ({count})", + "trashed_items_will_be_permanently_deleted_after": "ⴟāĩā´°ā´žā´ˇāĩ ⴚāĩ†ā´¯āĩā´¤ ⴇⴍⴙāĩā´™āĩž {days, plural, one {# ā´Ļā´ŋā´ĩⴏⴤāĩā´¤ā´ŋā´¨āĩ} other {# ā´Ļā´ŋā´ĩⴏⴙāĩā´™āĩžā´•āĩā´•āĩ}} ā´ļāĩ‡ā´ˇā´‚ ā´ļā´žā´ļāĩā´ĩā´¤ā´Žā´žā´¯ā´ŋ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´‚.", + "troubleshoot": "ⴟāĩā´°ā´Ŧā´ŋāĩžā´ˇāĩ‚ā´Ÿāĩā´Ÿāĩ", + "type": "ⴤⴰⴂ", + "unable_to_change_pin_code": "ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ ā´Žā´žā´ąāĩā´ąā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unable_to_setup_pin_code": "ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ ⴏⴜāĩā´œāĩ€ā´•ā´°ā´ŋā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯ā´ŋā´˛āĩā´˛", + "unarchive": "ā´…āĩēā´†āĩŧā´•āĩā´•āĩˆā´ĩāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "unarchive_action_prompt": "{count} ā´Žā´Ŗāĩā´Ŗā´‚ ā´†āĩŧā´•āĩā´•āĩˆā´ĩā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¤āĩ", + "unarchived_count": "{count, plural, other {ā´…āĩēā´†āĩŧā´•āĩā´•āĩˆā´ĩāĩ ⴚāĩ†ā´¯āĩā´¤ā´ĩ #}}", + "undo": "ā´¤ā´ŋā´°ā´ŋā´•āĩ†ā´šāĩ†ā´¯āĩā´¯āĩā´•", + "unfavorite": "ā´Ēāĩā´°ā´ŋā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿā´¤ā´˛āĩā´˛ā´žā´¤ā´žā´•āĩā´•āĩā´•", + "unfavorite_action_prompt": "{count} ā´Žā´Ŗāĩā´Ŗā´‚ ā´Ēāĩā´°ā´ŋā´¯ā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿā´ĩā´¯ā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¤āĩ", + "unhide_person": "ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´¯āĩ† ā´Žā´ąā´ĩā´ŋāĩŊā´¨ā´ŋā´¨āĩā´¨āĩ ā´Žā´žā´ąāĩā´ąāĩā´•", + "unknown": "ā´…ā´œāĩā´žā´žā´¤ā´‚", + "unknown_country": "ā´…ā´œāĩā´žā´žā´¤ ā´°ā´žā´œāĩā´¯ā´‚", + "unknown_year": "ā´…ā´œāĩā´žā´žā´¤ ā´ĩāĩŧⴎⴂ", + "unlimited": "ā´Ēā´°ā´ŋā´§ā´ŋā´¯ā´ŋā´˛āĩā´˛ā´žā´¤āĩā´¤ā´¤āĩ", + "unlink_motion_video": "ⴚⴞā´ŋā´•āĩā´•āĩā´¨āĩā´¨ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ ā´…āĩēā´˛ā´ŋā´™āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "unlink_oauth": "OAuth ā´…āĩēā´˛ā´ŋā´™āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "unlinked_oauth_account": "ā´…āĩēā´˛ā´ŋā´™āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¤ OAuth ā´…ā´•āĩā´•āĩ—ā´Ŗāĩā´Ÿāĩ", + "unmute_memories": "ā´“āĩŧā´Žāĩā´Žā´•āĩž ā´ļā´Ŧāĩā´Ļā´Žāĩā´ŗāĩā´ŗā´¤ā´žā´•āĩā´•āĩā´•", + "unnamed_album": "ā´Ēāĩ‡ā´°ā´ŋā´˛āĩā´˛ā´žā´¤āĩā´¤ ā´†āĩŊā´Ŧā´‚", + "unnamed_album_delete_confirmation": "ⴈ ā´†āĩŊā´Ŧā´‚ ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´Ŗā´Žāĩ†ā´¨āĩā´¨āĩ ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´Ŗāĩ‹?", + "unnamed_share": "ā´Ēāĩ‡ā´°ā´ŋā´˛āĩā´˛ā´žā´¤āĩā´¤ ā´Ēā´™āĩā´•ā´ŋⴟāĩŊ", + "unsaved_change": "ā´¸āĩ‡ā´ĩāĩ ⴚāĩ†ā´¯āĩā´¯ā´žā´¤āĩā´¤ ā´Žā´žā´ąāĩā´ąā´‚", + "unselect_all": "ā´Žā´˛āĩā´˛ā´žā´‚ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´¤āĩā´¤ā´¤āĩ ā´Žā´žā´ąāĩā´ąāĩā´•", + "unselect_all_duplicates": "ā´Žā´˛āĩā´˛ā´ž ā´Ąāĩā´¯āĩ‚ā´Ēāĩā´˛ā´ŋā´•āĩā´•āĩ‡ā´ąāĩā´ąāĩā´•ā´ŗāĩā´‚ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´¤āĩā´¤ā´¤āĩ ā´Žā´žā´ąāĩā´ąāĩā´•", + "unselect_all_in": "{group}-ā´˛āĩ† ā´Žā´˛āĩā´˛ā´žā´‚ ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´¤āĩā´¤ā´¤āĩ ā´Žā´žā´ąāĩā´ąāĩā´•", + "unstack": "ā´…āĩē-ā´¸āĩā´ąāĩā´ąā´žā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "unstack_action_prompt": "{count} ā´Žā´Ŗāĩā´Ŗā´‚ ā´…āĩē-ā´¸āĩā´ąāĩā´ąā´žā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "unstacked_assets_count": "{count, plural, one {# ā´…ā´¸ā´ąāĩā´ąāĩ} other {# ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž}} ā´…āĩē-ā´¸āĩā´ąāĩā´ąā´žā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "untagged": "ā´Ÿā´žā´—āĩ ⴚāĩ†ā´¯āĩā´¤ā´ŋⴟāĩā´Ÿā´ŋā´˛āĩā´˛", + "up_next": "ā´…ā´Ÿāĩā´¤āĩā´¤ā´¤āĩ", + "update_location_action_prompt": "ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´¤āĩā´¤ {count} ā´…ā´¸ā´ąāĩā´ąāĩā´•ā´ŗāĩā´Ÿāĩ† ā´¸āĩā´Ĩā´žā´¨ā´‚ ⴇⴤāĩā´Ēā´¯āĩ‹ā´—ā´ŋⴚāĩā´šāĩ ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•:", + "updated_at": "ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¤ā´¤āĩ", + "updated_password": "ā´Ēā´žā´¸āĩâ€Œā´ĩāĩ‡ā´Ąāĩ ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "upload": "ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ", + "upload_action_prompt": "{count} ā´Žā´Ŗāĩā´Ŗā´‚ ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąā´ŋā´¨ā´žā´¯ā´ŋ ā´•āĩā´¯āĩ‚ā´ĩā´ŋāĩŊ ⴚāĩ‡āĩŧā´¤āĩā´¤āĩ", + "upload_concurrency": "ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ā´•āĩ‹āĩēā´•ā´ąāĩģā´¸ā´ŋ", + "upload_details": "ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ā´ĩā´ŋā´ļā´Ļā´žā´‚ā´ļā´™āĩā´™āĩž", + "upload_dialog_info": "ā´¤ā´ŋā´°ā´žāĩā´žāĩ†ā´Ÿāĩā´¤āĩā´¤ ā´…ā´¸ā´ąāĩā´ąāĩ(ā´•āĩž) ā´¸āĩ†āĩŧā´ĩā´ąā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´Ŧā´žā´•āĩā´•ā´Ēāĩā´Ēāĩ ⴚāĩ†ā´¯āĩā´¯ā´Ŗāĩ‹?", + "upload_dialog_title": "ā´…ā´¸ā´ąāĩā´ąāĩ ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "upload_errors": "ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ {count, plural, one {# ā´Ēā´ŋā´ļā´•āĩ‹ā´Ÿāĩ†} other {# ā´Ēā´ŋā´ļā´•āĩā´•ā´ŗāĩ‹ā´Ÿāĩ†}} ā´Ēāĩ‚āĩŧā´¤āĩā´¤ā´ŋā´¯ā´žā´¯ā´ŋ, ā´Ēāĩā´¤ā´ŋā´¯ ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´•ā´žā´Ŗāĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ ā´Ēāĩ‡ā´œāĩ ā´Ēāĩā´¤āĩā´•āĩā´•āĩā´•.", + "upload_finished": "ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ā´•ā´´ā´ŋā´žāĩā´žāĩ", + "upload_progress": "ā´ļāĩ‡ā´ˇā´ŋā´•āĩā´•āĩā´¨āĩā´¨ā´¤āĩ {remaining, number} - ā´Ēāĩā´°āĩ‹ā´¸ā´¸āĩā´¸āĩ ⴚāĩ†ā´¯āĩā´¤ā´¤āĩ {processed, number}/{total, number}", + "upload_skipped_duplicates": "{count, plural, one {# ā´Ąāĩā´¯āĩ‚ā´Ēāĩā´˛ā´ŋā´•āĩā´•āĩ‡ā´ąāĩā´ąāĩ ā´…ā´¸ā´ąāĩā´ąāĩ} other {# ā´Ąāĩā´¯āĩ‚ā´Ēāĩā´˛ā´ŋā´•āĩā´•āĩ‡ā´ąāĩā´ąāĩ ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž}} ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•ā´ŋ", + "upload_status_duplicates": "ā´Ąāĩā´¯āĩ‚ā´Ēāĩā´˛ā´ŋā´•āĩā´•āĩ‡ā´ąāĩā´ąāĩā´•āĩž", + "upload_status_errors": "ā´Ēā´ŋā´ļā´•āĩā´•āĩž", + "upload_status_uploaded": "ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¤āĩ", + "upload_success": "ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ā´ĩā´ŋⴜⴝā´ŋⴚāĩā´šāĩ, ā´Ēāĩā´¤ā´ŋā´¯ ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ā´…ā´¸ā´ąāĩā´ąāĩā´•āĩž ā´•ā´žā´Ŗāĩā´¨āĩā´¨ā´¤ā´ŋā´¨āĩ ā´Ēāĩ‡ā´œāĩ ā´Ēāĩā´¤āĩā´•āĩā´•āĩā´•.", + "upload_to_immich": "Immich-ā´˛āĩ‡ā´•āĩā´•āĩ ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´• ({count})", + "uploading": "ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ", + "uploading_media": "ā´Žāĩ€ā´Ąā´ŋā´¯ ā´…ā´Ēāĩâ€Œā´˛āĩ‹ā´Ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨āĩ", + "url": "ā´¯āĩā´†āĩŧā´ŽāĩŊ", + "usage": "ā´‰ā´Ēā´¯āĩ‹ā´—ā´‚", + "use_biometric": "ā´Ŧā´¯āĩ‹ā´Žāĩ†ā´Ÿāĩā´°ā´ŋā´•āĩ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•", + "use_current_connection": "ā´¨ā´ŋā´˛ā´ĩā´ŋā´˛āĩ† ā´•ā´Ŗā´•āĩā´ˇāĩģ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•", + "use_custom_date_range": "ā´Ēā´•ā´°ā´‚ ā´•ā´¸āĩā´ąāĩā´ąā´‚ ā´¤āĩ€ā´¯ā´¤ā´ŋ ā´Ēā´°ā´ŋā´§ā´ŋ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•", + "user": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩāĩ", + "user_has_been_deleted": "ⴈ ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ† ⴇⴞāĩā´˛ā´žā´¤ā´žā´•āĩā´•ā´ŋ.", + "user_id": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤āĩƒ ā´ā´Ąā´ŋ", + "user_liked": "{user} {type, select, photo {ⴈ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹} video {ⴈ ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹} asset {ⴈ ā´…ā´¸ā´ąāĩā´ąāĩ} other {ⴇⴤāĩ}} ⴇⴎāĩā´Ÿā´Ēāĩā´Ēāĩ†ā´Ÿāĩā´Ÿāĩ", + "user_pin_code_settings": "ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ", + "user_pin_code_settings_description": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "user_privacy": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤āĩƒ ā´¸āĩā´ĩā´•ā´žā´°āĩā´¯ā´¤", + "user_purchase_settings": "ā´ĩā´žā´™āĩā´™āĩŊ", + "user_purchase_settings_description": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´ĩā´žā´™āĩā´™āĩŊ ā´•āĩˆā´•ā´žā´°āĩā´¯ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "user_role_set": "{user}-ā´¨āĩ† {role} ⴆⴝā´ŋ ⴏⴜāĩā´œā´Žā´žā´•āĩā´•ā´ŋ", + "user_usage_detail": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤āĩƒ ā´‰ā´Ēā´¯āĩ‹ā´— ā´ĩā´ŋā´ļā´Ļā´žā´‚ā´ļā´‚", + "user_usage_stats": "ā´…ā´•āĩā´•āĩ—ā´Ŗāĩā´Ÿāĩ ā´‰ā´Ēā´¯āĩ‹ā´— ā´¸āĩā´Ĩā´ŋā´¤ā´ŋā´ĩā´ŋā´ĩā´°ā´•āĩā´•ā´Ŗā´•āĩā´•āĩā´•āĩž", + "user_usage_stats_description": "ā´…ā´•āĩā´•āĩ—ā´Ŗāĩā´Ÿāĩ ā´‰ā´Ēā´¯āĩ‹ā´— ā´¸āĩā´Ĩā´ŋā´¤ā´ŋā´ĩā´ŋā´ĩā´°ā´•āĩā´•ā´Ŗā´•āĩā´•āĩā´•āĩž ā´•ā´žā´Ŗāĩā´•", + "username": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤āĩƒā´¨ā´žā´Žā´‚", + "users": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´•āĩā´•āĩž", + "users_added_to_album_count": "{count, plural, one {# ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ†} other {# ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´•āĩā´•ā´ŗāĩ†}} ā´†āĩŊā´Ŧā´¤āĩā´¤ā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ⴚāĩ‡āĩŧā´¤āĩā´¤āĩ", + "utilities": "ā´¯āĩ‚ā´Ÿāĩā´Ÿā´ŋā´˛ā´ŋā´ąāĩā´ąā´ŋā´•āĩž", + "validate": "ā´¸ā´žā´§āĩ‚ā´•ā´°ā´ŋā´•āĩā´•āĩā´•", + "validate_endpoint_error": "ā´Ļā´¯ā´ĩā´žā´¯ā´ŋ ā´¸ā´žā´§āĩā´ĩā´žā´¯ ā´’ā´°āĩ URL ā´¨āĩŊā´•āĩā´•", + "variables": "ā´ĩāĩ‡ā´°ā´ŋā´¯ā´Ŧā´ŋā´ŗāĩā´•āĩž", + "version": "ā´Ēā´¤ā´ŋā´Ēāĩā´Ēāĩ", + "version_announcement_closing": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´¸āĩā´šāĩƒā´¤āĩā´¤āĩ, ⴅⴞⴕāĩā´¸āĩ", + "version_announcement_message": "ā´¨ā´Žā´¸āĩā´•ā´žā´°ā´‚! Immich-ā´¨āĩā´ąāĩ† ā´’ā´°āĩ ā´Ēāĩā´¤ā´ŋā´¯ ā´Ēā´¤ā´ŋā´Ēāĩā´Ēāĩ ⴞⴭāĩā´¯ā´Žā´žā´Ŗāĩ. ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ⴏⴜāĩā´œāĩ€ā´•ā´°ā´Ŗā´‚ ā´ā´ąāĩā´ąā´ĩāĩā´‚ ā´Ēāĩā´¤ā´ŋā´¯ā´¤ā´žā´Ŗāĩ†ā´¨āĩā´¨āĩ ā´‰ā´ąā´Ēāĩā´Ēā´žā´•āĩā´•ā´žāĩģ ā´Ļā´¯ā´ĩā´žā´¯ā´ŋ ā´ąā´ŋā´˛āĩ€ā´¸āĩ ā´¨āĩ‹ā´Ÿāĩā´Ÿāĩā´•āĩž ā´ĩā´žā´¯ā´ŋā´•āĩā´•ā´žāĩģ ā´•āĩā´ąā´šāĩā´šāĩ ā´¸ā´Žā´¯ā´Žāĩ†ā´Ÿāĩā´•āĩā´•āĩā´•. ⴇⴤāĩ ā´¤āĩ†ā´ąāĩā´ąā´žā´¯ ā´•āĩ‹āĩēā´Ģā´ŋā´—ā´ąāĩ‡ā´ˇā´¨āĩā´•āĩž ā´’ā´´ā´ŋā´ĩā´žā´•āĩā´•ā´žāĩģ ā´¸ā´šā´žā´¯ā´ŋā´•āĩā´•āĩā´‚, ā´Ēāĩā´°ā´¤āĩā´¯āĩ‡ā´•ā´ŋⴚāĩā´šāĩā´‚ ā´¨ā´ŋā´™āĩā´™āĩž ā´ĩā´žā´šāĩā´šāĩā´Ÿā´ĩāĩŧ ā´…ā´˛āĩā´˛āĩ†ā´™āĩā´•ā´ŋāĩŊ ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† Immich ā´‡āĩģā´¸āĩā´ąāĩā´ąāĩģā´¸āĩ ā´¯ā´žā´¨āĩā´¤āĩā´°ā´ŋā´•ā´Žā´žā´¯ā´ŋ ā´…ā´Ēāĩā´Ąāĩ‡ā´ąāĩā´ąāĩ ⴚāĩ†ā´¯āĩā´¯āĩā´¨āĩā´¨ ā´ā´¤āĩ†ā´™āĩā´•ā´ŋā´˛āĩā´‚ ⴏⴂā´ĩā´ŋā´§ā´žā´¨ā´‚ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩā´Ŗāĩā´Ÿāĩ†ā´™āĩā´•ā´ŋāĩŊ.", + "version_history": "ā´Ēā´¤ā´ŋā´Ēāĩā´Ēāĩ ⴚⴰā´ŋā´¤āĩā´°ā´‚", + "version_history_item": "{date}-ā´¨āĩ {version} ā´‡āĩģā´¸āĩā´ąāĩā´ąā´žāĩž ⴚāĩ†ā´¯āĩā´¤āĩ", + "video": "ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹", + "video_hover_setting": "ā´šāĩ‹ā´ĩāĩŧ ⴚāĩ†ā´¯āĩā´¯āĩā´Žāĩā´Ēāĩ‹āĩž ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋāĩŊ ā´Ēāĩā´˛āĩ‡ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "video_hover_setting_description": "ā´Žāĩ—ā´¸āĩ ā´’ā´°āĩ ⴇⴍⴤāĩā´¤ā´ŋā´¨āĩ ā´Žāĩā´•ā´ŗā´ŋā´˛āĩ‚ā´Ÿāĩ† ā´šāĩ‹ā´ĩāĩŧ ⴚāĩ†ā´¯āĩā´¯āĩā´Žāĩā´Ēāĩ‹āĩž ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ ⴤⴂā´Ŧāĩā´¨āĩ†ā´¯ā´ŋāĩŊ ā´Ēāĩā´˛āĩ‡ ⴚāĩ†ā´¯āĩā´¯āĩā´•. ā´Ēāĩā´°ā´ĩāĩŧā´¤āĩā´¤ā´¨ā´°ā´šā´ŋā´¤ā´Žā´žā´•āĩā´•ā´ŋā´¯ā´žā´˛āĩā´‚, ā´Ēāĩā´˛āĩ‡ ⴐⴕāĩā´•ā´Ŗā´ŋā´¨āĩ ā´Žāĩā´•ā´ŗā´ŋā´˛āĩ‚ā´Ÿāĩ† ā´šāĩ‹ā´ĩāĩŧ ⴚāĩ†ā´¯āĩā´¤āĩ ā´Ēāĩā´˛āĩ‡ā´Ŧā´žā´•āĩā´•āĩ ⴆⴰⴂⴭā´ŋā´•āĩā´•ā´žāĩģ ā´•ā´´ā´ŋā´¯āĩā´‚.", + "videos": "ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•āĩž", + "videos_count": "{count, plural, one {# ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹} other {# ā´ĩāĩ€ā´Ąā´ŋā´¯āĩ‹ā´•āĩž}}", + "view": "ā´•ā´žā´Ŗāĩā´•", + "view_album": "ā´†āĩŊā´Ŧā´‚ ā´•ā´žā´Ŗāĩā´•", + "view_all": "ā´Žā´˛āĩā´˛ā´žā´‚ ā´•ā´žā´Ŗāĩā´•", + "view_all_users": "ā´Žā´˛āĩā´˛ā´ž ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´•āĩā´•ā´ŗāĩ†ā´¯āĩā´‚ ā´•ā´žā´Ŗāĩā´•", + "view_details": "ā´ĩā´ŋā´ļā´Ļā´žā´‚ā´ļā´™āĩā´™āĩž ā´•ā´žā´Ŗāĩā´•", + "view_in_timeline": "ⴟāĩˆā´‚ā´˛āĩˆā´¨ā´ŋāĩŊ ā´•ā´žā´Ŗāĩā´•", + "view_link": "ā´˛ā´ŋā´™āĩā´•āĩ ā´•ā´žā´Ŗāĩā´•", + "view_links": "ā´˛ā´ŋā´™āĩā´•āĩā´•āĩž ā´•ā´žā´Ŗāĩā´•", + "view_name": "ā´•ā´žā´Ŗāĩā´•", + "view_next_asset": "ā´…ā´Ÿāĩā´¤āĩā´¤ ā´…ā´¸ā´ąāĩā´ąāĩ ā´•ā´žā´Ŗāĩā´•", + "view_previous_asset": "ā´Žāĩā´Žāĩā´Ēā´¤āĩā´¤āĩ† ā´…ā´¸ā´ąāĩā´ąāĩ ā´•ā´žā´Ŗāĩā´•", + "view_qr_code": "QR ā´•āĩ‹ā´Ąāĩ ā´•ā´žā´Ŗāĩā´•", + "view_similar_photos": "ā´¸ā´Žā´žā´¨ā´Žā´žā´¯ ā´Ģāĩ‹ā´Ÿāĩā´Ÿāĩ‹ā´•āĩž ā´•ā´žā´Ŗāĩā´•", + "view_stack": "ā´¸āĩā´ąāĩā´ąā´žā´•āĩā´•āĩ ā´•ā´žā´Ŗāĩā´•", + "view_user": "ā´‰ā´Ēā´¯āĩ‹ā´•āĩā´¤ā´žā´ĩā´ŋā´¨āĩ† ā´•ā´žā´Ŗāĩā´•", + "viewer_remove_from_stack": "ā´¸āĩā´ąāĩā´ąā´žā´•āĩā´•ā´ŋāĩŊ ā´¨ā´ŋā´¨āĩā´¨āĩ ā´¨āĩ€ā´•āĩā´•ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "viewer_stack_use_as_main_asset": "ā´Ēāĩā´°ā´§ā´žā´¨ ā´…ā´¸ā´ąāĩā´ąā´žā´¯ā´ŋ ā´‰ā´Ēā´¯āĩ‹ā´—ā´ŋā´•āĩā´•āĩā´•", + "viewer_unstack": "ā´…āĩē-ā´¸āĩā´ąāĩā´ąā´žā´•āĩā´•āĩ ⴚāĩ†ā´¯āĩā´¯āĩā´•", + "visibility_changed": "{count, plural, one {# ā´ĩāĩā´¯ā´•āĩā´¤ā´ŋā´¯āĩā´Ÿāĩ†} other {# ⴆⴺāĩā´•ā´ŗāĩā´Ÿāĩ†}} ā´Ļāĩƒā´ļāĩā´¯ā´¤ ā´Žā´žā´ąāĩā´ąā´ŋ", "waiting": "ā´•ā´žā´¤āĩā´¤ā´ŋā´°ā´ŋā´•āĩā´•āĩā´¨āĩā´¨āĩ", "warning": "ā´Žāĩā´¨āĩā´¨ā´ąā´ŋā´¯ā´ŋā´Ēāĩā´Ēāĩ", "week": "ⴆⴴāĩā´š", "welcome": "ā´¸āĩā´ĩā´žā´—ā´¤ā´‚", + "welcome_to_immich": "Immich-ā´˛āĩ‡ā´•āĩā´•āĩ ā´¸āĩā´ĩā´žā´—ā´¤ā´‚", + "wifi_name": "ā´ĩāĩˆ-ā´Ģāĩˆā´¯āĩā´Ÿāĩ† ā´Ēāĩ‡ā´°āĩ", + "wrong_pin_code": "ā´¤āĩ†ā´ąāĩā´ąā´žā´¯ ā´Ēā´ŋāĩģ ā´•āĩ‹ā´Ąāĩ", "year": "ā´ĩāĩŧⴎⴂ", - "yes": "ā´…ā´¤āĩ†" + "years_ago": "{years, plural, one {# ā´ĩāĩŧⴎⴂ} other {# ā´ĩāĩŧⴎⴙāĩā´™āĩž}} ā´Žāĩā´Žāĩā´Ēāĩ", + "yes": "ā´…ā´¤āĩ†", + "you_dont_have_any_shared_links": "ā´¨ā´ŋā´™āĩā´™āĩžā´•āĩā´•āĩ ā´Ēā´™āĩā´•ā´ŋⴟāĩā´Ÿ ā´˛ā´ŋā´™āĩā´•āĩā´•ā´ŗāĩŠā´¨āĩā´¨āĩā´Žā´ŋā´˛āĩā´˛", + "your_wifi_name": "ā´¨ā´ŋā´™āĩā´™ā´ŗāĩā´Ÿāĩ† ā´ĩāĩˆ-ā´Ģāĩˆā´¯āĩā´Ÿāĩ† ā´Ēāĩ‡ā´°āĩ", + "zoom_image": "ⴚā´ŋā´¤āĩā´°ā´‚ ā´ĩā´˛āĩā´¤ā´žā´•āĩā´•āĩā´•", + "zoom_to_bounds": "ā´Ēā´°ā´ŋā´§ā´ŋā´•ā´ŗā´ŋā´˛āĩ‡ā´•āĩā´•āĩ ā´¸āĩ‚ā´‚ ⴚāĩ†ā´¯āĩā´¯āĩā´•" } diff --git a/i18n/mr.json b/i18n/mr.json index 1af1428d6a..fb1b61e2af 100644 --- a/i18n/mr.json +++ b/i18n/mr.json @@ -28,6 +28,8 @@ "add_to_album": "⤏⤂⤗āĨā¤°ā¤šā¤žā¤¤ ā¤Ÿā¤žā¤•ā¤ž", "add_to_album_bottom_sheet_added": "{album} ā¤Žā¤§āĨā¤¯āĨ‡ ⤜āĨ‹ā¤Ąā¤˛āĨ‡ ⤗āĨ‡ā¤˛āĨ‡", "add_to_album_bottom_sheet_already_exists": "⤆⤧āĨ€ā¤š {album} ā¤Žā¤§āĨā¤¯āĨ‡ ā¤†ā¤šāĨ‡", + "add_to_album_toggle": "⤅⤞āĨā¤Ŧā¤Žā¤¸ā¤žā¤ āĨ€ ⤍ā¤ŋā¤ĩā¤Ą ⤟āĨ‰ā¤—⤞ ā¤•ā¤°ā¤ž", + "add_to_albums": "⤅⤞āĨā¤Ŧā¤Žā¤Žā¤§āĨā¤¯āĨ‡ ⤜āĨ‹ā¤Ąā¤ž", "add_to_shared_album": "ā¤¸ā¤žā¤Žā¤žā¤¯ā¤ŋ⤕ ⤏⤂⤗āĨā¤°ā¤šā¤žā¤¤ ā¤Ÿā¤žā¤•ā¤ž", "add_url": "URL ā¤ĒāĨā¤°ā¤ĩā¤ŋ⤎āĨā¤Ÿ ā¤•ā¤°ā¤ž", "added_to_archive": "⤏⤂⤗āĨā¤°ā¤šā¤ŋ⤤ ⤕āĨ‡ā¤˛āĨ‡", @@ -355,6 +357,9 @@ "trash_number_of_days_description": "ā¤•ā¤žā¤¯ā¤Žā¤¸āĨā¤ĩ⤰āĨ€ā¤¤āĨā¤¯ā¤ž ā¤•ā¤žā¤ĸāĨ‚⤍ ā¤Ÿā¤žā¤•ā¤ŖāĨā¤¯ā¤žā¤ĒāĨ‚⤰āĨā¤ĩāĨ€ ⤟āĨā¤°āĨ…ā¤ļā¤Žā¤§āĨā¤¯āĨ‡ ā¤¸ā¤žā¤Žā¤—āĨā¤°āĨ€ ⤕ā¤ŋ⤤āĨ€ ā¤Ļā¤ŋā¤ĩ⤏ ⤠āĨ‡ā¤ĩā¤žā¤¯ā¤šāĨ€ ⤤āĨ‡ ⤕āĨā¤°ā¤Ž", "trash_settings": "⤟āĨā¤°āĨ…ā¤ļ ⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗āĨā¤œ", "trash_settings_description": "⤟āĨā¤°āĨ…ā¤ļ ⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗āĨā¤œ ā¤ĩāĨā¤¯ā¤ĩ⤏āĨā¤Ĩā¤žā¤Ēā¤ŋ⤤ ā¤•ā¤°ā¤ž", + "unlink_all_oauth_accounts": "⤏⤰āĨā¤ĩ OAuth ā¤–ā¤žā¤¤āĨā¤¯ā¤žā¤‚ā¤šāĨ€ ⤜āĨ‹ā¤Ąā¤ŖāĨ€ ⤤āĨ‹ā¤Ąā¤ž", + "unlink_all_oauth_accounts_description": "⤍ā¤ĩāĨā¤¯ā¤ž ⤏āĨ‡ā¤ĩā¤ž-ā¤ĒāĨā¤°ā¤Ļā¤žā¤¤āĨā¤¯ā¤žā¤•ā¤ĄāĨ‡ ⤏āĨā¤Ĩā¤˛ā¤žā¤‚ā¤¤ā¤° ⤕⤰⤪āĨā¤¯ā¤žā¤ĒāĨ‚⤰āĨā¤ĩāĨ€ ⤏⤰āĨā¤ĩ OAuth ā¤–ā¤žā¤¤āĨā¤¯ā¤žā¤‚ā¤šāĨ€ ⤜āĨ‹ā¤Ąā¤ŖāĨ€ ⤤āĨ‹ā¤Ąā¤žā¤¯ā¤˛ā¤ž ā¤ĩā¤ŋ⤏⤰āĨ‚ ā¤¨ā¤•ā¤ž.", + "unlink_all_oauth_accounts_prompt": "⤤āĨā¤ŽāĨā¤šāĨ€ ⤖⤰āĨ‹ā¤–⤰ ⤏⤰āĨā¤ĩ OAuth ā¤–ā¤žā¤¤āĨā¤¯ā¤žā¤‚ā¤šāĨ€ ⤜āĨ‹ā¤Ąā¤ŖāĨ€ ⤤āĨ‹ā¤ĄāĨ‚ ā¤‡ā¤šāĨā¤›ā¤ŋā¤¤ā¤ž ā¤•ā¤ž? ā¤¯ā¤žā¤ŽāĨā¤ŗāĨ‡ ā¤ĒāĨā¤°ā¤¤āĨā¤¯āĨ‡ā¤• ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤āĨā¤¯ā¤žā¤šā¤ž OAuth ID ⤰āĨ€ā¤¸āĨ‡ā¤Ÿ ā¤šāĨ‹ā¤ˆā¤˛ ⤆⤪ā¤ŋ ā¤šāĨ€ ⤕āĨƒā¤¤āĨ€ ā¤ĒāĨ‚⤰āĨā¤ĩ⤏āĨā¤Ĩā¤ŋ⤤āĨ€ā¤¤ ā¤†ā¤Ŗā¤¤ā¤ž ⤝āĨ‡ā¤Ŗā¤žā¤° ā¤¨ā¤žā¤šāĨ€.", "user_cleanup_job": "ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤ā¤ž ⤏āĨā¤ĩ⤚āĨā¤›ā¤¤ā¤ž", "user_delete_delay": "{user} ā¤¯ā¤žā¤‚ā¤šāĨ‡ ā¤–ā¤žā¤¤āĨ‡ ⤆⤪ā¤ŋ ā¤Žā¤žā¤˛ā¤Žā¤¤āĨā¤¤ā¤ž ā¤•ā¤žā¤¯ā¤Žā¤šāĨ€ ā¤šā¤Ÿā¤ĩā¤ŋ⤪āĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ {delay, plural, one {# ā¤Ļā¤ŋā¤ĩ⤏} other {# ā¤Ļā¤ŋā¤ĩ⤏}} ⤍⤂⤤⤰ ā¤ļāĨ‡ā¤ĄāĨā¤¯āĨ‚⤞ ⤕āĨ‡ā¤˛āĨ€ ā¤œā¤žā¤¤āĨ€ā¤˛.", "user_delete_delay_settings": "ā¤šā¤Ÿā¤ĩā¤ŋ⤪āĨā¤¯ā¤žā¤šāĨ€ ā¤ĩā¤ŋ⤞⤂ā¤ŦāĨ€ā¤¤ ā¤•ā¤žā¤˛ā¤žā¤ĩ⤧āĨ€", @@ -381,8 +386,6 @@ "admin_password": "ā¤ĒāĨā¤°ā¤ļā¤žā¤¸ā¤• ā¤Ēā¤žā¤¸ā¤ĩ⤰āĨā¤Ą", "administration": "ā¤ĒāĨā¤°ā¤ļā¤žā¤¸ā¤¨", "advanced": "ā¤ĒāĨā¤°ā¤—⤤", - "advanced_settings_beta_timeline_subtitle": "⤍ā¤ĩāĨ€ā¤¨ āĨ˛ā¤Ē ⤅⤍āĨā¤­ā¤ĩ ā¤ĩā¤žā¤Ē⤰āĨ‚⤍ ā¤Ēā¤šā¤ž", - "advanced_settings_beta_timeline_title": "ā¤ŦāĨ€ā¤Ÿā¤ž ā¤Ÿā¤žā¤ˆā¤Žā¤˛ā¤žā¤ˆā¤¨", "advanced_settings_enable_alternate_media_filter_subtitle": "⤏ā¤ŋ⤂⤕ ā¤Ļā¤°ā¤ŽāĨā¤¯ā¤žā¤¨ ā¤ĩāĨˆā¤•⤞āĨā¤Ēā¤ŋ⤕ ⤍ā¤ŋā¤•ā¤ˇā¤žā¤‚ā¤ĩ⤰ ā¤†ā¤§ā¤žā¤°ā¤ŋ⤤ ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤Ģā¤ŋ⤞āĨā¤Ÿā¤° ⤕⤰⤪āĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ ā¤šā¤ž ā¤Ē⤰āĨā¤¯ā¤žā¤¯ ā¤ĩā¤žā¤Ēā¤°ā¤ž. āĨ˛ā¤Ē ⤏⤰āĨā¤ĩ ⤅⤞āĨā¤Ŧā¤Ž ⤓⤺⤖⤪āĨā¤¯ā¤žā¤¤ ā¤¸ā¤Žā¤¸āĨā¤¯ā¤ž ⤝āĨ‡ā¤¤ ⤅⤏⤞āĨā¤¯ā¤žā¤¸ā¤š ā¤ĩā¤žā¤Ēā¤°ā¤ž.", "advanced_settings_enable_alternate_media_filter_title": "[ā¤ĒāĨā¤°ā¤¯āĨ‹ā¤—ā¤žā¤¤āĨā¤Žā¤•] ⤉ā¤Ē⤕⤰⤪-ā¤†ā¤§ā¤žā¤°ā¤ŋ⤤ ⤅⤞āĨā¤Ŧā¤Ž ⤏ā¤ŋ⤂⤕ ā¤Ģā¤ŋ⤞āĨā¤Ÿā¤° ā¤ĩā¤žā¤Ēā¤°ā¤ž", "advanced_settings_log_level_title": "⤞āĨ‰ā¤— ā¤Ēā¤žā¤¤ā¤ŗāĨ€: {level}", @@ -390,6 +393,8 @@ "advanced_settings_prefer_remote_title": "⤰ā¤ŋā¤ŽāĨ‹ā¤Ÿ ā¤ĒāĨā¤°ā¤¤ā¤ŋā¤Žā¤ž ā¤Ē⤏⤂⤤ ā¤•ā¤°ā¤ž", "advanced_settings_proxy_headers_subtitle": "ā¤ĒāĨā¤°ā¤¤āĨā¤¯āĨ‡ā¤• ⤍āĨ‡ā¤Ÿā¤ĩ⤰āĨā¤• ā¤ĩā¤ŋ⤍⤂⤤āĨ€ā¤¸āĨ‹ā¤Ŧ⤤ Immich ā¤Ēā¤žā¤ ā¤ĩā¤žā¤ĩā¤¯ā¤žā¤šāĨ‡ ā¤ĒāĨā¤°āĨ‰ā¤•āĨā¤¸āĨ€ ā¤šāĨ‡ā¤Ąā¤° ⤝āĨ‡ā¤ĨāĨ‡ ā¤Ē⤰ā¤ŋā¤­ā¤žā¤ˇā¤ŋ⤤ ā¤•ā¤°ā¤ž", "advanced_settings_proxy_headers_title": "ā¤ĒāĨā¤°āĨ‰ā¤•āĨā¤¸āĨ€ ā¤šāĨ‡ā¤Ąā¤°", + "advanced_settings_readonly_mode_subtitle": "ā¤¯ā¤ž ā¤ŽāĨ‹ā¤Ąā¤Žā¤§āĨā¤¯āĨ‡ ā¤ĢāĨ‹ā¤ŸāĨ‹ ā¤Ģ⤕āĨā¤¤ ā¤Ēā¤žā¤šā¤¤ā¤ž ⤝āĨ‡ā¤¤ā¤žā¤¤ - ⤅⤍āĨ‡ā¤• ā¤ĢāĨ‹ā¤ŸāĨ‹ ⤍ā¤ŋā¤ĩā¤Ąā¤ŖāĨ‡, ā¤ļāĨ‡ā¤…⤰ ⤕⤰⤪āĨ‡, ā¤•ā¤žā¤¸āĨā¤Ÿ ⤕⤰⤪āĨ‡ ⤆⤪ā¤ŋ ā¤šā¤Ÿā¤ĩ⤪āĨ‡ ⤅ā¤ļā¤ž ⤕āĨā¤°ā¤ŋā¤¯ā¤ž ⤍ā¤ŋ⤎āĨā¤•āĨā¤°ā¤ŋ⤝ ā¤°ā¤žā¤šā¤¤ā¤žā¤¤. ā¤ŽāĨā¤–āĨā¤¯ ⤏āĨā¤•āĨā¤°āĨ€ā¤¨ā¤ĩ⤰āĨ€ā¤˛ ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤ā¤ž ⤅ā¤ĩā¤¤ā¤žā¤°ā¤žā¤¤āĨ‚⤍ ā¤šā¤ž ā¤ŽāĨ‹ā¤Ą ā¤šā¤žā¤˛āĨ‚ ⤕ā¤ŋ⤂ā¤ĩā¤ž ā¤Ŧ⤂ā¤Ļ ā¤•ā¤°ā¤ž", + "advanced_settings_readonly_mode_title": "ā¤Ģ⤕āĨā¤¤ ā¤Ēā¤žā¤šā¤ŖāĨā¤¯ā¤žā¤šā¤ž ā¤ŽāĨ‹ā¤Ą", "advanced_settings_self_signed_ssl_subtitle": "⤏⤰āĨā¤ĩāĨā¤šā¤° ā¤ā¤‚ā¤Ąā¤ĒāĨ‰ā¤‡ā¤‚ā¤Ÿā¤¸ā¤žā¤ āĨ€ SSL ā¤ĒāĨā¤°ā¤Žā¤žā¤Ŗā¤Ē⤤āĨā¤° ⤏⤤āĨā¤¯ā¤žā¤Ē⤍ ā¤ĩ⤗⤺⤤āĨ‡. ⤏āĨā¤ĩā¤žā¤•āĨā¤ˇā¤°āĨ€ā¤¤ ā¤ĒāĨā¤°ā¤Žā¤žā¤Ŗā¤Ē⤤āĨā¤°ā¤žā¤‚ā¤¸ā¤žā¤ āĨ€ ⤆ā¤ĩā¤ļāĨā¤¯ā¤•.", "advanced_settings_self_signed_ssl_title": "⤏āĨā¤ĩ⤤⤃ ⤏āĨā¤ĩā¤žā¤•āĨā¤ˇā¤°āĨ€ā¤¤ SSL ā¤ĒāĨā¤°ā¤Žā¤žā¤Ŗā¤Ē⤤āĨā¤°ā¤žā¤‚ā¤¨ā¤ž ā¤Ē⤰ā¤ĩā¤žā¤¨ā¤—āĨ€ ā¤ĻāĨā¤¯ā¤ž", "advanced_settings_sync_remote_deletions_subtitle": "ā¤ĩāĨ‡ā¤Ŧā¤ĩ⤰ ā¤šāĨ€ ⤕āĨā¤°ā¤ŋā¤¯ā¤ž ⤕āĨ‡ā¤˛āĨ€ ⤗āĨ‡ā¤˛āĨā¤¯ā¤žā¤ĩ⤰ ā¤¯ā¤ž ⤉ā¤Ēā¤•ā¤°ā¤Ŗā¤žā¤ĩ⤰ ⤅⤏⤞āĨ‡ā¤˛āĨ‡ ⤅āĨ…⤏āĨ‡ā¤Ÿ ⤆ā¤ĒāĨ‹ā¤†ā¤Ē ā¤šā¤Ÿā¤ĩā¤ž ⤕ā¤ŋ⤂ā¤ĩā¤ž ā¤ĒāĨā¤¨ā¤°āĨā¤¸ā¤‚ā¤šā¤¯ā¤ŋ⤤ ā¤•ā¤°ā¤ž", @@ -417,6 +422,7 @@ "album_remove_user_confirmation": "⤆ā¤Ē⤪ ⤍ā¤ŋā¤ļāĨā¤šā¤ŋ⤤⤚ ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤ā¤ž {user} ā¤•ā¤žā¤ĸāĨ‚⤍ ā¤Ÿā¤žā¤•ā¤Ŗā¤žā¤° ā¤†ā¤šā¤žā¤¤ ā¤•ā¤ž?", "album_search_not_found": "⤤āĨā¤Žā¤šāĨā¤¯ā¤ž ā¤ļāĨ‹ā¤§ā¤žā¤ļāĨ€ ⤜āĨā¤ŗā¤Ŗā¤žā¤°āĨ‡ ⤕āĨ‹ā¤Ŗā¤¤āĨ‡ā¤šāĨ€ ⤅⤞āĨā¤Ŧā¤Ž ⤆ā¤ĸ⤺⤞āĨ‡ ā¤¨ā¤žā¤šāĨ€ā¤¤", "album_share_no_users": "ā¤…ā¤¸ā¤ž ā¤Ļā¤ŋ⤏⤤āĨ‡ ⤕āĨ€ ā¤šā¤ž ⤅⤞āĨā¤Ŧā¤Ž ⤤āĨā¤ŽāĨā¤šāĨ€ ⤏⤰āĨā¤ĩ ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤āĨā¤¯ā¤žā¤‚⤏āĨ‹ā¤Ŧ⤤ ā¤ļāĨ‡ā¤…⤰ ⤕āĨ‡ā¤˛ā¤ž ā¤†ā¤šāĨ‡ ⤕ā¤ŋ⤂ā¤ĩā¤ž ā¤ļāĨ‡ā¤…⤰ ⤕⤰⤪āĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ ⤕āĨā¤ ā¤˛ā¤žā¤šāĨ€ ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤ā¤ž ⤉ā¤Ē⤞ā¤ŦāĨā¤§ ā¤¨ā¤žā¤šāĨ€.", + "album_summary": "⤅⤞āĨā¤Ŧā¤Ž ā¤¸ā¤žā¤°ā¤žā¤‚ā¤ļ", "album_updated": "⤅⤞āĨā¤Ŧā¤Ž ⤅ā¤ĻāĨā¤¯ā¤¤ā¤¨ā¤ŋ⤤", "album_updated_setting_description": "ā¤ļāĨ‡ā¤…⤰ ⤕āĨ‡ā¤˛āĨ‡ā¤˛āĨā¤¯ā¤ž ⤅⤞āĨā¤Ŧā¤Žā¤Žā¤§āĨā¤¯āĨ‡ ⤍ā¤ĩāĨ€ā¤¨ ā¤Ģā¤žā¤ˆā¤˛āĨā¤¸ ⤆⤞āĨā¤¯ā¤žā¤¸ ā¤ˆā¤ŽāĨ‡ā¤˛ ⤏āĨ‚ā¤šā¤¨ā¤žā¤°āĨā¤Ĩ ā¤ĒāĨā¤°ā¤žā¤ĒāĨā¤¤ ā¤•ā¤°ā¤ž", "album_user_left": "⤏āĨ‹ā¤Ąā¤˛āĨ‡: {album}", @@ -455,6 +461,7 @@ "app_bar_signout_dialog_title": "ā¤¸ā¤žā¤‡ā¤¨ ā¤†ā¤‰ā¤Ÿ", "app_settings": "ā¤…â€āĨ…ā¤Ē ⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗āĨā¤œ", "appears_in": "ā¤Ļā¤ŋ⤏⤤āĨ‡ (⤕āĨā¤ āĨ‡ ā¤Ļā¤ŋ⤏⤤āĨ‡)", + "apply_count": "ā¤˛ā¤žā¤—āĨ‚ ā¤•ā¤°ā¤ž ({count, number})", "archive": "⤆⤰āĨā¤•ā¤žā¤‡ā¤ĩāĨā¤š", "archive_action_prompt": "{count} ⤆⤰āĨā¤•ā¤žā¤‡ā¤ĩāĨā¤šā¤Žā¤§āĨā¤¯āĨ‡ ⤜āĨ‹ā¤Ąā¤˛āĨ‡", "archive_or_unarchive_photo": "ā¤ĢāĨ‹ā¤ŸāĨ‹ ⤆⤰āĨā¤•ā¤žā¤‡ā¤ĩāĨā¤š ā¤•ā¤°ā¤ž ⤕ā¤ŋ⤂ā¤ĩā¤ž ⤅⤍⤆⤰āĨā¤•ā¤žā¤‡ā¤ĩāĨā¤š ā¤•ā¤°ā¤ž", @@ -487,6 +494,8 @@ "asset_restored_successfully": "ā¤¸ā¤žā¤§ā¤¨ ⤝ā¤ļ⤏āĨā¤ĩāĨ€ā¤Ē⤪āĨ‡ ā¤ĒāĨā¤¨ā¤°āĨā¤¸ā¤‚ā¤šā¤¯ā¤ŋ⤤ ⤕āĨ‡ā¤˛āĨ‡ ⤗āĨ‡ā¤˛āĨ‡", "asset_skipped": "ā¤ĩ⤗⤺⤞āĨ‡", "asset_skipped_in_trash": "⤟āĨā¤°āĨ…ā¤ļā¤Žā¤§āĨā¤¯āĨ‡", + "asset_trashed": "ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤• ā¤•ā¤šā¤°ā¤žā¤ĒāĨ‡ā¤ŸāĨ€ā¤¤ ā¤šā¤˛ā¤ĩā¤˛ā¤ž", + "asset_troubleshoot": "ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤• ā¤¸ā¤Žā¤¸āĨā¤¯ā¤žā¤¨ā¤ŋā¤ĩā¤žā¤°ā¤Ŗ", "asset_uploaded": "⤅ā¤Ē⤞āĨ‹ā¤Ą ā¤ā¤žā¤˛āĨ‡", "asset_uploading": "⤅ā¤Ē⤞āĨ‹ā¤Ą ⤕⤰⤤ ā¤†ā¤šāĨ‡â€Ļ", "asset_viewer_settings_subtitle": "⤆ā¤Ē⤞āĨā¤¯ā¤ž ⤗āĨ…⤞⤰āĨ€ ā¤ĩāĨā¤šāĨā¤¯āĨ‚ā¤…ā¤°ā¤šāĨā¤¯ā¤ž ⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗āĨā¤œ ā¤ĩāĨā¤¯ā¤ĩ⤏āĨā¤Ĩā¤žā¤Ēā¤ŋ⤤ ā¤•ā¤°ā¤ž", @@ -494,7 +503,9 @@ "assets": "ā¤¸ā¤žā¤§ā¤¨āĨ‡", "assets_added_count": "{count, plural, one {# ā¤¸ā¤žā¤§ā¤¨ ⤜āĨ‹ā¤Ąā¤˛āĨ‡} other {# ā¤¸ā¤žā¤§ā¤¨āĨ‡ ⤜āĨ‹ā¤Ąā¤˛āĨ‡}}", "assets_added_to_album_count": "{count, plural, one {# ā¤¸ā¤žā¤§ā¤¨ ⤅⤞āĨā¤Ŧā¤Žā¤Žā¤§āĨā¤¯āĨ‡ ⤜āĨ‹ā¤Ąā¤˛āĨ‡} other {# ā¤¸ā¤žā¤§ā¤¨āĨ‡ ⤅⤞āĨā¤Ŧā¤Žā¤Žā¤§āĨā¤¯āĨ‡ ⤜āĨ‹ā¤Ąā¤˛āĨ‡}}", + "assets_added_to_albums_count": "{albumTotal, plural, one {# ⤅⤞āĨā¤Ŧā¤Žā¤Žā¤§āĨā¤¯āĨ‡} other {# ⤅⤞āĨā¤Ŧā¤Žā¤Žā¤§āĨā¤¯āĨ‡}} {assetTotal, plural, one {# ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤•} other {# ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤•}} ⤜āĨ‹ā¤Ąā¤˛āĨ‡", "assets_cannot_be_added_to_album_count": "{count, plural, one {# ā¤¸ā¤žā¤§ā¤¨ ⤅⤞āĨā¤Ŧā¤Žā¤Žā¤§āĨā¤¯āĨ‡ ⤜āĨ‹ā¤Ąā¤¤ā¤ž ⤝āĨ‡ā¤Ŗā¤žā¤° ā¤¨ā¤žā¤šāĨ€} other {# ā¤¸ā¤žā¤§ā¤¨āĨ‡ ⤅⤞āĨā¤Ŧā¤Žā¤Žā¤§āĨā¤¯āĨ‡ ⤜āĨ‹ā¤Ąā¤¤ā¤ž ⤝āĨ‡ā¤Ŗā¤žā¤° ā¤¨ā¤žā¤šāĨ€ā¤¤}}", + "assets_cannot_be_added_to_albums": "{count, plural, one {# ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤• ⤕āĨ‹ā¤Ŗā¤¤āĨā¤¯ā¤žā¤šāĨ€ ⤅⤞āĨā¤Ŧā¤Žā¤Žā¤§āĨā¤¯āĨ‡ ⤜āĨ‹ā¤Ąā¤¤ā¤ž ⤝āĨ‡ā¤¤ ā¤¨ā¤žā¤šāĨ€} other {# ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤• ⤕āĨ‹ā¤Ŗā¤¤āĨā¤¯ā¤žā¤šāĨ€ ⤅⤞āĨā¤Ŧā¤Žā¤Žā¤§āĨā¤¯āĨ‡ ⤜āĨ‹ā¤Ąā¤¤ā¤ž ⤝āĨ‡ā¤¤ ā¤¨ā¤žā¤šāĨ€ā¤¤}}", "assets_count": "{count, plural, one {# ā¤¸ā¤žā¤§ā¤¨} other {# ā¤¸ā¤žā¤§ā¤¨āĨ‡}}", "assets_deleted_permanently": "{count} ā¤¸ā¤žā¤§ā¤¨(āĨ‡) ā¤•ā¤žā¤¯ā¤Žā¤šāĨ‡ ā¤šā¤Ÿā¤ĩā¤ŋ⤞āĨ‡", "assets_deleted_permanently_from_server": "Immich ⤏⤰āĨā¤ĩāĨā¤šā¤°ā¤ĩ⤰āĨ‚⤍ {count} ā¤¸ā¤žā¤§ā¤¨(āĨ‡) ā¤•ā¤žā¤¯ā¤Žā¤šāĨ‡ ā¤šā¤Ÿā¤ĩā¤ŋ⤞āĨ‡", @@ -502,6 +513,20 @@ "assets_downloaded_successfully": "{count, plural, one {ā¤ā¤• ā¤Ģā¤žā¤ˆā¤˛ ⤝ā¤ļ⤏āĨā¤ĩāĨ€ā¤°ā¤ŋ⤤āĨā¤¯ā¤ž ā¤Ąā¤žā¤‰ā¤¨ā¤˛āĨ‹ā¤Ą ā¤ā¤žā¤˛āĨ€} other {# ā¤Ģā¤žā¤ˆā¤˛āĨā¤¸ ⤝ā¤ļ⤏āĨā¤ĩāĨ€ā¤°ā¤ŋ⤤āĨā¤¯ā¤ž ā¤Ąā¤žā¤‰ā¤¨ā¤˛āĨ‹ā¤Ą ā¤ā¤žā¤˛āĨā¤¯ā¤ž}}", "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": "{count} ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤• ⤤āĨā¤Žā¤šāĨā¤¯ā¤ž ā¤Ąā¤ŋā¤ĩāĨā¤šā¤žā¤‡ā¤¸ā¤ĩ⤰āĨ‚⤍ ā¤•ā¤žā¤¯ā¤Žā¤šāĨ‡ ā¤•ā¤žā¤ĸ⤞āĨ‡ ⤗āĨ‡ā¤˛āĨ‡", + "assets_restore_confirmation": "ā¤•ā¤šā¤°ā¤žā¤ĒāĨ‡ā¤ŸāĨ€ā¤¤ā¤˛āĨ‡ ⤏⤰āĨā¤ĩ ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤• ā¤ĒāĨā¤¨ā¤°āĨā¤¸ā¤‚ā¤šā¤¯ā¤ŋ⤤ ā¤•ā¤°ā¤žā¤¯ā¤šāĨ‡ ā¤†ā¤šāĨ‡ā¤¤ ā¤•ā¤ž? ā¤šāĨ€ ⤕āĨƒā¤¤āĨ€ ā¤ĒāĨ‚⤰āĨā¤ĩā¤ĩ⤤ ā¤•ā¤°ā¤¤ā¤ž ⤝āĨ‡ā¤Ŗā¤žā¤° ā¤¨ā¤žā¤šāĨ€. ⤞⤕āĨā¤ˇā¤žā¤¤ ⤠āĨ‡ā¤ĩā¤ž - ⤑ā¤Ģā¤˛ā¤žā¤‡ā¤¨ ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤• ⤅ā¤ļā¤ž ā¤ĒāĨā¤°ā¤•ā¤žā¤°āĨ‡ ā¤ĒāĨā¤¨ā¤°āĨā¤¸ā¤‚ā¤šā¤¯ā¤ŋ⤤ ā¤•ā¤°ā¤¤ā¤ž ⤝āĨ‡ā¤¤ ā¤¨ā¤žā¤šāĨ€ā¤¤.", + "assets_restored_count": "{count, plural, one {# ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤• ā¤ĒāĨā¤¨ā¤°āĨā¤¸ā¤‚ā¤šā¤¯ā¤ŋ⤤ ⤕āĨ‡ā¤˛ā¤ž} other {# ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤• ā¤ĒāĨā¤¨ā¤°āĨā¤¸ā¤‚ā¤šā¤¯ā¤ŋ⤤ ⤕āĨ‡ā¤˛āĨ‡}}", + "assets_restored_successfully": "{count} ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤• ⤝ā¤ļ⤏āĨā¤ĩāĨ€ā¤°ā¤ŋ⤤āĨā¤¯ā¤ž ā¤ĒāĨā¤¨ā¤°āĨā¤¸ā¤‚ā¤šā¤¯ā¤ŋ⤤ ā¤ā¤žā¤˛āĨ‡", + "assets_trashed": "{count} ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤• ā¤•ā¤šā¤°ā¤žā¤ĒāĨ‡ā¤ŸāĨ€ā¤¤ ā¤šā¤˛ā¤ĩ⤞āĨ‡", + "assets_trashed_count": "{count, plural, one {# ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤• ā¤•ā¤šā¤°ā¤žā¤ĒāĨ‡ā¤ŸāĨ€ā¤¤ ā¤šā¤˛ā¤ĩā¤˛ā¤ž} other {# ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤• ā¤•ā¤šā¤°ā¤žā¤ĒāĨ‡ā¤ŸāĨ€ā¤¤ ā¤šā¤˛ā¤ĩ⤞āĨ‡}}", + "assets_trashed_from_server": "{count} ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤• Immich ⤏⤰āĨā¤ĩāĨā¤šā¤°ā¤ĩ⤰āĨ‚⤍ ā¤•ā¤šā¤°ā¤žā¤ĒāĨ‡ā¤ŸāĨ€ā¤¤ ā¤šā¤˛ā¤ĩ⤞āĨ‡", + "assets_were_part_of_album_count": "{count, plural, one {ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤• ⤆⤧āĨ€ā¤š ⤤āĨā¤¯ā¤ž ⤅⤞āĨā¤Ŧā¤Žā¤šā¤ž ā¤­ā¤žā¤— ā¤šāĨ‹ā¤¤ā¤ž} other {ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤• ⤆⤧āĨ€ā¤š ⤤āĨā¤¯ā¤ž ⤅⤞āĨā¤Ŧā¤Žā¤šā¤ž ā¤­ā¤žā¤— ā¤šāĨ‹ā¤¤āĨ‡}}", + "assets_were_part_of_albums_count": "{count, plural, one {ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤• ⤆⤧āĨ€ā¤š ⤅⤞āĨā¤Ŧā¤ŽāĨā¤¸ā¤šā¤ž ā¤­ā¤žā¤— ā¤šāĨ‹ā¤¤ā¤ž} other {ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤• ⤆⤧āĨ€ā¤š ⤅⤞āĨā¤Ŧā¤ŽāĨā¤¸ā¤šā¤ž ā¤­ā¤žā¤— ā¤šāĨ‹ā¤¤āĨ‡}}", + "authorized_devices": "⤅⤧ā¤ŋ⤕āĨƒā¤¤ ⤉ā¤Ē⤕⤰⤪āĨ‡", + "automatic_endpoint_switching_subtitle": "⤉ā¤Ē⤞ā¤ŦāĨā¤§ ⤅⤏⤞āĨā¤¯ā¤žā¤¸ ⤍ā¤ŋā¤ļāĨâ€ā¤šā¤ŋ⤤ Wi-Fi ā¤ĩ⤰ ⤏āĨā¤Ĩā¤žā¤¨ā¤ŋ⤕⤰ā¤ŋ⤤āĨā¤¯ā¤ž ⤕⤍āĨ‡ā¤•āĨā¤Ÿ ā¤•ā¤°ā¤ž ⤆⤪ā¤ŋ ⤇⤤⤰ ⤠ā¤ŋā¤•ā¤žā¤ŖāĨ€ ā¤Ē⤰āĨā¤¯ā¤žā¤¯āĨ€ ⤕⤍āĨ‡ā¤•āĨā¤ļ⤍ ā¤ĩā¤žā¤Ēā¤°ā¤ž", + "automatic_endpoint_switching_title": "⤏āĨā¤ĩā¤¯ā¤‚ā¤šā¤˛ā¤ŋ⤤ URL ⤏āĨā¤ĩā¤ŋ⤚ā¤ŋ⤂⤗", + "autoplay_slideshow": "⤏āĨā¤ĩā¤¯ā¤‚ā¤šā¤˛ā¤ŋ⤤ ⤏āĨā¤˛ā¤žā¤‡ā¤Ąā¤ļāĨ‹", "back": "ā¤Žā¤žā¤—āĨ‡", "back_close_deselect": "ā¤Žā¤žā¤—āĨ‡ ⤕ā¤ŋ⤂ā¤ĩā¤ž ā¤Ŧ⤂ā¤Ļ ā¤•ā¤°ā¤ž / ⤍ā¤ŋā¤ĩā¤Ą ⤰ā¤ĻāĨā¤Ļ ā¤•ā¤°ā¤ž", "background_location_permission": "ā¤ŦāĨ…⤕⤗āĨā¤°ā¤žā¤‰ā¤‚ā¤Ąā¤Žā¤§āĨā¤¯āĨ‡ ⤏āĨā¤Ĩā¤žā¤¨ ā¤Ē⤰ā¤ĩā¤žā¤¨ā¤—āĨ€ ā¤ĻāĨā¤¯ā¤ž", @@ -562,6 +587,7 @@ "backup_controller_page_turn_on": "ā¤ĢāĨ‹ā¤°ā¤—āĨā¤°ā¤žā¤‰ā¤‚ā¤Ą ā¤ŦāĨ…⤕⤅ā¤Ē ā¤šā¤žā¤˛āĨ‚ ā¤•ā¤°ā¤ž", "backup_controller_page_uploading_file_info": "ā¤Ģā¤žā¤ˆā¤˛ ā¤Žā¤žā¤šā¤ŋ⤤āĨ€ ⤅ā¤Ē⤞āĨ‹ā¤Ą ⤕⤰⤤ ā¤†ā¤šāĨ‡", "backup_err_only_album": "⤅⤂⤤ā¤ŋā¤Ž ⤅⤞āĨā¤Ŧā¤Ž ā¤•ā¤žā¤ĸā¤¤ā¤ž ⤝āĨ‡ā¤Ŗā¤žā¤° ā¤¨ā¤žā¤šāĨ€", + "backup_error_sync_failed": "ā¤¸ā¤Žā¤•āĨā¤°ā¤Žā¤Ŗ ⤅⤝ā¤ļ⤏āĨā¤ĩāĨ€. ā¤ŦāĨ…⤕⤅ā¤Ē ā¤ĒāĨā¤°ā¤•āĨā¤°ā¤ŋā¤¯ā¤ž ā¤•ā¤°ā¤¤ā¤ž ⤝āĨ‡ā¤¤ ā¤¨ā¤žā¤šāĨ€.", "backup_info_card_assets": "ā¤Ģā¤žā¤ˆā¤˛āĨā¤¸", "backup_manual_cancelled": "⤰ā¤ĻāĨā¤Ļ ⤕āĨ‡ā¤˛āĨ‡", "backup_manual_in_progress": "⤅ā¤Ē⤞āĨ‹ā¤Ą ⤆⤧āĨ€ā¤š ā¤šā¤žā¤˛āĨ‚ ā¤†ā¤šāĨ‡. ā¤ĨāĨ‹ā¤ĄāĨā¤¯ā¤žā¤ĩāĨ‡ā¤ŗāĨ‡ā¤¨ā¤‚⤤⤰ ā¤ĒāĨā¤¨āĨā¤šā¤ž ā¤ĒāĨā¤°ā¤¯ā¤¤āĨā¤¨ ā¤•ā¤°ā¤ž", @@ -572,8 +598,6 @@ "backup_setting_subtitle": "ā¤ŦāĨ…⤕⤗āĨā¤°ā¤žā¤‰ā¤‚ā¤Ą ⤆⤪ā¤ŋ ā¤ĢāĨ‹ā¤°ā¤—āĨā¤°ā¤žā¤‰ā¤‚ā¤Ą ⤅ā¤Ē⤞āĨ‹ā¤Ą ⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗āĨā¤œ ā¤ĩāĨā¤¯ā¤ĩ⤏āĨā¤Ĩā¤žā¤Ēā¤ŋ⤤ ā¤•ā¤°ā¤ž", "backup_settings_subtitle": "⤅ā¤Ē⤞āĨ‹ā¤Ą ⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗āĨā¤œ ā¤ĩāĨā¤¯ā¤ĩ⤏āĨā¤Ĩā¤žā¤Ēā¤ŋ⤤ ā¤•ā¤°ā¤ž", "backward": "ā¤Žā¤žā¤—ā¤žā¤¸ā¤˛āĨ‡ā¤˛āĨ‡", - "beta_sync": "ā¤ŦāĨ€ā¤Ÿā¤ž ⤏ā¤ŋ⤂⤕ ⤏āĨā¤Ĩā¤ŋ⤤āĨ€", - "beta_sync_subtitle": "⤍ā¤ĩāĨ€ā¤¨ ⤏ā¤ŋ⤂⤕ ā¤ĒāĨā¤°ā¤Ŗā¤žā¤˛āĨ€ ā¤ĩāĨā¤¯ā¤ĩ⤏āĨā¤Ĩā¤žā¤Ēā¤ŋ⤤ ā¤•ā¤°ā¤ž", "biometric_auth_enabled": "ā¤Ŧā¤žā¤¯āĨ‹ā¤ŽāĨ‡ā¤ŸāĨā¤°ā¤ŋ⤕ ā¤ĒāĨā¤°ā¤Žā¤žā¤ŖāĨ€ā¤•⤰⤪ ā¤šā¤žā¤˛āĨ‚ ā¤†ā¤šāĨ‡", "biometric_locked_out": "⤆ā¤Ē⤪ ā¤Ŧā¤žā¤¯āĨ‹ā¤ŽāĨ‡ā¤ŸāĨā¤°ā¤ŋ⤕ ā¤ĒāĨā¤°ā¤Žā¤žā¤ŖāĨ€ā¤•ā¤°ā¤Ŗā¤žā¤Ēā¤žā¤¸āĨ‚⤍ ⤞āĨ‰ā¤• ā¤†ā¤šā¤žā¤¤", "biometric_no_options": "⤕āĨ‹ā¤Ŗā¤¤āĨ‡ā¤šāĨ€ ā¤Ŧā¤žā¤¯āĨ‹ā¤ŽāĨ‡ā¤ŸāĨā¤°ā¤ŋ⤕ ā¤Ē⤰āĨā¤¯ā¤žā¤¯ ⤉ā¤Ē⤞ā¤ŦāĨā¤§ ā¤¨ā¤žā¤šāĨ€ā¤¤", @@ -631,6 +655,8 @@ "change_pin_code": "PIN ⤕āĨ‹ā¤Ą ā¤Ŧā¤Ļā¤˛ā¤ž", "change_your_password": "⤆ā¤Ēā¤˛ā¤ž ⤏⤂⤕āĨ‡ā¤¤ā¤ļā¤ŦāĨā¤Ļ ā¤Ŧā¤Ļā¤˛ā¤ž", "changed_visibility_successfully": "ā¤ĻāĨƒā¤ļāĨā¤¯ā¤Žā¤žā¤¨ā¤¤ā¤ž ⤝ā¤ļ⤏āĨā¤ĩāĨ€ā¤°ā¤ŋ⤤āĨā¤¯ā¤ž ā¤Ŧā¤Ļ⤞⤞āĨ€", + "charging": "ā¤šā¤žā¤°āĨā¤œā¤ŋ⤂⤗", + "charging_requirement_mobile_backup": "ā¤ŦāĨ…⤕⤗āĨā¤°ā¤žā¤‰ā¤‚ā¤Ą ā¤ŦāĨ…⤕⤅ā¤Ēā¤¸ā¤žā¤ āĨ€ ⤉ā¤Ē⤕⤰⤪ ā¤šā¤žā¤°āĨā¤œ ā¤šāĨ‹ā¤¤ ⤅⤏⤪āĨ‡ ⤆ā¤ĩā¤ļāĨā¤¯ā¤• ā¤†ā¤šāĨ‡", "check_corrupt_asset_backup": "⤭āĨā¤°ā¤ˇāĨā¤Ÿ ā¤Ģā¤žā¤ˆā¤˛ ā¤ŦāĨ…⤕⤅ā¤Ē ⤤ā¤Ēā¤žā¤¸ā¤ž", "check_corrupt_asset_backup_button": "⤤ā¤Ēā¤žā¤¸ā¤ŖāĨ€ ā¤•ā¤°ā¤ž", "check_corrupt_asset_backup_description": "ā¤Ģ⤕āĨā¤¤ Wi-Fi ā¤ĩ⤰ ā¤šā¤ž ⤤ā¤Ēā¤žā¤¸ ā¤šā¤žā¤˛ā¤ĩā¤ž ⤆⤪ā¤ŋ ⤏⤰āĨā¤ĩ ā¤Ģā¤žā¤ˆā¤˛āĨā¤¸ ā¤ŦāĨ…⤕⤅ā¤Ē ā¤ā¤žā¤˛āĨā¤¯ā¤žā¤ĩ⤰⤚. ā¤ĒāĨā¤°ā¤•āĨā¤°ā¤ŋā¤¯ā¤ž ā¤•ā¤žā¤šāĨ€ ā¤Žā¤ŋ⤍ā¤ŋ⤟āĨ‡ ā¤˛ā¤žā¤—āĨ‚ ā¤ļ⤕⤤āĨ‡.", @@ -717,6 +743,7 @@ "create_user": "ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤ā¤ž ā¤¤ā¤¯ā¤žā¤° ā¤•ā¤°ā¤ž", "created": "ā¤¤ā¤¯ā¤žā¤° ⤕āĨ‡ā¤˛āĨ‡", "created_at": "⤍ā¤ŋ⤰āĨā¤Žā¤ŋ⤤āĨ€ ā¤¤ā¤žā¤°āĨ€ā¤–", + "creating_linked_albums": "⤞ā¤ŋ⤂⤕ ⤕āĨ‡ā¤˛āĨ‡ā¤˛āĨ‡ ⤅⤞āĨā¤Ŧā¤Ž ā¤¤ā¤¯ā¤žā¤° ⤕⤰⤤ ā¤†ā¤šāĨ‡...", "crop": "ā¤›ā¤žā¤Ÿā¤ŖāĨ€ ā¤•ā¤°ā¤ž", "curated_object_page_title": "⤗āĨ‹ā¤ˇāĨā¤ŸāĨ€", "current_device": "ā¤ĩ⤰āĨā¤¤ā¤Žā¤žā¤¨ ⤉ā¤Ē⤕⤰⤪", @@ -1034,6 +1061,7 @@ "filter_people": "⤞āĨ‹ā¤• ā¤Ģā¤ŋ⤞āĨā¤Ÿā¤° ā¤•ā¤°ā¤ž", "filter_places": "⤠ā¤ŋā¤•ā¤žā¤ŖāĨ‡ ā¤Ģā¤ŋ⤞āĨā¤Ÿā¤° ā¤•ā¤°ā¤ž", "find_them_fast": "ā¤¨ā¤žā¤ĩā¤žā¤¨āĨ‡ ā¤Ēā¤Ÿā¤•ā¤¨ ā¤ļāĨ‹ā¤§ā¤ž", + "first": "ā¤ĒāĨā¤°ā¤Ĩā¤Ž", "fix_incorrect_match": "⤚āĨā¤•āĨ€ā¤šāĨ€ ⤜āĨā¤ŗā¤ŖāĨ€ ā¤ĻāĨā¤°āĨā¤¸āĨā¤¤ ā¤•ā¤°ā¤ž", "folder": "ā¤ĢāĨ‹ā¤˛āĨā¤Ąā¤°", "folder_not_found": "ā¤ĢāĨ‹ā¤˛āĨā¤Ąā¤° ā¤¸ā¤žā¤Ēā¤Ąā¤˛ā¤ž ā¤¨ā¤žā¤šāĨ€", @@ -1044,18 +1072,772 @@ "gcast_enabled": "Google Cast", "gcast_enabled_description": "ā¤šāĨ€ ⤏āĨā¤ĩā¤ŋā¤§ā¤ž ā¤šā¤žā¤˛ā¤ŖāĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ Google ā¤•ā¤ĄāĨ€ā¤˛ ā¤Ŧā¤žā¤šāĨā¤¯ ā¤¸ā¤‚ā¤¸ā¤žā¤§ā¤¨āĨ‡ ⤞āĨ‹ā¤Ą ⤕⤰⤤āĨ‡.", "general": "ā¤¸ā¤žā¤Žā¤žā¤¨āĨā¤¯", + "geolocation_instruction_location": "GPS ⤍ā¤ŋ⤰āĨā¤ĻāĨ‡ā¤ļā¤žā¤‚ā¤• ⤅⤏⤞āĨ‡ā¤˛āĨā¤¯ā¤ž ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤•ā¤žā¤ĩ⤰ ⤕āĨā¤˛ā¤ŋ⤕ ⤕⤰āĨ‚⤍ ⤤āĨā¤¯ā¤žā¤šāĨ‡ ⤏āĨā¤Ĩā¤žā¤¨ ā¤ĩā¤žā¤Ēā¤°ā¤ž, ⤕ā¤ŋ⤂ā¤ĩā¤ž ā¤ĨāĨ‡ā¤Ÿ ā¤¨ā¤•ā¤žā¤ļā¤žā¤ĩ⤰āĨ‚⤍ ⤏āĨā¤Ĩā¤žā¤¨ ⤍ā¤ŋā¤ĩā¤Ąā¤ž", "get_help": "ā¤Žā¤Ļ⤤ ⤘āĨā¤¯ā¤ž", "get_wifiname_error": "Wi-Fi ⤚āĨ‡ ā¤¨ā¤žā¤ĩ ā¤Žā¤ŋā¤ŗā¤žā¤˛āĨ‡ ā¤¨ā¤žā¤šāĨ€. ⤆ā¤ĩā¤ļāĨā¤¯ā¤• ā¤Ē⤰ā¤ĩā¤žā¤¨ā¤—āĨā¤¯ā¤ž ā¤Ļā¤ŋ⤞āĨā¤¯ā¤ž ā¤†ā¤šāĨ‡ā¤¤ ⤆⤪ā¤ŋ Wi-Fi ⤍āĨ‡ā¤Ÿā¤ĩ⤰āĨā¤•ā¤ļāĨ€ ⤜āĨ‹ā¤Ąā¤˛āĨ‡ ā¤†ā¤šā¤žā¤¤ ā¤¯ā¤žā¤šāĨ€ ā¤–ā¤žā¤¤āĨā¤°āĨ€ ā¤•ā¤°ā¤ž", "getting_started": "⤏āĨā¤°āĨā¤ĩā¤žā¤¤ ā¤•ā¤°ā¤ž", "go_back": "ā¤Žā¤žā¤—āĨ‡ ā¤œā¤ž", "go_to_folder": "ā¤ĢāĨ‹ā¤˛āĨā¤Ąā¤°ā¤•ā¤ĄāĨ‡ ā¤œā¤ž", "go_to_search": "ā¤ļāĨ‹ā¤§ā¤žā¤•ā¤ĄāĨ‡ ā¤œā¤ž", + "gps": "⤜āĨ€ā¤ĒāĨ€ā¤ā¤¸", + "gps_missing": "GPS ⤉ā¤Ē⤞ā¤ŦāĨā¤§ ā¤¨ā¤žā¤šāĨ€", "grant_permission": "ā¤Ē⤰ā¤ĩā¤žā¤¨ā¤—āĨ€ ā¤ĻāĨā¤¯ā¤ž", "group_albums_by": "⤅⤞āĨā¤Ŧā¤Ž ā¤—ā¤Ÿā¤Ŧā¤ĻāĨā¤§ ā¤•ā¤°ā¤ž: â€Ļ", "group_country": "ā¤ĻāĨ‡ā¤ļā¤žā¤¨āĨā¤¸ā¤žā¤° ā¤—ā¤Ÿ ā¤•ā¤°ā¤ž", "group_no": "ā¤—ā¤Ÿā¤Ŧā¤ĻāĨā¤§ ā¤¨ā¤žā¤šāĨ€", "group_owner": "ā¤Žā¤žā¤˛ā¤•ā¤žā¤¨āĨā¤¸ā¤žā¤° ā¤—ā¤Ÿ ā¤•ā¤°ā¤ž", "group_places_by": "⤏āĨā¤Ĩ⤺āĨ‡ ā¤—ā¤Ÿā¤Ŧā¤ĻāĨā¤§ ā¤•ā¤°ā¤ž: â€Ļ", + "group_year": "ā¤ĩ⤰āĨā¤ˇā¤žā¤¨āĨā¤¸ā¤žā¤° ā¤—ā¤Ÿā¤Ŧā¤ĻāĨā¤§ ā¤•ā¤°ā¤ž", + "haptic_feedback_switch": "ā¤šāĨ…ā¤ĒāĨā¤Ÿā¤ŋ⤕ ā¤ĢāĨ€ā¤Ąā¤ŦāĨ…⤕ ⤏⤕āĨā¤ˇā¤Ž ā¤•ā¤°ā¤ž", + "haptic_feedback_title": "ā¤šāĨ…ā¤ĒāĨā¤Ÿā¤ŋ⤕ ā¤ĢāĨ€ā¤Ąā¤ŦāĨ…⤕", + "has_quota": "⤕āĨ‹ā¤Ÿā¤ž ā¤†ā¤šāĨ‡", + "hash_asset": "ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤•ā¤žā¤šā¤ž ā¤šāĨ…ā¤ļ ā¤¤ā¤¯ā¤žā¤° ā¤•ā¤°ā¤ž", + "hashed_assets": "ā¤šāĨ…ā¤ļ ⤕āĨ‡ā¤˛āĨ‡ā¤˛āĨ‡ ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤•", + "hashing": "ā¤šāĨ…ā¤ļā¤ŋ⤂⤗", + "header_settings_add_header_tip": "ā¤šāĨ‡ā¤Ąā¤° ⤜āĨ‹ā¤Ąā¤ž", + "header_settings_field_validator_msg": "ā¤ŽāĨ‚⤞āĨā¤¯ ⤰ā¤ŋā¤•ā¤žā¤ŽāĨ‡ ⤅⤏āĨ‚ ā¤ļ⤕⤤ ā¤¨ā¤žā¤šāĨ€", + "header_settings_header_name_input": "ā¤šāĨ‡ā¤Ąā¤°ā¤šāĨ‡ ā¤¨ā¤žā¤ĩ", + "header_settings_header_value_input": "ā¤šāĨ‡ā¤Ąā¤°ā¤šāĨ‡ ā¤ŽāĨ‚⤞āĨā¤¯", + "headers_settings_tile_subtitle": "ā¤ĒāĨā¤°ā¤¤āĨā¤¯āĨ‡ā¤• ⤍āĨ‡ā¤Ÿā¤ĩ⤰āĨā¤• ā¤ĩā¤ŋ⤍⤂⤤āĨ€ā¤¸āĨ‹ā¤Ŧ⤤ ā¤…â€āĨ…ā¤Ē⤍āĨ‡ ā¤Ēā¤žā¤ ā¤ĩā¤žā¤¯ā¤šāĨ‡ ā¤ĒāĨā¤°āĨ‰ā¤•āĨā¤¸āĨ€ ā¤šāĨ‡ā¤Ąā¤°āĨā¤¸ ā¤Ē⤰ā¤ŋā¤­ā¤žā¤ˇā¤ŋ⤤ ā¤•ā¤°ā¤ž", + "headers_settings_tile_title": "ā¤¸ā¤žā¤¨āĨā¤•āĨ‚⤞ ā¤ĒāĨā¤°āĨ‰ā¤•āĨā¤¸āĨ€ ā¤šāĨ‡ā¤Ąā¤°āĨā¤¸", + "hi_user": "ā¤¨ā¤Žā¤¸āĨā¤•ā¤žā¤° {name} ({email})", + "hide_all_people": "⤏⤰āĨā¤ĩ ā¤ĩāĨā¤¯ā¤•āĨā¤¤āĨ€ ⤞ā¤Ēā¤ĩā¤ž", + "hide_gallery": "⤗āĨ…⤞⤰āĨ€ ⤞ā¤Ēā¤ĩā¤ž", + "hide_named_person": "ā¤ĩāĨā¤¯ā¤•āĨā¤¤āĨ€ {name} ⤞ā¤Ēā¤ĩā¤ž", + "hide_password": "⤏⤂⤕āĨ‡ā¤¤ā¤ļā¤ŦāĨā¤Ļ ⤞ā¤Ēā¤ĩā¤ž", + "hide_person": "ā¤ĩāĨā¤¯ā¤•āĨā¤¤āĨ€ ⤞ā¤Ēā¤ĩā¤ž", + "hide_unnamed_people": "ā¤¨ā¤žā¤ĩ ⤍⤏⤞āĨ‡ā¤˛āĨā¤¯ā¤ž ā¤ĩāĨā¤¯ā¤•āĨā¤¤āĨ€ ⤞ā¤Ēā¤ĩā¤ž", + "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_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_first_time_notice": "ā¤…â€āĨ…ā¤Ē ā¤ĒāĨā¤°ā¤Ĩā¤Žā¤š ā¤ĩā¤žā¤Ē⤰⤤ ā¤…ā¤¸ā¤žā¤˛ ⤤⤰ ā¤Ÿā¤žā¤‡ā¤Žā¤˛ā¤žā¤‡ā¤¨ā¤Žā¤§āĨā¤¯āĨ‡ ā¤ĢāĨ‹ā¤ŸāĨ‹ ⤆⤪ā¤ŋ ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓ ⤭⤰⤪āĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ ⤕āĨƒā¤Ēā¤¯ā¤ž ā¤ŦāĨ…⤕⤅ā¤Ē ⤅⤞āĨā¤Ŧā¤Ž ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "home_page_locked_error_local": "⤏āĨā¤Ĩā¤žā¤¨ā¤ŋ⤕ ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤• ⤞āĨ‰ā¤• ⤕āĨ‡ā¤˛āĨ‡ā¤˛āĨā¤¯ā¤ž ā¤ĢāĨ‹ā¤˛āĨā¤Ąā¤°ā¤Žā¤§āĨā¤¯āĨ‡ ā¤šā¤˛ā¤ĩā¤¤ā¤ž ⤝āĨ‡ā¤¤ ā¤¨ā¤žā¤šāĨ€ā¤¤, ā¤ĩ⤗⤺⤤ ā¤†ā¤šāĨ‡", + "home_page_locked_error_partner": "ā¤­ā¤žā¤—āĨ€ā¤Ļā¤žā¤°ā¤šāĨ‡ ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤• ⤞āĨ‰ā¤• ⤕āĨ‡ā¤˛āĨ‡ā¤˛āĨā¤¯ā¤ž ā¤ĢāĨ‹ā¤˛āĨā¤Ąā¤°ā¤Žā¤§āĨā¤¯āĨ‡ ā¤šā¤˛ā¤ĩā¤¤ā¤ž ⤝āĨ‡ā¤¤ ā¤¨ā¤žā¤šāĨ€ā¤¤, ā¤ĩ⤗⤺⤤ ā¤†ā¤šāĨ‡", + "home_page_share_err_local": "⤏āĨā¤Ĩā¤žā¤¨ā¤ŋ⤕ ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤• ⤞ā¤ŋ⤂⤕ā¤ĻāĨā¤ĩā¤žā¤°āĨ‡ ā¤ļāĨ‡ā¤…⤰ ā¤•ā¤°ā¤¤ā¤ž ⤝āĨ‡ā¤¤ ā¤¨ā¤žā¤šāĨ€ā¤¤, ā¤ĩ⤗⤺⤤ ā¤†ā¤šāĨ‡", + "home_page_upload_err_limit": "ā¤ā¤•ā¤žā¤ĩāĨ‡ā¤ŗāĨ€ ā¤•ā¤Žā¤žā¤˛ 30 ā¤ŽāĨ€ā¤Ąā¤ŋā¤¯ā¤ž ā¤˜ā¤Ÿā¤•ā¤š ⤅ā¤Ē⤞āĨ‹ā¤Ą ā¤•ā¤°ā¤¤ā¤ž ⤝āĨ‡ā¤¤ā¤žā¤¤, ā¤ĩ⤗⤺⤤ ā¤†ā¤šāĨ‡", + "host": "ā¤šāĨ‹ā¤¸āĨā¤Ÿ", + "hour": "ā¤¤ā¤žā¤¸", + "hours": "ā¤¤ā¤žā¤¸", + "id": "ID", + "idle": "⤍ā¤ŋ⤎āĨā¤•āĨā¤°ā¤ŋ⤝", + "ignore_icloud_photos": "iCloud ā¤ĩ⤰āĨ€ā¤˛ ā¤ĢāĨ‹ā¤ŸāĨ‹ ā¤ĻāĨā¤°āĨā¤˛ā¤•āĨā¤ˇā¤ŋ⤤ ā¤•ā¤°ā¤ž", + "ignore_icloud_photos_description": "iCloud ā¤ĩ⤰ ā¤¸ā¤žā¤ ā¤ĩ⤞āĨ‡ā¤˛āĨ‡ ā¤ĢāĨ‹ā¤ŸāĨ‹ Immich ⤏⤰āĨā¤ĩāĨā¤šā¤°ā¤ĩ⤰ ⤅ā¤Ē⤞āĨ‹ā¤Ą ⤕āĨ‡ā¤˛āĨ‡ ā¤œā¤žā¤Ŗā¤žā¤° ā¤¨ā¤žā¤šāĨ€ā¤¤", + "image": "ā¤ĢāĨ‹ā¤ŸāĨ‹", + "image_alt_text_date": "{isVideo, select, true {ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓} other {ā¤ĢāĨ‹ā¤ŸāĨ‹}} {date} ā¤˛ā¤ž ⤘āĨ‡ā¤¤ā¤˛āĨ‡", + "image_alt_text_date_1_person": "{isVideo, select, true {ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓} other {ā¤ĢāĨ‹ā¤ŸāĨ‹}} {person1} ⤏āĨ‹ā¤Ŧ⤤ {date} ā¤˛ā¤ž ⤘āĨ‡ā¤¤ā¤˛āĨ‡", + "image_alt_text_date_2_people": "{isVideo, select, true {ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓} other {ā¤ĢāĨ‹ā¤ŸāĨ‹}} {person1} ⤆⤪ā¤ŋ {person2} ⤏āĨ‹ā¤Ŧ⤤ {date} ā¤˛ā¤ž ⤘āĨ‡ā¤¤ā¤˛āĨ‡", + "image_alt_text_date_3_people": "{isVideo, select, true {ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓} other {ā¤ĢāĨ‹ā¤ŸāĨ‹}} {person1}, {person2} ⤆⤪ā¤ŋ {person3} ⤏āĨ‹ā¤Ŧ⤤ {date} ā¤˛ā¤ž ⤘āĨ‡ā¤¤ā¤˛āĨ‡", + "image_alt_text_date_4_or_more_people": "{isVideo, select, true {ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓} other {ā¤ĢāĨ‹ā¤ŸāĨ‹}} {person1}, {person2} ⤆⤪ā¤ŋ ⤆⤪⤖āĨ€ {additionalCount, number} ā¤œā¤Ŗā¤žā¤‚ā¤¸āĨ‹ā¤Ŧ⤤ {date} ā¤˛ā¤ž ⤘āĨ‡ā¤¤ā¤˛āĨ‡", + "image_alt_text_date_place": "{isVideo, select, true {ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓} other {ā¤ĢāĨ‹ā¤ŸāĨ‹}} {city}, {country} ⤝āĨ‡ā¤ĨāĨ‡ {date} ā¤˛ā¤ž ⤘āĨ‡ā¤¤ā¤˛āĨ‡", + "image_alt_text_date_place_1_person": "{isVideo, select, true {ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓} other {ā¤ĢāĨ‹ā¤ŸāĨ‹}} {city}, {country} ⤝āĨ‡ā¤ĨāĨ‡ {person1} ⤏āĨ‹ā¤Ŧ⤤ {date} ā¤˛ā¤ž ⤘āĨ‡ā¤¤ā¤˛āĨ‡", + "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 ā¤¸ā¤‚ā¤¸ā¤žā¤§ā¤¨āĨ‡", + "offline": "⤑ā¤Ģā¤˛ā¤žā¤‡ā¤¨", + "offset": "⤑ā¤Ģ⤏āĨ‡ā¤Ÿ", + "ok": "⤠āĨ€ā¤•", + "oldest_first": "⤏⤰āĨā¤ĩā¤žā¤¤ ⤜āĨā¤¨āĨ‡ ⤆⤧āĨ€", + "on_this_device": "ā¤¯ā¤ž ā¤Ąā¤ŋā¤ĩāĨā¤šā¤žā¤‡ā¤¸ā¤ĩ⤰", + "onboarding": "⤑⤍ā¤ŦāĨ‹ā¤°āĨā¤Ąā¤ŋ⤂⤗", + "onboarding_locale_description": "⤤āĨā¤Žā¤šāĨ€ ā¤Ē⤏⤂⤤āĨ€ā¤šāĨ€ ā¤­ā¤žā¤ˇā¤ž ⤍ā¤ŋā¤ĩā¤Ąā¤ž. ā¤šāĨ‡ ⤍⤂⤤⤰ ⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗āĨā¤œā¤Žā¤§āĨā¤¯āĨ‡ ā¤Ŧā¤Ļ⤞āĨ‚ ā¤ļā¤•ā¤¤ā¤ž.", + "onboarding_privacy_description": "ā¤–ā¤žā¤˛āĨ€ā¤˛ (ā¤Ē⤰āĨā¤¯ā¤žā¤¯āĨ€) ā¤ĩāĨˆā¤ļā¤ŋ⤎āĨā¤ŸāĨā¤¯āĨ‡ ā¤Ŧā¤žā¤šāĨā¤¯ ⤏āĨ‡ā¤ĩā¤žā¤‚ā¤ĩ⤰ ⤅ā¤ĩ⤞⤂ā¤ŦāĨ‚⤍ ā¤†ā¤šāĨ‡ā¤¤ ⤆⤪ā¤ŋ ⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗āĨā¤œā¤Žā¤§āĨā¤¯āĨ‡ ⤕⤧āĨ€ā¤šāĨ€ ⤅⤕āĨā¤ˇā¤Ž ā¤•ā¤°ā¤¤ā¤ž ⤝āĨ‡ā¤¤ā¤žā¤¤.", + "onboarding_server_welcome_description": "ā¤•ā¤žā¤šāĨ€ ā¤¸ā¤žā¤Žā¤žā¤¨āĨā¤¯ ⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗āĨā¤œā¤¸ā¤š ⤤āĨā¤Žā¤šāĨ€ ⤇⤍āĨā¤¸āĨā¤Ÿā¤¨āĨā¤¸ ⤏āĨ‡ā¤Ÿā¤…ā¤Ē ⤕⤰āĨ‚ā¤¯ā¤ž.", + "onboarding_theme_description": "⤤āĨā¤Žā¤šāĨā¤¯ā¤ž ⤇⤍āĨā¤¸āĨā¤Ÿā¤¨āĨā¤¸ā¤¸ā¤žā¤ āĨ€ ⤰⤂⤗ ā¤ĨāĨ€ā¤Ž ⤍ā¤ŋā¤ĩā¤Ąā¤ž. ā¤šāĨ‡ ⤍⤂⤤⤰ ⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗āĨā¤œā¤Žā¤§āĨā¤¯āĨ‡ ā¤Ŧā¤Ļ⤞āĨ‚ ā¤ļā¤•ā¤¤ā¤ž.", + "onboarding_user_welcome_description": "ā¤šā¤˛ā¤ž, ⤏āĨā¤°āĨā¤ĩā¤žā¤¤ ⤕⤰āĨ‚ā¤¯ā¤ž!", + "onboarding_welcome_user": "⤏āĨā¤ĩā¤žā¤—ā¤¤ ā¤†ā¤šāĨ‡, {user}", + "online": "ā¤‘ā¤¨ā¤˛ā¤žā¤‡ā¤¨", + "only_favorites": "ā¤Ģ⤕āĨā¤¤ ⤆ā¤ĩā¤Ąā¤¤āĨ‡", + "open": "ā¤‰ā¤˜ā¤Ąā¤ž", + "open_in_map_view": "ā¤¨ā¤•ā¤žā¤ļā¤ž ā¤ĻāĨƒā¤ļāĨā¤¯ā¤žā¤¤ ā¤‰ā¤˜ā¤Ąā¤ž", + "open_in_openstreetmap": "OpenStreetMap ā¤Žā¤§āĨā¤¯āĨ‡ ā¤‰ā¤˜ā¤Ąā¤ž", + "open_the_search_filters": "ā¤ļāĨ‹ā¤§ ā¤Ģā¤ŋ⤞āĨā¤Ÿā¤° ā¤‰ā¤˜ā¤Ąā¤ž", + "options": "ā¤Ē⤰āĨā¤¯ā¤žā¤¯", + "or": "⤕ā¤ŋ⤂ā¤ĩā¤ž", + "organize_into_albums": "⤅⤞āĨā¤Ŧā¤Žā¤Žā¤§āĨā¤¯āĨ‡ ⤆⤝āĨ‹ā¤œā¤ŋ⤤ ā¤•ā¤°ā¤ž", + "organize_into_albums_description": "⤏⤧āĨā¤¯ā¤žā¤šāĨā¤¯ā¤ž ā¤¸ā¤Žā¤•āĨā¤°ā¤Žā¤Ŗ ⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗āĨā¤œ ā¤ĩā¤žā¤Ē⤰āĨ‚⤍ ā¤ĩā¤ŋā¤ĻāĨā¤¯ā¤Žā¤žā¤¨ ā¤ĢāĨ‹ā¤ŸāĨ‹ ⤅⤞āĨā¤Ŧā¤Žā¤Žā¤§āĨā¤¯āĨ‡ ⤠āĨ‡ā¤ĩā¤ž", + "organize_your_library": "⤤āĨā¤Žā¤šāĨ€ ā¤˛ā¤žā¤¯ā¤ŦāĨā¤°ā¤°āĨ€ ā¤ĩāĨā¤¯ā¤ĩ⤏āĨā¤Ĩā¤ŋ⤤ ā¤•ā¤°ā¤ž", + "original": "ā¤ŽāĨ‚⤺", + "other": "⤇⤤⤰", + "other_devices": "⤇⤤⤰ ⤉ā¤Ē⤕⤰⤪āĨ‡", + "other_entities": "⤇⤤⤰ ā¤˜ā¤Ÿā¤•", + "other_variables": "⤇⤤⤰ ⤚⤞", + "owned": "ā¤Žā¤žā¤˛ā¤•āĨ€ā¤šāĨ‡", + "owner": "ā¤Žā¤žā¤˛ā¤•", + "partner": "ā¤­ā¤žā¤—āĨ€ā¤Ļā¤žā¤°", + "partner_can_access": "{partner} ā¤˛ā¤ž ā¤ĒāĨā¤°ā¤ĩāĨ‡ā¤ļ ā¤†ā¤šāĨ‡", + "partner_can_access_assets": "⤏⤂⤗āĨā¤°ā¤šā¤ŋ⤤ ā¤ĩ ā¤šā¤Ÿā¤ĩā¤ŋ⤞āĨ‡ā¤˛āĨ‡ ā¤ĩā¤—ā¤ŗā¤¤ā¤ž ⤤āĨā¤Žā¤šāĨ‡ ⤏⤰āĨā¤ĩ ā¤ĢāĨ‹ā¤ŸāĨ‹ ⤆⤪ā¤ŋ ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓", + "partner_can_access_location": "⤜āĨā¤¯ā¤ž ⤠ā¤ŋā¤•ā¤žā¤ŖāĨ€ ⤤āĨā¤Žā¤šāĨ‡ ā¤ĢāĨ‹ā¤ŸāĨ‹ ā¤•ā¤žā¤ĸ⤞āĨ‡ ⤗āĨ‡ā¤˛āĨ‡ ⤤āĨ‡ ⤏āĨā¤Ĩā¤žā¤¨", + "partner_list_user_photos": "{user} ⤚āĨ‡ ā¤ĢāĨ‹ā¤ŸāĨ‹", + "partner_list_view_all": "⤏⤰āĨā¤ĩ ā¤Ēā¤šā¤ž", + "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} ā¤†ā¤¤ā¤ž ⤤āĨā¤Žā¤šāĨ‡ ā¤ĢāĨ‹ā¤ŸāĨ‹ ā¤Ēā¤žā¤šāĨ‚ ā¤ļā¤•ā¤Ŗā¤žā¤° ā¤¨ā¤žā¤šāĨ€.", + "partner_sharing": "ā¤­ā¤žā¤—āĨ€ā¤Ļā¤žā¤° ā¤ļāĨ‡ā¤…⤰ā¤ŋ⤂⤗", + "partners": "ā¤­ā¤žā¤—āĨ€ā¤Ļā¤žā¤°", + "password": "ā¤Ēā¤žā¤¸ā¤ĩ⤰āĨā¤Ą", + "password_does_not_match": "ā¤Ēā¤žā¤¸ā¤ĩ⤰āĨā¤Ą ⤜āĨā¤ŗā¤¤ ā¤¨ā¤žā¤šāĨ€", + "password_required": "ā¤Ēā¤žā¤¸ā¤ĩ⤰āĨā¤Ą ⤆ā¤ĩā¤ļāĨā¤¯ā¤•", + "password_reset_success": "ā¤Ēā¤žā¤¸ā¤ĩ⤰āĨā¤Ą ⤰āĨ€ā¤¸āĨ‡ā¤Ÿ ⤝ā¤ļ⤏āĨā¤ĩāĨ€", + "past_durations": { + "days": "ā¤Žā¤žā¤—āĨ€ā¤˛ {days, plural, one {# ā¤Ļā¤ŋā¤ĩ⤏} other {# ā¤Ļā¤ŋā¤ĩ⤏}}", + "hours": "ā¤Žā¤žā¤—āĨ€ā¤˛ {hours, plural, one {# ā¤¤ā¤žā¤¸} other {# ā¤¤ā¤žā¤¸}}", + "years": "ā¤Žā¤žā¤—āĨ€ā¤˛ {years, plural, one {# ā¤ĩ⤰āĨā¤ˇ} other {# ā¤ĩ⤰āĨā¤ˇāĨ‡}}" + }, + "path": "ā¤Žā¤žā¤°āĨā¤—", + "pattern": "ā¤¨ā¤ŽāĨā¤¨ā¤ž", + "pause": "ā¤Ĩā¤žā¤‚ā¤Ŧā¤ĩā¤ž", + "pause_memories": "⤆⤠ā¤ĩ⤪āĨ€ ā¤Ĩā¤žā¤‚ā¤Ŧā¤ĩā¤ž", + "paused": "ā¤Ĩā¤žā¤‚ā¤Ŧā¤ĩ⤞āĨ‡", + "pending": "ā¤ĒāĨā¤°ā¤˛ā¤‚ā¤Ŧā¤ŋ⤤", + "people": "⤞āĨ‹ā¤•", + "people_edits_count": "⤏⤂ā¤Ēā¤žā¤Ļā¤ŋ⤤ {count, plural, one {# ā¤ĩāĨā¤¯ā¤•āĨā¤¤āĨ€} other {# ⤞āĨ‹ā¤•}}", + "people_feature_description": "⤞āĨ‹ā¤•ā¤žā¤‚ā¤¨āĨā¤¸ā¤žā¤° ā¤—ā¤Ÿā¤Ŧā¤ĻāĨā¤§ ā¤ĢāĨ‹ā¤ŸāĨ‹ ⤆⤪ā¤ŋ ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓ ā¤ŦāĨā¤°ā¤žā¤‰ā¤ ā¤•ā¤°ā¤ž", + "people_sidebar_description": "ā¤¸ā¤žā¤‡ā¤Ąā¤Ŧā¤žā¤°ā¤Žā¤§āĨā¤¯āĨ‡ â€œā¤˛āĨ‹ā¤•” ā¤¸ā¤žā¤ āĨ€ ā¤ĻāĨā¤ĩā¤ž ā¤Ļā¤žā¤–ā¤ĩā¤ž", + "permanent_deletion_warning": "ā¤•ā¤žā¤¯ā¤Žā¤¸āĨā¤ĩ⤰āĨ‚ā¤ĒāĨ€ ā¤ĩā¤ŋ⤞āĨ‹ā¤Ē⤍ ⤏āĨ‚ā¤šā¤¨ā¤ž", + "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 {# ā¤…â€āĨ…⤏āĨ‡ā¤ŸāĨā¤¸}}", + "permission": "ā¤Ē⤰ā¤ĩā¤žā¤¨ā¤—āĨ€", + "permission_empty": "⤤āĨā¤Žā¤šāĨ€ ā¤Ē⤰ā¤ĩā¤žā¤¨ā¤—āĨ€ ⤰ā¤ŋ⤕āĨā¤¤ ⤅⤏āĨ‚ ⤍⤝āĨ‡", + "permission_onboarding_back": "ā¤Žā¤žā¤—āĨ‡", + "permission_onboarding_continue_anyway": "⤤⤰āĨ€ā¤šāĨ€ ā¤ĒāĨā¤ĸāĨ‡ ā¤œā¤ž", + "permission_onboarding_get_started": "⤏āĨā¤°āĨ‚ ā¤•ā¤°ā¤ž", + "permission_onboarding_go_to_settings": "⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗āĨā¤œā¤Žā¤§āĨā¤¯āĨ‡ ā¤œā¤ž", + "permission_onboarding_permission_denied": "ā¤Ē⤰ā¤ĩā¤žā¤¨ā¤—āĨ€ ā¤¨ā¤žā¤•ā¤žā¤°ā¤˛āĨ€. Immich ā¤ĩā¤žā¤Ē⤰⤪āĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€, ⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗āĨā¤œā¤Žā¤§āĨā¤¯āĨ‡ ā¤ĢāĨ‹ā¤ŸāĨ‹ ⤆⤪ā¤ŋ ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓ ā¤Ē⤰ā¤ĩā¤žā¤¨ā¤—āĨā¤¯ā¤ž ā¤ĻāĨā¤¯ā¤ž.", + "permission_onboarding_permission_granted": "ā¤Ē⤰ā¤ĩā¤žā¤¨ā¤—āĨ€ ā¤Žā¤‚ā¤œāĨ‚⤰! ⤏⤰āĨā¤ĩ ā¤¤ā¤¯ā¤žā¤°.", + "permission_onboarding_permission_limited": "ā¤Ē⤰ā¤ĩā¤žā¤¨ā¤—āĨ€ ā¤Žā¤°āĨā¤¯ā¤žā¤Ļā¤ŋ⤤. Immich ā¤˛ā¤ž ⤏⤂ā¤ĒāĨ‚⤰āĨā¤Ŗ ⤗āĨ…⤞⤰āĨ€ ⤏⤂⤗āĨā¤°ā¤šā¤žā¤šā¤ž ā¤ŦāĨ…⤕⤅ā¤Ē ā¤ĩ ā¤ĩāĨā¤¯ā¤ĩ⤏āĨā¤Ĩā¤žā¤Ē⤍ ⤕⤰⤪āĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€, ⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗āĨā¤œā¤Žā¤§āĨā¤¯āĨ‡ ā¤ĢāĨ‹ā¤ŸāĨ‹ ⤆⤪ā¤ŋ ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓ ā¤Ē⤰ā¤ĩā¤žā¤¨ā¤—āĨā¤¯ā¤ž ā¤ĻāĨā¤¯ā¤ž.", + "permission_onboarding_request": "⤤āĨā¤Žā¤šāĨ‡ ā¤ĢāĨ‹ā¤ŸāĨ‹ ⤆⤪ā¤ŋ ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓ ā¤Ēā¤žā¤šā¤ŖāĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ Immich ā¤˛ā¤ž ā¤Ē⤰ā¤ĩā¤žā¤¨ā¤—āĨ€ ⤆ā¤ĩā¤ļāĨā¤¯ā¤• ā¤†ā¤šāĨ‡.", + "person": "ā¤ĩāĨā¤¯ā¤•āĨā¤¤āĨ€", + "person_age_months": "{months, plural, one {# ā¤Žā¤šā¤ŋā¤¨ā¤ž} other {# ā¤Žā¤šā¤ŋ⤍āĨ‡}} ā¤ĩ⤝", + "person_age_year_months": "1 ā¤ĩ⤰āĨā¤ˇ, {months, plural, one {# ā¤Žā¤šā¤ŋā¤¨ā¤ž} other {# ā¤Žā¤šā¤ŋ⤍āĨ‡}} ā¤ĩ⤝", + "person_age_years": "{years, plural, other {# ā¤ĩ⤰āĨā¤ˇā¤žā¤‚ā¤šāĨ‡}}", + "person_birthdate": "⤜⤍āĨā¤Ž {date} ⤰āĨ‹ā¤œāĨ€", + "person_hidden": "{name}{hidden, select, true { {hidden}} other {}}", + "photo_shared_all_users": "⤤āĨā¤ŽāĨā¤šāĨ€ ⤏⤰āĨā¤ĩ ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤āĨā¤¯ā¤žā¤‚⤏āĨ‹ā¤Ŧ⤤ ā¤ĢāĨ‹ā¤ŸāĨ‹ ā¤ļāĨ‡ā¤…⤰ ⤕āĨ‡ā¤˛āĨ‡ ā¤†ā¤šāĨ‡ā¤¤ ⤅⤏āĨ‡ ā¤Ļā¤ŋ⤏⤤āĨ‡ ⤕ā¤ŋ⤂ā¤ĩā¤ž ā¤ļāĨ‡ā¤…⤰ ⤕⤰⤪āĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ ⤕āĨ‹ā¤Ŗā¤¤ā¤žā¤šāĨ€ ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤ā¤ž ā¤¨ā¤žā¤šāĨ€.", + "photos": "ā¤ĢāĨ‹ā¤ŸāĨ‹", + "photos_and_videos": "ā¤ĢāĨ‹ā¤ŸāĨ‹ ⤆⤪ā¤ŋ ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓", + "photos_count": "{count, plural, one {{count, number} ā¤ĢāĨ‹ā¤ŸāĨ‹} other {{count, number} ā¤ĢāĨ‹ā¤ŸāĨ‹}}", + "photos_from_previous_years": "ā¤Žā¤žā¤—āĨ€ā¤˛ ā¤ĩ⤰āĨā¤ˇā¤žā¤‚⤤āĨ€ā¤˛ ā¤ĢāĨ‹ā¤ŸāĨ‹", + "pick_a_location": "⤏āĨā¤Ĩā¤žā¤¨ ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "pin_code_changed_successfully": "PIN ⤕āĨ‹ā¤Ą ⤝ā¤ļ⤏āĨā¤ĩāĨ€ā¤°ā¤ŋ⤤āĨā¤¯ā¤ž ā¤Ŧā¤Ļā¤˛ā¤˛ā¤ž", + "pin_code_reset_successfully": "PIN ⤕āĨ‹ā¤Ą ⤝ā¤ļ⤏āĨā¤ĩāĨ€ā¤°ā¤ŋ⤤āĨā¤¯ā¤ž ⤰āĨ€ā¤¸āĨ‡ā¤Ÿ ⤕āĨ‡ā¤˛ā¤ž", + "pin_code_setup_successfully": "PIN ⤕āĨ‹ā¤Ą ⤝ā¤ļ⤏āĨā¤ĩāĨ€ā¤°ā¤ŋ⤤āĨā¤¯ā¤ž ⤏āĨ‡ā¤Ÿ ⤕āĨ‡ā¤˛ā¤ž", + "pin_verification": "PIN ⤕āĨ‹ā¤Ą ā¤Ēā¤Ąā¤¤ā¤žā¤ŗā¤ŖāĨ€", + "place": "⤏āĨā¤Ĩā¤žā¤¨", + "places": "⤏āĨā¤Ĩā¤žā¤¨āĨ‡", + "places_count": "{count, plural, one {{count, number} ⤏āĨā¤Ĩā¤žā¤¨} other {{count, number} ⤏āĨā¤Ĩā¤žā¤¨āĨ‡}}", + "play": "ā¤ĒāĨā¤˛āĨ‡ ā¤•ā¤°ā¤ž", + "play_memories": "⤆⤠ā¤ĩ⤪āĨ€ ā¤ĒāĨā¤˛āĨ‡ ā¤•ā¤°ā¤ž", + "play_motion_photo": "ā¤ŽāĨ‹ā¤ļ⤍ ā¤ĢāĨ‹ā¤ŸāĨ‹ ā¤ĒāĨā¤˛āĨ‡ ā¤•ā¤°ā¤ž", + "play_or_pause_video": "ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓ ā¤ĒāĨā¤˛āĨ‡ ⤕ā¤ŋ⤂ā¤ĩā¤ž ā¤ĒāĨ‰ā¤œ ā¤•ā¤°ā¤ž", + "please_auth_to_access": "ā¤ĒāĨā¤°ā¤ĩāĨ‡ā¤ļā¤žā¤¸ā¤žā¤ āĨ€ ⤕āĨƒā¤Ēā¤¯ā¤ž ā¤ĒāĨā¤°ā¤Žā¤žā¤ŖāĨ€ā¤•⤰⤪ ā¤•ā¤°ā¤ž", + "port": "ā¤ĒāĨ‹ā¤°āĨā¤Ÿ", + "preferences_settings_subtitle": "ā¤…â€āĨ…ā¤Ē⤚āĨ€ ā¤ĒāĨā¤°ā¤žā¤§ā¤žā¤¨āĨā¤¯āĨ‡ ā¤ĩāĨā¤¯ā¤ĩ⤏āĨā¤Ĩā¤žā¤Ēā¤ŋ⤤ ā¤•ā¤°ā¤ž", + "preferences_settings_title": "ā¤ĒāĨā¤°ā¤žā¤§ā¤žā¤¨āĨā¤¯āĨ‡", + "preset": "ā¤ĒāĨā¤°ā¤ŋ⤏āĨ‡ā¤Ÿ", + "preview": "ā¤ĒāĨ‚⤰āĨā¤ĩā¤žā¤ĩ⤞āĨ‹ā¤•⤍", + "previous": "ā¤Žā¤žā¤—āĨ€ā¤˛", + "previous_memory": "ā¤Žā¤žā¤—āĨ€ā¤˛ ⤆⤠ā¤ĩ⤪", + "previous_or_next_day": "ā¤Ļā¤ŋā¤ĩ⤏ ā¤ĒāĨā¤ĸāĨ‡/ā¤Žā¤žā¤—āĨ‡", + "previous_or_next_month": "ā¤Žā¤šā¤ŋā¤¨ā¤ž ā¤ĒāĨā¤ĸāĨ‡/ā¤Žā¤žā¤—āĨ‡", + "previous_or_next_photo": "ā¤ĢāĨ‹ā¤ŸāĨ‹ ā¤ĒāĨā¤ĸāĨ‡/ā¤Žā¤žā¤—āĨ‡", + "previous_or_next_year": "ā¤ĩ⤰āĨā¤ˇ ā¤ĒāĨā¤ĸāĨ‡/ā¤Žā¤žā¤—āĨ‡", + "primary": "ā¤ĒāĨā¤°ā¤žā¤Ĩā¤Žā¤ŋ⤕", + "privacy": "⤗āĨ‹ā¤Ē⤍āĨ€ā¤¯ā¤¤ā¤ž", + "profile": "ā¤ĒāĨā¤°āĨ‹ā¤Ģā¤žā¤‡ā¤˛", + "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_github": "⤗ā¤ŋā¤Ÿā¤šā¤Ŧ", + "profile_drawer_readonly_mode": "ā¤Ģ⤕āĨā¤¤-ā¤ĩā¤žā¤šā¤¨ ā¤ŽāĨ‹ā¤Ą ⤏⤕āĨā¤ˇā¤Ž. ā¤Ŧā¤žā¤šāĨ‡ā¤° ā¤Ēā¤Ąā¤ŖāĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤āĨā¤¯ā¤žā¤šāĨā¤¯ā¤ž ⤅ā¤ĩā¤¤ā¤žā¤° ⤆⤝⤕āĨ‰ā¤¨ā¤ĩ⤰ ā¤˛ā¤žā¤‚ā¤Ŧ-ā¤ĒāĨā¤°āĨ‡ā¤¸ ā¤•ā¤°ā¤ž.", + "profile_drawer_server_out_of_date_major": "⤏⤰āĨā¤ĩāĨā¤šā¤° ā¤•ā¤žā¤˛ā¤Ŧā¤žā¤šāĨā¤¯ ā¤†ā¤šāĨ‡. ⤕āĨƒā¤Ēā¤¯ā¤ž ⤍ā¤ĩāĨ€ā¤¨ā¤¤ā¤Ž ā¤ŽāĨ‡ā¤œā¤° ⤆ā¤ĩāĨƒā¤¤āĨā¤¤āĨ€ā¤ĩ⤰ ⤅ā¤ĻāĨā¤¯ā¤¤ā¤¨ ā¤•ā¤°ā¤ž.", + "profile_drawer_server_out_of_date_minor": "⤏⤰āĨā¤ĩāĨā¤šā¤° ā¤•ā¤žā¤˛ā¤Ŧā¤žā¤šāĨā¤¯ ā¤†ā¤šāĨ‡. ⤕āĨƒā¤Ēā¤¯ā¤ž ⤍ā¤ĩāĨ€ā¤¨ā¤¤ā¤Ž ā¤Žā¤žā¤‡ā¤¨ā¤° ⤆ā¤ĩāĨƒā¤¤āĨā¤¤āĨ€ā¤ĩ⤰ ⤅ā¤ĻāĨā¤¯ā¤¤ā¤¨ ā¤•ā¤°ā¤ž.", + "profile_image_of_user": "{user} ⤚āĨ€ ā¤ĒāĨā¤°āĨ‹ā¤Ģā¤žā¤‡ā¤˛ ā¤ĒāĨā¤°ā¤¤ā¤ŋā¤Žā¤ž", + "profile_picture_set": "ā¤ĒāĨā¤°āĨ‹ā¤Ģā¤žā¤‡ā¤˛ ⤚ā¤ŋ⤤āĨā¤° ⤏āĨ‡ā¤Ÿ ⤕āĨ‡ā¤˛āĨ‡.", + "public_album": "ā¤¸ā¤žā¤°āĨā¤ĩ⤜⤍ā¤ŋ⤕ ⤅⤞āĨā¤Ŧā¤Ž", + "public_share": "ā¤¸ā¤žā¤°āĨā¤ĩ⤜⤍ā¤ŋ⤕ ā¤ļāĨ‡ā¤…⤰", + "purchase_account_info": "ā¤¸ā¤Žā¤°āĨā¤Ĩ⤕", + "purchase_activated_subtitle": "Immich ⤆⤪ā¤ŋ ā¤ŽāĨā¤•āĨā¤¤-⤏āĨā¤°āĨ‹ā¤¤ ⤏āĨ‰ā¤ĢāĨā¤Ÿā¤ĩāĨ‡ā¤…ā¤°ā¤˛ā¤ž ā¤Ēā¤žā¤ ā¤ŋ⤂ā¤Ŧā¤ž ā¤Ļā¤ŋ⤞āĨā¤¯ā¤žā¤Ŧā¤ĻāĨā¤Ļ⤞ ⤧⤍āĨā¤¯ā¤ĩā¤žā¤Ļ", + "purchase_activated_time": "{date} ⤰āĨ‹ā¤œāĨ€ ⤏⤕āĨā¤°ā¤ŋ⤝ ⤕āĨ‡ā¤˛āĨ‡", + "purchase_activated_title": "⤤āĨā¤Žā¤šāĨ€ ⤕āĨ€ ⤝ā¤ļ⤏āĨā¤ĩāĨ€ā¤Ē⤪āĨ‡ ⤏⤕āĨā¤°ā¤ŋ⤝ ⤕⤰⤪āĨā¤¯ā¤žā¤¤ ⤆⤞āĨ€ ā¤†ā¤šāĨ‡", + "purchase_button_activate": "⤏⤕āĨā¤°ā¤ŋ⤝ ā¤•ā¤°ā¤ž", + "purchase_button_buy": "⤖⤰āĨ‡ā¤ĻāĨ€ ā¤•ā¤°ā¤ž", + "purchase_button_buy_immich": "Immich ⤖⤰āĨ‡ā¤ĻāĨ€ ā¤•ā¤°ā¤ž", + "purchase_button_never_show_again": "ā¤ĒāĨā¤¨āĨā¤šā¤ž ā¤Ļā¤žā¤–ā¤ĩāĨ‚ ā¤¨ā¤•ā¤ž", + "purchase_button_reminder": "āĨŠāĨĻ ā¤Ļā¤ŋā¤ĩā¤¸ā¤žā¤‚ā¤¨āĨ€ ā¤Žā¤˛ā¤ž ⤆⤠ā¤ĩ⤪ ⤕⤰āĨ‚⤍ ā¤ĻāĨā¤¯ā¤ž", + "purchase_button_remove_key": "⤕āĨ€ ā¤šā¤Ÿā¤ĩā¤ž", + "purchase_button_select": "⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "purchase_failed_activation": "⤏⤕āĨā¤°ā¤ŋ⤝ ⤕⤰⤪āĨā¤¯ā¤žā¤¤ ⤅⤝ā¤ļ⤏āĨā¤ĩāĨ€! ⤝āĨ‹ā¤—āĨā¤¯ ā¤ĒāĨā¤°āĨ‹ā¤Ąā¤•āĨā¤Ÿ ⤕āĨ€ā¤¸ā¤žā¤ āĨ€ ⤕āĨƒā¤Ēā¤¯ā¤ž ⤤āĨā¤Žā¤šāĨ‡ ā¤ˆā¤ŽāĨ‡ā¤˛ ⤤ā¤Ēā¤žā¤¸ā¤ž!", + "purchase_individual_description_1": "ā¤ĩāĨˆā¤¯ā¤•āĨā¤¤ā¤ŋ⤕ ā¤ĩā¤žā¤Ēā¤°ā¤žā¤¸ā¤žā¤ āĨ€", + "purchase_individual_description_2": "ā¤¸ā¤Žā¤°āĨā¤Ĩ⤕ ⤏āĨā¤Ĩā¤ŋ⤤āĨ€", + "purchase_individual_title": "ā¤ĩāĨˆā¤¯ā¤•āĨā¤¤ā¤ŋ⤕", + "purchase_input_suggestion": "ā¤ĒāĨā¤°āĨ‰ā¤Ąā¤•āĨā¤Ÿ ⤕āĨ€ ā¤†ā¤šāĨ‡? ā¤–ā¤žā¤˛āĨ€ ⤕āĨ€ ā¤Ÿā¤žā¤•ā¤ž", + "purchase_license_subtitle": "⤏āĨ‡ā¤ĩāĨ‡ā¤šāĨā¤¯ā¤ž ā¤ĒāĨā¤ĸāĨ€ā¤˛ ā¤ĩā¤ŋā¤•ā¤žā¤¸ā¤žā¤¸ā¤žā¤ āĨ€ Immich ⤖⤰āĨ‡ā¤ĻāĨ€ ⤕⤰āĨ‚⤍ ā¤¸ā¤žā¤Ĩ ā¤ĻāĨā¤¯ā¤ž", + "purchase_lifetime_description": "⤆⤝āĨā¤ˇāĨā¤¯ā¤­ā¤°ā¤žā¤šāĨ€ ⤖⤰āĨ‡ā¤ĻāĨ€", + "purchase_option_title": "⤖⤰āĨ‡ā¤ĻāĨ€ ā¤Ē⤰āĨā¤¯ā¤žā¤¯", + "purchase_panel_info_1": "Immich ā¤¤ā¤¯ā¤žā¤° ⤕⤰⤪āĨ‡ ā¤ĩāĨ‡ā¤ŗā¤–ā¤žā¤Š ⤆⤪ā¤ŋ ⤕⤎āĨā¤Ÿā¤žā¤šāĨ‡ ā¤†ā¤šāĨ‡. ā¤†ā¤Žā¤šāĨ‡ ⤧āĨā¤¯āĨ‡ā¤¯ ā¤ŽāĨā¤•āĨā¤¤-⤏āĨā¤°āĨ‹ā¤¤ ⤏āĨ‰ā¤ĢāĨā¤Ÿā¤ĩāĨ‡ā¤…⤰ ā¤ĩ ⤍āĨˆā¤¤ā¤ŋ⤕ ā¤ĩāĨā¤¯ā¤žā¤ĩā¤¸ā¤žā¤¯ā¤ŋ⤕ ā¤Ēā¤ĻāĨā¤§ā¤¤āĨ€ā¤‚ā¤Žā¤§āĨ‚⤍ ⤟ā¤ŋā¤•ā¤žā¤Š ⤉⤤āĨā¤Ē⤍āĨā¤¨ ā¤Žā¤ŋ⤺ā¤ĩ⤪āĨ‡, ā¤ĩā¤ŋā¤•ā¤¸ā¤•ā¤žā¤‚ā¤¨ā¤ž ā¤†ā¤§ā¤žā¤° ā¤ĻāĨ‡ā¤ŖāĨ‡ ⤆⤪ā¤ŋ ā¤ļāĨ‹ā¤ˇā¤Ŗā¤•ā¤žā¤°āĨ€ ⤕āĨā¤˛ā¤žā¤‰ā¤Ą ⤏āĨ‡ā¤ĩā¤žā¤‚ā¤¨ā¤ž ā¤Ē⤰āĨā¤¯ā¤žā¤¯ ā¤ĻāĨ‡ā¤Ŗā¤žā¤°āĨ‡ ⤗āĨ‹ā¤Ē⤍āĨ€ā¤¯ā¤¤āĨ‡ā¤šā¤ž ā¤Žā¤žā¤¨ ā¤°ā¤žā¤–ā¤Ŗā¤žā¤°āĨ‡ ⤇⤕āĨ‹ā¤¸ā¤ŋ⤏āĨā¤Ÿā¤Ž ā¤¤ā¤¯ā¤žā¤° ⤕⤰⤪āĨ‡ ā¤šāĨ‡ ā¤†ā¤šāĨ‡.", + "purchase_panel_info_2": "ā¤†ā¤ŽāĨā¤šāĨ€ ā¤ĒāĨ‡ā¤ĩāĨ‰ā¤˛ ⤍ ā¤ĩā¤žā¤ĸā¤ĩ⤪āĨā¤¯ā¤žā¤¸ ā¤•ā¤Ÿā¤ŋā¤Ŧā¤ĻāĨā¤§ ā¤†ā¤šāĨ‹ā¤¤; ⤤āĨā¤¯ā¤žā¤ŽāĨā¤ŗāĨ‡ ā¤¯ā¤ž ⤖⤰āĨ‡ā¤ĻāĨ€ā¤ŽāĨā¤ŗāĨ‡ Immich ā¤Žā¤§āĨā¤¯āĨ‡ ⤕āĨ‹ā¤Ŗā¤¤āĨ€ā¤šāĨ€ ⤅⤤ā¤ŋ⤰ā¤ŋ⤕āĨā¤¤ ā¤ĩāĨˆā¤ļā¤ŋ⤎āĨā¤ŸāĨā¤¯āĨ‡ ā¤‰ā¤˜ā¤Ąā¤Ŗā¤žā¤° ā¤¨ā¤žā¤šāĨ€ā¤¤. ā¤šā¤žā¤˛āĨ‚ ā¤ĩā¤ŋā¤•ā¤žā¤¸ā¤žā¤¸ā¤žā¤ āĨ€ ā¤†ā¤ŽāĨā¤šāĨ€ ⤤āĨā¤Žā¤šāĨā¤¯ā¤žā¤¸ā¤žā¤°ā¤–āĨā¤¯ā¤ž ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤āĨā¤¯ā¤žā¤‚ā¤šāĨā¤¯ā¤ž ā¤Ēā¤žā¤ ā¤Ŧā¤ŗā¤žā¤ĩ⤰ ⤅ā¤ĩ⤞⤂ā¤ŦāĨ‚⤍ ā¤†ā¤šāĨ‹ā¤¤.", + "purchase_panel_title": "ā¤ĒāĨā¤°ā¤•⤞āĨā¤Ēā¤žā¤˛ā¤ž ā¤¸ā¤žā¤Ĩ ā¤ĻāĨā¤¯ā¤ž", + "purchase_per_server": "ā¤ĒāĨā¤°ā¤¤ā¤ŋ ⤏⤰āĨā¤ĩāĨā¤šā¤°", + "purchase_per_user": "ā¤ĒāĨā¤°ā¤¤ā¤ŋ ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤ā¤ž", + "purchase_remove_product_key": "ā¤ĒāĨā¤°āĨ‰ā¤Ąā¤•āĨā¤Ÿ ⤕āĨ€ ā¤•ā¤žā¤ĸā¤ž", + "purchase_remove_product_key_prompt": "⤤āĨā¤ŽāĨā¤šā¤žā¤˛ā¤ž ⤍⤕āĨā¤•āĨ€ ā¤ĒāĨā¤°āĨ‰ā¤Ąā¤•āĨā¤Ÿ ⤕āĨ€ ā¤•ā¤žā¤ĸā¤žā¤¯ā¤šāĨ€ ā¤†ā¤šāĨ‡ ā¤•ā¤ž?", + "purchase_remove_server_product_key": "⤏⤰āĨā¤ĩāĨā¤šā¤°ā¤šāĨ€ ā¤ĒāĨā¤°āĨ‰ā¤Ąā¤•āĨā¤Ÿ ⤕āĨ€ ā¤•ā¤žā¤ĸā¤ž", + "purchase_remove_server_product_key_prompt": "⤤āĨā¤ŽāĨā¤šā¤žā¤˛ā¤ž ⤍⤕āĨā¤•āĨ€ ⤏⤰āĨā¤ĩāĨā¤šā¤°ā¤šāĨ€ ā¤ĒāĨā¤°āĨ‰ā¤Ąā¤•āĨā¤Ÿ ⤕āĨ€ ā¤•ā¤žā¤ĸā¤žā¤¯ā¤šāĨ€ ā¤†ā¤šāĨ‡ ā¤•ā¤ž?", + "purchase_server_description_1": "⤏⤂ā¤ĒāĨ‚⤰āĨā¤Ŗ ⤏⤰āĨā¤ĩāĨā¤šā¤°ā¤¸ā¤žā¤ āĨ€", + "purchase_server_description_2": "ā¤¸ā¤Žā¤°āĨā¤Ĩ⤕ ⤏āĨā¤Ĩā¤ŋ⤤āĨ€", + "purchase_server_title": "⤏⤰āĨā¤ĩāĨā¤šā¤°", + "purchase_settings_server_activated": "⤏⤰āĨā¤ĩāĨā¤šā¤°ā¤šāĨ€ ā¤ĒāĨā¤°āĨ‰ā¤Ąā¤•āĨā¤Ÿ ⤕āĨ€ ā¤ĒāĨā¤°ā¤ļā¤žā¤¸ā¤•ā¤žā¤ĻāĨā¤ĩā¤žā¤°āĨ‡ ā¤ĩāĨā¤¯ā¤ĩ⤏āĨā¤Ĩā¤žā¤Ēā¤ŋ⤤ ⤕āĨ‡ā¤˛āĨ€ ā¤œā¤žā¤¤āĨ‡", + "query_asset_id": "⤅āĨ…⤏āĨ‡ā¤Ÿ ID ⤚āĨŒā¤•ā¤ļāĨ€", + "queue_status": "ā¤°ā¤žā¤‚ā¤—āĨ‡ā¤¤ {count}/{total}", + "rating": "⤏āĨā¤Ÿā¤žā¤° ⤰āĨ‡ā¤Ÿā¤ŋ⤂⤗", + "rating_clear": "⤰āĨ‡ā¤Ÿā¤ŋ⤂⤗ ā¤¸ā¤žā¤Ģ ā¤•ā¤°ā¤ž", + "rating_count": "{count, plural, one {# ā¤¤ā¤žā¤°ā¤ž} other {# ā¤¤ā¤žā¤°āĨ‡}}", + "rating_description": "ā¤Žā¤žā¤šā¤ŋ⤤āĨ€ ā¤ĒāĨ…⤍āĨ‡ā¤˛ā¤Žā¤§āĨā¤¯āĨ‡ EXIF ⤰āĨ‡ā¤Ÿā¤ŋ⤂⤗ ā¤Ļ⤰āĨā¤ļā¤ĩā¤ž", + "reaction_options": "⤰ā¤ŋā¤ā¤•āĨā¤ļ⤍ ā¤Ē⤰āĨā¤¯ā¤žā¤¯", + "read_changelog": "⤚āĨ‡ā¤‚ā¤œā¤˛āĨ‰ā¤— ā¤ĩā¤žā¤šā¤ž", + "readonly_mode_disabled": "ā¤Ģ⤕āĨā¤¤-ā¤ĩā¤žā¤šā¤¨ ā¤ŽāĨ‹ā¤Ą ⤍ā¤ŋ⤎āĨā¤•āĨā¤°ā¤ŋ⤝ ⤕āĨ‡ā¤˛ā¤ž", + "readonly_mode_enabled": "ā¤Ģ⤕āĨā¤¤-ā¤ĩā¤žā¤šā¤¨ ā¤ŽāĨ‹ā¤Ą ⤏⤕āĨā¤ˇā¤Ž ⤕āĨ‡ā¤˛ā¤ž", + "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": "⤍ā¤ŋā¤ĩā¤Ąā¤˛āĨ‡ā¤˛āĨ‡ ā¤†ā¤¯ā¤Ÿā¤Ž ā¤ĩā¤ŋā¤ĻāĨā¤¯ā¤Žā¤žā¤¨ ā¤ĩāĨā¤¯ā¤•āĨā¤¤āĨ€ā¤•ā¤ĄāĨ‡ ⤍ā¤ŋ⤝āĨā¤•āĨā¤¤ ā¤•ā¤°ā¤ž", + "recent": "⤅⤞āĨ€ā¤•ā¤ĄāĨ€ā¤˛", + "recent-albums": "⤅⤞āĨ€ā¤•ā¤ĄāĨ€ā¤˛ ⤅⤞āĨā¤Ŧā¤Ž", + "recent_searches": "⤅⤞āĨ€ā¤•ā¤ĄāĨ€ā¤˛ ā¤ļāĨ‹ā¤§", + "recently_added": "⤍āĨā¤•⤤āĨ‡ā¤š ⤜āĨ‹ā¤Ąā¤˛āĨ‡ā¤˛āĨ‡", + "recently_added_page_title": "⤍āĨā¤•⤤āĨ‡ā¤š ⤜āĨ‹ā¤Ąā¤˛āĨ‡ā¤˛āĨ‡", + "recently_taken": "⤅⤞āĨ€ā¤•ā¤ĄāĨ‡ ⤘āĨ‡ā¤¤ā¤˛āĨ‡ā¤˛āĨ‡", + "recently_taken_page_title": "⤅⤞āĨ€ā¤•ā¤ĄāĨ‡ ⤘āĨ‡ā¤¤ā¤˛āĨ‡ā¤˛āĨ‡", + "refresh": "⤰āĨ€ā¤ĢāĨā¤°āĨ‡ā¤ļ ā¤•ā¤°ā¤ž", + "refresh_encoded_videos": "ā¤ā¤¨āĨā¤•āĨ‹ā¤Ą ⤕āĨ‡ā¤˛āĨ‡ā¤˛āĨ‡ ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓ ⤰āĨ€ā¤ĢāĨā¤°āĨ‡ā¤ļ ā¤•ā¤°ā¤ž", + "refresh_faces": "⤚āĨ‡ā¤šā¤°āĨ‡ ⤰āĨ€ā¤ĢāĨā¤°āĨ‡ā¤ļ ā¤•ā¤°ā¤ž", + "refresh_metadata": "ā¤ŽāĨ‡ā¤Ÿā¤žā¤ĄāĨ‡ā¤Ÿā¤ž ⤰āĨ€ā¤ĢāĨā¤°āĨ‡ā¤ļ ā¤•ā¤°ā¤ž", + "refresh_thumbnails": "ā¤Ĩ⤂ā¤Ŧ⤍āĨ‡ā¤˛ ⤰āĨ€ā¤ĢāĨā¤°āĨ‡ā¤ļ ā¤•ā¤°ā¤ž", + "refreshed": "⤰āĨ€ā¤ĢāĨā¤°āĨ‡ā¤ļ ā¤ā¤žā¤˛āĨ‡", + "refreshes_every_file": "ā¤ĩā¤ŋā¤ĻāĨā¤¯ā¤Žā¤žā¤¨ ā¤ĩ ⤍ā¤ĩāĨ€ā¤¨ ⤏⤰āĨā¤ĩ ā¤Ģā¤žā¤‡ā¤˛āĨā¤¸ ā¤ĒāĨā¤¨āĨā¤šā¤ž ā¤ĩā¤žā¤šā¤ž", + "refreshing_encoded_video": "ā¤ā¤¨āĨā¤•āĨ‹ā¤Ą ⤕āĨ‡ā¤˛āĨ‡ā¤˛ā¤ž ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓ ⤰āĨ€ā¤ĢāĨā¤°āĨ‡ā¤ļ ⤕⤰⤤ ā¤†ā¤šāĨ‡", + "refreshing_faces": "⤚āĨ‡ā¤šā¤°āĨ‡ ⤰āĨ€ā¤ĢāĨā¤°āĨ‡ā¤ļ ⤕⤰⤤ ā¤†ā¤šāĨ‡", + "refreshing_metadata": "ā¤ŽāĨ‡ā¤Ÿā¤žā¤ĄāĨ‡ā¤Ÿā¤ž ⤰āĨ€ā¤ĢāĨā¤°āĨ‡ā¤ļ ⤕⤰⤤ ā¤†ā¤šāĨ‡", + "regenerating_thumbnails": "ā¤Ĩ⤂ā¤Ŧ⤍āĨ‡ā¤˛āĨā¤¸ ā¤ĒāĨā¤¨āĨā¤šā¤ž ā¤¤ā¤¯ā¤žā¤° ⤕⤰⤤ ā¤†ā¤šāĨ‡", + "remote": "ā¤ĻāĨ‚⤰⤏āĨā¤Ĩ", + "remote_assets": "ā¤ĻāĨ‚⤰⤏āĨā¤Ĩ ā¤†ā¤¯ā¤Ÿā¤Ž", + "remove": "ā¤•ā¤žā¤ĸā¤ž", + "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": "⤅⤞āĨā¤Ŧā¤Žā¤Žā¤§āĨ‚⤍ ā¤•ā¤žā¤ĸā¤ž", + "remove_from_album_action_prompt": "⤅⤞āĨā¤Ŧā¤Žā¤Žā¤§āĨ‚⤍ {count} ā¤•ā¤žā¤ĸ⤞āĨ‡", + "remove_from_favorites": "⤆ā¤ĩā¤ĄāĨ€ā¤¤āĨ‚⤍ ā¤•ā¤žā¤ĸā¤ž", + "remove_from_lock_folder_action_prompt": "⤞āĨ‰ā¤• ⤕āĨ‡ā¤˛āĨ‡ā¤˛āĨā¤¯ā¤ž ā¤ĢāĨ‹ā¤˛āĨā¤Ąā¤°ā¤Žā¤§āĨ‚⤍ {count} ā¤•ā¤žā¤ĸ⤞āĨ‡", + "remove_from_locked_folder": "⤞āĨ‰ā¤• ā¤ĢāĨ‹ā¤˛āĨā¤Ąā¤°ā¤Žā¤§āĨ‚⤍ ā¤•ā¤žā¤ĸā¤ž", + "remove_from_locked_folder_confirmation": "ā¤šāĨ‡ ā¤ĢāĨ‹ā¤ŸāĨ‹ ⤆⤪ā¤ŋ ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓ ⤞āĨ‰ā¤• ā¤ĢāĨ‹ā¤˛āĨā¤Ąā¤°ā¤Žā¤§āĨ‚⤍ ā¤Ŧā¤žā¤šāĨ‡ā¤° ā¤šā¤˛ā¤ĩā¤žā¤¯ā¤šāĨ‡ ā¤†ā¤šāĨ‡ā¤¤ ā¤•ā¤ž? ⤤āĨ‡ ⤤āĨā¤Žā¤šāĨā¤¯ā¤ž ā¤˛ā¤žā¤¯ā¤ŦāĨā¤°ā¤°āĨ€ā¤Žā¤§āĨā¤¯āĨ‡ ā¤Ļā¤ŋ⤏⤤āĨ€ā¤˛.", + "remove_from_shared_link": "ā¤ļāĨ‡ā¤…⤰āĨā¤Ą ā¤ĻāĨā¤ĩāĨā¤¯ā¤žā¤¤āĨ‚⤍ ā¤•ā¤žā¤ĸā¤ž", + "remove_memory": "ā¤ŽāĨ‡ā¤Žā¤°āĨ€ ā¤•ā¤žā¤ĸā¤ž", + "remove_photo_from_memory": "ā¤¯ā¤ž ā¤ŽāĨ‡ā¤Žā¤°āĨ€ā¤¤āĨ‚⤍ ā¤ĢāĨ‹ā¤ŸāĨ‹ ā¤•ā¤žā¤ĸā¤ž", + "remove_tag": "⤟āĨ…⤗ ā¤•ā¤žā¤ĸā¤ž", + "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_tagged_assets": "{count, plural, one {# ā¤†ā¤¯ā¤Ÿā¤Žā¤ĩ⤰āĨ‚⤍ ⤟āĨ…⤗ ā¤•ā¤žā¤ĸā¤˛ā¤ž} other {# ā¤†ā¤¯ā¤Ÿā¤Žā¤ĩ⤰āĨ‚⤍ ⤟āĨ…⤗ ā¤•ā¤žā¤ĸ⤞āĨ‡}}", + "rename": "ā¤¨ā¤žā¤ĩ ā¤Ŧā¤Ļā¤˛ā¤ž", + "repair": "ā¤ĻāĨā¤°āĨā¤¸āĨā¤¤āĨ€", + "repair_no_results_message": "ā¤…ā¤¨ā¤ŸāĨā¤°āĨ…⤕āĨā¤Ą ā¤ĩ ā¤šā¤°ā¤ĩ⤞āĨ‡ā¤˛āĨā¤¯ā¤ž ā¤Ģā¤žā¤‡ā¤˛āĨā¤¸ ⤝āĨ‡ā¤ĨāĨ‡ ā¤Ļā¤ŋ⤏⤤āĨ€ā¤˛", + "replace_with_upload": "⤅ā¤Ē⤞āĨ‹ā¤Ąā¤¨āĨ‡ ā¤Ŧā¤Ļā¤˛ā¤ž", + "repository": "⤰ā¤ŋā¤ĒāĨ‰ā¤ā¤ŋ⤟⤰āĨ€", + "require_password": "ā¤Ēā¤žā¤¸ā¤ĩ⤰āĨā¤Ą ⤆ā¤ĩā¤ļāĨā¤¯ā¤•", + "require_user_to_change_password_on_first_login": "ā¤Ēā¤šā¤ŋ⤞āĨā¤¯ā¤ž ⤞āĨ‰ā¤—ā¤ŋ⤍ā¤ĩāĨ‡ā¤ŗāĨ€ ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤āĨā¤¯ā¤žā¤¨āĨ‡ ā¤Ēā¤žā¤¸ā¤ĩ⤰āĨā¤Ą ā¤Ŧā¤Ļ⤞⤪āĨ‡ ⤆ā¤ĩā¤ļāĨā¤¯ā¤•", + "rescan": "ā¤ĒāĨā¤¨āĨā¤šā¤ž ⤏āĨā¤•āĨ…⤍ ā¤•ā¤°ā¤ž", + "reset": "⤰āĨ€ā¤¸āĨ‡ā¤Ÿ ā¤•ā¤°ā¤ž", + "reset_password": "ā¤Ēā¤žā¤¸ā¤ĩ⤰āĨā¤Ą ⤰āĨ€ā¤¸āĨ‡ā¤Ÿ ā¤•ā¤°ā¤ž", + "reset_people_visibility": "⤞āĨ‹ā¤•ā¤žā¤‚ā¤šāĨ€ ā¤ĻāĨƒā¤ļāĨā¤¯ā¤¤ā¤ž ⤰āĨ€ā¤¸āĨ‡ā¤Ÿ ā¤•ā¤°ā¤ž", + "reset_pin_code": "PIN ⤕āĨ‹ā¤Ą ⤰āĨ€ā¤¸āĨ‡ā¤Ÿ ā¤•ā¤°ā¤ž", + "reset_pin_code_description": "⤤āĨā¤Žā¤šā¤ž PIN ā¤ĩā¤ŋā¤¸ā¤°ā¤˛ā¤ž ⤅⤏⤞āĨā¤¯ā¤žā¤¸, ⤤āĨ‹ ⤰āĨ€ā¤¸āĨ‡ā¤Ÿ ⤕⤰⤪āĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ ⤏⤰āĨā¤ĩāĨā¤šā¤° ā¤ĒāĨā¤°ā¤ļā¤žā¤¸ā¤•ā¤žā¤ļāĨ€ ⤏⤂ā¤Ē⤰āĨā¤• ā¤¸ā¤žā¤§ā¤ž", + "reset_pin_code_success": "PIN ⤕āĨ‹ā¤Ą ⤝ā¤ļ⤏āĨā¤ĩāĨ€ā¤°āĨ€ā¤¤āĨā¤¯ā¤ž ⤰āĨ€ā¤¸āĨ‡ā¤Ÿ ⤕āĨ‡ā¤˛ā¤ž", + "reset_pin_code_with_password": "ā¤Ēā¤žā¤¸ā¤ĩ⤰āĨā¤Ąā¤¨āĨ‡ ⤤āĨā¤ŽāĨā¤šāĨ€ ⤍āĨ‡ā¤šā¤ŽāĨ€ PIN ⤕āĨ‹ā¤Ą ⤰āĨ€ā¤¸āĨ‡ā¤Ÿ ⤕⤰āĨ‚ ā¤ļā¤•ā¤¤ā¤ž", + "reset_sqlite": "SQLite ā¤ĄāĨ‡ā¤Ÿā¤žā¤ŦāĨ‡ā¤¸ ⤰āĨ€ā¤¸āĨ‡ā¤Ÿ ā¤•ā¤°ā¤ž", + "reset_sqlite_confirmation": "⤤āĨā¤ŽāĨā¤šā¤žā¤˛ā¤ž ⤍⤕āĨā¤•āĨ€ SQLite ā¤ĄāĨ‡ā¤Ÿā¤žā¤ŦāĨ‡ā¤¸ ⤰āĨ€ā¤¸āĨ‡ā¤Ÿ ā¤•ā¤°ā¤žā¤¯ā¤šā¤ž ā¤†ā¤šāĨ‡ ā¤•ā¤ž? ā¤ĄāĨ‡ā¤Ÿā¤ž ā¤ĒāĨā¤¨āĨā¤šā¤ž ā¤¸ā¤Žā¤•āĨā¤°ā¤Žā¤ŋ⤤ ⤕⤰⤪āĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ ⤤āĨā¤ŽāĨā¤šā¤žā¤˛ā¤ž ⤞āĨ‰ā¤—ā¤†ā¤‰ā¤Ÿ ⤕⤰āĨ‚⤍ ā¤ĒāĨā¤¨āĨā¤šā¤ž ⤞āĨ‰ā¤—⤇⤍ ā¤•ā¤°ā¤žā¤ĩāĨ‡ ā¤˛ā¤žā¤—āĨ‡ā¤˛", + "reset_sqlite_success": "SQLite ā¤ĄāĨ‡ā¤Ÿā¤žā¤ŦāĨ‡ā¤¸ ⤝ā¤ļ⤏āĨā¤ĩāĨ€ā¤°āĨ€ā¤¤āĨā¤¯ā¤ž ⤰āĨ€ā¤¸āĨ‡ā¤Ÿ ⤕āĨ‡ā¤˛ā¤ž", + "reset_to_default": "ā¤ĄāĨ€ā¤ĢāĨ‰ā¤˛āĨā¤Ÿā¤ĩ⤰ ⤰āĨ€ā¤¸āĨ‡ā¤Ÿ ā¤•ā¤°ā¤ž", + "resolve_duplicates": "ā¤ĄāĨā¤ĒāĨā¤˛ā¤ŋ⤕āĨ‡ā¤ŸāĨā¤¸ ⤏āĨ‹ā¤Ąā¤ĩā¤ž", + "resolved_all_duplicates": "⤏⤰āĨā¤ĩ ā¤ĄāĨā¤ĒāĨā¤˛ā¤ŋ⤕āĨ‡ā¤ŸāĨā¤¸ ⤏āĨ‹ā¤Ąā¤ĩ⤞āĨ‡", + "restore": "ā¤ĒāĨā¤¨ā¤°āĨā¤¸ā¤‚ā¤šā¤¯ā¤ŋ⤤ ā¤•ā¤°ā¤ž", + "restore_all": "⤏⤰āĨā¤ĩ ā¤ĒāĨā¤¨ā¤°āĨā¤¸ā¤‚ā¤šā¤¯ā¤ŋ⤤ ā¤•ā¤°ā¤ž", + "restore_trash_action_prompt": "ā¤•ā¤šā¤°ā¤žā¤ĒāĨ‡ā¤ŸāĨ€ā¤¤āĨ‚⤍ {count} ā¤ĒāĨā¤¨ā¤°āĨā¤¸ā¤‚ā¤šā¤¯ā¤ŋ⤤ ⤕āĨ‡ā¤˛āĨ‡", + "restore_user": "ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤ā¤ž ā¤ĒāĨā¤¨ā¤°āĨā¤¸ā¤‚ā¤šā¤¯ā¤ŋ⤤ ā¤•ā¤°ā¤ž", + "restored_asset": "ā¤ĒāĨā¤¨ā¤°āĨā¤¸ā¤‚ā¤šā¤¯ā¤ŋ⤤ ā¤†ā¤¯ā¤Ÿā¤Ž", + "resume": "ā¤ĒāĨā¤¨āĨā¤šā¤ž ⤏āĨā¤°āĨ‚ ā¤•ā¤°ā¤ž", + "resume_paused_jobs": "{count, plural, one {# ā¤Ĩā¤žā¤‚ā¤Ŧā¤ĩ⤞āĨ‡ā¤˛āĨ‡ ā¤•ā¤žā¤Ž} other {# ā¤Ĩā¤žā¤‚ā¤Ŧā¤ĩ⤞āĨ‡ā¤˛āĨ€ ā¤•ā¤žā¤ŽāĨ‡}} ā¤ĒāĨā¤¨āĨā¤šā¤ž ⤏āĨā¤°āĨ‚ ā¤•ā¤°ā¤ž", + "retry_upload": "⤅ā¤Ē⤞āĨ‹ā¤Ą ā¤ĒāĨā¤¨āĨā¤šā¤ž ā¤•ā¤°ā¤ž", + "review_duplicates": "ā¤ĄāĨā¤ĒāĨā¤˛ā¤ŋ⤕āĨ‡ā¤ŸāĨā¤¸ā¤šāĨ‡ ā¤ĒāĨā¤¨ā¤°ā¤žā¤ĩ⤞āĨ‹ā¤•⤍ ā¤•ā¤°ā¤ž", + "review_large_files": "ā¤ŽāĨ‹ā¤ āĨā¤¯ā¤ž ā¤Ģā¤žā¤‡ā¤˛āĨā¤¸ā¤šāĨ‡ ā¤ĒāĨā¤¨ā¤°ā¤žā¤ĩ⤞āĨ‹ā¤•⤍ ā¤•ā¤°ā¤ž", + "role": "⤭āĨ‚ā¤Žā¤ŋā¤•ā¤ž", + "role_editor": "⤏⤂ā¤Ēā¤žā¤Ļ⤕", + "role_viewer": "ā¤Ļ⤰āĨā¤ļ⤕", + "running": "ā¤šā¤žā¤˛āĨ‚", + "save": "⤜⤤⤍ ā¤•ā¤°ā¤ž", + "save_to_gallery": "⤗āĨ…⤞⤰āĨ€ā¤Žā¤§āĨā¤¯āĨ‡ ⤜⤤⤍ ā¤•ā¤°ā¤ž", + "saved_api_key": "⤜⤤⤍ ⤕āĨ‡ā¤˛āĨ‡ā¤˛āĨ€ API ⤕āĨ€", + "saved_profile": "⤜⤤⤍ ⤕āĨ‡ā¤˛āĨ‡ā¤˛āĨ‡ ā¤ĒāĨā¤°āĨ‹ā¤Ģā¤žā¤‡ā¤˛", + "saved_settings": "⤜⤤⤍ ⤕āĨ‡ā¤˛āĨ‡ā¤˛āĨā¤¯ā¤ž ⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗āĨā¤œ", + "say_something": "ā¤•ā¤žā¤šāĨ€ā¤¤ā¤°āĨ€ ā¤ŦāĨ‹ā¤˛ā¤ž", + "scaffold_body_error_occurred": "⤤āĨā¤°āĨā¤ŸāĨ€ ⤆⤞āĨ€", + "scan_all_libraries": "⤏⤰āĨā¤ĩ ā¤˛ā¤žā¤¯ā¤ŦāĨā¤°ā¤°āĨ€ ⤏āĨā¤•āĨ…⤍ ā¤•ā¤°ā¤ž", + "scan_library": "⤏āĨā¤•āĨ…⤍ ā¤•ā¤°ā¤ž", + "scan_settings": "⤏āĨā¤•āĨ…⤍ ⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗āĨā¤œ", + "scanning_for_album": "⤅⤞āĨā¤Ŧā¤Žā¤¸ā¤žā¤ āĨ€ ⤏āĨā¤•āĨ…⤍ ⤕⤰⤤ ā¤†ā¤šāĨ‡...", + "search": "ā¤ļāĨ‹ā¤§ā¤ž", + "search_albums": "⤅⤞āĨā¤Ŧā¤Ž ā¤ļāĨ‹ā¤§ā¤ž", + "search_by_context": "ā¤Ē⤰ā¤ŋ⤏āĨā¤Ĩā¤ŋ⤤āĨ€ā¤¨āĨā¤¸ā¤žā¤° ā¤ļāĨ‹ā¤§ā¤ž", + "search_by_description": "ā¤ĩ⤰āĨā¤Ŗā¤¨ā¤žā¤¨āĨā¤¸ā¤žā¤° ā¤ļāĨ‹ā¤§ā¤ž", + "search_by_description_example": "ā¤¸ā¤žā¤Ēā¤ž ā¤Žā¤§āĨ€ā¤˛ ā¤šā¤žā¤¯ā¤•ā¤ŋā¤‚ā¤—ā¤šā¤ž ā¤Ļā¤ŋā¤ĩ⤏", + "search_by_filename": "ā¤Ģā¤žā¤‡ā¤˛ ā¤¨ā¤žā¤ĩ/ā¤ā¤•āĨā¤¸āĨā¤ŸāĨ‡ā¤‚ā¤ļ⤍⤍āĨā¤¸ā¤žā¤° ā¤ļāĨ‹ā¤§ā¤ž", + "search_by_filename_example": "⤉ā¤Ļā¤ž. IMG_1234.JPG ⤕ā¤ŋ⤂ā¤ĩā¤ž PNG", + "search_camera_make": "⤕āĨ…ā¤ŽāĨ‡ā¤°ā¤ž ⤍ā¤ŋ⤰āĨā¤Žā¤žā¤¤ā¤ž ā¤ļāĨ‹ā¤§ā¤ž...", + "search_camera_model": "⤕āĨ…ā¤ŽāĨ‡ā¤°ā¤ž ā¤ŽāĨ‰ā¤ĄāĨ‡ā¤˛ ā¤ļāĨ‹ā¤§ā¤ž...", + "search_city": "ā¤ļā¤šā¤° ā¤ļāĨ‹ā¤§ā¤ž...", + "search_country": "ā¤ĻāĨ‡ā¤ļ ā¤ļāĨ‹ā¤§ā¤ž...", + "search_filter_apply": "ā¤Ģā¤ŋ⤞āĨā¤Ÿā¤° ā¤˛ā¤žā¤—āĨ‚ ā¤•ā¤°ā¤ž", + "search_filter_camera_title": "⤕āĨ…ā¤ŽāĨ‡ā¤°ā¤ž ā¤ĒāĨā¤°ā¤•ā¤žā¤° ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "search_filter_date": "ā¤¤ā¤žā¤°āĨ€ā¤–", + "search_filter_date_interval": "{start} ⤤āĨ‡ {end}", + "search_filter_date_title": "ā¤Ļā¤ŋā¤¨ā¤žā¤‚ā¤• ā¤ļāĨā¤°āĨ‡ā¤ŖāĨ€ ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "search_filter_display_option_not_in_album": "⤅⤞āĨā¤Ŧā¤Žā¤Žā¤§āĨā¤¯āĨ‡ ā¤¨ā¤žā¤šāĨ€", + "search_filter_display_options": "ā¤ĒāĨā¤°ā¤Ļ⤰āĨā¤ļ⤍ ā¤Ē⤰āĨā¤¯ā¤žā¤¯", + "search_filter_filename": "ā¤Ģā¤žā¤‡ā¤˛ ā¤¨ā¤žā¤ĩā¤žā¤¨āĨ‡ ā¤ļāĨ‹ā¤§ā¤ž", + "search_filter_location": "⤏āĨā¤Ĩā¤žā¤¨", + "search_filter_location_title": "⤏āĨā¤Ĩā¤žā¤¨ ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "search_filter_media_type": "ā¤Žā¤žā¤§āĨā¤¯ā¤Ž ā¤ĒāĨā¤°ā¤•ā¤žā¤°", + "search_filter_media_type_title": "ā¤Žā¤žā¤§āĨā¤¯ā¤Ž ā¤ĒāĨā¤°ā¤•ā¤žā¤° ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "search_filter_people_title": "⤞āĨ‹ā¤• ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "search_for": "ā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ ā¤ļāĨ‹ā¤§ā¤ž", + "search_for_existing_person": "ā¤ĩā¤ŋā¤ĻāĨā¤¯ā¤Žā¤žā¤¨ ā¤ĩāĨā¤¯ā¤•āĨā¤¤āĨ€ ā¤ļāĨ‹ā¤§ā¤ž", + "search_no_more_result": "⤆⤪⤖āĨ€ ā¤Ē⤰ā¤ŋā¤Ŗā¤žā¤Ž ā¤¨ā¤žā¤šāĨ€ā¤¤", + "search_no_people": "⤕āĨ‹ā¤Ŗā¤¤āĨ€ā¤šāĨ€ ā¤ĩāĨā¤¯ā¤•āĨā¤¤āĨ€ ā¤¨ā¤žā¤šāĨ€", + "search_no_people_named": "“{name}” ā¤¨ā¤žā¤ĩā¤žā¤šāĨ€ ā¤ĩāĨā¤¯ā¤•āĨā¤¤āĨ€ ā¤¸ā¤žā¤Ēā¤Ąā¤˛āĨ€ ā¤¨ā¤žā¤šāĨ€", + "search_no_result": "ā¤•ā¤žā¤šāĨ€ā¤šāĨ€ ā¤¸ā¤žā¤Ēā¤Ąā¤˛āĨ‡ ā¤¨ā¤žā¤šāĨ€; ā¤ĩāĨ‡ā¤—ā¤ŗā¤ž ā¤ļāĨ‹ā¤§ ā¤ļā¤ŦāĨā¤Ļ ⤕ā¤ŋ⤂ā¤ĩā¤ž ⤏⤂⤝āĨ‹ā¤œā¤¨ ā¤ĩā¤žā¤Ēā¤°ā¤ž", + "search_options": "ā¤ļāĨ‹ā¤§ ā¤Ē⤰āĨā¤¯ā¤žā¤¯", + "search_page_categories": "ā¤ļāĨā¤°āĨ‡ā¤ŖāĨā¤¯ā¤ž", + "search_page_motion_photos": "ā¤ŽāĨ‹ā¤ļ⤍ ā¤ĢāĨ‹ā¤ŸāĨ‹", + "search_page_no_objects": "ā¤ĩ⤏āĨā¤¤āĨ‚ā¤‚ā¤šāĨ€ ā¤Žā¤žā¤šā¤ŋ⤤āĨ€ ⤉ā¤Ē⤞ā¤ŦāĨā¤§ ā¤¨ā¤žā¤šāĨ€", + "search_page_no_places": "⤠ā¤ŋā¤•ā¤žā¤Ŗā¤žā¤‚ā¤šāĨ€ ā¤Žā¤žā¤šā¤ŋ⤤āĨ€ ⤉ā¤Ē⤞ā¤ŦāĨā¤§ ā¤¨ā¤žā¤šāĨ€", + "search_page_screenshots": "⤏āĨā¤•āĨā¤°āĨ€ā¤¨ā¤ļāĨ‰ā¤ŸāĨā¤¸", + "search_page_search_photos_videos": "⤤āĨā¤Žā¤šāĨ‡ ā¤ĢāĨ‹ā¤ŸāĨ‹ ā¤ĩ ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓ ā¤ļāĨ‹ā¤§ā¤ž", + "search_page_selfies": "⤏āĨ‡ā¤˛āĨā¤ĢāĨ€ā¤œ", + "search_page_things": "ā¤ĩ⤏āĨā¤¤āĨ‚", + "search_page_view_all_button": "⤏⤰āĨā¤ĩ ā¤Ēā¤šā¤ž", + "search_page_your_activity": "⤤āĨā¤Žā¤šāĨ‡ ⤕āĨā¤°ā¤ŋā¤¯ā¤žā¤•ā¤˛ā¤žā¤Ē", + "search_page_your_map": "⤤āĨā¤Žā¤šā¤ž ā¤¨ā¤•ā¤žā¤ļā¤ž", + "search_people": "⤞āĨ‹ā¤• ā¤ļāĨ‹ā¤§ā¤ž", + "search_places": "⤠ā¤ŋā¤•ā¤žā¤ŖāĨ‡ ā¤ļāĨ‹ā¤§ā¤ž", + "search_rating": "⤰āĨ‡ā¤Ÿā¤ŋ⤂⤗⤍āĨā¤¸ā¤žā¤° ā¤ļāĨ‹ā¤§ā¤ž...", + "search_result_page_new_search_hint": "⤍ā¤ĩāĨ€ā¤¨ ā¤ļāĨ‹ā¤§", + "search_settings": "ā¤ļāĨ‹ā¤§ ⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗āĨā¤œ", + "search_state": "ā¤°ā¤žā¤œāĨā¤¯/⤏āĨā¤ŸāĨ‡ā¤Ÿ ā¤ļāĨ‹ā¤§ā¤ž...", + "search_suggestion_list_smart_search_hint_1": "ā¤ĄāĨ€ā¤ĢāĨ‰ā¤˛āĨā¤Ÿā¤¨āĨ‡ ⤏āĨā¤Žā¤žā¤°āĨā¤Ÿ ⤏⤰āĨā¤š ⤏āĨā¤°āĨ‚ ā¤†ā¤šāĨ‡; ā¤ŽāĨ‡ā¤Ÿā¤žā¤ĄāĨ‡ā¤Ÿā¤ž ā¤ļāĨ‹ā¤§ā¤ŖāĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ ā¤šāĨ€ ā¤°ā¤šā¤¨ā¤ž ā¤ĩā¤žā¤Ēā¤°ā¤ž. ", + "search_suggestion_list_smart_search_hint_2": "m:⤤āĨā¤Žā¤šā¤ž-ā¤ļāĨ‹ā¤§-ā¤ļā¤ŦāĨā¤Ļ", + "search_tags": "⤟āĨ…⤗āĨā¤¸ ā¤ļāĨ‹ā¤§ā¤ž...", + "search_timezone": "ā¤ĩāĨ‡ā¤ŗā¤•āĨā¤ˇāĨ‡ā¤¤āĨā¤° ā¤ļāĨ‹ā¤§ā¤ž...", + "search_type": "ā¤ļāĨ‹ā¤§ ā¤ĒāĨā¤°ā¤•ā¤žā¤°", + "search_your_photos": "⤤āĨā¤Žā¤šāĨ‡ ā¤ĢāĨ‹ā¤ŸāĨ‹ ā¤ļāĨ‹ā¤§ā¤ž", + "searching_locales": "⤞āĨ‹ā¤•⤞āĨā¤¸ ā¤ļāĨ‹ā¤§ā¤¤ ā¤†ā¤šāĨ‡...", + "second": "⤏āĨ‡ā¤•⤂ā¤Ļ", + "see_all_people": "⤏⤰āĨā¤ĩ ⤞āĨ‹ā¤• ā¤Ēā¤žā¤šā¤ž", + "select": "⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "select_album_cover": "⤅⤞āĨā¤Ŧā¤Ž ⤕ā¤ĩāĨā¤šā¤° ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "select_all": "⤏⤰āĨā¤ĩ ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "select_all_duplicates": "⤏⤰āĨā¤ĩ ā¤ĄāĨā¤ĒāĨā¤˛ā¤ŋ⤕āĨ‡ā¤ŸāĨā¤¸ ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "select_all_in": "{group} ā¤Žā¤§āĨ€ā¤˛ ⤏⤰āĨā¤ĩ ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "select_avatar_color": "⤅ā¤ĩā¤¤ā¤žā¤°ā¤šā¤ž ⤰⤂⤗ ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "select_face": "⤚āĨ‡ā¤šā¤°ā¤ž ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "select_featured_photo": "ā¤Ģā¤ŋ⤚⤰āĨā¤Ą ā¤ĢāĨ‹ā¤ŸāĨ‹ ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "select_from_computer": "⤕āĨ‰ā¤ŽāĨā¤ĒāĨā¤¯āĨā¤Ÿā¤°ā¤Žā¤§āĨ‚⤍ ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "select_keep_all": "⤏⤰āĨā¤ĩ ⤠āĨ‡ā¤ĩ⤪āĨ‡ ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "select_library_owner": "ā¤˛ā¤žā¤¯ā¤ŦāĨā¤°ā¤°āĨ€ ā¤Žā¤žā¤˛ā¤• ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "select_new_face": "⤍ā¤ĩā¤ž ⤚āĨ‡ā¤šā¤°ā¤ž ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "select_person_to_tag": "⤟āĨ…⤗ ⤕⤰⤪āĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ ā¤ĩāĨā¤¯ā¤•āĨā¤¤āĨ€ ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "select_photos": "ā¤ĢāĨ‹ā¤ŸāĨ‹ ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "select_trash_all": "ā¤•ā¤šā¤°ā¤žā¤ĒāĨ‡ā¤ŸāĨ€ā¤¤āĨ€ā¤˛ ⤏⤰āĨā¤ĩ ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "select_user_for_sharing_page_err_album": "⤅⤞āĨā¤Ŧā¤Ž ā¤¤ā¤¯ā¤žā¤° ⤕⤰⤪āĨā¤¯ā¤žā¤¤ ⤅⤝ā¤ļ⤏āĨā¤ĩāĨ€", + "selected": "⤍ā¤ŋā¤ĩā¤Ąā¤˛āĨ‡ā¤˛āĨ‡", + "selected_count": "{count, plural, other {# ⤍ā¤ŋā¤ĩā¤Ąā¤˛āĨ‡}}", + "selected_gps_coordinates": "⤍ā¤ŋā¤ĩā¤Ąā¤˛āĨ‡ā¤˛āĨā¤¯ā¤ž GPS ⤏āĨā¤Ĩā¤žā¤¨ā¤¨ā¤ŋ⤰āĨā¤ĻāĨ‡ā¤ļā¤žā¤‚ā¤•", + "send_message": "⤏⤂ā¤ĻāĨ‡ā¤ļ ā¤Ēā¤žā¤ ā¤ĩā¤ž", + "send_welcome_email": "⤏āĨā¤ĩā¤žā¤—ā¤¤ ā¤ˆā¤ŽāĨ‡ā¤˛ ā¤Ēā¤žā¤ ā¤ĩā¤ž", + "server_endpoint": "⤏⤰āĨā¤ĩāĨā¤šā¤° ā¤ā¤‚ā¤Ąā¤ĒāĨ‰ā¤‡ā¤‚ā¤Ÿ", + "server_info_box_app_version": "⤅āĨ…ā¤Ē ⤆ā¤ĩāĨƒā¤¤āĨā¤¤āĨ€", + "server_info_box_server_url": "⤏⤰āĨā¤ĩāĨā¤šā¤° URL", + "server_offline": "⤏⤰āĨā¤ĩāĨā¤šā¤° ⤑ā¤Ģā¤˛ā¤žā¤‡ā¤¨", + "server_online": "⤏⤰āĨā¤ĩāĨā¤šā¤° ā¤‘ā¤¨ā¤˛ā¤žā¤‡ā¤¨", + "server_privacy": "⤏⤰āĨā¤ĩāĨā¤šā¤° ⤗āĨ‹ā¤Ē⤍āĨ€ā¤¯ā¤¤ā¤ž", + "server_stats": "⤏⤰āĨā¤ĩāĨā¤šā¤° ā¤†ā¤•ā¤ĄāĨ‡ā¤ĩā¤žā¤°āĨ€", + "server_version": "⤏⤰āĨā¤ĩāĨā¤šā¤° ⤆ā¤ĩāĨƒā¤¤āĨā¤¤āĨ€", + "set": "⤏āĨ‡ā¤Ÿ ā¤•ā¤°ā¤ž", + "set_as_album_cover": "⤅⤞āĨā¤Ŧā¤Ž ⤕ā¤ĩāĨā¤šā¤° ā¤ŽāĨā¤šā¤ŖāĨ‚⤍ ⤏āĨ‡ā¤Ÿ ā¤•ā¤°ā¤ž", + "set_as_featured_photo": "ā¤Ģā¤ŋ⤚⤰āĨā¤Ą ā¤ĢāĨ‹ā¤ŸāĨ‹ ā¤ŽāĨā¤šā¤ŖāĨ‚⤍ ⤏āĨ‡ā¤Ÿ ā¤•ā¤°ā¤ž", + "set_as_profile_picture": "ā¤ĒāĨā¤°āĨ‹ā¤Ģā¤žā¤‡ā¤˛ ā¤ĢāĨ‹ā¤ŸāĨ‹ ā¤ŽāĨā¤šā¤ŖāĨ‚⤍ ⤏āĨ‡ā¤Ÿ ā¤•ā¤°ā¤ž", + "set_date_of_birth": "⤜⤍āĨā¤Žā¤¤ā¤žā¤°āĨ€ā¤– ⤏āĨ‡ā¤Ÿ ā¤•ā¤°ā¤ž", + "set_profile_picture": "ā¤ĒāĨā¤°āĨ‹ā¤Ģā¤žā¤‡ā¤˛ ā¤ĢāĨ‹ā¤ŸāĨ‹ ⤏āĨ‡ā¤Ÿ ā¤•ā¤°ā¤ž", + "set_slideshow_to_fullscreen": "⤏āĨā¤˛ā¤žā¤‡ā¤Ąā¤ļāĨ‹ ā¤ĢāĨā¤˛ā¤¸āĨā¤•āĨā¤°āĨ€ā¤¨ ā¤•ā¤°ā¤ž", + "set_stack_primary_asset": "ā¤ŽāĨā¤–āĨā¤¯ ā¤†ā¤¯ā¤Ÿā¤Ž ā¤ŽāĨā¤šā¤ŖāĨ‚⤍ ⤏āĨ‡ā¤Ÿ ā¤•ā¤°ā¤ž", + "setting_image_viewer_help": "ā¤ĄāĨ€ā¤ŸāĨ‡ā¤˛ ā¤ĩāĨā¤šāĨā¤¯āĨ‚⤅⤰ ⤆⤧āĨ€ ā¤˛ā¤šā¤žā¤¨ ā¤Ĩ⤂ā¤Ŧ⤍āĨ‡ā¤˛ ⤞āĨ‹ā¤Ą ⤕⤰⤤āĨ‹, ⤍⤂⤤⤰ (⤏⤕āĨā¤ˇā¤Ž ⤅⤏⤞āĨā¤¯ā¤žā¤¸) ā¤Žā¤§āĨā¤¯ā¤Ž ā¤†ā¤•ā¤žā¤°ā¤žā¤šāĨ‡ ā¤ĒāĨā¤°ā¤ŋā¤ĩāĨā¤šāĨā¤¯āĨ‚ ⤞āĨ‹ā¤Ą ⤕⤰⤤āĨ‹, ⤆⤪ā¤ŋ ā¤ļāĨ‡ā¤ĩ⤟āĨ€ (⤏⤕āĨā¤ˇā¤Ž ⤅⤏⤞āĨā¤¯ā¤žā¤¸) ā¤ŽāĨ‚⤺ ā¤ĒāĨā¤°ā¤¤ā¤ŋā¤Žā¤ž ⤞āĨ‹ā¤Ą ⤕⤰⤤āĨ‹.", + "setting_image_viewer_original_subtitle": "ā¤ĒāĨ‚⤰āĨā¤Ŗ-⤰ā¤ŋā¤āĨ‹ā¤˛āĨā¤¯āĨ‚ā¤ļ⤍⤚āĨ€ ā¤ŽāĨ‚⤺ ā¤ĒāĨā¤°ā¤¤ā¤ŋā¤Žā¤ž ⤞āĨ‹ā¤Ą ⤕⤰⤪āĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ ⤏⤕āĨā¤ˇā¤Ž ā¤•ā¤°ā¤ž (ā¤ŽāĨ‹ā¤ āĨ€). ā¤ĄāĨ‡ā¤Ÿā¤ž ā¤ĩā¤žā¤Ē⤰ ā¤•ā¤ŽāĨ€ ⤕⤰⤪āĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ (⤍āĨ‡ā¤Ÿā¤ĩ⤰āĨā¤• ā¤ĩ ā¤Ąā¤ŋā¤ĩāĨā¤šā¤žā¤‡ā¤¸ ⤕āĨ…ā¤ļ ā¤ĻāĨ‹ā¤¨āĨā¤šāĨ€) ⤅⤕āĨā¤ˇā¤Ž ā¤•ā¤°ā¤ž.", + "setting_image_viewer_original_title": "ā¤ŽāĨ‚⤺ ā¤ĒāĨā¤°ā¤¤ā¤ŋā¤Žā¤ž ⤞āĨ‹ā¤Ą ā¤•ā¤°ā¤ž", + "setting_image_viewer_preview_subtitle": "ā¤Žā¤§āĨā¤¯ā¤Ž-⤰ā¤ŋā¤āĨ‹ā¤˛āĨā¤¯āĨ‚ā¤ļ⤍ ā¤ĒāĨā¤°ā¤¤ā¤ŋā¤Žā¤ž ⤞āĨ‹ā¤Ą ⤕⤰⤪āĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ ⤏⤕āĨā¤ˇā¤Ž ā¤•ā¤°ā¤ž. ⤅⤕āĨā¤ˇā¤Ž ⤕āĨ‡ā¤˛āĨā¤¯ā¤žā¤¸ ā¤ĨāĨ‡ā¤Ÿ ā¤ŽāĨ‚⤺ ā¤ĒāĨā¤°ā¤¤ā¤ŋā¤Žā¤ž ⤞āĨ‹ā¤Ą ā¤šāĨ‹ā¤ˆā¤˛ ⤕ā¤ŋ⤂ā¤ĩā¤ž ā¤Ģ⤕āĨā¤¤ ā¤Ĩ⤂ā¤Ŧ⤍āĨ‡ā¤˛ ā¤ĩā¤žā¤Ēā¤°ā¤˛ā¤ž ā¤œā¤žā¤ˆā¤˛.", + "setting_image_viewer_preview_title": "ā¤ĒāĨā¤°ā¤ŋā¤ĩāĨā¤šāĨā¤¯āĨ‚ ā¤ĒāĨā¤°ā¤¤ā¤ŋā¤Žā¤ž ⤞āĨ‹ā¤Ą ā¤•ā¤°ā¤ž", + "setting_image_viewer_title": "ā¤ĒāĨā¤°ā¤¤ā¤ŋā¤Žā¤ž", + "setting_languages_apply": "ā¤˛ā¤žā¤—āĨ‚ ā¤•ā¤°ā¤ž", + "setting_languages_subtitle": "⤅āĨ…ā¤Ē⤚āĨ€ ā¤­ā¤žā¤ˇā¤ž ā¤Ŧā¤Ļā¤˛ā¤ž", + "setting_notifications_notify_failures_grace_period": "ā¤Ēā¤žā¤°āĨā¤ļāĨā¤ĩ⤭āĨ‚ā¤ŽāĨ€ ā¤ŦāĨ…⤕⤅ā¤Ē ⤅ā¤Ē⤝ā¤ļā¤žā¤‚ā¤šāĨ€ ⤏āĨ‚ā¤šā¤¨ā¤ž: {duration}", + "setting_notifications_notify_hours": "{count} ā¤¤ā¤žā¤¸", + "setting_notifications_notify_immediately": "⤤⤤āĨā¤•ā¤žā¤ŗ", + "setting_notifications_notify_minutes": "{count} ā¤Žā¤ŋ⤍ā¤ŋ⤟āĨ‡", + "setting_notifications_notify_never": "⤕⤧āĨ€ā¤š ā¤¨ā¤žā¤šāĨ€", + "setting_notifications_notify_seconds": "{count} ⤏āĨ‡ā¤•⤂ā¤Ļ", + "setting_notifications_single_progress_subtitle": "ā¤ĒāĨā¤°ā¤¤āĨā¤¯āĨ‡ā¤• ā¤†ā¤¯ā¤Ÿā¤Žā¤¸ā¤žā¤ āĨ€ ⤤ā¤Ēā¤ļāĨ€ā¤˛ā¤ĩā¤žā¤° ⤅ā¤Ē⤞āĨ‹ā¤Ą ā¤ĒāĨā¤°ā¤—⤤āĨ€ ā¤Žā¤žā¤šā¤ŋ⤤āĨ€", + "setting_notifications_single_progress_title": "ā¤Ēā¤žā¤°āĨā¤ļāĨā¤ĩ⤭āĨ‚ā¤ŽāĨ€ ā¤ŦāĨ…⤕⤅ā¤Ē⤚āĨ€ ⤤ā¤Ēā¤ļāĨ€ā¤˛ā¤ĩā¤žā¤° ā¤ĒāĨā¤°ā¤—⤤āĨ€ ā¤Ļā¤žā¤–ā¤ĩā¤ž", + "setting_notifications_subtitle": "⤤āĨā¤Žā¤šāĨ€ ⤏āĨ‚ā¤šā¤¨ā¤ž ā¤ĒāĨā¤°ā¤žā¤§ā¤žā¤¨āĨā¤¯āĨ‡ ā¤¸ā¤Žā¤žā¤¯āĨ‹ā¤œā¤ŋ⤤ ā¤•ā¤°ā¤ž", + "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_title": "ā¤ŽāĨ‚⤺ ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓ ⤏⤕āĨā¤¤āĨ€ā¤¨āĨ‡ ā¤ĒāĨā¤˛āĨ‡ ā¤•ā¤°ā¤ž", + "settings": "⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗āĨā¤œ", + "settings_require_restart": "ā¤šāĨ€ ⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗ ā¤˛ā¤žā¤—āĨ‚ ⤕⤰⤪āĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ ⤕āĨƒā¤Ēā¤¯ā¤ž Immich ⤰āĨ€ā¤¸āĨā¤Ÿā¤žā¤°āĨā¤Ÿ ā¤•ā¤°ā¤ž", + "settings_saved": "⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗āĨā¤œ ⤜⤤⤍ ⤕āĨ‡ā¤˛āĨā¤¯ā¤ž", + "setup_pin_code": "PIN ⤕āĨ‹ā¤Ą ⤏āĨ‡ā¤Ÿ ā¤•ā¤°ā¤ž", + "share": "ā¤ļāĨ‡ā¤…⤰ ā¤•ā¤°ā¤ž", + "share_action_prompt": "{count} ā¤†ā¤¯ā¤Ÿā¤Ž ā¤ļāĨ‡ā¤…⤰ ⤕āĨ‡ā¤˛āĨ‡", + "share_add_photos": "ā¤ĢāĨ‹ā¤ŸāĨ‹ ⤜āĨ‹ā¤Ąā¤ž", + "share_assets_selected": "{count} ⤍ā¤ŋā¤ĩā¤Ąā¤˛āĨ‡", + "share_dialog_preparing": "ā¤¤ā¤¯ā¤žā¤° ⤕⤰⤤ ā¤†ā¤šāĨ‡...", + "share_link": "ā¤ļāĨ‡ā¤…⤰ ā¤ĻāĨā¤ĩā¤ž", + "shared": "ā¤ļāĨ‡ā¤…⤰ ⤕āĨ‡ā¤˛āĨ‡", + "shared_album_activities_input_disable": "⤟ā¤ŋā¤ĒāĨā¤Ē⤪āĨ€ ⤍ā¤ŋ⤎āĨā¤•āĨā¤°ā¤ŋ⤝ ā¤†ā¤šāĨ‡", + "shared_album_activity_remove_content": "ā¤šāĨ€ ⤕āĨƒā¤¤āĨ€ ā¤šā¤Ÿā¤ĩā¤žā¤¯ā¤šāĨ€ ā¤†ā¤šāĨ‡ ā¤•ā¤ž?", + "shared_album_activity_remove_title": "⤕āĨƒā¤¤āĨ€ ā¤šā¤Ÿā¤ĩā¤ž", + "shared_album_section_people_action_error": "⤅⤞āĨā¤Ŧā¤Žā¤Žā¤§āĨ‚⤍ ā¤Ŧā¤žā¤šāĨ‡ā¤° ā¤Ēā¤Ąā¤¤ā¤žā¤¨ā¤ž/ā¤•ā¤žā¤ĸā¤¤ā¤žā¤¨ā¤ž ⤤āĨā¤°āĨā¤ŸāĨ€", + "shared_album_section_people_action_leave": "⤅⤞āĨā¤Ŧā¤Žā¤Žā¤§āĨ‚⤍ ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤ā¤ž ā¤•ā¤žā¤ĸā¤ž", + "shared_album_section_people_action_remove_user": "⤅⤞āĨā¤Ŧā¤Žā¤Žā¤§āĨ‚⤍ ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤ā¤ž ā¤•ā¤žā¤ĸā¤ž", + "shared_album_section_people_title": "⤞āĨ‹ā¤•", + "shared_by": "ā¤¯ā¤žā¤‚ā¤¨āĨ€ ā¤ļāĨ‡ā¤…⤰ ⤕āĨ‡ā¤˛āĨ‡", + "shared_by_user": "{user} ā¤¯ā¤žā¤‚ā¤¨āĨ€ ā¤ļāĨ‡ā¤…⤰ ⤕āĨ‡ā¤˛āĨ‡", + "shared_by_you": "⤤āĨā¤Žā¤šāĨā¤¯ā¤žā¤•ā¤ĄāĨ‚⤍ ā¤ļāĨ‡ā¤…⤰ ⤕āĨ‡ā¤˛āĨ‡", + "shared_from_partner": "{partner} ā¤•ā¤ĄāĨ€ā¤˛ ā¤ĢāĨ‹ā¤ŸāĨ‹", + "shared_intent_upload_button_progress_text": "{current}/{total} ⤅ā¤Ē⤞āĨ‹ā¤Ą ā¤ā¤žā¤˛āĨ‡", + "shared_link_app_bar_title": "ā¤ļāĨ‡ā¤…⤰āĨā¤Ą ā¤ĻāĨā¤ĩāĨ‡", + "shared_link_clipboard_copied_massage": "⤕āĨā¤˛ā¤ŋā¤Ēā¤ŦāĨ‹ā¤°āĨā¤Ąā¤ĩ⤰ ⤕āĨ‰ā¤ĒāĨ€ ⤕āĨ‡ā¤˛āĨ‡", + "shared_link_clipboard_text": "ā¤ĻāĨā¤ĩā¤ž: {link}\nā¤Ēā¤žā¤¸ā¤ĩ⤰āĨā¤Ą: {password}", + "shared_link_create_error": "ā¤ļāĨ‡ā¤…⤰āĨā¤Ą ā¤ĻāĨā¤ĩā¤ž ā¤¤ā¤¯ā¤žā¤° ā¤•ā¤°ā¤¤ā¤žā¤¨ā¤ž ⤤āĨā¤°āĨā¤ŸāĨ€", + "shared_link_custom_url_description": "ā¤¸ā¤žā¤¨āĨā¤•āĨ‚⤞ URL ā¤ĻāĨā¤ĩā¤žā¤°āĨ‡ ā¤šā¤ž ā¤ļāĨ‡ā¤…⤰āĨā¤Ą ā¤ĻāĨā¤ĩā¤ž ā¤‰ā¤˜ā¤Ąā¤ž", + "shared_link_edit_description_hint": "ā¤ļāĨ‡ā¤…ā¤°ā¤šāĨ‡ ā¤ĩ⤰āĨā¤Ŗā¤¨ ā¤ĒāĨā¤°ā¤ĩā¤ŋ⤎āĨā¤Ÿ ā¤•ā¤°ā¤ž", + "shared_link_edit_expire_after_option_day": "1 ā¤Ļā¤ŋā¤ĩ⤏", + "shared_link_edit_expire_after_option_days": "{count} ā¤Ļā¤ŋā¤ĩ⤏", + "shared_link_edit_expire_after_option_hour": "1 ā¤¤ā¤žā¤¸", + "shared_link_edit_expire_after_option_hours": "{count} ā¤¤ā¤žā¤¸", + "shared_link_edit_expire_after_option_minute": "1 ā¤Žā¤ŋ⤍ā¤ŋ⤟", + "shared_link_edit_expire_after_option_minutes": "{count} ā¤Žā¤ŋ⤍ā¤ŋ⤟āĨ‡", + "shared_link_edit_expire_after_option_months": "{count} ā¤Žā¤šā¤ŋ⤍āĨ‡", + "shared_link_edit_expire_after_option_year": "{count} ā¤ĩ⤰āĨā¤ˇ", + "shared_link_edit_password_hint": "ā¤ļāĨ‡ā¤…ā¤°ā¤šā¤ž ā¤Ēā¤žā¤¸ā¤ĩ⤰āĨā¤Ą ā¤ĒāĨā¤°ā¤ĩā¤ŋ⤎āĨā¤Ÿ ā¤•ā¤°ā¤ž", + "shared_link_edit_submit_button": "ā¤ĻāĨā¤ĩā¤ž ⤅ā¤ĻāĨā¤¯ā¤¯ā¤žā¤ĩ⤤ ā¤•ā¤°ā¤ž", + "shared_link_error_server_url_fetch": "⤏⤰āĨā¤ĩāĨā¤šā¤° URL ā¤Žā¤ŋ⤺āĨ‚ ā¤ļā¤•ā¤˛ā¤ž ā¤¨ā¤žā¤šāĨ€", + "shared_link_expires_day": "{count} ā¤Ļā¤ŋā¤ĩā¤¸ā¤žā¤¤ ⤏⤂ā¤ĒāĨ‡ā¤˛", + "shared_link_expires_days": "{count} ā¤Ļā¤ŋā¤ĩā¤¸ā¤žā¤¤ ⤏⤂ā¤ĒāĨ‡ā¤˛", + "shared_link_expires_hour": "{count} ā¤¤ā¤žā¤¸ā¤žā¤¤ ⤏⤂ā¤ĒāĨ‡ā¤˛", + "shared_link_expires_hours": "{count} ā¤¤ā¤žā¤¸ā¤žā¤‚ā¤¤ ⤏⤂ā¤ĒāĨ‡ā¤˛", + "shared_link_expires_minute": "{count} ā¤Žā¤ŋ⤍ā¤ŋā¤Ÿā¤žā¤¤ ⤏⤂ā¤ĒāĨ‡ā¤˛", + "shared_link_expires_minutes": "{count} ā¤Žā¤ŋ⤍ā¤ŋā¤Ÿā¤žā¤‚ā¤¤ ⤏⤂ā¤ĒāĨ‡ā¤˛", + "shared_link_expires_never": "⤕⤧āĨ€ā¤š ⤏⤂ā¤Ē⤤ ā¤¨ā¤žā¤šāĨ€ ∞", + "shared_link_expires_second": "{count} ⤏āĨ‡ā¤•⤂ā¤Ļā¤žā¤¤ ⤏⤂ā¤ĒāĨ‡ā¤˛", + "shared_link_expires_seconds": "{count} ⤏āĨ‡ā¤•⤂ā¤Ļā¤žā¤¤ ⤏⤂ā¤ĒāĨ‡ā¤˛", + "shared_link_individual_shared": "ā¤ĩāĨˆā¤¯ā¤•āĨā¤¤ā¤ŋ⤕ ā¤ļāĨ‡ā¤…⤰", + "shared_link_info_chip_metadata": "EXIF (ā¤ā¤•āĨā¤¸ā¤ŋā¤Ģ)", + "shared_link_manage_links": "ā¤ļāĨ‡ā¤…⤰āĨā¤Ą ā¤ĻāĨā¤ĩāĨ‡ ā¤ĩāĨā¤¯ā¤ĩ⤏āĨā¤Ĩā¤žā¤Ēā¤ŋ⤤ ā¤•ā¤°ā¤ž", + "shared_link_options": "ā¤ļāĨ‡ā¤…⤰āĨā¤Ą ā¤ĻāĨā¤ĩā¤ž ā¤Ē⤰āĨā¤¯ā¤žā¤¯", + "shared_link_password_description": "ā¤šā¤ž ā¤ļāĨ‡ā¤…⤰āĨā¤Ą ā¤ĻāĨā¤ĩā¤ž ā¤Ēā¤žā¤šā¤ŖāĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ ā¤Ēā¤žā¤¸ā¤ĩ⤰āĨā¤Ą ⤆ā¤ĩā¤ļāĨā¤¯ā¤• ā¤†ā¤šāĨ‡", + "shared_links": "ā¤ļāĨ‡ā¤…⤰āĨā¤Ą ā¤ĻāĨā¤ĩāĨ‡", + "shared_links_description": "ā¤ĻāĨā¤ĩāĨā¤¯ā¤žā¤ĻāĨā¤ĩā¤žā¤°āĨ‡ ā¤ĢāĨ‹ā¤ŸāĨ‹ ⤆⤪ā¤ŋ ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓ ā¤ļāĨ‡ā¤…⤰ ā¤•ā¤°ā¤ž", + "shared_photos_and_videos_count": "{assetCount, plural, other {# ā¤ļāĨ‡ā¤…⤰āĨā¤Ą ā¤ĢāĨ‹ā¤ŸāĨ‹ ⤆⤪ā¤ŋ ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓}}", + "shared_with_me": "ā¤Žā¤žā¤āĨā¤¯ā¤žā¤¸āĨ‹ā¤Ŧ⤤ ā¤ļāĨ‡ā¤…⤰ ⤕āĨ‡ā¤˛āĨ‡ā¤˛āĨ‡", + "shared_with_partner": "{partner} ⤏āĨ‹ā¤Ŧ⤤ ā¤ļāĨ‡ā¤…⤰ ⤕āĨ‡ā¤˛āĨ‡", + "sharing": "ā¤ļāĨ‡ā¤…⤰ā¤ŋ⤂⤗", + "sharing_enter_password": "ā¤šāĨ‡ ā¤ĒāĨƒā¤ˇāĨā¤  ā¤Ēā¤žā¤šā¤ŖāĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ ⤕āĨƒā¤Ēā¤¯ā¤ž ā¤Ēā¤žā¤¸ā¤ĩ⤰āĨā¤Ą ā¤ĒāĨā¤°ā¤ĩā¤ŋ⤎āĨā¤Ÿ ā¤•ā¤°ā¤ž.", + "sharing_page_album": "ā¤ļāĨ‡ā¤…⤰āĨā¤Ą ⤅⤞āĨā¤Ŧā¤Ž", + "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": "⤅āĨ…⤏āĨ‡ā¤Ÿ ā¤•ā¤žā¤¯ā¤Žā¤šāĨ‡ ā¤šā¤Ÿā¤ĩ⤪āĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ ⇧ ā¤Ļā¤žā¤Ŧā¤ž", + "show_album_options": "⤅⤞āĨā¤Ŧā¤Ž ā¤Ē⤰āĨā¤¯ā¤žā¤¯ ā¤Ļā¤žā¤–ā¤ĩā¤ž", + "show_albums": "⤅⤞āĨā¤Ŧā¤Ž ā¤Ļā¤žā¤–ā¤ĩā¤ž", + "show_all_people": "⤏⤰āĨā¤ĩ ⤞āĨ‹ā¤• ā¤Ļā¤žā¤–ā¤ĩā¤ž", + "show_and_hide_people": "⤞āĨ‹ā¤• ā¤Ļā¤žā¤–ā¤ĩā¤ž ⤆⤪ā¤ŋ ⤞ā¤Ēā¤ĩā¤ž", + "show_file_location": "ā¤Ģā¤žā¤‡ā¤˛ā¤šāĨ‡ ⤏āĨā¤Ĩā¤žā¤¨ ā¤Ļā¤žā¤–ā¤ĩā¤ž", + "show_gallery": "⤗āĨ…⤞⤰āĨ€ ā¤Ļā¤žā¤–ā¤ĩā¤ž", + "show_hidden_people": "⤞ā¤Ēā¤ĩ⤞āĨ‡ā¤˛āĨ‡ ⤞āĨ‹ā¤• ā¤Ļā¤žā¤–ā¤ĩā¤ž", + "show_in_timeline": "ā¤Ÿā¤žā¤‡ā¤Žā¤˛ā¤žā¤‡ā¤¨ā¤Žā¤§āĨā¤¯āĨ‡ ā¤Ļā¤žā¤–ā¤ĩā¤ž", + "show_in_timeline_setting_description": "ā¤¯ā¤ž ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤āĨā¤¯ā¤žā¤šāĨ‡ ā¤ĢāĨ‹ā¤ŸāĨ‹-ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓ ⤤āĨā¤Žā¤šāĨā¤¯ā¤ž ā¤Ÿā¤žā¤‡ā¤Žā¤˛ā¤žā¤‡ā¤¨ā¤Žā¤§āĨā¤¯āĨ‡ ā¤Ļā¤žā¤–ā¤ĩā¤ž", + "show_keyboard_shortcuts": "⤕āĨ€ā¤ŦāĨ‹ā¤°āĨā¤Ą ā¤ļāĨ‰ā¤°āĨā¤Ÿā¤•ā¤Ÿ ā¤Ļā¤žā¤–ā¤ĩā¤ž", + "show_metadata": "ā¤ŽāĨ‡ā¤Ÿā¤žā¤ĄāĨ‡ā¤Ÿā¤ž ā¤Ļā¤žā¤–ā¤ĩā¤ž", + "show_or_hide_info": "ā¤Žā¤žā¤šā¤ŋ⤤āĨ€ ā¤Ļā¤žā¤–ā¤ĩā¤ž ⤕ā¤ŋ⤂ā¤ĩā¤ž ⤞ā¤Ēā¤ĩā¤ž", + "show_password": "ā¤Ēā¤žā¤¸ā¤ĩ⤰āĨā¤Ą ā¤Ļā¤žā¤–ā¤ĩā¤ž", + "show_person_options": "ā¤ĩāĨā¤¯ā¤•āĨā¤¤āĨ€ā¤šāĨ‡ ā¤Ē⤰āĨā¤¯ā¤žā¤¯ ā¤Ļā¤žā¤–ā¤ĩā¤ž", + "show_progress_bar": "ā¤ĒāĨā¤°ā¤—⤤āĨ€ ā¤Ē⤟āĨā¤ŸāĨ€ ā¤Ļā¤žā¤–ā¤ĩā¤ž", + "show_search_options": "ā¤ļāĨ‹ā¤§ ā¤Ē⤰āĨā¤¯ā¤žā¤¯ ā¤Ļā¤žā¤–ā¤ĩā¤ž", + "show_shared_links": "ā¤ļāĨ‡ā¤…⤰ ⤕āĨ‡ā¤˛āĨ‡ā¤˛āĨ‡ ā¤ĻāĨā¤ĩāĨ‡ ā¤Ļā¤žā¤–ā¤ĩā¤ž", + "show_slideshow_transition": "⤏āĨā¤˛ā¤žā¤‡ā¤Ąā¤ļāĨ‹ ⤟āĨā¤°ā¤žā¤‚ā¤ā¤ŋā¤ļ⤍ ā¤Ļā¤žā¤–ā¤ĩā¤ž", + "show_supporter_badge": "ā¤¸ā¤Žā¤°āĨā¤Ĩ⤕ ā¤ŦāĨ…ā¤œ", + "show_supporter_badge_description": "ā¤¸ā¤Žā¤°āĨā¤Ĩ⤕ ā¤ŦāĨ…ā¤œ ā¤Ļā¤žā¤–ā¤ĩā¤ž", + "shuffle": "ā¤ļā¤Ģ⤞", + "sidebar": "ā¤¸ā¤žā¤‡ā¤Ąā¤Ŧā¤žā¤°", + "sidebar_display_description": "ā¤¸ā¤žā¤‡ā¤Ąā¤Ŧā¤žā¤°ā¤Žā¤§āĨā¤¯āĨ‡ ā¤ĻāĨƒā¤ļāĨā¤¯ā¤žā¤šā¤ž ā¤ĻāĨā¤ĩā¤ž ā¤Ļā¤žā¤–ā¤ĩā¤ž", + "sign_out": "ā¤¸ā¤žā¤‡ā¤¨ ā¤†ā¤‰ā¤Ÿ", + "sign_up": "ā¤¸ā¤žā¤‡ā¤¨ ⤅ā¤Ē", + "size": "ā¤†ā¤•ā¤žā¤°", + "skip_to_content": "ā¤¸ā¤žā¤Žā¤—āĨā¤°āĨ€ā¤•ā¤ĄāĨ‡ ā¤œā¤ž", + "skip_to_folders": "ā¤ĢāĨ‹ā¤˛āĨā¤Ąā¤°āĨā¤¸ā¤•ā¤ĄāĨ‡ ā¤œā¤ž", + "skip_to_tags": "⤟āĨ…⤗āĨā¤¸ā¤•ā¤ĄāĨ‡ ā¤œā¤ž", + "slideshow": "⤏āĨā¤˛ā¤žā¤‡ā¤Ąā¤ļāĨ‹", + "slideshow_settings": "⤏āĨā¤˛ā¤žā¤‡ā¤Ąā¤ļāĨ‹ ⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗āĨā¤œ", + "sort_albums_by": "⤅⤞āĨā¤Ŧā¤Ž ā¤¯ā¤žā¤¨āĨā¤¸ā¤žā¤° ⤕āĨā¤°ā¤Ž ā¤˛ā¤žā¤ĩā¤žâ€Ļ", + "sort_created": "ā¤¤ā¤¯ā¤žā¤° ⤕āĨ‡ā¤˛āĨ‡ā¤˛āĨ€ ā¤¤ā¤žā¤°āĨ€ā¤–", + "sort_items": "ā¤†ā¤¯ā¤Ÿā¤Žā¤žā¤‚ā¤šāĨ€ ⤏⤂⤖āĨā¤¯ā¤ž", + "sort_modified": "ā¤Ŧā¤Ļ⤞ ⤕āĨ‡ā¤˛āĨ‡ā¤˛āĨ€ ā¤¤ā¤žā¤°āĨ€ā¤–", + "sort_newest": "⤅⤞āĨ€ā¤•ā¤Ąā¤šā¤ž ā¤ĢāĨ‹ā¤ŸāĨ‹", + "sort_oldest": "⤏⤰āĨā¤ĩā¤žā¤¤ ⤜āĨā¤¨ā¤ž ā¤ĢāĨ‹ā¤ŸāĨ‹", + "sort_people_by_similarity": "ā¤¸ā¤žā¤ŽāĨā¤¯ā¤¤āĨ‡ā¤¨āĨā¤¸ā¤žā¤° ā¤ĩāĨā¤¯ā¤•āĨā¤¤āĨ€ā¤‚ā¤šā¤ž ⤕āĨā¤°ā¤Ž ā¤˛ā¤žā¤ĩā¤ž", + "sort_recent": "⤍āĨā¤•ā¤¤ā¤žā¤š ⤘āĨ‡ā¤¤ā¤˛āĨ‡ā¤˛ā¤ž ā¤ĢāĨ‹ā¤ŸāĨ‹", + "sort_title": "ā¤ļāĨ€ā¤°āĨā¤ˇā¤•", + "source": "⤏āĨā¤¤āĨā¤°āĨ‹ā¤¤", + "stack": "⤏āĨā¤ŸāĨ…⤕", + "stack_action_prompt": "{count} ⤏āĨā¤ŸāĨ…⤕ ⤕āĨ‡ā¤˛āĨ‡", + "stack_duplicates": "ā¤ĄāĨā¤ĒāĨā¤˛ā¤ŋ⤕āĨ‡ā¤ŸāĨā¤¸ ⤏āĨā¤ŸāĨ…⤕ ā¤•ā¤°ā¤ž", + "stack_select_one_photo": "⤏āĨā¤ŸāĨ…ā¤•ā¤¸ā¤žā¤ āĨ€ ā¤ā¤• ā¤ŽāĨā¤–āĨā¤¯ ā¤ĢāĨ‹ā¤ŸāĨ‹ ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "stack_selected_photos": "⤍ā¤ŋā¤ĩā¤Ąā¤˛āĨ‡ā¤˛āĨ‡ ā¤ĢāĨ‹ā¤ŸāĨ‹ ⤏āĨā¤ŸāĨ…⤕ ā¤•ā¤°ā¤ž", + "stacked_assets_count": "⤏āĨā¤ŸāĨ…⤕ ⤕āĨ‡ā¤˛āĨ‡ā¤˛āĨ‡ {count, plural, one {# ā¤†ā¤¯ā¤Ÿā¤Ž} other {# ā¤†ā¤¯ā¤Ÿā¤Ž}}", + "stacktrace": "⤏āĨā¤ŸāĨ…ā¤•ā¤ŸāĨā¤°āĨ‡ā¤¸", + "start": "⤏āĨā¤°āĨ‚ ā¤•ā¤°ā¤ž", + "start_date": "⤏āĨā¤°āĨā¤ĩā¤žā¤¤āĨ€ā¤šāĨ€ ā¤¤ā¤žā¤°āĨ€ā¤–", + "state": "⤏āĨā¤Ĩā¤ŋ⤤āĨ€", + "status": "⤏āĨā¤ŸāĨ‡ā¤Ÿā¤¸", + "stop_casting": "ā¤•ā¤žā¤¸āĨā¤Ÿā¤ŋ⤂⤗ ā¤Ĩā¤žā¤‚ā¤Ŧā¤ĩā¤ž", + "stop_motion_photo": "ā¤ŽāĨ‹ā¤ļ⤍ ā¤ĢāĨ‹ā¤ŸāĨ‹ ā¤Ĩā¤žā¤‚ā¤Ŧā¤ĩā¤ž", + "stop_photo_sharing": "⤤āĨā¤Žā¤šāĨ‡ ā¤ĢāĨ‹ā¤ŸāĨ‹ ā¤ļāĨ‡ā¤…⤰ ⤕⤰⤪āĨ‡ ā¤Ĩā¤žā¤‚ā¤Ŧā¤ĩā¤žā¤¯ā¤šāĨ‡?", + "stop_photo_sharing_description": "{partner} ā¤¯ā¤žā¤‚ā¤¨ā¤ž ā¤†ā¤¤ā¤ž ⤤āĨā¤Žā¤šāĨ‡ ā¤ĢāĨ‹ā¤ŸāĨ‹ ā¤Ēā¤žā¤šā¤¤ā¤ž ⤝āĨ‡ā¤Ŗā¤žā¤° ā¤¨ā¤žā¤šāĨ€ā¤¤.", + "stop_sharing_photos_with_user": "ā¤¯ā¤ž ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤āĨā¤¯ā¤žā¤¸āĨ‹ā¤Ŧ⤤ ⤤āĨā¤Žā¤šāĨ‡ ā¤ĢāĨ‹ā¤ŸāĨ‹ ā¤ļāĨ‡ā¤…⤰ ⤕⤰⤪āĨ‡ ā¤Ĩā¤žā¤‚ā¤Ŧā¤ĩā¤ž", + "storage": "ā¤¸ā¤‚ā¤šā¤¯ā¤¨ ā¤œā¤žā¤—ā¤ž", + "storage_label": "ā¤¸ā¤‚ā¤šā¤¯ā¤¨ ⤞āĨ‡ā¤Ŧ⤞", + "storage_quota": "ā¤¸ā¤‚ā¤šā¤¯ā¤¨ ⤕āĨ‹ā¤Ÿā¤ž", + "storage_usage": "{available} ā¤ĒāĨˆā¤•āĨ€ {used} ā¤ĩā¤žā¤Ē⤰⤞āĨ‡", + "submit": "ā¤¸ā¤žā¤Ļ⤰ ā¤•ā¤°ā¤ž", + "success": "⤝ā¤ļ⤏āĨā¤ĩāĨ€", + "suggestions": "⤏āĨ‚ā¤šā¤¨ā¤ž", + "sunrise_on_the_beach": "ā¤¸ā¤ŽāĨā¤ĻāĨā¤°ā¤•ā¤ŋā¤¨ā¤žā¤ąāĨā¤¯ā¤žā¤ĩ⤰ ⤏āĨ‚⤰āĨā¤¯āĨ‹ā¤Ļ⤝", + "support": "ā¤¸ā¤šā¤žā¤¯āĨā¤¯", + "support_and_feedback": "ā¤¸ā¤šā¤žā¤¯āĨā¤¯ ⤆⤪ā¤ŋ ⤅⤭ā¤ŋā¤ĒāĨā¤°ā¤žā¤¯", + "support_third_party_description": "⤤āĨā¤Žā¤šāĨ€ Immich ⤏āĨā¤Ĩā¤žā¤Ēā¤¨ā¤ž ⤤āĨƒā¤¤āĨ€ā¤¯-ā¤Ē⤕āĨā¤ˇ ā¤ĒāĨ…⤕āĨ‡ā¤œā¤ĻāĨā¤ĩā¤žā¤°āĨ‡ ā¤Ļā¤ŋ⤞āĨ€ ā¤†ā¤šāĨ‡. ⤤āĨā¤ŽāĨā¤šā¤žā¤˛ā¤ž ⤝āĨ‡ā¤Ŗā¤žā¤ąāĨā¤¯ā¤ž ā¤¸ā¤Žā¤¸āĨā¤¯ā¤ž ⤤āĨā¤¯ā¤ž ā¤ĒāĨ…⤕āĨ‡ā¤œā¤ŽāĨā¤ŗāĨ‡ ⤅⤏āĨ‚ ā¤ļā¤•ā¤¤ā¤žā¤¤; ⤤āĨā¤¯ā¤žā¤ŽāĨā¤ŗāĨ‡ ā¤–ā¤žā¤˛āĨ€ā¤˛ ā¤ĻāĨā¤ĩāĨā¤¯ā¤žā¤‚ā¤šā¤ž ā¤ĩā¤žā¤Ē⤰ ⤕⤰āĨ‚⤍ ⤏⤰āĨā¤ĩā¤ĒāĨā¤°ā¤Ĩā¤Ž ⤤āĨā¤¯ā¤žā¤‚ā¤šāĨā¤¯ā¤žā¤•ā¤ĄāĨ‡ ā¤¸ā¤Žā¤¸āĨā¤¯ā¤ž ⤍āĨ‹ā¤‚ā¤Ļā¤ĩā¤ž.", + "swap_merge_direction": "ā¤Žā¤°āĨā¤œ ā¤Ļā¤ŋā¤ļāĨ‡ā¤šāĨ€ ⤅ā¤Ļā¤˛ā¤žā¤Ŧā¤Ļ⤞ ā¤•ā¤°ā¤ž", + "sync": "ā¤¸ā¤Žā¤•āĨā¤°ā¤Žā¤Ŗ", + "sync_albums": "⤅⤞āĨā¤Ŧā¤Ž ā¤¸ā¤Žā¤•āĨā¤°ā¤Žā¤ŋ⤤ ā¤•ā¤°ā¤ž", + "sync_albums_manual_subtitle": "⤅ā¤Ē⤞āĨ‹ā¤Ą ⤕āĨ‡ā¤˛āĨ‡ā¤˛āĨ‡ ⤏⤰āĨā¤ĩ ā¤ĢāĨ‹ā¤ŸāĨ‹-ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓ ⤍ā¤ŋā¤ĩā¤Ąā¤˛āĨ‡ā¤˛āĨā¤¯ā¤ž ā¤ŦāĨ…⤕⤅ā¤Ē ⤅⤞āĨā¤Ŧā¤Žā¤Žā¤§āĨā¤¯āĨ‡ ā¤¸ā¤Žā¤•āĨā¤°ā¤Žā¤ŋ⤤ ā¤•ā¤°ā¤ž", + "sync_local": "⤏āĨā¤Ĩā¤žā¤¨ā¤ŋ⤕ ā¤¸ā¤Žā¤•āĨā¤°ā¤Žā¤Ŗ", + "sync_remote": "ā¤ĻāĨ‚⤰⤏āĨā¤Ĩ ā¤¸ā¤Žā¤•āĨā¤°ā¤Žā¤Ŗ", + "sync_status": "ā¤¸ā¤Žā¤•āĨā¤°ā¤Žā¤Ŗ ⤏āĨā¤Ĩā¤ŋ⤤āĨ€", + "sync_status_subtitle": "ā¤¸ā¤Žā¤•āĨā¤°ā¤Žā¤Ŗ ā¤ĒāĨā¤°ā¤Ŗā¤žā¤˛āĨ€ ā¤Ēā¤žā¤šā¤ž ⤆⤪ā¤ŋ ā¤ĩāĨā¤¯ā¤ĩ⤏āĨā¤Ĩā¤žā¤Ēā¤ŋ⤤ ā¤•ā¤°ā¤ž", + "sync_upload_album_setting_subtitle": "Immich ā¤ĩ⤰āĨ€ā¤˛ ⤍ā¤ŋā¤ĩā¤Ąā¤˛āĨ‡ā¤˛āĨā¤¯ā¤ž ⤅⤞āĨā¤Ŧā¤Žā¤Žā¤§āĨā¤¯āĨ‡ ⤤āĨā¤Žā¤šāĨ‡ ā¤ĢāĨ‹ā¤ŸāĨ‹ ā¤ĩ ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓ ā¤¤ā¤¯ā¤žā¤° ā¤•ā¤°ā¤ž ⤆⤪ā¤ŋ ⤅ā¤Ē⤞āĨ‹ā¤Ą ā¤•ā¤°ā¤ž", + "tag": "⤟āĨ…⤗", + "tag_assets": "ā¤†ā¤¯ā¤Ÿā¤Žā¤¨ā¤ž ⤟āĨ…⤗ ā¤˛ā¤žā¤ĩā¤ž", + "tag_created": "ā¤¤ā¤¯ā¤žā¤° ⤕āĨ‡ā¤˛āĨ‡ā¤˛ā¤ž ⤟āĨ…⤗: {tag}", + "tag_feature_description": "ā¤¤ā¤žā¤°āĨā¤•ā¤ŋ⤕ ⤟āĨ…⤗ ā¤ĩā¤ŋā¤ˇā¤¯ā¤žā¤‚ā¤¨āĨā¤¸ā¤žā¤° ā¤—ā¤Ÿā¤Ŧā¤ĻāĨā¤§ ā¤ĢāĨ‹ā¤ŸāĨ‹ ā¤ĩ ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓ ā¤ŦāĨā¤°ā¤žā¤‰ā¤ ā¤•ā¤°ā¤ž", + "tag_not_found_question": "⤟āĨ…⤗ ā¤¸ā¤žā¤Ēā¤Ąā¤¤ ā¤¨ā¤žā¤šāĨ€? ⤍ā¤ĩā¤ž ⤟āĨ…⤗ ā¤¤ā¤¯ā¤žā¤° ā¤•ā¤°ā¤ž", + "tag_people": "ā¤ĩāĨā¤¯ā¤•āĨā¤¤āĨ€ā¤‚ā¤¨ā¤ž ⤟āĨ…⤗ ā¤•ā¤°ā¤ž", + "tag_updated": "⤅ā¤ĻāĨā¤¯ā¤¯ā¤žā¤ĩ⤤ ⤟āĨ…⤗: {tag}", + "tagged_assets": "⤟āĨ…⤗ ⤕āĨ‡ā¤˛āĨ‡ā¤˛āĨ‡ {count, plural, one {# ā¤†ā¤¯ā¤Ÿā¤Ž} other {# ā¤†ā¤¯ā¤Ÿā¤Ž}}", + "tags": "⤟āĨ…⤗āĨā¤¸", + "tap_to_run_job": "⤜āĨ‰ā¤Ŧ ā¤šā¤žā¤˛ā¤ĩ⤪āĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ ⤟āĨ…ā¤Ē ā¤•ā¤°ā¤ž", + "template": "⤟āĨ‡ā¤ŽāĨā¤Ē⤞āĨ‡ā¤Ÿ", + "theme": "ā¤ĨāĨ€ā¤Ž", + "theme_selection": "ā¤ĨāĨ€ā¤Ž ⤍ā¤ŋā¤ĩā¤Ą", + "theme_selection_description": "ā¤ŦāĨā¤°ā¤žā¤‰ā¤ā¤°ā¤šāĨā¤¯ā¤ž ⤏ā¤ŋ⤏āĨā¤Ÿā¤Ž ā¤Ē⤏⤂⤤āĨ€ā¤¨āĨā¤¸ā¤žā¤° ā¤ĨāĨ€ā¤Ž ⤆ā¤ĒāĨ‹ā¤†ā¤Ē ā¤˛ā¤žā¤‡ā¤Ÿ/ā¤Ąā¤žā¤°āĨā¤• ā¤•ā¤°ā¤ž", + "theme_setting_asset_list_storage_indicator_title": "⤅āĨ…⤏āĨ‡ā¤Ÿ ā¤Ÿā¤žā¤‡ā¤˛āĨā¤¸ā¤ĩ⤰ ⤏āĨā¤ŸāĨ‹ā¤°āĨ‡ā¤œ ⤍ā¤ŋ⤰āĨā¤ĻāĨ‡ā¤ļ⤕ ā¤Ļā¤žā¤–ā¤ĩā¤ž", + "theme_setting_asset_list_tiles_per_row_title": "ā¤ĒāĨā¤°ā¤¤āĨā¤¯āĨ‡ā¤• ā¤°ā¤žā¤‚ā¤—āĨ‡ā¤¤āĨ€ā¤˛ ⤅āĨ…⤏āĨ‡ā¤ŸāĨā¤¸ā¤šāĨ€ ⤏⤂⤖āĨā¤¯ā¤ž ({count})", + "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_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_title": "ā¤ĨāĨā¤°āĨ€-⤏āĨā¤ŸāĨ‡ā¤œ ⤞āĨ‹ā¤Ąā¤ŋ⤂⤗ ⤏āĨā¤°āĨ‚ ā¤•ā¤°ā¤ž", + "they_will_be_merged_together": "⤤āĨ‡ ā¤ā¤•ā¤¤āĨā¤° ā¤ĩā¤ŋ⤞āĨ€ā¤¨ ⤕āĨ‡ā¤˛āĨ‡ ā¤œā¤žā¤¤āĨ€ā¤˛", + "third_party_resources": "⤤āĨƒā¤¤āĨ€ā¤¯-ā¤Ē⤕āĨā¤ˇ ā¤¸ā¤‚ā¤¸ā¤žā¤§ā¤¨āĨ‡", + "time_based_memories": "ā¤ĩāĨ‡ā¤ŗ-ā¤†ā¤§ā¤žā¤°ā¤ŋ⤤ ā¤ŽāĨ‡ā¤Žā¤°āĨ€ā¤œ", + "timeline": "ā¤Ÿā¤žā¤‡ā¤Žā¤˛ā¤žā¤‡ā¤¨", + "timezone": "ā¤ĩāĨ‡ā¤ŗā¤•āĨā¤ˇāĨ‡ā¤¤āĨā¤°", + "to_archive": "⤆⤰āĨā¤•ā¤žā¤‡ā¤ĩāĨā¤š ā¤•ā¤°ā¤ž", + "to_change_password": "ā¤Ē⤰ā¤ĩ⤞āĨ€ā¤šā¤ž ā¤ļā¤ŦāĨā¤Ļ ā¤Ŧā¤Ļā¤˛ā¤ž", + "to_favorite": "⤆ā¤ĩā¤ĄāĨ€ā¤Žā¤§āĨā¤¯āĨ‡ ⤜āĨ‹ā¤Ąā¤ž", + "to_login": "⤞āĨ‰ā¤— ⤇⤍ ā¤•ā¤°ā¤ž", + "to_multi_select": "ā¤Ŧā¤šāĨ-⤍ā¤ŋā¤ĩā¤Ą ā¤•ā¤°ā¤ž", + "to_parent": "ā¤Ēā¤žā¤˛ā¤•ā¤žā¤•ā¤ĄāĨ‡ ā¤œā¤ž", + "to_select": "⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "to_trash": "ā¤•ā¤šā¤°ā¤žā¤ĒāĨ‡ā¤ŸāĨ€ā¤¤ ā¤Ÿā¤žā¤•ā¤ž", + "toggle_settings": "⤏āĨ‡ā¤Ÿā¤ŋ⤂⤗āĨā¤œ ⤟āĨ‰ā¤—⤞ ā¤•ā¤°ā¤ž", + "total": "ā¤ā¤•āĨ‚⤪", + "total_usage": "ā¤ā¤•āĨ‚⤪ ā¤ĩā¤žā¤Ē⤰", + "trash": "ā¤•ā¤šā¤°ā¤žā¤ĒāĨ‡ā¤ŸāĨ€", + "trash_action_prompt": "{count} ā¤•ā¤šā¤°ā¤žā¤ĒāĨ‡ā¤ŸāĨ€ā¤¤ ā¤šā¤˛ā¤ĩ⤞āĨ‡", + "trash_all": "⤏⤰āĨā¤ĩ ā¤•ā¤šā¤°ā¤žā¤ĒāĨ‡ā¤ŸāĨ€ā¤¤ ā¤Ÿā¤žā¤•ā¤ž", + "trash_count": "ā¤•ā¤šā¤°ā¤žā¤ĒāĨ‡ā¤ŸāĨ€ {count, number}", + "trash_delete_asset": "ā¤•ā¤šā¤°ā¤žā¤ĒāĨ‡ā¤ŸāĨ€ā¤¤ ā¤Ÿā¤žā¤•ā¤ž/⤅āĨ…⤏āĨ‡ā¤Ÿ ā¤šā¤Ÿā¤ĩā¤ž", + "trash_emptied": "ā¤•ā¤šā¤°ā¤žā¤ĒāĨ‡ā¤ŸāĨ€ ⤰ā¤ŋā¤•ā¤žā¤ŽāĨ€ ⤕āĨ‡ā¤˛āĨ€", + "trash_no_results_message": "ā¤•ā¤šā¤°ā¤žā¤ĒāĨ‡ā¤ŸāĨ€ā¤¤ ā¤Ÿā¤žā¤•ā¤˛āĨ‡ā¤˛āĨ‡ ā¤ĢāĨ‹ā¤ŸāĨ‹ ā¤ĩ ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓ ⤝āĨ‡ā¤ĨāĨ‡ ā¤Ļā¤ŋ⤏⤤āĨ€ā¤˛.", + "trash_page_delete_all": "⤏⤰āĨā¤ĩ ā¤šā¤Ÿā¤ĩā¤ž", + "trash_page_empty_trash_dialog_content": "ā¤•ā¤šā¤°ā¤žā¤ĒāĨ‡ā¤ŸāĨ€ ⤰ā¤ŋā¤•ā¤žā¤ŽāĨ€ ā¤•ā¤°ā¤žā¤¯ā¤šāĨ€ ā¤•ā¤ž? ā¤šāĨ‡ ā¤†ā¤¯ā¤Ÿā¤Ž Immich ā¤Žā¤§āĨ‚⤍ ā¤•ā¤žā¤¯ā¤Žā¤šāĨ‡ ā¤šā¤Ÿā¤ĩ⤞āĨ‡ ā¤œā¤žā¤¤āĨ€ā¤˛", + "trash_page_info": "ā¤•ā¤šā¤°ā¤žā¤ĒāĨ‡ā¤ŸāĨ€ā¤¤āĨ€ā¤˛ ā¤†ā¤¯ā¤Ÿā¤Ž {days} ā¤Ļā¤ŋā¤ĩā¤¸ā¤žā¤‚ā¤¨ā¤‚ā¤¤ā¤° ā¤•ā¤žā¤¯ā¤Žā¤šāĨ‡ ā¤šā¤Ÿā¤ĩ⤞āĨ‡ ā¤œā¤žā¤¤āĨ€ā¤˛", + "trash_page_no_assets": "ā¤•ā¤šā¤°ā¤žā¤ĒāĨ‡ā¤ŸāĨ€ā¤¤ ⤕āĨ‹ā¤Ŗā¤¤āĨ‡ā¤šāĨ€ ā¤†ā¤¯ā¤Ÿā¤Ž ā¤¨ā¤žā¤šāĨ€ā¤¤", + "trash_page_restore_all": "⤏⤰āĨā¤ĩ ā¤Ē⤰⤤ ā¤†ā¤Ŗā¤ž", + "trash_page_select_assets_btn": "ā¤†ā¤¯ā¤Ÿā¤Ž ⤍ā¤ŋā¤ĩā¤Ąā¤ž", + "trash_page_title": "ā¤•ā¤šā¤°ā¤žā¤ĒāĨ‡ā¤ŸāĨ€ ({count})", + "trashed_items_will_be_permanently_deleted_after": "ā¤•ā¤šā¤°ā¤žā¤ĒāĨ‡ā¤ŸāĨ€ā¤¤āĨ€ā¤˛ ā¤†ā¤¯ā¤Ÿā¤Ž {days, plural, one {# ā¤Ļā¤ŋā¤ĩā¤¸ā¤žā¤‚ā¤¨ā¤‚ā¤¤ā¤°} other {# ā¤Ļā¤ŋā¤ĩā¤¸ā¤žā¤‚ā¤¨ā¤‚ā¤¤ā¤°}} ā¤•ā¤žā¤¯ā¤Žā¤šāĨ‡ ā¤šā¤Ÿā¤ĩ⤞āĨ‡ ā¤œā¤žā¤¤āĨ€ā¤˛.", + "troubleshoot": "ā¤¸ā¤Žā¤¸āĨā¤¯ā¤ž ⤍ā¤ŋā¤ĩā¤žā¤°ā¤Ŗ", + "type": "ā¤ĒāĨā¤°ā¤•ā¤žā¤°", + "unable_to_change_pin_code": "PIN ⤕āĨ‹ā¤Ą ā¤Ŧā¤Ļā¤˛ā¤¤ā¤ž ⤝āĨ‡ā¤¤ ā¤¨ā¤žā¤šāĨ€", + "unable_to_setup_pin_code": "PIN ⤕āĨ‹ā¤Ą ⤏āĨ‡ā¤Ÿ ⤕⤰āĨ‚ ā¤ļ⤕⤤ ā¤¨ā¤žā¤šāĨ€", + "unarchive": "⤅⤍⤆⤰āĨā¤•ā¤žā¤‡ā¤ĩāĨā¤š ā¤•ā¤°ā¤ž", + "unarchive_action_prompt": "{count} ⤆⤰āĨā¤•ā¤žā¤‡ā¤ĩāĨā¤šā¤Žā¤§āĨ‚⤍ ā¤•ā¤žā¤ĸ⤞āĨ‡", + "unarchived_count": "{count, plural, other {⤅⤍⤆⤰āĨā¤•ā¤žā¤‡ā¤ĩāĨā¤š #}}", + "undo": "ā¤ĒāĨ‚⤰āĨā¤ĩā¤ĩ⤤ ā¤•ā¤°ā¤ž", + "unfavorite": "⤆ā¤ĩā¤ĄāĨ€ā¤¤āĨ‚⤍ ā¤•ā¤žā¤ĸā¤ž", + "unfavorite_action_prompt": "{count} ⤆ā¤ĩā¤ĄāĨ€ā¤¤āĨ‚⤍ ā¤•ā¤žā¤ĸ⤞āĨ‡", + "unhide_person": "ā¤ĩāĨā¤¯ā¤•āĨā¤¤āĨ€ ā¤Ļ⤰āĨā¤ļā¤ĩā¤ž", + "unknown": "ā¤…ā¤œāĨā¤žā¤žā¤¤", + "unknown_country": "ā¤…ā¤œāĨā¤žā¤žā¤¤ ā¤ĻāĨ‡ā¤ļ", + "unknown_year": "ā¤…ā¤œāĨā¤žā¤žā¤¤ ā¤ĩ⤰āĨā¤ˇ", + "unlimited": "ā¤…ā¤Žā¤°āĨā¤¯ā¤žā¤Ļā¤ŋ⤤", + "unlink_motion_video": "ā¤ŽāĨ‹ā¤ļ⤍ ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓ ⤅⤍⤞ā¤ŋ⤂⤕ ā¤•ā¤°ā¤ž", + "unlink_oauth": "OAuth ⤅⤍⤞ā¤ŋ⤂⤕ ā¤•ā¤°ā¤ž", + "unlinked_oauth_account": "OAuth ā¤–ā¤žā¤¤āĨ‡ ⤅⤍⤞ā¤ŋ⤂⤕ ⤕āĨ‡ā¤˛āĨ‡", + "unmute_memories": "ā¤ŽāĨ‡ā¤Žā¤°āĨ€ā¤œ ā¤…ā¤¨ā¤ŽāĨā¤¯āĨ‚ā¤Ÿ ā¤•ā¤°ā¤ž", + "unnamed_album": "ā¤¨ā¤žā¤ĩ ⤍⤏⤞āĨ‡ā¤˛ā¤ž ⤅⤞āĨā¤Ŧā¤Ž", + "unnamed_album_delete_confirmation": "⤤āĨā¤ŽāĨā¤šā¤žā¤˛ā¤ž ā¤šā¤ž ⤅⤞āĨā¤Ŧā¤Ž ā¤–ā¤°ā¤‚ā¤š ā¤šā¤Ÿā¤ĩā¤žā¤¯ā¤šā¤ž ā¤†ā¤šāĨ‡ ā¤•ā¤ž?", + "unnamed_share": "ā¤¨ā¤žā¤ĩ ⤍⤏⤞āĨ‡ā¤˛āĨ‡ ā¤ļāĨ‡ā¤…⤰", + "unsaved_change": "⤍ ā¤¸ā¤žā¤ ā¤ĩ⤞āĨ‡ā¤˛ā¤ž ā¤Ŧā¤Ļ⤞", + "unselect_all": "⤏⤰āĨā¤ĩ ⤍ā¤ŋā¤ĩā¤ĄāĨ€ ⤰ā¤ĻāĨā¤Ļ ā¤•ā¤°ā¤ž", + "unselect_all_duplicates": "⤏⤰āĨā¤ĩ ā¤ĄāĨā¤ĒāĨā¤˛ā¤ŋ⤕āĨ‡ā¤ŸāĨā¤¸ā¤šāĨ€ ⤍ā¤ŋā¤ĩā¤Ą ⤰ā¤ĻāĨā¤Ļ ā¤•ā¤°ā¤ž", + "unselect_all_in": "{group} ā¤Žā¤§āĨ€ā¤˛ ⤏⤰āĨā¤ĩ ⤍ā¤ŋā¤ĩā¤ĄāĨ€ ⤰ā¤ĻāĨā¤Ļ ā¤•ā¤°ā¤ž", + "unstack": "⤏āĨā¤ŸāĨ…⤕ ā¤ĩāĨ‡ā¤—ā¤ŗā¤ž ā¤•ā¤°ā¤ž", + "unstack_action_prompt": "{count} ⤅⤍⤏āĨā¤ŸāĨ…⤕ ⤕āĨ‡ā¤˛āĨ‡", + "unstacked_assets_count": "⤅⤍⤏āĨā¤ŸāĨ…⤕ ⤕āĨ‡ā¤˛āĨ‡ā¤˛āĨ‡ {count, plural, one {# ā¤†ā¤¯ā¤Ÿā¤Ž} other {# ā¤†ā¤¯ā¤Ÿā¤Ž}}", + "untagged": "⤟āĨ…⤗ ⤍⤏⤞āĨ‡ā¤˛āĨ‡", + "up_next": "ā¤ĒāĨā¤ĸāĨ‡", + "update_location_action_prompt": "⤍ā¤ŋā¤ĩā¤Ąā¤˛āĨ‡ā¤˛āĨā¤¯ā¤ž {count} ā¤†ā¤¯ā¤Ÿā¤Žā¤šāĨ‡ ⤏āĨā¤Ĩā¤žā¤¨ ā¤¯ā¤žā¤¨āĨ‡ ⤅ā¤ĻāĨā¤¯ā¤¯ā¤žā¤ĩ⤤ ā¤•ā¤°ā¤ž:", + "updated_at": "⤅ā¤ĻāĨā¤¯ā¤¯ā¤žā¤ĩ⤤ ⤕āĨ‡ā¤˛āĨ‡", + "updated_password": "ā¤Ē⤰ā¤ĩ⤞āĨ€ā¤šā¤ž ā¤ļā¤ŦāĨā¤Ļ ⤅ā¤ĻāĨā¤¯ā¤¯ā¤žā¤ĩ⤤ ⤕āĨ‡ā¤˛ā¤ž", + "upload": "⤅ā¤Ē⤞āĨ‹ā¤Ą", + "upload_action_prompt": "⤅ā¤Ē⤞āĨ‹ā¤Ąā¤¸ā¤žā¤ āĨ€ {count} ā¤°ā¤žā¤‚ā¤—āĨ‡ā¤¤", + "upload_concurrency": "⤅ā¤Ē⤞āĨ‹ā¤Ą ā¤¸ā¤Žā¤žā¤‚ā¤¤ā¤°ā¤¤ā¤ž", + "upload_details": "⤅ā¤Ē⤞āĨ‹ā¤Ą ⤤ā¤Ēā¤ļāĨ€ā¤˛", + "upload_dialog_info": "⤍ā¤ŋā¤ĩā¤Ąā¤˛āĨ‡ā¤˛āĨ‡ ā¤†ā¤¯ā¤Ÿā¤Ž ⤏⤰āĨā¤ĩāĨā¤šā¤°ā¤ĩ⤰ ā¤ŦāĨ…⤕⤅ā¤Ē ā¤•ā¤°ā¤žā¤¯ā¤šāĨ‡ ā¤•ā¤ž?", + "upload_dialog_title": "⤅āĨ…⤏āĨ‡ā¤Ÿ ⤅ā¤Ē⤞āĨ‹ā¤Ą ā¤•ā¤°ā¤ž", + "upload_errors": "⤅ā¤Ē⤞āĨ‹ā¤Ą ā¤ĒāĨ‚⤰āĨā¤Ŗ ā¤ā¤žā¤˛āĨ‡; {count, plural, one {# ⤤āĨā¤°āĨā¤ŸāĨ€} other {# ⤤āĨā¤°āĨā¤ŸāĨ€}} ⤆ā¤ĸ⤺⤞āĨā¤¯ā¤ž. ⤍ā¤ĩāĨ€ā¤¨ ⤅ā¤Ē⤞āĨ‹ā¤Ą ā¤†ā¤¯ā¤Ÿā¤Ž ā¤Ēā¤žā¤šā¤ŖāĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ ā¤ĒāĨƒā¤ˇāĨā¤  ⤰āĨ€ā¤ĢāĨā¤°āĨ‡ā¤ļ ā¤•ā¤°ā¤ž.", + "upload_finished": "⤅ā¤Ē⤞āĨ‹ā¤Ą ā¤ĒāĨ‚⤰āĨā¤Ŗ", + "upload_progress": "⤉⤰āĨā¤ĩ⤰ā¤ŋ⤤ {remaining, number} — ā¤ĒāĨā¤°ā¤•āĨā¤°ā¤ŋā¤¯ā¤ž ā¤ā¤žā¤˛āĨ‡ā¤˛āĨ‡ {processed, number}/{total, number}", + "upload_skipped_duplicates": "ā¤ĩ⤗⤺⤞āĨ‡ {count, plural, one {# ā¤ĄāĨā¤ĒāĨā¤˛ā¤ŋ⤕āĨ‡ā¤Ÿ ā¤†ā¤¯ā¤Ÿā¤Ž} other {# ā¤ĄāĨā¤ĒāĨā¤˛ā¤ŋ⤕āĨ‡ā¤Ÿ ā¤†ā¤¯ā¤Ÿā¤Ž}}", + "upload_status_duplicates": "ā¤ĄāĨā¤ĒāĨā¤˛ā¤ŋ⤕āĨ‡ā¤Ÿ", + "upload_status_errors": "⤤āĨā¤°āĨā¤ŸāĨ€", + "upload_status_uploaded": "⤅ā¤Ē⤞āĨ‹ā¤Ą ā¤ā¤žā¤˛āĨ‡", + "upload_success": "⤅ā¤Ē⤞āĨ‹ā¤Ą ⤝ā¤ļ⤏āĨā¤ĩāĨ€. ⤍ā¤ĩāĨ€ā¤¨ ⤅ā¤Ē⤞āĨ‹ā¤Ą ā¤†ā¤¯ā¤Ÿā¤Ž ā¤Ļā¤ŋ⤏⤪āĨā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ ā¤ĒāĨƒā¤ˇāĨā¤  ⤰āĨ€ā¤ĢāĨā¤°āĨ‡ā¤ļ ā¤•ā¤°ā¤ž.", + "upload_to_immich": "Immich ā¤ĩ⤰ ⤅ā¤Ē⤞āĨ‹ā¤Ą ā¤•ā¤°ā¤ž ({count})", + "uploading": "⤅ā¤Ē⤞āĨ‹ā¤Ą ā¤šāĨ‹ā¤¤ ā¤†ā¤šāĨ‡", + "uploading_media": "ā¤Žā¤žā¤§āĨā¤¯ā¤ŽāĨ‡ ⤅ā¤Ē⤞āĨ‹ā¤Ą ā¤šāĨ‹ā¤¤ ā¤†ā¤šāĨ‡ā¤¤", + "url": "URL", + "usage": "ā¤ĩā¤žā¤Ē⤰", + "use_biometric": "ā¤Ŧā¤žā¤¯āĨ‹ā¤ŽāĨ‡ā¤ŸāĨā¤°ā¤ŋ⤕ ā¤ĩā¤žā¤Ēā¤°ā¤ž", + "use_current_connection": "⤏⤧āĨā¤¯ā¤žā¤šāĨ‡ ⤕⤍āĨ‡ā¤•āĨā¤ļ⤍ ā¤ĩā¤žā¤Ēā¤°ā¤ž", + "use_custom_date_range": "ā¤¯ā¤žā¤ā¤ĩ⤜āĨ€ ā¤¸ā¤žā¤¨āĨā¤•āĨ‚⤞ ā¤Ļā¤ŋā¤¨ā¤žā¤‚ā¤• ā¤ļāĨā¤°āĨ‡ā¤ŖāĨ€ ā¤ĩā¤žā¤Ēā¤°ā¤ž", + "user": "ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤ā¤ž", + "user_has_been_deleted": "ā¤šā¤ž ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤ā¤ž ā¤šā¤Ÿā¤ĩā¤ŋā¤˛ā¤ž ⤗āĨ‡ā¤˛ā¤ž ā¤†ā¤šāĨ‡.", + "user_id": "ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤ā¤ž ā¤†ā¤¯ā¤ĄāĨ€", + "user_liked": "{user} ā¤¯ā¤žā¤‚ā¤¨ā¤ž {type, select, photo {ā¤šā¤ž ā¤ĢāĨ‹ā¤ŸāĨ‹} video {ā¤šā¤ž ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓} asset {ā¤šā¤ž ā¤†ā¤¯ā¤Ÿā¤Ž} other {ā¤šāĨ‡}} ⤆ā¤ĩā¤Ąā¤˛āĨ‡", + "user_pin_code_settings": "PIN ⤕āĨ‹ā¤Ą", + "user_pin_code_settings_description": "⤤āĨā¤Žā¤šā¤ž PIN ⤕āĨ‹ā¤Ą ā¤ĩāĨā¤¯ā¤ĩ⤏āĨā¤Ĩā¤žā¤Ēā¤ŋ⤤ ā¤•ā¤°ā¤ž", + "user_privacy": "ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤ā¤ž ⤗āĨ‹ā¤Ē⤍āĨ€ā¤¯ā¤¤ā¤ž", + "user_purchase_settings": "⤖⤰āĨ‡ā¤ĻāĨ€", + "user_purchase_settings_description": "⤤āĨā¤Žā¤šāĨ€ ⤖⤰āĨ‡ā¤ĻāĨ€ ā¤ĩāĨā¤¯ā¤ĩ⤏āĨā¤Ĩā¤žā¤Ēā¤ŋ⤤ ā¤•ā¤°ā¤ž", + "user_role_set": "{user} ā¤¯ā¤žā¤‚ā¤¨ā¤ž {role} ā¤ŽāĨā¤šā¤ŖāĨ‚⤍ ⤏āĨ‡ā¤Ÿ ā¤•ā¤°ā¤ž", + "user_usage_detail": "ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤āĨā¤¯ā¤žā¤šāĨā¤¯ā¤ž ā¤ĩā¤žā¤Ēā¤°ā¤žā¤šā¤ž ⤤ā¤Ēā¤ļāĨ€ā¤˛", + "user_usage_stats": "ā¤–ā¤žā¤¤āĨā¤¯ā¤žā¤šāĨā¤¯ā¤ž ā¤ĩā¤žā¤Ēā¤°ā¤žā¤šāĨā¤¯ā¤ž ā¤¸ā¤žā¤‚ā¤–āĨā¤¯ā¤ŋ⤕āĨ€", + "user_usage_stats_description": "ā¤–ā¤žā¤¤āĨā¤¯ā¤žā¤šāĨā¤¯ā¤ž ā¤ĩā¤žā¤Ēā¤°ā¤žā¤šāĨā¤¯ā¤ž ā¤¸ā¤žā¤‚ā¤–āĨā¤¯ā¤ŋ⤕āĨ€ ā¤Ēā¤šā¤ž", + "username": "ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤ā¤žā¤¨ā¤žā¤ĩ", + "users": "ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤āĨ‡", + "users_added_to_album_count": "⤅⤞āĨā¤Ŧā¤Žā¤Žā¤§āĨā¤¯āĨ‡ {count, plural, one {# ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤ā¤ž ⤜āĨ‹ā¤Ąā¤˛ā¤ž} other {# ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤āĨ‡ ⤜āĨ‹ā¤Ąā¤˛āĨ‡}}", + "utilities": "⤉ā¤Ē⤝āĨā¤•āĨā¤¤ā¤¤ā¤ž", + "validate": "⤤ā¤Ēā¤žā¤¸ā¤ž", + "validate_endpoint_error": "⤕āĨƒā¤Ēā¤¯ā¤ž ā¤ĩāĨˆā¤§ URL ā¤ĒāĨā¤°ā¤ĩā¤ŋ⤎āĨā¤Ÿ ā¤•ā¤°ā¤ž", + "variables": "⤚⤞", + "version": "⤆ā¤ĩāĨƒā¤¤āĨā¤¤āĨ€", + "version_announcement_closing": "⤤āĨā¤Žā¤šā¤ž ā¤Žā¤ŋ⤤āĨā¤°, ā¤…â€āĨ…⤞āĨ‡ā¤•āĨā¤¸", + "version_announcement_message": "ā¤¨ā¤Žā¤¸āĨā¤•ā¤žā¤°! Immich ⤚āĨ€ ⤍ā¤ĩāĨ€ ⤆ā¤ĩāĨƒā¤¤āĨā¤¤āĨ€ ⤉ā¤Ē⤞ā¤ŦāĨā¤§ ā¤†ā¤šāĨ‡. ⤤āĨā¤Žā¤šāĨ€ ā¤¸ā¤‚ā¤°ā¤šā¤¨ā¤ž ⤅ā¤ĻāĨā¤¯ā¤¯ā¤žā¤ĩ⤤ ⤆⤪ā¤ŋ ā¤Ŧā¤ŋ⤍⤚āĨ‚⤕ ā¤°ā¤žā¤šā¤žā¤ĩāĨ€ ā¤¯ā¤žā¤¸ā¤žā¤ āĨ€ ⤕āĨƒā¤Ēā¤¯ā¤ž ā¤•ā¤žā¤šāĨ€ ā¤ĩāĨ‡ā¤ŗ ā¤•ā¤žā¤ĸāĨ‚⤍ ⤰ā¤ŋ⤞āĨ€ā¤œ ⤍āĨ‹ā¤ŸāĨā¤¸ ā¤ĩā¤žā¤šā¤ž, ā¤ĩā¤ŋā¤ļāĨ‡ā¤ˇā¤¤ā¤ƒ ⤤āĨā¤ŽāĨā¤šāĨ€ WatchTower ⤕ā¤ŋ⤂ā¤ĩā¤ž ⤅ā¤ĻāĨā¤¯ā¤¯ā¤žā¤ĩ⤤ ā¤ĒāĨā¤°ā¤•āĨā¤°ā¤ŋā¤¯ā¤ž ⤏āĨā¤ĩā¤¯ā¤‚ā¤šā¤˛ā¤ŋ⤤ā¤Ē⤪āĨ‡ ā¤šā¤žā¤¤ā¤žā¤ŗā¤Ŗā¤žā¤°āĨ€ ⤕āĨ‹ā¤Ŗā¤¤āĨ€ā¤šāĨ€ ā¤ĩāĨā¤¯ā¤ĩ⤏āĨā¤Ĩā¤ž ā¤ĩā¤žā¤Ē⤰⤤ ā¤…ā¤¸ā¤žā¤˛ ⤤⤰.", + "version_history": "⤆ā¤ĩāĨƒā¤¤āĨā¤¤āĨ€ ⤇⤤ā¤ŋā¤šā¤žā¤¸", + "version_history_item": "{date} ⤰āĨ‹ā¤œāĨ€ {version} ⤏āĨā¤Ĩā¤žā¤Ēā¤ŋ⤤ ⤕āĨ‡ā¤˛āĨ€", + "video": "ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓", + "video_hover_setting": "ā¤šā¤žā¤ĩ⤰ ⤕āĨ‡ā¤˛āĨā¤¯ā¤žā¤ĩ⤰ ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓ ā¤Ĩ⤂ā¤Ŧ⤍āĨ‡ā¤˛ ā¤ĒāĨā¤˛āĨ‡ ā¤•ā¤°ā¤ž", + "video_hover_setting_description": "ā¤†ā¤¯ā¤Ÿā¤Žā¤ĩ⤰ ā¤Žā¤žā¤Šā¤¸ ⤍āĨ‡ā¤˛āĨā¤¯ā¤žā¤ĩ⤰ ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓ ā¤Ĩ⤂ā¤Ŧ⤍āĨ‡ā¤˛ ā¤ĒāĨā¤˛āĨ‡ ā¤šāĨ‹ā¤ˆā¤˛. ā¤Ē⤰āĨā¤¯ā¤žā¤¯ ā¤Ŧ⤂ā¤Ļ ā¤…ā¤¸ā¤˛ā¤ž ⤤⤰āĨ€ ā¤ĒāĨā¤˛āĨ‡ ⤚ā¤ŋ⤍āĨā¤šā¤žā¤ĩ⤰ ā¤šā¤žā¤ĩ⤰ ⤕āĨ‡ā¤˛āĨā¤¯ā¤žā¤¸ ā¤ĒāĨā¤˛āĨ‡ā¤ŦāĨ…⤕ ⤏āĨā¤°āĨ‚ ā¤•ā¤°ā¤¤ā¤ž ⤝āĨ‡ā¤ˆā¤˛.", + "videos": "ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓", + "videos_count": "{count, plural, one {# ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓} other {# ā¤ĩāĨā¤šā¤ŋā¤Ąā¤ŋ⤓}}", + "view": "ā¤Ēā¤šā¤ž", + "view_album": "⤅⤞āĨā¤Ŧā¤Ž ā¤Ēā¤šā¤ž", + "view_all": "⤏⤰āĨā¤ĩ ā¤Ēā¤šā¤ž", + "view_all_users": "⤏⤰āĨā¤ĩ ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤āĨ‡ ā¤Ēā¤šā¤ž", + "view_details": "⤤ā¤Ēā¤ļāĨ€ā¤˛ ā¤Ēā¤šā¤ž", + "view_in_timeline": "ā¤Ÿā¤žā¤‡ā¤Žā¤˛ā¤žā¤‡ā¤¨ā¤Žā¤§āĨā¤¯āĨ‡ ā¤Ēā¤šā¤ž", + "view_link": "ā¤ĻāĨā¤ĩā¤ž ā¤Ēā¤šā¤ž", + "view_links": "ā¤ĻāĨā¤ĩāĨ‡ ā¤Ēā¤šā¤ž", + "view_name": "ā¤Ēā¤šā¤ž", + "view_next_asset": "ā¤ĒāĨā¤ĸāĨ€ā¤˛ ā¤†ā¤¯ā¤Ÿā¤Ž ā¤Ēā¤šā¤ž", + "view_previous_asset": "ā¤Žā¤žā¤—āĨ€ā¤˛ ā¤†ā¤¯ā¤Ÿā¤Ž ā¤Ēā¤šā¤ž", + "view_qr_code": "QR ⤕āĨ‹ā¤Ą ā¤Ēā¤šā¤ž", + "view_similar_photos": "ā¤¸ā¤Žā¤žā¤¨ ā¤ĢāĨ‹ā¤ŸāĨ‹ ā¤Ēā¤šā¤ž", + "view_stack": "⤏āĨā¤ŸāĨ…⤕ ā¤Ēā¤šā¤ž", + "view_user": "ā¤ĩā¤žā¤Ē⤰⤕⤰āĨā¤¤ā¤ž ā¤Ēā¤šā¤ž", + "viewer_remove_from_stack": "⤏āĨā¤ŸāĨ…ā¤•ā¤Žā¤§āĨ‚⤍ ā¤•ā¤žā¤ĸā¤ž", + "viewer_stack_use_as_main_asset": "ā¤ŽāĨā¤–āĨā¤¯ ā¤†ā¤¯ā¤Ÿā¤Ž ā¤ŽāĨā¤šā¤ŖāĨ‚⤍ ā¤ĩā¤žā¤Ēā¤°ā¤ž", + "viewer_unstack": "⤏āĨā¤ŸāĨ…⤕ ā¤ĩāĨ‡ā¤—ā¤ŗā¤ž ā¤•ā¤°ā¤ž", + "visibility_changed": "ā¤ĻāĨƒā¤ļāĨā¤¯ā¤¤ā¤ž {count, plural, one {# ā¤ĩāĨā¤¯ā¤•āĨā¤¤āĨ€ā¤¸ā¤žā¤ āĨ€ ā¤Ŧā¤Ļ⤞⤞āĨ€} other {# ā¤ĩāĨā¤¯ā¤•āĨā¤¤āĨ€ā¤‚ā¤¸ā¤žā¤ āĨ€ ā¤Ŧā¤Ļ⤞⤞āĨ€}}", "waiting": "ā¤ĒāĨā¤°ā¤¤āĨ€ā¤•āĨā¤ˇāĨ‡ā¤¤", "warning": "⤚āĨ‡ā¤¤ā¤žā¤ĩ⤪āĨ€", "week": "⤆⤠ā¤ĩā¤Ąā¤ž", @@ -1066,5 +1848,6 @@ "year": "ā¤ĩ⤰āĨā¤ˇ", "yes": "ā¤šāĨ‹", "you_dont_have_any_shared_links": "⤆ā¤Ē⤞āĨā¤¯ā¤žā¤•ā¤ĄāĨ‡ ⤕āĨ‹ā¤Ŗā¤¤āĨ‡ā¤šāĨ€ ā¤¸ā¤žā¤Žā¤žā¤¯ā¤ŋ⤕ ā¤ĻāĨā¤ĩāĨ‡ ā¤¨ā¤žā¤šāĨ€ā¤¤", - "zoom_image": "ā¤ĒāĨā¤°ā¤¤ā¤ŋā¤Žā¤ž ā¤āĨ‚ā¤Ž ā¤•ā¤°ā¤ž" + "zoom_image": "ā¤ĒāĨā¤°ā¤¤ā¤ŋā¤Žā¤ž ā¤āĨ‚ā¤Ž ā¤•ā¤°ā¤ž", + "zoom_to_bounds": "⤏āĨ€ā¤ŽāĨ‡ā¤Ē⤰āĨā¤¯ā¤‚⤤ ā¤āĨ‚ā¤Ž ā¤•ā¤°ā¤ž" } diff --git a/i18n/ms.json b/i18n/ms.json index e7e0432a4c..c72b1ff688 100644 --- a/i18n/ms.json +++ b/i18n/ms.json @@ -14,6 +14,7 @@ "add_a_location": "Tambah lokasi", "add_a_name": "Tambah nama", "add_a_title": "Tambah tajuk", + "add_birthday": "Tambah hari jadi", "add_endpoint": "Tambah titik akhir", "add_exclusion_pattern": "Tambahkan corak pengecualian", "add_import_path": "Tambahkan laluan import", @@ -27,6 +28,8 @@ "add_to_album": "Tambah ke album", "add_to_album_bottom_sheet_added": "Dimasukkan ke {album}", "add_to_album_bottom_sheet_already_exists": "Sudah ada di {album}", + "add_to_albums": "Tambah pada album", + "add_to_albums_count": "Tambah pada album ({count})", "add_to_shared_album": "Tambah ke album yang dikongsi", "add_url": "Tambah URL", "added_to_archive": "Tambah ke arkib", @@ -44,6 +47,9 @@ "backup_database": "Buat Salinan Pangkalan Data", "backup_database_enable_description": "Dayakan salinan pangkalan data", "backup_keep_last_amount": "Jumlah salinan pangkalan data sebelumnya untuk disimpan", + "backup_onboarding_1_description": "salinan luar tapak di awan atau di lokasi fizikal lain", + "backup_onboarding_2_description": "salinan tempatan pada peranti yang berbeza. Ini termasuk fail utama dan sandaran fail tersebut secara setempat.", + "backup_onboarding_3_description": "jumlah salinan data anda, termasuk fail asal. Ini termasuk 1 salinan luar tapak dan 2 salinan tempatan.", "backup_settings": "Tetapan Salinan Pangkalan Data", "backup_settings_description": "Urus tetapan salinan pangkalan data.", "cleared_jobs": "Kerja telah dibersihkan untuk: {job}", @@ -373,8 +379,6 @@ "admin_password": "Kata laluan Pentadbir", "administration": "Pentadbiran", "advanced": "Lanjutan", - "advanced_settings_beta_timeline_subtitle": "Cuba pengalaman aplikasi baharu", - "advanced_settings_beta_timeline_title": "Garis masa beta", "advanced_settings_enable_alternate_media_filter_subtitle": "Gunakan pilihan ini untuk menapis media semasa penyegerakan berdasarkan kriteria alternatif. Hanya cuba jika anda menghadapi masalah dengan aplikasi mengesan semua album.", "advanced_settings_enable_alternate_media_filter_title": "[EKSPERIMENTAL] Gunakan penapis penyelarasan album peranti alternatif", "advanced_settings_log_level_title": "Tahap log: {level}", diff --git a/i18n/nb_NO.json b/i18n/nb_NO.json index fe676921c3..75429712d5 100644 --- a/i18n/nb_NO.json +++ b/i18n/nb_NO.json @@ -23,23 +23,25 @@ "add_partner": "Legg til partner", "add_path": "Legg til sti", "add_photos": "Legg til bilder", - "add_tag": "Legg til tagg", + "add_tag": "Legg til merkelapp", "add_to": "Legg til iâ€Ļ", "add_to_album": "Legg til album", "add_to_album_bottom_sheet_added": "Lagt til i {album}", "add_to_album_bottom_sheet_already_exists": "Allerede i {album}", + "add_to_album_bottom_sheet_some_local_assets": "Noen lokale elementer kunne ikke legges til i albumet", "add_to_album_toggle": "Avhuking for {album}", "add_to_albums": "Legg til i album", "add_to_albums_count": "Legg til i albumer ({count})", "add_to_shared_album": "Legg til delt album", + "add_upload_to_stack": "Legg til opplasting i stakken", "add_url": "Legg til URL", - "added_to_archive": "Lagt til i arkiv", - "added_to_favorites": "Lagt til i favoritter", + "added_to_archive": "Lagt til i arkivet", + "added_to_favorites": "Lagt til favoritter", "added_to_favorites_count": "Lagt til {count, number} i favoritter", "admin": { "add_exclusion_pattern_description": "Legg til ekskluderingsmønstre. Globbing med *, ** og ? støttes. For ÃĨ ignorere alle filer i en hvilken som helst mappe som heter \"Raw\", bruk \"**/Raw/**\". For ÃĨ ignorere alle filer som slutter pÃĨ \".tif\", bruk \"**/*.tif\". For ÃĨ ignorere en absolutt filplassering, bruk \"/filsti/til/ignorer/**\".", "admin_user": "Administrasjonsbruker", - "asset_offline_description": "Dette eksterne biblioteksobjektet finnes ikke lenger pÃĨ disk og har blitt flyttet til papirkurven. Hvis filen ble flyttet innad i biblioteket, se etter det tilsvarende objektet i tidslinjen din. For ÃĨ gjenopprette objektet, vennligst sørg for at filstien under er tilgjengelig for Immich og skann biblioteket.", + "asset_offline_description": "Dette eksterne bibliotekselementet finnes ikke lenger pÃĨ disk og har blitt flyttet til papirkurven. Hvis filen ble flyttet innad i biblioteket, se etter det tilsvarende elementet i tidslinjen din. For ÃĨ gjenopprette elementet, vennligst sørg for at filstien under er tilgjengelig for Immich og skann biblioteket.", "authentication_settings": "Godkjenningsinnstillinger", "authentication_settings_description": "Administrer passord, OAuth, og andre innstillinger for autentisering", "authentication_settings_disable_all": "Er du sikker pÃĨ at du ønsker ÃĨ deaktivere alle innloggingsmetoder? Innlogging vil bli fullstendig deaktivert.", @@ -59,12 +61,12 @@ "backup_settings_description": "HÃĨndter innstillinger for database-dump.", "cleared_jobs": "Ryddet opp jobber for: {job}", "config_set_by_file": "Konfigurasjonen er for øyeblikket satt av en konfigurasjonsfil", - "confirm_delete_library": "Er du sikker pÃĨ at du vil slette biblioteket {library}?", - "confirm_delete_library_assets": "Er du sikker pÃĨ at du vil slette dette biblioteket? Dette vil slette alt innhold ({count, plural, one {# objekt} other {# objekter}}) og tilhørende eiendeler fra Immich og kan ikke angres. Filene vil forbli pÃĨ disken.", + "confirm_delete_library": "Vil du virkelig slette biblioteket {library}?", + "confirm_delete_library_assets": "Vil du virkelig slette dette biblioteket? Dette vil slette alt innhold ({count, plural, one {# element} other {# elementer}}) og tilhørende eiendeler fra Immich og kan ikke angres. Filene vil forbli pÃĨ disken.", "confirm_email_below": "For ÃĨ bekrefte, skriv inn \"{email}\" nedenfor", - "confirm_reprocess_all_faces": "Er du sikker pÃĨ at du vil behandle alle ansikter pÃĨ nytt? Dette vil ogsÃĨ fjerne navngitte personer.", - "confirm_user_password_reset": "Er du sikker pÃĨ at du vil tilbakestille passordet til {user}?", - "confirm_user_pin_code_reset": "Er du sikker pÃĨ at du vil tilbakestille PIN-koden til {user} ?", + "confirm_reprocess_all_faces": "Vil du virkelig behandle alle ansikter pÃĨ nytt? Dette vil ogsÃĨ fjerne navngitte personer.", + "confirm_user_password_reset": "Vil du virkelig tilbakestille passordet til {user}?", + "confirm_user_pin_code_reset": "Vil du virkelig tilbakestille PIN-koden til {user} ?", "create_job": "Lag jobb", "cron_expression": "Cron uttrykk", "cron_expression_description": "Still inn skanneintervallet med cron-formatet. For mer informasjon henvises til f.eks. Crontab Guru", @@ -122,7 +124,14 @@ "library_watching_settings_description": "Se automatisk etter endrede filer", "logging_enable_description": "Aktiver logging", "logging_level_description": "Hvis aktivert, hvilket loggnivÃĨ som skal brukes.", - "logging_settings": "Logger", + "logging_settings": "Loggføring", + "machine_learning_availability_checks": "Tilgjengelighetssjekk", + "machine_learning_availability_checks_description": "Automatisk oppdag og velg tilgjengelige maskinlÃĻring-servere", + "machine_learning_availability_checks_enabled": "Aktiver tilgjengelighetssjekk", + "machine_learning_availability_checks_interval": "Sjekkintervall", + "machine_learning_availability_checks_interval_description": "Interval i millisekunder mellom tilgjengelighetssjekk", + "machine_learning_availability_checks_timeout": "Forespørselstimeout", + "machine_learning_availability_checks_timeout_description": "Tidsavbrudd i millisekunder for tilgjengelighetssjekk", "machine_learning_clip_model": "Clip-modell", "machine_learning_clip_model_description": "Navnet pÃĨ en CLIP-modell finnes her. Merk at du mÃĨ kjøre 'Smart Søk'-jobben pÃĨ nytt for alle bilder etter at du har endret modell.", "machine_learning_duplicate_detection": "Duplikatsøk", @@ -182,9 +191,9 @@ "nightly_tasks_database_cleanup_setting": "Opprydningsjobber for databasen", "nightly_tasks_database_cleanup_setting_description": "Rydder opp i gamle, utgÃĨtte data fra databasen", "nightly_tasks_generate_memories_setting": "Genererer minner", - "nightly_tasks_generate_memories_setting_description": "Generer nye minner fra objekter", + "nightly_tasks_generate_memories_setting_description": "Generer nye minner fra elementer", "nightly_tasks_missing_thumbnails_setting": "Generer manglende miniatyrbilder", - "nightly_tasks_missing_thumbnails_setting_description": "Legg til objekter i kø som mangler miniatyrbilder for generering", + "nightly_tasks_missing_thumbnails_setting_description": "Legg til elementer i kø som mangler miniatyrbilder for generering", "nightly_tasks_settings": "Innstillinger for nattjobber", "nightly_tasks_settings_description": "Endre pÃĨ nattjobber", "nightly_tasks_start_time_setting": "Starttid", @@ -268,7 +277,7 @@ "storage_template_hash_verification_enabled_description": "Aktiver hasjverifisering. Ikke deaktiver dette med mindre du er sikker pÃĨ konsekvensene", "storage_template_migration": "Implementer lagringsmal", "storage_template_migration_description": "Bruk gjeldende {template} pÃĨ tidligere opplastede bilder", - "storage_template_migration_info": "Lagringsmalen vil endre filtypen til smÃĨ bokstaver. Malendringer vil kun gjelde nye objekter. For ÃĨ anvende malen pÃĨ tidligere opplastede objekter, kjør {job}.", + "storage_template_migration_info": "Lagringsmalen vil endre filtypen til smÃĨ bokstaver. Malendringer vil kun gjelde nye elementer. For ÃĨ anvende malen pÃĨ tidligere opplastede elementer, kjør {job}.", "storage_template_migration_job": "Migreringsjobb for lagringsmal", "storage_template_more_details": "For mer informasjon om denne funksjonen, se lagringsmalen og dens konsekvenser", "storage_template_onboarding_description_v2": "NÃĨr aktivert vil denne funksjonen automatisk organisere filer basert pÃĨ en brukerdefinert mal. For mer informasjon, se denne linken dokumentasjon.", @@ -360,7 +369,7 @@ "trash_settings_description": "Administrer papirkurv-innstillinger", "unlink_all_oauth_accounts": "Koble fra alle OAuth-kontoer", "unlink_all_oauth_accounts_description": "Husk ÃĨ koble fra alle OAuth-kontoer før du migrerer til ny leverandør.", - "unlink_all_oauth_accounts_prompt": "Er du sikker pÃĨ at du vil koble fra alle OAuth-kontoer? Dette vil nullstille OAuth ID for hver bruker, og kan ikke angres.", + "unlink_all_oauth_accounts_prompt": "Vil du virkelig koble fra alle OAuth-kontoer? Dette vil nullstille OAuth ID for hver bruker, og kan ikke angres.", "user_cleanup_job": "Bruker opprydning", "user_delete_delay": "{user}s konto og elementer vil legges i kø for permanent sletting om {delay, plural, one {# dag} other {# dager}}.", "user_delete_delay_settings": "Sletteforsinkelse", @@ -383,12 +392,10 @@ "video_conversion_job": "Transkod videoer", "video_conversion_job_description": "Konverter videoer for bedre kompatibilitet med nettlesere og enheter" }, - "admin_email": "Administrator E-post", - "admin_password": "Administrator Passord", + "admin_email": "Administrator e-post", + "admin_password": "Administratorpassord", "administration": "Administrasjon", "advanced": "Avansert", - "advanced_settings_beta_timeline_subtitle": "Prøv den nye app opplevelsen", - "advanced_settings_beta_timeline_title": "Beta tidslinje", "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ÃĨ: {level}", @@ -408,32 +415,33 @@ "age_months": "Alder {months, plural, one {# mÃĨned} other {# mÃĨneder}}", "age_year_months": "Alder 1 ÃĨr, {months, plural, one {# mÃĨned} other {# mÃĨneder}}", "age_years": "{years, plural, other {Alder #}}", - "album_added": "Album lagt til", + "album_added": "Album opprettet", "album_added_notification_setting_description": "Motta en e-postvarsling nÃĨr du legges til i et delt album", "album_cover_updated": "Albumomslag oppdatert", - "album_delete_confirmation": "Er du sikker pÃĨ at du vil slette albumet {album}?", + "album_delete_confirmation": "Vil du virkelig slette albumet {album}?", "album_delete_confirmation_description": "Hvis dette albumet deles, vil andre brukere miste tilgangen til dette.", "album_deleted": "Album slettet", "album_info_card_backup_album_excluded": "EKSKLUDERT", "album_info_card_backup_album_included": "INKLUDERT", "album_info_updated": "Albuminformasjon oppdatert", "album_leave": "Forlate album?", - "album_leave_confirmation": "Er du sikker pÃĨ at du vil forlate {album}?", - "album_name": "Album Navn", + "album_leave_confirmation": "Vil du virkelig forlate {album}?", + "album_name": "Albumnavn", "album_options": "Albumalternativer", "album_remove_user": "Fjerne bruker?", - "album_remove_user_confirmation": "Er du sikker pÃĨ at du vil fjerne {user}?", + "album_remove_user_confirmation": "Vil du virkelig fjerne {user}?", "album_search_not_found": "Ingen album ble funnet som traff ditt søk", - "album_share_no_users": "Ser ut til at du har delt dette albumet med alle brukere, eller du ikke har noen brukere ÃĨ dele det med.", + "album_share_no_users": "Dette albumet er allerede delt med du har delt dette albumet med alle brukere, eller du ikke har noen brukere ÃĨ dele det med.", + "album_summary": "Oppsummering av album", "album_updated": "Album oppdatert", "album_updated_setting_description": "Motta e-postvarsling nÃĨr et delt album fÃĨr nye filer", "album_user_left": "Forlot {album}", "album_user_removed": "Fjernet {user}", - "album_viewer_appbar_delete_confirm": "Er du sikker pÃĨ at du vil slette dette albumet fra kontoen din?", + "album_viewer_appbar_delete_confirm": "Vil du virkelig slette dette albumet fra kontoen din?", "album_viewer_appbar_share_err_delete": "Kunne ikke slette albumet", "album_viewer_appbar_share_err_leave": "Kunne ikke forlate albumet", - "album_viewer_appbar_share_err_remove": "Det oppstod et problem ved fjerning av objekter fra albumet", - "album_viewer_appbar_share_err_title": "Feilet ved endring av albumtittel", + "album_viewer_appbar_share_err_remove": "Det oppstod et problem ved fjerning av elementer fra albumet", + "album_viewer_appbar_share_err_title": "Mislyktes ved endring av albumtittel", "album_viewer_appbar_share_leave": "Forlat album", "album_viewer_appbar_share_to": "Del til", "album_viewer_page_share_add_users": "Legg til brukere", @@ -454,11 +462,11 @@ "allow_public_user_to_upload": "Tillat uautentiserte brukere ÃĨ laste opp", "alt_text_qr_code": "QR-kodebilde", "anti_clockwise": "Mot klokken", - "api_key": "API Nøkkel", + "api_key": "API-nøkkel", "api_key_description": "Denne verdien vil vises kun Ên gang. Pass pÃĨ ÃĨ kopiere den før du lukker vinduet.", "api_key_empty": "API-nøkkelnavnet bør ikke vÃĻre tomt", "api_keys": "API-nøkler", - "app_bar_signout_dialog_content": "Er du sikker pÃĨ at du vil logge ut?", + "app_bar_signout_dialog_content": "Vil du virkelig logge ut?", "app_bar_signout_dialog_ok": "Ja", "app_bar_signout_dialog_title": "Logg ut", "app_settings": "Appinstillinger", @@ -467,16 +475,16 @@ "archive": "Arkiv", "archive_action_prompt": "{count} lagt til i arkivet", "archive_or_unarchive_photo": "Arkiver eller ta ut av arkivet", - "archive_page_no_archived_assets": "Ingen arkiverte objekter funnet", + "archive_page_no_archived_assets": "Ingen arkiverte elementer funnet", "archive_page_title": "Arkiv ({count})", "archive_size": "Arkivstørrelse", "archive_size_description": "Konfigurer arkivstørrelsen for nedlastinger (i GiB)", "archived": "Arkivert", "archived_count": "{count, plural, other {Arkivert #}}", "are_these_the_same_person": "Er disse samme person?", - "are_you_sure_to_do_this": "Er du sikker pÃĨ at du vil gjøre dette?", - "asset_action_delete_err_read_only": "Kan ikke slette objekt(er) med kun lese-rettighet, hopper over", - "asset_action_share_err_offline": "Kan ikke hente offline objekt(er), hopper over", + "are_you_sure_to_do_this": "Vil du virkelig gjøre dette?", + "asset_action_delete_err_read_only": "Kunne ikke slette element(er) med kun lese-rettighet, hopper over", + "asset_action_share_err_offline": "Kunne ikke hente offline element(er), hopper over", "asset_added_to_album": "Lagt til i album", "asset_adding_to_album": "Legger til i albumâ€Ļ", "asset_description_updated": "Elementbeskrivelse har blitt oppdatert", @@ -492,35 +500,37 @@ "asset_list_settings_subtitle": "Innstillinger for layout av fotorutenett", "asset_list_settings_title": "Fotorutenett", "asset_offline": "Fil utilgjengelig", - "asset_offline_description": "Dette elementet er offline. Immich kan ikke aksessere dets lokasjon. Vennlist pÃĨse at elementet er tilgijengelig og skann sÃĨ biblioteket pÃĨ nytt.", + "asset_offline_description": "Dette elementet er offline. Immich kan ikke aksessere dets lokasjon. Vennligst pÃĨse at elementet er tilgjengelig og skann sÃĨ biblioteket pÃĨ nytt.", "asset_restored_successfully": "Objekt(er) gjenopprettet", "asset_skipped": "Hoppet over", - "asset_skipped_in_trash": "I søppelbøtten", + "asset_skipped_in_trash": "I papirkurven", + "asset_trashed": "Objekt slettet", + "asset_troubleshoot": "Feilsøk element", "asset_uploaded": "Lastet opp", "asset_uploading": "Laster oppâ€Ļ", "asset_viewer_settings_subtitle": "Endre dine visningsinnstillinger for galleriet", "asset_viewer_settings_title": "Objektviser", "assets": "Filer", - "assets_added_count": "Lagt til {count, plural, one {# objekt} other {# objekter}}", - "assets_added_to_album_count": "Lagt til {count, plural, one {# objekter} other {# objekt}} i album", + "assets_added_count": "Lagt til {count, plural, one {# element} other {# elementer}}", + "assets_added_to_album_count": "Lagt til {count, plural, one {# elementer} other {# element}} i album", "assets_added_to_albums_count": "Lagt til {assetTotal, plural, one {# asset} other {# assets}} til {albumTotal, plural, one {# album} other {# albums}}", "assets_cannot_be_added_to_album_count": "{count, plural, one {Objektet} other {Objektene}} kan ikke legges til i albumet", "assets_cannot_be_added_to_albums": "{count, plural, one {Asset} other {Assets}} kan ikke legges til i noen av albumene", "assets_count": "{count, plural, one {# fil} other {# filer}}", - "assets_deleted_permanently": "{count} objekt(er) slettet permanent", - "assets_deleted_permanently_from_server": "{count} objekt(er) slettet permanent fra Immich-serveren", + "assets_deleted_permanently": "{count} element(er) slettet permanent", + "assets_deleted_permanently_from_server": "{count} element(er) slettet permanent fra Immich-serveren", "assets_downloaded_failed": "{count, plural, one {Nedlasting av # fil - {error} fil feilet} other {Nedlastede # filer - {error} filer feilet}}", "assets_downloaded_successfully": "{count, plural, one {Nedlastet # fil vellykket} other {Nedlastede # filer vellykket}}", - "assets_moved_to_trash_count": "Flyttet {count, plural, one {# objekt} other {# objekter}} til søppel", - "assets_permanently_deleted_count": "Slettet {count, plural, one {# objekt} other {# objekter}} permanent", - "assets_removed_count": "Slettet {count, plural, one {# objekt} other {# objekter}}", - "assets_removed_permanently_from_device": "{count} objekt(er) slettet permanent fra enheten din", - "assets_restore_confirmation": "Er du sikker pÃĨ at du vil gjenopprette alle slettede eiendeler? Denne handlingen kan ikke angres! VÃĻr oppmerksom pÃĨ at frakoblede ressurser ikke kan gjenopprettes pÃĨ denne mÃĨten.", - "assets_restored_count": "Gjenopprettet {count, plural, one {# objekt} other {# objekter}}", - "assets_restored_successfully": "{count} objekt(er) gjenopprettet", - "assets_trashed": "{count} objekt(er) slettet", - "assets_trashed_count": "Kastet {count, plural, one {# objekt} other {# objekter}}", - "assets_trashed_from_server": "{count} objekt(er) slettet fra Immich serveren", + "assets_moved_to_trash_count": "Flyttet {count, plural, one {# element} other {# elementer}} til søppel", + "assets_permanently_deleted_count": "Slettet {count, plural, one {# element} other {# elementer}} permanent", + "assets_removed_count": "Slettet {count, plural, one {# element} other {# elementer}}", + "assets_removed_permanently_from_device": "{count} element(er) slettet permanent fra enheten din", + "assets_restore_confirmation": "Vil du virkelig gjenopprette alle slettede eiendeler? Denne handlingen kan ikke angres! VÃĻr oppmerksom pÃĨ at frakoblede ressurser ikke kan gjenopprettes pÃĨ denne mÃĨten.", + "assets_restored_count": "Gjenopprettet {count, plural, one {# element} other {# elementer}}", + "assets_restored_successfully": "{count} element(er) gjenopprettet", + "assets_trashed": "{count} element(er) slettet", + "assets_trashed_count": "Kastet {count, plural, one {# element} other {# elementer}}", + "assets_trashed_from_server": "{count} element(er) slettet fra Immich serveren", "assets_were_part_of_album_count": "{count, plural, one {Objektet} other {Objektene}} er allerede lagt til i albumet", "assets_were_part_of_albums_count": "{count, plural, one {Asset was} other {Assets were}} allerede inkludert i albumet", "authorized_devices": "Autoriserte enheter", @@ -529,22 +539,25 @@ "autoplay_slideshow": "Autoavspilling av lysbildefremvisning", "back": "Tilbake", "back_close_deselect": "Tilbake, lukk eller fjern merking", + "background_backup_running_error": "Bakgrunnsbackup kjører, kan ikke starte manuell backup", "background_location_permission": "Bakgrunnstillatelse for plassering", "background_location_permission_content": "For ÃĨ bytte nettverk nÃĨr du kjører i bakgrunnen, mÃĨ Immich *alltid* ha presis posisjonstilgang slik at appen kan lese Wi-Fi-nettverkets navn", + "background_options": "Bakgrunnsinnstillinger", "backup": "Sikkerhetskopiering", "backup_album_selection_page_albums_device": "Album pÃĨ enhet ({count})", "backup_album_selection_page_albums_tap": "Trykk for ÃĨ inkludere, dobbelttrykk for ÃĨ ekskludere", "backup_album_selection_page_assets_scatter": "Objekter kan bli spredd over flere album. Album kan derfor bli inkludert eller ekskludert under sikkerhetskopieringen.", "backup_album_selection_page_select_albums": "Velg album", "backup_album_selection_page_selection_info": "Valginformasjon", - "backup_album_selection_page_total_assets": "Totalt antall unike objekter", + "backup_album_selection_page_total_assets": "Totalt antall unike elementer", + "backup_albums_sync": "Synkronisering av sikkerhetskopialbum", "backup_all": "Alle", - "backup_background_service_backup_failed_message": "Sikkerhetskopiering av objekter feilet. Prøver pÃĨ nyttâ€Ļ", + "backup_background_service_backup_failed_message": "Sikkerhetskopiering av elementer feilet. Prøver pÃĨ nyttâ€Ļ", "backup_background_service_connection_failed_message": "Tilkobling til server feilet. Prøver pÃĨ nyttâ€Ļ", "backup_background_service_current_upload_notification": "Laster opp {filename}", - "backup_background_service_default_notification": "Ser etter nye objekterâ€Ļ", - "backup_background_service_error_title": "Sikkerhetskopieringsfeil", - "backup_background_service_in_progress_notification": "Sikkerhetskopierer objekterâ€Ļ", + "backup_background_service_default_notification": "Ser etter nye elementerâ€Ļ", + "backup_background_service_error_title": "Feil under sikkerhetskopiering", + "backup_background_service_in_progress_notification": "Sikkerhetskopierer elementerâ€Ļ", "backup_background_service_upload_failure_notification": "Opplasting feilet {filename}", "backup_controller_page_albums": "Sikkerhetskopier albumer", "backup_controller_page_background_app_refresh_disabled_content": "Aktiver bakgrunnsoppdatering i Innstillinger > Generelt > Bakgrunnsoppdatering for ÃĨ bruke sikkerhetskopiering i bakgrunnen.", @@ -556,8 +569,8 @@ "backup_controller_page_background_battery_info_title": "Batterioptimalisering", "backup_controller_page_background_charging": "Kun ved lading", "backup_controller_page_background_configure_error": "Konfigurering av bakgrunnstjenesten feilet", - "backup_controller_page_background_delay": "Forsink sikkerhetskopiering av nye objekter: {duration}", - "backup_controller_page_background_description": "Skru pÃĨ bakgrunnstjenesten for ÃĨ automatisk sikkerhetskopiere alle nye objekter uten ÃĨ mÃĨtte ÃĨpne appen", + "backup_controller_page_background_delay": "Forsink sikkerhetskopiering av nye elementer: {duration}", + "backup_controller_page_background_description": "Skru pÃĨ bakgrunnstjenesten for ÃĨ automatisk sikkerhetskopiere alle nye elementer uten ÃĨ mÃĨtte ÃĨpne appen", "backup_controller_page_background_is_off": "Automatisk sikkerhetskopiering i bakgrunnen er deaktivert", "backup_controller_page_background_is_on": "Automatisk sikkerhetskopiering i bakgrunnen er aktivert", "backup_controller_page_background_turn_off": "Skru av bakgrunnstjenesten", @@ -567,9 +580,9 @@ "backup_controller_page_backup_selected": "Valgte: ", "backup_controller_page_backup_sub": "Opplastede bilder og videoer", "backup_controller_page_created": "Opprettet: {date}", - "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_desc_backup": "SlÃĨ pÃĨ sikkerhetskopiering i forgrunnen for automatisk ÃĨ laste opp nye elementer til serveren nÃĨr du ÃĨpner appen.", "backup_controller_page_excluded": "Ekskludert: ", - "backup_controller_page_failed": "Feilet ({count})", + "backup_controller_page_failed": "Mislyktes ({count})", "backup_controller_page_filename": "Filnavn: {filename} [{size}]", "backup_controller_page_id": "ID: {id}", "backup_controller_page_info": "Informasjon om sikkerhetskopi", @@ -586,8 +599,9 @@ "backup_controller_page_turn_off": "SlÃĨ av sikkerhetskopiering i forgrunnen", "backup_controller_page_turn_on": "SlÃĨ pÃĨ sikkerhetskopiering i forgrunnen", "backup_controller_page_uploading_file_info": "Laster opp filinformasjon", - "backup_err_only_album": "Kan ikke fjerne det eneste albumet", - "backup_info_card_assets": "objekter", + "backup_err_only_album": "Kunne ikke fjerne det eneste albumet", + "backup_error_sync_failed": "Synkronisering feilet. Kunne ikke fortsette sikkerhetskopiering.", + "backup_info_card_assets": "elementer", "backup_manual_cancelled": "Avbrutt", "backup_manual_in_progress": "Opplasting er allerede i gang. Prøv igjen om litt", "backup_manual_success": "Vellykket", @@ -597,8 +611,6 @@ "backup_setting_subtitle": "Administrer opplastingsinnstillinger for bakgrunn og forgrunn", "backup_settings_subtitle": "HÃĨndter opplastingsinnstillinger", "backward": "Bakover", - "beta_sync": "Beta synkroniseringsstatus", - "beta_sync_subtitle": "HÃĨndter det nye synkroniseringssystemet", "biometric_auth_enabled": "Biometrisk autentisering aktivert", "biometric_locked_out": "Du er lÃĨst ute av biometrisk verifisering", "biometric_no_options": "Ingen biometriske valg tilgjengelige", @@ -609,15 +621,15 @@ "bugs_and_feature_requests": "Feil og funksjonsforespørsler", "build": "Bygg", "build_image": "Lag Bilde", - "bulk_delete_duplicates_confirmation": "Er du sikker pÃĨ at du vil slette {count, plural, one {# duplisert fil} other {# dupliserte filer}}? Dette vil beholde største filen fra hver gruppe og vil permanent slette alle andre duplikater. Du kan ikke angre denne handlingen!", - "bulk_keep_duplicates_confirmation": "Er du sikker pÃĨ at du vil beholde {count, plural, one {# duplikat} other {# duplikater}}? Dette vil løse alle duplikatgrupper uten ÃĨ slette noe.", - "bulk_trash_duplicates_confirmation": "Er du sikker pÃĨ ønsker ÃĨ slette {count, plural, one {# duplisert objekt} other {# dupliserte objekter}}? Dette vil beholde største filen fra hver gruppe, samt slette alle andre duplikater.", + "bulk_delete_duplicates_confirmation": "Vil du virkelig slette {count, plural, one {# duplisert fil} other {# dupliserte filer}}? Dette vil beholde største filen fra hver gruppe og vil permanent slette alle andre duplikater. Du kan ikke angre denne handlingen!", + "bulk_keep_duplicates_confirmation": "Vil du virkelig beholde {count, plural, one {# duplikat} other {# duplikater}}? Dette vil løse alle duplikatgrupper uten ÃĨ slette noe.", + "bulk_trash_duplicates_confirmation": "Vil du virkelig ÃĨ slette {count, plural, one {# duplisert element} other {# dupliserte elementer}}? Dette vil beholde største filen fra hver gruppe, samt slette alle andre duplikater.", "buy": "Kjøp Immich", "cache_settings_clear_cache_button": "Tøm buffer", "cache_settings_clear_cache_button_title": "Tømmer app-ens buffer. Dette vil ha betydelig innvirkning pÃĨ appens ytelse inntil bufferen er gjenoppbygd.", "cache_settings_duplicated_assets_clear_button": "TØM", "cache_settings_duplicated_assets_subtitle": "Bilder og videoer som er ignorert av app'en", - "cache_settings_duplicated_assets_title": "Dupliserte objekter ({count})", + "cache_settings_duplicated_assets_title": "Dupliserte elementer ({count})", "cache_settings_statistics_album": "Bibliotekminiatyrbilder", "cache_settings_statistics_full": "Originalbilder", "cache_settings_statistics_shared": "Delte albumminiatyrbilder", @@ -634,9 +646,9 @@ "cancel_search": "Avbryt søk", "canceled": "Avbrutt", "canceling": "Avbryter", - "cannot_merge_people": "Kan ikke slÃĨ sammen personer", + "cannot_merge_people": "Kunne ikke slÃĨ sammen personer", "cannot_undo_this_action": "Du kan ikke gjøre om denne handlingen!", - "cannot_update_the_description": "Kan ikke oppdatere beskrivelsen", + "cannot_update_the_description": "Kunne ikke oppdatere beskrivelsen", "cast": "Strøm", "cast_description": "Konfigurer tilgjengelige cast-destinasjoner", "change_date": "Endre dato", @@ -646,19 +658,21 @@ "change_location": "Endre sted", "change_name": "Endre navn", "change_name_successfully": "Navneendring vellykket", - "change_password": "Endre Passord", + "change_password": "Endre passord", "change_password_description": "Dette er enten første gang du logger inn i systemet, eller det har blitt gjort en forespørsel om ÃĨ endre passordet ditt. Vennligst skriv inn det nye passordet nedenfor.", "change_password_form_confirm_password": "Bekreft passord", "change_password_form_description": "Hei {name}!\n\nDette er enten første gang du logger pÃĨ systemet, eller det er sendt en forespørsel om ÃĨ endre passordet ditt. Vennligst skriv inn det nye passordet nedenfor.", "change_password_form_new_password": "Nytt passord", "change_password_form_password_mismatch": "Passordene stemmer ikke", "change_password_form_reenter_new_password": "Skriv nytt passord igjen", - "change_pin_code": "Endre PIN kode", + "change_pin_code": "Endre PIN-kode", "change_your_password": "Endre passordet ditt", "changed_visibility_successfully": "Endret synlighet vellykket", - "check_corrupt_asset_backup": "Sjekk etter korrupte backupobjekter", + "charging": "Lading", + "charging_requirement_mobile_backup": "Bakgrunnsbackup krever at enheten lader", + "check_corrupt_asset_backup": "Sjekk etter korrupte backupelementer", "check_corrupt_asset_backup_button": "Utfør sjekk", - "check_corrupt_asset_backup_description": "Kjør denne sjekken kun over Wi-Fi og nÃĨr alle objekter har blitt lastet opp. Denne sjekken kan ta noen minutter.", + "check_corrupt_asset_backup_description": "Kjør denne sjekken kun over Wi-Fi og nÃĨr alle elementer har blitt lastet opp. Denne sjekken kan ta noen minutter.", "check_logs": "Sjekk Logger", "choose_matching_people_to_merge": "Velg personer som skal slÃĨs sammen", "city": "By", @@ -691,8 +705,8 @@ "completed": "Fullført", "confirm": "Bekreft", "confirm_admin_password": "Bekreft administratorpassord", - "confirm_delete_face": "Er du sikker pÃĨ at du vil slette {name} sitt ansikt fra ativia?", - "confirm_delete_shared_link": "Er du sikker pÃĨ at du vil slette denne delte lenken?", + "confirm_delete_face": "Vil du virkelig slette {name} sitt ansikt fra ativia?", + "confirm_delete_shared_link": "Vil du virkelig slette denne delte lenken?", "confirm_keep_this_delete_others": "Alle andre ressurser i denne stabelen vil bli slettet bortsett fra denne ressursen. Er du sikker pÃĨ at du vil fortsette?", "confirm_new_pin_code": "Bekreft ny PIN kode", "confirm_password": "Bekreft passord", @@ -710,7 +724,7 @@ "control_bottom_app_bar_edit_time": "Endre Dato og tid", "control_bottom_app_bar_share_link": "Del Lenke", "control_bottom_app_bar_share_to": "Del til", - "control_bottom_app_bar_trash_from_immich": "Flytt til søppelkasse", + "control_bottom_app_bar_trash_from_immich": "Flytt til papirkurv", "copied_image_to_clipboard": "Bildet er kopiert til utklippstavlen.", "copied_to_clipboard": "Kopiert til utklippstavlen!", "copy_error": "Kopi feil", @@ -725,9 +739,9 @@ "covers": "Omslag", "create": "Opprett", "create_album": "Opprett album", - "create_album_page_untitled": "Uten navn", + "create_album_page_untitled": "Navnløst", "create_library": "Opprett Bibliotek", - "create_link": "Opprett link", + "create_link": "Opprett lenke", "create_link_to_share": "Opprett delelink", "create_link_to_share_description": "La alle med lenken se de(t) valgte bildet/bildene", "create_new": "LAG NY", @@ -736,12 +750,13 @@ "create_new_user": "Opprett ny bruker", "create_shared_album_page_share_add_assets": "LEGG TIL OBJEKTER", "create_shared_album_page_share_select_photos": "Velg bilder", - "create_shared_link": "Opprett delt link", - "create_tag": "Lag tag", + "create_shared_link": "Opprett delt lenke", + "create_tag": "Lag merkelapp", "create_tag_description": "Lag en ny tag. For undertag, vennligst fullfør hele stien til taggen, inkludert forovervendt skrÃĨstrek.", "create_user": "Opprett Bruker", "created": "Opprettet", "created_at": "Laget", + "creating_linked_albums": "Oppretter sammenkoblede albumer...", "crop": "BeskjÃĻr", "curated_object_page_title": "Ting", "current_device": "NÃĨvÃĻrende enhet", @@ -770,23 +785,23 @@ "default_locale": "Standard sprÃĨkinnstilling", "default_locale_description": "Formater datoer og tall basert pÃĨ nettleserens sprÃĨkinnstilling", "delete": "Slett", - "delete_action_confirmation_message": "Er du sikker pÃĨ at du vil slette dette objektet? Dette vil flytte objektet til søppelkassen og vil gi deg beskjed om du vil slette det lokalt", + "delete_action_confirmation_message": "Vil du virkelig slette dette elementet? Dette vil flytte elementet til papirkurvn og vil gi deg beskjed om du vil slette det lokalt", "delete_action_prompt": "{count} slettet", "delete_album": "Slett album", - "delete_api_key_prompt": "Er du sikker pÃĨ at du vil slette denne API-nøkkelen?", - "delete_dialog_alert": "Disse objektene vil bli slettet permanent fra Immich og fra enheten din", - "delete_dialog_alert_local": "Disse objektene vil bli permanent slettet fra enheten din, men vil fortsatt vÃĻre tilgjengelige fra Immich serveren", - "delete_dialog_alert_local_non_backed_up": "Noen av objektene er ikke sikkerhetskopiert til Immich og vil bli permanent fjernet fra enheten din", - "delete_dialog_alert_remote": "Disse objektene vil bli permanent slettet fra Immich serveren", + "delete_api_key_prompt": "Vil du virkelig slette denne API-nøkkelen?", + "delete_dialog_alert": "Disse elementene vil bli slettet permanent fra Immich og fra enheten din", + "delete_dialog_alert_local": "Disse elementene vil bli permanent slettet fra enheten din, men vil fortsatt vÃĻre tilgjengelige fra Immich serveren", + "delete_dialog_alert_local_non_backed_up": "Noen av elementene er ikke sikkerhetskopiert til Immich og vil bli permanent fjernet fra enheten din", + "delete_dialog_alert_remote": "Disse elementene vil bli permanent slettet fra Immich serveren", "delete_dialog_ok_force": "Slett uansett", "delete_dialog_title": "Slett permanent", - "delete_duplicates_confirmation": "Er du sikker pÃĨ at du vil slette disse duplikatene permanent?", + "delete_duplicates_confirmation": "Vil du virkelig slette disse duplikatene permanent?", "delete_face": "Slett ansik", "delete_key": "Slett nøkkel", "delete_library": "Slett bibliotek", "delete_link": "Slett lenke", "delete_local_action_prompt": "{count} slettet lokalt", - "delete_local_dialog_ok_backed_up_only": "Slett kun sikkerhetskopierte objekter", + "delete_local_dialog_ok_backed_up_only": "Slett kun sikkerhetskopierte elementer", "delete_local_dialog_ok_force": "Slett uansett", "delete_others": "Slett andre", "delete_permanently": "Slett permanent", @@ -794,7 +809,7 @@ "delete_shared_link": "Slett delt lenke", "delete_shared_link_dialog_title": "Slett delt link", "delete_tag": "Slett tag", - "delete_tag_confirmation_prompt": "Er du sikker pÃĨ at du vil slette {tagName} tag?", + "delete_tag_confirmation_prompt": "Vil du virkelig slette {tagName} tag?", "delete_user": "Slett bruker", "deleted_shared_link": "Slettet delt lenke", "deletes_missing_assets": "Slett eiendeler som mangler fra disk", @@ -819,7 +834,7 @@ "documentation": "Dokumentasjon", "done": "Ferdig", "download": "Last ned", - "download_action_prompt": "Laster ned {count} objekter", + "download_action_prompt": "Laster ned {count} elementer", "download_canceled": "Nedlasting avbrutt", "download_complete": "Nedlasting fullført", "download_enqueue": "Nedlasting satt i kø", @@ -878,7 +893,7 @@ "email_notifications": "Epostvarsler", "empty_folder": "Denne mappen er tom", "empty_trash": "Tøm papirkurv", - "empty_trash_confirmation": "Er du sikker pÃĨ at du vil tømme søppelbøtta? Dette vil slette alle filene i søppelbøtta permanent fra Immich.\nDu kan ikke angre denne handlingen!", + "empty_trash_confirmation": "Vil du virkelig Tømme søppelbøtta? Dette vil slette alle filene i søppelbøtta permanent fra Immich.\nDu kan ikke angre denne handlingen!", "enable": "Aktivere", "enable_backup": "Aktiver backup", "enable_biometric_auth_description": "Skriv inn PINkoden for ÃĨ aktivere biometrisk autentisering", @@ -889,23 +904,25 @@ "enter_your_pin_code": "Skriv inn din PIN kode", "enter_your_pin_code_subtitle": "Skriv inn din PIN kode for ÃĨ fÃĨ tilgang til lÃĨst mappe", "error": "Feil", - "error_change_sort_album": "Feilet ved endring av sorteringsrekkefølge pÃĨ albumer", + "error_change_sort_album": "Mislyktes ved endring av sorteringsrekkefølge pÃĨ albumer", "error_delete_face": "Feil ved sletting av ansikt fra aktivia", + "error_getting_places": "Feil ved henting av steder", "error_loading_image": "Feil ved lasting av bilde", + "error_loading_partners": "Feil ved lasting av partnere: {error}", "error_saving_image": "Feil: {error}", "error_tag_face_bounding_box": "Feil ved merking av ansikt - klarte ikke ÃĨ fÃĨ koordinatene pÃĨ omrisset", "error_title": "Feil - Noe gikk galt", "errors": { - "cannot_navigate_next_asset": "Kan ikke navigere til neste fil", - "cannot_navigate_previous_asset": "Kan ikke navigere til forrige fil", - "cant_apply_changes": "Kan ikke legge til endringene", - "cant_change_activity": "Kan ikke {enabled, select, true {disable} other {enable}} aktivitet", - "cant_change_asset_favorite": "Kan ikke endre favoritt til filen", - "cant_change_metadata_assets_count": "Kan ikke endre metadata for {count, plural, one {# objekt} other {# objekter}}", - "cant_get_faces": "Kan ikke finne ansikter", - "cant_get_number_of_comments": "Kan ikke hente antall kommentarer", - "cant_search_people": "Kan ikke søke etter mennesker", - "cant_search_places": "Kan ikke søke etter plasser", + "cannot_navigate_next_asset": "Kunne ikke navigere til neste fil", + "cannot_navigate_previous_asset": "Kunne ikke navigere til forrige fil", + "cant_apply_changes": "Kunne ikke legge til endringene", + "cant_change_activity": "Kunne ikke {enabled, select, true {disable} other {enable}} aktivitet", + "cant_change_asset_favorite": "Kunne ikke endre favoritt til filen", + "cant_change_metadata_assets_count": "Kunne ikke endre metadata for {count, plural, one {# element} other {# elementer}}", + "cant_get_faces": "Kunne ikke finne ansikter", + "cant_get_number_of_comments": "Kunne ikke hente antall kommentarer", + "cant_search_people": "Kunne ikke søke etter mennesker", + "cant_search_places": "Kunne ikke søke etter plasser", "error_adding_assets_to_album": "Feil med ÃĨ legge til bilder til album", "error_adding_users_to_album": "Feil, kan ikke legge til brukere til album", "error_deleting_shared_user": "Feil med ÃĨ slette delt bruker", @@ -916,17 +933,17 @@ "exclusion_pattern_already_exists": "Dette eksklusjonsmønsteret eksisterer allerede.", "failed_to_create_album": "Feil med ÃĨ lage album", "failed_to_create_shared_link": "Feil med ÃĨ lage delt lenke", - "failed_to_edit_shared_link": "Feilet med ÃĨ redigere delt lenke", - "failed_to_get_people": "Feilet med ÃĨ finne mennesker", - "failed_to_keep_this_delete_others": "Feilet med ÃĨ beholde dette bilde og slette de andre", - "failed_to_load_asset": "Feilet med ÃĨ laste bilder", - "failed_to_load_assets": "Feilet med ÃĨ laste bilde", + "failed_to_edit_shared_link": "Mislyktes med ÃĨ redigere delt lenke", + "failed_to_get_people": "Mislyktes med ÃĨ finne mennesker", + "failed_to_keep_this_delete_others": "Mislyktes med ÃĨ beholde dette bilde og slette de andre", + "failed_to_load_asset": "Mislyktes med ÃĨ laste bilder", + "failed_to_load_assets": "Mislyktes med ÃĨ laste bilde", "failed_to_load_notifications": "Kunne ikke laste inn varsler", "failed_to_load_people": "Feilen med ÃĨ laste mennesker", - "failed_to_remove_product_key": "Feilet med ÃĨ ta bort produkt nøkkel", + "failed_to_remove_product_key": "Mislyktes med ÃĨ ta bort produkt nøkkel", "failed_to_reset_pin_code": "Kunne ikke tilbakestille PIN-koden", - "failed_to_stack_assets": "Feilet med ÃĨ stable bilder", - "failed_to_unstack_assets": "Feilet med ÃĨ avstable bilder", + "failed_to_stack_assets": "Mislyktes med ÃĨ stable bilder", + "failed_to_unstack_assets": "Mislyktes med ÃĨ avstable bilder", "failed_to_update_notification_status": "Kunne ikke oppdatere varslingsstatusen", "import_path_already_exists": "Denne importstien eksisterer allerede.", "incorrect_email_or_password": "Feil epost eller passord", @@ -934,87 +951,87 @@ "profile_picture_transparent_pixels": "Profil bilde kan ikke ha gjennomsiktige piksler. Vennligst zoom inn og/eller flytt bilde.", "quota_higher_than_disk_size": "Du har satt kvoten større enn diskstørrelsen", "something_went_wrong": "Noe gikk galt", - "unable_to_add_album_users": "Kan ikke legge til brukere i albumet", - "unable_to_add_assets_to_shared_link": "Kan ikke legge til bilder til delt lenke", - "unable_to_add_comment": "Kan ikke legge til kommentar", - "unable_to_add_exclusion_pattern": "Kan ikke legge til eksklusjonsmønster", - "unable_to_add_import_path": "Kan ikke legge til importsti", - "unable_to_add_partners": "Kan ikke legge til partnere", - "unable_to_add_remove_archive": "Kan ikke {archived, select, true {fjerne objekt fra} other {flytte objekt til}} arkivet", - "unable_to_add_remove_favorites": "Kan ikke {favorite, select, true {legge til objekt til} other {fjerne objekt fra}} favoritter", - "unable_to_archive_unarchive": "Kan ikke {archived, select, true {archive} other {unarchive}}", - "unable_to_change_album_user_role": "Kan ikke endre brukerens rolle i albumet", - "unable_to_change_date": "Kan ikke endre dato", + "unable_to_add_album_users": "Kunne ikke legge til brukere i albumet", + "unable_to_add_assets_to_shared_link": "Kunne ikke legge til bilder til delt lenke", + "unable_to_add_comment": "Kunne ikke legge til kommentar", + "unable_to_add_exclusion_pattern": "Kunne ikke legge til eksklusjonsmønster", + "unable_to_add_import_path": "Kunne ikke legge til importsti", + "unable_to_add_partners": "Kunne ikke legge til partnere", + "unable_to_add_remove_archive": "Kunne ikke {archived, select, true {fjerne element fra} other {flytte element til}} arkivet", + "unable_to_add_remove_favorites": "Kunne ikke {favorite, select, true {legge til element til} other {fjerne element fra}} favoritter", + "unable_to_archive_unarchive": "Kunne ikke {archived, select, true {archive} other {unarchive}}", + "unable_to_change_album_user_role": "Kunne ikke endre brukerens rolle i albumet", + "unable_to_change_date": "Kunne ikke endre dato", "unable_to_change_description": "Klarte ikke ÃĨ oppdatere beskrivelse", - "unable_to_change_favorite": "Kan ikke endre favoritt for bildet", - "unable_to_change_location": "Kan ikke endre plassering", - "unable_to_change_password": "Kan ikke endre passord", - "unable_to_change_visibility": "Kan ikke endre synlighet for {count, plural, one {# person} other {# people}}", + "unable_to_change_favorite": "Kunne ikke endre favoritt for bildet", + "unable_to_change_location": "Kunne ikke endre plassering", + "unable_to_change_password": "Kunne ikke endre passord", + "unable_to_change_visibility": "Kunne ikke endre synlighet for {count, plural, one {# person} other {# people}}", "unable_to_complete_oauth_login": "Kunne ikke fullføre OAuth innlogging", - "unable_to_connect": "Kan ikke koble til", - "unable_to_copy_to_clipboard": "Kan ikke kopiere til utklippstavlen, sørg for at du fÃĨr tilgang til siden via HTTPS", - "unable_to_create_admin_account": "Kan ikke opprette administrator bruker", - "unable_to_create_api_key": "Kan ikke opprette en ny API-nøkkel", - "unable_to_create_library": "Kan ikke opprette bibliotek", - "unable_to_create_user": "Kan ikke opprette bruker", - "unable_to_delete_album": "Kan ikke slette album", - "unable_to_delete_asset": "Kan ikke slette filen", + "unable_to_connect": "Kunne ikke koble til", + "unable_to_copy_to_clipboard": "Kunne ikke kopiere til utklippstavlen, sørg for at du fÃĨr tilgang til siden via HTTPS", + "unable_to_create_admin_account": "Kunne ikke opprette administrator bruker", + "unable_to_create_api_key": "Kunne ikke opprette en ny API-nøkkel", + "unable_to_create_library": "Kunne ikke opprette bibliotek", + "unable_to_create_user": "Kunne ikke opprette bruker", + "unable_to_delete_album": "Kunne ikke slette album", + "unable_to_delete_asset": "Kunne ikke slette filen", "unable_to_delete_assets": "Feil med ÃĨ slette bilde", - "unable_to_delete_exclusion_pattern": "Kan ikke slette eksklusjonsmønster", - "unable_to_delete_import_path": "Kan ikke slette importsti", - "unable_to_delete_shared_link": "Kan ikke slette delt lenke", - "unable_to_delete_user": "Kan ikke slette bruker", - "unable_to_download_files": "Kan ikke laste ned filer", - "unable_to_edit_exclusion_pattern": "Kan ikke redigere eksklusjonsmønster", - "unable_to_edit_import_path": "Kan ikke redigere importsti", - "unable_to_empty_trash": "Kan ikke tømme papirkurven", - "unable_to_enter_fullscreen": "Kan ikke gÃĨ inn i fullskjerm", - "unable_to_exit_fullscreen": "Kan ikke gÃĨ ut fra fullskjerm", - "unable_to_get_comments_number": "Kan ikke hente antall kommentarer", - "unable_to_get_shared_link": "Kan ikke hente delt lenke", - "unable_to_hide_person": "Kan ikke skjule person", - "unable_to_link_motion_video": "Kan ikke lenke bevegelig video", - "unable_to_link_oauth_account": "Kan ikke lenke til OAuth-konto", - "unable_to_log_out_all_devices": "Kan ikke logge ut fra alle enheter", - "unable_to_log_out_device": "Kan ikke logge ut av enhet", - "unable_to_login_with_oauth": "Kan ikke logge inn med OAuth", - "unable_to_play_video": "Kan ikke spille av video", + "unable_to_delete_exclusion_pattern": "Kunne ikke slette eksklusjonsmønster", + "unable_to_delete_import_path": "Kunne ikke slette importsti", + "unable_to_delete_shared_link": "Kunne ikke slette delt lenke", + "unable_to_delete_user": "Kunne ikke slette bruker", + "unable_to_download_files": "Kunne ikke laste ned filer", + "unable_to_edit_exclusion_pattern": "Kunne ikke redigere eksklusjonsmønster", + "unable_to_edit_import_path": "Kunne ikke redigere importsti", + "unable_to_empty_trash": "Kunne ikke Tømme papirkurven", + "unable_to_enter_fullscreen": "Kunne ikke gÃĨ inn i fullskjerm", + "unable_to_exit_fullscreen": "Kunne ikke gÃĨ ut fra fullskjerm", + "unable_to_get_comments_number": "Kunne ikke hente antall kommentarer", + "unable_to_get_shared_link": "Kunne ikke hente delt lenke", + "unable_to_hide_person": "Kunne ikke skjule person", + "unable_to_link_motion_video": "Kunne ikke lenke bevegelig video", + "unable_to_link_oauth_account": "Kunne ikke lenke til OAuth-konto", + "unable_to_log_out_all_devices": "Kunne ikke logge ut fra alle enheter", + "unable_to_log_out_device": "Kunne ikke logge ut av enhet", + "unable_to_login_with_oauth": "Kunne ikke logge inn med OAuth", + "unable_to_play_video": "Kunne ikke spille av video", "unable_to_reassign_assets_existing_person": "Kunne ikke endre bruker pÃĨ bildene til {name, select, null {an existing person} other {{name}}}", "unable_to_reassign_assets_new_person": "Kunne ikke tildele bildene til en ny person", - "unable_to_refresh_user": "Kan ikke oppdatere bruker", - "unable_to_remove_album_users": "Kan ikke fjerne brukere fra album", - "unable_to_remove_api_key": "Kan ikke fjerne API-nøkkel", + "unable_to_refresh_user": "Kunne ikke oppdatere bruker", + "unable_to_remove_album_users": "Kunne ikke fjerne brukere fra album", + "unable_to_remove_api_key": "Kunne ikke fjerne API-nøkkel", "unable_to_remove_assets_from_shared_link": "Kunne ikke fjerne bilder fra delt lenke", - "unable_to_remove_library": "Kan ikke fjerne bibliotek", - "unable_to_remove_partner": "Kan ikke fjerne partner", - "unable_to_remove_reaction": "Kan ikke fjerne reaksjon", - "unable_to_reset_password": "Kan ikke tilbakestille passord", + "unable_to_remove_library": "Kunne ikke fjerne bibliotek", + "unable_to_remove_partner": "Kunne ikke fjerne partner", + "unable_to_remove_reaction": "Kunne ikke fjerne reaksjon", + "unable_to_reset_password": "Kunne ikke tilbakestille passord", "unable_to_reset_pin_code": "Klarte ikke ÃĨ resette PIN kode", - "unable_to_resolve_duplicate": "Kan ikke løse duplikat", - "unable_to_restore_assets": "Kan ikke gjenopprette filer", - "unable_to_restore_trash": "Kan ikke gjenopprette papirkurven", - "unable_to_restore_user": "Kan ikke gjenopprette bruker", - "unable_to_save_album": "Kan ikke lagre album", - "unable_to_save_api_key": "Kan ikke lagre API-nøkkel", + "unable_to_resolve_duplicate": "Kunne ikke løse duplikat", + "unable_to_restore_assets": "Kunne ikke gjenopprette filer", + "unable_to_restore_trash": "Kunne ikke gjenopprette papirkurven", + "unable_to_restore_user": "Kunne ikke gjenopprette bruker", + "unable_to_save_album": "Kunne ikke lagre album", + "unable_to_save_api_key": "Kunne ikke lagre API-nøkkel", "unable_to_save_date_of_birth": "Kunne ikke lagre bursdag", - "unable_to_save_name": "Kan ikke lagre navn", - "unable_to_save_profile": "Kan ikke lagre profil", - "unable_to_save_settings": "Kan ikke lagre instillinger", - "unable_to_scan_libraries": "Kan ikke skanne biblioteker", - "unable_to_scan_library": "Kan ikke skanne bibliotek", + "unable_to_save_name": "Kunne ikke lagre navn", + "unable_to_save_profile": "Kunne ikke lagre profil", + "unable_to_save_settings": "Kunne ikke lagre instillinger", + "unable_to_scan_libraries": "Kunne ikke skanne biblioteker", + "unable_to_scan_library": "Kunne ikke skanne bibliotek", "unable_to_set_feature_photo": "Kunne ikke sette funksjonsbilde", - "unable_to_set_profile_picture": "Kan ikke sette profilbilde", - "unable_to_submit_job": "Kan ikke sende inn jobb", - "unable_to_trash_asset": "Kan ikke flytte filen til papirkurven", - "unable_to_unlink_account": "Kan ikke fjerne kobling til konto", + "unable_to_set_profile_picture": "Kunne ikke sette profilbilde", + "unable_to_submit_job": "Kunne ikke sende inn jobb", + "unable_to_trash_asset": "Kunne ikke flytte filen til papirkurven", + "unable_to_unlink_account": "Kunne ikke fjerne kobling til konto", "unable_to_unlink_motion_video": "Kunne ikke ta pÃĨ kobling pÃĨ bevegelig video", "unable_to_update_album_cover": "Kunne ikke oppdatere album bilde", "unable_to_update_album_info": "Kunne ikke oppdatere informasjon i album", - "unable_to_update_library": "Kan ikke oppdatere bibliotek", - "unable_to_update_location": "Kan ikke oppdatere plassering", - "unable_to_update_settings": "Kan ikke oppdatere innstillinger", - "unable_to_update_timeline_display_status": "Kan ikke oppdatere visningsstatus for tidslinje", - "unable_to_update_user": "Kan ikke oppdatere bruker", + "unable_to_update_library": "Kunne ikke oppdatere bibliotek", + "unable_to_update_location": "Kunne ikke oppdatere plassering", + "unable_to_update_settings": "Kunne ikke oppdatere innstillinger", + "unable_to_update_timeline_display_status": "Kunne ikke oppdatere visningsstatus for tidslinje", + "unable_to_update_user": "Kunne ikke oppdatere bruker", "unable_to_upload_file": "Kunne ikke laste opp fil" }, "exif": "EXIF", @@ -1045,17 +1062,18 @@ "external_network": "Eksternt nettverk", "external_network_sheet_info": "NÃĨr du ikke er pÃĨ det foretrukne Wi-Fi-nettverket, vil appen koble seg til serveren via den første av URL-ene nedenfor den kan nÃĨ, fra topp til bunn", "face_unassigned": "Ikke tilordnet", - "failed": "Feilet", + "failed": "Mislyktes", "failed_to_authenticate": "Kunne ikke autentisere", - "failed_to_load_assets": "Feilet med ÃĨ laste fil", + "failed_to_load_assets": "Mislyktes med ÃĨ laste fil", "failed_to_load_folder": "Kunne ikke laste inn mappe", "favorite": "Favoritt", "favorite_action_prompt": "{count} lagt til i favoritter", "favorite_or_unfavorite_photo": "Merk som favoritt eller fjern som favoritt", "favorites": "Favoritter", - "favorites_page_no_favorites": "Ingen favorittobjekter funnet", + "favorites_page_no_favorites": "Ingen favorittelementer funnet", "feature_photo_updated": "Fremhevet bilde oppdatert", "features": "Funksjoner", + "features_in_development": "Funksjoner under utvikling", "features_setting_description": "Administrerer funksjoner for appen", "file_name": "Filnavn", "file_name_or_extension": "Filnavn eller filtype", @@ -1076,10 +1094,7 @@ "gcast_enabled": "Google Cast", "gcast_enabled_description": "Denne funksjonen laster eksterne ressurser fra Google for ÃĨ fungere.", "general": "Generelt", - "geolocation_instruction_all_have_location": "Alle objekter for denne datoen har allerede lokasjonsdata. Prøv ÃĨ vise alle objekter eller velg en annen dato", - "geolocation_instruction_location": "Klikk pÃĨ et objekt med GPS-koordinater for ÃĨ bruke posisjonen, eller velg en posisjon direkte fra kartet", - "geolocation_instruction_no_date": "Velg en dato for ÃĨ administrere posisjonsdata for bilder og videoer fra den dagen", - "geolocation_instruction_no_photos": "Ingen bilder eller videoer funnet for denne datoen. Velg en annen dato for ÃĨ vise dem", + "geolocation_instruction_location": "Klikk pÃĨ et element med GPS-koordinater for ÃĨ bruke posisjonen, eller velg en posisjon direkte fra kartet", "get_help": "FÃĨ Hjelp", "get_wifiname_error": "Kunne ikke hente Wi-Fi-navnet. Sørg for at du har gitt de nødvendige tillatelsene og er koblet til et Wi-Fi-nettverk", "getting_started": "Kom i gang", @@ -1098,8 +1113,8 @@ "haptic_feedback_switch": "Aktivert haptisk tilbakemelding", "haptic_feedback_title": "Haptisk tilbakemelding", "has_quota": "Kvote", - "hash_asset": "Hash objekter", - "hashed_assets": "Hashede objekter", + "hash_asset": "Hash elementer", + "hashed_assets": "Hashede elementer", "hashing": "Hasher", "header_settings_add_header_tip": "Legg til header", "header_settings_field_validator_msg": "Verdi kan ikke vÃĻre null", @@ -1114,22 +1129,22 @@ "hide_password": "Skjul passord", "hide_person": "Skjul person", "hide_unnamed_people": "Skjul mennesker uten navn", - "home_page_add_to_album_conflicts": "Lagt til {added} objekter til album {album}. {failed} objekter er allerede i albumet.", - "home_page_add_to_album_err_local": "Kan ikke legge til lokale objekter til album enda, hopper over", - "home_page_add_to_album_success": "Lagt til {added} objekter til album {album}.", - "home_page_album_err_partner": "Kan ikke legge til partnerobjekter i album enda, hopper over", - "home_page_archive_err_local": "Kan ikke arkivere lokale objekter enda, hopper over", - "home_page_archive_err_partner": "Kan ikke arkivere partnerobjekter, hopper over", + "home_page_add_to_album_conflicts": "Lagt til {added} elementer til album {album}. {failed} elementer er allerede i albumet.", + "home_page_add_to_album_err_local": "Kunne ikke legge til lokale elementer til album enda, hopper over", + "home_page_add_to_album_success": "Lagt til {added} elementer til album {album}.", + "home_page_album_err_partner": "Kunne ikke legge til partnerelementer i album enda, hopper over", + "home_page_archive_err_local": "Kunne ikke arkivere lokale elementer enda, hopper over", + "home_page_archive_err_partner": "Kunne ikke arkivere partnerelementer, hopper over", "home_page_building_timeline": "Genererer tidslinjen", - "home_page_delete_err_partner": "Kan ikke slette partnerobjekter, hopper over", - "home_page_delete_remote_err_local": "Lokale objekter i fjernslettingsvalgene, hopper over", - "home_page_favorite_err_local": "Kan ikke sette favoritt pÃĨ lokale objekter enda, hopper over", - "home_page_favorite_err_partner": "Kan ikke merke partnerobjekter som favoritt enda, hopper over", + "home_page_delete_err_partner": "Kunne ikke slette partnerelementer, hopper over", + "home_page_delete_remote_err_local": "Lokale elementer i fjernslettingsvalgene, hopper over", + "home_page_favorite_err_local": "Kunne ikke sette favoritt pÃĨ lokale elementer enda, hopper over", + "home_page_favorite_err_partner": "Kunne ikke merke partnerelementer som favoritt enda, hopper over", "home_page_first_time_notice": "Hvis dette er første gangen du benytter appen, velg et album (eller flere) for sikkerhetskopiering, slik at tidslinjen kan fylles med dine bilder og videoer", - "home_page_locked_error_local": "Kunne ikke flytte lokale objekter til lÃĨst mappe, hopper over", - "home_page_locked_error_partner": "Kunne ikke flytte partner objekter til lÃĨst mappe, hopper over", - "home_page_share_err_local": "Kan ikke dele lokale objekter via link, hopper over", - "home_page_upload_err_limit": "Maksimalt 30 objekter kan lastes opp om gangen, hopper over", + "home_page_locked_error_local": "Kunne ikke flytte lokale elementer til lÃĨst mappe, hopper over", + "home_page_locked_error_partner": "Kunne ikke flytte partner elementer til lÃĨst mappe, hopper over", + "home_page_share_err_local": "Kunne ikke dele lokale elementer via link, hopper over", + "home_page_upload_err_limit": "Maksimalt 30 elementer kan lastes opp om gangen, hopper over", "host": "Vert", "hour": "Time", "hours": "Timer", @@ -1185,7 +1200,7 @@ "keep": "Behold", "keep_all": "Behold alle", "keep_this_delete_others": "Behold denne, slett de andre", - "kept_this_deleted_others": "Behold denne filen og slett {count, plural, one {# objekt} other {# objekter}}", + "kept_this_deleted_others": "Behold denne filen og slett {count, plural, one {# element} other {# elementer}}", "keyboard_shortcuts": "Tastatursnarveier", "language": "SprÃĨk", "language_no_results_subtitle": "Prøv ÃĨ endre søkeord", @@ -1206,7 +1221,7 @@ "library_options": "Bibliotekalternativer", "library_page_device_albums": "Albumer pÃĨ enheten", "library_page_new_album": "Nytt album", - "library_page_sort_asset_count": "Antall objekter", + "library_page_sort_asset_count": "Antall elementer", "library_page_sort_created": "Nylig opplastet", "library_page_sort_last_modified": "Sist endret", "library_page_sort_title": "Albumtittel", @@ -1221,8 +1236,9 @@ "loading": "Laster", "loading_search_results_failed": "Klarte ikke ÃĨ laste inn søkeresultater", "local": "Lokal", - "local_asset_cast_failed": "Kan ikke caste et bilde som ikke er lastet opp til serveren", - "local_assets": "Lokale objekter", + "local_asset_cast_failed": "Kunne ikke caste et bilde som ikke er lastet opp til serveren", + "local_assets": "Lokale elementer", + "local_media_summary": "Oppsummering av lokale media", "local_network": "Lokalt nettverk", "local_network_sheet_info": "Appen vil koble til serveren via denne URL-en nÃĨr du bruker det angitte Wi-Fi-nettverket", "location_permission": "Stedstillatelse", @@ -1234,6 +1250,7 @@ "location_picker_longitude_hint": "Skriv inn lengdegrad her", "lock": "LÃĨs", "locked_folder": "LÃĨst mappe", + "log_detail_title": "Loggdetaljer", "log_out": "Logg ut", "log_out_all_devices": "Logg ut fra alle enheter", "logged_in_as": "Logget inn som {user}", @@ -1258,12 +1275,13 @@ "login_form_password_hint": "passord", "login_form_save_login": "Forbli innlogget", "login_form_server_empty": "Skriv inn en server-URL.", - "login_form_server_error": "Kan ikke koble til server.", + "login_form_server_error": "Kunne ikke koble til server.", "login_has_been_disabled": "Innlogging har blitt deaktivert.", "login_password_changed_error": "Det skjedde en feil ved oppdatering av passordet", "login_password_changed_success": "Passord oppdatert", - "logout_all_device_confirmation": "Er du sikker pÃĨ at du vil logge ut av alle enheter?", - "logout_this_device_confirmation": "Er du sikker pÃĨ at du vil logge ut av denne enheten?", + "logout_all_device_confirmation": "Vil du virkelig logge ut av alle enheter?", + "logout_this_device_confirmation": "Vil du virkelig logge ut av denne enheten?", + "logs": "Logger", "longitude": "Lengdegrad", "look": "Se", "loop_videos": "Gjenta Videoer", @@ -1281,14 +1299,14 @@ "manage_your_oauth_connection": "Administrer tilkoblingen din med OAuth", "map": "Kart", "map_assets_in_bounds": "{count, plural, =0 {Ingen bilder i dette omrÃĨdet} one {# photo} other {# photos}}", - "map_cannot_get_user_location": "Kan ikke hente brukerlokasjon", + "map_cannot_get_user_location": "Kunne ikke hente brukerlokasjon", "map_location_dialog_yes": "Ja", "map_location_picker_page_use_location": "Bruk denne lokasjonen", - "map_location_service_disabled_content": "Lokasjonstjeneste mÃĨ vÃĻre aktivert for ÃĨ vise objekter fra din nÃĨvÃĻrende lokasjon. Vil du aktivere det nÃĨ?", + "map_location_service_disabled_content": "Lokasjonstjeneste mÃĨ vÃĻre aktivert for ÃĨ vise elementer fra din nÃĨvÃĻrende lokasjon. Vil du aktivere det nÃĨ?", "map_location_service_disabled_title": "Lokasjonstjeneste deaktivert", "map_marker_for_images": "Kart makeringer for bilder tatt i {city}, {country}", "map_marker_with_image": "Kartmarkør med bilde", - "map_no_location_permission_content": "Lokasjonstilgang er pÃĨkrevet for ÃĨ vise objekter fra din nÃĨvÃĻrende lokasjon. Vil du tillate det nÃĨ?", + "map_no_location_permission_content": "Lokasjonstilgang er pÃĨkrevet for ÃĨ vise elementer fra din nÃĨvÃĻrende lokasjon. Vil du tillate det nÃĨ?", "map_no_location_permission_title": "Lokasjonstilgang avvist", "map_settings": "Kartinnstillinger", "map_settings_dark_mode": "Mørk modus", @@ -1306,6 +1324,7 @@ "mark_as_read": "Merk som lest", "marked_all_as_read": "Merket alle som lest", "matches": "Samsvarende", + "matching_assets": "Matchende elementer", "media_type": "Mediatype", "memories": "Minner", "memories_all_caught_up": "Alt utført", @@ -1335,17 +1354,18 @@ "move_to_lock_folder_action_prompt": "{count} lagt til i lÃĨst mappe", "move_to_locked_folder": "Flytt til lÃĨst mappe", "move_to_locked_folder_confirmation": "Disse bildene og videoene vil bli fjernet fra alle albumer, og kun tilgjengelige via den lÃĨste mappen", - "moved_to_archive": "Flyttet {count, plural, one {# objekt} other {# objekter}} til arkivet", - "moved_to_library": "Flyttet {count, plural, one {# objekt} other {# objekter}} til biblioteket", + "moved_to_archive": "Flyttet {count, plural, one {# element} other {# elementer}} til arkivet", + "moved_to_library": "Flyttet {count, plural, one {# element} other {# elementer}} til biblioteket", "moved_to_trash": "Flyttet til papirkurven", - "multiselect_grid_edit_date_time_err_read_only": "Kan ikke endre dato pÃĨ objekt(er) med kun lese-rettigheter, hopper over", - "multiselect_grid_edit_gps_err_read_only": "Kan ikke endre lokasjon pÃĨ objekt(er) med kun lese-rettigheter, hopper over", + "multiselect_grid_edit_date_time_err_read_only": "Kunne ikke endre dato pÃĨ element(er) med kun lese-rettigheter, hopper over", + "multiselect_grid_edit_gps_err_read_only": "Kunne ikke endre lokasjon pÃĨ element(er) med kun lese-rettigheter, hopper over", "mute_memories": "Demp minner", "my_albums": "Mine album", "name": "Navn", "name_or_nickname": "Navn eller kallenavn", "network_requirement_photos_upload": "Bruk mobildata for backup av bilder", "network_requirement_videos_upload": "Bruk mobildata for backup av videoer", + "network_requirements": "Nettverkskrav", "network_requirements_updated": "Nettverkskrav endret, resetter backupkø", "networking_settings": "Nettverk", "networking_subtitle": "Administrer serverendepunkt-innstillinger", @@ -1356,6 +1376,7 @@ "new_person": "Ny person", "new_pin_code": "Ny PIN-kode", "new_pin_code_subtitle": "Dette er første gang du ÃĨpner den lÃĨste mappen. Lag en PIN-kode for ÃĨ sikre tilgangen til denne siden", + "new_timeline": "Ny tidslinje", "new_user_created": "Ny bruker opprettet", "new_version_available": "NY VERSJON TILGJENGELIG", "newest_first": "Nyeste først", @@ -1367,22 +1388,27 @@ "no_albums_yet": "Det ser ut som om du ikke har noen album enda.", "no_archived_assets_message": "Arkiver bilder og videoer for ÃĨ skjule dem fra visningen av bildene dine", "no_assets_message": "KLIKK FOR Å LASTE OPP DITT FØRSTE BILDE", - "no_assets_to_show": "Ingen objekter ÃĨ vise", + "no_assets_to_show": "Ingen elementer ÃĨ vise", "no_cast_devices_found": "Ingen caste-enheter oppdaget", + "no_checksum_local": "Ingen sjekksum tilgjengelig - Kunne ikke hente lokale elementer", + "no_checksum_remote": "Ingen sjekksum tilgjengelig - Kunne ikke hente eksterne elementer", "no_duplicates_found": "Ingen duplikater ble funnet.", "no_exif_info_available": "Ingen EXIF-informasjon tilgjengelig", "no_explore_results_message": "Last opp flere bilder for ÃĨ utforske samlingen din.", "no_favorites_message": "Legg til favoritter for ÃĨ finne dine beste bilder og videoer raskt", "no_libraries_message": "Opprett et eksternt bibliotek for ÃĨ se bildene og videoene dine", + "no_local_assets_found": "Ingen lokale elementer funnet med denne sjekksummen", "no_locked_photos_message": "Bilder og videoer i den lÃĨste mappen er skjult og vil ikke vises nÃĨr du blar i biblioteket.", "no_name": "Ingen navn", "no_notifications": "Ingen varsler", "no_people_found": "Ingen samsvarende personer funnet", "no_places": "Ingen steder", + "no_remote_assets_found": "Ingen eksterne elementer funnet med denne sjekksummen", "no_results": "Ingen resultater", "no_results_description": "Prøv et synonym eller mer generelt søkeord", "no_shared_albums_message": "Opprett et album for ÃĨ dele bilder og videoer med personer i nettverket ditt", "no_uploads_in_progress": "Ingen opplasting pÃĨgÃĨr", + "not_available": "Ikke tilgjengelig", "not_in_any_album": "Ikke i noe album", "not_selected": "Ikke valgt", "note_apply_storage_label_to_previously_uploaded assets": "Merk: For ÃĨ bruke lagringsetiketten pÃĨ tidligere opplastede filer, kjør", @@ -1423,7 +1449,7 @@ "original": "original", "other": "Annet", "other_devices": "Andre enheter", - "other_entities": "Andre objekter", + "other_entities": "Andre elementer", "other_variables": "Andre variabler", "owned": "Dine", "owner": "Eier", @@ -1463,10 +1489,10 @@ "permanent_deletion_warning": "Advarsel om permanent sletting", "permanent_deletion_warning_setting_description": "Vis en advarsel ved permanent sletting av filer", "permanently_delete": "Slett permanent", - "permanently_delete_assets_count": "Slett {count, plural, one {objekt} other {objekter}} permanent", - "permanently_delete_assets_prompt": "Er du sikker pÃĨ at du vil permanent slette {count, plural, one {dette objektet?} other {disse # objektene?}} Dette vil ogsÃĨ slette {count, plural, one {det fra dets} other {de fra deres}} album(er).", + "permanently_delete_assets_count": "Slett {count, plural, one {element} other {elementer}} permanent", + "permanently_delete_assets_prompt": "Vil du virkelig permanent slette {count, plural, one {dette elementet?} other {disse # elementene?}} Dette vil ogsÃĨ slette {count, plural, one {det fra dets} other {de fra deres}} album(er).", "permanently_deleted_asset": "Filen har blitt permanent slettet", - "permanently_deleted_assets_count": "Permanent slett {count, plural, one {# objekt} other {# objekter}}", + "permanently_deleted_assets_count": "Permanent slett {count, plural, one {# element} other {# elementer}}", "permission": "Tillatelse", "permission_empty": "Dine tillatelser burde ikke vÃĻre tomme", "permission_onboarding_back": "Tilbake", @@ -1504,6 +1530,7 @@ "port": "Port", "preferences_settings_subtitle": "Administrer appens preferanser", "preferences_settings_title": "Innstillinger", + "preparing": "Forbereder", "preset": "ForhÃĨndsinstilling", "preview": "ForhÃĨndsvis", "previous": "Forrige", @@ -1520,7 +1547,7 @@ "profile_drawer_client_out_of_date_minor": "Mobilapp er utdatert. Vennligst oppdater til nyeste versjon.", "profile_drawer_client_server_up_to_date": "Klient og server er oppdatert", "profile_drawer_github": "GitHub", - "profile_drawer_readonly_mode": "Skrivebeskyttet modus er aktivert. Dobbelttrykk pÃĨ brukerens avatarikon for ÃĨ avslutte.", + "profile_drawer_readonly_mode": "Skrivebeskyttet modus er aktivert. Langttrykk pÃĨ brukerens avatarikon for ÃĨ avslutte.", "profile_drawer_server_out_of_date_major": "Server er utdatert. Vennligst oppdater til nyeste versjon.", "profile_drawer_server_out_of_date_minor": "Server er utdatert. Vennligst oppdater til nyeste versjon.", "profile_image_of_user": "Profil bilde av {user}", @@ -1538,7 +1565,7 @@ "purchase_button_reminder": "PÃĨminn meg om 30 dager", "purchase_button_remove_key": "Ta bort produktnøkkel", "purchase_button_select": "Velg", - "purchase_failed_activation": "Feilet med ÃĨ aktivere! Vennligst sjekk eposten for riktig produktnøkkel!", + "purchase_failed_activation": "Mislyktes med ÃĨ aktivere! Vennligst sjekk eposten for riktig produktnøkkel!", "purchase_individual_description_1": "For en person", "purchase_individual_description_2": "Støttespiller status", "purchase_individual_title": "Individuell", @@ -1552,14 +1579,14 @@ "purchase_per_server": "For hver server", "purchase_per_user": "For hver bruker", "purchase_remove_product_key": "Ta bor Produktnøkkel", - "purchase_remove_product_key_prompt": "Er du sikker pÃĨ at du vil ta bort produktnøkkelen?", + "purchase_remove_product_key_prompt": "Vil du virkelig ta bort produktnøkkelen?", "purchase_remove_server_product_key": "Ta bort Server Produktnøkkel", - "purchase_remove_server_product_key_prompt": "Er du sikker pÃĨ at du vil ta bort Server Produktnøkkelen?", + "purchase_remove_server_product_key_prompt": "Vil du virkelig ta bort Server Produktnøkkelen?", "purchase_server_description_1": "For hele serveren", "purchase_server_description_2": "Støttespiller status", "purchase_server_title": "Server", "purchase_settings_server_activated": "Produktnøkkel for server er administrert av administratoren", - "query_asset_id": "Forespør objektID", + "query_asset_id": "Forespør elementID", "queue_status": "Kø {count}/{total}", "rating": "Stjernevurdering", "rating_clear": "Slett vurdering", @@ -1569,9 +1596,10 @@ "read_changelog": "Les endringslogg", "readonly_mode_disabled": "Skrivebeskyttet modus deaktivert", "readonly_mode_enabled": "Skrivebeskyttet modus aktivert", + "ready_for_upload": "Klar for opplasting", "reassign": "Tilordne pÃĨ nytt", - "reassigned_assets_to_existing_person": "Flyttet {count, plural, one {# objekt} other {# objekter}} to {name, select, null {en eksisterende person} other {{name}}}", - "reassigned_assets_to_new_person": "Flyttet {count, plural, one {# objekt} other {# objekter}} til en ny person", + "reassigned_assets_to_existing_person": "Flyttet {count, plural, one {# element} other {# elementer}} to {name, select, null {en eksisterende person} other {{name}}}", + "reassigned_assets_to_new_person": "Flyttet {count, plural, one {# element} other {# elementer}} til en ny person", "reassing_hint": "Tilordne valgte eiendeler til en eksisterende person", "recent": "Nylig", "recent-albums": "Nylige album", @@ -1592,10 +1620,11 @@ "refreshing_metadata": "Oppdaterer matadata", "regenerating_thumbnails": "Regenererer miniatyrbilder", "remote": "Eksternt", - "remote_assets": "Eksterne objekter", + "remote_assets": "Eksterne elementer", + "remote_media_summary": "Oppsummering av eksterne media", "remove": "Fjern", - "remove_assets_album_confirmation": "Er du sikker pÃĨ at du fil slette {count, plural, one {# objekt} other {# objekter}} fra albumet?", - "remove_assets_shared_link_confirmation": "Er du sikker pÃĨ at du vil slette {count, plural, one {# objekt} other {# objekter}} fra den delte lenken?", + "remove_assets_album_confirmation": "Er du sikker pÃĨ at du fil slette {count, plural, one {# element} other {# elementer}} fra albumet?", + "remove_assets_shared_link_confirmation": "Vil du virkelig slette {count, plural, one {# element} other {# elementer}} fra den delte lenken?", "remove_assets_title": "Vil du fjerne eiendeler?", "remove_custom_date_range": "Fjern egendefinert datoperiode", "remove_deleted_assets": "Fjern fra frakoblede filer", @@ -1604,7 +1633,7 @@ "remove_from_favorites": "Fjern fra favoritter", "remove_from_lock_folder_action_prompt": "{count} fjernet fra lÃĨst mappe", "remove_from_locked_folder": "Fjern fra lÃĨst mappe", - "remove_from_locked_folder_confirmation": "Er du sikker pÃĨ at du vil flytte disse bildene og videoene ut av den lÃĨste mappen? De vil bli synlige i biblioteket.", + "remove_from_locked_folder_confirmation": "Vil du virkelig flytte disse bildene og videoene ut av den lÃĨste mappen? De vil bli synlige i biblioteket.", "remove_from_shared_link": "Fjern fra delt lenke", "remove_memory": "Slett minne", "remove_photo_from_memory": "Slett bilde fra dette minne", @@ -1617,7 +1646,7 @@ "removed_from_favorites_count": "{count, plural, other {Removed #}} fra favoritter", "removed_memory": "Slettet minne", "removed_photo_from_memory": "Slettet bilde fra minne", - "removed_tagged_assets": "Fjern tag fra {count, plural, one {# objekt} other {# objekter}}", + "removed_tagged_assets": "Fjern tag fra {count, plural, one {# element} other {# elementer}}", "rename": "Gi nytt navn", "repair": "Reparer", "repair_no_results_message": "Usporrede og savnede filer vil vises her", @@ -1634,17 +1663,18 @@ "reset_pin_code_success": "PIN-koden er tilbakestilt", "reset_pin_code_with_password": "Du kan alltid tilbakestiller PIN-koden med passordet ditt", "reset_sqlite": "Reset SQLite Databasen", - "reset_sqlite_confirmation": "Er du sikker pÃĨ at du vil resette SQLite databasen? Du blir nødt til ÃĨ logge ut og inn igjen for ÃĨ resynkronisere data", + "reset_sqlite_confirmation": "Vil du virkelig resette SQLite databasen? Du blir nødt til ÃĨ logge ut og inn igjen for ÃĨ resynkronisere data", "reset_sqlite_success": "Vellykket resetting av SQLite databasen", "reset_to_default": "Tilbakestill til standard", "resolve_duplicates": "Løs duplikater", "resolved_all_duplicates": "Løste alle duplikater", "restore": "Gjenopprett", "restore_all": "Gjenopprett alle", - "restore_trash_action_prompt": "{count} gjenopprettet fra søppelbøtten", + "restore_trash_action_prompt": "{count} gjenopprettet fra papirkurven", "restore_user": "Gjenopprett bruker", "restored_asset": "Gjenopprettet ressurs", "resume": "Fortsett", + "resume_paused_jobs": "Fortsett {count, plural, one {# paused job} other {# paused jobs}}", "retry_upload": "Prøv opplasting pÃĨ nytt", "review_duplicates": "GjennomgÃĨ duplikater", "review_large_files": "Se gjennom store filer", @@ -1696,7 +1726,7 @@ "search_options": "Søke alternativer", "search_page_categories": "Kategorier", "search_page_motion_photos": "Bevegelige bilder", - "search_page_no_objects": "Ingen objektinfo tilgjengelig", + "search_page_no_objects": "Ingen elementinfo tilgjengelig", "search_page_no_places": "Ingen stedsinformasjon er tilgjengelig", "search_page_screenshots": "Skjermbilder", "search_page_search_photos_videos": "Søk etter dine bilder og videoer", @@ -1735,7 +1765,7 @@ "select_person_to_tag": "Velg en person ÃĨ tagge", "select_photos": "Velg bilder", "select_trash_all": "Velg ÃĨ flytte alt til papirkurven", - "select_user_for_sharing_page_err_album": "Feilet ved oppretting av album", + "select_user_for_sharing_page_err_album": "Mislyktes ved oppretting av album", "selected": "Valgt", "selected_count": "{count, plural, other {# valgt}}", "selected_gps_coordinates": "Valgte GPS-koordinater", @@ -1771,10 +1801,10 @@ "setting_notifications_notify_minutes": "{count} minutter", "setting_notifications_notify_never": "aldri", "setting_notifications_notify_seconds": "{count} sekunder", - "setting_notifications_single_progress_subtitle": "Detaljert opplastingsinformasjon per objekt", + "setting_notifications_single_progress_subtitle": "Detaljert opplastingsinformasjon per element", "setting_notifications_single_progress_title": "Vis detaljert status pÃĨ sikkerhetskopiering i bakgrunnen", "setting_notifications_subtitle": "Juster notifikasjonsinnstillinger", - "setting_notifications_total_progress_subtitle": "Total opplastingsstatus (fullført/totalt objekter)", + "setting_notifications_total_progress_subtitle": "Total opplastingsstatus (fullført/totalt elementer)", "setting_notifications_total_progress_title": "Vis status pÃĨ sikkerhetskopiering i bakgrunnen", "setting_video_viewer_looping_title": "Looping", "setting_video_viewer_original_video_subtitle": "NÃĨr det streames en video fra serveren, spill originalkvaliteten selv om en omkodet versjon finnes. Dette kan medføre buffring. Videoer som er lagret lokalt pÃĨ enheten spilles i originalkvalitet uavhengig av denne innstillingen.", @@ -1784,7 +1814,7 @@ "settings_saved": "Innstillinger lagret", "setup_pin_code": "Sett opp en PINkode", "share": "Del", - "share_action_prompt": "Delte {count} objekter", + "share_action_prompt": "Delte {count} elementer", "share_add_photos": "Legg til bilder", "share_assets_selected": "{count} valgt", "share_dialog_preparing": "Forbereder ...", @@ -1818,7 +1848,7 @@ "shared_link_edit_expire_after_option_year": "{count} ÃĨr", "shared_link_edit_password_hint": "Skriv inn dele-passord", "shared_link_edit_submit_button": "Oppdater link", - "shared_link_error_server_url_fetch": "Kan ikke hente server-url", + "shared_link_error_server_url_fetch": "Kunne ikke hente server-url", "shared_link_expires_day": "UtgÃĨr om {count} dag", "shared_link_expires_days": "UtgÃĨr om {count} dager", "shared_link_expires_hour": "UtgÃĨr om {count} time", @@ -1849,10 +1879,8 @@ "shift_to_permanent_delete": "trykk ⇧ for ÃĨ slette eiendeler permanent", "show_album_options": "Vis albumalternativer", "show_albums": "Vis album", - "show_all_assets": "Via alle objekter", "show_all_people": "Vis alle mennesker", "show_and_hide_people": "Vis og skjul personer", - "show_assets_without_location": "Vis objekter uten lokasjon", "show_file_location": "Vis filplassering", "show_gallery": "Vis galleri", "show_hidden_people": "Vis skjulte personer", @@ -1869,6 +1897,7 @@ "show_slideshow_transition": "Vis overgang til lysbildefremvisning", "show_supporter_badge": "Supportermerke", "show_supporter_badge_description": "Vis et supportermerke", + "show_text_search_menu": "Vis tekstsøk meny", "shuffle": "Bland", "sidebar": "Sidefelt", "sidebar_display_description": "Vis en lenke for visningen i sidefeltet", @@ -1895,10 +1924,11 @@ "stack_duplicates": "Stable duplikater", "stack_select_one_photo": "Velg hovedbilde for bildestabbel", "stack_selected_photos": "Stable valgte bilder", - "stacked_assets_count": "Stable {count, plural, one {# objekt} other {# objekter}}", + "stacked_assets_count": "Stable {count, plural, one {# element} other {# elementer}}", "stacktrace": "Stakkspor", "start": "Start", "start_date": "Startdato", + "start_date_before_end_date": "Startdato mÃĨ vÃĻre før sluttdato", "state": "Fylke", "status": "Status", "stop_casting": "Stopp casting", @@ -1923,6 +1953,8 @@ "sync_albums_manual_subtitle": "Synkroniser alle opplastede videoer og bilder til det valgte backupalbumet", "sync_local": "Synkroniser lokalt", "sync_remote": "Synkroniser eksternt", + "sync_status": "Synkroniseringsstatus", + "sync_status_subtitle": "Vis og hÃĨndter synkronisering", "sync_upload_album_setting_subtitle": "Opprett og last opp dine bilder og videoer til det valgte albumet pÃĨ Immich", "tag": "Tagg", "tag_assets": "Merk ressurser", @@ -1931,15 +1963,15 @@ "tag_not_found_question": "Finner du ikke en merke? Opprett en nytt merke.", "tag_people": "Tag Folk", "tag_updated": "Oppdater merke: {tag}", - "tagged_assets": "Merket {count, plural, one {# objekt} other {# objekter}}", + "tagged_assets": "Merket {count, plural, one {# element} other {# elementer}}", "tags": "Merker", "tap_to_run_job": "Trykk for ÃĨ kjøre jobben", "template": "Mal", "theme": "Tema", "theme_selection": "Temavalg", "theme_selection_description": "Automatisk sett tema til lys eller mørk basert pÃĨ nettleserens systeminnstilling", - "theme_setting_asset_list_storage_indicator_title": "Vis lagringsindiaktor pÃĨ objekter i fotorutenettet", - "theme_setting_asset_list_tiles_per_row_title": "Antall objekter per rad ({count})", + "theme_setting_asset_list_storage_indicator_title": "Vis lagringsindiaktor pÃĨ elementer i fotorutenettet", + "theme_setting_asset_list_tiles_per_row_title": "Antall elementer per rad ({count})", "theme_setting_colorful_interface_subtitle": "Angi primÃĻrfarge til bakgrunner.", "theme_setting_colorful_interface_title": "Fargefullt grensesnitt", "theme_setting_image_viewer_quality_subtitle": "Juster kvaliteten pÃĨ bilder i detaljvisning", @@ -1971,17 +2003,18 @@ "trash_action_prompt": "{count} flyttet til søppel", "trash_all": "Slett alt", "trash_count": "Slett {count, number}", - "trash_delete_asset": "Slett objekt", - "trash_emptied": "Søppelbøtte tømt", + "trash_delete_asset": "Slett element", + "trash_emptied": "Søppelbøtte Tømt", "trash_no_results_message": "Her vises bilder og videoer som er flyttet til papirkurven.", "trash_page_delete_all": "Slett alt", - "trash_page_empty_trash_dialog_content": "Vil du tømme søppelbøtten? Objektene vil bli permanent fjernet fra Immich", - "trash_page_info": "Objekter i søppelbøtten blir permanent fjernet etter {days} dager", - "trash_page_no_assets": "Ingen forkastede objekter", + "trash_page_empty_trash_dialog_content": "Vil du Tømme papirkurven? Objektene vil bli permanent fjernet fra Immich", + "trash_page_info": "Objekter i papirkurven blir permanent fjernet etter {days} dager", + "trash_page_no_assets": "Ingen forkastede elementer", "trash_page_restore_all": "Gjenopprett alt", - "trash_page_select_assets_btn": "Velg objekter", + "trash_page_select_assets_btn": "Velg elementer", "trash_page_title": "Søppelbøtte ({count})", "trashed_items_will_be_permanently_deleted_after": "Elementer i papirkurven vil bli permanent slettet etter {days, plural, one {# dag} other {# dager}}.", + "troubleshoot": "Feilsøk", "type": "Type", "unable_to_change_pin_code": "Klarte ikke ÃĨ endre PIN-kode", "unable_to_setup_pin_code": "Klarte ikke ÃĨ sette opp PINkode", @@ -2001,7 +2034,7 @@ "unlinked_oauth_account": "Koblet fra OAuth-konto", "unmute_memories": "Opphev demping av minner", "unnamed_album": "Navnløst album", - "unnamed_album_delete_confirmation": "Er du sikker pÃĨ at du vil slette dette albumet?", + "unnamed_album_delete_confirmation": "Vil du virkelig slette dette albumet?", "unnamed_share": "Deling uten navn", "unsaved_change": "Ulagrede endringer", "unselect_all": "Fjern alle valg", @@ -2009,22 +2042,22 @@ "unselect_all_in": "Fjern velging av alle i {group}", "unstack": "avstable", "unstack_action_prompt": "{count} ustakket", - "unstacked_assets_count": "Ikke stablet {count, plural, one {# objekt} other {# objekter}}", + "unstacked_assets_count": "Ikke stablet {count, plural, one {# element} other {# elementer}}", "untagged": "Umerket", "up_next": "Neste", - "update_location_action_prompt": "Oppdater plasseringen til {count} valgte objekter med:", + "update_location_action_prompt": "Oppdater plasseringen til {count} valgte elementer med:", "updated_at": "Oppdatert", "updated_password": "Passord oppdatert", "upload": "Last opp", "upload_action_prompt": "{count} i kø for opplasting", "upload_concurrency": "Samtidig opplastning", "upload_details": "Opplastingsdetaljer", - "upload_dialog_info": "Vil du utføre backup av valgte objekt(er) til serveren?", - "upload_dialog_title": "Last opp objekt", + "upload_dialog_info": "Vil du utføre backup av valgte element(er) til serveren?", + "upload_dialog_title": "Last opp element", "upload_errors": "Opplasting fullført med {count, plural, one {# error} other {# errors}}, oppdater siden for ÃĨ se nye opplastingsressurser.", "upload_finished": "Opplasting fullført", "upload_progress": "GjenstÃĨende {remaining, number} – behandlet {processed, number}/{total, number}", - "upload_skipped_duplicates": "Hoppet over {count, plural, one {# duplisert objekt} other {# dupliserte objekter}}", + "upload_skipped_duplicates": "Hoppet over {count, plural, one {# duplisert element} other {# dupliserte elementer}}", "upload_status_duplicates": "Duplikater", "upload_status_errors": "Feil", "upload_status_uploaded": "Opplastet", @@ -2037,11 +2070,10 @@ "use_biometric": "Bruk biometri", "use_current_connection": "bruk nÃĨvÃĻrende tilkobling", "use_custom_date_range": "Bruk egendefinert datoperiode i stedet", - "use_this_location": "Trykk for ÃĨ bruke lokasjon", "user": "Bruker", "user_has_been_deleted": "Denne brukeren har blitt slettet.", "user_id": "Bruker ID", - "user_liked": "{user} likte {type, select, photo {dette bildet} video {denne videoen} asset {dette objektet} other {dette}}", + "user_liked": "{user} likte {type, select, photo {dette bildet} video {denne videoen} asset {dette elementet} other {dette}}", "user_pin_code_settings": "PINkode", "user_pin_code_settings_description": "HÃĨndter din PINkode", "user_privacy": "Personverninnstillinger", @@ -2084,7 +2116,7 @@ "view_stack": "Vis stabel", "view_user": "Vis bruker", "viewer_remove_from_stack": "Fjern fra stabling", - "viewer_stack_use_as_main_asset": "Bruk som hovedobjekt", + "viewer_stack_use_as_main_asset": "Bruk som hovedelement", "viewer_unstack": "avstable", "visibility_changed": "Synlighet endret for {count, plural, one {# person} other {# people}}", "waiting": "Venter", @@ -2099,5 +2131,6 @@ "yes": "Ja", "you_dont_have_any_shared_links": "Du har ingen delte lenker", "your_wifi_name": "Ditt Wi-Fi-navn", - "zoom_image": "Zoom Bilde" + "zoom_image": "Zoom Bilde", + "zoom_to_bounds": "Zoom til grensene" } diff --git a/i18n/nl.json b/i18n/nl.json index 29a60f8844..28be27f00f 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -28,10 +28,12 @@ "add_to_album": "Aan album toevoegen", "add_to_album_bottom_sheet_added": "Toegevoegd aan {album}", "add_to_album_bottom_sheet_already_exists": "Staat al in {album}", + "add_to_album_bottom_sheet_some_local_assets": "Sommige lokale items konden niet aan album toegevoegd worden", "add_to_album_toggle": "Selectie inschakelen voor {album}", "add_to_albums": "Toevoegen aan albums", "add_to_albums_count": "Toevoegen aan albums ({count})", "add_to_shared_album": "Aan gedeeld album toevoegen", + "add_upload_to_stack": "Voeg upload toe aan stack", "add_url": "URL toevoegen", "added_to_archive": "Toegevoegd aan archief", "added_to_favorites": "Toegevoegd aan favorieten", @@ -41,7 +43,7 @@ "admin_user": "Beheerder gebruiker", "asset_offline_description": "Dit item uit een externe bibliotheek is niet meer beschikbaar op de schijf en is naar de prullenbak verplaatst. Als het bestand binnen de bibliotheek is verplaatst, controleer dan je tijdlijn voor het nieuwe bijbehorende item. Om dit bestand te herstellen, zorg ervoor dat het onderstaande bestandspad toegankelijk is voor Immich en scan de bibliotheek opnieuw.", "authentication_settings": "Authenticatie-instellingen", - "authentication_settings_description": "Wachtwoord, OAuth, en andere authenticatie-instellingen beheren", + "authentication_settings_description": "Wachtwoord-, OAuth-, en andere authenticatie-instellingen beheren", "authentication_settings_disable_all": "Weet je zeker dat je alle inlogmethoden wilt uitschakelen? Inloggen zal volledig worden uitgeschakeld.", "authentication_settings_reenable": "Gebruik een servercommando om opnieuw in te schakelen.", "background_task_job": "Achtergrondtaken", @@ -64,7 +66,7 @@ "confirm_email_below": "Typ hieronder \"{email}\" ter bevestiging", "confirm_reprocess_all_faces": "Weet je zeker dat je alle gezichten opnieuw wilt verwerken? Hiermee worden ook alle mensen gewist.", "confirm_user_password_reset": "Weet je zeker dat je het wachtwoord van {user} wilt resetten?", - "confirm_user_pin_code_reset": "Weet je zeker dat je de PIN code van {user} wilt resetten?", + "confirm_user_pin_code_reset": "Weet je zeker dat je de pincode van {user} wilt resetten?", "create_job": "Taak maken", "cron_expression": "Cron expressie", "cron_expression_description": "Stel het scaninterval in met het cron-formaat. Voor meer informatie kun je bijvoorbeeld kijken naar Crontab Guru", @@ -85,7 +87,7 @@ "image_fullsize_enabled_description": "Genereer afbeelding op volledig formaat voor niet-webvriendelijke formaten. Als “Verkies ingesloten voorbeeldafbeelding” is ingeschakeld, worden ingesloten voorvertoningen direct gebruikt zonder conversie. Heeft geen invloed op webvriendelijke formaten zoals JPEG.", "image_fullsize_quality_description": "Beeldkwaliteit op ware grootte van 1-100. Hoger is beter, maar genereert grotere bestanden.", "image_fullsize_title": "Instellingen afbeelding op ware grootte", - "image_prefer_embedded_preview": "Verkies ingesloten voorbeeldafbeelding", + "image_prefer_embedded_preview": "Voorkeur geven aan ingesloten voorbeeldafbeelding", "image_prefer_embedded_preview_setting_description": "Gebruik ingesloten voorbeeldafbeelding van RAW-bestanden als invoer voor beeldverwerking wanneer beschikbaar. Dit kan preciezere kleuren produceren voor sommige afbeeldingen, maar de kwaliteit van het voorbeeld is afhankelijk van de camera en de afbeelding kan mogelijk meer compressie-artefacten bevatten.", "image_prefer_wide_gamut": "Voorkeur geven aan wide gamut", "image_prefer_wide_gamut_setting_description": "Display P3 gebruiken voor voorbeeldafbeeldingen. Dit behoudt de levendigheid van afbeeldingen met brede kleurruimtes beter, maar afbeeldingen kunnen er anders uitzien op oude apparaten met een oude browserversie. sRGB-afbeeldingen blijven sRGB gebruiken om kleurverschuivingen te vermijden.", @@ -102,7 +104,7 @@ "image_thumbnail_title": "Thumbnailinstellingen", "job_concurrency": "{job} gelijktijdigheid", "job_created": "Taak aangemaakt", - "job_not_concurrency_safe": "Deze taak kan niet gelijktijdig worden uitgevoerd.", + "job_not_concurrency_safe": "Deze taak kan niet parallel worden uitgevoerd.", "job_settings": "Achtergrondtaak-instellingen", "job_settings_description": "Beheer aantal gelijktijdige taken", "job_status": "Taakstatus", @@ -122,13 +124,20 @@ "library_watching_settings_description": "Automatisch gewijzigde bestanden bijhouden", "logging_enable_description": "Logboek inschakelen", "logging_level_description": "Indien ingeschakeld, welk logniveau er wordt gebruikt.", - "logging_settings": "Logging", - "machine_learning_clip_model": "CLIP model", - "machine_learning_clip_model_description": "De naam van een CLIP-model dat hier is vermeld. Let op: je moet de 'Slim Zoeken -taak opnieuw uitvoeren voor alle afbeeldingen wanneer je een model wijzigt.", - "machine_learning_duplicate_detection": "Duplicaat detectie", + "logging_settings": "Logboek", + "machine_learning_availability_checks": "Beschikbaarheidscontroles", + "machine_learning_availability_checks_description": "Automatisch detecteren en selecteren van beschikbare machine learning servers", + "machine_learning_availability_checks_enabled": "Activeer beschikbaarheidscontroles", + "machine_learning_availability_checks_interval": "Controleinterval", + "machine_learning_availability_checks_interval_description": "Interval in milliseconden tussen beschikbaarheidscontroles", + "machine_learning_availability_checks_timeout": "Verzoek time-out", + "machine_learning_availability_checks_timeout_description": "Time-out in milliseconden voor beschikbaarheidscontroles", + "machine_learning_clip_model": "CLIP-model", + "machine_learning_clip_model_description": "De naam van een CLIP-model dat hier is vermeld. Let op: je moet de 'Slim Zoeken'-taak voor alle afbeeldingen opnieuw uitvoeren wanneer je een model wijzigt.", + "machine_learning_duplicate_detection": "Duplicaatdetectie", "machine_learning_duplicate_detection_enabled": "Duplicaatdetectie inschakelen", "machine_learning_duplicate_detection_enabled_description": "Indien uitgeschakeld, worden identieke items nog steeds gededupliceerd.", - "machine_learning_duplicate_detection_setting_description": "Gebruik CLIP om exactie kopieÃĢn te vinden", + "machine_learning_duplicate_detection_setting_description": "Gebruik CLIP-embeddings om mogelijke kopieÃĢn te vinden", "machine_learning_enabled": "Machine learning inschakelen", "machine_learning_enabled_description": "Wanneer uitgeschakeld zullen alle ML instellingen uitgezet worden, ongeacht onderstaande instellingen.", "machine_learning_facial_recognition": "Gezichtsherkenning", @@ -156,8 +165,8 @@ "manage_log_settings": "Beheer logboekinstellingen", "map_dark_style": "Donkere stijl", "map_enable_description": "Kaartfuncties inschakelen", - "map_gps_settings": "Kaart & GPS Instellingen", - "map_gps_settings_description": "Beheer kaart & GPS (omgekeerde geocodering) instellingen", + "map_gps_settings": "Kaart- & gps-instellingen", + "map_gps_settings_description": "Beheer kaart- & gps-instellingen (omgekeerde geocodering)", "map_implications": "De kaartfunctie is afhankelijk van een externe service (tiles.immich.cloud)", "map_light_style": "Lichte stijl", "map_manage_reverse_geocoding_settings": "Beheer omgekeerde geocodering instellingen", @@ -170,27 +179,27 @@ "memory_cleanup_job": "Herinneringen opschonen", "memory_generate_job": "Herinneringen genereren", "metadata_extraction_job": "Metadata ophalen", - "metadata_extraction_job_description": "Metadata ophalen van ieder item, zoals GPS, gezichten en resolutie", + "metadata_extraction_job_description": "Metadata ophalen van ieder item, zoals gps, gezichten en resolutie", "metadata_faces_import_setting": "Gezichten importeren inschakelen", "metadata_faces_import_setting_description": "Gezichten importeren uit EXIF-gegevens van afbeeldingen en sidecar bestanden", - "metadata_settings": "Metadata instellingen", - "metadata_settings_description": "Beheer metadata instellingen", + "metadata_settings": "Metadata-instellingen", + "metadata_settings_description": "Beheer metadata-instellingen", "migration_job": "Migratie", "migration_job_description": "Migreer thumbnails voor items en gezichten naar de nieuwste mapstructuur", "nightly_tasks_cluster_faces_setting_description": "Gezichtsherkenning uitvoeren op nieuw gedetecteerde gezichten", "nightly_tasks_cluster_new_faces_setting": "Cluster nieuwe gezichten", - "nightly_tasks_database_cleanup_setting": "Database opschoon taken", - "nightly_tasks_database_cleanup_setting_description": "Ruim oude data op van de database", + "nightly_tasks_database_cleanup_setting": "Database-opruimtaken", + "nightly_tasks_database_cleanup_setting_description": "Ruim oude, niet meer geldige data op uit de database", "nightly_tasks_generate_memories_setting": "Genereer herinneringen", "nightly_tasks_generate_memories_setting_description": "Maak nieuwe herinneringen van items", "nightly_tasks_missing_thumbnails_setting": "Genereer ontbrekende thumbnails", "nightly_tasks_missing_thumbnails_setting_description": "Items zonder thumbnail in een wachtrij plaatsen voor het genereren van thumbnails", - "nightly_tasks_settings": "Instellingen voor nacht taken", - "nightly_tasks_settings_description": "Beheer nacht taken", - "nightly_tasks_start_time_setting": "Start tijd", - "nightly_tasks_start_time_setting_description": "De tijd waarop de server begint met het uitvoeren van de nacht taken", - "nightly_tasks_sync_quota_usage_setting": "Synchroniseer quota gebruik", - "nightly_tasks_sync_quota_usage_setting_description": "update gebruiker opslag quota, gebaseerd op huidig gebruik", + "nightly_tasks_settings": "Instellingen voor nachtelijke taken", + "nightly_tasks_settings_description": "Beheer nachtelijke taken", + "nightly_tasks_start_time_setting": "Starttijd", + "nightly_tasks_start_time_setting_description": "De tijd waarop de server begint met het uitvoeren van de nachtelijke taken", + "nightly_tasks_sync_quota_usage_setting": "Synchroniseer opslaglimieten", + "nightly_tasks_sync_quota_usage_setting_description": "Update opslaglimieten van gebruikers, gebaseerd op huidig gebruik", "no_paths_added": "Geen paden toegevoegd", "no_pattern_added": "Geen patroon toegevoegd", "note_apply_storage_label_previous_assets": "Opmerking: om het opslaglabel toe te passen op eerder geÃŧploade items, voer de volgende taak uit", @@ -265,12 +274,12 @@ "storage_template_date_time_sample": "Voorbeeldtijd {date}", "storage_template_enable_description": "Engine voor opslagtemplate inschakelen", "storage_template_hash_verification_enabled": "Hashverificatie ingeschakeld", - "storage_template_hash_verification_enabled_description": "Zet hashverificatie aan, schakel dit niet uit tenzij je zeker bent van de implicaties", + "storage_template_hash_verification_enabled_description": "Zet hashverificatie aan. Schakel dit niet uit tenzij je zeker bent van de gevolgen", "storage_template_migration": "Opslagtemplate migratie", "storage_template_migration_description": "Pas de huidige {template} toe op eerder geÃŧploade items", "storage_template_migration_info": "Wijzigingen in de opslagtemplate worden alleen toegepast op nieuwe items. Om de template met terugwerkende kracht toe te passen op eerder geÃŧploade items, voer je de {job} uit.", "storage_template_migration_job": "Opslagtemplate migratietaak", - "storage_template_more_details": "Voor meer details over deze functie, bekijk de Opslagstemplate en de implicaties daarvan", + "storage_template_more_details": "Meer details over deze functie vind je onder Opslagtemplate, net als de gevolgen daarvan", "storage_template_onboarding_description_v2": "Wanneer ingeschakeld, zal deze functie bestanden automatisch organiseren gebaseerd op een template gedefinieerd door de gebruiker. Voor meer informatie, bekijk de documentatie.", "storage_template_path_length": "Geschatte padlengte: {length, number}/{limit, number}", "storage_template_settings": "Opslagtemplate", @@ -293,7 +302,7 @@ "theme_settings_description": "Beheer het uiterlijk van de Immich webinterface", "thumbnail_generation_job": "Thumbnail genereren", "thumbnail_generation_job_description": "Genereer grote, kleine en vervaagde thumbnails voor ieder item, en genereer thumbnails voor iedere persoon", - "transcoding_acceleration_api": "Acceleration API", + "transcoding_acceleration_api": "Versnelling API", "transcoding_acceleration_api_description": "De API die met je apparaat zal communiceren om transcodering te versnellen. Deze instelling is 'best effort': wanneer fouten optreden wordt teruggevallen op softwaretranscodering. VP9 kan wel of niet werken, afhankelijk van je hardware.", "transcoding_acceleration_nvenc": "NVENC (vereist NVIDIA GPU)", "transcoding_acceleration_qsv": "Quick Sync (vereist 7e generatie Intel CPU of nieuwer)", @@ -312,7 +321,7 @@ "transcoding_codecs_learn_more": "Om meer te leren over de terminologie die hier wordt gebruikt, bekijk de FFmpeg documentatie voor H.264 codec, HEVC codec en VP9 codec.", "transcoding_constant_quality_mode": "Constante kwaliteit modus", "transcoding_constant_quality_mode_description": "ICQ is beter dan CQP, maar sommige hardware versnellingsmethodes ondersteunen deze modus niet. Als u deze optie instelt, wordt de voorkeur gegeven aan de opgegeven modus bij gebruik van op kwaliteit gebaseerde encoding. Deze optie wordt genegeerd door NVENC omdat het ICQ niet ondersteunt.", - "transcoding_constant_rate_factor": "Constant rate factor (-crf)", + "transcoding_constant_rate_factor": "Constant tarief factor (-ctf)", "transcoding_constant_rate_factor_description": "Niveau voor videokwaliteit. Typische waarden zijn 23 voor H.264, 28 voor HEVC, 31 voor VP9 en 35 voor AV1. Lager is beter, maar produceert grotere bestanden.", "transcoding_disabled_description": "Transcodeer geen video's. Het afspelen kan op sommige clients niet meer werken", "transcoding_encoding_options": "Coderings Opties", @@ -325,7 +334,7 @@ "transcoding_max_b_frames_description": "Hogere waarden verbeteren de compressie efficiÃĢntie, maar vertragen de codering. Is mogelijk niet compatibel met hardwareversnelling op oudere apparaten. 0 schakelt B-frames uit, terwijl -1 deze waarde automatisch instelt.", "transcoding_max_bitrate": "Maximum bitrate", "transcoding_max_bitrate_description": "Het instellen van een maximale bitrate kan de bestandsgrootte voorspelbaarder maken, tegen geringe kosten voor de kwaliteit. Bij 720p zijn de typische waarden 2600 kbit/s voor VP9 of HEVC, of 4500 kbit/s voor H.264. Uitgeschakeld indien ingesteld op 0.", - "transcoding_max_keyframe_interval": "Maximum keyframe interval", + "transcoding_max_keyframe_interval": "Maximale keyframe interval", "transcoding_max_keyframe_interval_description": "Stelt de maximale frameafstand tussen keyframes in. Lagere waarden verslechteren de compressie efficiÃĢntie, maar verbeteren de zoektijden en kunnen de kwaliteit verbeteren in scènes met snelle bewegingen. 0 stelt deze waarde automatisch in.", "transcoding_optimal_description": "Video's met een hogere resolutie dan de doelresolutie of niet in een geaccepteerd formaat", "transcoding_policy": "Transcode beleid", @@ -341,11 +350,11 @@ "transcoding_settings_description": "Beheer welke videos worden getranscodeerd en hoe ze worden verwerkt", "transcoding_target_resolution": "Target resolutie", "transcoding_target_resolution_description": "Hogere resoluties kunnen meer details behouden, maar het coderen ervan duurt langer, de bestandsgrootte is groter en de app reageert mogelijk minder snel.", - "transcoding_temporal_aq": "Temporal AQ", + "transcoding_temporal_aq": "Tijdelijke AQ", "transcoding_temporal_aq_description": "Alleen van toepassing op NVENC. Verhoogt de kwaliteit van scènes met veel details en weinig beweging. Is mogelijk niet compatibel met oudere apparaten.", "transcoding_threads": "Threads", "transcoding_threads_description": "Hogere waarden leiden tot snellere codering, maar laten minder ruimte over voor de server om andere taken te verwerken terwijl deze actief is. Deze waarde mag niet groter zijn dan het aantal CPU cores. Maximaliseert het gebruik als deze is ingesteld op 0.", - "transcoding_tone_mapping": "Tone-mapping", + "transcoding_tone_mapping": "Tone mapping", "transcoding_tone_mapping_description": "Probeert het uiterlijk van HDR-video's te behouden wanneer ze worden geconverteerd naar SDR. Elk algoritme maakt verschillende afwegingen voor kleur, detail en helderheid. Hable behoudt detail, Mobius behoudt kleur en Reinhard behoudt helderheid.", "transcoding_transcode_policy": "Transcodeerbeleid", "transcoding_transcode_policy_description": "Beleid voor wanneer een video getranscodeerd moet worden. HDR-video's worden altijd getranscodeerd (behalve als transcodering is uitgeschakeld).", @@ -364,7 +373,7 @@ "user_cleanup_job": "Gebruiker opschoning", "user_delete_delay": "Het account en de items van {user} worden over {delay, plural, one {# dag} other {# dagen}} permanent verwijderd.", "user_delete_delay_settings": "Verwijder vertraging", - "user_delete_delay_settings_description": "Aantal dagen na verwijdering om het account en de items van een gebruiker permanent te verwijderen. De taak voor het verwijderen van gebruikers wordt om middernacht uitgevoerd om te controleren of gebruikers verwijderd kunnen worden. Wijzigingen in deze instelling worden bij de volgende uitvoering meegenomen.", + "user_delete_delay_settings_description": "Aantal dagen na verwijdering om het account en de items van een gebruiker permanent te verwijderen. De taak voor het verwijderen van gebruikers wordt om middernacht uitgevoerd om te controleren of gebruiker te verwijderen zijn. Wijzigingen in deze instelling worden bij de volgende uitvoering meegenomen.", "user_delete_immediately": "Het account en de items van {user} worden onmiddellijk in de wachtrij geplaatst voor permanente verwijdering.", "user_delete_immediately_checkbox": "Gebruikers en items in de wachtrij plaatsen voor onmiddellijke verwijdering", "user_details": "Gebruiker details", @@ -387,8 +396,6 @@ "admin_password": "Beheerder wachtwoord", "administration": "Beheer", "advanced": "Geavanceerd", - "advanced_settings_beta_timeline_subtitle": "Probeer de nieuwe app-ervaring", - "advanced_settings_beta_timeline_title": "Beta tijdlijn", "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": "Logniveau: {level}", @@ -410,9 +417,9 @@ "age_years": "{years, plural, other {Leeftijd #}}", "album_added": "Album toegevoegd", "album_added_notification_setting_description": "Ontvang een e-mailmelding wanneer je aan een gedeeld album wordt toegevoegd", - "album_cover_updated": "Album cover is bijgewerkt", + "album_cover_updated": "Albumomslag is bijgewerkt", "album_delete_confirmation": "Weet je zeker dat je het album {album} wilt verwijderen?", - "album_delete_confirmation_description": "Als dit album gedeeld is, hebben andere gebruikers er geen toegang meer toe.", + "album_delete_confirmation_description": "Als dit album gedeeld is, zullen andere gebruikers geen toegang meer hebben.", "album_deleted": "Album verwijderd", "album_info_card_backup_album_excluded": "UITGESLOTEN", "album_info_card_backup_album_included": "INBEGREPEN", @@ -425,6 +432,7 @@ "album_remove_user_confirmation": "Weet je zeker dat je {user} wilt verwijderen?", "album_search_not_found": "Geen albums gevonden die aan je zoekopdracht voldoen", "album_share_no_users": "Het lijkt erop dat je dit album met alle gebruikers hebt gedeeld, of dat je geen gebruikers hebt om mee te delen.", + "album_summary": "Album samenvatting", "album_updated": "Album bijgewerkt", "album_updated_setting_description": "Ontvang een e-mailmelding wanneer een gedeeld album nieuwe items heeft", "album_user_left": "{album} verlaten", @@ -496,6 +504,8 @@ "asset_restored_successfully": "Item succesvol hersteld", "asset_skipped": "Overgeslagen", "asset_skipped_in_trash": "In prullenbak", + "asset_trashed": "Asset verwijderd", + "asset_troubleshoot": "Asset probleemoplossing", "asset_uploaded": "GeÃŧpload", "asset_uploading": "Uploadenâ€Ļ", "asset_viewer_settings_subtitle": "Beheer je instellingen voor galerijweergave", @@ -529,8 +539,10 @@ "autoplay_slideshow": "Diavoorstelling automatisch afspelen", "back": "Terug", "back_close_deselect": "Terug, sluiten of deselecteren", + "background_backup_running_error": "Achtergrond backup draait, handmatige backup kan niet worden gestart", "background_location_permission": "Achtergrond locatie toestemming", "background_location_permission_content": "Om van netwerk te wisselen terwijl de app op de achtergrond draait, heeft Immich *altijd* toegang tot de exacte locatie nodig om de naam van het WiFi-netwerk te kunnen lezen", + "background_options": "Achtergrond opties", "backup": "Back-up", "backup_album_selection_page_albums_device": "Albums op apparaat ({count})", "backup_album_selection_page_albums_tap": "Tik om op te nemen, dubbel tik om uit te sluiten", @@ -538,6 +550,7 @@ "backup_album_selection_page_select_albums": "Selecteer albums", "backup_album_selection_page_selection_info": "Selectie info", "backup_album_selection_page_total_assets": "Totaal unieke items", + "backup_albums_sync": "Backup albums synchronisatie", "backup_all": "Alle", "backup_background_service_backup_failed_message": "Fout bij het back-uppen van de items. Opnieuw proberenâ€Ļ", "backup_background_service_connection_failed_message": "Fout bij het verbinden met de server. Opnieuw proberenâ€Ļ", @@ -587,6 +600,7 @@ "backup_controller_page_turn_on": "Back-up op de voorgrond aanzetten", "backup_controller_page_uploading_file_info": "Bestandsgegevens uploaden", "backup_err_only_album": "Kan het enige album niet verwijderen", + "backup_error_sync_failed": "Synchronisatie mislukt. Kan back-up niet verwerken.", "backup_info_card_assets": "bestanden", "backup_manual_cancelled": "Geannuleerd", "backup_manual_in_progress": "Het uploaden is al bezig. Probeer het na een tijdje", @@ -597,8 +611,6 @@ "backup_setting_subtitle": "Beheer achtergrond en voorgrond uploadinstellingen", "backup_settings_subtitle": "Beheer upload instellingen", "backward": "Achteruit", - "beta_sync": "Beta Sync Status", - "beta_sync_subtitle": "Beheer het nieuwe synchronisatiesysteem", "biometric_auth_enabled": "Biometrische authenticatie ingeschakeld", "biometric_locked_out": "Biometrische authenticatie is vergrendeld", "biometric_no_options": "Geen biometrische opties beschikbaar", @@ -653,9 +665,11 @@ "change_password_form_new_password": "Nieuw wachtwoord", "change_password_form_password_mismatch": "Wachtwoorden komen niet overeen", "change_password_form_reenter_new_password": "Vul het wachtwoord opnieuw in", - "change_pin_code": "Wijzig PIN code", + "change_pin_code": "Wijzig pincode", "change_your_password": "Wijzig je wachtwoord", "changed_visibility_successfully": "Zichtbaarheid succesvol gewijzigd", + "charging": "Opladen", + "charging_requirement_mobile_backup": "Achtergrond backup vereist dat het apparaat wordt opgeladen", "check_corrupt_asset_backup": "Controleer op corrupte back-ups van items", "check_corrupt_asset_backup_button": "Controle uitvoeren", "check_corrupt_asset_backup_description": "Voer deze controle alleen uit via WiFi en nadat alle items zijn geback-upt. De procedure kan een paar minuten duren.", @@ -694,7 +708,7 @@ "confirm_delete_face": "Weet je zeker dat je het gezicht van {name} wilt verwijderen uit het item?", "confirm_delete_shared_link": "Weet je zeker dat je deze gedeelde link wilt verwijderen?", "confirm_keep_this_delete_others": "Alle andere items in de stack worden verwijderd, behalve deze. Weet je zeker dat je wilt doorgaan?", - "confirm_new_pin_code": "Bevestig nieuwe PIN code", + "confirm_new_pin_code": "Bevestig nieuwe pincode", "confirm_password": "Bevestig wachtwoord", "confirm_tag_face": "Wil je dit gezicht taggen als {name}?", "confirm_tag_face_unnamed": "Wil je dit gezicht taggen?", @@ -710,7 +724,7 @@ "control_bottom_app_bar_edit_time": "Datum & tijd bewerken", "control_bottom_app_bar_share_link": "Link delen", "control_bottom_app_bar_share_to": "Delen met", - "control_bottom_app_bar_trash_from_immich": "Verwijderen uit Immich", + "control_bottom_app_bar_trash_from_immich": "Verwijderen van Immich", "copied_image_to_clipboard": "Afbeelding gekopieerd naar klembord.", "copied_to_clipboard": "Gekopieerd naar klembord!", "copy_error": "Fout bij kopiÃĢren", @@ -722,7 +736,7 @@ "copy_to_clipboard": "KopiÃĢren naar klembord", "country": "Land", "cover": "Bedekken", - "covers": "Covers", + "covers": "Omslagen", "create": "Aanmaken", "create_album": "Album aanmaken", "create_album_page_untitled": "Naamloos", @@ -742,10 +756,11 @@ "create_user": "Gebruiker aanmaken", "created": "Aangemaakt", "created_at": "Aangemaakt", + "creating_linked_albums": "Gekoppelde albums worden aangemaakt...", "crop": "Bijsnijden", "curated_object_page_title": "Dingen", "current_device": "Huidig apparaat", - "current_pin_code": "Huidige PIN code", + "current_pin_code": "Huidige pincode", "current_server_address": "Huidig serveradres", "custom_locale": "Aangepaste landinstelling", "custom_locale_description": "Formatteer datums en getallen op basis van de taal en de regio", @@ -807,7 +822,7 @@ "disabled": "Uitgeschakeld", "disallow_edits": "Geen bewerkingen toestaan", "discord": "Discord", - "discover": "Zoeken", + "discover": "Zoek", "discovered_devices": "Gevonden apparaten", "dismiss_all_errors": "Negeer alle fouten", "dismiss_error": "Negeer fout", @@ -827,7 +842,7 @@ "download_failed": "Download mislukt", "download_finished": "Download voltooid", "download_include_embedded_motion_videos": "Ingesloten video's", - "download_include_embedded_motion_videos_description": "Voeg video's toe die ingesloten zijn in bewegende foto's als een apart bestand", + "download_include_embedded_motion_videos_description": "Voeg video's die in bewegingsfoto's zijn ingebed toe als een apart bestand", "download_notfound": "Download niet gevonden", "download_paused": "Download gepauseerd", "download_settings": "Downloaden", @@ -837,7 +852,7 @@ "download_sucess_android": "Het bestand is gedownload naar DCIM/Immich", "download_waiting_to_retry": "Wachten om opnieuw te proberen", "downloading": "Downloaden", - "downloading_asset_filename": "Item {filename} downloaden...", + "downloading_asset_filename": "Downloaden asset {filename}", "downloading_media": "Media aan het downloaden", "drop_files_to_upload": "Zet bestanden ergens neer om ze te uploaden", "duplicates": "Duplicaten", @@ -891,7 +906,9 @@ "error": "Fout", "error_change_sort_album": "Sorteervolgorde van album wijzigen mislukt", "error_delete_face": "Fout bij verwijderen van gezicht uit het item", + "error_getting_places": "Fout bij ophalen plaatsen", "error_loading_image": "Fout bij laden afbeelding", + "error_loading_partners": "Fout bij ophalen partners: {error}", "error_saving_image": "Fout: {error}", "error_tag_face_bounding_box": "Fout bij taggen van gezicht - kan coÃļrdinaten van omvattend kader niet ophalen", "error_title": "Fout - Er is iets misgegaan", @@ -924,7 +941,7 @@ "failed_to_load_notifications": "Kon meldingen niet laden", "failed_to_load_people": "Kan mensen niet laden", "failed_to_remove_product_key": "Fout bij het verwijderen van de licentiesleutel", - "failed_to_reset_pin_code": "Resetten van PIN code mislukt", + "failed_to_reset_pin_code": "Resetten van pincode mislukt", "failed_to_stack_assets": "Fout bij stapelen van items", "failed_to_unstack_assets": "Fout bij ontstapelen van items", "failed_to_update_notification_status": "Kon notificatiestatus niet updaten", @@ -989,7 +1006,7 @@ "unable_to_remove_partner": "Kan partner niet verwijderen", "unable_to_remove_reaction": "Kan reactie niet verwijderen", "unable_to_reset_password": "Kan wachtwoord niet resetten", - "unable_to_reset_pin_code": "Kan PIN code niet resetten", + "unable_to_reset_pin_code": "Kan pincode niet resetten", "unable_to_resolve_duplicate": "Kan duplicaat niet oplossen", "unable_to_restore_assets": "Kan items niet herstellen", "unable_to_restore_trash": "Kan niet herstellen uit prullenbak", @@ -1008,7 +1025,7 @@ "unable_to_trash_asset": "Kan item niet naar prullenbak verplaatsen", "unable_to_unlink_account": "Kan account niet ontkoppelen", "unable_to_unlink_motion_video": "Kan bewegende video niet ontkoppelen", - "unable_to_update_album_cover": "Kan album cover niet bijwerken", + "unable_to_update_album_cover": "Kan albumomslag niet bijwerken", "unable_to_update_album_info": "Kan albumgegevens niet bijwerken", "unable_to_update_library": "Kan bibliotheek niet bijwerken", "unable_to_update_location": "Kan locatie niet bijwerken", @@ -1022,6 +1039,7 @@ "exif_bottom_sheet_description_error": "Fout bij het bijwerken van de beschrijving", "exif_bottom_sheet_details": "DETAILS", "exif_bottom_sheet_location": "LOCATIE", + "exif_bottom_sheet_no_description": "Geen beschrijving", "exif_bottom_sheet_people": "MENSEN", "exif_bottom_sheet_person_add_person": "Naam toevoegen", "exit_slideshow": "Diavoorstelling sluiten", @@ -1056,6 +1074,7 @@ "favorites_page_no_favorites": "Geen favoriete items gevonden", "feature_photo_updated": "Uitgelichte afbeelding bijgewerkt", "features": "Functies", + "features_in_development": "Functies in ontwikkeling", "features_setting_description": "Beheer de app functies", "file_name": "Bestandsnaam", "file_name_or_extension": "Bestandsnaam of extensie", @@ -1071,15 +1090,12 @@ "folder_not_found": "Map niet gevonden", "folders": "Mappen", "folders_feature_description": "Bladeren door de mapweergave van de foto's en video's op het bestandssysteem", - "forgot_pin_code_question": "PIN vergeten?", + "forgot_pin_code_question": "Pincode vergeten?", "forward": "Vooruit", "gcast_enabled": "Google Cast", "gcast_enabled_description": "Deze functie gebruikt externe bronnen van Google om te kunnen werken.", "general": "Algemeen", - "geolocation_instruction_all_have_location": "Alle items voor deze datum hebben al locatiegegevens. Probeer alle items te tonen of selecteer een andere datum", - "geolocation_instruction_location": "Klik op een item met GPS coÃļrdinaten om de locatie te gebruiken, of selecteer een locatie direct vanaf de kaart", - "geolocation_instruction_no_date": "Selecteer een datum om locatiegegevens te beheren voor foto's en video's van die dag", - "geolocation_instruction_no_photos": "Geen foto's of video's gevonden voor deze datum. Selecteer een andere datum om ze te tonen", + "geolocation_instruction_location": "Klik op een item met gps-coÃļrdinaten om de locatie te gebruiken, of kies een locatie direct op de kaart", "get_help": "Krijg hulp", "get_wifiname_error": "Kon de WiFi-naam niet ophalen. Zorg ervoor dat je de benodigde machtigingen hebt verleend en verbonden bent met een WiFi-netwerk", "getting_started": "Aan de slag", @@ -1124,7 +1140,7 @@ "home_page_delete_err_partner": "Partner items kunnen niet verwijderd worden, overslaan", "home_page_delete_remote_err_local": "Lokale items staan in verwijder selectie externe items, overslaan", "home_page_favorite_err_local": "Lokale items kunnen nog niet als favoriet worden aangemerkt, overslaan", - "home_page_favorite_err_partner": "Partner items kunnen nog niet ge-favoriet worden, overslaan", + "home_page_favorite_err_partner": "Partner items kunnen nog niet als favoriet gemarkeerd worden, overslaan", "home_page_first_time_notice": "Als dit de eerste keer is dat je de app gebruikt, zorg er dan voor dat je een back-up album kiest, zodat de tijdlijn gevuld kan worden met foto's en video's uit het album", "home_page_locked_error_local": "Kan lokale bestanden niet naar de vergrendelde map verplaatsen, sla over", "home_page_locked_error_partner": "Kan partnerbestanden niet naar de vergrendelde map verplaatsen, sla over", @@ -1168,7 +1184,7 @@ "day_at_onepm": "Iedere dag om 13 uur", "hours": "{hours, plural, one {Ieder uur} other {Iedere {hours, number} uren}}", "night_at_midnight": "Iedere avond om middernacht", - "night_at_twoam": "Iedere nacht om 2 uur" + "night_at_twoam": "Elke nacht om 2 uur" }, "invalid_date": "Ongeldige datum", "invalid_date_format": "Ongeldig datumformaat", @@ -1223,6 +1239,7 @@ "local": "Lokaal", "local_asset_cast_failed": "Kan geen item casten die nog niet geÃŧpload is naar de server", "local_assets": "Lokale Items", + "local_media_summary": "Lokale media samenvatting", "local_network": "Lokaal netwerk", "local_network_sheet_info": "De app maakt verbinding met de server via deze URL wanneer het opgegeven WiFi-netwerk wordt gebruikt", "location_permission": "Locatietoestemming", @@ -1234,6 +1251,7 @@ "location_picker_longitude_hint": "Voer hier je lengtegraad in", "lock": "Vergrendel", "locked_folder": "Vergrendelde map", + "log_detail_title": "Log details", "log_out": "Uitloggen", "log_out_all_devices": "Uitloggen op alle apparaten", "logged_in_as": "Ingelogd als {user}", @@ -1264,6 +1282,7 @@ "login_password_changed_success": "Wachtwoord succesvol bijgewerkt", "logout_all_device_confirmation": "Weet je zeker dat je wilt uitloggen op alle apparaten?", "logout_this_device_confirmation": "Weet je zeker dat je wilt uitloggen op dit apparaat?", + "logs": "Logs", "longitude": "Lengtegraad", "look": "Uiterlijk", "loop_videos": "Video's herhalen", @@ -1306,6 +1325,7 @@ "mark_as_read": "Markeren als gelezen", "marked_all_as_read": "Allen gemarkeerd als gelezen", "matches": "Overeenkomsten", + "matching_assets": "Overeenkomende assets", "media_type": "Mediatype", "memories": "Herinneringen", "memories_all_caught_up": "Je bent helemaal bij", @@ -1346,6 +1366,7 @@ "name_or_nickname": "Naam of gebruikersnaam", "network_requirement_photos_upload": "Gebruik mobiele data voor de backup van foto's", "network_requirement_videos_upload": "Gebruik mobiele data voor de backups van video's", + "network_requirements": "Netwerk vereisten", "network_requirements_updated": "Netwerkeisen zijn gewijzigd, back-upwachtrij wordt opnieuw ingesteld", "networking_settings": "Netwerk", "networking_subtitle": "Beheer de instellingen voor de server-URL", @@ -1354,8 +1375,9 @@ "new_api_key": "Nieuwe API-sleutel", "new_password": "Nieuw wachtwoord", "new_person": "Nieuw persoon", - "new_pin_code": "Nieuwe PIN code", + "new_pin_code": "Nieuwe pincode", "new_pin_code_subtitle": "Dit is de eerste keer dat u de vergrendelde map opent. Stel een pincode in om deze pagina veilig te openen", + "new_timeline": "Nieuwe tijdlijn", "new_user_created": "Nieuwe gebruiker aangemaakt", "new_version_available": "NIEUWE VERSIE BESCHIKBAAR", "newest_first": "Nieuwste eerst", @@ -1369,20 +1391,25 @@ "no_assets_message": "KLIK HIER OM JE EERSTE FOTO TE UPLOADEN", "no_assets_to_show": "Geen foto's om te laten zien", "no_cast_devices_found": "Geen cast-apparaten gevonden", + "no_checksum_local": "Geen checksum beschikbaar - kan lokale assets niet ophalen", + "no_checksum_remote": "Geen checksum beschikbaar - kan online assets niet ophalen", "no_duplicates_found": "Er zijn geen duplicaten gevonden.", "no_exif_info_available": "Geen exif info beschikbaar", "no_explore_results_message": "Upload meer foto's om je verzameling te verkennen.", "no_favorites_message": "Voeg favorieten toe om snel je beste foto's en video's te vinden", "no_libraries_message": "Maak een externe bibliotheek om je foto's en video's te bekijken", + "no_local_assets_found": "Geen lokale assets gevonden met deze checksum", "no_locked_photos_message": "Foto’s en video’s in de vergrendelde map zijn verborgen en worden niet weergegeven wanneer je door je bibliotheek bladert of zoekt.", "no_name": "Geen naam", "no_notifications": "Geen meldingen", "no_people_found": "Geen mensen gevonden", "no_places": "Geen plaatsen", + "no_remote_assets_found": "Geen online assets gevonden met deze checksum", "no_results": "Geen resultaten", "no_results_description": "Probeer een synoniem of een algemener zoekwoord", "no_shared_albums_message": "Maak een album om foto's en video's te delen met mensen in je netwerk", "no_uploads_in_progress": "Geen uploads bezig", + "not_available": "n.v.t.", "not_in_any_album": "Niet in een album", "not_selected": "Niet geselecteerd", "note_apply_storage_label_to_previously_uploaded assets": "Opmerking: om het opslaglabel toe te passen op eerder geÃŧploade items, voer de volgende taak uit", @@ -1402,7 +1429,7 @@ "ok": "Ok", "oldest_first": "Oudste eerst", "on_this_device": "Op dit apparaat", - "onboarding": "Onboarding", + "onboarding": "Introductie", "onboarding_locale_description": "Selecteer je voorkeurstaal. Je dan dit later wijzigen in je instellingen.", "onboarding_privacy_description": "De volgende (optionele) functies zijn afhankelijk van externe services en kunnen op elk moment worden uitgeschakeld in de instellingen.", "onboarding_server_welcome_description": "Laten we je instantie instellen met een aantal veelgebruikte instellingen.", @@ -1417,6 +1444,8 @@ "open_the_search_filters": "Open de zoekfilters", "options": "Opties", "or": "of", + "organize_into_albums": "Organiseren in albums", + "organize_into_albums_description": "Bestaande foto's in albums plaatsen met de huidige synchronisatie-instellingen", "organize_your_library": "Organiseer je bibliotheek", "original": "origineel", "other": "Overige", @@ -1487,9 +1516,9 @@ "photos_count": "{count, plural, one {{count, number} foto} other {{count, number} foto's}}", "photos_from_previous_years": "Foto's van voorgaande jaren", "pick_a_location": "Kies een locatie", - "pin_code_changed_successfully": "PIN code succesvol gewijzigd", - "pin_code_reset_successfully": "PIN code succesvol gereset", - "pin_code_setup_successfully": "PIN code succesvol ingesteld", + "pin_code_changed_successfully": "Pincode succesvol gewijzigd", + "pin_code_reset_successfully": "Pincode succesvol gereset", + "pin_code_setup_successfully": "Pincode succesvol ingesteld", "pin_verification": "Pincodeverificatie", "place": "Plaats", "places": "Plaatsen", @@ -1502,6 +1531,7 @@ "port": "Poort", "preferences_settings_subtitle": "Beheer de voorkeuren van de app", "preferences_settings_title": "Voorkeuren", + "preparing": "Voorbereiden", "preset": "Voorinstelling", "preview": "Voorbeeld", "previous": "Vorige", @@ -1513,19 +1543,19 @@ "primary": "Primair", "privacy": "Privacy", "profile": "Profiel", - "profile_drawer_app_logs": "Logboek", + "profile_drawer_app_logs": "Logs", "profile_drawer_client_out_of_date_major": "Mobiele app is verouderd. Werk bij naar de nieuwste hoofdversie.", "profile_drawer_client_out_of_date_minor": "Mobiele app is verouderd. Werk bij naar de nieuwste subversie.", "profile_drawer_client_server_up_to_date": "App en server zijn up-to-date", "profile_drawer_github": "GitHub", - "profile_drawer_readonly_mode": "Alleen-lezen-modus ingeschakeld. Dubbeltik op het avatarpictogram van de gebruiker om te verlaten.", + "profile_drawer_readonly_mode": "Alleen-lezen-modus ingeschakeld. Druk lang op je profielfoto om te verlaten.", "profile_drawer_server_out_of_date_major": "Server is verouderd. Werk bij naar de nieuwste hoofdversie.", "profile_drawer_server_out_of_date_minor": "Server is verouderd. Werk bij naar de nieuwste subversie.", "profile_image_of_user": "Profielfoto van {user}", "profile_picture_set": "Profielfoto ingesteld.", "public_album": "Openbaar album", "public_share": "Openbare deellink", - "purchase_account_info": "Supporter", + "purchase_account_info": "Ondersteuner", "purchase_activated_subtitle": "Bedankt voor het ondersteunen van Immich en open-source software", "purchase_activated_time": "Geactiveerd op {date}", "purchase_activated_title": "Je licentiesleutel is succesvol geactiveerd", @@ -1543,7 +1573,7 @@ "purchase_input_suggestion": "Heb je een licentiesleutel? Voer deze hieronder in", "purchase_license_subtitle": "Koop Immich om de verdere ontwikkeling van de service te ondersteunen", "purchase_lifetime_description": "Levenslange aankoop", - "purchase_option_title": "AANKOOP MOGELIJKHEDEN", + "purchase_option_title": "AANKOOPMOGELIJKHEDEN", "purchase_panel_info_1": "Het bouwen van Immich kost veel tijd en moeite, en we hebben fulltime engineers die eraan werken om het zo goed mogelijk te maken. Onze missie is om open-source software en ethische bedrijfspraktijken een duurzame inkomstenbron te laten worden voor ontwikkelaars en een ecosysteem te creÃĢren dat de privacy respecteert met echte alternatieven voor uitbuitende cloudservices.", "purchase_panel_info_2": "Omdat we ons inzetten om geen paywalls toe te voegen, krijg je met deze aankoop geen extra functies in Immich. We vertrouwen op gebruikers zoals jij om de verdere ontwikkeling van Immich te ondersteunen.", "purchase_panel_title": "Steun het project", @@ -1557,6 +1587,7 @@ "purchase_server_description_2": "Supporterstatus", "purchase_server_title": "Server", "purchase_settings_server_activated": "De licentiesleutel van de server wordt beheerd door de beheerder", + "query_asset_id": "Item-ID opvragen", "queue_status": "Wachtrij {count}/{total}", "rating": "Sterwaardering", "rating_clear": "Waardering verwijderen", @@ -1566,6 +1597,7 @@ "read_changelog": "Lees wijzigingen", "readonly_mode_disabled": "Alleen-lezen modus uitgeschakeld", "readonly_mode_enabled": "Alleen-lezen modus ingeschakeld", + "ready_for_upload": "Klaar voor upload", "reassign": "Opnieuw toewijzen", "reassigned_assets_to_existing_person": "{count, plural, one {# item} other {# items}} opnieuw toegewezen aan {name, select, null {een bestaand persoon} other {{name}}}", "reassigned_assets_to_new_person": "{count, plural, one {# item} other {# items}} opnieuw toegewezen aan een nieuw persoon", @@ -1590,6 +1622,7 @@ "regenerating_thumbnails": "Thumbnails opnieuw aan het genereren", "remote": "Externe", "remote_assets": "Externe Items", + "remote_media_summary": "Online media samenvatting", "remove": "Verwijderen", "remove_assets_album_confirmation": "Weet je zeker dat je {count, plural, one {# item} other {# items}} uit het album wilt verwijderen?", "remove_assets_shared_link_confirmation": "Weet je zeker dat je {count, plural, one {# item} other {# items}} uit deze gedeelde link wilt verwijderen?", @@ -1626,10 +1659,10 @@ "reset": "Resetten", "reset_password": "Wachtwoord resetten", "reset_people_visibility": "Zichtbaarheid mensen resetten", - "reset_pin_code": "Reset PIN code", - "reset_pin_code_description": "Als je jouw PIN code bent vergeten, neem dan contact op met de administrator van de server om deze te resetten", - "reset_pin_code_success": "Resetten van PIN code gelukt", - "reset_pin_code_with_password": "Je kan altijd je PIN code resetten met je wachtwoord", + "reset_pin_code": "Reset pincode", + "reset_pin_code_description": "Als je jouw pincode bent vergeten, neem dan contact op met de administrator van de server om deze te resetten", + "reset_pin_code_success": "Resetten van pincode gelukt", + "reset_pin_code_with_password": "Je kan je pincode altijd resetten met je wachtwoord", "reset_sqlite": "SQLite database resetten", "reset_sqlite_confirmation": "Ben je zeker dat je de SQLite database wilt resetten? Je zal moeten uitloggen om de data opnieuw te synchroniseren", "reset_sqlite_success": "De SQLite database is succesvol gereset", @@ -1642,6 +1675,7 @@ "restore_user": "Gebruiker herstellen", "restored_asset": "Item hersteld", "resume": "Hervatten", + "resume_paused_jobs": "Hervat {count, plural, one {# gepauseerde taak} other {# gepauseerde taken}}", "retry_upload": "Opnieuw uploaden", "review_duplicates": "Controleer duplicaten", "review_large_files": "Grote bestanden beoordelen", @@ -1695,7 +1729,7 @@ "search_page_motion_photos": "Bewegende foto's", "search_page_no_objects": "Geen objectgegevens beschikbaar", "search_page_no_places": "Geen locatiegegevens beschikbaar", - "search_page_screenshots": "Screenshots", + "search_page_screenshots": "Schermafbeelding", "search_page_search_photos_videos": "Zoek naar je foto's en video's", "search_page_selfies": "Selfies", "search_page_things": "Dingen", @@ -1718,7 +1752,7 @@ "second": "Seconde", "see_all_people": "Bekijk alle mensen", "select": "Selecteer", - "select_album_cover": "Selecteer album cover", + "select_album_cover": "Selecteer albumomslag", "select_all": "Alles selecteren", "select_all_duplicates": "Selecteer alle duplicaten", "select_all_in": "Selecteer alles in {group}", @@ -1735,7 +1769,7 @@ "select_user_for_sharing_page_err_album": "Album aanmaken mislukt", "selected": "Geselecteerd", "selected_count": "{count, plural, other {# geselecteerd}}", - "selected_gps_coordinates": "geselecteerde GPS coÃļrdinaten", + "selected_gps_coordinates": "Geselecteerde gps-coÃļrdinaten", "send_message": "Bericht versturen", "send_welcome_email": "Stuur welkomstmail", "server_endpoint": "Server-URL", @@ -1747,7 +1781,7 @@ "server_stats": "Serverstatistieken", "server_version": "Serverversie", "set": "Instellen", - "set_as_album_cover": "Stel in als album cover", + "set_as_album_cover": "Stel in als albumomslag", "set_as_featured_photo": "Instellen als uitgelichte foto", "set_as_profile_picture": "Instellen als profielfoto", "set_date_of_birth": "Geboortedatum instellen", @@ -1779,7 +1813,7 @@ "settings": "Instellingen", "settings_require_restart": "Start Immich opnieuw op om deze instelling toe te passen", "settings_saved": "Instellingen opgeslagen", - "setup_pin_code": "Stel een PIN code in", + "setup_pin_code": "Stel een pincode in", "share": "Delen", "share_action_prompt": "{count} item(s) gedeeld", "share_add_photos": "Foto's toevoegen", @@ -1846,10 +1880,8 @@ "shift_to_permanent_delete": "druk op ⇧ om items permanent te verwijderen", "show_album_options": "Toon albumopties", "show_albums": "Toon albums", - "show_all_assets": "Toon alle items", "show_all_people": "Toon alle mensen", "show_and_hide_people": "Toon & verberg mensen", - "show_assets_without_location": "Toon items zonder locatie", "show_file_location": "Toon bestandslocatie", "show_gallery": "Toon galerij", "show_hidden_people": "Verbogen mensen weergeven", @@ -1866,6 +1898,7 @@ "show_slideshow_transition": "Diavoorstellingsovergang tonen", "show_supporter_badge": "Supportersbadge", "show_supporter_badge_description": "Toon een supportersbadge", + "show_text_search_menu": "Laat tekst zoek menu zien", "shuffle": "Willekeurig", "sidebar": "Zijbalk", "sidebar_display_description": "Toon een link naar deze pagina in de zijbalk", @@ -1896,6 +1929,7 @@ "stacktrace": "Stacktrace", "start": "Start", "start_date": "Startdatum", + "start_date_before_end_date": "Startdatum moet voor einddatum liggen", "state": "Staat", "status": "Status", "stop_casting": "Stop met casten", @@ -1915,11 +1949,13 @@ "support_and_feedback": "Ondersteuning & feedback", "support_third_party_description": "Je Immich installatie is door een derde partij samengesteld. Problemen die je ervaart, kunnen door dat pakket veroorzaakt zijn. Meld problemen in eerste instantie bij hen via de onderstaande links.", "swap_merge_direction": "Wissel richting voor samenvoegen om", - "sync": "Sync", + "sync": "Synchroniseren", "sync_albums": "Albums synchroniseren", "sync_albums_manual_subtitle": "Synchroniseer alle geÃŧploade video’s en foto’s naar de geselecteerde back-up albums", "sync_local": "Lokaal synchroniseren", "sync_remote": "Op afstand synchroniseren", + "sync_status": "Sync Status", + "sync_status_subtitle": "Bekijk en beheer het synchronisatie systeem", "sync_upload_album_setting_subtitle": "Maak en upload je foto's en video's naar de geselecteerde albums op Immich", "tag": "Tag", "tag_assets": "Items taggen", @@ -1979,9 +2015,10 @@ "trash_page_select_assets_btn": "Selecteer items", "trash_page_title": "Prullenbak ({count})", "trashed_items_will_be_permanently_deleted_after": "Items in de prullenbak worden na {days, plural, one {# dag} other {# dagen}} permanent verwijderd.", + "troubleshoot": "Problemen oplossen", "type": "Type", - "unable_to_change_pin_code": "PIN code kan niet gewijzigd worden", - "unable_to_setup_pin_code": "PIN code kan niet ingesteld worden", + "unable_to_change_pin_code": "Pincode kan niet gewijzigd worden", + "unable_to_setup_pin_code": "Pincode kan niet ingesteld worden", "unarchive": "Herstellen uit archief", "unarchive_action_prompt": "{count} verwijderd uit het archief", "unarchived_count": "{count, plural, other {# verwijderd uit archief}}", @@ -2034,13 +2071,12 @@ "use_biometric": "Gebruik biometrische authenticatie", "use_current_connection": "gebruik huidige verbinding", "use_custom_date_range": "Gebruik in plaats daarvan een aangepast datumbereik", - "use_this_location": "Klik om locatie te gebruiken", "user": "Gebruiker", "user_has_been_deleted": "Deze gebruiker is verwijderd.", "user_id": "Gebruikers ID", "user_liked": "{user} heeft {type, select, photo {deze foto} video {deze video} asset {} other {dit item}} geliket", - "user_pin_code_settings": "PIN Code", - "user_pin_code_settings_description": "Beheer je PIN code", + "user_pin_code_settings": "Pincode", + "user_pin_code_settings_description": "Beheer je pincode", "user_privacy": "Gebruikersprivacy", "user_purchase_settings": "Kopen", "user_purchase_settings_description": "Beheer je aankoop", @@ -2061,8 +2097,8 @@ "version_history": "Versiegeschiedenis", "version_history_item": "{version} geïnstalleerd op {date}", "video": "Video", - "video_hover_setting": "Speel videothumbnail af bij hoveren", - "video_hover_setting_description": "Speel videothumbnail af wanneer de muis over het item beweegt. Zelfs wanneer uitgeschakeld, kan het afspelen worden gestart door de muis over het afspeelpictogram te bewegen.", + "video_hover_setting": "Speel videominiatuur af bij hoveren", + "video_hover_setting_description": "Speel videominiatuur af wanneer de muis over het item beweegt. Zelfs wanneer uitgeschakeld, kan het afspelen worden gestart door de muis over het afspeelpictogram te bewegen.", "videos": "Video's", "videos_count": "{count, plural, one {# video} other {# video's}}", "view": "Bekijken", @@ -2074,13 +2110,14 @@ "view_link": "Bekijk link", "view_links": "Links bekijken", "view_name": "Bekijken", - "view_next_asset": "Bekijk volgende item", - "view_previous_asset": "Bekijk vorige item", + "view_next_asset": "Bekijk volgend item", + "view_previous_asset": "Bekijk vorig item", "view_qr_code": "QR-code bekijken", + "view_similar_photos": "Bekijk vergelijkbare foto's", "view_stack": "Bekijk stapel", "view_user": "Bekijk gebruiker", - "viewer_remove_from_stack": "Verwijder van Stapel", - "viewer_stack_use_as_main_asset": "Gebruik als Hoofd Item", + "viewer_remove_from_stack": "Verwijder van stapel", + "viewer_stack_use_as_main_asset": "Zet bovenaan de stapel", "viewer_unstack": "Ontstapel", "visibility_changed": "Zichtbaarheid gewijzigd voor {count, plural, one {# persoon} other {# mensen}}", "waiting": "Wachtend", @@ -2095,5 +2132,6 @@ "yes": "Ja", "you_dont_have_any_shared_links": "Je hebt geen gedeelde links", "your_wifi_name": "Je WiFi-naam", - "zoom_image": "Inzoomen" + "zoom_image": "Inzoomen", + "zoom_to_bounds": "Zoom naar randen" } diff --git a/i18n/nn.json b/i18n/nn.json index 01f76f528b..7b2f256c94 100644 --- a/i18n/nn.json +++ b/i18n/nn.json @@ -28,6 +28,8 @@ "add_to_album": "Legg til i album", "add_to_album_bottom_sheet_added": "Lagt til i {album}", "add_to_album_bottom_sheet_already_exists": "Allereie i {album}", + "add_to_albums": "Legg til i album", + "add_to_albums_count": "Legg til i album ({count})", "add_to_shared_album": "Legg til i delt album", "add_url": "Legg til URL", "added_to_archive": "Lagt til i arkiv", @@ -45,6 +47,7 @@ "backup_database": "Lag tryggingskopi av database", "backup_database_enable_description": "Aktiver tryggingskopiering av database", "backup_keep_last_amount": "Antal tryggingskopiar ÃĨ behalde", + "backup_onboarding_1_description": "sikkerheitskopi i skya eller pÃĨ eit anna fysisk sted.", "backup_onboarding_2_description": "lokale kopiar pÃĨ andre einingar. Dette inkluderer hovudfilene og backup av desse filene lokalt.", "backup_onboarding_3_description": "fullstendige kopiar av dine data, inkludert originalfilene. Dette inkluderer 1 utomhus kopi og 2 lokale kopiar.", "backup_onboarding_description": "Ein 3-2-1 backup-strategi tilrÃĨdast for ÃĨ verne dataa dine. Du bør ha kopiar av dei opplasta bileta/videoane dine samt Immich-databasen, slik at du har ei fleirdelt backup-løysing.", @@ -78,6 +81,7 @@ "image_format_description": "WebP gjev mindre filstorleik enn JPEG, men er treigare ÃĨ lage.", "image_fullsize_description": "Bilete i full storleik utan metadata, i bruk nÃĨr zooma inn", "image_fullsize_enabled": "Skru pÃĨ generering av bilete i full storleik", + "image_fullsize_enabled_description": "Generer bilete i full storleik for ikkje web-tilpassa formatar. NÃĨr \"Foretrekk", "image_fullsize_quality_description": "Kvalitet pÃĨ bilete i full storleik frÃĨ 1-100. Høgare er betre, men gjev større filer.", "image_fullsize_title": "Innstillingar for bilete i full storleik", "image_prefer_embedded_preview": "Bruk helst innebygd førehandsvisning", @@ -118,6 +122,9 @@ "logging_enable_description": "Aktiver loggføring", "logging_level_description": "NÃĨr aktivert, kva loggnivÃĨ ÃĨ bruke.", "logging_settings": "Logging", + "machine_learning_availability_checks_description": "Automatiser oppdaging og prioritet av tilgjengelege maskinlÃĻrings-serverar", + "machine_learning_availability_checks_interval": "Sjekk intervall", + "machine_learning_availability_checks_timeout_description": "Utløpstid i millisekund for tilgjengelegheitssjekk", "machine_learning_clip_model": "CLIP modell", "machine_learning_clip_model_description": "Namnet pÃĨ ein CLIP modell finst her. Merk at du mÃĨ køyre 'Smart Søk'-jobben pÃĨ nytt for alle bilete etter du har forandra modell.", "machine_learning_duplicate_detection": "Duplikatdeteksjon", @@ -139,6 +146,7 @@ "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 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_min_recognized_faces_description": "Minste tal pÃĨ gjenkjende fjes for ÃĨ opprette ein person. Aukar ein dette, vert ansiktsgjenkjenninga meir presis, pÃĨ bekostning av auka sjanse for at ansikt ikkje vert tileigna ein person.", "machine_learning_settings": "Innstillingar for maskinlÃĻring", "machine_learning_settings_description": "Administrer maskinlÃĻringsfunksjonar og innstillingar", "machine_learning_smart_search": "Smart Søk", @@ -154,6 +162,7 @@ "map_settings": "Kart", "map_settings_description": "Endre kartinnstillingar", "map_style_description": "URL til eit style.json-karttema", + "memory_generate_job": "Minne-generering", "metadata_extraction_job": "Hent ut metadata", "metadata_extraction_job_description": "Hent ut metadata frÃĨ kvart bilete, slik som GPS, ansikt og oppløysing", "metadata_faces_import_setting": "Skru pÃĨ import av ansikt", @@ -161,6 +170,17 @@ "metadata_settings": "Metadata Innstillinger", "metadata_settings_description": "Endre metadata-innstillingar", "migration_job": "Migrasjon", + "migration_job_description": "Overfør miniatyrbilete for bilete og ansikt til den nyaste mappestrukturen", + "nightly_tasks_cluster_faces_setting_description": "Køyr ansiktsgjenkjenning pÃĨ nyleg identifiserte ansikt", + "nightly_tasks_database_cleanup_setting_description": "Fjern gamal, utgÃĨtt data frÃĨ databasen", + "nightly_tasks_generate_memories_setting": "Generer minner", + "nightly_tasks_generate_memories_setting_description": "Lag nye minner frÃĨ bilete", + "nightly_tasks_missing_thumbnails_setting": "Generer manglande miniatyrbilete", + "nightly_tasks_missing_thumbnails_setting_description": "Set bilete utan miniatyrbilete i kø for generering av miniatyrbilete", + "nightly_tasks_settings": "Innstillingar for nattlege jobbar", + "nightly_tasks_settings_description": "Handsam nattlege jobbar", + "nightly_tasks_start_time_setting": "Starttid", + "nightly_tasks_start_time_setting_description": "Tidspunktet serveren køyrer nattlege jobbar", "notification_email_from_address": "FrÃĨ adresse", "notification_email_test_email_failed": "Mislukka sending av test-e-post, sjekk konfigurasjonen din", "notification_email_test_email_sent": "Det vart sendt ei test-melding til {email}. Sjekk e-posten din.", diff --git a/i18n/pa.json b/i18n/pa.json index 0967ef424b..0801a54351 100644 --- a/i18n/pa.json +++ b/i18n/pa.json @@ -1 +1,21 @@ -{} +{ + "about": "⍐ā¨Ē ā¨Ŧā¨žā¨°āŠ‡", + "account": "⍖ā¨ŧā¨žā¨¤ā¨ž", + "account_settings": "⍖ā¨ŧā¨žā¨¤ā¨ž ā¨¸āŠˆā¨Ÿā¨ŋāŠ°ā¨—ā¨žā¨‚", + "action": "ā¨•ā¨žā¨°ā¨ĩā¨žā¨ˆ", + "action_common_update": "ā¨…āŠąā¨Ēā¨ĄāŠ‡ā¨Ÿ", + "actions": "ā¨•ā¨žā¨°ā¨ĩā¨žā¨ˆā¨†ā¨‚", + "active": "⍕ā¨ŋ⍰ā¨ŋ⍆⍏ā¨ŧāŠ€ā¨˛", + "activity": "ā¨—ā¨¤āŠ€ā¨ĩā¨ŋā¨§āŠ€", + "add": "⍏ā¨ŧā¨žā¨Žā¨˛ ā¨•ā¨°āŠ‹", + "add_a_description": "ā¨ĩāŠ‡ā¨°ā¨ĩā¨ž ⍏ā¨ŧā¨žā¨Žā¨˛ ā¨•ā¨°āŠ‹", + "add_a_location": "ā¨‡āŠąā¨• ⍏ā¨Ĩā¨žā¨¨ ⍏ā¨ŧā¨žā¨Žā¨˛ ā¨•ā¨°āŠ‹", + "add_a_name": "ā¨¨ā¨žā¨Ž ⍏ā¨ŧā¨žā¨Žā¨˛ ā¨•ā¨°āŠ‹", + "add_a_title": "⍏ā¨ŋā¨°ā¨˛āŠ‡ā¨– ⍏ā¨ŧā¨žā¨Žā¨˛ ā¨•ā¨°āŠ‹", + "add_birthday": "ā¨œā¨¨ā¨Žā¨Ļā¨ŋ⍍ ⍏ā¨ŧā¨žā¨Žā¨˛ ā¨•ā¨°āŠ‹", + "add_endpoint": "ā¨ā¨‚ā¨Ąā¨ĒāŠā¨†ā¨‡āŠ°ā¨Ÿ ⍏ā¨ŧā¨žā¨Žā¨˛ ā¨•ā¨°āŠ‹", + "add_exclusion_pattern": "ā¨…ā¨˛ā¨šā¨ŋā¨Ļā¨—āŠ€ ā¨ĒāŠˆā¨Ÿā¨°ā¨¨ ⍏ā¨ŧā¨žā¨Žā¨˛ ā¨•ā¨°āŠ‹", + "add_import_path": "ā¨†ā¨¯ā¨žā¨¤ ā¨Žā¨žā¨°ā¨— ⍏ā¨ŧā¨žā¨Žā¨˛ ā¨•ā¨°āŠ‹", + "add_location": "⍏ā¨Ĩā¨žā¨¨ ⍏ā¨ŧā¨žā¨Žā¨˛ ā¨•ā¨°āŠ‹", + "add_more_users": "ā¨šāŠ‹ā¨° ⍉ā¨Ēā¨­āŠ‹ā¨—ā¨¤ā¨ž ⍏ā¨ŧā¨žā¨Žā¨˛ ā¨•ā¨°āŠ‹" +} diff --git a/i18n/pl.json b/i18n/pl.json index 64fe2ac60f..2531f8210d 100644 --- a/i18n/pl.json +++ b/i18n/pl.json @@ -28,10 +28,12 @@ "add_to_album": "Dodaj do albumu", "add_to_album_bottom_sheet_added": "Dodano do {album}", "add_to_album_bottom_sheet_already_exists": "JuÅŧ jest w {album}", + "add_to_album_bottom_sheet_some_local_assets": "NiektÃŗre lokalne zasoby nie mogły zostać dodane do albumu", "add_to_album_toggle": "Przełącz wybieranie dla {album}", "add_to_albums": "Dodaj do albumÃŗw", "add_to_albums_count": "Dodaj do albumÃŗw ({count})", "add_to_shared_album": "Dodaj do udostępnionego albumu", + "add_upload_to_stack": "Dodaj przesłane do stosu", "add_url": "Dodaj URL", "added_to_archive": "Dodano do archiwum", "added_to_favorites": "Dodano do ulubionych", @@ -123,6 +125,13 @@ "logging_enable_description": "Uruchom zapisywanie logÃŗw", "logging_level_description": "Kiedy włączone, jakiego poziomu uÅŧyć.", "logging_settings": "Rejestrowanie logÃŗw", + "machine_learning_availability_checks": "Sprawdzanie dostępności", + "machine_learning_availability_checks_description": "Automatyczne wykrywaj i preferuj dostępne serwery uczenia maszynowego", + "machine_learning_availability_checks_enabled": "Włącz sprawdzanie dostępności", + "machine_learning_availability_checks_interval": "Częstotliwość sprawdzania", + "machine_learning_availability_checks_interval_description": "Odstęp czasu w milisekundach między sprawdzeniami dostępności", + "machine_learning_availability_checks_timeout": "Upłynął czas Åŧądania", + "machine_learning_availability_checks_timeout_description": "Limit czasu Åŧądania w milisekundach dla sprawdzania dostępności", "machine_learning_clip_model": "Model CLIP", "machine_learning_clip_model_description": "Nazwa modelu CLIP jest wymieniona tutaj. ZwrÃŗÄ‡ uwagę, Åŧe po zmianie modelu musisz ponownie uruchomić zadanie 'Smart Search' dla wszystkich obrazÃŗw.", "machine_learning_duplicate_detection": "Wykrywanie DuplikatÃŗw", @@ -233,7 +242,7 @@ "oauth_storage_quota_default": "Domyślna ilość miejsca w magazynie (GiB)", "oauth_storage_quota_default_description": "Limit w GiB do wykorzystania, gdy nie podano Åŧadnej wartości.", "oauth_timeout": "Upłynął czas Åŧądania", - "oauth_timeout_description": "Limit czasu Åŧądania (w milisekundach)", + "oauth_timeout_description": "Limit czasu Åŧądania w milisekundach", "password_enable_description": "Zaloguj uÅŧywając e-mail i hasła", "password_settings": "Logowanie Hasłem", "password_settings_description": "Zarządzaj ustawieniami logowania hasłem", @@ -387,8 +396,6 @@ "admin_password": "Hasło Administratora", "administration": "Administracja", "advanced": "Zaawansowane", - "advanced_settings_beta_timeline_subtitle": "WyprÃŗbuj nową funkcjonalność aplikacji", - "advanced_settings_beta_timeline_title": "Beta-Timeline", "advanced_settings_enable_alternate_media_filter_subtitle": "UÅŧyj tej opcji do filtrowania mediÃŗw podczas synchronizacji alternatywnych kryteriÃŗw. UÅŧywaj tylko wtedy gdy aplikacja ma problemy z wykrywaniem wszystkich albumÃŗw.", "advanced_settings_enable_alternate_media_filter_title": "[EKSPERYMENTALNE] UÅŧyj alternatywnego filtra synchronizacji albumu", "advanced_settings_log_level_title": "Poziom szczegÃŗÅ‚owości dziennika: {level}", @@ -425,6 +432,7 @@ "album_remove_user_confirmation": "Na pewno chcesz usunąć {user}?", "album_search_not_found": "Nie znaleziono albumÃŗw pasujących do Twojego wyszukiwania", "album_share_no_users": "Wygląda na to, Åŧe ten album albo udostępniono wszystkim uÅŧytkownikom, albo nie ma komu go udostępnić.", + "album_summary": "Podsumowanie albumu", "album_updated": "Album zaktualizowany", "album_updated_setting_description": "Otrzymaj powiadomienie e-mail, gdy do udostępnionego Ci albumu zostaną dodane nowe zasoby", "album_user_left": "Opuszczono {album}", @@ -443,7 +451,7 @@ "albums_default_sort_order": "Domyślna kolejność sortowania w albumach", "albums_default_sort_order_description": "Początkowa kolejność sortowania zasobÃŗw przy tworzeniu nowych albumÃŗw.", "albums_feature_description": "Kolekcje zasobÃŗw, ktÃŗre moÅŧna udostępniać innym uÅŧytkownikom.", - "albums_on_device_count": "AlbumÃŗw na urzadzeniu ({count})", + "albums_on_device_count": "Albumy na urządzeniu ({count})", "all": "Wszystkie", "all_albums": "Wszystkie albumy", "all_people": "Wszystkie osoby", @@ -496,6 +504,8 @@ "asset_restored_successfully": "ZasÃŗb został pomyślnie przywrÃŗcony", "asset_skipped": "Pominięto", "asset_skipped_in_trash": "W koszu", + "asset_trashed": "ZasÃŗb wrzucono do kosza", + "asset_troubleshoot": "Rozwiązywanie problemÃŗw z zasobami", "asset_uploaded": "Przesłano", "asset_uploading": "Przesyłanieâ€Ļ", "asset_viewer_settings_subtitle": "Zarządzaj ustawieniami przeglądarki galerii", @@ -504,7 +514,7 @@ "assets_added_count": "Dodano {count, plural, one {# zasÃŗb} few {# zasoby} other {# zasobÃŗw}}", "assets_added_to_album_count": "Dodano {count, plural, one {# zasÃŗb} few {# zasoby} other {# zasobÃŗw}} do albumu", "assets_added_to_albums_count": "Dodano {assetTotal, plural, one {# zasÃŗb} few {# zasoby} other {# zasobÃŗw}} do {albumTotal, plural, one {# albumu} other {# albumÃŗw}}", - "assets_cannot_be_added_to_album_count": "{count, plural, one {sztuka Elementu} other {szt. ElementÃŗw}} nie moÅŧe być dodana do albumu", + "assets_cannot_be_added_to_album_count": "{count, plural, one {ZasÃŗb nie moÅŧe zostać dodany} other {Zasoby nie mogą zostać dodane}} do albumu", "assets_cannot_be_added_to_albums": "{count, plural, one {ZasÃŗb nie moÅŧe być dodany} other {Zasoby nie mogą być dodane}} do Åŧadnego z albumÃŗw", "assets_count": "{count, plural, one {# zasÃŗb} few {# zasoby} other {# zasobÃŗw}}", "assets_deleted_permanently": "{count} zostało trwale usuniętych", @@ -521,7 +531,7 @@ "assets_trashed": "{count} szt. zostało wrzucone do kosza", "assets_trashed_count": "Wrzucono do kosza {count, plural, one {# zasÃŗb} few {# zasoby} other {# zasobÃŗw}}", "assets_trashed_from_server": "{count} szt. usuniętych z serwera Immich", - "assets_were_part_of_album_count": "{count, plural, one {ZasÃŗb był} few {Zasoby były} many {ZasobÃŗw było} other {ZasobÃŗw było}} juÅŧ częścią albumu", + "assets_were_part_of_album_count": "{count, plural, one {ZasÃŗb był} other {Zasoby były}} juÅŧ częścią albumu", "assets_were_part_of_albums_count": "{count, plural, one {ZasÃŗb był} other {Zasoby były}} juÅŧ częścią albumÃŗw", "authorized_devices": "Autoryzowane urządzenia", "automatic_endpoint_switching_subtitle": "Połącz się lokalnie przez wyznaczoną sieć Wi-Fi, jeśli jest dostępna, i korzystaj z alternatywnych połączeń gdzie indziej", @@ -529,15 +539,18 @@ "autoplay_slideshow": "Automatyczne odtwarzanie pokazu slajdÃŗw", "back": "Wstecz", "back_close_deselect": "WrÃŗÄ‡, zamknij lub odznacz", + "background_backup_running_error": "Tworzenie kopii zapasowej w tle jest obecnie w toku, nie moÅŧna rozpocząć ręcznego tworzenia kopii zapasowej", "background_location_permission": "Uprawnienia do lokalizacji w tle", "background_location_permission_content": "Aby mÃŗc przełączać sieć podczas pracy w tle, Immich musi *zawsze* mieć dostęp do dokładnej lokalizacji, aby aplikacja mogła odczytać nazwę sieci Wi-Fi", + "background_options": "Opcje w tle", "backup": "Kopia zapasowa", "backup_album_selection_page_albums_device": "Albumy na urządzeniu ({count})", "backup_album_selection_page_albums_tap": "Stuknij, aby włączyć, stuknij dwukrotnie, aby wykluczyć", "backup_album_selection_page_assets_scatter": "Pliki mogą być rozproszone w wielu albumach. Dzięki temu albumy mogą być włączane lub wyłączane podczas procesu tworzenia kopii zapasowej.", - "backup_album_selection_page_select_albums": "Zaznacz albumy", + "backup_album_selection_page_select_albums": "Wybierz albumy", "backup_album_selection_page_selection_info": "Info o wyborze", "backup_album_selection_page_total_assets": "Łącznie unikalnych plikÃŗw", + "backup_albums_sync": "Synchronizacja kopii zapasowych albumÃŗw", "backup_all": "Wszystkie", "backup_background_service_backup_failed_message": "Nie udało się wykonać kopii zapasowej zasobÃŗw. Ponowna prÃŗbaâ€Ļ", "backup_background_service_connection_failed_message": "Nie udało się połączyć z serwerem. Ponowna prÃŗbaâ€Ļ", @@ -564,7 +577,7 @@ "backup_controller_page_background_turn_on": "Włącz usługę w tle", "backup_controller_page_background_wifi": "Tylko Wi-Fi", "backup_controller_page_backup": "Kopia zapasowa", - "backup_controller_page_backup_selected": "Zaznaczone: ", + "backup_controller_page_backup_selected": "Wybrane: ", "backup_controller_page_backup_sub": "Zdjęcia i filmy z utworzoną kopią zapasową", "backup_controller_page_created": "Utworzono dnia: {date}", "backup_controller_page_desc_backup": "Włącz kopię zapasową na pierwszym planie, aby automatycznie przesyłać nowe zasoby na serwer po otworzeniu aplikacji.", @@ -573,7 +586,7 @@ "backup_controller_page_filename": "Nazwa pliku: {filename} [{size}]", "backup_controller_page_id": "ID: {id}", "backup_controller_page_info": "Informacje o kopii zapasowej", - "backup_controller_page_none_selected": "Brak wybranych", + "backup_controller_page_none_selected": "Nic nie wybrano", "backup_controller_page_remainder": "Pozostałe", "backup_controller_page_remainder_sub": "Pozostałe zdjęcia i filmy wybrane do wykonania kopii zapasowej", "backup_controller_page_server_storage": "Pamięć Serwera", @@ -587,6 +600,7 @@ "backup_controller_page_turn_on": "Włącz kopię zapasową na pierwszym planie", "backup_controller_page_uploading_file_info": "Informacje o przesyłanym pliku", "backup_err_only_album": "Nie moÅŧna usunąć jedynego albumu", + "backup_error_sync_failed": "Synchronizacja nie powiodła się. Nie moÅŧna wykonać kopii zapasowej.", "backup_info_card_assets": "zasoby", "backup_manual_cancelled": "Anulowano", "backup_manual_in_progress": "Przesyłanie juÅŧ trwa. SprÃŗbuj po pewnym czasie", @@ -597,8 +611,6 @@ "backup_setting_subtitle": "Zarządzaj ustawieniami przesyłania w tle i na pierwszym planie", "backup_settings_subtitle": "Zarządzanie ustawieniami przesyłania", "backward": "Do tyłu", - "beta_sync": "Status synchronizacji w wersji Beta", - "beta_sync_subtitle": "Zarządzaj nowym systemem synchronizacji", "biometric_auth_enabled": "Włączono logowanie biometryczne", "biometric_locked_out": "Uwierzytelnianie biometryczne jest dla Ciebie zablokowane", "biometric_no_options": "Brak moÅŧliwości biometrii", @@ -640,7 +652,7 @@ "cast": "OdtwÃŗrz na telewizorze", "cast_description": "Skonfiguruj dostępne cele do przesyłania", "change_date": "Zmień datę", - "change_description": "Zmiana opisu", + "change_description": "Zmień opis", "change_display_order": "Zmień kolejność wyświetlania", "change_expiration_time": "Zmień czas waÅŧności", "change_location": "Zmień lokalizację", @@ -656,6 +668,8 @@ "change_pin_code": "Zmień kod PIN", "change_your_password": "Zmień swoje hasło", "changed_visibility_successfully": "Pomyślnie zmieniono widoczność", + "charging": "Ładowanie", + "charging_requirement_mobile_backup": "Tworzenie kopii zapasowej w tle wymaga by urządzenie było podłączone do ładowania", "check_corrupt_asset_backup": "SprawdÅē, czy kopie zapasowe zasobÃŗw nie są uszkodzone", "check_corrupt_asset_backup_button": "Wykonaj sprawdzenie", "check_corrupt_asset_backup_description": "Uruchom sprawdzenie tylko przez Wi-Fi i po utworzeniu kopii zapasowej wszystkich zasobÃŗw. Procedura moÅŧe potrwać kilka minut.", @@ -663,10 +677,10 @@ "choose_matching_people_to_merge": "Wybierz osoby, aby złączyć je w jedną", "city": "Miasto", "clear": "Wyczyść", - "clear_all": "Wyczyść", + "clear_all": "Wyczyść wszystko", "clear_all_recent_searches": "Usuń ostatnio wyszukiwane", "clear_file_cache": "Wyczyść pamięć podręczną plikÃŗw", - "clear_message": "Zamknij wiadomość", + "clear_message": "Wyczyść wiadomość", "clear_value": "Wyczyść wartość", "client_cert_dialog_msg_confirm": "OK", "client_cert_enter_password": "WprowadÅē hasło", @@ -693,7 +707,7 @@ "confirm_admin_password": "PotwierdÅē Hasło Administratora", "confirm_delete_face": "Czy na pewno chcesz usunąć twarz {name} z zasobÃŗw?", "confirm_delete_shared_link": "Czy na pewno chcesz usunąć ten udostępniony link?", - "confirm_keep_this_delete_others": "Wszystkie inne zasoby zostaną usunięte poza tym zasobem. Czy jesteś pewien, Åŧe chcesz kontynuować?", + "confirm_keep_this_delete_others": "Wszystkie inne zasoby w tym stosie, z wyjątkiem tego zasobu, zostaną usunięte. Czy jesteś pewien, Åŧe chcesz kontynuować?", "confirm_new_pin_code": "PotwierdÅē nowy kod PIN", "confirm_password": "PotwierdÅē hasło", "confirm_tag_face": "Chcesz dodać do tej twarzy etykietę {name}?", @@ -710,7 +724,7 @@ "control_bottom_app_bar_edit_time": "Edytuj datę i godzinę", "control_bottom_app_bar_share_link": "Udostępnij link", "control_bottom_app_bar_share_to": "Wyślij", - "control_bottom_app_bar_trash_from_immich": "Przenieść do kosza", + "control_bottom_app_bar_trash_from_immich": "Przenieś do kosza", "copied_image_to_clipboard": "Skopiowano obraz do schowka.", "copied_to_clipboard": "Skopiowano do schowka!", "copy_error": "Błąd kopiowania", @@ -742,6 +756,7 @@ "create_user": "StwÃŗrz uÅŧytkownika", "created": "Utworzono", "created_at": "Utworzony", + "creating_linked_albums": "Tworzenie połączonych albumÃŗw...", "crop": "Przytnij", "curated_object_page_title": "Rzeczy", "current_device": "Obecne urządzenie", @@ -788,7 +803,7 @@ "delete_local_action_prompt": "{count} lokalnie usunięto", "delete_local_dialog_ok_backed_up_only": "Usuń tylko kopię zapasową", "delete_local_dialog_ok_force": "Usuń mimo to", - "delete_others": "Usuń inne", + "delete_others": "Usuń pozostałe", "delete_permanently": "Usuń trwale", "delete_permanently_action_prompt": "{count} trwale usuniętych", "delete_shared_link": "Usuń udostępniony link", @@ -890,8 +905,10 @@ "enter_your_pin_code_subtitle": "WprowadÅē twÃŗj kod PIN, aby uzyskać dostęp do folderu zablokowanego", "error": "Błąd", "error_change_sort_album": "Nie udało się zmienić kolejności sortowania albumÃŗw", - "error_delete_face": "Wystąpił błąd podczas usuwania twarzy z zasobÃŗw", + "error_delete_face": "Błąd podczas usuwania twarzy z zasobÃŗw", + "error_getting_places": "Błąd podczas pozyskiwania lokalizacji", "error_loading_image": "Błąd podczas ładowania zdjęcia", + "error_loading_partners": "Błąd podczas ładowania partnerÃŗw: {error}", "error_saving_image": "Błąd: {error}", "error_tag_face_bounding_box": "Błąd przy dodawaniu etykiety dla tej twarzy - nie moÅŧe uzyskać wspÃŗÅ‚rzędnych granicznych", "error_title": "Błąd - Coś poszło nie tak", @@ -900,7 +917,7 @@ "cannot_navigate_previous_asset": "Nie moÅŧna przejść do poprzedniego zasobu", "cant_apply_changes": "Nie moÅŧna zastosować zmian", "cant_change_activity": "Nie moÅŧna {enabled, select, true {wyłączyć} other {włączyć}} aktywności", - "cant_change_asset_favorite": "Nie moÅŧna zmienić ulubionego dla zasobu", + "cant_change_asset_favorite": "Nie moÅŧna zmienić statusu ulubionego dla zasobu", "cant_change_metadata_assets_count": "Nie moÅŧna zmienić metadanych {count, plural, one {# zasobu} other {# zasobÃŗw}}", "cant_get_faces": "Nie moÅŧna pozyskać twarzy", "cant_get_number_of_comments": "Nie moÅŧna uzyskać liczby komentarzy", @@ -925,7 +942,7 @@ "failed_to_load_people": "Nie udało się pobrać ludzi", "failed_to_remove_product_key": "Nie udało się usunąć klucza produktu", "failed_to_reset_pin_code": "Nie udało się zresetować kodu PIN", - "failed_to_stack_assets": "Nie udało się zestawić zasobÃŗw", + "failed_to_stack_assets": "Nie udało się utworzyć stosu z zasobÃŗw", "failed_to_unstack_assets": "Nie udało się rozdzielić zasobÃŗw", "failed_to_update_notification_status": "Nie udało się zaktualizować stanu powiadomienia", "import_path_already_exists": "Ta ścieÅŧka importu juÅŧ istnieje.", @@ -1022,6 +1039,7 @@ "exif_bottom_sheet_description_error": "Wystąpił błąd podczas aktualizacji opisu", "exif_bottom_sheet_details": "SZCZEGÓŁY", "exif_bottom_sheet_location": "LOKALIZACJA", + "exif_bottom_sheet_no_description": "Brak opisu", "exif_bottom_sheet_people": "LUDZIE", "exif_bottom_sheet_person_add_person": "Dodaj nazwę", "exit_slideshow": "Zamknij Pokaz SlajdÃŗw", @@ -1056,6 +1074,7 @@ "favorites_page_no_favorites": "Nie znaleziono ulubionych zasobÃŗw", "feature_photo_updated": "Zdjęcie gÅ‚Ãŗwne zaktualizowane pomyślnie", "features": "Funkcje", + "features_in_development": "Funkcje w fazie rozwoju", "features_setting_description": "Zarządzaj funkcjami aplikacji", "file_name": "Nazwa pliku", "file_name_or_extension": "Nazwie lub rozszerzeniu pliku", @@ -1076,10 +1095,7 @@ "gcast_enabled": "Google Cast", "gcast_enabled_description": "Ta funkcja , aby działać, ładuje zewnętrzne zasoby z Google.", "general": "OgÃŗlne", - "geolocation_instruction_all_have_location": "Wszystkie zasoby z tego dnia mają juÅŧ dane o lokalizacji. SprÃŗbuj wyświetlić wszystkie zasoby lub wybierz inną datę", "geolocation_instruction_location": "Kliknij na zasÃŗb z wspÃŗÅ‚rzędnymi GPS, aby uÅŧyć jego lokalizacji, lub wybierz lokalizację bezpośrednio z mapy", - "geolocation_instruction_no_date": "Wybierz datę, aby zarządzać danymi o lokalizacji dla zdjęć i filmÃŗw z tego dnia", - "geolocation_instruction_no_photos": "Nie znaleziono Åŧadnych zdjęć ani filmÃŗw dla tej daty. Wybierz inną datę, aby je wyświetlić", "get_help": "Pomoc", "get_wifiname_error": "Nie moÅŧna uzyskać nazwy Wi-Fi. Upewnij się, Åŧe udzieliłeś niezbędnych uprawnień i jesteś połączony z siecią Wi-Fi", "getting_started": "Pierwsze kroki", @@ -1156,7 +1172,7 @@ "immich_web_interface": "Interfejs internetowy Immich", "import_from_json": "Wczytaj z JSON", "import_path": "ŚcieÅŧka importu", - "in_albums": "W {count, plural, one {# album} other {# albumy}}", + "in_albums": "W {count, plural, one {# albumie} other {# albumach}}", "in_archive": "W archiwum", "include_archived": "Uwzględnij zarchiwizowane", "include_shared_albums": "Uwzględnij udostępnione albumy", @@ -1180,11 +1196,11 @@ "ios_debug_info_no_sync_yet": "Nie uruchomiono jeszcze Åŧadnego zadania synchronizacji w tle", "ios_debug_info_processes_queued": "{count, plural, one {{count} proces w tle w kolejce} few {{count} procesy w tle w kolejce} other {{count} procesÃŗw w tle w kolejce}}", "ios_debug_info_processing_ran_at": "Przetwarzanie przebiegło {dateTime}", - "items_count": "{count, plural, one {# element} other {# elementy}}", + "items_count": "{count, plural, one {# element} few {# elementy} other {# elementÃŗw}}", "jobs": "Zadania", "keep": "Zachowaj", "keep_all": "Zachowaj wszystko", - "keep_this_delete_others": "Zachowaj to, usuń inne", + "keep_this_delete_others": "Zachowaj to, usuń pozostałe", "kept_this_deleted_others": "Zachowano ten zasÃŗb i usunięto {count, plural, one {#zasÃŗb} other {#zasoby}}", "keyboard_shortcuts": "SkrÃŗty klawiaturowe", "language": "Język", @@ -1223,6 +1239,7 @@ "local": "Lokalny", "local_asset_cast_failed": "Nie moÅŧna strumieniować zasobu, ktÃŗry nie został przesłany na serwer", "local_assets": "Zasoby lokalne", + "local_media_summary": "Podsumowanie lokalnych mediÃŗw", "local_network": "Sieć lokalna", "local_network_sheet_info": "Aplikacja połączy się z serwerem za pośrednictwem tego adresu URL podczas korzystania z określonej sieci Wi-Fi", "location_permission": "Zezwolenie na lokalizację", @@ -1234,6 +1251,7 @@ "location_picker_longitude_hint": "Wpisz tutaj swoją długość geograficzną", "lock": "Zablokuj", "locked_folder": "Folder zablokowany", + "log_detail_title": "SzczegÃŗÅ‚y dziennika", "log_out": "Wyloguj", "log_out_all_devices": "Wyloguj ze Wszystkich Urządzeń", "logged_in_as": "Zalogowano jako {user}", @@ -1264,6 +1282,7 @@ "login_password_changed_success": "Hasło zostało zmienione", "logout_all_device_confirmation": "Czy na pewno chcesz wylogować się ze wszystkich urządzeń?", "logout_this_device_confirmation": "Czy na pewno chcesz wylogować to urządzenie?", + "logs": "Logi", "longitude": "Długość geograficzna", "look": "Wygląd", "loop_videos": "Powtarzaj filmy", @@ -1306,6 +1325,7 @@ "mark_as_read": "Zaznacz jako odczytane", "marked_all_as_read": "Zaznaczono wszystkie jako przeczytane", "matches": "Powiązania", + "matching_assets": "Pasujące zasoby", "media_type": "Typ zasobu", "memories": "Wspomnienia", "memories_all_caught_up": "Wszystko złapane", @@ -1346,6 +1366,7 @@ "name_or_nickname": "Nazwa lub pseudonim", "network_requirement_photos_upload": "UÅŧywaj danych komÃŗrkowych do tworzenia kopii zapasowych zdjęć", "network_requirement_videos_upload": "UÅŧywaj danych komÃŗrkowych do tworzenia kopii zapasowych filmÃŗw", + "network_requirements": "Wymagania sieciowe", "network_requirements_updated": "Zmieniono wymagania sieciowe, resetowanie kolejki kopii zapasowych", "networking_settings": "Sieć", "networking_subtitle": "Zarządzaj ustawieniami punktu końcowego serwera", @@ -1356,6 +1377,7 @@ "new_person": "Nowa osoba", "new_pin_code": "Nowy kod PIN", "new_pin_code_subtitle": "Jest to pierwszy raz, kiedy wchodzisz do folderu zablokowanego. UtwÃŗrz kod PIN, aby bezpiecznie korzystać z tej strony", + "new_timeline": "Nowa oś czasu", "new_user_created": "Pomyślnie stworzono nowego uÅŧytkownika", "new_version_available": "NOWA WERSJA DOSTĘPNA", "newest_first": "Od najnowszych", @@ -1369,20 +1391,25 @@ "no_assets_message": "KLIKNIJ, ABY WYSŁAĆ PIERWSZE ZDJĘCIE", "no_assets_to_show": "Brak zasobÃŗw do pokazania", "no_cast_devices_found": "Nie znaleziono urządzeń do przesyłania strumieniowego", + "no_checksum_local": "Brak sumy kontrolnej - nie moÅŧna pobrać lokalnych zasobÃŗw", + "no_checksum_remote": "Brak sumy kontrolnej - nie moÅŧna pobrać zdalnego zasobu", "no_duplicates_found": "Nie znaleziono duplikatÃŗw.", "no_exif_info_available": "Nie znaleziono informacji exif", "no_explore_results_message": "Prześlij więcej zdjęć, aby przeglądać swÃŗj zbiÃŗr.", "no_favorites_message": "Dodaj ulubione aby szybko znaleÅēć swoje najlepsze zdjęcia i filmy", "no_libraries_message": "StwÃŗrz bibliotekę zewnętrzną, aby przeglądać swoje zdjęcia i filmy", + "no_local_assets_found": "Nie znaleziono Åŧadnych lokalnych zasobÃŗw o tej sumie kontrolnej", "no_locked_photos_message": "Zdjęcia i filmy w folderze zablokowanym są ukryte i nie będą wyświetlane podczas przeglądania biblioteki.", "no_name": "Brak Nazwy", "no_notifications": "Brak powiadomień", "no_people_found": "Brak pasujących osÃŗb", "no_places": "Brak miejsc", + "no_remote_assets_found": "Nie znaleziono Åŧadnych zdalnych zasobÃŗw o tej sumie kontrolnej", "no_results": "Brak wynikÃŗw", "no_results_description": "SprÃŗbuj uÅŧyć synonimu lub bardziej ogÃŗlnego słowa kluczowego", "no_shared_albums_message": "StwÃŗrz album aby udostępnić zdjęcia i filmy osobom w Twojej sieci", "no_uploads_in_progress": "Brak przesyłań w toku", + "not_available": "Nie dotyczy", "not_in_any_album": "Bez albumu", "not_selected": "Nie wybrano", "note_apply_storage_label_to_previously_uploaded assets": "Uwaga: Aby przypisać etykietę magazynowania do wcześniej przesłanych zasobÃŗw, uruchom", @@ -1417,6 +1444,8 @@ "open_the_search_filters": "OtwÃŗrz filtry wyszukiwania", "options": "Opcje", "or": "lub", + "organize_into_albums": "Uporządkuj w albumy", + "organize_into_albums_description": "Umieść istniejące zdjęcia w albumach przy uÅŧyciu bieÅŧących ustawień synchronizacji", "organize_your_library": "Organizuj swoją bibliotekę", "original": "oryginalny", "other": "Inne", @@ -1462,7 +1491,7 @@ "permanent_deletion_warning_setting_description": "PokaÅŧ ostrzeÅŧenie przy trwałym usuwaniu zasobÃŗw", "permanently_delete": "Usuń trwale", "permanently_delete_assets_count": "Trwale usuń {count, plural, one {zasÃŗb} few {zasoby} many {zasobÃŗw} other {zasobÃŗw}}", - "permanently_delete_assets_prompt": "Czy na pewno chcesz trwale usunąć {count, plural, one {ten zasÃŗb?} other {te # zasoby?}} Spowoduje to rÃŗwnieÅŧ usunięcie {count, plural, one {go z jego} other {ich z ich}} album(Ãŗw).", + "permanently_delete_assets_prompt": "Czy na pewno chcesz trwale usunąć {count, plural, one {ten zasÃŗb?} few {te # zasoby?} other {te # zasobÃŗw?}} Spowoduje to rÃŗwnieÅŧ usunięcie {count, plural, one {go z jego} other {ich z ich}} album(Ãŗw).", "permanently_deleted_asset": "Pomyślnie trwale usunięto zasÃŗb", "permanently_deleted_assets_count": "Trwale usunięto {count, plural, one {# zasÃŗb} other {# zasobÃŗw}}", "permission": "Pozwolenie", @@ -1502,6 +1531,7 @@ "port": "Port", "preferences_settings_subtitle": "Zarządzaj preferencjami aplikacji", "preferences_settings_title": "Ustawienia", + "preparing": "Przygotowywanie", "preset": "Ustawienie", "preview": "Podgląd", "previous": "Poprzedni", @@ -1518,7 +1548,7 @@ "profile_drawer_client_out_of_date_minor": "Aplikacja mobilna jest nieaktualna. Zaktualizuj do najnowszej pomniejszej wersji.", "profile_drawer_client_server_up_to_date": "Klient i serwer są aktualne", "profile_drawer_github": "GitHub", - "profile_drawer_readonly_mode": "Włączono tryb tylko do odczytu. Aby wyjść, naleÅŧy dwukrotnie dotknąć ikony awatara uÅŧytkownika.", + "profile_drawer_readonly_mode": "Włączono tryb tylko do odczytu. Aby wyjść, naciśnij i przytrzymaj ikonę awatara uÅŧytkownika.", "profile_drawer_server_out_of_date_major": "Serwer jest nieaktualny. Zaktualizuj do najnowszej gÅ‚Ãŗwnej wersji.", "profile_drawer_server_out_of_date_minor": "Serwer jest nieaktualny. Zaktualizuj do najnowszej pomniejszej wersji.", "profile_image_of_user": "Zdjęcie profilowe {user}", @@ -1557,6 +1587,7 @@ "purchase_server_description_2": "Status wspierającego", "purchase_server_title": "Serwer", "purchase_settings_server_activated": "Klucz produktu serwera jest zarządzany przez administratora", + "query_asset_id": "Zapytanie o ID zasobu", "queue_status": "Kolejkowanie {count}/{total}", "rating": "Ocena gwiazdkowa", "rating_clear": "Wyczyść ocenę", @@ -1566,6 +1597,7 @@ "read_changelog": "Zobacz Zmiany", "readonly_mode_disabled": "Tryb tylko do odczytu wyłączony", "readonly_mode_enabled": "Tryb tylko do odczytu włączony", + "ready_for_upload": "Gotowe do przesłania", "reassign": "Przypisz ponownie", "reassigned_assets_to_existing_person": "Przypisano ponownie {count, plural, one {# zasÃŗb} other {# zasobÃŗw}} do {name, select, null {istniejącej osoby} other {{name}}}", "reassigned_assets_to_new_person": "Przypisano ponownie {count, plural, one {# zasÃŗb} other {# zasobÃŗw}} do nowej osoby", @@ -1590,8 +1622,9 @@ "regenerating_thumbnails": "Regenerowanie miniatur", "remote": "Zdalny", "remote_assets": "Zasoby zdalne", + "remote_media_summary": "Podsumowanie mediÃŗw zdalnych", "remove": "Usuń", - "remove_assets_album_confirmation": "Czy na pewno chcesz usunąć {count, plural, one {# zasÃŗb} other {# zasoby}} z albumu?", + "remove_assets_album_confirmation": "Czy na pewno chcesz usunąć {count, plural, one {# zasÃŗb} few {# zasoby} other {# zasobÃŗw}} z albumu?", "remove_assets_shared_link_confirmation": "Czy na pewno chcesz usunąć {count, plural, one {# zasÃŗb} other {# zasoby}} z tego udostępnionego linku?", "remove_assets_title": "Usunąć zasoby?", "remove_custom_date_range": "Usuń niestandardowy zakres dat", @@ -1603,8 +1636,8 @@ "remove_from_locked_folder": "Usuń z folderu zablokowanego", "remove_from_locked_folder_confirmation": "Czy na pewno chcesz przenieść te zdjęcia i filmy z folderu zablokowanego? Będą one widoczne w bibliotece.", "remove_from_shared_link": "Usuń z udostępnionego linku", - "remove_memory": "Usuń pamięć", - "remove_photo_from_memory": "Usuń zdjęcia z tej pamięci", + "remove_memory": "Usuń wspomnienie", + "remove_photo_from_memory": "Usuń zdjęcia z tych wspomnień", "remove_tag": "Usuń tag", "remove_url": "Usuń URL", "remove_user": "Usuń uÅŧytkownika", @@ -1612,15 +1645,15 @@ "removed_from_archive": "Usunięto z archiwum", "removed_from_favorites": "Usunięto z ulubionych", "removed_from_favorites_count": "{count, plural, other {Usunięto #}} z ulubionych", - "removed_memory": "Pamięć została usunięta", - "removed_photo_from_memory": "Usunięto zdjęcie z pamięci", + "removed_memory": "Wspomnienie usunięte", + "removed_photo_from_memory": "Usunięto zdjęcie ze wspomnień", "removed_tagged_assets": "Usunięto etykietę z {count, plural, one {# zasobu} other {# zasobÃŗw}}", "rename": "Zmień nazwę", "repair": "Napraw", "repair_no_results_message": "Tutaj pojawią się nieśledzone i brakujące pliki", "replace_with_upload": "Prześlij nową wersję", "repository": "Repozytorium", - "require_password": "Wymagaj hasło", + "require_password": "Wymagaj hasła", "require_user_to_change_password_on_first_login": "Zmuś uÅŧytkownika do zmiany hasła podczas następnego logowania", "rescan": "Ponowne skanowanie", "reset": "Reset", @@ -1642,6 +1675,7 @@ "restore_user": "PrzywrÃŗÄ‡ uÅŧytkownika", "restored_asset": "PrzywrÃŗcony zasÃŗb", "resume": "WznÃŗw", + "resume_paused_jobs": "WznÃŗw {count, plural, one {# wstrzymane zadanie} few {# wstrzymane zadania} other {# wstrzymanych zadań}}", "retry_upload": "Prześlij ponownie", "review_duplicates": "Przejrzyj duplikaty", "review_large_files": "Przejrzyj duÅŧe pliki", @@ -1664,7 +1698,7 @@ "search_albums": "Przeszukaj albumy", "search_by_context": "Wyszukaj według treści", "search_by_description": "Wyszukaj według opisu", - "search_by_description_example": "Jednodniowa wycieczka gÃŗrska w Bieszczady", + "search_by_description_example": "Całodniowa wycieczka w Bieszczady", "search_by_filename": "Szukaj według nazwy pliku lub rozszerzenia", "search_by_filename_example": "np. IMG_1234.JPG lub PNG", "search_camera_make": "Wyszukaj markę aparatu...", @@ -1713,7 +1747,7 @@ "search_tags": "Wyszukaj etykiety...", "search_timezone": "Wyszukaj strefę czasową...", "search_type": "Wyszukaj w", - "search_your_photos": "Szukaj swoich zdjęć", + "search_your_photos": "Przeszukaj swoje zdjęcia", "searching_locales": "Wyszukaj region...", "second": "Sekunda", "see_all_people": "Zobacz wszystkie osoby", @@ -1733,9 +1767,9 @@ "select_photos": "Wybierz zdjęcia", "select_trash_all": "Zaznacz wszystko do kosza", "select_user_for_sharing_page_err_album": "Nie udało się utworzyć albumu", - "selected": "Zaznaczone", + "selected": "Wybrane", "selected_count": "{count, plural, other {# wybrane}}", - "selected_gps_coordinates": "wybrane wspÃŗÅ‚rzędne GPS", + "selected_gps_coordinates": "Wybrane WspÃŗÅ‚rzędne GPS", "send_message": "Wyślij wiadomość", "send_welcome_email": "Wyślij e-mail powitalny", "server_endpoint": "Punkt końcowy serwera", @@ -1846,10 +1880,8 @@ "shift_to_permanent_delete": "naciśnij ⇧, aby trwale usunąć zasÃŗb", "show_album_options": "PokaÅŧ opcje albumu", "show_albums": "PokaÅŧ albumy", - "show_all_assets": "PokaÅŧ wszystkie zasoby", "show_all_people": "PokaÅŧ wszystkie osoby", "show_and_hide_people": "PokaÅŧ lub ukryj osoby", - "show_assets_without_location": "PokaÅŧ zasoby bez lokalizacji", "show_file_location": "PokaÅŧ ścieÅŧkę pliku", "show_gallery": "Wyświetl galerię", "show_hidden_people": "PokaÅŧ ukryte osoby", @@ -1866,6 +1898,7 @@ "show_slideshow_transition": "PokaÅŧ przejście pokazu slajdÃŗw", "show_supporter_badge": "Odznaka wspierającego", "show_supporter_badge_description": "PokaÅŧ odznakę wspierającego", + "show_text_search_menu": "PokaÅŧ menu wyszukiwania tekstowego", "shuffle": "Losuj", "sidebar": "Panel boczny", "sidebar_display_description": "Wyświetl link do widoku w pasku bocznym", @@ -1890,12 +1923,13 @@ "stack": "Stos", "stack_action_prompt": "{count} zgrupowano", "stack_duplicates": "Stos duplikatÃŗw", - "stack_select_one_photo": "Wybierz jedno gÅ‚Ãŗwne zdjęcie do stosu", - "stack_selected_photos": "Układaj wybrane zdjęcia", - "stacked_assets_count": "UłoÅŧone {count, plural, one {# zasÃŗb} other{# zasoby}}", + "stack_select_one_photo": "Wybierz jedno gÅ‚Ãŗwne zdjęcie dla stosu", + "stack_selected_photos": "UtwÃŗrz stos z wybranych zdjęć", + "stacked_assets_count": "Utworzono stos z {count, plural, one {# zasobu} other {# zasobÃŗw}}", "stacktrace": "Ślad stosu", "start": "Start", "start_date": "Od dnia", + "start_date_before_end_date": "Data początkowa musi być wcześniejsza niÅŧ data końcowa", "state": "WojewÃŗdztwo", "status": "Status", "stop_casting": "Zatrzymaj strumieniowanie", @@ -1920,6 +1954,8 @@ "sync_albums_manual_subtitle": "Zsynchronizuj wszystkie przesłane filmy i zdjęcia z wybranymi albumami z włączoną kopią zapasową", "sync_local": "Synchronizacja lokalna", "sync_remote": "Synchronizacja zdalna", + "sync_status": "Stan synchronizacji", + "sync_status_subtitle": "Wyświetl i zarządzaj systemem synchronizacji", "sync_upload_album_setting_subtitle": "TwÃŗrz i przesyłaj swoje zdjęcia i filmy do wybranych albumÃŗw w Immich", "tag": "Etykieta", "tag_assets": "Ustaw etykiety zasobÃŗw", @@ -1953,7 +1989,7 @@ "time_based_memories": "Wspomnienia oparte na czasie", "timeline": "Oś czasu", "timezone": "Strefa czasowa", - "to_archive": "Archiwum", + "to_archive": "Zarchiwizuj", "to_change_password": "Zmień hasło", "to_favorite": "Dodaj do ulubionych", "to_login": "Zaloguj się", @@ -1967,7 +2003,7 @@ "trash": "Kosz", "trash_action_prompt": "{count} przeniesione do kosza", "trash_all": "Usuń wszystkie", - "trash_count": "Kosz {count, number}", + "trash_count": "Usuń {count, number}", "trash_delete_asset": "Kosz/Usuń zasÃŗb", "trash_emptied": "OprÃŗÅŧnione śmieci", "trash_no_results_message": "Tu znajdziesz wyrzucone zdjęcia i filmy.", @@ -1979,10 +2015,11 @@ "trash_page_select_assets_btn": "Wybierz zasoby", "trash_page_title": "Kosz ({count})", "trashed_items_will_be_permanently_deleted_after": "Wyrzucone zasoby zostaną trwale usunięte po {days, plural, one {jednym dniu} other {# dniach}}.", + "troubleshoot": "RozwiąÅŧ problemy", "type": "Typ", "unable_to_change_pin_code": "Nie moÅŧna zmienić kodu PIN", "unable_to_setup_pin_code": "Nie moÅŧna ustawić kodu PIN", - "unarchive": "Cofnij archiwizację", + "unarchive": "PrzywrÃŗÄ‡ z archiwum", "unarchive_action_prompt": "{count} usunięto z archiwum", "unarchived_count": "{count, plural, one {# cofnięta archiwizacja} few {# cofnięte archiwizacje} other {# cofniętych archiwizacji}}", "undo": "Cofnij", @@ -2004,9 +2041,9 @@ "unselect_all": "Odznacz wszystko", "unselect_all_duplicates": "Odznacz wszystkie duplikaty", "unselect_all_in": "Odznacz wszystkie w {group}", - "unstack": "RozÅ‚ÃŗÅŧ stos", - "unstack_action_prompt": "{count} odgrupowano", - "unstacked_assets_count": "{count, plural, one {RozłoÅŧony # zasÃŗb} few {RozłoÅŧone # zasoby} other {RozłoÅŧonych # zasobÃŗw}}", + "unstack": "Rozdziel stos", + "unstack_action_prompt": "{count} rozdzielono", + "unstacked_assets_count": "Rozdzielono {count, plural, one {# zasÃŗb} few {# zasoby} other {# zasobÃŗw}}", "untagged": "Nieoznaczone", "up_next": "Do następnego", "update_location_action_prompt": "Zaktualizuj lokalizację {count} wybranych zasobÃŗw na:", @@ -2034,7 +2071,6 @@ "use_biometric": "UÅŧyj biometrii", "use_current_connection": "uÅŧyj bieÅŧącego połączenia", "use_custom_date_range": "Zamiast tego uÅŧyj niestandardowego zakresu dat", - "use_this_location": "Kliknij, aby uÅŧyć lokalizacji", "user": "UÅŧytkownik", "user_has_been_deleted": "Ten uÅŧytkownik został usunięty.", "user_id": "ID uÅŧytkownika", @@ -2077,11 +2113,12 @@ "view_next_asset": "Wyświetl następny zasÃŗb", "view_previous_asset": "Wyświetl poprzedni zasÃŗb", "view_qr_code": "PokaÅŧ kod QR", - "view_stack": "Zobacz UłoÅŧenie", + "view_similar_photos": "Zobacz podobne zdjęcia", + "view_stack": "Zobacz stos", "view_user": "Wyświetl uÅŧytkownika", "viewer_remove_from_stack": "Usuń ze stosu", "viewer_stack_use_as_main_asset": "UÅŧyj jako gÅ‚Ãŗwnego zasobu", - "viewer_unstack": "RozÅ‚ÃŗÅŧ Stos", + "viewer_unstack": "Rozdziel stos", "visibility_changed": "Zmieniono widoczność dla {count, plural, one {# osoby} other {# osÃŗb}}", "waiting": "Oczekujące", "warning": "OstrzeÅŧenie", @@ -2095,5 +2132,6 @@ "yes": "Tak", "you_dont_have_any_shared_links": "Nie masz Åŧadnych udostępnionych linkÃŗw", "your_wifi_name": "Twoja nazwa Wi-Fi", - "zoom_image": "Powiększ obraz" + "zoom_image": "Powiększ obraz", + "zoom_to_bounds": "Powiększ do krawędzi" } diff --git a/i18n/pt.json b/i18n/pt.json index f43fac797b..fdb3561ed2 100644 --- a/i18n/pt.json +++ b/i18n/pt.json @@ -28,10 +28,12 @@ "add_to_album": "Adicionar ao ÃĄlbum", "add_to_album_bottom_sheet_added": "Adicionado a {album}", "add_to_album_bottom_sheet_already_exists": "JÃĄ existe em {album}", + "add_to_album_bottom_sheet_some_local_assets": "Alguns conteÃēdos locais nÃŖo puderam ser adicionados no ÃĄlbum", "add_to_album_toggle": "Alternar seleÃ§ÃŖo para {album}", "add_to_albums": "Adicionar aos ÃĄlbuns", "add_to_albums_count": "Adicionar aos ÃĄlbuns ({count})", "add_to_shared_album": "Adicionar ao ÃĄlbum partilhado", + "add_upload_to_stack": "Adicionar carregamento à fila", "add_url": "Adicionar URL", "added_to_archive": "Adicionado ao arquivo", "added_to_favorites": "Adicionado aos favoritos", @@ -123,6 +125,13 @@ "logging_enable_description": "Ativar registo", "logging_level_description": "Quando ativado, qual o nível de log a usar.", "logging_settings": "Registo", + "machine_learning_availability_checks": "VerificaÃ§ÃŖo de disponibilidade", + "machine_learning_availability_checks_description": "Detectar automaticamente e dar preferÃĒncia aos servidores de aprendizagem automÃĄtica disponíveis", + "machine_learning_availability_checks_enabled": "Ativar confirmaçÃĩes de disponibilidade", + "machine_learning_availability_checks_interval": "ConfirmaÃ§ÃŖo de intervalo", + "machine_learning_availability_checks_interval_description": "Intervalo, em milisegundos, entre confirmaçÃĩes de disponibilidade", + "machine_learning_availability_checks_timeout": "Tempo limite para requisiÃ§ÃŖo", + "machine_learning_availability_checks_timeout_description": "Tempo limite em milissegundos para verificaçÃĩes de disponibilidade", "machine_learning_clip_model": "Modelo CLIP", "machine_learning_clip_model_description": "O nome do modelo CLIP definido aqui. Tome nota de que Ê necessÃĄrio voltar a executar a tarefa de \"Pesquisa Inteligente\" para todas as imagens depois de alterar o modelo.", "machine_learning_duplicate_detection": "DeteÃ§ÃŖo de Itens Duplicados", @@ -360,7 +369,7 @@ "trash_settings_description": "Gerir definiçÃĩes da reciclagem", "unlink_all_oauth_accounts": "Desvincular todas as contas OAuth", "unlink_all_oauth_accounts_description": "Lembre-se de desvincular todas as contas OAuth antes de migrar para um novo provedor.", - "unlink_all_oauth_accounts_prompt": "Tem a certeza de que deseja desvincular todas as contas OAuth? Isso redefinirÃĄ o ID OAuth de cada utilizador e nÃŖo poderÃĄ ser desfeito.", + "unlink_all_oauth_accounts_prompt": "Tem a certeza de que deseja desvincular todas as contas OAuth? Isto irÃĄ redefinir o ID OAuth de cada utilizador e nÃŖo poderÃĄ ser anulado.", "user_cleanup_job": "Limpeza de utilizadores", "user_delete_delay": "A conta e os ficheiros de {user} serÃŖo agendados para eliminaÃ§ÃŖo permanente dentro de {delay, plural, one {# dia} other {# dias}}.", "user_delete_delay_settings": "Atraso de eliminaÃ§ÃŖo", @@ -387,8 +396,6 @@ "admin_password": "Palavra-passe do administrador", "administration": "AdministraÃ§ÃŖo", "advanced": "Avançado", - "advanced_settings_beta_timeline_subtitle": "Experimente as novas funcionalidades da aplicaÃ§ÃŖo", - "advanced_settings_beta_timeline_title": "Linha temporal da versÃŖo Beta", "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: {level}", @@ -396,8 +403,8 @@ "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_readonly_mode_subtitle": "Activa o modo somente leitura, onde as fotos podem ser visualizadas. Recursos como selecionar vÃĄrias imagens, partilhar, transmitir e excluir ficam deactivados. Activar/Desactivar o modo somente leitura via avatar do utilizador na janela principal", - "advanced_settings_readonly_mode_title": "Modo somente leitura", + "advanced_settings_readonly_mode_subtitle": "Ativa o modo sÃŗ de leitura, onde as fotos apenas podem ser visualizadas. FunçÃĩes como selecionar vÃĄrias imagens, partilhar, transmitir e eliminar ficam deactivadas. Pode ativar ou desativar o modo sÃŗ de leitura atravÊs da imagem de perfil do utilizador na janela principal", + "advanced_settings_readonly_mode_title": "Modo sÃŗ de leitura", "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", @@ -425,6 +432,7 @@ "album_remove_user_confirmation": "Tem a certeza de que quer remover {user}?", "album_search_not_found": "Nenhum ÃĄlbum encontrado segundo a pesquisa", "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_summary": "Resumo do ÃĄlbum", "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}", @@ -496,6 +504,8 @@ "asset_restored_successfully": "Arquivo restaurado com sucesso", "asset_skipped": "Ignorado", "asset_skipped_in_trash": "Na reciclagem", + "asset_trashed": "Ficheiro apagado", + "asset_troubleshoot": "ResoluÃ§ÃŖo de problemas com conteÃēdos", "asset_uploaded": "Enviado", "asset_uploading": "A enviarâ€Ļ", "asset_viewer_settings_subtitle": "Gerenciar as configuraçÃĩes do visualizador da galeria", @@ -503,9 +513,9 @@ "assets": "Ficheiros", "assets_added_count": "{count, plural, one {# ficheiro adicionado} other {# ficheiros adicionados}}", "assets_added_to_album_count": "{count, plural, one {# ficheiro adicionado} other {# ficheiros adicionados}} ao ÃĄlbum", - "assets_added_to_albums_count": "Adicionado {assetTotal, plural, one {# asset} other {# assets}} a {albumTotal, plural, one {# album} other {# albums}}", + "assets_added_to_albums_count": "{assetTotal, plural, one {Foi adicionado # ficheiro} other {Foram adiciondos # ficheiros}} a {albumTotal, plural, one {# ÃĄlbum} other {# albuns}}", "assets_cannot_be_added_to_album_count": "NÃŖo foi possível adicionar {count, plural, one {ficheiro} other {ficheiros}} ao ÃĄlbum", - "assets_cannot_be_added_to_albums": "{count, plural, one {Asset} other {Assets}} nÃŖo pode ser adicionado a nenhum dos ÃĄlbuns", + "assets_cannot_be_added_to_albums": "{count, plural, one {Ficheiro nÃŖo pode ser adicionado} other {Ficheiros nÃŖo podem ser adiciondos}} a nenhum dos ÃĄlbuns", "assets_count": "{count, plural, one {# ficheiro} other {# ficheiros}}", "assets_deleted_permanently": "{count} ficheiro(s) eliminado(s) permanentemente", "assets_deleted_permanently_from_server": "{count} ficheiro(s) eliminado(s) permanentemente do servidor Immich", @@ -522,15 +532,17 @@ "assets_trashed_count": "{count, plural, one {# ficheiro enviado} other {# ficheiros enviados}} para a reciclagem", "assets_trashed_from_server": "{count} 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", - "assets_were_part_of_albums_count": "{count, plural, one {Asset was} other {Assets were}} jÃĄ faz parte dos ÃĄlbuns", + "assets_were_part_of_albums_count": "{count, plural, one {Ficheiro jÃĄ fazia} other {Ficheiros jÃĄ faziam}} parte dos ÃĄlbuns", "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", "automatic_endpoint_switching_title": "Troca automÃĄtica de URL", "autoplay_slideshow": "ApresentaÃ§ÃŖo automÃĄtica de diapositivos", "back": "Voltar", "back_close_deselect": "Voltar, fechar ou desmarcar", + "background_backup_running_error": "Com a cÃŗpia de segurança de fundo em execuÃ§ÃŖo, nÃŖo Ê possível inicar uma manual", "background_location_permission": "PermissÃŖo de localizaÃ§ÃŖo em segundo plano", "background_location_permission_content": "Para que seja possível trocar a URL quando estiver executando em segundo plano, o Immich deve *sempre* ter a permissÃŖo de localizaÃ§ÃŖo precisa para que o aplicativo consiga ler o nome da rede Wi-Fi", + "background_options": "OpçÃĩes de fundo", "backup": "CÃŗpia de segurança", "backup_album_selection_page_albums_device": "Álbuns no dispositivo ({count})", "backup_album_selection_page_albums_tap": "Toque para incluir, duplo toque para excluir", @@ -538,6 +550,7 @@ "backup_album_selection_page_select_albums": "Selecione Álbuns", "backup_album_selection_page_selection_info": "InformaçÃĩes da SeleÃ§ÃŖo", "backup_album_selection_page_total_assets": "Total de arquivos Ãēnicos", + "backup_albums_sync": "CÃŗpia de segurança de sincronizaÃ§ÃŖo de ÃĄlbuns", "backup_all": "Tudo", "backup_background_service_backup_failed_message": "Ocorreu um erro ao efetuar cÃŗpia de segurança dos ficheiros. A tentar de novoâ€Ļ", "backup_background_service_connection_failed_message": "Ocorreu um erro na ligaÃ§ÃŖo ao servidor. A tentar de novoâ€Ļ", @@ -577,7 +590,7 @@ "backup_controller_page_remainder": "Restante", "backup_controller_page_remainder_sub": "Fotos e vídeos selecionados restantes para fazer backup", "backup_controller_page_server_storage": "Armazenamento no servidor", - "backup_controller_page_start_backup": "Iniciar Backup", + "backup_controller_page_start_backup": "Iniciar CÃŗpia de Segurança", "backup_controller_page_status_off": "Backup automÃĄtico desativado", "backup_controller_page_status_on": "Backup automÃĄtico ativado", "backup_controller_page_storage_format": "{used} de {total} utilizado", @@ -587,18 +600,17 @@ "backup_controller_page_turn_on": "Ativar backup", "backup_controller_page_uploading_file_info": "Enviando arquivo", "backup_err_only_album": "NÃŖo Ê possível remover apenas o ÃĄlbum", + "backup_error_sync_failed": "A sincronizaÃ§ÃŖo falhou. NÃŖo Ê possível fazer a cÃŗpia de segurança.", "backup_info_card_assets": "arquivos", "backup_manual_cancelled": "Cancelado", "backup_manual_in_progress": "Envio jÃĄ estÃĄ em progresso. Tente novamente mais tarde", "backup_manual_success": "Sucesso", "backup_manual_title": "Estado do envio", "backup_options": "DefiniçÃĩes de cÃŗpia de segurança", - "backup_options_page_title": "OpçÃĩes de backup", + "backup_options_page_title": "OpçÃĩes de cÃŗpia de segurança", "backup_setting_subtitle": "Gerenciar as configuraçÃĩes de envio em primeiro e segundo plano", "backup_settings_subtitle": "Gerir definiçÃĩes de carregamento", "backward": "Para trÃĄs", - "beta_sync": "Estado de SincronizaÃ§ÃŖo Beta", - "beta_sync_subtitle": "Gerir o novo sistema de sincronizaÃ§ÃŖo", "biometric_auth_enabled": "AutenticaÃ§ÃŖo biomÊtrica ativada", "biometric_locked_out": "EstÃĄ impedido de utilizar a autenticaÃ§ÃŖo biomÊtrica", "biometric_no_options": "Sem opçÃĩes biomÊtricas disponíveis", @@ -656,6 +668,8 @@ "change_pin_code": "Alterar cÃŗdigo PIN", "change_your_password": "Alterar a sua palavra-passe", "changed_visibility_successfully": "Visibilidade alterada com sucesso", + "charging": "A carregar", + "charging_requirement_mobile_backup": "CÃŗpia de segurança de fundo necessita que o dispositivo esteja a carregar", "check_corrupt_asset_backup": "Verificar por backups corrompidos", "check_corrupt_asset_backup_button": "Verificar", "check_corrupt_asset_backup_description": "Execute esta verificaÃ§ÃŖo somente em uma rede Wi-Fi e quando o backup de todos os arquivos jÃĄ estiver concluído. O processo demora alguns minutos.", @@ -742,6 +756,7 @@ "create_user": "Criar utilizador", "created": "Criado", "created_at": "Criado a", + "creating_linked_albums": "A criar albuns ligados...", "crop": "Cortar", "curated_object_page_title": "Objetos", "current_device": "Dispositivo atual", @@ -891,7 +906,9 @@ "error": "Erro", "error_change_sort_album": "Ocorreu um erro ao mudar a ordem de exibiÃ§ÃŖo", "error_delete_face": "Falha ao remover rosto do ficheiro", + "error_getting_places": "Erro ao obter locais", "error_loading_image": "Erro ao carregar a imagem", + "error_loading_partners": "Erro ao carregar parceiros: {error}", "error_saving_image": "Erro: {error}", "error_tag_face_bounding_box": "Erro ao marcar o rosto - nÃŖo foi possível localizar o rosto", "error_title": "Erro - Algo correu mal", @@ -924,7 +941,7 @@ "failed_to_load_notifications": "Ocorreu um erro ao carregar notificaçÃĩes", "failed_to_load_people": "Ocorreu um erro ao carregar pessoas", "failed_to_remove_product_key": "Ocorreu um erro ao remover chave de produto", - "failed_to_reset_pin_code": "Falha ao repor o cÃŗdigo PIN", + "failed_to_reset_pin_code": "Ocorreu um erro ao repor o cÃŗdigo PIN", "failed_to_stack_assets": "Ocorreu um erro ao empilhar os ficheiros", "failed_to_unstack_assets": "Ocorreu um erro ao desempilhar ficheiros", "failed_to_update_notification_status": "Ocorreu um erro ao atualizar o estado das notificaçÃĩes", @@ -933,7 +950,7 @@ "paths_validation_failed": "Ocorreu um erro na validaÃ§ÃŖo de {paths, plural, one {# caminho} other {# caminhos}}", "profile_picture_transparent_pixels": "Imagem de perfil nÃŖo pode ter pixeis transparentes. Por favor amplie e/ou mova a imagem.", "quota_higher_than_disk_size": "Definiu uma quota maior do que o tamanho do disco", - "something_went_wrong": "Algo deu errado", + "something_went_wrong": "Algo correu mal", "unable_to_add_album_users": "NÃŖo foi possível adicionar utilizadores ao ÃĄlbum", "unable_to_add_assets_to_shared_link": "NÃŖo foi possível adicionar os ficheiros ao link partilhado", "unable_to_add_comment": "NÃŖo foi possível adicionar o comentÃĄrio", @@ -1056,6 +1073,7 @@ "favorites_page_no_favorites": "Nenhum favorito encontrado", "feature_photo_updated": "Foto principal atualizada", "features": "Funcionalidades", + "features_in_development": "Funcionalidades em Desenvolvimento", "features_setting_description": "Configurar as funcionalidades da aplicaÃ§ÃŖo", "file_name": "Nome do ficheiro", "file_name_or_extension": "Nome do ficheiro ou extensÃŖo", @@ -1071,15 +1089,12 @@ "folder_not_found": "Pasta nÃŖo encontrada", "folders": "Pastas", "folders_feature_description": "Navegar na vista de pastas por fotos e vídeos no sistema de ficheiros", - "forgot_pin_code_question": "Esqueceu o seu PIN?", + "forgot_pin_code_question": "Esqueceu-se do seu PIN?", "forward": "Para a frente", "gcast_enabled": "Google Cast", "gcast_enabled_description": "Esta funcionalidade requer o carregamento de recursos externos da Google para poder funcionar.", "general": "Geral", - "geolocation_instruction_all_have_location": "Todos os activos desta data jÃĄ possuem dados de localizaÃ§ÃŖo. Tente exibir todos os ativos ou seleccione uma data diferente", - "geolocation_instruction_location": "Clique num ativo com coordenadas GPS para usar a sua localizaÃ§ÃŖo ou seleccione um local diretamente do mapa", - "geolocation_instruction_no_date": "Seleccione uma data para gerir os dados de localizaÃ§ÃŖo de fotos e vídeos daquele dia", - "geolocation_instruction_no_photos": "Nenhuma foto ou vídeo encontrado para esta data. Seleccione uma data diferente para exibi-los", + "geolocation_instruction_location": "Clique num ficheiro com coordenadas GPS para usar a sua localizaÃ§ÃŖo ou selecione um local diretamente do mapa", "get_help": "Obter Ajuda", "get_wifiname_error": "NÃŖo foi possível obter o nome do Wi-Fi. Verifique se concedeu as permissÃĩes necessÃĄrias e se estÃĄ conectado a uma rede Wi-Fi", "getting_started": "Primeiros Passos", @@ -1212,7 +1227,7 @@ "library_page_sort_title": "Título do ÃĄlbum", "licenses": "Licenças", "light": "Claro", - "like": "Gostar", + "like": "Gosto", "like_deleted": "Gosto removido", "link_motion_video": "Relacionar video animado", "link_to_oauth": "Link do OAuth", @@ -1223,6 +1238,7 @@ "local": "Local", "local_asset_cast_failed": "NÃŖo Ê possível transmitir um ficheiro que nÃŖo tenha sido enviado antes para o servidor", "local_assets": "Ficheiros Locais", + "local_media_summary": "SumÃĄrio de conteÃēdo local", "local_network": "Rede local", "local_network_sheet_info": "O aplicativo irÃĄ se conectar ao servidor atravÊs desta URL quando estiver na rede Wi-Fi especificada", "location_permission": "PermissÃŖo de localizaÃ§ÃŖo", @@ -1234,12 +1250,13 @@ "location_picker_longitude_hint": "Digite a longitude", "lock": "Trancar", "locked_folder": "Pasta Trancada", + "log_detail_title": "Detalhes de registo", "log_out": "Sair", "log_out_all_devices": "Terminar a sessÃŖo de todos os dispositivos", "logged_in_as": "Utilizador atual: {user}", "logged_out_all_devices": "SessÃŖo terminada em todos os dispositivos", "logged_out_device": "SessÃŖo terminada no dispositivo", - "login": "Iniciar sessÃŖo", + "login": "Iniciar SessÃŖo", "login_disabled": "Login desativado", "login_form_api_exception": "Erro de API. Verifique a URL do servidor e tente novamente.", "login_form_back_button_text": "Voltar", @@ -1248,7 +1265,7 @@ "login_form_endpoint_url": "URL do servidor", "login_form_err_http": "Por favor especifique http:// ou https://", "login_form_err_invalid_email": "Email InvÃĄlido", - "login_form_err_invalid_url": "URL invÃĄlida", + "login_form_err_invalid_url": "URL invÃĄlido", "login_form_err_leading_whitespace": "Espaço em branco no início", "login_form_err_trailing_whitespace": "Espaço em branco no fim", "login_form_failed_get_oauth_server_config": "Ocorreu um erro ao iniciar sessÃŖo com o OAuth, verifique o URL do servidor", @@ -1264,11 +1281,12 @@ "login_password_changed_success": "Palavra-passe atualizada com sucesso", "logout_all_device_confirmation": "Tem a certeza de que deseja terminar a sessÃŖo em todos os dispositivos?", "logout_this_device_confirmation": "Tem a certeza de que deseja terminar a sessÃŖo deste dispositivo?", + "logs": "Logs", "longitude": "Longitude", "look": "Estilo", "loop_videos": "Repetir vídeos", "loop_videos_description": "Ativar para repetir os vídeos automaticamente durante a exibiÃ§ÃŖo.", - "main_branch_warning": "EstÃĄ a utilizar uma versÃŖo de desenvolvimento, recomendamos vivamente que utilize uma versÃŖo estÃĄvel!", + "main_branch_warning": "EstÃĄ a usar uma versÃŖo de desenvolvimento; recomendamos vivamente que use uma versÃŖo de lançamento!", "main_menu": "Menu Principal", "make": "Marca", "manage_geolocation": "Gerir localizaÃ§ÃŖo", @@ -1280,7 +1298,7 @@ "manage_your_devices": "Gerir os seus dispositivos com sessÃŖo iniciada", "manage_your_oauth_connection": "Gerir a sua ligaÃ§ÃŖo ao OAuth", "map": "Mapa", - "map_assets_in_bounds": "{count, plural, =0 {No photos in this area} one {# photo} other {# photos}}", + "map_assets_in_bounds": "{count, plural, =0 {Sem fotos nesta ÃĄrea} one {# foto} other {# fotos}}", "map_cannot_get_user_location": "Impossível obter a sua localizaÃ§ÃŖo", "map_location_dialog_yes": "Sim", "map_location_picker_page_use_location": "Utilizar esta localizaÃ§ÃŖo", @@ -1306,6 +1324,7 @@ "mark_as_read": "Marcar como lido", "marked_all_as_read": "Tudo marcado como lido", "matches": "CorrespondÃĒncias", + "matching_assets": "ConteÃēdos coincidentes", "media_type": "Tipo de mÊdia", "memories": "MemÃŗrias", "memories_all_caught_up": "Finalizamos por hoje", @@ -1344,11 +1363,12 @@ "my_albums": "Os meus ÃĄlbuns", "name": "Nome", "name_or_nickname": "Nome ou alcunha", - "network_requirement_photos_upload": "Usar dados mÃŗveis para fazer backup de fotos", - "network_requirement_videos_upload": "Usar dados mÃŗveis para fazer backup de vídeos", - "network_requirements_updated": "Requisitos de rede alterados, redefinindo fila de backup", - "networking_settings": "ConexÃĩes", - "networking_subtitle": "Gerencie a conexÃŖo do servidor", + "network_requirement_photos_upload": "Usar dados mÃŗveis para fazer cÃŗpia de segurança de fotos", + "network_requirement_videos_upload": "Usar dados mÃŗveis para fazer cÃŗpia de segurança de vídeos", + "network_requirements": "Requisitos de rede", + "network_requirements_updated": "Requisitos de rede alterados, a redefinir fila de cÃŗpia de segurança", + "networking_settings": "LigaçÃĩes", + "networking_subtitle": "Gerir as ligaçÃĩes de rede do servidor", "never": "Nunca", "new_album": "Novo Álbum", "new_api_key": "Nova Chave de API", @@ -1356,6 +1376,7 @@ "new_person": "Nova Pessoa", "new_pin_code": "Novo cÃŗdigo PIN", "new_pin_code_subtitle": "Esta Ê a primeira vez que acede à pasta trancada. Crie um cÃŗdigo PIN para aceder a esta pÃĄgina de forma segura", + "new_timeline": "Nova Linha do Tempo", "new_user_created": "Novo utilizador criado", "new_version_available": "NOVA VERSÃO DISPONÍVEL", "newest_first": "Mais recente primeiro", @@ -1369,20 +1390,25 @@ "no_assets_message": "FAÇA CLIQUE PARA CARREGAR A SUA PRIMEIRA FOTO", "no_assets_to_show": "NÃŖo hÃĄ arquivos para exibir", "no_cast_devices_found": "Nenhum dispositivo de transmissÃŖo encontrado", + "no_checksum_local": "Sem cÃĄlculo de verificaÃ§ÃŖo disponível - nÃŖo pode capturar conteÃēdos locais", + "no_checksum_remote": "Soma de verificaÃ§ÃŖo (checksum) nÃŖo disponível - nÃŖo Ê possível obter o recurso remoto", "no_duplicates_found": "Nenhum item duplicado foi encontrado.", "no_exif_info_available": "Sem informaçÃĩes exif disponíveis", "no_explore_results_message": "Carregue mais fotos para explorar a sua coleÃ§ÃŖo.", "no_favorites_message": "Adicione aos favoritos para encontrar as suas melhores fotos e vídeos rapidamente", "no_libraries_message": "Crie uma biblioteca externa para ver as suas fotos e vídeos", + "no_local_assets_found": "Sem cÃĄlculo de verificaÃ§ÃŖo disponível", "no_locked_photos_message": "Fotos e vídeos na pasta trancada estÃŖo ocultos e nÃŖo serÃŖo exibidos enquanto explora ou pesquisa na biblioteca.", "no_name": "Sem nome", "no_notifications": "Sem notificaçÃĩes", "no_people_found": "Nenhuma pessoa encontrada", "no_places": "Sem lugares", + "no_remote_assets_found": "Soma de verificaÃ§ÃŖo (checksum) nÃŖo disponível - nÃŖo Ê possível obter o recurso remoto", "no_results": "Sem resultados", "no_results_description": "Tente um sinÃŗnimo ou uma palavra-chave mais comum", "no_shared_albums_message": "Crie um ÃĄlbum para partilhar fotos e vídeos com pessoas na sua rede", "no_uploads_in_progress": "Nenhum carregamento em curso", + "not_available": "N/A", "not_in_any_album": "NÃŖo estÃĄ em nenhum ÃĄlbum", "not_selected": "NÃŖo selecionado", "note_apply_storage_label_to_previously_uploaded assets": "Nota: Para aplicar o RÃŗtulo de Armazenamento a ficheiros carregados anteriormente, execute o", @@ -1417,6 +1443,8 @@ "open_the_search_filters": "Abrir os filtros de pesquisa", "options": "OpçÃĩes", "or": "ou", + "organize_into_albums": "Organizar em ÃĄlbuns", + "organize_into_albums_description": "Colocar fotos existentes em ÃĄlbuns utilizando as definiçÃĩes atuais de sincronizaÃ§ÃŖo", "organize_your_library": "Organizar a sua biblioteca", "original": "original", "other": "Outro", @@ -1476,9 +1504,9 @@ "permission_onboarding_permission_limited": "PermissÃŖo limitada. Para permitir que o Immich faça backups e gerencie sua galeria, conceda permissÃĩes para fotos e vídeos nas configuraçÃĩes.", "permission_onboarding_request": "O Immich requer autorizaÃ§ÃŖo para ver as suas fotos e vídeos.", "person": "Pessoa", - "person_age_months": "{months, plural, one {# month} other {# months}} idade", - "person_age_year_months": "1 ano, {months, plural, one {# month} other {# months}} idade", - "person_age_years": "{years, plural, other {# years}} idade", + "person_age_months": "{months, plural, one {# month} other {# months}} de idade", + "person_age_year_months": "1 ano, {months, plural, one {# month} other {# months}} de idade", + "person_age_years": "{years, plural, other {# anos}} de idade", "person_birthdate": "Nasceu a {date}", "person_hidden": "{name}{hidden, select, true { (oculto)} other {}}", "photo_shared_all_users": "Parece que partilhou as suas fotos com todos os utilizadores ou nÃŖo tem nenhum utilizador para partilhar.", @@ -1502,6 +1530,7 @@ "port": "Porta", "preferences_settings_subtitle": "Gerenciar preferÃĒncias do aplicativo", "preferences_settings_title": "PreferÃĒncias", + "preparing": "A Preparar", "preset": "PredefiniÃ§ÃŖo", "preview": "PrÊ-visualizar", "previous": "Anterior", @@ -1518,7 +1547,7 @@ "profile_drawer_client_out_of_date_minor": "O aplicativo estÃĄ desatualizado. Por favor, atualize para a versÃŖo mais recente.", "profile_drawer_client_server_up_to_date": "Cliente e Servidor atualizados", "profile_drawer_github": "GitHub", - "profile_drawer_readonly_mode": "Modo somente leitura activado. Toque duas vezes no ícone do avatar do utilizador para sair.", + "profile_drawer_readonly_mode": "Modo sÃŗ de leitura ativado. Faça um toque longo no ícone do perfil do utilizador para sair.", "profile_drawer_server_out_of_date_major": "O servidor estÃĄ desatualizado. Atualize para a versÃŖo principal mais recente.", "profile_drawer_server_out_of_date_minor": "O servidor estÃĄ desatualizado. Atualize para a versÃŖo mais recente.", "profile_image_of_user": "Imagem de perfil de {user}", @@ -1545,7 +1574,7 @@ "purchase_lifetime_description": "Compra vitalícia", "purchase_option_title": "OPÇÕES DE COMPRA", "purchase_panel_info_1": "O desenvolvimento do Immich requer muito tempo e esforço, e temos engenheiros a tempo inteiro a trabalhar nele para melhorÃĄ-lo quanto possível. A nossa missÃŖo Ê para que o software de cÃŗdigo aberto e prÃĄticas de negÃŗcio Êticas se tornem numa fonte de rendimento sustentÃĄvel para os desenvolvedores e criar um ecossistema que respeite a privacidade dos utilizadores e que ofereça alternativas reais a serviços cloud explorativos.", - "purchase_panel_info_2": "Como estamos comprometidos a nÃŖo adicionar acesso pago, esta compra nÃŖo lhe darÃĄ acesso a nenhuma funcionalidade adicional do Immich. Contamos com utilizadores como vocÃĒ para dar suporte ao desenvolvimento contínuo do Immich.", + "purchase_panel_info_2": "Uma vez que estamos empenhados em nÃŖo adicionar barreiras de pagamento, esta compra nÃŖo lhe darÃĄ quaisquer funcionalidades adicionais no Immich. Contamos com utilizadores como vocÃĒ para apoiar o desenvolvimento contínuo do Immich.", "purchase_panel_title": "Apoie o projeto", "purchase_per_server": "Por servidor", "purchase_per_user": "Por utilizador", @@ -1557,6 +1586,7 @@ "purchase_server_description_2": "Status de apoiante", "purchase_server_title": "Servidor", "purchase_settings_server_activated": "A chave de produto do servidor Ê gerida pelo administrador", + "query_asset_id": "Consultar ID do ficheiro", "queue_status": "Em fila {count}/{total}", "rating": "ClassificaÃ§ÃŖo por estrelas", "rating_clear": "Limpar classificaÃ§ÃŖo", @@ -1564,8 +1594,9 @@ "rating_description": "Mostrar a classificaÃ§ÃŖo EXIF no painel de informaçÃĩes", "reaction_options": "OpçÃĩes de reaÃ§ÃŖo", "read_changelog": "Ler Novidades", - "readonly_mode_disabled": "Modo somente leitura desactivado", - "readonly_mode_enabled": "Modo somente leitura activado", + "readonly_mode_disabled": "Modo sÃŗ de leitura desativado", + "readonly_mode_enabled": "Modo sÃŗ de leitura ativado", + "ready_for_upload": "Pronto para upload", "reassign": "Reatribuir", "reassigned_assets_to_existing_person": "Reatribuir {count, plural, one {# ficheiro} other {# ficheiros}} para {name, select, null {uma pessoa existente} other {{name}}}", "reassigned_assets_to_new_person": "Reatribuído {count, plural, one {# ficheiro} other {# ficheiros}} a uma nova pessoa", @@ -1590,6 +1621,7 @@ "regenerating_thumbnails": "A atualizar miniaturas", "remote": "Remoto", "remote_assets": "Ficheiros Remotos", + "remote_media_summary": "SumÃĄrio de Ficheiros Remotos", "remove": "Remover", "remove_assets_album_confirmation": "Tem a certeza de que deseja remover {count, plural, one {# ficheiro} other {# ficheiros}} do ÃĄlbum?", "remove_assets_shared_link_confirmation": "Tem certeza de que deseja remover {count, plural, one {# ficheiro} other {# ficheiros}} deste link partilhado?", @@ -1627,9 +1659,9 @@ "reset_password": "Redefinir palavra-passe", "reset_people_visibility": "Redefinir pessoas ocultas", "reset_pin_code": "Repor cÃŗdigo PIN", - "reset_pin_code_description": "Se esqueceu o seu cÃŗdigo PIN, pode entrar em contato com o administrador do servidor para o repor", + "reset_pin_code_description": "Se esqueceu o seu cÃŗdigo PIN, pode entrar em contacto com o administrador do servidor para o repor", "reset_pin_code_success": "CÃŗdigo PIN redefinido com sucesso", - "reset_pin_code_with_password": "Pode sempre repor o seu cÃŗdigo PIN com a sua senha", + "reset_pin_code_with_password": "Pode sempre repor o seu cÃŗdigo PIN com a sua palavra-passe", "reset_sqlite": "Reiniciar Base de Dados SQLite", "reset_sqlite_confirmation": "Tem a certeza de que quer reiniciar a base de dados SQLite? Vai ter de terminar a sessÃŖo e entrar outra vez para sincronizar os dados de novo", "reset_sqlite_success": "Base de dados SQLite reiniciada com sucesso", @@ -1642,9 +1674,10 @@ "restore_user": "Restaurar utilizador", "restored_asset": "Ficheiro restaurado", "resume": "Continuar", + "resume_paused_jobs": "Continuar {count, plural, one {# trabalho em pausa} other {# trabalhos em pausa}}", "retry_upload": "Tentar carregar novamente", "review_duplicates": "Rever itens duplicados", - "review_large_files": "Rever arquivos grandes", + "review_large_files": "Rever ficheiros grandes", "role": "FunÃ§ÃŖo", "role_editor": "Editor", "role_viewer": "Visualizador", @@ -1735,7 +1768,7 @@ "select_user_for_sharing_page_err_album": "Ocorreu um erro ao criar o ÃĄlbum", "selected": "Selecionados", "selected_count": "{count, plural, other {# selecionados}}", - "selected_gps_coordinates": "coordenadas gps seleccionadas", + "selected_gps_coordinates": "Coordenadas GPS selecionadas", "send_message": "Enviar mensagem", "send_welcome_email": "Enviar E-mail de boas vindas", "server_endpoint": "URL do servidor", @@ -1829,7 +1862,7 @@ "shared_link_info_chip_metadata": "EXIF", "shared_link_manage_links": "Gerenciar links compartilhados", "shared_link_options": "OpçÃĩes de link partilhado", - "shared_link_password_description": "Exigir uma senha para aceder a este link partilhado", + "shared_link_password_description": "Exigir uma palavra-passe para aceder a este link partilhado", "shared_links": "Links partilhados", "shared_links_description": "Partilhar fotos e videos com um link", "shared_photos_and_videos_count": "{assetCount, plural, other {# Fotos & videos partilhados.}}", @@ -1846,10 +1879,8 @@ "shift_to_permanent_delete": "Pressione ⇧ para eliminar o ficheiro permanentemente", "show_album_options": "Exibir opçÃĩes do ÃĄlbum", "show_albums": "Mostrar ÃĄlbuns", - "show_all_assets": "Mostrar todos os recursos", "show_all_people": "Mostrar todas as pessoas", "show_and_hide_people": "Mostrar & ocultar pessoas", - "show_assets_without_location": "Mostrar recursos sem localizaÃ§ÃŖo", "show_file_location": "Exibir localizaÃ§ÃŖo do ficheiro", "show_gallery": "Exibir galeria", "show_hidden_people": "Exibir pessoas ocultadas", @@ -1866,6 +1897,7 @@ "show_slideshow_transition": "Mostrar transiçÃĩes no Modo de ApresentaÃ§ÃŖo", "show_supporter_badge": "Emblema de apoiante", "show_supporter_badge_description": "Mostrar um emblema de apoiante", + "show_text_search_menu": "Mostrar menu de pesquisa de texto", "shuffle": "AleatÃŗrio", "sidebar": "Barra lateral", "sidebar_display_description": "Mostrar um link para a vista na barra lateral", @@ -1896,6 +1928,7 @@ "stacktrace": "Stacktrace", "start": "Iniciar", "start_date": "Data de início", + "start_date_before_end_date": "A data de início deve ser anterior à data de fim", "state": "Estado/Distrito", "status": "Estado", "stop_casting": "Parar transmissÃŖo", @@ -1920,6 +1953,8 @@ "sync_albums_manual_subtitle": "Sincronizar todas as fotos e vídeos enviados para o ÃĄlbum de backup selecionado", "sync_local": "SincronizaÃ§ÃŖo Local", "sync_remote": "SincronizaÃ§ÃŖo Remota", + "sync_status": "Estado da sincronizaÃ§ÃŖo", + "sync_status_subtitle": "Ver e gerir o sistema de sincronizaÃ§ÃŖo", "sync_upload_album_setting_subtitle": "Crie e envie suas fotos e vídeos para o ÃĄlbum selecionado no Immich", "tag": "Etiqueta", "tag_assets": "Etiquetar ficheiros", @@ -1979,6 +2014,7 @@ "trash_page_select_assets_btn": "Selecionar arquivos", "trash_page_title": "Reciclagem ({count})", "trashed_items_will_be_permanently_deleted_after": "Os itens da reciclagem sÃŖo eliminados permanentemente apÃŗs {days, plural, one {# dia} other {# dias}}.", + "troubleshoot": "Diagnosticar problemas", "type": "Tipo", "unable_to_change_pin_code": "NÃŖo foi possível alterar o cÃŗdigo PIN", "unable_to_setup_pin_code": "NÃŖo foi possível configurar o cÃŗdigo PIN", @@ -2009,7 +2045,7 @@ "unstacked_assets_count": "Desempilhados {count, plural, one {# ficheiro} other {# ficheiros}}", "untagged": "Marcador removido", "up_next": "A seguir", - "update_location_action_prompt": "Actualize a localizaÃ§ÃŖo de {count} activos seleccionados com:", + "update_location_action_prompt": "Atualize a localizaÃ§ÃŖo de {count} ficheiros selecionados com:", "updated_at": "Atualizado a", "updated_password": "Palavra-passe atualizada", "upload": "Carregar", @@ -2034,7 +2070,6 @@ "use_biometric": "Utilizar dados biomÊtricos", "use_current_connection": "usar conexÃŖo atual", "use_custom_date_range": "Utilizar um intervalo de datas personalizado", - "use_this_location": "Clique para usar a localizaÃ§ÃŖo", "user": "Utilizador", "user_has_been_deleted": "Este utilizador for eliminado.", "user_id": "ID do utilizador", @@ -2077,6 +2112,7 @@ "view_next_asset": "Ver prÃŗximo ficheiro", "view_previous_asset": "Ver ficheiro anterior", "view_qr_code": "Ver cÃŗdigo QR", + "view_similar_photos": "Ver fotos similares", "view_stack": "Ver pilha", "view_user": "Ver utilizador", "viewer_remove_from_stack": "Remover da pilha", @@ -2095,5 +2131,6 @@ "yes": "Sim", "you_dont_have_any_shared_links": "NÃŖo tem links partilhados", "your_wifi_name": "Nome da sua rede Wi-Fi", - "zoom_image": "Ampliar/Reduzir imagem" + "zoom_image": "Ampliar/Reduzir imagem", + "zoom_to_bounds": "Aproximar aos limites" } diff --git a/i18n/pt_BR.json b/i18n/pt_BR.json index 54e6e0212f..5103df2ebc 100644 --- a/i18n/pt_BR.json +++ b/i18n/pt_BR.json @@ -28,10 +28,12 @@ "add_to_album": "Adicionar ao ÃĄlbum", "add_to_album_bottom_sheet_added": "Adicionado ao {album}", "add_to_album_bottom_sheet_already_exists": "JÃĄ existe em {album}", + "add_to_album_bottom_sheet_some_local_assets": "Alguns arquivos / mídias nÃŖo puderam ser adicionados ao ÃĄlbum", "add_to_album_toggle": "Alternar a seleÃ§ÃŖo de {album}", "add_to_albums": "Adicionar aos ÃĄlbuns", "add_to_albums_count": "Adicionar aos ÃĄlbuns ({count})", "add_to_shared_album": "Adicionar ao ÃĄlbum compartilhado", + "add_upload_to_stack": "Adicionar upload ao grupo", "add_url": "Adicionar URL", "added_to_archive": "Adicionado ao arquivo", "added_to_favorites": "Adicionado aos favoritos", @@ -123,6 +125,13 @@ "logging_enable_description": "Habilitar logs", "logging_level_description": "Quando ativado, qual nível de log usar.", "logging_settings": "Logs", + "machine_learning_availability_checks": "VerficaçÃĩes de disponibilidade", + "machine_learning_availability_checks_description": "Automaticamente detectar e preferir servidores de machine learning disponíveis", + "machine_learning_availability_checks_enabled": "Habilitar verificaçÃĩes de disponibilidade", + "machine_learning_availability_checks_interval": "Intervalo de verificaÃ§ÃŖo", + "machine_learning_availability_checks_interval_description": "Intervalo em milisegundos entre verificaçÃĩes de disponibilidade", + "machine_learning_availability_checks_timeout": "Tempo limite da solicitaÃ§ÃŖo", + "machine_learning_availability_checks_timeout_description": "Tempo limite em milisegundos para verificaçÃĩes de disponibilidade", "machine_learning_clip_model": "Modelo CLIP", "machine_learning_clip_model_description": "O nome de um modelo CLIP listado aqui. Lembre-se de executar novamente a tarefa de 'Pesquisa Inteligente' para todas as imagens apÃŗs alterar o modelo.", "machine_learning_duplicate_detection": "DetecÃ§ÃŖo de duplicidade", @@ -387,8 +396,6 @@ "admin_password": "Senha do administrador", "administration": "AdministraÃ§ÃŖo", "advanced": "Avançado", - "advanced_settings_beta_timeline_subtitle": "Teste a nova interface do aplicativo", - "advanced_settings_beta_timeline_title": "Linha do tempo Beta", "advanced_settings_enable_alternate_media_filter_subtitle": "Use esta opÃ§ÃŖo para filtrar mídias durante a sincronizaÃ§ÃŖo com base em critÊrios alternativos. Tente esta opÃ§ÃŖo somente se o aplicativo estiver com problemas para detectar todos os ÃĄlbuns.", "advanced_settings_enable_alternate_media_filter_title": "[EXPERIMENTAL] Utilizar filtro alternativo de sincronizaÃ§ÃŖo de ÃĄlbum de dispositivo", "advanced_settings_log_level_title": "Nível de log: {level}", @@ -425,6 +432,7 @@ "album_remove_user_confirmation": "Tem certeza de que deseja remover {user}?", "album_search_not_found": "NÃŖo hÃĄ ÃĄlbum que corresponda à sua pesquisa", "album_share_no_users": "Parece que vocÃĒ jÃĄ compartilhou este ÃĄlbum com todos os usuÃĄrios ou nÃŖo hÃĄ nenhum usuÃĄrio para compartilhar.", + "album_summary": "Resumo do ÃĄlbum", "album_updated": "Álbum atualizado", "album_updated_setting_description": "Receba uma notificaÃ§ÃŖo por e-mail quando um ÃĄlbum compartilhado tiver novos recursos", "album_user_left": "Saiu do ÃĄlbum {album}", @@ -496,6 +504,8 @@ "asset_restored_successfully": "Arquivo restaurado", "asset_skipped": "Ignorado", "asset_skipped_in_trash": "Na lixeira", + "asset_trashed": "Arquivo enviado para a lixeira", + "asset_troubleshoot": "DiagnÃŗstico do arquivo", "asset_uploaded": "Enviado", "asset_uploading": "Enviandoâ€Ļ", "asset_viewer_settings_subtitle": "Gerenciar as configuraçÃĩes do visualizador da galeria", @@ -529,8 +539,10 @@ "autoplay_slideshow": "ApresentaÃ§ÃŖo de slides automÃĄtica", "back": "Voltar", "back_close_deselect": "Voltar, fechar ou desmarcar", + "background_backup_running_error": "NÃŖo Ê possível iniciar o backup manual agora pois o backup em segundo plano jÃĄ estÃĄ sendo executado", "background_location_permission": "PermissÃŖo de localizaÃ§ÃŖo em segundo plano", "background_location_permission_content": "Para que seja possível trocar o endereço quando estiver executando em segundo plano, o Immich deve *sempre* ter a permissÃŖo de localizaÃ§ÃŖo precisa para que o aplicativo consiga ler o nome da rede Wi-Fi", + "background_options": "OpçÃĩes de Plano de Fundo", "backup": "Backup", "backup_album_selection_page_albums_device": "Álbuns no dispositivo ({count})", "backup_album_selection_page_albums_tap": "Toque para incluir, toque duas vezes para excluir", @@ -538,6 +550,7 @@ "backup_album_selection_page_select_albums": "Selecionar ÃĄlbuns", "backup_album_selection_page_selection_info": "InformaçÃĩes da SeleÃ§ÃŖo", "backup_album_selection_page_total_assets": "Total de recursos exclusivos", + "backup_albums_sync": "Backup de sincronizaÃ§ÃŖo de ÃĄlbuns", "backup_all": "Todos", "backup_background_service_backup_failed_message": "Falha ao fazer backup. Tentando novamenteâ€Ļ", "backup_background_service_connection_failed_message": "Falha na conexÃŖo com o servidor. Tentando novamenteâ€Ļ", @@ -587,6 +600,7 @@ "backup_controller_page_turn_on": "Ativar backup automÃĄtico", "backup_controller_page_uploading_file_info": "InformaçÃĩes do arquivo", "backup_err_only_album": "NÃŖo Ê possível remover o Ãēnico ÃĄlbum", + "backup_error_sync_failed": "A sincronizaÃ§ÃŖo falhou. NÃŖo foi possível processar o backup.", "backup_info_card_assets": "arquivos", "backup_manual_cancelled": "Cancelado", "backup_manual_in_progress": "Envio jÃĄ estÃĄ em progresso. Tente novamente mais tarde", @@ -597,8 +611,6 @@ "backup_setting_subtitle": "Gerenciar as configuraçÃĩes de envio em primeiro e segundo plano", "backup_settings_subtitle": "Gerenciar configuraçÃĩes de envio", "backward": "Para trÃĄs", - "beta_sync": "Status da sincronizaÃ§ÃŖo Beta", - "beta_sync_subtitle": "Configurar o novo sistema de sincronizaÃ§ÃŖo", "biometric_auth_enabled": "AutenticaÃ§ÃŖo por biometria ativada", "biometric_locked_out": "Sua autenticaÃ§ÃŖo por biometria estÃĄ bloqueada", "biometric_no_options": "NÃŖo hÃĄ opçÃĩes de biometria disponíveis", @@ -656,6 +668,8 @@ "change_pin_code": "Alterar cÃŗdigo PIN", "change_your_password": "Alterar sua senha", "changed_visibility_successfully": "Visibilidade alterada com sucesso", + "charging": "Carregando", + "charging_requirement_mobile_backup": "Backups em plano de fundo requerem que o dispositivo esteja sendo carregado", "check_corrupt_asset_backup": "Verifique se hÃĄ backups corrompidos", "check_corrupt_asset_backup_button": "Verificar", "check_corrupt_asset_backup_description": "Execute esta verificaÃ§ÃŖo somente em uma rede Wi-Fi e quando o backup de todos os arquivos jÃĄ estiver concluído. O processo demora alguns minutos.", @@ -742,6 +756,7 @@ "create_user": "Criar usuÃĄrio", "created": "Criado", "created_at": "Criado em", + "creating_linked_albums": "Criando ÃĄlbuns relacionados...", "crop": "Cortar", "curated_object_page_title": "Objetos", "current_device": "Dispositivo atual", @@ -770,7 +785,7 @@ "default_locale": "LocalizaÃ§ÃŖo PadrÃŖo", "default_locale_description": "Formatar datas e nÃēmeros baseados na linguagem do seu navegador", "delete": "Excluir", - "delete_action_confirmation_message": "Confirma deletar este arquivo? O arquivo serÃĄ enviado para a lixeira do servidor e depois perguntarÃĄ se deseja deletar do seu dispositivo local", + "delete_action_confirmation_message": "Tem certeza? O arquivo serÃĄ enviado para a lixeira do servidor, depois vocÃĒ poderÃĄ confirmar se deseja tambÊm deletar do seu dispositivo local", "delete_action_prompt": "{count} deletados", "delete_album": "Excluir ÃĄlbum", "delete_api_key_prompt": "Tem certeza de que deseja excluir esta chave de API?", @@ -891,7 +906,9 @@ "error": "Erro", "error_change_sort_album": "Falha ao alterar a ordem de exibiÃ§ÃŖo", "error_delete_face": "Erro ao remover face do arquivo", + "error_getting_places": "Erro ao buscar os locais", "error_loading_image": "Erro ao carregar a pÃĄgina", + "error_loading_partners": "Erro ao carregar parceiros: {error}", "error_saving_image": "Erro: {error}", "error_tag_face_bounding_box": "Erro ao marcar o rosto - nÃŖo foi possível localizar o rosto", "error_title": "Erro - Algo deu errado", @@ -1056,6 +1073,7 @@ "favorites_page_no_favorites": "Nenhuma mídia favorita encontrada", "feature_photo_updated": "Foto principal atualizada", "features": "Funcionalidades", + "features_in_development": "FunçÃĩes em desenvolvimento", "features_setting_description": "Gerenciar as funcionalidades da aplicaÃ§ÃŖo", "file_name": "Nome do arquivo", "file_name_or_extension": "Nome do arquivo ou extensÃŖo", @@ -1076,10 +1094,7 @@ "gcast_enabled": "Google Cast", "gcast_enabled_description": "Esta funcionalidade carrega recursos externos do Google para funcionar.", "general": "Geral", - "geolocation_instruction_all_have_location": "Todos arquivos nesta data jÃĄ possuem dados de localizaÃ§ÃŖo. Tente exibir todos os arquivos ou selecione uma data diferente", "geolocation_instruction_location": "Selecione um arquivo com as coordenadas de GPS desejada, ou selecione a localizaÃ§ÃŖo diretamente no mapa", - "geolocation_instruction_no_date": "Selecione uma data para gerenciar os dados de localizaÃ§ÃŖo das fotos e vídeos daquele dia", - "geolocation_instruction_no_photos": "Nenhuma foto ou vídeo encontrado nesta data. Selecione uma data diferente para ser exibida", "get_help": "Obter Ajuda", "get_wifiname_error": "NÃŖo foi possível obter o nome do Wi-Fi. Verifique se concedeu as permissÃĩes necessÃĄrias e se estÃĄ conectado a uma rede Wi-Fi", "getting_started": "Primeiros passos", @@ -1223,6 +1238,7 @@ "local": "Local", "local_asset_cast_failed": "NÃŖo Ê possível transmitir um arquivo que nÃŖo foi enviado ao servidor", "local_assets": "Arquivos no dispositivo", + "local_media_summary": "Resumo das mídias locais", "local_network": "Rede local", "local_network_sheet_info": "O aplicativo irÃĄ se conectar ao servidor atravÊs deste endereço quando estiver na rede Wi-Fi especificada", "location_permission": "PermissÃŖo de localizaÃ§ÃŖo", @@ -1234,6 +1250,7 @@ "location_picker_longitude_hint": "Digite a longitude", "lock": "Trancar", "locked_folder": "Pasta com senha", + "log_detail_title": "Detalhes do Log", "log_out": "Sair", "log_out_all_devices": "Sair de todos dispositivos", "logged_in_as": "UsuÃĄrio atual: {user}", @@ -1264,6 +1281,7 @@ "login_password_changed_success": "Senha atualizada com sucesso", "logout_all_device_confirmation": "Tem certeza de que deseja sair de todos os dispositivos?", "logout_this_device_confirmation": "Tem certeza de que deseja sair deste dispositivo?", + "logs": "Logs", "longitude": "Longitude", "look": "Estilo", "loop_videos": "Repetir vídeos", @@ -1306,6 +1324,7 @@ "mark_as_read": "Marcar como lido", "marked_all_as_read": "Tudo marcado como lido", "matches": "CorrespondÃĒncias", + "matching_assets": "Arquivos encontrados", "media_type": "Tipo de mídia", "memories": "MemÃŗrias", "memories_all_caught_up": "Finalizamos por hoje", @@ -1346,6 +1365,7 @@ "name_or_nickname": "Nome ou apelido", "network_requirement_photos_upload": "Use a rede mÃŗvel para enviar fotos", "network_requirement_videos_upload": "Use a rede mÃŗvel para enviar vídeos", + "network_requirements": "Requerimentos de Rede", "network_requirements_updated": "Requerimentos de rede alterados, reiniciando a fila de envio", "networking_settings": "ConexÃĩes", "networking_subtitle": "Gerencie as conexÃĩes ao servidor", @@ -1356,6 +1376,7 @@ "new_person": "Nova Pessoa", "new_pin_code": "Novo cÃŗdigo PIN", "new_pin_code_subtitle": "Esta Ê a primeira vez que estÃĄ acessando a pasta com senha. Crie um cÃŗdigo PIN para acessar esta pÃĄgina de forma segura", + "new_timeline": "Nova Linha do Tempo", "new_user_created": "Novo usuÃĄrio criado", "new_version_available": "NOVA VERSÃO DISPONÍVEL", "newest_first": "Mais recente primeiro", @@ -1369,20 +1390,25 @@ "no_assets_message": "CLIQUE PARA ENVIAR SUA PRIMEIRA FOTO", "no_assets_to_show": "NÃŖo hÃĄ arquivos para exibir", "no_cast_devices_found": "Nenhum dispositivo encontrado", + "no_checksum_local": "Nenhum checksum disponível - nÃŖo foi possível carregar os arquivos locais", + "no_checksum_remote": "Nenhum checksum disponível - nÃŖo foi possível carregar os arquivos remotos", "no_duplicates_found": "Nenhuma duplicidade foi encontrada.", "no_exif_info_available": "Sem informaçÃĩes exif disponíveis", "no_explore_results_message": "Envie mais fotos para explorar sua coleÃ§ÃŖo.", "no_favorites_message": "Adicione aos favoritos para encontrar suas melhores fotos e vídeos rapidamente", "no_libraries_message": "Crie uma biblioteca externa para ver suas fotos e vídeos", + "no_local_assets_found": "Nenhum arquivo local foi encontrado com este checksum", "no_locked_photos_message": "Fotos e vídeos na pasta com senha sÃŖo ocultos e nÃŖo serÃŖo exibidos enquanto explora ou pesquisa na biblioteca.", "no_name": "Sem Nome", "no_notifications": "Nenhuma notificaÃ§ÃŖo", "no_people_found": "Nenhuma pessoa encontrada", "no_places": "Sem lugares", + "no_remote_assets_found": "Nenhum arquivo remoto foi encontrado com este checksum", "no_results": "Sem resultados", "no_results_description": "Tente um sinônimo ou uma palavra-chave mais geral", "no_shared_albums_message": "Crie um ÃĄlbum para compartilhar fotos e vídeos com pessoas em sua rede", "no_uploads_in_progress": "Nenhum envio em progresso", + "not_available": "N/A", "not_in_any_album": "Fora de ÃĄlbum", "not_selected": "NÃŖo selecionado", "note_apply_storage_label_to_previously_uploaded assets": "Nota: Para aplicar o rÃŗtulo de armazenamento a arquivos enviados anteriormente, execute o", @@ -1417,6 +1443,8 @@ "open_the_search_filters": "Abre os filtros de pesquisa", "options": "OpçÃĩes", "or": "ou", + "organize_into_albums": "Organizar em ÃĄlbuns", + "organize_into_albums_description": "Colocar imagens existentes em ÃĄlbuns usando as configuraçÃĩes de sincronizaÃ§ÃŖo atuais", "organize_your_library": "Organize sua biblioteca", "original": "original", "other": "Outro", @@ -1502,6 +1530,7 @@ "port": "Porta", "preferences_settings_subtitle": "Gerenciar as preferÃĒncias do aplicativo", "preferences_settings_title": "PreferÃĒncias", + "preparing": "Preparando", "preset": "PredefiniÃ§ÃŖo", "preview": "PrÊ-visualizar", "previous": "Anterior", @@ -1518,7 +1547,7 @@ "profile_drawer_client_out_of_date_minor": "O aplicativo estÃĄ desatualizado. Por favor, atualize para a versÃŖo mais recente.", "profile_drawer_client_server_up_to_date": "Cliente e Servidor estÃŖo atualizados", "profile_drawer_github": "GitHub", - "profile_drawer_readonly_mode": "Modo apenas visualizaÃ§ÃŖo ativado. Toque duas vezes na foto do usuÃĄrio para sair deste modo.", + "profile_drawer_readonly_mode": "Modo apenas leitura habilidato. DÃĒ um toque prolongado na foto do usuÃĄrio para sair deste modo.", "profile_drawer_server_out_of_date_major": "O servidor estÃĄ desatualizado. Atualize para a versÃŖo principal mais recente.", "profile_drawer_server_out_of_date_minor": "O servidor estÃĄ desatualizado. Atualize para a versÃŖo mais recente.", "profile_image_of_user": "Imagem do perfil de {user}", @@ -1557,6 +1586,7 @@ "purchase_server_description_2": "Status de Contribuidor", "purchase_server_title": "Servidor", "purchase_settings_server_activated": "A chave do produto para servidor Ê gerenciada pelo administrador", + "query_asset_id": "Consultar ID do Ativo", "queue_status": "Na fila {count} de {total}", "rating": "Estrelas", "rating_clear": "Limpar classificaÃ§ÃŖo", @@ -1566,6 +1596,7 @@ "read_changelog": "Ler Novidades", "readonly_mode_disabled": "Modo apenas visualizaÃ§ÃŖo desativado", "readonly_mode_enabled": "Modo apenas visualizaÃ§ÃŖo ativado", + "ready_for_upload": "Pronto para upload", "reassign": "Reatribuir", "reassigned_assets_to_existing_person": "{count, plural, one {# arquivo reatribuído} other {# arquivos reatribuídos}} a {name, select, null {uma pessoa} other {{name}}}", "reassigned_assets_to_new_person": "{count, plural, one {# arquivo reatribuído} other {# arquivos reatribuídos}} a uma nova pessoa", @@ -1590,6 +1621,7 @@ "regenerating_thumbnails": "Regenerando miniaturas", "remote": "Remoto", "remote_assets": "Arquivos Remotos", + "remote_media_summary": "Resumo das mídias remotas", "remove": "Remover", "remove_assets_album_confirmation": "Tem certeza de que deseja remover {count, plural, one {# arquivo} other {# arquivos}} do ÃĄlbum?", "remove_assets_shared_link_confirmation": "Tem certeza de que deseja remover {count, plural, one {# arquivo} other {# arquivos}} desse link compartilhado?", @@ -1642,6 +1674,7 @@ "restore_user": "Restaurar usuÃĄrio", "restored_asset": "Arquivo restaurado", "resume": "Continuar", + "resume_paused_jobs": "Retomar {count, plural, one {# paused job} other {# paused jobs}}", "retry_upload": "Tentar enviar novamente", "review_duplicates": "Revisar duplicidade", "review_large_files": "Ver arquivos grandes", @@ -1735,7 +1768,7 @@ "select_user_for_sharing_page_err_album": "Falha ao criar ÃĄlbum", "selected": "Selecionados", "selected_count": "{count, plural, one {# selecionado} other {# selecionados}}", - "selected_gps_coordinates": "selecione as coordenadas de GPS", + "selected_gps_coordinates": "Coordenadas de GPS Selecionada", "send_message": "Enviar mensagem", "send_welcome_email": "Enviar E-mail de boas vindas", "server_endpoint": "URL do servidor", @@ -1846,10 +1879,8 @@ "shift_to_permanent_delete": "pressione ⇧ para excluir permanentemente o arquivo", "show_album_options": "Exibir opçÃĩes do ÃĄlbum", "show_albums": "Exibir ÃĄlbuns", - "show_all_assets": "Ver todos arquivos", "show_all_people": "Mostrar todas as pessoas", "show_and_hide_people": "Mostrar & ocultar pessoas", - "show_assets_without_location": "Ver arquivos sem localizaÃ§ÃŖo", "show_file_location": "Exibir local do arquivo", "show_gallery": "Exibir galeria", "show_hidden_people": "Exibir pessoas ocultadas", @@ -1866,6 +1897,7 @@ "show_slideshow_transition": "Usar transiçÃĩes no modo de apresentaÃ§ÃŖo", "show_supporter_badge": "Insígnia de apoiador", "show_supporter_badge_description": "Mostrar uma insígnia de apoiador", + "show_text_search_menu": "Mostrar menu de pesquisa por texto", "shuffle": "AleatÃŗrio", "sidebar": "Barra lateral", "sidebar_display_description": "Exibir um link para a visualizaÃ§ÃŖo na barra lateral", @@ -1896,6 +1928,7 @@ "stacktrace": "Stacktrace", "start": "Início", "start_date": "Data inicial", + "start_date_before_end_date": "A data de início deve ser antes da data final", "state": "Estado", "status": "Status", "stop_casting": "Parar transmissÃŖo", @@ -1920,6 +1953,8 @@ "sync_albums_manual_subtitle": "Sincronize todos as fotos e vídeos enviados para os ÃĄlbuns de backup selecionados", "sync_local": "SincronizaÃ§ÃŖo Local", "sync_remote": "SincronizaÃ§ÃŖo Remota", + "sync_status": "Status da SincronizaÃ§ÃŖo", + "sync_status_subtitle": "Ver e gerenciar o sistema de sincronizaÃ§ÃŖo", "sync_upload_album_setting_subtitle": "Crie e envie suas fotos e vídeos para o ÃĄlbum selecionado no Immich", "tag": "Marcador", "tag_assets": "Marcar arquivos", @@ -1979,6 +2014,7 @@ "trash_page_select_assets_btn": "Selecionar arquivos", "trash_page_title": "Lixeira ({count})", "trashed_items_will_be_permanently_deleted_after": "Os itens da lixeira serÃŖo deletados permanentemente apÃŗs {days, plural, one {# dia} other {# dias}}.", + "troubleshoot": "Diagnosticar", "type": "Tipo", "unable_to_change_pin_code": "NÃŖo foi possível alterar o cÃŗdigo PIN", "unable_to_setup_pin_code": "NÃŖo foi possível criar o cÃŗdigo PIN", @@ -2004,7 +2040,7 @@ "unselect_all": "Desselecionar todos", "unselect_all_duplicates": "Desselecionar todas as duplicatas", "unselect_all_in": "Remover seleÃ§ÃŖo de {group}", - "unstack": "Retirar do grupo", + "unstack": "Desagrupar", "unstack_action_prompt": "{count} desagrupados", "unstacked_assets_count": "{count, plural, one {# arquivo retirado} other {# arquivos retirados}} do grupo", "untagged": "Marcador removido", @@ -2034,7 +2070,6 @@ "use_biometric": "Usar biometria", "use_current_connection": "usar conexÃŖo atual", "use_custom_date_range": "Usar intervalo de datas personalizado", - "use_this_location": "Clique para marcar o local", "user": "UsuÃĄrio", "user_has_been_deleted": "Este usuÃĄrio foi excluído.", "user_id": "ID do usuÃĄrio", @@ -2077,6 +2112,7 @@ "view_next_asset": "Ver prÃŗximo arquivo", "view_previous_asset": "Ver arquivo anterior", "view_qr_code": "Ver QR Code", + "view_similar_photos": "Ver fotos similares", "view_stack": "Ver grupo", "view_user": "Visualizar usuÃĄrio", "viewer_remove_from_stack": "Remover do grupo", @@ -2095,5 +2131,6 @@ "yes": "Sim", "you_dont_have_any_shared_links": "NÃŖo hÃĄ links compartilhados", "your_wifi_name": "Nome do seu Wi-Fi", - "zoom_image": "Ampliar imagem" + "zoom_image": "Ampliar imagem", + "zoom_to_bounds": "Ampliar para preencher" } diff --git a/i18n/ro.json b/i18n/ro.json index 6218a0dff7..ffa7d6f6f0 100644 --- a/i18n/ro.json +++ b/i18n/ro.json @@ -1,12 +1,12 @@ { "about": "Despre", "account": "Cont", - "account_settings": "Setări Cont", + "account_settings": "Setări cont", "acknowledge": "Văzut", "action": "AcÅŖiune", "action_common_update": "Actualizează", "actions": "AcÅŖiuni", - "active": "Activ", + "active": "Active", "activity": "Activitate", "activity_changed": "Activitatea este {enabled, select, true {activată} other {dezactivată}}", "add": "Adaugă", @@ -28,6 +28,7 @@ "add_to_album": "Adaugă ÃŽn album", "add_to_album_bottom_sheet_added": "Adăugat ÃŽn {album}", "add_to_album_bottom_sheet_already_exists": "Deja ÃŽn {album}", + "add_to_album_bottom_sheet_some_local_assets": "Unele resurse locale nu au putut fi adăugate la album", "add_to_album_toggle": "Selectează/deselectează {album}", "add_to_albums": "Adaugă la albume", "add_to_albums_count": "Adaugă la albume ({count})", @@ -40,12 +41,12 @@ "add_exclusion_pattern_description": "Adăugați modele de excludere. Globing folosind *, ** și ? este suportat. Pentru a ignora toate fișierele din orice director numit „Raw”, utilizați „**/Raw/**”. Pentru a ignora toate fișierele care se termină ÃŽn „.tif”, utilizați „**/*.tif”. Pentru a ignora o cale absolută, utilizați „/path/to/ignore/**”.", "admin_user": "Utilizator admin", "asset_offline_description": "Acest material din biblioteca externă nu se mai găsește pe disc și a fost mutat ÃŽn coșul de gunoi. Dacă fișierul a fost mutat ÃŽn bibliotecă, verificați cronologia pentru noul material corespunzător. Pentru a restabili acest material, asigurați-vă că calea fișierului de mai jos poate fi accesată de Immich și scanați biblioteca.", - "authentication_settings": "Setări de Autentificare", + "authentication_settings": "Setări de autentificare", "authentication_settings_description": "Gestionează parola, OAuth și alte setări de autentificare", "authentication_settings_disable_all": "Ești sigur că vrei sa dezactivezi toate metodele de autentificare? Autentificarea va fi complet dezactivată.", "authentication_settings_reenable": "Pentru a reactiva, folosește Comandă Server.", "background_task_job": "Activități de Fundal", - "backup_database": "Salvare Bază de Date", + "backup_database": "Salvare bază de date", "backup_database_enable_description": "Activare salvarea bazei de date", "backup_keep_last_amount": "Număr de copii de rezervă anterioare de păstrat", "backup_onboarding_1_description": "copie externă ÃŽn cloud sau ÃŽntr-o altă locație fizică.", @@ -72,9 +73,9 @@ "disable_login": "Dezactivați autentificarea", "duplicate_detection_job_description": "Rulați ÃŽnvățarea automată pe materiale pentru a detecta imagini similare. Se bazează pe Căutare Inteligentă", "exclusion_pattern_description": "Modelele de excludere vă permit să ignorați fișierele și folderele atunci cÃĸnd vă scanați biblioteca. Acest lucru este util dacă aveți foldere care conțin fișiere pe care nu doriți să le importați, cum ar fi fișierele RAW.", - "external_library_management": "Managementul Bibliotecii Externe", + "external_library_management": "Gestionarea bibliotecilor externe", "face_detection": "Detecție facială", - "face_detection_description": "Detectează fețele din fișiere folosind ÃŽnvățare automată. Pentru videoclipuri, este luată ÃŽn considerare doar miniatura. „ReÃŽnprospătează” (re)procesează toate fișierele. „Resetează” adaugă ÃŽn coadă fișierele care nu au fost ÃŽncă procesate. Fețele detectate vor fi puse ÃŽn coadă pentru recunoașterea facială după finalizarea detectării feței, grupÃĸndu-le ÃŽn persoane existente sau noi.", + "face_detection_description": "Detectează fețele din fișiere folosind ÃŽnvățare automată. Pentru videoclipuri, este luată ÃŽn considerare doar miniatura. „ReÃŽmprospătează” (re)procesează toate fișierele. „Resetează” adaugă ÃŽn coadă fișierele care nu au fost ÃŽncă procesate. Fețele detectate vor fi puse ÃŽn coadă pentru recunoașterea facială după finalizarea detectării feței, grupÃĸndu-le ÃŽn persoane existente sau noi.", "facial_recognition_job_description": "Grupați fețele detectate ÃŽn persoane. Acest pas rulează după ce Detectarea Feței este finalizată. „Resetează” (re)grupează toate fețele. „Lipsă” adaugă ÃŽn coadă fețe care nu au o persoană desemnată.", "failed_job_command": "Comanda {command} a eșuat pentru jobul: {job}", "force_delete_user_warning": "AVERTISMENT: Acest lucru va elimina imediat utilizatorul și toate activele sale. Acest lucru nu poate fi anulat și fișierele nu pot fi recuperate.", @@ -91,30 +92,30 @@ "image_prefer_wide_gamut_setting_description": "Utilizați Display P3 pentru miniaturi. Acest lucru păstrează mai bine vibrația imaginilor cu spații de culoare largi, dar imaginile pot apărea diferit pe dispozitivele cu o versiune mai veche de browser. Imaginile sRGB sunt păstrate ca sRGB pentru a evita schimbările de culoare.", "image_preview_description": "Imagine de dimensiune medie cu metadate eliminate, utilizată la vizualizarea unui singur element și pentru ÃŽnvățarea automată", "image_preview_quality_description": "Calitatea previzualizării de la 1 la 100. O valoare mai mare oferă o calitate mai bună, dar produce fișiere mai mari și poate reduce receptivitatea aplicației. Setarea unei valori scăzute poate afecta calitatea ÃŽnvățării automate.", - "image_preview_title": "Previzualizați Setările", + "image_preview_title": "Previzualizați setările", "image_quality": "Calitate", "image_resolution": "Rezolutie", "image_resolution_description": "Rezoluțiile mai mari pot păstra mai multe detalii, dar necesită mai mult timp pentru a fi codificate, au dimensiuni mai mari ale fișierelor și pot reduce răspunsul aplicației.", - "image_settings": "Setări Imagine", + "image_settings": "Setări imagine", "image_settings_description": "Gestionează calitatea și rezoluția imaginilor generate", "image_thumbnail_description": "Miniatură mică cu metadate eliminate, utilizată la vizualizarea grupurilor de fotografii, cum ar fi ÃŽn cronologia principală", "image_thumbnail_quality_description": "Calitatea miniaturii de la 1 la 100. O valoare mai mare oferă o calitate mai bună, dar produce fișiere mai mari și poate reduce receptivitatea aplicației.", - "image_thumbnail_title": "Setari Miniaturi", + "image_thumbnail_title": "Setari miniaturi", "job_concurrency": "Concurență {job}", "job_created": "Sarcină creată", "job_not_concurrency_safe": "Această sarcină nu este sigură pentru a rula ÃŽn concurență.", - "job_settings": "Setări Sarcină", + "job_settings": "Setări sarcină", "job_settings_description": "Administrează concurența sarcinilor", - "job_status": "Starea Sarcinii", + "job_status": "Starea sarcinii", "jobs_delayed": "{jobCount, plural, other {# ÃŽntÃĸrziat}}", "jobs_failed": "{jobCount, plural, other {# eșuat}}", - "library_created": "Librărie creată:{library}", + "library_created": "Librărie creată: {library}", "library_deleted": "Bibliotecă ștearsă", "library_import_path_description": "Specificați un folder pentru a ÃŽl importa. Acest folder, inclusiv sub-folderele, vor fi scanate pentru imagini și videoclipuri.", - "library_scanning": "Scanare Periodică", + "library_scanning": "Scanare periodică", "library_scanning_description": "Configurează scanarea periodică pentru bibliotecă", "library_scanning_enable_description": "Activează scanarea periodică pentru bibliotecă", - "library_settings": "Bibliotecă Externă", + "library_settings": "Bibliotecă externă", "library_settings_description": "Administrează setările pentru biblioteci externe", "library_tasks_description": "Scanează bibliotecile externe de active noi sau modificate", "library_watching_enable_description": "Urmărește bibliotecile externe pentru schimbări ale fișierelor", @@ -123,9 +124,16 @@ "logging_enable_description": "Activează ÃŽnregistrarea log-urilor", "logging_level_description": "Dacă setarea este activată, ÃŽnregistrează evenimentele cu nivelul de utilizat.", "logging_settings": "Înregistrare", + "machine_learning_availability_checks": "Verificări disponibilitate", + "machine_learning_availability_checks_description": "Detectează automat si preferă serverele cu ÃŽnvațare automată", + "machine_learning_availability_checks_enabled": "Activează verificare disponibilitate", + "machine_learning_availability_checks_interval": "Interval verificare", + "machine_learning_availability_checks_interval_description": "Interval in milisecunde ÃŽntre verificările de disponibilitate", + "machine_learning_availability_checks_timeout": "Timp de expirare cerere", + "machine_learning_availability_checks_timeout_description": "Timp de așteptare ÃŽn milisecunde pentru verificările de disponibilitate", "machine_learning_clip_model": "Model CLIP", "machine_learning_clip_model_description": "Numele unui model CLIP listat aici. Rețineți că trebuie să rulați din nou funcția „Smart Search” pentru toate imaginile la schimbarea unui model.", - "machine_learning_duplicate_detection": "Detectare Duplicate", + "machine_learning_duplicate_detection": "Detectare duplicate", "machine_learning_duplicate_detection_enabled": "Activează detectarea duplicatelor", "machine_learning_duplicate_detection_enabled_description": "Dacă este dezactivată, elementele identice vor fi ÃŽn continuare de-duplicate.", "machine_learning_duplicate_detection_setting_description": "Utilizați ÃŽncorporările CLIP pentru a găsi dubluri probabile", @@ -152,11 +160,11 @@ "machine_learning_smart_search_enabled": "Activați căutarea inteligentă", "machine_learning_smart_search_enabled_description": "Dacă este dezactivată, imaginile nu vor fi codificate pentru căutarea inteligentă.", "machine_learning_url_description": "URL-ul serverului de ÃŽnvățare automată. Dacă sunt furnizate mai multe URL-uri, fiecare server va fi ÃŽncercat pe rÃĸnd, pÃĸnă cÃĸnd unul răspunde cu succes, ÃŽn ordine de la primul pÃĸnă la ultimul. Serverele care nu răspund vor fi ignorate temporar pÃĸnă revin online.", - "manage_concurrency": "Gestionarea Simultaneității", + "manage_concurrency": "Gestionarea simultaneității", "manage_log_settings": "Administrați setările jurnalului", "map_dark_style": "Mod ÃŽntunecat", "map_enable_description": "Activați funcțiile hărții", - "map_gps_settings": "Setări Hartă & GPS", + "map_gps_settings": "Setări hartă & GPS", "map_gps_settings_description": "Gestionare setări Hartă & GPS (localizare inversă)", "map_implications": "Caracteristica hărții se bazează pe un serviciu extern de planșe (tiles.immich.cloud)", "map_light_style": "Mod deschis", @@ -173,7 +181,7 @@ "metadata_extraction_job_description": "Extragere informații metadate din fiecare fișier cum ar fi localizare GPS, fețe și rezoluție,", "metadata_faces_import_setting": "Activare import fețe", "metadata_faces_import_setting_description": "Importă fețe din datele EXIF ale imaginii și din fișiere tip \"sidecar\"", - "metadata_settings": "Setări Metadate", + "metadata_settings": "Setări metadate", "metadata_settings_description": "Gestionează setările pentru metadate", "migration_job": "Migrare", "migration_job_description": "Migrați miniaturile pentru elemente și fețe la cea mai recentă structură de foldere", @@ -251,7 +259,7 @@ "send_welcome_email": "Trimite email de bun-venit", "server_external_domain_settings": "Domeniu extern", "server_external_domain_settings_description": "Domeniu pentru distribuire publicĮŽ a scurtĮŽturilor, incluzÃĸnd http(s)://", - "server_public_users": "Utilizatori Publici", + "server_public_users": "Utilizatori publici", "server_public_users_description": "Toți utilizatorii (nume și e-mail) sunt listați atunci cÃĸnd adăugați un utilizator la albumele partajate. CÃĸnd este dezactivată, lista de utilizatori va fi disponibilă numai pentru utilizatorii admin.", "server_settings": "SetĮŽri Server", "server_settings_description": "GestioneazĮŽ setĮŽrile serverului", @@ -273,7 +281,7 @@ "storage_template_more_details": "Pentru mai multe detalii despre aceasta caracteristică, accesați Șablon stocare si implicațiile", "storage_template_onboarding_description_v2": "CÃĸnd este activată, această funcție va organiza automat fișierele pe baza șablonului definit de către utilizator. Pentru mai multe informații, accesează documentația.", "storage_template_path_length": "Limita de lungime pentru calea aproximativă: {length, number}/{limit, number}", - "storage_template_settings": "Șablon Stocare", + "storage_template_settings": "Șablon stocare", "storage_template_settings_description": "Gestionează structura folderelor și numele fișierelor pentru elementele ÃŽncărcate", "storage_template_user_label": "{label} este eticheta de stocare a utilizatorului", "system_settings": "SetĮŽri de Sistem", @@ -289,9 +297,9 @@ "template_settings_description": "Gestionați șabloanele personalizate pentru notificări", "theme_custom_css_settings": "CSS personalizat", "theme_custom_css_settings_description": "Foile de stil ÃŽn cascadă (CSS) permit personalizarea designului Immich.", - "theme_settings": "Setări Temă", + "theme_settings": "Setări temă", "theme_settings_description": "Gestionează personalizarea interfeței web Immich", - "thumbnail_generation_job": "Generare Miniaturi", + "thumbnail_generation_job": "Generare miniaturi", "thumbnail_generation_job_description": "Generează miniaturi mari, mici și estompate pentru fiecare resursă, precum și miniaturi pentru fiecare persoană", "transcoding_acceleration_api": "API de accelerare", "transcoding_acceleration_api_description": "API-ul care va interacționa cu dispozitivul tău pentru a accelera transcodarea. Această setare este 'cel mai bun efort': va reveni la transcodarea software ÃŽn caz de eșec. VP9 poate funcționa sau nu, ÃŽn funcție de hardware-ul tău.", @@ -317,7 +325,7 @@ "transcoding_disabled_description": "Nu transcodifică niciun videoclip; acest lucru poate afecta redarea pe anumite dispozitive", "transcoding_encoding_options": "Opțiuni codificare", "transcoding_encoding_options_description": "Setează codecuri , calitatea, rezoluția și alte opțiuni pentru videoclipuri codificare", - "transcoding_hardware_acceleration": "Accelerare Hardware", + "transcoding_hardware_acceleration": "Accelerare hardware", "transcoding_hardware_acceleration_description": "Experimental: transcodare mai rapidă, dar poate reduce calitatea la aceeași rată de biți", "transcoding_hardware_decoding": "Decodare hardware", "transcoding_hardware_decoding_setting_description": "Se aplică doar pentru NVENC, QSV și RKMPP. Activează accelerarea completă ÃŽn loc de doar accelerarea codificării. S-ar putea să nu funcționeze pentru toate videoclipurile.", @@ -337,7 +345,7 @@ "transcoding_reference_frames": "Cadre de referință", "transcoding_reference_frames_description": "Numărul de cadre de referință atunci cÃĸnd se comprimă un cadru dat. Valorile mai mari ÃŽmbunătățesc eficiența compresiei, dar ÃŽncetinesc codarea. 0 setează această valoare automat.", "transcoding_required_description": "Numai videoclipuri care nu sunt ÃŽntr-un format acceptat", - "transcoding_settings": "Setări de Transcodare Video", + "transcoding_settings": "Setări de transcodare video", "transcoding_settings_description": "Gestionează care videoclipuri să transcodam și cum să le procesam", "transcoding_target_resolution": "Rezoluția țintă", "transcoding_target_resolution_description": "Rezoluțiile mai mari pot păstra mai multe detalii, dar necesită mai mult timp pentru codare, au dimensiuni mai mari ale fișierelor și pot reduce răspunsul aplicației.", @@ -368,27 +376,25 @@ "user_delete_immediately": "Contul și resursele utilizatorului {user} vor fi puse ÃŽn coadă pentru ștergere permanentă imediat.", "user_delete_immediately_checkbox": "Pune utilizatorul și resursele ÃŽn coadă pentru ștergere imediată", "user_details": "Detalii utilizator", - "user_management": "Gestionarea Utilizatorilor", + "user_management": "Gestionarea utilizatorilor", "user_password_has_been_reset": "Parola utilizatorului a fost resetată:", "user_password_reset_description": "Vă rugăm să furnizați utilizatorului parola temporară și să ÃŽi informați că va trebui să o schimbe la următoarea autentificare.", "user_restore_description": "Contul utilizatorului {user} va fi restaurat.", "user_restore_scheduled_removal": "Restaurare utilizator - ștergere programată pe {date, date, long}", - "user_settings": "SetĮŽri Utilizator", + "user_settings": "SetĮŽri utilizator", "user_settings_description": "GestioneazĮŽ setĮŽrile utilizatorului", "user_successfully_removed": "Utilizatorul {email} a fost eliminat cu succes.", "version_check_enabled_description": "Activează verificarea versiunii", "version_check_implications": "Funcția de verificare a versiunii se bazează pe comunicarea periodică cu github.com", - "version_check_settings": "Verificare Versiune", + "version_check_settings": "Verificare versiune", "version_check_settings_description": "ActiveazĮŽ/dezactiveazĮŽ notificarea unei noi versiuni", "video_conversion_job": "Transcodați videoclipuri", "video_conversion_job_description": "Transcodați videoclipurile pentru o compatibilitate mai mare cu browserele și dispozitivele" }, - "admin_email": "E-mail Administrator", - "admin_password": "Parolă Administrator", + "admin_email": "E-mail administrator", + "admin_password": "Parolă administrator", "administration": "Administrare", "advanced": "Avansat", - "advanced_settings_beta_timeline_subtitle": "Încearcă noua experiență ÃŽn aplicație", - "advanced_settings_beta_timeline_title": "Cronologie beta", "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: {level}", @@ -396,7 +402,7 @@ "advanced_settings_prefer_remote_title": "Preferă fotografii la distanță", "advanced_settings_proxy_headers_subtitle": "Definește antetele proxy pe care Immich ar trebui să le trimită cu fiecare solicitare de rețea", "advanced_settings_proxy_headers_title": "Antete Proxy", - "advanced_settings_readonly_mode_subtitle": "Activează modul doar-citire, ÃŽn care fotografiile pot fi doar vizualizate, iar acțiuni precum selectarea mai multor imagini, partajarea, redarea pe alt dispozitiv sau ștergerea sunt dezactivate. Activează/Dezactivează modul doar-citire din avatarul utilizatorului de pe ecranul principal.", + "advanced_settings_readonly_mode_subtitle": "Activează modul doar-citire, ÃŽn care fotografiile pot fi doar vizualizate, iar acțiuni precum selectarea mai multor imagini, partajarea, redarea pe alt dispozitiv sau ștergerea sunt dezactivate. Activează/Dezactivează modul doar-citire din avatarul utilizatorului de pe ecranul principal", "advanced_settings_readonly_mode_title": "Mod doar-citire", "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", @@ -425,6 +431,7 @@ "album_remove_user_confirmation": "Ești sigur că dorești eliminarea {user}?", "album_search_not_found": "Nu s-au găsit albume care să corespundă căutării dumneavoastră", "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_summary": "Rezumat album", "album_updated": "Album actualizat", "album_updated_setting_description": "Primiți o notificare prin e-mail cÃĸnd un album partajat are elemente noi", "album_user_left": "A părăsit {album}", @@ -461,7 +468,7 @@ "app_bar_signout_dialog_content": "Ești sigur că vrei să te deconectezi?", "app_bar_signout_dialog_ok": "Da", "app_bar_signout_dialog_title": "Deconectare", - "app_settings": "Setări Aplicație", + "app_settings": "Setări aplicație", "appears_in": "Apare ÃŽn", "apply_count": "Aplică ({count, number})", "archive": "Arhivă", @@ -472,7 +479,7 @@ "archive_size": "Mărime arhivă", "archive_size_description": "Configurează dimensiunea arhivei pentru descărcări (ÃŽn GiB)", "archived": "Arhivat", - "archived_count": "{count, plural, other {Arhivat/e#}}", + "archived_count": "{count, plural, one {Arhivat} few {# arhivate} other {# arhivate}}", "are_these_the_same_person": "Sunt aceștia aceeași persoană?", "are_you_sure_to_do_this": "Sunteți sigur că doriți să faceți acest lucru?", "asset_action_delete_err_read_only": "Fișierele cu permisiuni doar de citire nu au putut fi șterse, omitere", @@ -482,7 +489,7 @@ "asset_description_updated": "Descrierea resursei a fost actualizată", "asset_filename_is_offline": "Resursa {filename} este offline", "asset_has_unassigned_faces": "Resursa are fețe neatribuite", - "asset_hashing": "Calculare amprentă digitală", + "asset_hashing": "Calculare amprentă digitalăâ€Ļ", "asset_list_group_by_sub_title": "Grupare după", "asset_list_layout_settings_dynamic_layout_title": "Aspect dinamic", "asset_list_layout_settings_group_automatically": "Automat", @@ -496,6 +503,8 @@ "asset_restored_successfully": "Date restaurate cu succes", "asset_skipped": "Sărit", "asset_skipped_in_trash": "În coșul de gunoi", + "asset_trashed": "Resursă ștearsă", + "asset_troubleshoot": "Depanare resursă", "asset_uploaded": "Încărcat", "asset_uploading": "Se incarcăâ€Ļ", "asset_viewer_settings_subtitle": "Gestionați setările de vizualizare a galeriei", @@ -522,14 +531,17 @@ "assets_trashed_count": "Mutat ÃŽn coșul de gunoi {count, plural, one {# resursă} other {# resurse}}", "assets_trashed_from_server": "{count} resursă(e) eliminate de pe serverul Immich", "assets_were_part_of_album_count": "{count, plural, one {Resursa era} other {Resursele erau}} deja parte din album", + "assets_were_part_of_albums_count": "{count, plural, one {Asset was} other {Assets were}} deja parte din albume", "authorized_devices": "Dispozitive Autorizate", "automatic_endpoint_switching_subtitle": "Conectează-te local prin rețeaua Wi‐Fi configurată cÃĸnd este valabilă și prin rețele alternative ÃŽn caz contrar", "automatic_endpoint_switching_title": "Alternare URL automată", "autoplay_slideshow": "Derulare slideshow automat", "back": "Înapoi", "back_close_deselect": "Înapoi, ÃŽnchidere sau deselectare", + "background_backup_running_error": "Procesul de backup ÃŽn fundal este activ, nu se poate porni backup manual", "background_location_permission": "Permisiune locație ÃŽn fundal", "background_location_permission_content": "Pentru a putea schimba rețeaua activă ÃŽn fundal, Immich are nevoie de acces *permanent* la locația precisă pentru a citi numele rețelei Wi-Fi", + "background_options": "Opțiuni de fundal", "backup": "Backup", "backup_album_selection_page_albums_device": "Albume ÃŽn dispozitiv ({count})", "backup_album_selection_page_albums_tap": "Apasă odata pentru a include, de două ori pentru a exclude", @@ -537,6 +549,7 @@ "backup_album_selection_page_select_albums": "Selectează albume", "backup_album_selection_page_selection_info": "Informații selecție", "backup_album_selection_page_total_assets": "Total resurse unice", + "backup_albums_sync": "Sincronizarea albumelor de backup", "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â€Ļ", @@ -576,7 +589,7 @@ "backup_controller_page_remainder": "Rămas(e)", "backup_controller_page_remainder_sub": "Fotografii și videoclipuri din selecție rămase pentru backup", "backup_controller_page_server_storage": "Stocare server", - "backup_controller_page_start_backup": "Începe backup", + "backup_controller_page_start_backup": "Începe copia de rezervă", "backup_controller_page_status_off": "Backup-ul automat ÃŽn prim-plan este oprit", "backup_controller_page_status_on": "Backup-ul automat ÃŽn prim-plan este pornit", "backup_controller_page_storage_format": "{used} din {total} folosit", @@ -586,17 +599,17 @@ "backup_controller_page_turn_on": "Activează backup-ul ÃŽn prim-plan", "backup_controller_page_uploading_file_info": "Informații ÃŽncărcare fișier", "backup_err_only_album": "Nu poți șterge singurul album", + "backup_error_sync_failed": "Sincronizarea a eșuat. Nu se poate procesa copia de rezervă.", "backup_info_card_assets": "resurse", "backup_manual_cancelled": "Anulat", "backup_manual_in_progress": "Încărcarea este deja ÃŽn curs. Încearcă din nou mai tÃĸrziu", "backup_manual_success": "Succes", "backup_manual_title": "Status ÃŽncărcare", - "backup_options_page_title": "Opțiuni Backup", + "backup_options": "Opțiuni copie de rezervă", + "backup_options_page_title": "Opțiuni copie de rezervă", "backup_setting_subtitle": "Schimbă opțiuni pentru backup ÃŽn prim-plan și ÃŽn fundal", "backup_settings_subtitle": "Gestionați setările de ÃŽncărcare", "backward": "În sens invers", - "beta_sync": "Starea sincronizării Beta", - "beta_sync_subtitle": "Gestionați noul sistem de sincronizare", "biometric_auth_enabled": "Autentificare biometrică activată", "biometric_locked_out": "Sunteți blocați de la autentificare biometrică", "biometric_no_options": "Nu sunt disponibile opțiuni biometrice", @@ -604,7 +617,7 @@ "birthdate_saved": "Data nașterii salvată cu succes", "birthdate_set_description": "Data nașterii este utilizată pentru a calcula vÃĸrsta acestei persoane la momentul realizării fotografiei.", "blurred_background": "Fundal neclar", - "bugs_and_feature_requests": "Erori și Solicitări de Caracteristici", + "bugs_and_feature_requests": "Erori și solicitări de caracteristici", "build": "Versiunea", "build_image": "Versiune Imagine", "bulk_delete_duplicates_confirmation": "Ești sigur că vrei să ștergi ÃŽn masă {count, plural, one {# resursă duplicată} other {# resurse duplicate}}? Aceasta va păstra cea mai mare resursă din fiecare grup și va șterge permanent toate celelalte duplicate. Nu poți anula această acțiune!", @@ -654,6 +667,8 @@ "change_pin_code": "Schimbă codul PIN", "change_your_password": "Schimbă-ți parola", "changed_visibility_successfully": "Schimbare vizibilitate cu succes", + "charging": "Încărcare", + "charging_requirement_mobile_backup": "Pentru copia de rezervă ÃŽn fundal, dispozitivul trebuie să fie ÃŽn curs de ÃŽncărcare", "check_corrupt_asset_backup": "Verifică copii de rezervă a resurselor corupte", "check_corrupt_asset_backup_button": "Efectuează verificarea", "check_corrupt_asset_backup_description": "Rulează această verificare doar prin Wi-Fi și doar după ce toate resursele au fost salvate ÃŽn copia de rezerva. Procedura poate dura cÃĸteva minute.", @@ -705,7 +720,7 @@ "control_bottom_app_bar_delete_from_immich": "Șterge din Immich", "control_bottom_app_bar_delete_from_local": "Șterge din dispozitiv", "control_bottom_app_bar_edit_location": "Editează locație", - "control_bottom_app_bar_edit_time": "Editează Data și Ora", + "control_bottom_app_bar_edit_time": "Editează data și ora", "control_bottom_app_bar_share_link": "Partajează linkul", "control_bottom_app_bar_share_to": "Distribuire către", "control_bottom_app_bar_trash_from_immich": "Mută ÃŽn coș", @@ -740,6 +755,7 @@ "create_user": "Creează utilizator", "created": "Creat", "created_at": "Creat", + "creating_linked_albums": "Crearea albumelor cu link...", "crop": "Decupează", "curated_object_page_title": "Obiecte", "current_device": "Dispozitiv curent", @@ -759,6 +775,7 @@ "date_of_birth_saved": "Data nașterii salvată cu succes", "date_range": "Interval de date", "day": "Zi", + "days": "Zile", "deduplicate_all": "Deduplicați Toate", "deduplication_criteria_1": "Marimea imagini ÃŽn octeți", "deduplication_criteria_2": "Numărul de date EXIF", @@ -843,10 +860,12 @@ "edit": "Editare", "edit_album": "Editare album", "edit_avatar": "Editare avatar", - "edit_birthday": "Editează ziua de naștere", + "edit_birthday": "Modifică ziua de naștere", "edit_date": "Editare dată", "edit_date_and_time": "Editare dată și oră", "edit_date_and_time_action_prompt": "{count} data și ora modificării", + "edit_date_and_time_by_offset": "Schimbă data prin decalaj", + "edit_date_and_time_by_offset_interval": "Noul interval de date: {from} - {to}", "edit_description": "Editează descrierea", "edit_description_prompt": "Vă rugăm să selectați o descriere nouă:", "edit_exclusion_pattern": "Editarea modelului de excludere", @@ -856,7 +875,7 @@ "edit_key": "Tastă de editare", "edit_link": "Editare link", "edit_location": "Editare locație", - "edit_location_action_prompt": "{count} locație(i) editată(e)", + "edit_location_action_prompt": "{count} locație(i) modificată(e)", "edit_location_dialog_title": "Locație", "edit_name": "Editare nume", "edit_people": "Editare persoane", @@ -886,7 +905,9 @@ "error": "Eroare", "error_change_sort_album": "Nu s-a putut modifica ordinea de sortare a albumului", "error_delete_face": "Eroare la ștergerea feței din activ", + "error_getting_places": "Eroare la obținerea locațiilor", "error_loading_image": "Eroare la ÃŽncărcarea imaginii", + "error_loading_partners": "Eroare la ÃŽncărcarea partenerilor: {error}", "error_saving_image": "Eroare: {error}", "error_tag_face_bounding_box": "Eroare la etichetarea feței - nu se pot obține coordonatele casetei de delimitare", "error_title": "Eroare - ceva nu a mers", @@ -919,6 +940,7 @@ "failed_to_load_notifications": "Nu s-au putut ÃŽncărca notificările", "failed_to_load_people": "Eșec la ÃŽncărcarea persoanelor", "failed_to_remove_product_key": "Eșec la eliminarea cheii de produs", + "failed_to_reset_pin_code": "Nu s-a reușit resetarea codului PIN", "failed_to_stack_assets": "Eșec la combinarea resurselor", "failed_to_unstack_assets": "Eșec la desfășurarea resurselor", "failed_to_update_notification_status": "Nu s-a putut actualiza starea notificării", @@ -927,6 +949,7 @@ "paths_validation_failed": "{paths, plural, one {# cale} other {# căi}} nu a trecut validarea", "profile_picture_transparent_pixels": "Pozele de profil nu pot avea pixeli transparenți. Te rugăm să mărești imaginea și/sau să o muți.", "quota_higher_than_disk_size": "Ați stabilit o valoare a spațiului de stocare mai mare decÃĸt dimensiunea discului", + "something_went_wrong": "Ceva nu a mers bine", "unable_to_add_album_users": "Imposibil de adăugat utilizatori ÃŽn album", "unable_to_add_assets_to_shared_link": "Imposibil de adăugat resurse la link-ul partajat", "unable_to_add_comment": "Imposibil de adăugat comentariu", @@ -1034,7 +1057,7 @@ "export_database_description": "Exportați baza de date SQLite", "extension": "Extensie", "external": "Extern", - "external_libraries": "Biblioteci Externe", + "external_libraries": "Biblioteci externe", "external_network": "Rețea externă", "external_network_sheet_info": "CÃĸnd nu se află ÃŽn rețeaua Wi-Fi preferată, aplicația se va conecta la server prin prima dintre adresele URL de mai jos pe care o poate accesa, ÃŽncepÃĸnd de sus ÃŽn jos", "face_unassigned": "Nealocat", @@ -1049,6 +1072,7 @@ "favorites_page_no_favorites": "Nu au fost găsite resurse favorite", "feature_photo_updated": "Fotografie caracteristică actualizată", "features": "Caracteristici", + "features_in_development": "Funcții ÃŽn dezvoltare", "features_setting_description": "Gestionați funcțiile aplicației", "file_name": "Nume de fișier", "file_name_or_extension": "Numele sau extensia fișierului", @@ -1058,21 +1082,26 @@ "filter_people": "Filtrați persoanele", "filter_places": "Filtrează locurile", "find_them_fast": "Găsiți-le rapid prin căutare după nume", + "first": "Primul", "fix_incorrect_match": "Remediați potrivirea incorectă", "folder": "Dosar", "folder_not_found": "Dosar negăsit", - "folders": "Foldere", + "folders": "Fișiere", "folders_feature_description": "Răsfoire ÃŽn conținutul folderului pentru fotografiile și videoclipurile din sistemul de fișiere", + "forgot_pin_code_question": "Ai uitat codul PIN?", "forward": "Redirecționare", "gcast_enabled": "Google Cast", "gcast_enabled_description": "Această funcție ÃŽncarcă resurse externe de la Google pentru a funcționa.", "general": "General", + "geolocation_instruction_location": "Apasă pe o resursă cu coordonate GPS pentru a folosi locația sa, sau selectează direct o locație de pe hartă", "get_help": "Obțineți Ajutor", "get_wifiname_error": "Nu s-a putut obține numele rețelei Wi-Fi. Asigurați-vă că ați acordat permisiunile necesare și că sunteți conectat la o rețea Wi-Fi", "getting_started": "Noțiuni de Bază", "go_back": "Întoarcere", "go_to_folder": "Accesați folderul", "go_to_search": "Spre căutare", + "gps": "GPS", + "gps_missing": "Fără GPS", "grant_permission": "Acordați permisiunea", "group_albums_by": "Grupați albume de...", "group_country": "Grupare după țară", @@ -1083,6 +1112,9 @@ "haptic_feedback_switch": "Activează feedback-ul haptic", "haptic_feedback_title": "Feedback haptic", "has_quota": "Are spațiu de stocare", + "hash_asset": "Hash-ul resursei", + "hashed_assets": "Resurse hashed", + "hashing": "Generare hash", "header_settings_add_header_tip": "Adăugați antet", "header_settings_field_validator_msg": "Valoarea nu poate fi goală", "header_settings_header_name_input": "Numele antetului", @@ -1109,11 +1141,12 @@ "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_locked_error_local": "Nu se pot muta resursele locale ÃŽn folderul blocat, se omit", - "home_page_locked_error_partner": "Nu se pot muta materialele partenerului ÃŽn folderul blocat, se omit.", + "home_page_locked_error_partner": "Nu se pot muta resursele partenerului ÃŽn folderul blocat, se omit.", "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ă", "hour": "Oră", + "hours": "Ore", "id": "ID", "idle": "Inactiv", "ignore_icloud_photos": "Ignoră fotografiile din iCloud", @@ -1173,10 +1206,13 @@ "language_no_results_title": "Nu au fost găsite limbi", "language_search_hint": "Căutați limbi...", "language_setting_description": "Selectați limba preferată", + "large_files": "Fișiere mari", + "last": "Ultimul", "last_seen": "Văzut ultima dată", "latest_version": "Ultima Versiune", "latitude": "Latitudine", "leave": "Părăsiți", + "leave_album": "Părăsește albumul", "lens_model": "Model obiectiv", "let_others_respond": "Permite altora să răspundă", "level": "Nivel", @@ -1190,6 +1226,7 @@ "library_page_sort_title": "Titlu album", "licenses": "Licențe", "light": "Lumină", + "like": "Îmi place", "like_deleted": "Preferat șters", "link_motion_video": "Link video ÃŽn mișcare", "link_to_oauth": "Link către OAuth", @@ -1200,6 +1237,7 @@ "local": "Local", "local_asset_cast_failed": "Nu se poate converti un element care nu este ÃŽncărcat pe server", "local_assets": "Asset-uri locale", + "local_media_summary": "Rezumatul fișierelor media locale", "local_network": "Rețea locală", "local_network_sheet_info": "Aplicația se va conecta la server prin intermediul acestei adrese URL atunci cÃĸnd utilizează rețeaua Wi-Fi specificată", "location_permission": "Permisiunea de locație", @@ -1211,6 +1249,7 @@ "location_picker_longitude_hint": "Introdu longitudinea aici", "lock": "Blocare", "locked_folder": "Dosar blocat", + "log_detail_title": "Detalii jurnal", "log_out": "Deconectare", "log_out_all_devices": "Deconectați-vă de la toate dispozitivele", "logged_in_as": "Conectat ca {user}", @@ -1241,13 +1280,15 @@ "login_password_changed_success": "Parola a fost actualizată cu succes", "logout_all_device_confirmation": "Sigur doriți să deconectați toate dispozitivele?", "logout_this_device_confirmation": "Sigur doriți să deconectați acest dispozitiv?", + "logs": "Jurnale", "longitude": "Longitudine", "look": "Examinare", "loop_videos": "Buclă videoclipuri", "loop_videos_description": "Activați pentru a rula in buclă automat un videoclip ÃŽn vizualizatorul de detalii.", "main_branch_warning": "Utilizați o versiune de dezvoltare; vă recomandăm insistent să utilizați o versiune de lansare!", "main_menu": "Meniu principal", - "make": "Face", + "make": "Marcă", + "manage_geolocation": "Gestionați locația", "manage_shared_links": "Administrați link-urile distribuite", "manage_sharing_with_partners": "Gestionați partajarea cu partenerii", "manage_the_app_settings": "Gestionați setările aplicației", @@ -1256,7 +1297,7 @@ "manage_your_devices": "Gestionați-vă dispozitivele conectate", "manage_your_oauth_connection": "Gestionați-vă conexiunea OAuth", "map": "Hartă", - "map_assets_in_bounds": "{count, plural, one {# poză} other {# poze}}", + "map_assets_in_bounds": "{count, plural, =0 {Nu există fotografii ÃŽn această zonă} one {# fotografie} other {# fotografii}}", "map_cannot_get_user_location": "Nu se poate obține locația utilizatorului", "map_location_dialog_yes": "Da", "map_location_picker_page_use_location": "Folosește această locație", @@ -1282,6 +1323,7 @@ "mark_as_read": "Marchează ca citit", "marked_all_as_read": "Marcate toate ca citite", "matches": "Corespunde", + "matching_assets": "Resurse similare", "media_type": "Tip media", "memories": "Amintiri", "memories_all_caught_up": "Sunteți la zi", @@ -1299,7 +1341,8 @@ "merge_people_successfully": "Persoane ÃŽmbinate cu succes", "merged_people_count": "Imbinate {count, plural, one {# persoană} other {# persoane}}", "minimize": "Minimizare", - "minute": "Minute", + "minute": "Minut", + "minutes": "Minute", "missing": "Lipsă", "model": "Model", "month": "Lună", @@ -1319,6 +1362,10 @@ "my_albums": "Albumele mele", "name": "Nume", "name_or_nickname": "Nume sau poreclĮŽ", + "network_requirement_photos_upload": "Utilizați datele mobile pentru a face copii de rezervă ale fotografiilor", + "network_requirement_videos_upload": "Utilizați datele mobile pentru a face copii de rezervă ale videoclipurilor", + "network_requirements": "Cerințe privind rețeaua", + "network_requirements_updated": "Cerințele rețelei s-au modificat, resetarea cozii copiei de rezervă", "networking_settings": "Rețele", "networking_subtitle": "Gestionați setările endpoint-ului serverului", "never": "Niciodată", @@ -1328,6 +1375,7 @@ "new_person": "PersoanĮŽ nouĮŽ", "new_pin_code": "Cod PIN nou", "new_pin_code_subtitle": "Aceasta este prima dată cÃĸnd accesați folderul blocat. Creați un cod PIN pentru a accesa ÃŽn siguranță această pagină", + "new_timeline": "Noua cronologie", "new_user_created": "Utilizator nou creat", "new_version_available": "VERSIUNE NOUĂ DISPONIBILĂ", "newest_first": "Cel mai nou primul", @@ -1341,20 +1389,25 @@ "no_assets_message": "CLICK PENTRU A ÎNCĂRCA PRIMA TA FOTOGRAFIE", "no_assets_to_show": "Nicio resursă de afișat", "no_cast_devices_found": "Nu s-au găsit dispozitive de difuzare", + "no_checksum_local": "Nu există checksum – nu se pot prelua resursele locale", + "no_checksum_remote": "Nu există checksum – nu se pot prelua resursele la distanță", "no_duplicates_found": "Nu au fost găsite duplicate.", "no_exif_info_available": "Nu există informații exif disponibile", "no_explore_results_message": "Încarcați mai multe fotografii pentru a vă explora colecția.", "no_favorites_message": "Adăugați favorite pentru a găsi rapid cele mai bune fotografii și videoclipuri", "no_libraries_message": "Creați o bibliotecă externă pentru a vă vizualiza fotografiile și videoclipurile", + "no_local_assets_found": "Nicio resursă locală găsită cu acest checksum", "no_locked_photos_message": "Fotografiile și videoclipurile din folderul blocat sunt ascunse și nu vor apărea atunci cÃĸnd răsfoiți sau căutați ÃŽn bibliotecă.", "no_name": "Fără Nume", "no_notifications": "Nicio notificare", "no_people_found": "Nu au fost găsite persoane potrivite căutării", "no_places": "Nu există locuri", + "no_remote_assets_found": "Nicio resursă de la distanță găsită cu acest checksum", "no_results": "Fără rezultate", "no_results_description": "Încercați un sinonim sau un cuvÃĸnt cheie mai general", "no_shared_albums_message": "Creați un album pentru a partaja fotografii și videoclipuri cu persoanele din rețeaua dvs", "no_uploads_in_progress": "Nicio ÃŽncărcare ÃŽn curs", + "not_available": "N/A", "not_in_any_album": "Nu există ÃŽn niciun album", "not_selected": "Neselectat", "note_apply_storage_label_to_previously_uploaded assets": "Notă: Pentru a aplica eticheta de stocare la resursele ÃŽncărcate anterior, rulați", @@ -1370,6 +1423,7 @@ "oauth": "OAuth", "official_immich_resources": "Resurse Oficiale Immich", "offline": "Offline", + "offset": "Decalaj", "ok": "Bine", "oldest_first": "Cel mai vechi mai ÃŽntÃĸi", "on_this_device": "Pe acest dispozitiv", @@ -1388,6 +1442,8 @@ "open_the_search_filters": "Deschideți filtrele de căutare", "options": "Opțiuni", "or": "sau", + "organize_into_albums": "Organizați ÃŽn albume", + "organize_into_albums_description": "Pune fotografiile existente ÃŽn albume folosind setările curente de sincronizare", "organize_your_library": "Organizează-ți biblioteca", "original": "original", "other": "Alte", @@ -1447,6 +1503,9 @@ "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ĮŽ", + "person_age_months": "{months, plural, one {# lună} other {# luni}}", + "person_age_year_months": "1 an, {months, plural, one {# lună} other {# luni}}", + "person_age_years": "{years, plural, other {# years}} vechime", "person_birthdate": "Născut pe {date}", "person_hidden": "{name}{hidden, select, true { (ascuns)} other {}}", "photo_shared_all_users": "Se pare că ți-ai partajat fotografiile tuturor utilizatorilor sau că nu ai niciun utilizator căruia să le distribui.", @@ -1470,6 +1529,7 @@ "port": "Port", "preferences_settings_subtitle": "Gestionați preferințele aplicației", "preferences_settings_title": "Preferințe", + "preparing": "Se prepară", "preset": "Presetat", "preview": "Previzualizare", "previous": "Anterior", @@ -1486,6 +1546,7 @@ "profile_drawer_client_out_of_date_minor": "Aplicația nu folosește ultima versiune. Te rugăm să actualizezi la ultima versiune minoră.", "profile_drawer_client_server_up_to_date": "Aplicația client și server-ul sunt actualizate", "profile_drawer_github": "GitHub", + "profile_drawer_readonly_mode": "Mod doar citire activat. Ține apăsat pe pictograma avatarului utilizatorului pentru a ieși.", "profile_drawer_server_out_of_date_major": "Server-ul nu folosește ultima versiune. Te rugăm să actualizezi la ultima versiune majoră.", "profile_drawer_server_out_of_date_minor": "Server-ul nu folosește ultima versiune. Te rugăm să actulizezi la ultima versiune minoră.", "profile_image_of_user": "Imagine de profil a lui {user}", @@ -1524,6 +1585,7 @@ "purchase_server_description_2": "Statutul de suporter", "purchase_server_title": "Server", "purchase_settings_server_activated": "Cheia de produs a serverului este gestionată de administrator", + "query_asset_id": "Interoghează ID-ul resursei", "queue_status": "Se pun ÃŽn coadă {count}/{total}", "rating": "Evaluare cu stele", "rating_clear": "Anulați evaluarea", @@ -1531,6 +1593,9 @@ "rating_description": "Afișați evaluarea EXIF ÃŽn panoul de informații", "reaction_options": "Opțiuni de reacție", "read_changelog": "Citiți Jurnalul de Modificări", + "readonly_mode_disabled": "Modul doar citire dezactivat", + "readonly_mode_enabled": "Modul doar citire activat", + "ready_for_upload": "Pregătit pentru ÃŽncărcare", "reassign": "Reatribuiți", "reassigned_assets_to_existing_person": "Re-alocat {count, plural, one {# resursă} other {# resurse}} to {name, select, null {unei persoane existente} other {{name}}}", "reassigned_assets_to_new_person": "Re-alocat {count, plural, one {# resursă} other {# resurse}} unei noi persoane", @@ -1555,6 +1620,7 @@ "regenerating_thumbnails": "Se regenerează miniaturile", "remote": "De la distanță", "remote_assets": "Elemente la distanță", + "remote_media_summary": "Rezumat media de la distanță", "remove": "Eliminați", "remove_assets_album_confirmation": "Sigur doriți să eliminați {count, plural, one {# resursă} other {# resurse}} din album?", "remove_assets_shared_link_confirmation": "Sigur doriți să eliminați {count, plural, one {# resursă} other {# resurse}} din acest link comun?", @@ -1592,6 +1658,9 @@ "reset_password": "Resetare parolă", "reset_people_visibility": "Resetați vizibilitatea persoanelor", "reset_pin_code": "Resetare cod PIN", + "reset_pin_code_description": "Dacă ți-ai uitat codul PIN, poți contacta administratorul serverului pentru a-l reseta", + "reset_pin_code_success": "Codul PIN a fost resetat cu succes", + "reset_pin_code_with_password": "Puteți reseta oricÃĸnd codul PIN cu ajutorul parolei", "reset_sqlite": "Resetare bază de date SQLite", "reset_sqlite_confirmation": "Sigur doriți să resetați baza de date SQLite? Va trebui să vă deconectați și să vă conectați din nou pentru a resincroniza datele", "reset_sqlite_success": "Resetarea cu succes a bazei de date SQLite", @@ -1604,8 +1673,10 @@ "restore_user": "Restabiliți utilizatorul", "restored_asset": "Resursă restaurată", "resume": "Reluare", + "resume_paused_jobs": "Reluați {count, plural, one {# paused job} other {# paused jobs}}", "retry_upload": "ReÃŽncercați ÃŽncărcarea", "review_duplicates": "Examinați duplicatele", + "review_large_files": "Revizuirea fișierelor mari", "role": "Rol", "role_editor": "Editor", "role_viewer": "Vizualizator", @@ -1617,7 +1688,7 @@ "saved_settings": "Setări salvate", "say_something": "Spuneți ceva", "scaffold_body_error_occurred": "A apărut o eroare", - "scan_all_libraries": "Scanați Toate Bibliotecile", + "scan_all_libraries": "Scanați toate bibliotecile", "scan_library": "Scanare", "scan_settings": "Setări Scanare", "scanning_for_album": "Se scanează după album...", @@ -1630,8 +1701,8 @@ "search_by_filename_example": "i.e. IMG_1234.JPG sau PNG", "search_camera_make": "Se caută marca camerei...", "search_camera_model": "Se caută modelul camerei...", - "search_city": "Se caută orașul...", - "search_country": "Se caută țara...", + "search_city": "Caută ÃŽn orașul...", + "search_country": "Caută ÃŽn țara...", "search_filter_apply": "Aplicați filtrul", "search_filter_camera_title": "Selectați tipul de cameră", "search_filter_date": "Dată", @@ -1646,7 +1717,7 @@ "search_filter_media_type_title": "Selectați tipul media", "search_filter_people_title": "Selectați persoane", "search_for": "Căutare după", - "search_for_existing_person": "Se caută o persoană existentă", + "search_for_existing_person": "Caută o persoană existentă", "search_no_more_result": "Nu mai există rezultate", "search_no_people": "Fără persoane", "search_no_people_named": "Nicio persoană numită \"{name}\"", @@ -1668,7 +1739,7 @@ "search_rating": "Caută după notă...", "search_result_page_new_search_hint": "Căutare nouă", "search_settings": "Setări de căutare", - "search_state": "Starea căutării...", + "search_state": "Caută ÃŽn Stat/Județ...", "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...", @@ -1696,6 +1767,7 @@ "select_user_for_sharing_page_err_album": "Creare album eșuată", "selected": "Selectat", "selected_count": "{count, plural, other {# selectat}}", + "selected_gps_coordinates": "Coordonate GPS selectate", "send_message": "Trimiteți mesaj", "send_welcome_email": "Trimiteți email de bun venit", "server_endpoint": "Endpoint server", @@ -1704,7 +1776,7 @@ "server_offline": "Serverul este offline", "server_online": "Server online", "server_privacy": "Confidențialitatea serverului", - "server_stats": "Statistici Server", + "server_stats": "Statistici server", "server_version": "Versiune Server", "set": "Setați", "set_as_album_cover": "Setați ca și copertă a albumului", @@ -1763,6 +1835,7 @@ "shared_link_clipboard_copied_massage": "Copiat ÃŽn clipboard", "shared_link_clipboard_text": "Link: {link}\nParolă: {password}", "shared_link_create_error": "Eroare ÃŽn timpul creării linkului de distribuire", + "shared_link_custom_url_description": "Accesează acest link partajat cu un URL personalizat", "shared_link_edit_description_hint": "Introdu descrierea distribuirii", "shared_link_edit_expire_after_option_day": "1 zi", "shared_link_edit_expire_after_option_days": "{count} zile", @@ -1788,6 +1861,7 @@ "shared_link_info_chip_metadata": "EXIF", "shared_link_manage_links": "Administrează link-urile distribuite", "shared_link_options": "Opțiuni de link partajat", + "shared_link_password_description": "Solicită o parolă pentru a accesa acest link partajat", "shared_links": "Link-uri distribuite", "shared_links_description": "Partajare imagini și clipuri printr-un link", "shared_photos_and_videos_count": "{assetCount, plural, other {# fotografii și videoclipuri partajate.}}", @@ -1822,6 +1896,7 @@ "show_slideshow_transition": "Afișați tranziția de prezentare", "show_supporter_badge": "Insigna suporterului", "show_supporter_badge_description": "Arată o insignă de suporter", + "show_text_search_menu": "Afișează meniul de căutare text", "shuffle": "Amestecați", "sidebar": "Bara laterală", "sidebar_display_description": "Afișați un link către vizualizare ÃŽn bara laterală", @@ -1837,6 +1912,7 @@ "sort_created": "Data creării", "sort_items": "Numărul de articole", "sort_modified": "Data modificării", + "sort_newest": "Cea mai nouă fotografie", "sort_oldest": "Cea mai veche fotografie", "sort_people_by_similarity": "Sortează oameni după asemanare", "sort_recent": "Cea mai recentă fotografie", @@ -1851,7 +1927,8 @@ "stacktrace": "Urmă stivă", "start": "Început", "start_date": "Data de ÃŽncepere", - "state": "SituaÅŖie", + "start_date_before_end_date": "Data de ÃŽnceput trebuie să fie ÃŽnainte de data de sfÃĸrșit", + "state": "Stat/Județ", "status": "Stare", "stop_casting": "Opriți difuzarea", "stop_motion_photo": "Opriți Fotografia in Mișcare", @@ -1875,6 +1952,8 @@ "sync_albums_manual_subtitle": "Sincronizează toate videoclipurile și fotografiile ÃŽncărcate cu albumele de rezervă selectate", "sync_local": "Sincronizare locală", "sync_remote": "Sincronizare la distanță", + "sync_status": "Status-ul sincronizării", + "sync_status_subtitle": "Vizualizează și gestionează sistemul de sincronizare", "sync_upload_album_setting_subtitle": "Creează și ÃŽncarcă fotografiile și videoclipurile tale ÃŽn albumele selectate de pe Immich", "tag": "Etichetă", "tag_assets": "Eticheta resurselor", @@ -1912,7 +1991,9 @@ "to_change_password": "SchimbaÅŖi parola", "to_favorite": "Favorit", "to_login": "Conectare", + "to_multi_select": "pentru selecție multiplă", "to_parent": "Du-te la părinte", + "to_select": "a selecta", "to_trash": "Coș de gunoi", "toggle_settings": "Activați setările", "total": "Total", @@ -1932,6 +2013,7 @@ "trash_page_select_assets_btn": "Selectează resurse", "trash_page_title": "Coș ({count})", "trashed_items_will_be_permanently_deleted_after": "Elementele din coșul de gunoi vor fi șterse definitiv după {days, plural, one {# zi} other {# zile}}.", + "troubleshoot": "Depanați", "type": "Tip", "unable_to_change_pin_code": "Nu se poate schimba codul PIN", "unable_to_setup_pin_code": "Nu se poate configura codul PIN", @@ -1958,10 +2040,11 @@ "unselect_all_duplicates": "Deselectați toate duplicatele", "unselect_all_in": "Deselectați toate din {group}", "unstack": "Dezasamblați", - "unstack_action_prompt": "{count} unstacked", + "unstack_action_prompt": "{count} neÃŽmpachetate", "unstacked_assets_count": "Nestivuit {count, plural, one {# resursă} other {# resurse}}", "untagged": "Neetichetat", "up_next": "Mai departe", + "update_location_action_prompt": "Actualizează locația pentru {count} resurse selectate cu:", "updated_at": "Actualizat", "updated_password": "Parolă actualizată", "upload": "Încărcați", @@ -2028,13 +2111,14 @@ "view_next_asset": "Vizualizați următoarea resursă", "view_previous_asset": "Vizualizați resursa anterioară", "view_qr_code": "Vezi cod QR", + "view_similar_photos": "Vizualizați poze similare", "view_stack": "Vizualizați Stiva", "view_user": "Vizualizare utilizator", "viewer_remove_from_stack": "Șterge din grup", "viewer_stack_use_as_main_asset": "Folosește ca resursă principală", "viewer_unstack": "Anulează grup", "visibility_changed": "Vizibilitatea schimbată pentru {count, plural, one {# persoană} other {# persoane}}", - "waiting": "Așteptați", + "waiting": "În așteptare", "warning": "Avertisment", "week": "SĮŽptĮŽmÃĸnĮŽ", "welcome": "Bun venit", @@ -2046,5 +2130,6 @@ "yes": "Da", "you_dont_have_any_shared_links": "Nu aveți linkuri partajate", "your_wifi_name": "Numele rețelei tale WiFi", - "zoom_image": "Măriți Imaginea" + "zoom_image": "Măriți Imaginea", + "zoom_to_bounds": "Mărește la margini" } diff --git a/i18n/ru.json b/i18n/ru.json index f7f5724e2d..17d6c804a2 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -7,7 +7,7 @@ "action_common_update": "ОбĐŊĐžĐ˛Đ¸Ņ‚ŅŒ", "actions": "ДĐĩĐšŅŅ‚Đ˛Đ¸Ņ", "active": "Đ’Ņ‹ĐŋĐžĐģĐŊŅĐĩŅ‚ŅŅ", - "activity": "АĐēŅ‚Đ¸Đ˛ĐŊĐžŅŅ‚ŅŒ", + "activity": "ДĐĩĐšŅŅ‚Đ˛Đ¸Ņ", "activity_changed": "АĐēŅ‚Đ¸Đ˛ĐŊĐžŅŅ‚ŅŒ {enabled, select, true {вĐēĐģŅŽŅ‡ĐĩĐŊа} other {ĐžŅ‚ĐēĐģŅŽŅ‡ĐĩĐŊа}}", "add": "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ", "add_a_description": "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ ĐžĐŋĐ¸ŅĐ°ĐŊиĐĩ", @@ -26,20 +26,22 @@ "add_tag": "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ Ņ‚ĐĩĐŗ", "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_added": "ДобавĐģĐĩĐŊĐž в аĐģŅŒĐąĐžĐŧ {album}", + "add_to_album_bottom_sheet_already_exists": "ĐŖĐļĐĩ в аĐģŅŒĐąĐžĐŧĐĩ {album}", + "add_to_album_bottom_sheet_some_local_assets": "НĐĩĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ ĐžĐąŅŠĐĩĐē҂ҋ ĐŊĐĩ дОйавĐģĐĩĐŊŅ‹ в аĐģŅŒĐąĐžĐŧ, ĐŋĐžŅĐēĐžĐģҌĐē҃ Đĩ҉Đĩ ĐŊĐĩ ĐˇĐ°ĐŗŅ€ŅƒĐļĐĩĐŊŅ‹ ĐŊа ҁĐĩŅ€Đ˛ĐĩŅ€", "add_to_album_toggle": "ПĐĩŅ€ĐĩĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ Đ˛Ņ‹Đ´ĐĩĐģĐĩĐŊиĐĩ Đ´ĐģŅ аĐģŅŒĐąĐžĐŧа {album}", "add_to_albums": "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ в аĐģŅŒĐąĐžĐŧŅ‹", "add_to_albums_count": "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ в аĐģŅŒĐąĐžĐŧŅ‹ ({count})", "add_to_shared_album": "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ в ĐžĐąŅ‰Đ¸Đš аĐģŅŒĐąĐžĐŧ", + "add_upload_to_stack": "Đ—Đ°ĐŗŅ€ŅƒĐˇĐ¸Ņ‚ŅŒ и Đ´ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ в ĐŗŅ€ŅƒĐŋĐŋ҃", "add_url": "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ URL", "added_to_archive": "ДобавĐģĐĩĐŊĐž в Đ°Ņ€Ņ…Đ¸Đ˛", "added_to_favorites": "ДобавĐģĐĩĐŊĐž в Đ¸ĐˇĐąŅ€Đ°ĐŊĐŊĐžĐĩ", - "added_to_favorites_count": "ДобавĐģĐĩĐŊĐž{count, number} в Đ¸ĐˇĐąŅ€Đ°ĐŊĐŊĐžĐĩ", + "added_to_favorites_count": "{count, plural, one {# ĐžĐąŅŠĐĩĐēŅ‚ дОйавĐģĐĩĐŊ} many {# ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛ дОйавĐģĐĩĐŊĐž} other {# ĐžĐąŅŠĐĩĐēŅ‚Đ° дОйавĐģĐĩĐŊĐž}} в Đ¸ĐˇĐąŅ€Đ°ĐŊĐŊĐžĐĩ", "admin": { "add_exclusion_pattern_description": "Đ”ĐžĐąĐ°Đ˛ŅŒŅ‚Đĩ ŅˆĐ°ĐąĐģĐžĐŊŅ‹ Đ¸ŅĐēĐģŅŽŅ‡ĐĩĐŊиК. ПоддĐĩŅ€ĐļĐ¸Đ˛Đ°ŅŽŅ‚ŅŅ ŅĐ¸ĐŧвОĐģŅ‹ ĐŋĐžĐ´ŅŅ‚Đ°ĐŊОвĐēи *, ** и ?. Đ§Ņ‚ĐžĐąŅ‹ Đ¸ĐŗĐŊĐžŅ€Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ Đ˛ŅĐĩ Ņ„Đ°ĐšĐģŅ‹ в ĐģŅŽĐąĐžĐŧ ĐēĐ°Ņ‚Đ°ĐģĐžĐŗĐĩ ҁ иĐŧĐĩĐŊĐĩĐŧ \"Raw\", ҃ĐēаĐļĐ¸Ņ‚Đĩ \"**/Raw/**\". Đ§Ņ‚ĐžĐąŅ‹ Đ¸ĐŗĐŊĐžŅ€Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ Đ˛ŅĐĩ Ņ„Đ°ĐšĐģŅ‹, СаĐēаĐŊŅ‡Đ¸Đ˛Đ°ŅŽŅ‰Đ¸ĐĩŅŅ ĐŊа \".tif\", Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐšŅ‚Đĩ \"**/*.tif\". Đ§Ņ‚ĐžĐąŅ‹ Đ¸ĐŗĐŊĐžŅ€Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ ĐŋŅƒŅ‚ŅŒ ҆ĐĩĐģиĐēĐžĐŧ, ҃ĐēаĐļĐ¸Ņ‚Đĩ \"/path/to/ignore/**\".", "admin_user": "АдĐŧиĐŊĐ¸ŅŅ‚Ņ€Đ°Ņ‚ĐžŅ€", - "asset_offline_description": "Đ­Ņ‚ĐžŅ‚ Ņ„Đ°ĐšĐģ вĐŊĐĩ҈ĐŊĐĩĐš йийĐģĐ¸ĐžŅ‚ĐĩĐēи ĐŊĐĩ ĐąŅ‹Đģ ĐŊаКдĐĩĐŊ ĐŊа Đ´Đ¸ŅĐēĐĩ и ĐąŅ‹Đģ ĐŋĐĩŅ€ĐĩĐŧĐĩ҉ґĐŊ в ĐēĐžŅ€ĐˇĐ¸ĐŊ҃. Đ•ŅĐģи Ņ„Đ°ĐšĐģ ĐąŅ‹Đģ ĐŋĐĩŅ€ĐĩĐŧĐĩ҉ґĐŊ вĐŊŅƒŅ‚Ņ€Đ¸ йийĐģĐ¸ĐžŅ‚ĐĩĐēи, ĐŋŅ€ĐžĐ˛ĐĩŅ€ŅŒŅ‚Đĩ Đ˛Ņ€ĐĩĐŧĐĩĐŊĐŊŅƒŅŽ ҈ĐēаĐģ҃, Ņ‡Ņ‚ĐžĐąŅ‹ ĐŊĐ°ĐšŅ‚Đ¸ ĐŊĐžĐ˛Ņ‹Đš ŅĐžĐžŅ‚Đ˛ĐĩŅ‚ŅŅ‚Đ˛ŅƒŅŽŅ‰Đ¸Đš Ņ€ĐĩŅŅƒŅ€Ņ. Đ§Ņ‚ĐžĐąŅ‹ Đ˛ĐžŅŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ Ņ„Đ°ĐšĐģ, ŅƒĐąĐĩĐ´Đ¸Ņ‚ĐĩҁҌ, Ņ‡Ņ‚Đž ĐŋŅƒŅ‚ŅŒ ĐŊиĐļĐĩ Đ´ĐžŅŅ‚ŅƒĐŋĐĩĐŊ Đ´ĐģŅ Immich и Đ˛Ņ‹ĐŋĐžĐģĐŊĐ¸Ņ‚Đĩ ҁĐēаĐŊĐ¸Ņ€ĐžĐ˛Đ°ĐŊиĐĩ йийĐģĐ¸ĐžŅ‚ĐĩĐēи.", + "asset_offline_description": "Đ­Ņ‚ĐžŅ‚ ĐžĐąŅŠĐĩĐēŅ‚ иС вĐŊĐĩ҈ĐŊĐĩĐš йийĐģĐ¸ĐžŅ‚ĐĩĐēи ĐŊĐĩ ĐąŅ‹Đģ ОйĐŊĐ°Ņ€ŅƒĐļĐĩĐŊ ĐŊа Đ´Đ¸ŅĐēĐĩ и ĐŋĐžŅŅ‚ĐžĐŧ҃ ĐŋĐĩŅ€ĐĩĐŧĐĩ҉ґĐŊ в ĐēĐžŅ€ĐˇĐ¸ĐŊ҃. Đ•ŅĐģи Ņ„Đ°ĐšĐģ ĐžĐąŅŠĐĩĐēŅ‚Đ° ĐąŅ‹Đģ ĐŋĐĩŅ€ĐĩĐŧĐĩ҉ґĐŊ вĐŊŅƒŅ‚Ņ€Đ¸ йийĐģĐ¸ĐžŅ‚ĐĩĐēи, ĐŋŅ€ĐžĐ˛ĐĩŅ€ŅŒŅ‚Đĩ Đ˛Ņ€ĐĩĐŧĐĩĐŊĐŊŅƒŅŽ ҈ĐēаĐģ҃, Ņ‡Ņ‚ĐžĐąŅ‹ ĐŊĐ°ĐšŅ‚Đ¸ ĐŊĐžĐ˛Ņ‹Đš ŅĐžĐžŅ‚Đ˛ĐĩŅ‚ŅŅ‚Đ˛ŅƒŅŽŅ‰Đ¸Đš ĐžĐąŅŠĐĩĐēŅ‚. Đ§Ņ‚ĐžĐąŅ‹ Đ˛ĐžŅŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ Ņ„Đ°ĐšĐģ, ŅƒĐąĐĩĐ´Đ¸Ņ‚ĐĩҁҌ, Ņ‡Ņ‚Đž ҁĐģĐĩĐ´ŅƒŅŽŅ‰Đ¸Đš ĐŋŅƒŅ‚ŅŒ Đ´ĐžŅŅ‚ŅƒĐŋĐĩĐŊ Đ´ĐģŅ Immich, и Đ˛Ņ‹ĐŋĐžĐģĐŊĐ¸Ņ‚Đĩ ҁĐēаĐŊĐ¸Ņ€ĐžĐ˛Đ°ĐŊиĐĩ йийĐģĐ¸ĐžŅ‚ĐĩĐēи.", "authentication_settings": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи Đ°ŅƒŅ‚ĐĩĐŊŅ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ†Đ¸Đ¸", "authentication_settings_description": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ĐŋĐ°Ņ€ĐžĐģŅĐŧи, OAuth и Đ´Ņ€ŅƒĐŗĐ¸Đŧи ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēаĐŧи Đ°ŅƒŅ‚ĐĩĐŊŅ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ†Đ¸Đ¸", "authentication_settings_disable_all": "Đ’Ņ‹ ŅƒĐ˛ĐĩŅ€ĐĩĐŊŅ‹, Ņ‡Ņ‚Đž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ĐžŅ‚ĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ Đ˛ŅĐĩ ĐŧĐĩŅ‚ĐžĐ´Ņ‹ Đ˛Ņ…ĐžĐ´Đ°? Đ’Ņ…ĐžĐ´ ĐąŅƒĐ´ĐĩŅ‚ ĐŋĐžĐģĐŊĐžŅŅ‚ŅŒŅŽ ĐžŅ‚ĐēĐģŅŽŅ‡ĐĩĐŊ.", @@ -65,9 +67,9 @@ "confirm_reprocess_all_faces": "Đ’Ņ‹ ŅƒĐ˛ĐĩŅ€ĐĩĐŊŅ‹, Ņ‡Ņ‚Đž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ĐŋĐžĐ˛Ņ‚ĐžŅ€ĐŊĐž ĐžĐŋŅ€ĐĩĐ´ĐĩĐģĐ¸Ņ‚ŅŒ Đ˛ŅĐĩ ĐģĐ¸Ņ†Đ°? Đ‘ŅƒĐ´ŅƒŅ‚ Ņ‚Đ°ĐēĐļĐĩ ŅƒĐ´Đ°ĐģĐĩĐŊŅ‹ иĐŧĐĩĐŊа ŅĐž Đ˛ŅĐĩŅ… ĐģĐ¸Ņ†.", "confirm_user_password_reset": "Đ’Ņ‹ Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Ņ‚ĐĩĐģҌĐŊĐž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ŅĐąŅ€ĐžŅĐ¸Ņ‚ŅŒ ĐŋĐ°Ņ€ĐžĐģҌ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ {user}?", "confirm_user_pin_code_reset": "Đ’Ņ‹ Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Ņ‚ĐĩĐģҌĐŊĐž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ŅĐąŅ€ĐžŅĐ¸Ņ‚ŅŒ PIN-ĐēОд ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ {user}?", - "create_job": "ĐĄĐžĐˇĐ´Đ°Ņ‚ŅŒ СадаĐŊиĐĩ", + "create_job": "ĐĄĐžĐˇĐ´Đ°Ņ‚ŅŒ ĐˇĐ°Đ´Đ°Ņ‡Ņƒ", "cron_expression": "Đ Đ°ŅĐŋĐ¸ŅĐ°ĐŊиĐĩ (Đ˛Ņ‹Ņ€Đ°ĐļĐĩĐŊиĐĩ ĐŋĐģаĐŊĐ¸Ņ€ĐžĐ˛Ņ‰Đ¸Đēа cron)", - "cron_expression_description": "Đ§Đ°ŅŅ‚ĐžŅ‚Đ° и Đ˛Ņ€ĐĩĐŧŅ Đ˛Ņ‹ĐŋĐžĐģĐŊĐĩĐŊĐ¸Ņ СадаĐŊĐ¸Ņ в Ņ„ĐžŅ€ĐŧĐ°Ņ‚Đĩ ĐŋĐģаĐŊĐ¸Ņ€ĐžĐ˛Ņ‰Đ¸Đēа cron. Đ’ĐžŅĐŋĐžĐģŅŒĐˇŅƒĐšŅ‚ĐĩҁҌ ĐŋŅ€Đ¸ ĐŊĐĩĐžĐąŅ…ĐžĐ´Đ¸ĐŧĐžŅŅ‚Đ¸ Đ˛Đ¸ĐˇŅƒĐ°ĐģҌĐŊŅ‹Đŧ Ņ€ĐĩдаĐēŅ‚ĐžŅ€ĐžĐŧ Crontab Guru", + "cron_expression_description": "Đ§Đ°ŅŅ‚ĐžŅ‚Đ° и Đ˛Ņ€ĐĩĐŧŅ Đ˛Ņ‹ĐŋĐžĐģĐŊĐĩĐŊĐ¸Ņ ĐˇĐ°Đ´Đ°Ņ‡Đ¸ в Ņ„ĐžŅ€ĐŧĐ°Ņ‚Đĩ ĐŋĐģаĐŊĐ¸Ņ€ĐžĐ˛Ņ‰Đ¸Đēа cron. Đ’ĐžŅĐŋĐžĐģŅŒĐˇŅƒĐšŅ‚ĐĩҁҌ ĐŋŅ€Đ¸ ĐŊĐĩĐžĐąŅ…ĐžĐ´Đ¸ĐŧĐžŅŅ‚Đ¸ Đ˛Đ¸ĐˇŅƒĐ°ĐģҌĐŊŅ‹Đŧ Ņ€ĐĩдаĐēŅ‚ĐžŅ€ĐžĐŧ Crontab Guru", "cron_expression_presets": "Đ Đ°ŅĐŋĐ¸ŅĐ°ĐŊиĐĩ (ĐŋŅ€ĐĩĐ´ŅƒŅŅ‚Đ°ĐŊОвĐģĐĩĐŊĐŊŅ‹Đĩ Đ˛Đ°Ņ€Đ¸Đ°ĐŊ҂ҋ)", "disable_login": "ĐžŅ‚ĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ Đ˛Ņ…ĐžĐ´", "duplicate_detection_job_description": "ЗаĐŋ҃ҁĐēаĐĩŅ‚ ĐžĐŋŅ€ĐĩĐ´ĐĩĐģĐĩĐŊиĐĩ ĐŋĐžŅ…ĐžĐļĐ¸Ņ… Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиК ĐŋŅ€Đ¸ ĐŋĐžĐŧĐžŅ‰Đ¸ ĐŧĐ°ŅˆĐ¸ĐŊĐŊĐžĐŗĐž ĐˇŅ€ĐĩĐŊĐ¸Ņ (ĐˇĐ°Đ˛Đ¸ŅĐ¸Ņ‚ ĐžŅ‚ ҃ĐŧĐŊĐžĐŗĐž ĐŋĐžĐ¸ŅĐēа)", @@ -77,7 +79,7 @@ "face_detection_description": "ОбĐŊĐ°Ņ€ŅƒĐļиваĐĩŅ‚ ĐģĐ¸Ņ†Đ° ĐŊа ĐžĐąŅŠĐĩĐēŅ‚Đ°Ņ… ҁ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°ĐŊиĐĩĐŧ ĐŧĐ°ŅˆĐ¸ĐŊĐŊĐžĐŗĐž ĐžĐąŅƒŅ‡ĐĩĐŊĐ¸Ņ. ДĐģŅ видĐĩĐž аĐŊаĐģĐ¸ĐˇĐ¸Ņ€ŅƒĐĩŅ‚ŅŅ Ņ‚ĐžĐģҌĐēĐž ĐŧиĐŊĐ¸Đ°Ņ‚ŅŽŅ€Đ°. КĐŊĐžĐŋĐēа \"ОбĐŊĐžĐ˛Đ¸Ņ‚ŅŒ\" СаĐŋ҃ҁĐēаĐĩŅ‚ ĐŋĐžĐ˛Ņ‚ĐžŅ€ĐŊŅƒŅŽ ĐžĐąŅ€Đ°ĐąĐžŅ‚Đē҃ Đ˛ŅĐĩŅ… ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛. \"ĐĄĐąŅ€ĐžŅ\" — Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊĐž ŅƒĐ´Đ°ĐģŅĐĩŅ‚ Đ˛ŅĐĩ иĐŧĐĩŅŽŅ‰Đ¸ĐĩŅŅ даĐŊĐŊŅ‹Đĩ Đž ĐģĐ¸Ņ†Đ°Ņ…. \"ĐžŅ‚ŅŅƒŅ‚ŅŅ‚Đ˛ŅƒŅŽŅ‰Đ¸Đĩ\" — ŅŅ‚Đ°Đ˛Đ¸Ņ‚ в ĐžŅ‡ĐĩŅ€ĐĩĐ´ŅŒ ĐžĐąŅŠĐĩĐē҂ҋ, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ Đĩ҉ґ ĐŊĐĩ ĐąŅ‹Đģи ĐžĐąŅ€Đ°ĐąĐžŅ‚Đ°ĐŊŅ‹. ОбĐŊĐ°Ņ€ŅƒĐļĐĩĐŊĐŊŅ‹Đĩ ĐģĐ¸Ņ†Đ° ĐŋĐžĐŧĐĩŅ‰Đ°ŅŽŅ‚ŅŅ в ĐžŅ‡ĐĩŅ€ĐĩĐ´ŅŒ Đ´ĐģŅ ĐˇĐ°Đ´Đ°Ņ‡Đ¸ Đ Đ°ŅĐŋОСĐŊаваĐŊиĐĩ ĐģĐ¸Ņ† и ĐŋĐžŅĐģĐĩĐ´ŅƒŅŽŅ‰ĐĩĐš Đ¸Ņ… ĐŋŅ€Đ¸Đ˛ŅĐˇĐēи Đē ŅŅƒŅ‰ĐĩŅŅ‚Đ˛ŅƒŅŽŅ‰Đ¸Đŧ иĐģи ĐŊĐžĐ˛Ņ‹Đŧ ĐģŅŽĐ´ŅĐŧ.", "facial_recognition_job_description": "Đ“Ņ€ŅƒĐŋĐŋĐ¸Ņ€ŅƒĐĩŅ‚ и ĐŊаСĐŊĐ°Ņ‡Đ°ĐĩŅ‚ ОйĐŊĐ°Ņ€ŅƒĐļĐĩĐŊĐŊŅ‹Đĩ ĐģĐ¸Ņ†Đ° ĐģŅŽĐ´ŅĐŧ. Đ’Ņ‹ĐŋĐžĐģĐŊŅĐĩŅ‚ŅŅ ĐŋĐžŅĐģĐĩ СавĐĩŅ€ŅˆĐĩĐŊĐ¸Ņ ĐˇĐ°Đ´Đ°Ņ‡Đ¸ ОбĐŊĐ°Ņ€ŅƒĐļĐĩĐŊиĐĩ ĐģĐ¸Ņ†. КĐŊĐžĐŋĐēа \"ĐĄĐąŅ€ĐžŅ\" (ĐŋĐĩŅ€Đĩ)ĐŊаСĐŊĐ°Ņ‡Đ°ĐĩŅ‚ Đ˛ŅĐĩ ĐģĐ¸Ņ†Đ°. \"ĐžŅ‚ŅŅƒŅ‚ŅŅ‚Đ˛ŅƒŅŽŅ‰Đ¸Đĩ\" — дОйавĐģŅĐĩŅ‚ в ĐžŅ‡ĐĩŅ€ĐĩĐ´ŅŒ ĐžĐąŅ€Đ°ĐąĐžŅ‚Đēи ĐģĐ¸Ņ†Đ°, ĐŊĐĩ ĐŋŅ€Đ¸Đ˛ŅĐˇĐ°ĐŊĐŊŅ‹Đĩ Đē ҇ĐĩĐģОвĐĩĐē҃.", "failed_job_command": "КоĐŧаĐŊда {command} ĐŊĐĩ Đ˛Ņ‹ĐŋĐžĐģĐŊĐĩĐŊа Đ´ĐģŅ ĐˇĐ°Đ´Đ°Ņ‡Đ¸: {job}", - "force_delete_user_warning": "ĐŸĐ Đ•Đ”ĐŖĐŸĐ Đ•Đ–Đ”Đ•ĐĐ˜Đ•: Đ­Ņ‚Đž ĐŋŅ€Đ¸Đ˛ĐĩĐ´ĐĩŅ‚ Đē ĐŊĐĩĐŧĐĩĐ´ĐģĐĩĐŊĐŊĐžĐŧ҃ ŅƒĐ´Đ°ĐģĐĩĐŊĐ¸ŅŽ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ и ĐĩĐŗĐž Ņ€ĐĩŅŅƒŅ€ŅĐžĐ˛. Đ­Ņ‚Đž Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Đĩ ĐŊĐĩвОСĐŧĐžĐļĐŊĐž ĐžŅ‚ĐŧĐĩĐŊĐ¸Ņ‚ŅŒ, и Ņ„Đ°ĐšĐģŅ‹ ĐŊĐĩ ĐŧĐžĐŗŅƒŅ‚ ĐąŅ‹Ņ‚ŅŒ Đ˛ĐžŅŅŅ‚Đ°ĐŊОвĐģĐĩĐŊŅ‹.", + "force_delete_user_warning": "ĐŸĐ Đ•Đ”ĐŖĐŸĐ Đ•Đ–Đ”Đ•ĐĐ˜Đ•: Đ­Ņ‚Đž ĐŋŅ€Đ¸Đ˛ĐĩĐ´ĐĩŅ‚ Đē ĐŊĐĩĐŧĐĩĐ´ĐģĐĩĐŊĐŊĐžĐŧ҃ ŅƒĐ´Đ°ĐģĐĩĐŊĐ¸ŅŽ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ и Đ˛ŅĐĩŅ… ĐĩĐŗĐž ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛. Đ­Ņ‚Đž Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Đĩ ĐŊĐĩвОСĐŧĐžĐļĐŊĐž ĐžŅ‚ĐŧĐĩĐŊĐ¸Ņ‚ŅŒ, Ņ„Đ°ĐšĐģŅ‹ ĐŊĐĩ ҁĐŧĐžĐŗŅƒŅ‚ ĐąŅ‹Ņ‚ŅŒ Đ˛ĐžŅŅŅ‚Đ°ĐŊОвĐģĐĩĐŊŅ‹.", "image_format": "Đ¤ĐžŅ€ĐŧĐ°Ņ‚", "image_format_description": "WebP ŅĐžĐˇĐ´Đ°ĐĩŅ‚ Ņ„Đ°ĐšĐģŅ‹ ĐŧĐĩĐŊҌ҈ĐĩĐŗĐž Ņ€Đ°ĐˇĐŧĐĩŅ€Đ°, ҇ĐĩĐŧ JPEG, ĐŊĐž ĐēĐžĐ´Đ¸Ņ€ŅƒĐĩŅ‚ ĐŧĐĩĐ´ĐģĐĩĐŊĐŊĐĩĐĩ.", "image_fullsize_description": "ПоĐģĐŊĐžŅ€Đ°ĐˇĐŧĐĩŅ€ĐŊĐžĐĩ Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиĐĩ ĐąĐĩС ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐŊҋ҅, Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐĩŅ‚ŅŅ ĐŋŅ€Đ¸ ŅƒĐ˛ĐĩĐģĐ¸Ņ‡ĐĩĐŊии", @@ -100,11 +102,11 @@ "image_thumbnail_description": "МаĐģĐĩĐŊҌĐēĐ°Ņ ĐŧиĐŊĐ¸Đ°Ņ‚ŅŽŅ€Đ° ҁ ŅƒĐ´Đ°ĐģĐĩĐŊĐŊŅ‹Đŧи ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐŊŅ‹Đŧи, Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐĩĐŧĐ°Ņ ĐŋŅ€Đ¸ ĐŋŅ€ĐžŅĐŧĐžŅ‚Ņ€Đĩ ĐŗŅ€ŅƒĐŋĐŋ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đš, Ņ‚Đ°ĐēĐ¸Ņ… ĐēаĐē ĐžŅĐŊОвĐŊĐ°Ņ Đ˛Ņ€ĐĩĐŧĐĩĐŊĐŊĐ°Ņ ҈ĐēаĐģа", "image_thumbnail_quality_description": "ĐšĐ°Ņ‡ĐĩŅŅ‚Đ˛Đž ĐŧиĐŊĐ¸Đ°Ņ‚ŅŽŅ€ ĐžŅ‚ 1 Đ´Đž 100. ЧĐĩĐŧ Đ˛Ņ‹ŅˆĐĩ ĐēĐ°Ņ‡ĐĩŅŅ‚Đ˛Đž, Ņ‚ĐĩĐŧ ĐģŅƒŅ‡ŅˆĐĩ, ĐŊĐž ĐŋŅ€Đ¸ ŅŅ‚ĐžĐŧ ŅĐžĐˇĐ´Đ°ŅŽŅ‚ŅŅ Ņ„Đ°ĐšĐģŅ‹ йОĐģҌ҈ĐĩĐŗĐž Ņ€Đ°ĐˇĐŧĐĩŅ€Đ° и ĐŧĐžĐļĐĩŅ‚ ҁĐŊĐ¸ĐˇĐ¸Ņ‚ŅŒŅŅ ҁĐēĐžŅ€ĐžŅŅ‚ŅŒ ĐžŅ‚ĐēĐģиĐēа ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸Ņ.", "image_thumbnail_title": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи ĐŧиĐŊĐ¸Đ°Ņ‚ŅŽŅ€", - "job_concurrency": "ĐŸĐ°Ņ€Đ°ĐģĐģĐĩĐģҌĐŊĐ°Ņ ĐžĐąŅ€Đ°ĐąĐžŅ‚Đēа СадаĐŊĐ¸Ņ - {job}", - "job_created": "ЗадаĐŊиĐĩ ŅĐžĐˇĐ´Đ°ĐŊĐž", + "job_concurrency": "Đ§Đ¸ŅĐģĐž ĐŋĐ°Ņ€Đ°ĐģĐģĐĩĐģҌĐŊҋ҅ ĐŋĐžŅ‚ĐžĐēОв ĐˇĐ°Đ´Đ°Ņ‡Đ¸ {job}", + "job_created": "Đ—Đ°Đ´Đ°Ņ‡Đ° ŅĐžĐˇĐ´Đ°ĐŊа", "job_not_concurrency_safe": "Đ­Ņ‚Đ° ĐˇĐ°Đ´Đ°Ņ‡Đ° ĐŊĐĩ ОйĐĩҁĐŋĐĩŅ‡Đ¸Đ˛Đ°ĐĩŅ‚ ĐąĐĩСОĐŋĐ°ŅĐŊĐžŅŅ‚ŅŒ ĐŋĐ°Ņ€Đ°ĐģĐģĐĩĐģҌĐŊĐžŅŅ‚Đ¸ Đ˛Ņ‹ĐŋĐžĐģĐŊĐĩĐŊĐ¸Ņ.", - "job_settings": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи СадаĐŊиК", - "job_settings_description": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ĐŋĐ°Ņ€Đ°ĐģĐģĐĩĐģҌĐŊОК ĐžĐąŅ€Đ°ĐąĐžŅ‚ĐēОК СадаĐŊиК", + "job_settings": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи ĐˇĐ°Đ´Đ°Ņ‡", + "job_settings_description": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ĐŋĐ°Ņ€Đ°ĐģĐģĐĩĐģҌĐŊĐžŅŅ‚ŅŒŅŽ Đ˛Ņ‹ĐŋĐžĐģĐŊĐĩĐŊĐ¸Ņ ĐˇĐ°Đ´Đ°Ņ‡", "job_status": "ĐĄĐžŅŅ‚ĐžŅĐŊиĐĩ Đ˛Ņ‹ĐŋĐžĐģĐŊĐĩĐŊĐ¸Ņ ĐˇĐ°Đ´Đ°Ņ‡", "jobs_delayed": "{jobCount, plural, one {# ĐžŅ‚ĐģĐžĐļĐĩĐŊа} other {# ĐžŅ‚ĐģĐžĐļĐĩĐŊĐž}}", "jobs_failed": "{jobCount, plural, other {# ĐŊĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ Đ˛Ņ‹ĐŋĐžĐģĐŊĐ¸Ņ‚ŅŒ}}", @@ -123,20 +125,27 @@ "logging_enable_description": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ вĐĩĐ´ĐĩĐŊиĐĩ ĐļŅƒŅ€ĐŊаĐģа", "logging_level_description": "Đ•ŅĐģи вĐēĐģŅŽŅ‡ĐĩĐŊĐž, Đ˛Ņ‹ĐąĐĩŅ€Đ¸Ņ‚Đĩ ĐļĐĩĐģаĐĩĐŧŅ‹Đš ŅƒŅ€ĐžĐ˛ĐĩĐŊҌ ĐļŅƒŅ€ĐŊаĐģĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ.", "logging_settings": "ВĐĩĐ´ĐĩĐŊиĐĩ ĐļŅƒŅ€ĐŊаĐģа", + "machine_learning_availability_checks": "ĐŸŅ€ĐžĐ˛ĐĩŅ€Đēа Đ´ĐžŅŅ‚ŅƒĐŋĐŊĐžŅŅ‚Đ¸", + "machine_learning_availability_checks_description": "ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐĩҁĐēи ĐžĐŋŅ€ĐĩĐ´ĐĩĐģŅŅ‚ŅŒ и Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ Đ´ĐžŅŅ‚ŅƒĐŋĐŊŅ‹Đĩ ҁĐĩŅ€Đ˛ĐĩҀҋ ĐŧĐ°ŅˆĐ¸ĐŊĐŊĐžĐŗĐž ĐžĐąŅƒŅ‡ĐĩĐŊĐ¸Ņ", + "machine_learning_availability_checks_enabled": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ ĐŋŅ€ĐžĐ˛ĐĩŅ€Đē҃ Đ´ĐžŅŅ‚ŅƒĐŋĐŊĐžŅŅ‚Đ¸", + "machine_learning_availability_checks_interval": "ИĐŊŅ‚ĐĩŅ€Đ˛Đ°Đģ ĐŋŅ€ĐžĐ˛ĐĩŅ€Đēи", + "machine_learning_availability_checks_interval_description": "ИĐŊŅ‚ĐĩŅ€Đ˛Đ°Đģ в ĐŧиĐģĐģĐ¸ŅĐĩĐē҃ĐŊĐ´Đ°Ņ… ĐŧĐĩĐļĐ´Ņƒ ĐŋŅ€ĐžĐ˛ĐĩŅ€ĐēаĐŧи", + "machine_learning_availability_checks_timeout": "ĐĸаКĐŧ-Đ°ŅƒŅ‚ СаĐŋŅ€ĐžŅĐ°", + "machine_learning_availability_checks_timeout_description": "Đ’Ņ€ĐĩĐŧŅ ĐžĐļидаĐŊĐ¸Ņ ĐžŅ‚Đ˛ĐĩŅ‚Đ° ҁĐĩŅ€Đ˛ĐĩŅ€Đ° в ĐŧиĐģĐģĐ¸ŅĐĩĐē҃ĐŊĐ´Đ°Ņ… Đ´ĐģŅ ĐžĐŋŅ€ĐĩĐ´ĐĩĐģĐĩĐŊĐ¸Ņ Đ´ĐžŅŅ‚ŅƒĐŋĐŊĐžŅŅ‚Đ¸", "machine_learning_clip_model": "CLIP ĐŧОдĐĩĐģҌ", - "machine_learning_clip_model_description": "НазваĐŊĐ¸Ņ ĐŧОдĐĩĐģĐĩĐš CLIP Ņ€Đ°ĐˇĐŧĐĩ҉ĐĩĐŊŅ‹ СдĐĩҁҌ. ĐžĐąŅ€Đ°Ņ‚Đ¸Ņ‚Đĩ вĐŊиĐŧаĐŊиĐĩ, Ņ‡Ņ‚Đž ĐŋŅ€Đ¸ иСĐŧĐĩĐŊĐĩĐŊии ĐŧОдĐĩĐģи ĐŊĐĩĐžĐąŅ…ĐžĐ´Đ¸ĐŧĐž СаĐŊОвО СаĐŋŅƒŅŅ‚Đ¸Ņ‚ŅŒ ĐˇĐ°Đ´Đ°Ņ‡Ņƒ ÂĢИĐŊŅ‚ĐĩĐģĐģĐĩĐēŅ‚ŅƒĐ°ĐģҌĐŊŅ‹Đš ĐŋĐžĐ¸ŅĐēÂģ Đ´ĐģŅ Đ˛ŅĐĩŅ… Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиК.", + "machine_learning_clip_model_description": "НазваĐŊĐ¸Ņ Đ´ĐžŅŅ‚ŅƒĐŋĐŊҋ҅ CLIP ĐŧОдĐĩĐģĐĩĐš Ņ€Đ°ĐˇĐŧĐĩ҉ĐĩĐŊŅ‹ СдĐĩҁҌ.\nĐŸŅ€Đ¸ иСĐŧĐĩĐŊĐĩĐŊии ĐŧОдĐĩĐģи ĐŊĐĩĐžĐąŅ…ĐžĐ´Đ¸ĐŧĐž СаĐŊОвО СаĐŋŅƒŅŅ‚Đ¸Ņ‚ŅŒ ĐˇĐ°Đ´Đ°Ņ‡Ņƒ ÂĢИĐŊŅ‚ĐĩĐģĐģĐĩĐēŅ‚ŅƒĐ°ĐģҌĐŊŅ‹Đš ĐŋĐžĐ¸ŅĐēÂģ Đ´ĐģŅ Đ˛ŅĐĩŅ… ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛.", "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": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚Đĩ ĐŧĐ°ŅˆĐ¸ĐŊĐŊĐžĐĩ ĐžĐąŅƒŅ‡ĐĩĐŊиĐĩ", - "machine_learning_enabled_description": "ĐŸŅ€Đ¸ ĐžŅ‚ĐēĐģŅŽŅ‡ĐĩĐŊии, Đ˛ŅĐĩ Ņ„ŅƒĐŊĐēŅ†Đ¸Đ¸ ML ĐąŅƒĐ´ŅƒŅ‚ ĐžŅ‚ĐēĐģŅŽŅ‡ĐĩĐŊŅ‹ ĐŊĐĩĐˇĐ°Đ˛Đ¸ŅĐ¸ĐŧĐž ĐžŅ‚ ҁĐģĐĩĐ´ŅƒŅŽŅ‰Đ¸Ņ… ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€ĐžĐ˛.", + "machine_learning_duplicate_detection_enabled_description": "Đ•ŅĐģи ŅŅ‚ĐžŅ‚ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ĐžŅ‚ĐēĐģŅŽŅ‡Ņ‘ĐŊ, Đ°ĐąŅĐžĐģŅŽŅ‚ĐŊĐž идĐĩĐŊŅ‚Đ¸Ņ‡ĐŊŅ‹Đĩ Ņ„Đ°ĐšĐģŅ‹ Đ˛ŅŅ‘ Ņ€Đ°Đ˛ĐŊĐž ĐŊĐĩ ĐąŅƒĐ´ŅƒŅ‚ ĐˇĐ°ĐŗŅ€ŅƒĐļĐ°Ņ‚ŅŒŅŅ.", + "machine_learning_duplicate_detection_setting_description": "Đ˜ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°ĐŊиĐĩ CLIP ĐŧОдĐĩĐģĐĩĐš Đ´ĐģŅ Đ˛Ņ‹ŅĐ˛ĐģĐĩĐŊĐ¸Ņ вОСĐŧĐžĐļĐŊҋ҅ Đ´ŅƒĐąĐģиĐēĐ°Ņ‚ĐžĐ˛", + "machine_learning_enabled": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ ĐŧĐ°ŅˆĐ¸ĐŊĐŊĐžĐĩ ĐžĐąŅƒŅ‡ĐĩĐŊиĐĩ", + "machine_learning_enabled_description": "ĐŸŅ€Đ¸ Đ˛Ņ‹ĐēĐģŅŽŅ‡ĐĩĐŊии ĐąŅƒĐ´ŅƒŅ‚ ĐžŅ‚ĐēĐģŅŽŅ‡ĐĩĐŊŅ‹ Đ˛ŅĐĩ Ņ„ŅƒĐŊĐēŅ†Đ¸Đ¸ ML ĐŊĐĩĐˇĐ°Đ˛Đ¸ŅĐ¸ĐŧĐž ĐžŅ‚ ҁĐģĐĩĐ´ŅƒŅŽŅ‰Đ¸Ņ… ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€ĐžĐ˛.", "machine_learning_facial_recognition": "Đ Đ°ŅĐŋОСĐŊаваĐŊиĐĩ ĐģĐ¸Ņ†", "machine_learning_facial_recognition_description": "ОбĐŊĐ°Ņ€ŅƒĐļĐ¸Đ˛Đ°Ņ‚ŅŒ, Ņ€Đ°ŅĐŋОСĐŊĐ°Đ˛Đ°Ņ‚ŅŒ и ĐŗŅ€ŅƒĐŋĐŋĐ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ ĐģĐ¸Ņ†Đ° ĐŊа Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸ŅŅ…", "machine_learning_facial_recognition_model": "МодĐĩĐģҌ Đ´ĐģŅ Ņ€Đ°ŅĐŋОСĐŊаваĐŊĐ¸Ņ ĐģĐ¸Ņ†", - "machine_learning_facial_recognition_model_description": "МодĐĩĐģи ĐŋĐĩŅ€ĐĩŅ‡Đ¸ŅĐģĐĩĐŊŅ‹ в ĐŋĐžŅ€ŅĐ´ĐēĐĩ ŅƒĐąŅ‹Đ˛Đ°ĐŊĐ¸Ņ Ņ€Đ°ĐˇĐŧĐĩŅ€Đ°. БоĐģŅŒŅˆĐ¸Đĩ ĐŧОдĐĩĐģи Ņ€Đ°ĐąĐžŅ‚Đ°ŅŽŅ‚ ĐŧĐĩĐ´ĐģĐĩĐŊĐŊĐĩĐĩ и Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒŅŽŅ‚ йОĐģҌ҈Đĩ ĐŋаĐŧŅŅ‚Đ¸, ĐŊĐž Đ´Đ°ŅŽŅ‚ ĐģŅƒŅ‡ŅˆĐ¸Đĩ Ņ€ĐĩĐˇŅƒĐģŅŒŅ‚Đ°Ņ‚Ņ‹. ĐžĐąŅ€Đ°Ņ‚Đ¸Ņ‚Đĩ вĐŊиĐŧаĐŊиĐĩ, Ņ‡Ņ‚Đž ĐŋŅ€Đ¸ ҁĐŧĐĩĐŊĐĩ ĐŧОдĐĩĐģи ĐŊĐĩĐžĐąŅ…ĐžĐ´Đ¸ĐŧĐž ĐŋĐžĐ˛Ņ‚ĐžŅ€ĐŊĐž СаĐŋŅƒŅŅ‚Đ¸Ņ‚ŅŒ СадаĐŊиĐĩ Ņ€Đ°ŅĐŋОСĐŊаваĐŊĐ¸Ņ ĐģĐ¸Ņ† Đ´ĐģŅ Đ˛ŅĐĩŅ… Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиК.", + "machine_learning_facial_recognition_model_description": "МодĐĩĐģи ĐŋĐĩŅ€ĐĩŅ‡Đ¸ŅĐģĐĩĐŊŅ‹ в ĐŋĐžŅ€ŅĐ´ĐēĐĩ ŅƒĐąŅ‹Đ˛Đ°ĐŊĐ¸Ņ Đ¸Ņ… Ņ€Đ°ĐˇĐŧĐĩŅ€Đ°. БоĐģŅŒŅˆĐ¸Đĩ ĐŧОдĐĩĐģи Ņ€Đ°ĐąĐžŅ‚Đ°ŅŽŅ‚ ĐŧĐĩĐ´ĐģĐĩĐŊĐŊĐĩĐĩ и Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒŅŽŅ‚ йОĐģҌ҈Đĩ ĐŋаĐŧŅŅ‚Đ¸, ĐŊĐž Đ´Đ°ŅŽŅ‚ ĐģŅƒŅ‡ŅˆĐ¸Đĩ Ņ€ĐĩĐˇŅƒĐģŅŒŅ‚Đ°Ņ‚Ņ‹. ĐŸŅ€Đ¸ ҁĐŧĐĩĐŊĐĩ ĐŧОдĐĩĐģи ĐŊĐĩĐžĐąŅ…ĐžĐ´Đ¸ĐŧĐž ĐŋĐžĐ˛Ņ‚ĐžŅ€ĐŊĐž СаĐŋŅƒŅŅ‚Đ¸Ņ‚ŅŒ ĐˇĐ°Đ´Đ°Ņ‡Ņƒ Ņ€Đ°ŅĐŋОСĐŊаваĐŊĐ¸Ņ ĐģĐ¸Ņ† Đ´ĐģŅ Đ˛ŅĐĩŅ… Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиК.", "machine_learning_facial_recognition_setting": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ Ņ„ŅƒĐŊĐēŅ†Đ¸ŅŽ Ņ€Đ°ŅĐŋОСĐŊаваĐŊĐ¸Ņ ĐģĐ¸Ņ†", - "machine_learning_facial_recognition_setting_description": "Đ•ŅĐģи ĐžŅ‚ĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ ŅŅ‚Ņƒ Ņ„ŅƒĐŊĐēŅ†Đ¸ŅŽ, Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ ĐŊĐĩ ĐąŅƒĐ´ŅƒŅ‚ ĐēĐžĐ´Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒŅŅ Đ´ĐģŅ Ņ€Đ°ŅĐŋОСĐŊаваĐŊĐ¸Ņ ĐģĐ¸Ņ† и ĐŊĐĩ ĐąŅƒĐ´ŅƒŅ‚ СаĐŋĐžĐģĐŊŅŅ‚ŅŒ Ņ€Đ°ĐˇĐ´ĐĩĐģ Đ›ŅŽĐ´Đ¸ ĐŊа ĐžĐąĐˇĐžŅ€ĐŊОК ŅŅ‚Ņ€Đ°ĐŊĐ¸Ņ†Đĩ.", + "machine_learning_facial_recognition_setting_description": "ĐŸŅ€Đ¸ ĐžŅ‚ĐēĐģŅŽŅ‡ĐĩĐŊии ŅŅ‚ĐžĐš Ņ„ŅƒĐŊĐēŅ†Đ¸Đ¸ Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ ĐŊĐĩ ĐąŅƒĐ´ŅƒŅ‚ ĐēĐžĐ´Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒŅŅ Đ´ĐģŅ Ņ€Đ°ŅĐŋОСĐŊаваĐŊĐ¸Ņ ĐģĐ¸Ņ†, и ĐŊĐĩ ĐąŅƒĐ´ĐĩŅ‚ СаĐŋĐžĐģĐŊŅŅ‚ŅŒŅŅ Ņ€Đ°ĐˇĐ´ĐĩĐģ Đ›ŅŽĐ´Đ¸.", "machine_learning_max_detection_distance": "МаĐēŅĐ¸ĐŧаĐģҌĐŊĐžĐĩ Ņ€Đ°ĐˇĐģĐ¸Ņ‡Đ¸Đĩ Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиК", "machine_learning_max_detection_distance_description": "МаĐēŅĐ¸ĐŧаĐģҌĐŊĐžĐĩ Ņ€Đ°ĐˇĐģĐ¸Ņ‡Đ¸Đĩ ĐŧĐĩĐļĐ´Ņƒ Đ´Đ˛ŅƒĐŧŅ Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸ŅĐŧи, Ņ‡Ņ‚ĐžĐąŅ‹ ŅŅ‡Đ¸Ņ‚Đ°Ņ‚ŅŒ Đ¸Ņ… Đ´ŅƒĐąĐģиĐēĐ°Ņ‚Đ°Đŧи, в диаĐŋаСОĐŊĐĩ 0,001-0,1. БоĐģĐĩĐĩ Đ˛Ņ‹ŅĐžĐēиĐĩ СĐŊĐ°Ņ‡ĐĩĐŊĐ¸Ņ ĐŋОСвОĐģŅŅŽŅ‚ ОйĐŊĐ°Ņ€ŅƒĐļĐ¸Ņ‚ŅŒ йОĐģҌ҈Đĩ Đ´ŅƒĐąĐģиĐēĐ°Ņ‚ĐžĐ˛, ĐŊĐž ĐŧĐžĐŗŅƒŅ‚ ĐŋŅ€Đ¸Đ˛ĐĩŅŅ‚Đ¸ Đē ĐģĐžĐļĐŊŅ‹Đŧ ŅŅ€Đ°ĐąĐ°Ņ‚Ņ‹Đ˛Đ°ĐŊĐ¸ŅĐŧ.", "machine_learning_max_recognition_distance": "ĐŸĐžŅ€ĐžĐŗ Ņ€Đ°ŅĐŋОСĐŊаваĐŊĐ¸Ņ", @@ -146,13 +155,13 @@ "machine_learning_min_recognized_faces": "МиĐŊиĐŧ҃Đŧ Ņ€Đ°ŅĐŋОСĐŊаĐŊĐŊҋ҅ ĐģĐ¸Ņ†", "machine_learning_min_recognized_faces_description": "МиĐŊиĐŧаĐģҌĐŊĐžĐĩ ĐēĐžĐģĐ¸Ņ‡ĐĩŅŅ‚Đ˛Đž Ņ€Đ°ŅĐŋОСĐŊаĐŊĐŊҋ҅ ĐģĐ¸Ņ† Đ´ĐģŅ ŅĐžĐˇĐ´Đ°ĐŊĐ¸Ņ ҇ĐĩĐģОвĐĩĐēа. ĐŖĐ˛ĐĩĐģĐ¸Ņ‡ĐĩĐŊиĐĩ ŅŅ‚ĐžĐŗĐž ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° Đ´ĐĩĐģаĐĩŅ‚ Ņ€Đ°ŅĐŋОСĐŊаваĐŊиĐĩ ĐģĐ¸Ņ† йОĐģĐĩĐĩ Ņ‚ĐžŅ‡ĐŊŅ‹Đŧ, ĐŊĐž ĐŋŅ€Đ¸ ŅŅ‚ĐžĐŧ ŅƒĐ˛ĐĩĐģĐ¸Ņ‡Đ¸Đ˛Đ°ĐĩŅ‚ŅŅ вĐĩŅ€ĐžŅŅ‚ĐŊĐžŅŅ‚ŅŒ Ņ‚ĐžĐŗĐž, Ņ‡Ņ‚Đž ĐģĐ¸Ņ†Đž ĐŊĐĩ ĐąŅƒĐ´ĐĩŅ‚ ĐŋŅ€Đ¸ŅĐ˛ĐžĐĩĐŊĐž ҇ĐĩĐģОвĐĩĐē҃.", "machine_learning_settings": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи ĐŧĐ°ŅˆĐ¸ĐŊĐŊĐžĐŗĐž ĐžĐąŅƒŅ‡ĐĩĐŊĐ¸Ņ", - "machine_learning_settings_description": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ Ņ„ŅƒĐŊĐēŅ†Đ¸ŅĐŧи и ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēаĐŧи ĐŧĐ°ŅˆĐ¸ĐŊĐŊĐžĐŗĐž ĐžĐąŅƒŅ‡ĐĩĐŊĐ¸Ņ", + "machine_learning_settings_description": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ Ņ„ŅƒĐŊĐēŅ†Đ¸ŅĐŧи и ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēаĐŧи ĐŧĐ°ŅˆĐ¸ĐŊĐŊĐžĐŗĐž ĐžĐąŅƒŅ‡ĐĩĐŊĐ¸Ņ (ML)", "machine_learning_smart_search": "ИĐŊŅ‚ĐĩĐģĐģĐĩĐēŅ‚ŅƒĐ°ĐģҌĐŊŅ‹Đš ĐŋĐžĐ¸ŅĐē", - "machine_learning_smart_search_description": "ĐĄĐĩĐŧаĐŊŅ‚Đ¸Ņ‡ĐĩҁĐēиК ĐŋĐžĐ¸ŅĐē Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиК ҁ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°ĐŊиĐĩĐŧ вĐģĐžĐļĐĩĐŊиК CLIP", + "machine_learning_smart_search_description": "ĐĄĐĩĐŧаĐŊŅ‚Đ¸Ņ‡ĐĩҁĐēиК (ĐēĐžĐŊŅ‚ĐĩĐēҁ҂ĐŊŅ‹Đš) ĐŋĐžĐ¸ŅĐē ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛ ҁ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°ĐŊиĐĩĐŧ CLIP ĐŧОдĐĩĐģĐĩĐš", "machine_learning_smart_search_enabled": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ иĐŊŅ‚ĐĩĐģĐģĐĩĐēŅ‚ŅƒĐ°ĐģҌĐŊŅ‹Đš ĐŋĐžĐ¸ŅĐē", - "machine_learning_smart_search_enabled_description": "Đ•ŅĐģи ŅŅ‚ĐžŅ‚ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ĐžŅ‚ĐēĐģŅŽŅ‡ĐĩĐŊ, Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ ĐŊĐĩ ĐąŅƒĐ´ŅƒŅ‚ ĐēĐžĐ´Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒŅŅ Đ´ĐģŅ иĐŊŅ‚ĐĩĐģĐģĐĩĐēŅ‚ŅƒĐ°ĐģҌĐŊĐžĐŗĐž ĐŋĐžĐ¸ŅĐēа.", + "machine_learning_smart_search_enabled_description": "ĐŸŅ€Đ¸ ĐžŅ‚ĐēĐģŅŽŅ‡ĐĩĐŊии ŅŅ‚ĐžĐš Ņ„ŅƒĐŊĐēŅ†Đ¸Đ¸ Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ ĐŊĐĩ ĐąŅƒĐ´ŅƒŅ‚ ĐēĐžĐ´Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒŅŅ Đ´ĐģŅ иĐŊŅ‚ĐĩĐģĐģĐĩĐēŅ‚ŅƒĐ°ĐģҌĐŊĐžĐŗĐž ĐŋĐžĐ¸ŅĐēа.", "machine_learning_url_description": "URL-Đ°Đ´Ņ€Đĩҁ ҁĐĩŅ€Đ˛ĐĩŅ€Đ° ĐŧĐ°ŅˆĐ¸ĐŊĐŊĐžĐŗĐž ĐžĐąŅƒŅ‡ĐĩĐŊĐ¸Ņ. Đ•ŅĐģи ҃ĐēаСаĐŊĐž ĐŊĐĩҁĐēĐžĐģҌĐēĐž, СаĐŋŅ€ĐžŅŅ‹ ĐąŅƒĐ´ŅƒŅ‚ ĐžŅ‚ĐŋŅ€Đ°Đ˛ĐģŅŅ‚ŅŒŅŅ ĐŋĐž ĐžŅ‡ĐĩŅ€Đĩди ĐŊа ĐēаĐļĐ´Ņ‹Đš, ĐŋĐžĐēа ĐžŅ‚ ОдĐŊĐžĐŗĐž иС ĐŊĐ¸Ņ… ĐŊĐĩ ĐąŅƒĐ´ĐĩŅ‚ ĐŋĐžĐģŅƒŅ‡ĐĩĐŊ ҃ҁĐŋĐĩ҈ĐŊŅ‹Đš ĐžŅ‚Đ˛ĐĩŅ‚. ĐĄĐĩŅ€Đ˛ĐĩҀҋ, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ ĐŊĐĩ ĐžŅ‚Đ˛ĐĩŅ‡Đ°ŅŽŅ‚, ĐąŅƒĐ´ŅƒŅ‚ Đ˛Ņ€ĐĩĐŧĐĩĐŊĐŊĐž Đ¸ĐŗĐŊĐžŅ€Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒŅŅ Đ´Đž Ņ‚ĐĩŅ… ĐŋĐžŅ€, ĐŋĐžĐēа ĐŊĐĩ ŅŅ‚Đ°ĐŊŅƒŅ‚ ҁĐŊОва Đ´ĐžŅŅ‚ŅƒĐŋĐŊŅ‹.", - "manage_concurrency": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ĐŋĐ°Ņ€Đ°ĐģĐģĐĩĐģҌĐŊĐžŅŅ‚ŅŒŅŽ СадаĐŊиК", + "manage_concurrency": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ĐŋĐ°Ņ€Đ°ĐģĐģĐĩĐģҌĐŊĐžŅŅ‚ŅŒŅŽ", "manage_log_settings": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēаĐŧи ĐļŅƒŅ€ĐŊаĐģа", "map_dark_style": "ĐĸŅ‘ĐŧĐŊŅ‹Đš ŅŅ‚Đ¸ĐģҌ", "map_enable_description": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ Ņ„ŅƒĐŊĐēŅ†Đ¸Đ¸ ĐēĐ°Ņ€Ņ‚Ņ‹", @@ -170,9 +179,9 @@ "memory_cleanup_job": "ĐžŅ‡Đ¸ŅŅ‚Đēа Đ˛ĐžŅĐŋĐžĐŧиĐŊаĐŊиК", "memory_generate_job": "ХОСдаĐŊиĐĩ Đ˛ĐžŅĐŋĐžĐŧиĐŊаĐŊиК", "metadata_extraction_job": "ИСвĐģĐĩ҇ĐĩĐŊиĐĩ ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐŊҋ҅", - "metadata_extraction_job_description": "ИСвĐģĐĩĐēаĐĩŅ‚ ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐŊŅ‹Đĩ иС ĐēаĐļĐ´ĐžĐŗĐž Ņ„Đ°ĐšĐģа, Ņ‚Đ°ĐēиĐĩ ĐēаĐē ĐŧĐĩŅŅ‚ĐžĐŋĐžĐģĐžĐļĐĩĐŊиĐĩ, ĐģĐ¸Ņ†Đ° и Ņ€Đ°ĐˇŅ€Đĩ҈ĐĩĐŊиĐĩ", + "metadata_extraction_job_description": "ИСвĐģĐĩ҇ĐĩĐŊиĐĩ ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐŊҋ҅ иС Ņ„Đ°ĐšĐģОв, Ņ‚Đ°ĐēĐ¸Ņ… ĐēаĐē ĐŧĐĩŅŅ‚ĐžĐŋĐžĐģĐžĐļĐĩĐŊиĐĩ, ĐģĐ¸Ņ†Đ° и Ņ€Đ°ĐˇŅ€Đĩ҈ĐĩĐŊиĐĩ", "metadata_faces_import_setting": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ иĐŧĐŋĐžŅ€Ņ‚ ĐģĐ¸Ņ†", - "metadata_faces_import_setting_description": "ИĐŧĐŋĐžŅ€Ņ‚ ĐģĐ¸Ņ† иС Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиК EXIF-даĐŊĐŊҋ҅ и Ņ„Đ°ĐšĐģОв sidecar", + "metadata_faces_import_setting_description": "ИĐŧĐŋĐžŅ€Ņ‚ ĐģĐ¸Ņ† иС EXIF-даĐŊĐŊҋ҅ и Ņ„Đ°ĐšĐģОв sidecar", "metadata_settings": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐŊҋ҅", "metadata_settings_description": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēаĐŧи ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐŊҋ҅", "migration_job": "ĐœĐ¸ĐŗŅ€Đ°Ņ†Đ¸Ņ", @@ -247,7 +256,7 @@ "reset_settings_to_default": "ĐĄĐąŅ€ĐžŅ ĐŊĐ°ŅŅ‚Ņ€ĐžĐĩĐē Đ´Đž СĐŊĐ°Ņ‡ĐĩĐŊиК ĐŋĐž ҃ĐŧĐžĐģŅ‡Đ°ĐŊĐ¸ŅŽ", "reset_settings_to_recent_saved": "НĐĩ ŅĐžŅ…Ņ€Đ°ĐŊŅ‘ĐŊĐŊŅ‹Đĩ иСĐŧĐĩĐŊĐĩĐŊĐ¸Ņ ŅĐąŅ€ĐžŅˆĐĩĐŊŅ‹ Đē ĐŋĐžŅĐģĐĩĐ´ĐŊиĐŧ ŅĐžŅ…Ņ€Đ°ĐŊĐĩĐŊĐŊŅ‹Đŧ СĐŊĐ°Ņ‡ĐĩĐŊĐ¸ŅĐŧ", "scanning_library": "ĐĄĐēаĐŊĐ¸Ņ€ĐžĐ˛Đ°ĐŊиĐĩ йийĐģĐ¸ĐžŅ‚ĐĩĐēи", - "search_jobs": "ĐŸĐžĐ¸ŅĐē СадаĐŊиКâ€Ļ", + "search_jobs": "ĐŸĐžĐ¸ŅĐē ĐˇĐ°Đ´Đ°Ņ‡â€Ļ", "send_welcome_email": "ĐžŅ‚ĐŋŅ€Đ°Đ˛Đ¸Ņ‚ŅŒ ĐŋŅ€Đ¸Đ˛ĐĩŅ‚ŅŅ‚Đ˛ĐĩĐŊĐŊĐžĐĩ ĐŋĐ¸ŅŅŒĐŧĐž", "server_external_domain_settings": "ВĐŊĐĩ҈ĐŊиК Đ´ĐžĐŧĐĩĐŊ", "server_external_domain_settings_description": "ДоĐŧĐĩĐŊ Đ´ĐģŅ ĐŋŅƒĐąĐģĐ¸Ņ‡ĐŊҋ҅ ҁҁҋĐģĐžĐē, вĐēĐģŅŽŅ‡Đ°Ņ http(s)://", @@ -268,8 +277,8 @@ "storage_template_hash_verification_enabled_description": "ВĐēĐģŅŽŅ‡Đ°ĐĩŅ‚ ĐŋŅ€ĐžĐ˛ĐĩŅ€Đē҃ Ņ…ĐĩŅˆĐ°, ĐŊĐĩ ĐžŅ‚ĐēĐģŅŽŅ‡Đ°ĐšŅ‚Đĩ ĐĩŅ‘, ĐĩҁĐģи ĐŊĐĩ ŅƒĐ˛ĐĩŅ€ĐĩĐŊŅ‹ в ĐŋĐžŅĐģĐĩĐ´ŅŅ‚Đ˛Đ¸ŅŅ…", "storage_template_migration": "ĐŸŅ€Đ¸ĐŧĐĩĐŊĐĩĐŊиĐĩ ŅˆĐ°ĐąĐģĐžĐŊа Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đ°", "storage_template_migration_description": "ĐŸŅ€Đ¸ĐŧĐĩĐŊŅĐĩŅ‚ Ņ‚ĐĩĐēŅƒŅ‰Đ¸Đš {template} Đē Ņ€Đ°ĐŊĐĩĐĩ ĐˇĐ°ĐŗŅ€ŅƒĐļĐĩĐŊĐŊŅ‹Đŧ ĐžĐąŅŠĐĩĐēŅ‚Đ°Đŧ", - "storage_template_migration_info": "Đ Đ°ŅŅˆĐ¸Ņ€ĐĩĐŊĐ¸Ņ Ņ„Đ°ĐšĐģОв Đ˛ŅĐĩĐŗĐ´Đ° ĐąŅƒĐ´ŅƒŅ‚ ŅĐžŅ…Ņ€Đ°ĐŊŅŅ‚ŅŒŅŅ в ĐŊиĐļĐŊĐĩĐŧ Ņ€ĐĩĐŗĐ¸ŅŅ‚Ņ€Đĩ. ИСĐŧĐĩĐŊĐĩĐŊĐ¸Ņ в ŅˆĐ°ĐąĐģĐžĐŊĐĩ ĐąŅƒĐ´ŅƒŅ‚ ĐŋŅ€Đ¸ĐŧĐĩĐŊŅŅ‚ŅŒŅŅ Ņ‚ĐžĐģҌĐēĐž Đē ĐŊĐžĐ˛Ņ‹Đŧ Ņ€ĐĩŅŅƒŅ€ŅĐ°Đŧ. Đ§Ņ‚ĐžĐąŅ‹ ĐŋŅ€Đ¸ĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ŅˆĐ°ĐąĐģĐžĐŊ Đē Ņ€Đ°ĐŊĐĩĐĩ ĐˇĐ°ĐŗŅ€ŅƒĐļĐĩĐŊĐŊŅ‹Đŧ Ņ€ĐĩŅŅƒŅ€ŅĐ°Đŧ, СаĐŋŅƒŅŅ‚Đ¸Ņ‚Đĩ {job}.", - "storage_template_migration_job": "ЗадаĐŊиĐĩ ĐŋĐž ĐŋŅ€Đ¸ĐŧĐĩĐŊĐĩĐŊĐ¸ŅŽ ŅˆĐ°ĐąĐģĐžĐŊа Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đ°", + "storage_template_migration_info": "Đ Đ°ŅŅˆĐ¸Ņ€ĐĩĐŊĐ¸Ņ Ņ„Đ°ĐšĐģОв Đ˛ŅĐĩĐŗĐ´Đ° ĐąŅƒĐ´ŅƒŅ‚ ŅĐžŅ…Ņ€Đ°ĐŊŅŅ‚ŅŒŅŅ в ĐŊиĐļĐŊĐĩĐŧ Ņ€ĐĩĐŗĐ¸ŅŅ‚Ņ€Đĩ. ИСĐŧĐĩĐŊĐĩĐŊĐ¸Ņ в ŅˆĐ°ĐąĐģĐžĐŊĐĩ ĐąŅƒĐ´ŅƒŅ‚ ĐŋŅ€Đ¸ĐŧĐĩĐŊŅŅ‚ŅŒŅŅ Ņ‚ĐžĐģҌĐēĐž Đē ĐŊĐžĐ˛Ņ‹Đŧ ĐžĐąŅŠĐĩĐēŅ‚Đ°Đŧ. Đ§Ņ‚ĐžĐąŅ‹ ĐŋŅ€Đ¸ĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ŅˆĐ°ĐąĐģĐžĐŊ Đē Ņ€Đ°ĐŊĐĩĐĩ ĐˇĐ°ĐŗŅ€ŅƒĐļĐĩĐŊĐŊŅ‹Đŧ ĐžĐąŅŠĐĩĐēŅ‚Đ°Đŧ, СаĐŋŅƒŅŅ‚Đ¸Ņ‚Đĩ {job}.", + "storage_template_migration_job": "Đ—Đ°Đ´Đ°Ņ‡Đ° ĐŋĐž ĐŋŅ€Đ¸ĐŧĐĩĐŊĐĩĐŊĐ¸ŅŽ ŅˆĐ°ĐąĐģĐžĐŊа Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đ°", "storage_template_more_details": "ДĐģŅ ĐŋĐžĐģŅƒŅ‡ĐĩĐŊĐ¸Ņ Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊОК иĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Đ¸ Ой ŅŅ‚ĐžĐš Ņ„ŅƒĐŊĐēŅ†Đ¸Đ¸ ĐžĐąŅ€Đ°Ņ‚Đ¸Ņ‚ĐĩҁҌ Đē Ņ€Đ°ĐˇĐ´ĐĩĐģаĐŧ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸Đ¸ ШайĐģĐžĐŊ Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đ° и ĐĄŅ‚Ņ€ŅƒĐēŅ‚ŅƒŅ€Đ° Ņ…Ņ€Đ°ĐŊĐĩĐŊĐ¸Ņ Ņ„Đ°ĐšĐģОв", "storage_template_onboarding_description_v2": "Đ•ŅĐģи ŅŅ‚Đ° Ņ„ŅƒĐŊĐēŅ†Đ¸Ņ вĐēĐģŅŽŅ‡ĐĩĐŊа, ĐžĐŊа Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐĩҁĐēи ĐžŅ€ĐŗĐ°ĐŊĐ¸ĐˇŅƒĐĩŅ‚ Ņ„Đ°ĐšĐģŅ‹ ĐŊа ĐžŅĐŊОвĐĩ СадаĐŊĐŊĐžĐŗĐž ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģĐĩĐŧ ŅˆĐ°ĐąĐģĐžĐŊа. ДĐģŅ ĐŋĐžĐģŅƒŅ‡ĐĩĐŊĐ¸Ņ Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊОК иĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Đ¸ ĐžĐąŅ€Đ°Ņ‚Đ¸Ņ‚ĐĩҁҌ Đē Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸Đ¸.", "storage_template_path_length": "ĐŸŅ€Đ¸ĐŧĐĩŅ€ĐŊŅ‹Đš ĐŋŅ€ĐĩĐ´ĐĩĐģ Đ´ĐģиĐŊŅ‹ ĐŋŅƒŅ‚Đ¸: {length, number}/{limit, number}", @@ -364,7 +373,7 @@ "user_cleanup_job": "ĐžŅ‡Đ¸ŅŅ‚Đēа ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ", "user_delete_delay": "АĐēĐēĐ°ŅƒĐŊŅ‚ и Ņ„Đ°ĐšĐģŅ‹ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ {user} ĐąŅƒĐ´ŅƒŅ‚ ĐžŅ‚ĐģĐžĐļĐĩĐŊŅ‹ Đ´Đž ĐžĐēĐžĐŊŅ‡Đ°Ņ‚ĐĩĐģҌĐŊĐžĐŗĐž ŅƒĐ´Đ°ĐģĐĩĐŊĐ¸Ņ ҇ĐĩŅ€ĐĩС {delay, plural, one {# Đ´ĐĩĐŊҌ} few {# Đ´ĐŊŅ} many {# Đ´ĐŊĐĩĐš} other {# Đ´ĐŊŅ}}.", "user_delete_delay_settings": "ĐžŅ‚ĐģĐžĐļĐĩĐŊĐŊĐžĐĩ ŅƒĐ´Đ°ĐģĐĩĐŊиĐĩ", - "user_delete_delay_settings_description": "ĐĄŅ€ĐžĐē в Đ´ĐŊŅŅ…, ĐŋĐž Đ¸ŅŅ‚Đĩ҇ĐĩĐŊиĐĩ ĐēĐžŅ‚ĐžŅ€ĐžĐŗĐž ĐŋŅ€ĐžĐ¸ŅŅ…ĐžĐ´Đ¸Ņ‚ ĐžĐēĐžĐŊŅ‡Đ°Ņ‚ĐĩĐģҌĐŊĐžĐĩ ŅƒĐ´Đ°ĐģĐĩĐŊиĐĩ ŅƒŅ‡ĐĩŅ‚ĐŊОК СаĐŋĐ¸ŅĐ¸ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ и ĐĩĐŗĐž Ņ€ĐĩŅŅƒŅ€ŅĐžĐ˛. Đ—Đ°Đ´Đ°Ņ‡Đ° ĐŋĐž ŅƒĐ´Đ°ĐģĐĩĐŊĐ¸ŅŽ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģĐĩĐš Đ˛Ņ‹ĐŋĐžĐģĐŊŅĐĩŅ‚ŅŅ в ĐŋĐžĐģĐŊĐžŅ‡ŅŒ. ИСĐŧĐĩĐŊĐĩĐŊĐ¸Ņ ŅŅ‚ĐžĐš ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēи ĐąŅƒĐ´ŅƒŅ‚ ŅƒŅ‡Ņ‚ĐĩĐŊŅ‹ ĐŋŅ€Đ¸ ҁĐģĐĩĐ´ŅƒŅŽŅ‰ĐĩĐŧ СаĐŋ҃ҁĐēĐĩ ĐˇĐ°Đ´Đ°Ņ‡Đ¸.", + "user_delete_delay_settings_description": "ĐĄŅ€ĐžĐē в Đ´ĐŊŅŅ…, ĐŋĐž Đ¸ŅŅ‚Đĩ҇ĐĩĐŊии ĐēĐžŅ‚ĐžŅ€ĐžĐŗĐž ĐŋŅ€ĐžĐ¸ŅŅ…ĐžĐ´Đ¸Ņ‚ ĐžĐēĐžĐŊŅ‡Đ°Ņ‚ĐĩĐģҌĐŊĐžĐĩ ŅƒĐ´Đ°ĐģĐĩĐŊиĐĩ ŅƒŅ‡Ņ‘Ņ‚ĐŊОК СаĐŋĐ¸ŅĐ¸ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ и Đ˛ŅĐĩŅ… ĐĩĐŗĐž ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛. Đ—Đ°Đ´Đ°Ņ‡Đ° ĐŋĐž ŅƒĐ´Đ°ĐģĐĩĐŊĐ¸ŅŽ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģĐĩĐš Đ˛Ņ‹ĐŋĐžĐģĐŊŅĐĩŅ‚ŅŅ в ĐŋĐžĐģĐŊĐžŅ‡ŅŒ. ИСĐŧĐĩĐŊĐĩĐŊиĐĩ ŅŅ‚ĐžĐš ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēи ĐąŅƒĐ´ĐĩŅ‚ ŅƒŅ‡Ņ‚ĐĩĐŊĐž ĐŋŅ€Đ¸ ҁĐģĐĩĐ´ŅƒŅŽŅ‰ĐĩĐŧ СаĐŋ҃ҁĐēĐĩ ĐˇĐ°Đ´Đ°Ņ‡Đ¸.", "user_delete_immediately": "АĐēĐēĐ°ŅƒĐŊŅ‚ и Ņ„Đ°ĐšĐģŅ‹ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ {user} ĐąŅƒĐ´ŅƒŅ‚ ĐŊĐĩĐŧĐĩĐ´ĐģĐĩĐŊĐŊĐž ĐŋĐžŅŅ‚Đ°Đ˛ĐģĐĩĐŊŅ‹ в ĐžŅ‡ĐĩŅ€ĐĩĐ´ŅŒ Đ´ĐģŅ ĐžĐēĐžĐŊŅ‡Đ°Ņ‚ĐĩĐģҌĐŊĐžĐŗĐž ŅƒĐ´Đ°ĐģĐĩĐŊĐ¸Ņ.", "user_delete_immediately_checkbox": "ПоĐŧĐĩŅŅ‚Đ¸Ņ‚ŅŒ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ и ĐĩĐŗĐž Ņ„Đ°ĐšĐģŅ‹ в ĐžŅ‡ĐĩŅ€ĐĩĐ´ŅŒ Đ´ĐģŅ ĐŊĐĩĐŧĐĩĐ´ĐģĐĩĐŊĐŊĐžĐŗĐž ŅƒĐ´Đ°ĐģĐĩĐŊĐ¸Ņ", "user_details": "ДаĐŊĐŊŅ‹Đĩ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ", @@ -387,8 +396,6 @@ "admin_password": "ĐŸĐ°Ņ€ĐžĐģҌ адĐŧиĐŊĐ¸ŅŅ‚Ņ€Đ°Ņ‚ĐžŅ€Đ°", "administration": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ҁĐĩŅ€Đ˛ĐĩŅ€ĐžĐŧ", "advanced": "Đ Đ°ŅŅˆĐ¸Ņ€ĐĩĐŊĐŊŅ‹Đĩ", - "advanced_settings_beta_timeline_subtitle": "ПоĐŋŅ€ĐžĐąŅƒĐšŅ‚Đĩ ĐŊĐžĐ˛Ņ‹Đš Ņ„ŅƒĐŊĐēŅ†Đ¸ĐžĐŊаĐģ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸Ņ", - "advanced_settings_beta_timeline_title": "БĐĩŅ‚Đ°-вĐĩŅ€ŅĐ¸Ņ Đ˛Ņ€ĐĩĐŧĐĩĐŊĐŊОК ҈ĐēаĐģŅ‹", "advanced_settings_enable_alternate_media_filter_subtitle": "ĐŸĐžĐ´ĐąĐžŅ€ ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛ Đ´ĐģŅ ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Đ¸ ĐŊа ĐžŅĐŊОвĐĩ аĐģŅŒŅ‚ĐĩŅ€ĐŊĐ°Ņ‚Đ¸Đ˛ĐŊҋ҅ ĐēŅ€Đ¸Ņ‚ĐĩŅ€Đ¸Đĩв. ĐŸŅ€ĐžĐąŅƒĐšŅ‚Đĩ вĐēĐģŅŽŅ‡Đ°Ņ‚ŅŒ Ņ‚ĐžĐģҌĐēĐž в Ņ‚ĐžĐŧ ҁĐģŅƒŅ‡Đ°Đĩ, ĐĩҁĐģи в ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊии ĐĩŅŅ‚ŅŒ ĐŋŅ€ĐžĐąĐģĐĩĐŧŅ‹ ҁ ОйĐŊĐ°Ņ€ŅƒĐļĐĩĐŊиĐĩĐŧ Đ˛ŅĐĩŅ… аĐģŅŒĐąĐžĐŧОв.", "advanced_settings_enable_alternate_media_filter_title": "[ЭКСПЕРИМЕНĐĸАЛĐŦНО] Đ˜ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°ĐŊиĐĩ аĐģŅŒŅ‚ĐĩŅ€ĐŊĐ°Ņ‚Đ¸Đ˛ĐŊĐžĐŗĐž ҁĐŋĐžŅĐžĐąĐ° ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Đ¸ аĐģŅŒĐąĐžĐŧОв ĐŊа ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đĩ", "advanced_settings_log_level_title": "ĐŖŅ€ĐžĐ˛ĐĩĐŊҌ ĐģĐžĐŗĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ: {level}", @@ -396,20 +403,20 @@ "advanced_settings_prefer_remote_title": "ĐŸŅ€ĐĩĐ´ĐŋĐžŅ‡Đ¸Ņ‚Đ°Ņ‚ŅŒ Ņ„ĐžŅ‚Đž ĐŊа ҁĐĩŅ€Đ˛ĐĩŅ€Đĩ", "advanced_settings_proxy_headers_subtitle": "ОĐŋŅ€ĐĩĐ´ĐĩĐģĐ¸Ņ‚Đĩ ĐˇĐ°ĐŗĐžĐģОвĐēи ĐŋŅ€ĐžĐēŅĐ¸-ҁĐĩŅ€Đ˛ĐĩŅ€Đ°, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ Immich Đ´ĐžĐģĐļĐĩĐŊ ĐžŅ‚ĐŋŅ€Đ°Đ˛ĐģŅŅ‚ŅŒ ҁ ĐēаĐļĐ´Ņ‹Đŧ ҁĐĩŅ‚ĐĩĐ˛Ņ‹Đŧ СаĐŋŅ€ĐžŅĐžĐŧ", "advanced_settings_proxy_headers_title": "Đ—Đ°ĐŗĐžĐģОвĐēи ĐŋŅ€ĐžĐēŅĐ¸", - "advanced_settings_readonly_mode_subtitle": "ВĐēĐģŅŽŅ‡Đ°ĐĩŅ‚ Ņ€ĐĩĐļиĐŧ ÂĢŅ‚ĐžĐģҌĐēĐž ĐŋŅ€ĐžŅĐŧĐžŅ‚Ņ€Âģ, в ĐēĐžŅ‚ĐžŅ€ĐžĐŧ ĐŧĐžĐļĐŊĐž Ņ‚ĐžĐģҌĐēĐž ĐŋŅ€ĐžŅĐŧĐ°Ņ‚Ņ€Đ¸Đ˛Đ°Ņ‚ŅŒ ĐžĐąŅŠĐĩĐē҂ҋ. Đ¤ŅƒĐŊĐēŅ†Đ¸Đ¸ Đ˛Ņ‹ĐąĐžŅ€Đ° ĐŊĐĩҁĐēĐžĐģҌĐēĐ¸Ņ… ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛, ĐŋŅƒĐąĐģиĐēĐ°Ņ†Đ¸Đ¸, Ņ‚Ņ€Đ°ĐŊҁĐģŅŅ†Đ¸Đ¸ и ŅƒĐ´Đ°ĐģĐĩĐŊĐ¸Ņ ĐąŅƒĐ´ŅƒŅ‚ ĐŊĐĩĐ´ĐžŅŅ‚ŅƒĐŋĐŊŅ‹. ВĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ/ĐžŅ‚ĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ Ņ€ĐĩĐļиĐŧ ÂĢŅ‚ĐžĐģҌĐēĐž ĐŋŅ€ĐžŅĐŧĐžŅ‚Ņ€Âģ ĐŧĐžĐļĐŊĐž ҁ ĐŋĐžĐŧĐžŅ‰ŅŒŅŽ СĐŊĐ°Ņ‡Đēа Đ°Đ˛Đ°Ņ‚Đ°Ņ€Đ° ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ ĐŊа ĐŗĐģавĐŊĐžĐŧ ŅĐēŅ€Đ°ĐŊĐĩ.", + "advanced_settings_readonly_mode_subtitle": "ВĐēĐģŅŽŅ‡Đ°ĐĩŅ‚ Ņ€ĐĩĐļиĐŧ, в ĐēĐžŅ‚ĐžŅ€ĐžĐŧ ĐŧĐžĐļĐŊĐž Ņ‚ĐžĐģҌĐēĐž ĐŋŅ€ĐžŅĐŧĐ°Ņ‚Ņ€Đ¸Đ˛Đ°Ņ‚ŅŒ ĐžĐąŅŠĐĩĐē҂ҋ. Đ¤ŅƒĐŊĐēŅ†Đ¸Đ¸ Đ˛Ņ‹ĐąĐžŅ€Đ° ĐŊĐĩҁĐēĐžĐģҌĐēĐ¸Ņ… ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛, ĐŋŅƒĐąĐģиĐēĐ°Ņ†Đ¸Đ¸, Ņ‚Ņ€Đ°ĐŊҁĐģŅŅ†Đ¸Đ¸ и ŅƒĐ´Đ°ĐģĐĩĐŊĐ¸Ņ ĐąŅƒĐ´ŅƒŅ‚ ĐŊĐĩĐ´ĐžŅŅ‚ŅƒĐŋĐŊŅ‹. ВĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ/ĐžŅ‚ĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ ŅŅ‚ĐžŅ‚ Ņ€ĐĩĐļиĐŧ ĐŧĐžĐļĐŊĐž ŅƒĐ´ĐĩŅ€ĐļĐ¸Đ˛Đ°Ņ СĐŊĐ°Ņ‡ĐžĐē Đ°Đ˛Đ°Ņ‚Đ°Ņ€Đ° ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ ĐŊа ĐŗĐģавĐŊĐžĐŧ ŅĐēŅ€Đ°ĐŊĐĩ.", "advanced_settings_readonly_mode_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": "Đ Đĩ҈ĐĩĐŊиĐĩ ĐŋŅ€ĐžĐąĐģĐĩĐŧ", + "advanced_settings_troubleshooting_subtitle": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ Ņ€Đ°ŅŅˆĐ¸Ņ€ĐĩĐŊĐŊŅ‹Đĩ вОСĐŧĐžĐļĐŊĐžŅŅ‚Đ¸ Đ´ĐģŅ Đ´Đ¸Đ°ĐŗĐŊĐžŅŅ‚Đ¸Đēи и Ņ€Đĩ҈ĐĩĐŊĐ¸Ņ ĐŋŅ€ĐžĐąĐģĐĩĐŧ", + "advanced_settings_troubleshooting_title": "Đ ĐĩĐļиĐŧ Đ´Đ¸Đ°ĐŗĐŊĐžŅŅ‚Đ¸Đēи", "age_months": "{months, plural, one {# ĐŧĐĩŅŅŅ†} many {# ĐŧĐĩŅŅŅ†Đĩв} other {# ĐŧĐĩŅŅŅ†Đ°}}", "age_year_months": "1 ĐŗĐžĐ´ {months, plural, one {# ĐŧĐĩŅŅŅ†} many {# ĐŧĐĩŅŅŅ†Đĩв} other {# ĐŧĐĩŅŅŅ†Đ°}}", "age_years": "{years, plural, one {# ĐŗĐžĐ´} many {# ĐģĐĩŅ‚} other {# ĐŗĐžĐ´Đ°}}", "album_added": "АĐģŅŒĐąĐžĐŧ дОйавĐģĐĩĐŊ", - "album_added_notification_setting_description": "ПоĐģŅƒŅ‡Đ°Ņ‚ŅŒ ŅƒĐ˛ĐĩĐ´ĐžĐŧĐģĐĩĐŊиĐĩ ĐŋĐž ŅĐģĐĩĐēŅ‚Ņ€ĐžĐŊĐŊОК ĐŋĐžŅ‡Ņ‚Đĩ, ĐēĐžĐŗĐ´Đ° Đ˛Ņ‹ дОйавĐģĐĩĐŊŅ‹ Đē ĐžĐąŅ‰ĐĩĐŧ҃ аĐģŅŒĐąĐžĐŧ҃", + "album_added_notification_setting_description": "ПоĐģŅƒŅ‡Đ°Ņ‚ŅŒ ŅƒĐ˛ĐĩĐ´ĐžĐŧĐģĐĩĐŊиĐĩ ĐŋĐž ŅĐģĐĩĐēŅ‚Ņ€ĐžĐŊĐŊОК ĐŋĐžŅ‡Ņ‚Đĩ, ĐēĐžĐŗĐ´Đ° ваĐŧ ĐŋŅ€ĐĩĐ´ĐžŅŅ‚Đ°Đ˛Đ¸Đģи Đ´ĐžŅŅ‚ŅƒĐŋ в ĐžĐąŅ‰Đ¸Đš аĐģŅŒĐąĐžĐŧ", "album_cover_updated": "ОбĐģĐžĐļĐēа аĐģŅŒĐąĐžĐŧа ОйĐŊОвĐģĐĩĐŊа", "album_delete_confirmation": "Đ’Ņ‹ ŅƒĐ˛ĐĩŅ€ĐĩĐŊŅ‹, Ņ‡Ņ‚Đž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ŅƒĐ´Đ°ĐģĐ¸Ņ‚ŅŒ аĐģŅŒĐąĐžĐŧ {album}?", "album_delete_confirmation_description": "Đ•ŅĐģи аĐģŅŒĐąĐžĐŧ ĐąŅ‹Đģ ĐžĐąŅ‰Đ¸Đŧ, Đ´Ņ€ŅƒĐŗĐ¸Đĩ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģи йОĐģҌ҈Đĩ ĐŊĐĩ ҁĐŧĐžĐŗŅƒŅ‚ ĐŋĐžĐģŅƒŅ‡Đ¸Ņ‚ŅŒ Đē ĐŊĐĩĐŧ҃ Đ´ĐžŅŅ‚ŅƒĐŋ.", @@ -425,8 +432,9 @@ "album_remove_user_confirmation": "Đ’Ņ‹ ŅƒĐ˛ĐĩŅ€ĐĩĐŊŅ‹, Ņ‡Ņ‚Đž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ŅƒĐ´Đ°ĐģĐ¸Ņ‚ŅŒ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ {user}?", "album_search_not_found": "НĐĩ ĐŊаКдĐĩĐŊĐž аĐģŅŒĐąĐžĐŧОв ĐŋĐž Đ˛Đ°ŅˆĐĩĐŧ҃ СаĐŋŅ€ĐžŅŅƒ", "album_share_no_users": "НĐĩŅ‚ Đ´ĐžŅŅ‚ŅƒĐŋĐŊҋ҅ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģĐĩĐš, ҁ ĐēĐžŅ‚ĐžŅ€Ņ‹Đŧи ĐŧĐžĐļĐŊĐž ĐŋОдĐĩĐģĐ¸Ņ‚ŅŒŅŅ аĐģŅŒĐąĐžĐŧĐžĐŧ.", + "album_summary": "ИĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Ņ Ой аĐģŅŒĐąĐžĐŧĐĩ", "album_updated": "АĐģŅŒĐąĐžĐŧ ОйĐŊОвĐģŅ‘ĐŊ", - "album_updated_setting_description": "ПоĐģŅƒŅ‡Đ°Ņ‚ŅŒ ŅƒĐ˛ĐĩĐ´ĐžĐŧĐģĐĩĐŊиĐĩ ĐŋĐž ŅĐģĐĩĐēŅ‚Ņ€ĐžĐŊĐŊОК ĐŋĐžŅ‡Ņ‚Đĩ ĐŋŅ€Đ¸ дОйавĐģĐĩĐŊии ĐŊĐžĐ˛Ņ‹Ņ… Ņ€ĐĩŅŅƒŅ€ŅĐžĐ˛ в ĐžĐąŅ‰Đ¸Đš аĐģŅŒĐąĐžĐŧ", + "album_updated_setting_description": "ПоĐģŅƒŅ‡Đ°Ņ‚ŅŒ ŅƒĐ˛ĐĩĐ´ĐžĐŧĐģĐĩĐŊиĐĩ ĐŋĐž ŅĐģĐĩĐēŅ‚Ņ€ĐžĐŊĐŊОК ĐŋĐžŅ‡Ņ‚Đĩ ĐŋŅ€Đ¸ дОйавĐģĐĩĐŊии ĐŊĐžĐ˛Ņ‹Ņ… ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛ в ĐžĐąŅ‰Đ¸Đš аĐģŅŒĐąĐžĐŧ", "album_user_left": "Đ’Ņ‹ ĐŋĐžĐēиĐŊ҃Đģи {album}", "album_user_removed": "ПоĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģҌ {user} ŅƒĐ´Đ°ĐģĐĩĐŊ", "album_viewer_appbar_delete_confirm": "Đ’Ņ‹ ŅƒĐ˛ĐĩŅ€ĐĩĐŊŅ‹, Ņ‡Ņ‚Đž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ŅƒĐ´Đ°ĐģĐ¸Ņ‚ŅŒ аĐģŅŒĐąĐžĐŧ иС ŅĐ˛ĐžĐĩĐš ŅƒŅ‡ĐĩŅ‚ĐŊОК СаĐŋĐ¸ŅĐ¸?", @@ -448,7 +456,7 @@ "all_albums": "Đ’ŅĐĩ аĐģŅŒĐąĐžĐŧŅ‹", "all_people": "Đ’ŅĐĩ ĐģŅŽĐ´Đ¸", "all_videos": "Đ’ŅĐĩ видĐĩĐž", - "allow_dark_mode": "Đ Đ°ĐˇŅ€ĐĩŅˆĐ¸Ņ‚ŅŒ Ņ‚ĐĩĐŧĐŊŅ‹Đš Ņ€ĐĩĐļиĐŧ", + "allow_dark_mode": "Đ Đ°ĐˇŅ€ĐĩŅˆĐ¸Ņ‚ŅŒ ҂ґĐŧĐŊŅ‹Đš Ņ€ĐĩĐļиĐŧ", "allow_edits": "Đ Đ°ĐˇŅ€ĐĩŅˆĐ¸Ņ‚ŅŒ Ņ€ĐĩдаĐēŅ‚Đ¸Ņ€ĐžĐ˛Đ°ĐŊиĐĩ", "allow_public_user_to_download": "Đ Đ°ĐˇŅ€ĐĩŅˆĐ¸Ņ‚ŅŒ ҁĐēĐ°Ņ‡Đ¸Đ˛Đ°ĐŊиĐĩ", "allow_public_user_to_upload": "Đ Đ°ĐˇŅ€ĐĩŅˆĐ¸Ņ‚ŅŒ дОйавĐģĐĩĐŊиĐĩ Ņ„Đ°ĐšĐģОв", @@ -496,10 +504,12 @@ "asset_restored_successfully": "ĐžĐąŅŠĐĩĐēŅ‚ ҃ҁĐŋĐĩ҈ĐŊĐž Đ˛ĐžŅŅŅ‚Đ°ĐŊОвĐģĐĩĐŊ", "asset_skipped": "ĐŸŅ€ĐžĐŋŅƒŅ‰ĐĩĐŊĐž", "asset_skipped_in_trash": "В ĐēĐžŅ€ĐˇĐ¸ĐŊĐĩ", + "asset_trashed": "ĐžĐąŅŠĐĩĐēŅ‚ ŅƒĐ´Đ°ĐģŅ‘ĐŊ", + "asset_troubleshoot": "ДаĐŊĐŊŅ‹Đĩ Đ´ĐģŅ Đ´Đ¸Đ°ĐŗĐŊĐžŅŅ‚Đ¸Đēи", "asset_uploaded": "Đ—Đ°ĐŗŅ€ŅƒĐļĐĩĐŊĐž", "asset_uploading": "Đ—Đ°ĐŗŅ€ŅƒĐˇĐēаâ€Ļ", - "asset_viewer_settings_subtitle": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēа ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€ĐžĐ˛ ĐžŅ‚ĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ", - "asset_viewer_settings_title": "ĐŸŅ€ĐžŅĐŧĐžŅ‚Ņ€ Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиК", + "asset_viewer_settings_subtitle": "ĐŸĐ°Ņ€Đ°ĐŧĐĩ҂Ҁҋ ĐžŅ‚ĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ", + "asset_viewer_settings_title": "ĐŸŅ€ĐžŅĐŧĐžŅ‚Ņ€ ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛", "assets": "ĐžĐąŅŠĐĩĐē҂ҋ", "assets_added_count": "{count, plural, one {ДобавĐģĐĩĐŊ # ĐžĐąŅŠĐĩĐēŅ‚} many {ДобавĐģĐĩĐŊĐž # ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛} other {ДобавĐģĐĩĐŊĐž # ĐžĐąŅŠĐĩĐēŅ‚Đ°}}", "assets_added_to_album_count": "В аĐģŅŒĐąĐžĐŧ {count, plural, one {дОйавĐģĐĩĐŊ # ĐžĐąŅŠĐĩĐēŅ‚} many {дОйавĐģĐĩĐŊĐž # ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛} other {дОйавĐģĐĩĐŊĐž # ĐžĐąŅŠĐĩĐēŅ‚Đ°}}", @@ -529,24 +539,27 @@ "autoplay_slideshow": "ĐĐ˛Ņ‚ĐžĐ˛ĐžŅĐŋŅ€ĐžĐ¸ĐˇĐ˛ĐĩĐ´ĐĩĐŊиĐĩ ҁĐģĐ°ĐšĐ´ŅˆĐžŅƒ", "back": "Назад", "back_close_deselect": "Назад, СаĐēŅ€Ņ‹Ņ‚ŅŒ иĐģи ĐžŅ‚ĐŧĐĩĐŊĐ¸Ņ‚ŅŒ Đ˛Ņ‹ĐąĐžŅ€", + "background_backup_running_error": "Đ’Ņ‹ĐŋĐžĐģĐŊŅĐĩŅ‚ŅŅ Ņ„ĐžĐŊОвОĐĩ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐĩ ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊиĐĩ, СаĐŋ҃ҁĐē Đ˛Ņ€ŅƒŅ‡ĐŊŅƒŅŽ ĐŋĐžĐēа ĐŊĐĩвОСĐŧĐžĐļĐĩĐŊ", "background_location_permission": "Đ”ĐžŅŅ‚ŅƒĐŋ Đē ĐŧĐĩŅŅ‚ĐžĐŋĐžĐģĐžĐļĐĩĐŊĐ¸ŅŽ в Ņ„ĐžĐŊĐĩ", "background_location_permission_content": "Đ§Ņ‚ĐžĐąŅ‹ ŅŅ‡Đ¸Ņ‚Ņ‹Đ˛Đ°Ņ‚ŅŒ иĐŧŅ Wi-Fi ҁĐĩŅ‚Đ¸ в Ņ„ĐžĐŊĐĩ, ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸ŅŽ *Đ˛ŅĐĩĐŗĐ´Đ°* ĐŊĐĩĐžĐąŅ…ĐžĐ´Đ¸Đŧ Đ´ĐžŅŅ‚ŅƒĐŋ Đē Ņ‚ĐžŅ‡ĐŊĐžĐŧ҃ ĐŧĐĩŅŅ‚ĐžĐŋĐžĐģĐžĐļĐĩĐŊĐ¸ŅŽ ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đ°", + "background_options": "Đ’Ņ‹ĐŋĐžĐģĐŊĐĩĐŊиĐĩ Ņ„ĐžĐŊĐžĐ˛Ņ‹Ņ… ĐˇĐ°Đ´Đ°Ņ‡", "backup": "Đ ĐĩСĐĩŅ€Đ˛ĐŊĐžĐĩ ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊиĐĩ", "backup_album_selection_page_albums_device": "АĐģŅŒĐąĐžĐŧŅ‹ ĐŊа ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đĩ ({count})", "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_selection_info": "Đ’Ņ‹ĐąŅ€Đ°ĐŊĐŊŅ‹Đĩ аĐģŅŒĐąĐžĐŧŅ‹", "backup_album_selection_page_total_assets": "Đ’ŅĐĩĐŗĐž ҃ĐŊиĐēаĐģҌĐŊҋ҅ ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛", + "backup_albums_sync": "ХиĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Ņ аĐģŅŒĐąĐžĐŧОв", "backup_all": "Đ’ŅĐĩ", "backup_background_service_backup_failed_message": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ Đ˛Ņ‹ĐŋĐžĐģĐŊĐ¸Ņ‚ŅŒ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐĩ ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊиĐĩ. ĐŸĐžĐ˛Ņ‚ĐžŅ€ĐŊĐ°Ņ ĐŋĐžĐŋҋ҂Đēаâ€Ļ", "backup_background_service_connection_failed_message": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ ĐŋОдĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒŅŅ Đē ҁĐĩŅ€Đ˛ĐĩŅ€Ņƒ. ĐŸĐžĐ˛Ņ‚ĐžŅ€ĐŊĐ°Ņ ĐŋĐžĐŋҋ҂Đēаâ€Ļ", "backup_background_service_current_upload_notification": "Đ—Đ°ĐŗŅ€ŅƒĐļаĐĩŅ‚ŅŅ {filename}", "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": "ĐžŅˆĐ¸ĐąĐēа ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēи {filename}", - "backup_controller_page_albums": "Đ ĐĩСĐĩŅ€Đ˛ĐŊĐžĐĩ ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊиĐĩ аĐģŅŒĐąĐžĐŧОв", + "backup_controller_page_albums": "АĐģŅŒĐąĐžĐŧŅ‹", "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": "ПĐĩŅ€ĐĩĐšŅ‚Đ¸ в ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēи", @@ -556,15 +569,15 @@ "backup_controller_page_background_battery_info_title": "ОĐŋŅ‚Đ¸ĐŧĐ¸ĐˇĐ°Ņ†Đ¸Ņ ĐąĐ°Ņ‚Đ°Ņ€Đĩи", "backup_controller_page_background_charging": "ĐĸĐžĐģҌĐēĐž вО Đ˛Ņ€ĐĩĐŧŅ ĐˇĐ°Ņ€ŅĐ´Đēи", "backup_controller_page_background_configure_error": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ ĐŊĐ°ŅŅ‚Ņ€ĐžĐ¸Ņ‚ŅŒ Ņ„ĐžĐŊĐžĐ˛ŅƒŅŽ ҁĐģ҃ĐļĐąŅƒ", - "backup_controller_page_background_delay": "ĐžŅ‚ĐģĐžĐļĐ¸Ņ‚ŅŒ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐĩ ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊиĐĩ ĐŊĐžĐ˛Ņ‹Ņ… ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛: {duration}", + "backup_controller_page_background_delay": "ЗадĐĩŅ€ĐļĐēа ĐŋĐĩŅ€ĐĩĐ´ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēОК ĐŊĐžĐ˛Ņ‹Ņ… ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛: {duration}", "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": "Đ—Đ°ĐŗŅ€ŅƒĐļĐĩĐŊĐž", + "backup_controller_page_backup_selected": "Đ’Ņ‹ĐąŅ€Đ°ĐŊŅ‹: ", "backup_controller_page_backup_sub": "Đ—Đ°ĐŗŅ€ŅƒĐļĐĩĐŊĐŊŅ‹Đĩ Ņ„ĐžŅ‚Đž и видĐĩĐž", "backup_controller_page_created": "ХОСдаĐŊĐž: {date}", "backup_controller_page_desc_backup": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚Đĩ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐĩ ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊиĐĩ в аĐēŅ‚Đ¸Đ˛ĐŊĐžĐŧ Ņ€ĐĩĐļиĐŧĐĩ, Ņ‡Ņ‚ĐžĐąŅ‹ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐĩҁĐēи ĐˇĐ°ĐŗŅ€ŅƒĐļĐ°Ņ‚ŅŒ ĐŊĐžĐ˛Ņ‹Đĩ ĐžĐąŅŠĐĩĐē҂ҋ ĐŋŅ€Đ¸ ĐžŅ‚ĐēŅ€Ņ‹Ņ‚Đ¸Đ¸ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸Ņ.", @@ -573,7 +586,7 @@ "backup_controller_page_filename": "ИĐŧŅ Ņ„Đ°ĐšĐģа: {filename} [{size}]", "backup_controller_page_id": "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": "ĐĨŅ€Đ°ĐŊиĐģĐ¸Ņ‰Đĩ ĐŊа ҁĐĩŅ€Đ˛ĐĩŅ€Đĩ", @@ -587,6 +600,7 @@ "backup_controller_page_turn_on": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ", "backup_controller_page_uploading_file_info": "ИĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Ņ Đž ĐˇĐ°ĐŗŅ€ŅƒĐļаĐĩĐŧĐžĐŧ Ņ„Đ°ĐšĐģĐĩ", "backup_err_only_album": "НĐĩвОСĐŧĐžĐļĐŊĐž ŅƒĐ´Đ°ĐģĐ¸Ņ‚ŅŒ ĐĩдиĐŊŅŅ‚Đ˛ĐĩĐŊĐŊŅ‹Đš аĐģŅŒĐąĐžĐŧ", + "backup_error_sync_failed": "ХйОК ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Đ¸. НĐĩвОСĐŧĐžĐļĐŊĐž Đ˛Ņ‹ĐŋĐžĐģĐŊĐ¸Ņ‚ŅŒ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐĩ ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊиĐĩ.", "backup_info_card_assets": "ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛", "backup_manual_cancelled": "ĐžŅ‚ĐŧĐĩĐŊĐĩĐŊĐž", "backup_manual_in_progress": "Đ—Đ°ĐŗŅ€ŅƒĐˇĐēа в ĐŋŅ€ĐžŅ†ĐĩҁҁĐĩ. ПоĐŋŅ€ĐžĐąŅƒĐšŅ‚Đĩ ĐŋОСĐļĐĩ", @@ -597,8 +611,6 @@ "backup_setting_subtitle": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēа аĐēŅ‚Đ¸Đ˛ĐŊĐžĐŗĐž и Ņ„ĐžĐŊĐžĐ˛ĐžĐŗĐž Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ", "backup_settings_subtitle": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēа ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēи ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛", "backward": "Назад", - "beta_sync": "ĐĄŅ‚Đ°Ņ‚ŅƒŅ ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Đ¸", - "beta_sync_subtitle": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ĐŊОвОК ŅĐ¸ŅŅ‚ĐĩĐŧОК ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Đ¸", "biometric_auth_enabled": "БиоĐŧĐĩŅ‚Ņ€Đ¸Ņ‡ĐĩҁĐēĐ°Ņ Đ°ŅƒŅ‚ĐĩĐŊŅ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ†Đ¸Ņ вĐēĐģŅŽŅ‡ĐĩĐŊа", "biometric_locked_out": "ВаĐŧ СаĐēҀҋ҂ Đ´ĐžŅŅ‚ŅƒĐŋ Đē йиОĐŧĐĩŅ‚Ņ€Đ¸Ņ‡ĐĩҁĐēОК Đ°ŅƒŅ‚ĐĩĐŊŅ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ†Đ¸Đ¸", "biometric_no_options": "БиоĐŧĐĩŅ‚Ņ€Đ¸Ņ‡ĐĩҁĐēĐ°Ņ Đ°ŅƒŅ‚ĐĩĐŊŅ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ†Đ¸Ņ ĐŊĐĩĐ´ĐžŅŅ‚ŅƒĐŋĐŊа", @@ -637,8 +649,8 @@ "cannot_merge_people": "НĐĩвОСĐŧĐžĐļĐŊĐž ĐžĐąŅŠĐĩдиĐŊĐ¸Ņ‚ŅŒ ĐģŅŽĐ´ĐĩĐš", "cannot_undo_this_action": "Đ­Ņ‚Đž Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Đĩ ĐŊĐĩĐģŅŒĐˇŅ ĐžŅ‚ĐŧĐĩĐŊĐ¸Ņ‚ŅŒ!", "cannot_update_the_description": "НĐĩвОСĐŧĐžĐļĐŊĐž ОйĐŊĐžĐ˛Đ¸Ņ‚ŅŒ ĐžĐŋĐ¸ŅĐ°ĐŊиĐĩ", - "cast": "ĐĸŅ€Đ°ĐŊҁĐģĐ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ", - "cast_description": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēа Đ´ĐžŅŅ‚ŅƒĐŋĐŊҋ҅ ҆ĐĩĐģĐĩĐš Ņ‚Ņ€Đ°ĐŊҁĐģŅŅ†Đ¸Đ¸", + "cast": "ĐĸŅ€Đ°ĐŊҁĐģŅŅ†Đ¸Ņ", + "cast_description": "Đ’Ņ‹ĐąĐžŅ€ Đ´ĐžŅŅ‚ŅƒĐŋĐŊҋ҅ ҁĐŋĐžŅĐžĐąĐžĐ˛ Đ´ĐģŅ Ņ‚Ņ€Đ°ĐŊҁĐģŅŅ†Đ¸Đ¸", "change_date": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ Đ´Đ°Ņ‚Ņƒ", "change_description": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ĐžĐŋĐ¸ŅĐ°ĐŊиĐĩ", "change_display_order": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ĐŋĐžŅ€ŅĐ´ĐžĐē ĐžŅ‚ĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ", @@ -656,6 +668,8 @@ "change_pin_code": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ PIN-ĐēОд", "change_your_password": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ŅĐ˛ĐžĐš ĐŋĐ°Ņ€ĐžĐģҌ", "changed_visibility_successfully": "ВидиĐŧĐžŅŅ‚ŅŒ ҃ҁĐŋĐĩ҈ĐŊĐž иСĐŧĐĩĐŊĐĩĐŊа", + "charging": "ĐŸŅ€Đ¸ ĐˇĐ°Ņ€ŅĐ´ĐēĐĩ", + "charging_requirement_mobile_backup": "ЗаĐŋ҃ҁĐēĐ°Ņ‚ŅŒ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐĩ ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊиĐĩ Ņ‚ĐžĐģҌĐēĐž вО Đ˛Ņ€ĐĩĐŧŅ ĐˇĐ°Ņ€ŅĐ´Đēи", "check_corrupt_asset_backup": "ĐŸŅ€ĐžĐ˛ĐĩŅ€Đēа ĐŋĐžĐ˛Ņ€ĐĩĐļĐ´ĐĩĐŊĐŊҋ҅ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊҋ҅ ĐēĐžĐŋиК", "check_corrupt_asset_backup_button": "ĐŸŅ€ĐžĐ˛ĐĩŅ€Đ¸Ņ‚ŅŒ", "check_corrupt_asset_backup_description": "ЗаĐŋ҃ҁĐēĐ°ĐšŅ‚Đĩ ĐŋŅ€ĐžĐ˛ĐĩŅ€Đē҃ Ņ‚ĐžĐģҌĐēĐž ҇ĐĩŅ€ĐĩС Wi-Fi и ĐŋĐžŅĐģĐĩ ŅĐžĐˇĐ´Đ°ĐŊĐ¸Ņ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊОК ĐēĐžĐŋии Đ˛ŅĐĩŅ… ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛. ОĐŋĐĩŅ€Đ°Ņ†Đ¸Ņ ĐŧĐžĐļĐĩŅ‚ СаĐŊŅŅ‚ŅŒ ĐŊĐĩҁĐēĐžĐģҌĐēĐž ĐŧиĐŊŅƒŅ‚.", @@ -683,8 +697,8 @@ "color": "ĐĻвĐĩŅ‚", "color_theme": "ĐĻвĐĩŅ‚ĐžĐ˛Đ°Ņ Ņ‚ĐĩĐŧа", "comment_deleted": "КоĐŧĐŧĐĩĐŊŅ‚Đ°Ņ€Đ¸Đš ŅƒĐ´Đ°ĐģŅ‘ĐŊ", - "comment_options": "ĐŸĐ°Ņ€Đ°ĐŧĐĩ҂Ҁҋ ĐēĐžĐŧĐŧĐĩĐŊŅ‚Đ°Ņ€Đ¸Đĩв", - "comments_and_likes": "КоĐŧĐŧĐĩĐŊŅ‚Đ°Ņ€Đ¸Đ¸ и ĐģаКĐēи", + "comment_options": "ДĐĩĐšŅŅ‚Đ˛Đ¸Ņ ҁ ĐēĐžĐŧĐŧĐĩĐŊŅ‚Đ°Ņ€Đ¸ĐĩĐŧ", + "comments_and_likes": "КоĐŧĐŧĐĩĐŊŅ‚Đ°Ņ€Đ¸Đ¸ и ĐžŅ‚ĐŧĐĩŅ‚Đēи \"ĐŊŅ€Đ°Đ˛Đ¸Ņ‚ŅŅ\"", "comments_are_disabled": "КоĐŧĐŧĐĩĐŊŅ‚Đ°Ņ€Đ¸Đ¸ ĐžŅ‚ĐēĐģŅŽŅ‡ĐĩĐŊŅ‹", "common_create_new_album": "ĐĄĐžĐˇĐ´Đ°Ņ‚ŅŒ ĐŊĐžĐ˛Ņ‹Đš аĐģŅŒĐąĐžĐŧ", "common_server_error": "ПоĐļаĐģŅƒĐšŅŅ‚Đ°, ĐŋŅ€ĐžĐ˛ĐĩŅ€ŅŒŅ‚Đĩ ĐŋОдĐēĐģŅŽŅ‡ĐĩĐŊиĐĩ Đē ҁĐĩŅ‚Đ¸ и ŅƒĐąĐĩĐ´Đ¸Ņ‚ĐĩҁҌ, Ņ‡Ņ‚Đž Đ˛Đ°Ņˆ ҁĐĩŅ€Đ˛ĐĩŅ€ Đ´ĐžŅŅ‚ŅƒĐŋĐĩĐŊ, а вĐĩŅ€ŅĐ¸Đ¸ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸Ņ и ҁĐĩŅ€Đ˛ĐĩŅ€Đ° — ŅĐžĐ˛ĐŧĐĩŅŅ‚Đ¸ĐŧŅ‹.", @@ -692,7 +706,7 @@ "confirm": "ĐŸĐžĐ´Ņ‚Đ˛ĐĩŅ€Đ´Đ¸Ņ‚ŅŒ", "confirm_admin_password": "ĐŸĐžĐ´Ņ‚Đ˛ĐĩŅ€Đ´Đ¸Ņ‚Đĩ ĐŋĐ°Ņ€ĐžĐģҌ адĐŧиĐŊĐ¸ŅŅ‚Ņ€Đ°Ņ‚ĐžŅ€Đ°", "confirm_delete_face": "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ ĐģĐ¸Ņ†Đž ҇ĐĩĐģОвĐĩĐēа {name} иС ŅŅ‚ĐžĐŗĐž ĐžĐąŅŠĐĩĐēŅ‚Đ°?", - "confirm_delete_shared_link": "Đ’Ņ‹ ŅƒĐ˛ĐĩŅ€ĐĩĐŊŅ‹, Ņ‡Ņ‚Đž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ŅƒĐ´Đ°ĐģĐ¸Ņ‚ŅŒ ŅŅ‚Ņƒ ĐŋŅƒĐąĐģĐ¸Ņ‡ĐŊŅƒŅŽ ҁҁҋĐģĐē҃?", + "confirm_delete_shared_link": "Đ’Ņ‹ Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Ņ‚ĐĩĐģҌĐŊĐž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ŅƒĐ´Đ°ĐģĐ¸Ņ‚ŅŒ ŅŅ‚Ņƒ ĐŋŅƒĐąĐģĐ¸Ņ‡ĐŊŅƒŅŽ ҁҁҋĐģĐē҃?", "confirm_keep_this_delete_others": "Đ’ŅĐĩ ĐžŅŅ‚Đ°ĐģҌĐŊŅ‹Đĩ ĐžĐąŅŠĐĩĐē҂ҋ в ĐŗŅ€ŅƒĐŋĐŋĐĩ ĐąŅƒĐ´ŅƒŅ‚ ŅƒĐ´Đ°ĐģĐĩĐŊŅ‹, ĐēŅ€ĐžĐŧĐĩ ŅŅ‚ĐžĐŗĐž ĐžĐąŅŠĐĩĐēŅ‚Đ°. Đ’Ņ‹ ŅƒĐ˛ĐĩŅ€ĐĩĐŊŅ‹, Ņ‡Ņ‚Đž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ĐŋŅ€ĐžĐ´ĐžĐģĐļĐ¸Ņ‚ŅŒ?", "confirm_new_pin_code": "ĐŸĐžĐ´Ņ‚Đ˛ĐĩŅ€Đ´Đ¸Ņ‚Đĩ ĐŊĐžĐ˛Ņ‹Đš PIN-ĐēОд", "confirm_password": "ĐŸĐžĐ´Ņ‚Đ˛ĐĩŅ€Đ´Đ¸Ņ‚Đĩ ĐŋĐ°Ņ€ĐžĐģҌ", @@ -708,18 +722,18 @@ "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": "ПодĐĩĐģĐ¸Ņ‚ŅŒŅŅ ҁҁҋĐģĐēОК", + "control_bottom_app_bar_share_link": "ĐĄĐžĐˇĐ´Đ°Ņ‚ŅŒ ҁҁҋĐģĐē҃", "control_bottom_app_bar_share_to": "ПодĐĩĐģĐ¸Ņ‚ŅŒŅŅ ҁ", "control_bottom_app_bar_trash_from_immich": "В ĐēĐžŅ€ĐˇĐ¸ĐŊ҃", "copied_image_to_clipboard": "Đ˜ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиĐĩ ҁĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐž в ĐąŅƒŅ„ĐĩŅ€ ОйĐŧĐĩĐŊа.", "copied_to_clipboard": "ĐĄĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐž в ĐąŅƒŅ„ĐĩŅ€ ОйĐŧĐĩĐŊа!", - "copy_error": "ĐžŅˆĐ¸ĐąĐēа ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ", + "copy_error": "ĐĄĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ ĐžŅˆĐ¸ĐąĐē҃", "copy_file_path": "КоĐŋĐ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ ĐŋŅƒŅ‚ŅŒ Đē Ņ„Đ°ĐšĐģ҃", "copy_image": "КоĐŋĐ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ", "copy_link": "КоĐŋĐ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ ҁҁҋĐģĐē҃", "copy_link_to_clipboard": "ĐĄĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ ҁҁҋĐģĐē҃ в ĐąŅƒŅ„ĐĩŅ€ ОйĐŧĐĩĐŊа", "copy_password": "ĐĄĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ ĐŋĐ°Ņ€ĐžĐģҌ", - "copy_to_clipboard": "ĐĄĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēи в ĐąŅƒŅ„ĐĩŅ€ ОйĐŧĐĩĐŊа", + "copy_to_clipboard": "ĐĄĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ в ĐąŅƒŅ„ĐĩŅ€ ОйĐŧĐĩĐŊа", "country": "ĐĄŅ‚Ņ€Đ°ĐŊа", "cover": "ОбĐģĐžĐļĐēа", "covers": "ОбĐģĐžĐļĐēи", @@ -729,7 +743,7 @@ "create_library": "ĐĄĐžĐˇĐ´Đ°Ņ‚ŅŒ йийĐģĐ¸ĐžŅ‚ĐĩĐē҃", "create_link": "ĐĄĐžĐˇĐ´Đ°Ņ‚ŅŒ ҁҁҋĐģĐē҃", "create_link_to_share": "ĐĄĐžĐˇĐ´Đ°Ņ‚ŅŒ ҁҁҋĐģĐē҃ ĐžĐąŅ‰ĐĩĐŗĐž Đ´ĐžŅŅ‚ŅƒĐŋа", - "create_link_to_share_description": "Đ Đ°ĐˇŅ€ĐĩŅˆĐ¸Ņ‚ŅŒ Đ˛ŅĐĩĐŧ, ҃ ĐēĐžĐŗĐž ĐĩŅŅ‚ŅŒ ҁҁҋĐģĐēа, ĐŋŅ€ĐžŅĐŧĐžŅ‚Ņ€ĐĩŅ‚ŅŒ Đ˛Ņ‹ĐąŅ€Đ°ĐŊĐŊŅ‹Đĩ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đ¸", + "create_link_to_share_description": "Đ Đ°ĐˇŅ€ĐĩŅˆĐ¸Ņ‚ŅŒ Đ˛ŅĐĩĐŧ, ҃ ĐēĐžĐŗĐž ĐĩŅŅ‚ŅŒ ҁҁҋĐģĐēа, ĐŋŅ€ĐžŅĐŧĐ°Ņ‚Ņ€Đ¸Đ˛Đ°Ņ‚ŅŒ Đ˛Ņ‹ĐąŅ€Đ°ĐŊĐŊŅ‹Đĩ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đ¸", "create_new": "СОЗДАĐĸĐŦ НОВĐĢЙ", "create_new_person": "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ ĐŊĐžĐ˛ĐžĐŗĐž ҇ĐĩĐģОвĐĩĐēа", "create_new_person_hint": "НазĐŊĐ°Ņ‡Đ¸Ņ‚ŅŒ Đ˛Ņ‹ĐąŅ€Đ°ĐŊĐŊŅ‹Đĩ ĐžĐąŅŠĐĩĐē҂ҋ ĐŊа ĐŊĐžĐ˛ĐžĐŗĐž ҇ĐĩĐģОвĐĩĐēа", @@ -742,6 +756,7 @@ "create_user": "ĐĄĐžĐˇĐ´Đ°Ņ‚ŅŒ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ", "created": "ХОСдаĐŊ", "created_at": "ХОСдаĐŊ", + "creating_linked_albums": "ХОСдаĐŊиĐĩ ŅĐ˛ŅĐˇĐ°ĐŊĐŊҋ҅ аĐģŅŒĐąĐžĐŧОв...", "crop": "ĐžĐąŅ€ĐĩĐˇĐ°Ņ‚ŅŒ", "curated_object_page_title": "ĐŸŅ€ĐĩĐ´ĐŧĐĩ҂ҋ", "current_device": "ĐĸĐĩĐēŅƒŅ‰ĐĩĐĩ ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đž", @@ -753,7 +768,7 @@ "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "E, MMM dd, yyyy", "dark": "ĐĸŅ‘ĐŧĐŊĐ°Ņ", - "dark_theme": "ĐĸŅ‘ĐŧĐŊĐ°Ņ Ņ‚ĐĩĐŧа", + "dark_theme": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ/Đ˛Ņ‹ĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ ҂ґĐŧĐŊŅƒŅŽ Ņ‚ĐĩĐŧ҃", "date_after": "Đ”Đ°Ņ‚Đ° ĐŋĐžŅĐģĐĩ", "date_and_time": "Đ”Đ°Ņ‚Đ° и Đ’Ņ€ĐĩĐŧŅ", "date_before": "Đ”Đ°Ņ‚Đ° Đ´Đž", @@ -770,7 +785,7 @@ "default_locale": "Đ”Đ°Ņ‚Đ° и Đ˛Ņ€ĐĩĐŧŅ ĐŋĐž ҃ĐŧĐžĐģŅ‡Đ°ĐŊĐ¸ŅŽ", "default_locale_description": "Đ˜ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ Ņ„ĐžŅ€ĐŧĐ°Ņ‚ Đ´Đ°Ņ‚Ņ‹ и Đ˛Ņ€ĐĩĐŧĐĩĐŊи в ŅĐžĐžŅ‚Đ˛ĐĩŅ‚ŅŅ‚Đ˛Đ¸Đ¸ ҁ ŅĐˇŅ‹ĐēĐžĐ˛Ņ‹Đŧ ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐžĐŧ Đ˛Đ°ŅˆĐĩĐŗĐž ĐąŅ€Đ°ŅƒĐˇĐĩŅ€Đ°", "delete": "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ", - "delete_action_confirmation_message": "Đ’Ņ‹ Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Ņ‚ĐĩĐģҌĐŊĐž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ŅƒĐ´Đ°ĐģĐ¸Ņ‚ŅŒ ŅŅ‚ĐžŅ‚ ĐžĐąŅŠĐĩĐēŅ‚? Đ­Ņ‚Đž Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Đĩ ĐŋĐĩŅ€ĐĩĐŧĐĩŅŅ‚Đ¸Ņ‚ ĐžĐąŅŠĐĩĐēŅ‚ в ĐēĐžŅ€ĐˇĐ¸ĐŊ҃ ҁĐĩŅ€Đ˛ĐĩŅ€Đ° и ĐŋŅ€ĐĩĐ´ĐģĐžĐļĐ¸Ņ‚ ŅƒĐ´Đ°ĐģĐ¸Ņ‚ŅŒ ĐĩĐŗĐž ĐģĐžĐēаĐģҌĐŊĐž.", + "delete_action_confirmation_message": "Đ’Ņ‹ Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Ņ‚ĐĩĐģҌĐŊĐž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ŅƒĐ´Đ°ĐģĐ¸Ņ‚ŅŒ ŅŅ‚ĐžŅ‚ ĐžĐąŅŠĐĩĐēŅ‚? Đ­Ņ‚Đž Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Đĩ ĐŋĐĩŅ€ĐĩĐŧĐĩŅŅ‚Đ¸Ņ‚ ĐžĐąŅŠĐĩĐēŅ‚ в ĐēĐžŅ€ĐˇĐ¸ĐŊ҃ ҁĐĩŅ€Đ˛ĐĩŅ€Đ° и ĐŋĐžĐŋŅ€ĐžĐąŅƒĐĩŅ‚ ŅƒĐ´Đ°ĐģĐ¸Ņ‚ŅŒ ĐĩĐŗĐž ĐģĐžĐēаĐģҌĐŊĐž.", "delete_action_prompt": "ĐžĐąŅŠĐĩĐē҂ҋ ŅƒĐ´Đ°ĐģĐĩĐŊŅ‹ ({count} ŅˆŅ‚.)", "delete_album": "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ аĐģŅŒĐąĐžĐŧ", "delete_api_key_prompt": "Đ’Ņ‹ Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Ņ‚ĐĩĐģҌĐŊĐž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ŅƒĐ´Đ°ĐģĐ¸Ņ‚ŅŒ ŅŅ‚ĐžŅ‚ API ĐēĐģŅŽŅ‡?", @@ -811,7 +826,7 @@ "discovered_devices": "ОбĐŊĐ°Ņ€ŅƒĐļĐĩĐŊĐŊŅ‹Đĩ ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đ°", "dismiss_all_errors": "ĐĄĐąŅ€ĐžŅĐ¸Ņ‚ŅŒ Đ˛ŅĐĩ ĐžŅˆĐ¸ĐąĐēи", "dismiss_error": "ĐĄĐąŅ€ĐžŅĐ¸Ņ‚ŅŒ ĐžŅˆĐ¸ĐąĐē҃", - "display_options": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи ĐžŅ‚ĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ", + "display_options": "ДоĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊĐž", "display_order": "ĐŸĐžŅ€ŅĐ´ĐžĐē ĐžŅ‚ĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ", "display_original_photos": "ĐžŅ‚ĐžĐąŅ€Đ°ĐļĐĩĐŊиĐĩ ĐžŅ€Đ¸ĐŗĐ¸ĐŊаĐģҌĐŊҋ҅ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đš", "display_original_photos_setting_description": "ĐžŅ‚ĐēŅ€Ņ‹Đ˛Đ°Ņ‚ŅŒ ĐŋŅ€Đ¸ ĐŋŅ€ĐžŅĐŧĐžŅ‚Ņ€Đĩ ĐžŅ€Đ¸ĐŗĐ¸ĐŊаĐģ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đ¸ вĐŧĐĩŅŅ‚Đž ĐŧиĐŊĐ¸Đ°Ņ‚ŅŽŅ€Ņ‹, ĐĩҁĐģи Đ¸ŅŅ…ĐžĐ´ĐŊŅ‹Đš Ņ„ĐžŅ€ĐŧĐ°Ņ‚ ĐŋОддĐĩŅ€ĐļиваĐĩŅ‚ŅŅ ĐąŅ€Đ°ŅƒĐˇĐĩŅ€ĐžĐŧ. ВозĐŧĐžĐļĐŊĐž ҁĐŊиĐļĐĩĐŊиĐĩ ҁĐēĐžŅ€ĐžŅŅ‚Đ¸ ĐžŅ‚ĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đš.", @@ -827,7 +842,7 @@ "download_failed": "Đ—Đ°ĐŗŅ€ŅƒĐˇĐēа ĐŊĐĩ ŅƒĐ´Đ°ĐģĐ°ŅŅŒ", "download_finished": "Đ—Đ°ĐŗŅ€ŅƒĐˇĐēа ĐžĐēĐžĐŊ҇ĐĩĐŊа", "download_include_embedded_motion_videos": "Đ’ŅŅ‚Ņ€ĐžĐĩĐŊĐŊŅ‹Đĩ видĐĩĐž", - "download_include_embedded_motion_videos_description": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ видĐĩĐž, Đ˛ŅŅ‚Ņ€ĐžĐĩĐŊĐŊŅ‹Đĩ в ĐļĐ¸Đ˛Ņ‹Đĩ Ņ„ĐžŅ‚Đž, в видĐĩ ĐžŅ‚Đ´ĐĩĐģҌĐŊĐžĐŗĐž Ņ„Đ°ĐšĐģа", + "download_include_embedded_motion_videos_description": "ĐĄĐžŅ…Ņ€Đ°ĐŊŅŅ‚ŅŒ видĐĩĐž, Đ˛ŅŅ‚Ņ€ĐžĐĩĐŊĐŊŅ‹Đĩ в ĐļĐ¸Đ˛Ņ‹Đĩ Ņ„ĐžŅ‚Đž, в видĐĩ ĐžŅ‚Đ´ĐĩĐģҌĐŊҋ҅ Ņ„Đ°ĐšĐģОв", "download_notfound": "Đ—Đ°ĐŗŅ€ŅƒĐˇĐēа ĐŊĐĩ ĐŊаКдĐĩĐŊа", "download_paused": "Đ—Đ°ĐŗŅ€ŅƒĐˇĐēа ĐŋŅ€Đ¸ĐžŅŅ‚Đ°ĐŊОвĐģĐĩĐŊа", "download_settings": "ĐĄĐēĐ°Ņ‡Đ¸Đ˛Đ°ĐŊиĐĩ", @@ -843,11 +858,11 @@ "duplicates": "Đ”ŅƒĐąĐģиĐēĐ°Ņ‚Ņ‹", "duplicates_description": "ĐŸŅ€ĐžŅĐŧĐžŅ‚Ņ€Đ¸Ņ‚Đĩ ĐŊаКдĐĩĐŊĐŊŅ‹Đĩ Đ´ŅƒĐąĐģиĐēĐ°Ņ‚Ņ‹ и в ĐēаĐļдОК ĐŗŅ€ŅƒĐŋĐŋĐĩ ҃ĐēаĐļĐ¸Ņ‚Đĩ, ĐēаĐēиĐĩ ĐžĐąŅŠĐĩĐē҂ҋ ĐžŅŅ‚Đ°Đ˛Đ¸Ņ‚ŅŒ, а ĐēаĐēиĐĩ ŅƒĐ´Đ°ĐģĐ¸Ņ‚ŅŒ", "duration": "ĐŸŅ€ĐžĐ´ĐžĐģĐļĐ¸Ņ‚ĐĩĐģҌĐŊĐžŅŅ‚ŅŒ", - "edit": "Đ ĐĩдаĐēŅ‚Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ", - "edit_album": "Đ ĐĩдаĐēŅ‚Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ аĐģŅŒĐąĐžĐŧ", + "edit": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ", + "edit_album": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ аĐģŅŒĐąĐžĐŧ", "edit_avatar": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ Đ°Đ˛Đ°Ņ‚Đ°Ņ€", "edit_birthday": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ Đ´Đ°Ņ‚Ņƒ Ņ€ĐžĐļĐ´ĐĩĐŊĐ¸Ņ", - "edit_date": "Ņ€ĐĩдаĐēŅ‚Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ Đ´Đ°Ņ‚Ņƒ", + "edit_date": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ Đ´Đ°Ņ‚Ņƒ", "edit_date_and_time": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ Đ´Đ°Ņ‚Ņƒ и Đ˛Ņ€ĐĩĐŧŅ", "edit_date_and_time_action_prompt": "Đ”Đ°Ņ‚Đ° и Đ˛Ņ€ĐĩĐŧŅ иСĐŧĐĩĐŊĐĩĐŊŅ‹ ҃ {count} ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛", "edit_date_and_time_by_offset": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ Đ´Đ°Ņ‚Ņƒ ĐŋĐž ҁĐŧĐĩ҉ĐĩĐŊĐ¸ŅŽ", @@ -859,14 +874,14 @@ "edit_import_path": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ĐŋŅƒŅ‚ŅŒ иĐŧĐŋĐžŅ€Ņ‚Đ°", "edit_import_paths": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ĐŋŅƒŅ‚ŅŒ иĐŧĐŋĐžŅ€Ņ‚Đ°", "edit_key": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ĐēĐģŅŽŅ‡", - "edit_link": "Đ ĐĩдаĐēŅ‚Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ ҁҁҋĐģĐē҃", - "edit_location": "Đ ĐĩдаĐēŅ‚Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ ĐŧĐĩŅŅ‚ĐžĐŋĐžĐģĐžĐļĐĩĐŊиĐĩ", + "edit_link": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ҁҁҋĐģĐē҃", + "edit_location": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ĐŧĐĩŅŅ‚ĐžĐŋĐžĐģĐžĐļĐĩĐŊиĐĩ", "edit_location_action_prompt": "МĐĩŅŅ‚Đ° иСĐŧĐĩĐŊĐĩĐŊŅ‹ ({count} ŅˆŅ‚.)", "edit_location_dialog_title": "МĐĩŅŅ‚ĐžĐŋĐžĐģĐžĐļĐĩĐŊиĐĩ", - "edit_name": "Đ ĐĩдаĐēŅ‚Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ иĐŧŅ", - "edit_people": "Đ ĐĩдаĐēŅ‚Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ ĐģŅŽĐ´ĐĩĐš", + "edit_name": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ иĐŧŅ", + "edit_people": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ĐģŅŽĐ´ĐĩĐš", "edit_tag": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ Ņ‚ĐĩĐŗ", - "edit_title": "Đ ĐĩдаĐēŅ‚Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ Đ—Đ°ĐŗĐžĐģОвОĐē", + "edit_title": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ĐˇĐ°ĐŗĐžĐģОвОĐē", "edit_user": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ", "edited": "ĐžŅ‚Ņ€ĐĩдаĐēŅ‚Đ¸Ņ€ĐžĐ˛Đ°ĐŊĐž", "editor": "Đ ĐĩдаĐēŅ‚ĐžŅ€", @@ -880,7 +895,7 @@ "empty_trash": "ĐžŅ‡Đ¸ŅŅ‚Đ¸Ņ‚ŅŒ ĐēĐžŅ€ĐˇĐ¸ĐŊ҃", "empty_trash_confirmation": "Đ’Ņ‹ Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Ņ‚ĐĩĐģҌĐŊĐž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ĐžŅ‡Đ¸ŅŅ‚Đ¸Ņ‚ŅŒ ĐēĐžŅ€ĐˇĐ¸ĐŊ҃? Đ’ŅĐĩ ĐžĐąŅŠĐĩĐē҂ҋ в ĐŊĐĩĐš ĐąŅƒĐ´ŅƒŅ‚ ĐŊĐ°Đ˛ŅĐĩĐŗĐ´Đ° ŅƒĐ´Đ°ĐģĐĩĐŊŅ‹ иС Immich.\nĐ’Ņ‹ ĐŊĐĩ ҁĐŧĐžĐļĐĩŅ‚Đĩ ĐžŅ‚ĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ŅŅ‚Đž Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Đĩ!", "enable": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ", - "enable_backup": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐĩ ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊиĐĩ", + "enable_backup": "АĐēŅ‚Đ¸Đ˛Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ", "enable_biometric_auth_description": "ВвĐĩĐ´Đ¸Ņ‚Đĩ ŅĐ˛ĐžĐš PIN-ĐēОд Đ´ĐģŅ вĐēĐģŅŽŅ‡ĐĩĐŊĐ¸Ņ йиОĐŧĐĩŅ‚Ņ€Đ¸Ņ‡ĐĩҁĐēОК Đ°ŅƒŅ‚ĐĩĐŊŅ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ†Đ¸Đ¸", "enabled": "ВĐēĐģŅŽŅ‡ĐĩĐŊĐž", "end_date": "Đ”Đ°Ņ‚Đ° ĐžĐēĐžĐŊŅ‡Đ°ĐŊĐ¸Ņ", @@ -891,28 +906,30 @@ "error": "ĐžŅˆĐ¸ĐąĐēа", "error_change_sort_album": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ иСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ĐŋĐžŅ€ŅĐ´ĐžĐē ŅĐžŅ€Ņ‚Đ¸Ņ€ĐžĐ˛Đēи аĐģŅŒĐąĐžĐŧа", "error_delete_face": "ĐžŅˆĐ¸ĐąĐēа ĐŋŅ€Đ¸ ŅƒĐ´Đ°ĐģĐĩĐŊии ĐģĐ¸Ņ†Đ° иС ĐžĐąŅŠĐĩĐēŅ‚Đ°", + "error_getting_places": "ĐžŅˆĐ¸ĐąĐēа ĐŋĐžĐģŅƒŅ‡ĐĩĐŊĐ¸Ņ ĐŧĐĩҁ҂", "error_loading_image": "ĐžŅˆĐ¸ĐąĐēа ĐŋŅ€Đ¸ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēĐĩ Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ", + "error_loading_partners": "ĐžŅˆĐ¸ĐąĐēа ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēи ĐŋĐ°Ņ€Ņ‚ĐŊŅ‘Ņ€ĐžĐ˛: {error}", "error_saving_image": "ĐžŅˆĐ¸ĐąĐēа: {error}", "error_tag_face_bounding_box": "ĐžŅˆĐ¸ĐąĐēа ĐŋŅ€Đ¸ дОйавĐģĐĩĐŊии ĐžŅ‚ĐŧĐĩŅ‚Đēи - ĐŊĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ ĐŋĐžĐģŅƒŅ‡Đ¸Ņ‚ŅŒ ĐēĐžĐžŅ€Đ´Đ¸ĐŊĐ°Ņ‚Ņ‹ Ņ€Đ°ĐŧĐēи ĐģĐ¸Ņ†Đ°", "error_title": "ĐžŅˆĐ¸ĐąĐēа - Đ§Ņ‚Đž-Ņ‚Đž ĐŋĐžŅˆĐģĐž ĐŊĐĩ Ņ‚Đ°Đē", "errors": { "cannot_navigate_next_asset": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ ĐŋĐĩŅ€ĐĩĐšŅ‚Đ¸ Đē ҁĐģĐĩĐ´ŅƒŅŽŅ‰ĐĩĐŧ҃ ĐžĐąŅŠĐĩĐēŅ‚Ņƒ", - "cannot_navigate_previous_asset": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ ĐŋĐĩŅ€ĐĩĐšŅ‚Đ¸ Đē ĐŋŅ€ĐĩĐ´Ņ‹Đ´ŅƒŅ‰ĐĩĐŧ҃ Ņ€ĐĩŅŅƒŅ€ŅŅƒ", + "cannot_navigate_previous_asset": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ ĐŋĐĩŅ€ĐĩĐšŅ‚Đ¸ Đē ĐŋŅ€ĐĩĐ´Ņ‹Đ´ŅƒŅ‰ĐĩĐŧ҃ ĐžĐąŅŠĐĩĐēŅ‚Ņƒ", "cant_apply_changes": "НĐĩ ŅƒĐ´Đ°ĐĩŅ‚ŅŅ ĐŋŅ€Đ¸ĐŧĐĩĐŊĐ¸Ņ‚ŅŒ иСĐŧĐĩĐŊĐĩĐŊĐ¸Ņ", "cant_change_activity": "НĐĩ ŅƒĐ´Đ°ĐĩŅ‚ŅŅ {enabled, select, true {ĐžŅ‚ĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ} other {вĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ}} аĐēŅ‚Đ¸Đ˛ĐŊĐžŅŅ‚ŅŒ", - "cant_change_asset_favorite": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ иСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ŅŅ‚Đ°Ņ‚ŅƒŅ \"Đ¸ĐˇĐąŅ€Đ°ĐŊĐŊĐžĐĩ\" Đ´ĐģŅ Ņ€ĐĩŅŅƒŅ€ŅĐ°", + "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": "НĐĩ ŅƒĐ´Đ°ĐĩŅ‚ŅŅ Đ˛Ņ‹ĐŋĐžĐģĐŊĐ¸Ņ‚ŅŒ ĐŋĐžĐ¸ŅĐē ĐŧĐĩҁ҂", - "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_to_create_album": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ ŅĐžĐˇĐ´Đ°Ņ‚ŅŒ аĐģŅŒĐąĐžĐŧ", "failed_to_create_shared_link": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ ŅĐžĐˇĐ´Đ°Ņ‚ŅŒ ĐŋŅƒĐąĐģĐ¸Ņ‡ĐŊŅƒŅŽ ҁҁҋĐģĐē҃", @@ -1004,7 +1021,7 @@ "unable_to_scan_library": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ ĐŋŅ€ĐžŅĐēаĐŊĐ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ йийĐģĐ¸ĐžŅ‚ĐĩĐē҃", "unable_to_set_feature_photo": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ ŅƒŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸ŅŽ ĐŊа ОйĐģĐžĐļĐē҃", "unable_to_set_profile_picture": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ ŅƒŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ Ņ„ĐžŅ‚Đž ĐŋŅ€ĐžŅ„Đ¸ĐģŅ", - "unable_to_submit_job": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ ĐžŅ‚ĐŋŅ€Đ°Đ˛Đ¸Ņ‚ŅŒ СадаĐŊиĐĩ", + "unable_to_submit_job": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ ĐžŅ‚ĐŋŅ€Đ°Đ˛Đ¸Ņ‚ŅŒ ĐˇĐ°Đ´Đ°Ņ‡Ņƒ ĐŊа Đ˛Ņ‹ĐŋĐžĐģĐŊĐĩĐŊиĐĩ", "unable_to_trash_asset": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ ĐŋĐĩŅ€ĐĩĐŧĐĩŅŅ‚Đ¸Ņ‚ŅŒ ĐžĐąŅŠĐĩĐēŅ‚ в ĐēĐžŅ€ĐˇĐ¸ĐŊ҃", "unable_to_unlink_account": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ ĐžŅ‚ŅĐžĐĩдиĐŊĐ¸Ņ‚ŅŒ ŅƒŅ‡Ņ‘Ņ‚ĐŊŅƒŅŽ СаĐŋĐ¸ŅŅŒ", "unable_to_unlink_motion_video": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ ĐžŅ‚ŅĐžĐĩдиĐŊĐ¸Ņ‚ŅŒ двиĐļŅƒŅ‰ĐĩĐĩŅŅ видĐĩĐž", @@ -1022,6 +1039,7 @@ "exif_bottom_sheet_description_error": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ ОйĐŊĐžĐ˛Đ¸Ņ‚ŅŒ ĐžĐŋĐ¸ŅĐ°ĐŊиĐĩ", "exif_bottom_sheet_details": "ПОДРОБНОСĐĸИ", "exif_bottom_sheet_location": "МЕСĐĸО", + "exif_bottom_sheet_no_description": "НĐĩŅ‚ ĐžĐŋĐ¸ŅĐ°ĐŊĐ¸Ņ", "exif_bottom_sheet_people": "ЛЮДИ", "exif_bottom_sheet_person_add_person": "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ иĐŧŅ", "exit_slideshow": "Đ’Ņ‹ĐšŅ‚Đ¸ иС ҁĐģаКд-ŅˆĐžŅƒ", @@ -1043,7 +1061,7 @@ "external": "ВĐŊĐĩ҈ĐŊиК", "external_libraries": "ВĐŊĐĩ҈ĐŊиĐĩ йийĐģĐ¸ĐžŅ‚ĐĩĐēи", "external_network": "ВĐŊĐĩ҈ĐŊŅŅ ҁĐĩŅ‚ŅŒ", - "external_network_sheet_info": "ĐšĐžĐŗĐ´Đ° ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đž ĐŊĐĩ ĐŋОдĐēĐģŅŽŅ‡ĐĩĐŊĐž Đē Đ˛Ņ‹ĐąŅ€Đ°ĐŊĐŊОК Wi-Fi ҁĐĩŅ‚Đ¸, ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ ĐąŅƒĐ´ĐĩŅ‚ ĐŋŅ‹Ņ‚Đ°Ņ‚ŅŒŅŅ ĐŋОдĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒŅŅ Đē ҁĐĩŅ€Đ˛ĐĩŅ€Ņƒ ĐŋĐž Đ°Đ´Ņ€ĐĩŅĐ°Đŧ ĐŊиĐļĐĩ, ŅĐ˛ĐĩŅ€Ņ…Ņƒ вĐŊиС, Đ´Đž ҃ҁĐŋĐĩ҈ĐŊĐžĐŗĐž ĐŋОдĐēĐģŅŽŅ‡ĐĩĐŊĐ¸Ņ", + "external_network_sheet_info": "ĐšĐžĐŗĐ´Đ° ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đž ĐŊĐĩ ĐŋОдĐēĐģŅŽŅ‡ĐĩĐŊĐž Đē ҃ĐēаСаĐŊĐŊОК Wi-Fi ҁĐĩŅ‚Đ¸, ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ ĐąŅƒĐ´ĐĩŅ‚ ĐŋŅ‹Ņ‚Đ°Ņ‚ŅŒŅŅ ĐŋОдĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒŅŅ Đē ҁĐĩŅ€Đ˛ĐĩŅ€Ņƒ ĐŋĐž Đ°Đ´Ņ€ĐĩŅĐ°Đŧ ĐŊиĐļĐĩ, ŅĐ˛ĐĩŅ€Ņ…Ņƒ вĐŊиС Đ´Đž ҃ҁĐŋĐĩ҈ĐŊĐžĐŗĐž ĐŋОдĐēĐģŅŽŅ‡ĐĩĐŊĐ¸Ņ", "face_unassigned": "НĐĩ ĐŊаСĐŊĐ°Ņ‡ĐĩĐŊĐž", "failed": "ĐžŅˆĐ¸ĐąĐēа", "failed_to_authenticate": "ĐžŅˆĐ¸ĐąĐēа Đ°ŅƒŅ‚ĐĩĐŊŅ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ†Đ¸Đ¸", @@ -1056,6 +1074,7 @@ "favorites_page_no_favorites": "В Đ¸ĐˇĐąŅ€Đ°ĐŊĐŊĐžĐŧ ҁĐĩĐšŅ‡Đ°Ņ ĐŋŅƒŅŅ‚Đž", "feature_photo_updated": "Đ˜ĐˇĐąŅ€Đ°ĐŊĐŊĐžĐĩ Ņ„ĐžŅ‚Đž ОйĐŊОвĐģĐĩĐŊĐž", "features": "ДоĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊŅ‹Đĩ вОСĐŧĐžĐļĐŊĐžŅŅ‚Đ¸", + "features_in_development": "Đ¤ŅƒĐŊĐēŅ†Đ¸Đ¸ в Ņ€Đ°ĐˇŅ€Đ°ĐąĐžŅ‚ĐēĐĩ", "features_setting_description": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊŅ‹Đŧи вОСĐŧĐžĐļĐŊĐžŅŅ‚ŅĐŧи ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸Ņ", "file_name": "ИĐŧŅ Ņ„Đ°ĐšĐģа", "file_name_or_extension": "ИĐŧŅ Ņ„Đ°ĐšĐģа иĐģи Ņ€Đ°ŅŅˆĐ¸Ņ€ĐĩĐŊиĐĩ", @@ -1070,16 +1089,13 @@ "folder": "ПаĐŋĐēа", "folder_not_found": "ПаĐŋĐēа ĐŊĐĩ ĐŊаКдĐĩĐŊа", "folders": "ПаĐŋĐēи", - "folders_feature_description": "ĐŸŅ€ĐžŅĐŧĐžŅ‚Ņ€ ĐŋаĐŋĐžĐē ҁ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸ŅĐŧи и видĐĩĐž в Ņ„Đ°ĐšĐģОвОК ŅĐ¸ŅŅ‚ĐĩĐŧĐĩ", + "folders_feature_description": "ĐŸŅ€ĐžŅĐŧĐžŅ‚Ņ€ ĐŋаĐŋĐžĐē ҁ Ņ„ĐžŅ‚Đž и видĐĩĐž в Ņ„Đ°ĐšĐģОвОК ŅĐ¸ŅŅ‚ĐĩĐŧĐĩ", "forgot_pin_code_question": "Đ—Đ°ĐąŅ‹Đģи PIN-ĐēОд?", "forward": "ВĐŋĐĩŅ€Ņ‘Đ´", "gcast_enabled": "Google Cast", - "gcast_enabled_description": "Đ­Ņ‚ĐžŅ‚ Ņ„ŅƒĐŊĐēŅ†Đ¸ĐžĐŊаĐģ ҂ҀĐĩĐąŅƒĐĩŅ‚ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēи вĐŊĐĩ҈ĐŊĐ¸Ņ… Ņ€ĐĩŅŅƒŅ€ŅĐžĐ˛ ҁ ҁĐĩŅ€Đ˛ĐĩŅ€ĐžĐ˛ Google.", + "gcast_enabled_description": "ДĐģŅ Ņ€Đ°ĐąĐžŅ‚Ņ‹ ҂ҀĐĩĐąŅƒĐĩŅ‚ŅŅ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēа вĐŊĐĩ҈ĐŊĐ¸Ņ… Ņ€ĐĩŅŅƒŅ€ŅĐžĐ˛ ҁ ҁĐĩŅ€Đ˛ĐĩŅ€ĐžĐ˛ Google.", "general": "ĐžĐąŅ‰Đ¸Đĩ", - "geolocation_instruction_all_have_location": "Đ’ŅĐĩ ĐžĐąŅŠĐĩĐē҂ҋ в ŅŅ‚ĐžĐŧ ĐŋĐĩŅ€Đ¸ĐžĐ´Đĩ ҃ĐļĐĩ ŅĐžĐ´ĐĩŅ€ĐļĐ°Ņ‚ даĐŊĐŊŅ‹Đĩ Đž ĐŧĐĩŅŅ‚ĐžĐŋĐžĐģĐžĐļĐĩĐŊии. ВĐēĐģŅŽŅ‡Đ¸Ņ‚Đĩ ĐžŅ‚ĐžĐąŅ€Đ°ĐļĐĩĐŊиĐĩ Đ˛ŅĐĩŅ… ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛ иĐģи ҃ĐēаĐļĐ¸Ņ‚Đĩ Đ´Ņ€ŅƒĐŗĐžĐš ĐŋĐĩŅ€Đ¸ĐžĐ´.", "geolocation_instruction_location": "Đ’Ņ‹ĐąĐĩŅ€Đ¸Ņ‚Đĩ ĐžĐąŅŠĐĩĐēŅ‚ ҁ иĐŧĐĩŅŽŅ‰Đ¸ĐŧĐ¸ŅŅ ĐēĐžĐžŅ€Đ´Đ¸ĐŊĐ°Ņ‚Đ°Đŧи, Ņ‡Ņ‚ĐžĐąŅ‹ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ Đ¸Ņ…, ĐģийО Đ˛Ņ€ŅƒŅ‡ĐŊŅƒŅŽ ҃ĐēаĐļĐ¸Ņ‚Đĩ ĐŧĐĩŅŅ‚Đž ĐŊа ĐēĐ°Ņ€Ņ‚Đĩ", - "geolocation_instruction_no_date": "ĐŖĐēаĐļĐ¸Ņ‚Đĩ Đ´Đ°Ņ‚Ņƒ Đ´ĐģŅ ҃ĐŋŅ€Đ°Đ˛ĐģĐĩĐŊĐ¸Ņ ĐēĐžĐžŅ€Đ´Đ¸ĐŊĐ°Ņ‚Đ°Đŧи ĐŧĐĩҁ҂ ŅŅŠŅ‘ĐŧĐēи Са ŅŅ‚ĐžŅ‚ Đ´ĐĩĐŊҌ", - "geolocation_instruction_no_photos": "НĐĩ ĐŊаКдĐĩĐŊĐž ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛ в ŅŅ‚ĐžĐŧ ĐŋĐĩŅ€Đ¸ĐžĐ´Đĩ. ĐŖĐēаĐļĐ¸Ņ‚Đĩ Đ´Ņ€ŅƒĐŗŅƒŅŽ Đ´Đ°Ņ‚Ņƒ.", "get_help": "ПоĐģŅƒŅ‡Đ¸Ņ‚ŅŒ ĐŋĐžĐŧĐžŅ‰ŅŒ", "get_wifiname_error": "НĐĩ ŅƒĐ´Đ°ĐģĐžŅŅŒ ĐŋĐžĐģŅƒŅ‡Đ¸Ņ‚ŅŒ иĐŧŅ Wi-Fi ҁĐĩŅ‚Đ¸. ĐŖĐąĐĩĐ´Đ¸Ņ‚ĐĩҁҌ, Ņ‡Ņ‚Đž Đ˛Ņ‹ ĐŋОдĐēĐģŅŽŅ‡ĐĩĐŊŅ‹ Đē ҁĐĩŅ‚Đ¸ и ĐŋŅ€ĐĩĐ´ĐžŅŅ‚Đ°Đ˛Đ¸Đģи ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸ŅŽ ĐŊĐĩĐžĐąŅ…ĐžĐ´Đ¸ĐŧŅ‹Đĩ Ņ€Đ°ĐˇŅ€Đĩ҈ĐĩĐŊĐ¸Ņ", "getting_started": "ĐĄŅ‚Đ°Ņ€Ņ‚", @@ -1098,8 +1114,8 @@ "haptic_feedback_switch": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ Ņ‚Đ°ĐēŅ‚Đ¸ĐģҌĐŊŅƒŅŽ ĐžŅ‚Đ´Đ°Ņ‡Ņƒ", "haptic_feedback_title": "ĐĸаĐēŅ‚Đ¸ĐģҌĐŊĐ°Ņ ĐžŅ‚Đ´Đ°Ņ‡Đ°", "has_quota": "ĐšĐ˛ĐžŅ‚Đ°", - "hash_asset": "ĐĨĐĩŅˆĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐŊŅ‹Đš ĐžĐąŅŠĐĩĐēŅ‚", - "hashed_assets": "ĐĨĐĩŅˆĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐŊŅ‹Đĩ ĐžĐąŅŠĐĩĐē҂ҋ", + "hash_asset": "ĐĨĐĩŅˆĐ¸Ņ€ĐžĐ˛Đ°ĐŊиĐĩ ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛", + "hashed_assets": "ĐĨĐĩŅˆĐ¸", "hashing": "ĐĨĐĩŅˆĐ¸Ņ€ĐžĐ˛Đ°ĐŊиĐĩ", "header_settings_add_header_tip": "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ ĐˇĐ°ĐŗĐžĐģОвОĐē", "header_settings_field_validator_msg": "ЗĐŊĐ°Ņ‡ĐĩĐŊиĐĩ ĐŊĐĩ ĐŧĐžĐļĐĩŅ‚ ĐąŅ‹Ņ‚ŅŒ ĐŋŅƒŅŅ‚Ņ‹Đŧ", @@ -1117,14 +1133,14 @@ "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_album_err_partner": "НĐĩвОСĐŧĐžĐļĐŊĐž Đ´ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ ĐžĐąŅŠĐĩĐē҂ҋ ĐŋĐ°Ņ€Ņ‚ĐŊŅ‘Ņ€Đ° в аĐģŅŒĐąĐžĐŧ, ĐŋŅ€ĐžĐŋ҃ҁĐē", "home_page_archive_err_local": "ПоĐēа ĐŊĐĩĐģŅŒĐˇŅ Đ´ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ ĐģĐžĐēаĐģҌĐŊŅ‹Đĩ Ņ„Đ°ĐšĐģŅ‹ в Đ°Ņ€Ņ…Đ¸Đ˛, ĐŋŅ€ĐžĐŋ҃ҁĐē", - "home_page_archive_err_partner": "НĐĩвОСĐŧĐžĐļĐŊĐž Đ°Ņ€Ņ…Đ¸Đ˛Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ ĐŧĐĩдиа ĐŋĐ°Ņ€Ņ‚ĐŊĐĩŅ€Đ°, ĐŋŅ€ĐžĐŋ҃ҁĐē", + "home_page_archive_err_partner": "НĐĩвОСĐŧĐžĐļĐŊĐž Đ´ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ ĐžĐąŅŠĐĩĐē҂ҋ ĐŋĐ°Ņ€Ņ‚ĐŊŅ‘Ņ€Đ° в Đ°Ņ€Ņ…Đ¸Đ˛, ĐŋŅ€ĐžĐŋ҃ҁĐē", "home_page_building_timeline": "ĐŸĐžŅŅ‚Ņ€ĐžĐĩĐŊиĐĩ Ņ…Ņ€ĐžĐŊĐžĐģĐžĐŗĐ¸Đ¸", - "home_page_delete_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_favorite_err_partner": "НĐĩвОСĐŧĐžĐļĐŊĐž Đ´ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ ĐžĐąŅŠĐĩĐē҂ҋ ĐŋĐ°Ņ€Ņ‚ĐŊŅ‘Ņ€Đ° в Đ¸ĐˇĐąŅ€Đ°ĐŊĐŊĐžĐĩ, ĐŋŅ€ĐžĐŋ҃ҁĐē", "home_page_first_time_notice": "ПĐĩŅ€ĐĩĐ´ ĐŊĐ°Ņ‡Đ°ĐģĐžĐŧ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°ĐŊĐ¸Ņ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸Ņ Đ˛Ņ‹ĐąĐĩŅ€Đ¸Ņ‚Đĩ аĐģŅŒĐąĐžĐŧ ҁ ĐžĐąŅŠĐĩĐēŅ‚Đ°Đŧи Đ´ĐģŅ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ, Ņ‡Ņ‚ĐžĐąŅ‹ ĐžĐŊи ĐžŅ‚ĐžĐąŅ€Đ°ĐˇĐ¸ĐģĐ¸ŅŅŒ ĐŊа Đ˛Ņ€ĐĩĐŧĐĩĐŊĐŊОК ҈ĐēаĐģĐĩ", "home_page_locked_error_local": "НĐĩвОСĐŧĐžĐļĐŊĐž ĐŋĐĩŅ€ĐĩĐŧĐĩŅŅ‚Đ¸Ņ‚ŅŒ ĐģĐžĐēаĐģҌĐŊŅ‹Đĩ ĐžĐąŅŠĐĩĐē҂ҋ в ĐģĐ¸Ņ‡ĐŊŅƒŅŽ ĐŋаĐŋĐē҃, ĐŋŅ€ĐžĐŋ҃ҁĐē", "home_page_locked_error_partner": "НĐĩвОСĐŧĐžĐļĐŊĐž ĐŋĐĩŅ€ĐĩĐŧĐĩŅŅ‚Đ¸Ņ‚ŅŒ ĐžĐąŅŠĐĩĐē҂ҋ ĐŋĐ°Ņ€Ņ‚ĐŊŅ‘Ņ€Đ° в ĐģĐ¸Ņ‡ĐŊŅƒŅŽ ĐŋаĐŋĐē҃, ĐŋŅ€ĐžĐŋ҃ҁĐē", @@ -1159,8 +1175,8 @@ "in_albums": "В {count, plural, one {# аĐģŅŒĐąĐžĐŧĐĩ} other {# аĐģŅŒĐąĐžĐŧĐ°Ņ…}}", "in_archive": "В Đ°Ņ€Ņ…Đ¸Đ˛Đĩ", "include_archived": "ĐžŅ‚ĐžĐąŅ€Đ°ĐļĐ°Ņ‚ŅŒ Đ°Ņ€Ņ…Đ¸Đ˛", - "include_shared_albums": "ВĐēĐģŅŽŅ‡Đ°Ņ‚ŅŒ ĐžĐąŅ‰Đ¸Đĩ аĐģŅŒĐąĐžĐŧŅ‹", - "include_shared_partner_assets": "ВĐēĐģŅŽŅ‡Đ°Ņ‚ŅŒ ĐžĐąŅ‰Đ¸Đĩ Ņ€ĐĩŅŅƒŅ€ŅŅ‹ ĐŋĐ°Ņ€Ņ‚ĐŊĐĩŅ€Đ°", + "include_shared_albums": "ВĐēĐģŅŽŅ‡Đ°Ņ‚ŅŒ ĐžĐąŅŠĐĩĐē҂ҋ ĐžĐąŅ‰Đ¸Ņ… аĐģŅŒĐąĐžĐŧОв", + "include_shared_partner_assets": "ВĐēĐģŅŽŅ‡Đ°Ņ‚ŅŒ ĐžĐąŅŠĐĩĐē҂ҋ ĐŋĐ°Ņ€Ņ‚ĐŊŅ‘Ņ€ĐžĐ˛", "individual_share": "ИĐŊĐ´Đ¸Đ˛Đ¸Đ´ŅƒĐ°ĐģҌĐŊĐ°Ņ ĐŋĐžĐ´ĐąĐžŅ€Đēа", "individual_shares": "ĐŸĐžĐ´ĐąĐžŅ€Đēи", "info": "ИĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Ņ", @@ -1172,7 +1188,7 @@ }, "invalid_date": "НĐĩвĐĩŅ€ĐŊĐ°Ņ Đ´Đ°Ņ‚Đ°", "invalid_date_format": "НĐĩвĐĩŅ€ĐŊŅ‹Đš Ņ„ĐžŅ€ĐŧĐ°Ņ‚ Đ´Đ°Ņ‚Ņ‹", - "invite_people": "ĐŸŅ€Đ¸ĐŗĐģĐ°ŅĐ¸Ņ‚ŅŒ", + "invite_people": "ĐŸŅ€Đ¸ĐŗĐģĐ°ŅĐ¸Ņ‚ŅŒ ŅƒŅ‡Đ°ŅŅ‚ĐŊиĐēа", "invite_to_album": "ĐŸŅ€Đ¸ĐŗĐģĐ°ŅĐ¸Ņ‚ŅŒ в аĐģŅŒĐąĐžĐŧ", "ios_debug_info_fetch_ran_at": "Đ’Ņ‹ĐąĐžŅ€Đēа СаĐŋŅƒŅ‰ĐĩĐŊа {dateTime}", "ios_debug_info_last_sync_at": "ĐŸĐžŅĐģĐĩĐ´ĐŊŅŅ ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Ņ {dateTime}", @@ -1190,7 +1206,7 @@ "language": "Đ¯ĐˇŅ‹Đē", "language_no_results_subtitle": "ПоĐŋŅ€ĐžĐąŅƒĐšŅ‚Đĩ ҁĐēĐžŅ€Ņ€ĐĩĐēŅ‚Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ ĐŋĐžĐ¸ŅĐēĐžĐ˛Ņ‹Đš СаĐŋŅ€ĐžŅ", "language_no_results_title": "Đ¯ĐˇŅ‹ĐēОв ĐŊĐĩ ĐŊаКдĐĩĐŊĐž", - "language_search_hint": "ĐŸĐžĐ¸ŅĐē ŅĐˇŅ‹ĐēОв...", + "language_search_hint": "ĐŸĐžĐ¸ŅĐē ŅĐˇŅ‹Đēа...", "language_setting_description": "Đ’Ņ‹ĐąĐĩŅ€Đ¸Ņ‚Đĩ ĐŋŅ€ĐĩĐ´ĐŋĐžŅ‡Đ¸Ņ‚Đ°ĐĩĐŧŅ‹Đš ваĐŧи ŅĐˇŅ‹Đē", "large_files": "ФаКĐģŅ‹ ĐŊаийОĐģҌ҈ĐĩĐŗĐž Ņ€Đ°ĐˇĐŧĐĩŅ€Đ°", "last": "ĐŸĐžŅĐģĐĩĐ´ĐŊиК", @@ -1200,10 +1216,10 @@ "leave": "ПоĐēиĐŊŅƒŅ‚ŅŒ", "leave_album": "ПоĐēиĐŊŅƒŅ‚ŅŒ аĐģŅŒĐąĐžĐŧ", "lens_model": "МодĐĩĐģҌ ĐžĐąŅŠĐĩĐēŅ‚Đ¸Đ˛Đ°", - "let_others_respond": "ПозвоĐģŅŅ‚ŅŒ Đ´Ņ€ŅƒĐŗĐ¸Đŧ ĐžŅ‚ĐēĐģиĐēĐ°Ņ‚ŅŒŅŅ", + "let_others_respond": "Đ Đ°ĐˇŅ€ĐĩŅˆĐ¸Ņ‚ŅŒ Đ´Ņ€ŅƒĐŗĐ¸Đŧ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅĐŧ дОйавĐģŅŅ‚ŅŒ ĐēĐžĐŧĐŧĐĩĐŊŅ‚Đ°Ņ€Đ¸Đ¸ и ĐžŅ‚ĐŧĐĩŅ‚Đēи \"ĐŊŅ€Đ°Đ˛Đ¸Ņ‚ŅŅ\"", "level": "ĐŖŅ€ĐžĐ˛ĐĩĐŊҌ", "library": "БибĐģĐ¸ĐžŅ‚ĐĩĐēа", - "library_options": "ОĐŋŅ†Đ¸Đ¸ йийĐģĐ¸ĐžŅ‚ĐĩĐēи", + "library_options": "ДĐĩĐšŅŅ‚Đ˛Đ¸Ņ ҁ йийĐģĐ¸ĐžŅ‚ĐĩĐēОК", "library_page_device_albums": "АĐģŅŒĐąĐžĐŧŅ‹ ĐŊа ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đĩ", "library_page_new_album": "ĐĐžĐ˛Ņ‹Đš аĐģŅŒĐąĐžĐŧ", "library_page_sort_asset_count": "КоĐģĐ¸Ņ‡ĐĩŅŅ‚Đ˛Đž ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛", @@ -1221,10 +1237,11 @@ "loading": "Đ—Đ°ĐŗŅ€ŅƒĐˇĐēа", "loading_search_results_failed": "Đ—Đ°ĐŗŅ€ŅƒĐˇĐēа Ņ€ĐĩĐˇŅƒĐģŅŒŅ‚Đ°Ņ‚ĐžĐ˛ ĐŋĐžĐ¸ŅĐēа ĐŊĐĩ ŅƒĐ´Đ°ĐģĐ°ŅŅŒ", "local": "На ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đĩ", - "local_asset_cast_failed": "НĐĩвОСĐŧĐžĐļĐŊĐž Ņ‚Ņ€Đ°ĐŊҁĐģĐ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ ĐžĐąŅŠĐĩĐēŅ‚, ĐēĐžŅ‚ĐžŅ€Ņ‹Đš Đĩ҉ґ ĐŊĐĩ ĐˇĐ°ĐŗŅ€ŅƒĐļĐĩĐŊ ĐŊа ҁĐĩŅ€Đ˛ĐĩŅ€", + "local_asset_cast_failed": "НĐĩвОСĐŧĐžĐļĐŊа Ņ‚Ņ€Đ°ĐŊҁĐģŅŅ†Đ¸Ņ ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ Đĩ҉ґ ĐŊĐĩ ĐˇĐ°ĐŗŅ€ŅƒĐļĐĩĐŊŅ‹ ĐŊа ҁĐĩŅ€Đ˛ĐĩŅ€", "local_assets": "ĐžĐąŅŠĐĩĐē҂ҋ ĐŊа ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đĩ", + "local_media_summary": "ИĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Ņ Ой ĐžĐąŅŠĐĩĐēŅ‚Đĩ ĐŊа ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đĩ", "local_network": "ЛоĐēаĐģҌĐŊĐ°Ņ ҁĐĩŅ‚ŅŒ", - "local_network_sheet_info": "ĐŸŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ ĐąŅƒĐ´ĐĩŅ‚ ĐŋОдĐēĐģŅŽŅ‡Đ°Ņ‚ŅŒŅŅ Đē ҁĐĩŅ€Đ˛ĐĩŅ€Ņƒ ĐŋĐž ŅŅ‚ĐžĐŧ҃ Đ°Đ´Ņ€Đĩҁ҃, ĐēĐžĐŗĐ´Đ° ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đž ĐŋОдĐēĐģŅŽŅ‡ĐĩĐŊĐž Đē Đ˛Ņ‹ĐąŅ€Đ°ĐŊĐŊОК Wi-Fi ҁĐĩŅ‚Đ¸", + "local_network_sheet_info": "ĐŸŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ ĐąŅƒĐ´ĐĩŅ‚ ĐŋОдĐēĐģŅŽŅ‡Đ°Ņ‚ŅŒŅŅ Đē ҁĐĩŅ€Đ˛ĐĩŅ€Ņƒ ĐŋĐž ŅŅ‚ĐžĐŧ҃ Đ°Đ´Ņ€Đĩҁ҃, ĐēĐžĐŗĐ´Đ° ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đž ĐŋОдĐēĐģŅŽŅ‡ĐĩĐŊĐž Đē ҃ĐēаСаĐŊĐŊОК Wi-Fi ҁĐĩŅ‚Đ¸", "location_permission": "Đ”ĐžŅŅ‚ŅƒĐŋ Đē ĐŧĐĩŅŅ‚ĐžĐŋĐžĐģĐžĐļĐĩĐŊĐ¸ŅŽ", "location_permission_content": "Đ§Ņ‚ĐžĐąŅ‹ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ Ņ„ŅƒĐŊĐēŅ†Đ¸ŅŽ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐĩҁĐēĐžĐŗĐž ĐŋĐĩŅ€ĐĩĐēĐģŅŽŅ‡ĐĩĐŊĐ¸Ņ, Immich ĐŊĐĩĐžĐąŅ…ĐžĐ´Đ¸ĐŧĐž Ņ€Đ°ĐˇŅ€Đĩ҈ĐĩĐŊиĐĩ ĐŊа Ņ‚ĐžŅ‡ĐŊĐžĐĩ ĐžĐŋŅ€ĐĩĐ´ĐĩĐģĐĩĐŊиĐĩ ĐŧĐĩŅŅ‚ĐžĐŋĐžĐģĐžĐļĐĩĐŊĐ¸Ņ, Ņ‡Ņ‚ĐžĐąŅ‹ ĐžĐŊĐž ĐŧĐžĐŗĐģĐž ŅŅ‡Đ¸Ņ‚Ņ‹Đ˛Đ°Ņ‚ŅŒ ĐŊаСваĐŊиĐĩ Ņ‚ĐĩĐēŅƒŅ‰ĐĩĐš Wi-Fi ҁĐĩŅ‚Đ¸", "location_picker_choose_on_map": "Đ’Ņ‹ĐąŅ€Đ°Ņ‚ŅŒ ĐŊа ĐēĐ°Ņ€Ņ‚Đĩ", @@ -1234,6 +1251,7 @@ "location_picker_longitude_hint": "ВвĐĩĐ´Đ¸Ņ‚Đĩ Đ´ĐžĐģĐŗĐžŅ‚Ņƒ", "lock": "ЗабĐģĐžĐēĐ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ", "locked_folder": "Đ›Đ¸Ņ‡ĐŊĐ°Ņ ĐŋаĐŋĐēа", + "log_detail_title": "ДĐĩŅ‚Đ°Đģи ŅĐžĐąŅ‹Ņ‚Đ¸Ņ", "log_out": "Đ’Ņ‹ĐšŅ‚Đ¸", "log_out_all_devices": "ЗавĐĩŅ€ŅˆĐ¸Ņ‚ŅŒ ҁĐĩаĐŊҁҋ ĐŊа Đ˛ŅĐĩŅ… ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đ°Ņ…", "logged_in_as": "ĐĐ˛Ņ‚ĐžŅ€Đ¸ĐˇĐžĐ˛Đ°ĐŊ ĐēаĐē {user}", @@ -1264,6 +1282,7 @@ "login_password_changed_success": "ĐŸĐ°Ņ€ĐžĐģҌ ҃ҁĐŋĐĩ҈ĐŊĐž ОйĐŊОвĐģĐĩĐŊ", "logout_all_device_confirmation": "Đ’Ņ‹ Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Ņ‚ĐĩĐģҌĐŊĐž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ СавĐĩŅ€ŅˆĐ¸Ņ‚ŅŒ Đ˛ŅĐĩ ҁĐĩаĐŊҁҋ, ĐēŅ€ĐžĐŧĐĩ Ņ‚ĐĩĐēŅƒŅ‰ĐĩĐŗĐž?", "logout_this_device_confirmation": "Đ’Ņ‹ Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Ņ‚ĐĩĐģҌĐŊĐž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ СавĐĩŅ€ŅˆĐ¸Ņ‚ŅŒ ҁĐĩаĐŊҁ ĐŊа ŅŅ‚ĐžĐŧ ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đĩ?", + "logs": "Đ–ŅƒŅ€ĐŊаĐģ ŅĐžĐąŅ‹Ņ‚Đ¸Đš", "longitude": "ДоĐģĐŗĐžŅ‚Đ°", "look": "ĐŸŅ€ĐžŅĐŧĐžŅ‚Ņ€", "loop_videos": "ĐĻиĐēĐģĐ¸Ņ‡ĐĩҁĐēĐžĐĩ Đ˛ĐžŅĐŋŅ€ĐžĐ¸ĐˇĐ˛ĐĩĐ´ĐĩĐŊиĐĩ видĐĩĐž", @@ -1273,7 +1292,7 @@ "make": "ĐŸŅ€ĐžĐ¸ĐˇĐ˛ĐžĐ´Đ¸Ņ‚ĐĩĐģҌ", "manage_geolocation": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ĐŧĐĩŅŅ‚Đ°Đŧи ŅŅŠŅ‘ĐŧĐēи", "manage_shared_links": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ĐŋŅƒĐąĐģĐ¸Ņ‡ĐŊŅ‹Đŧи ҁҁҋĐģĐēаĐŧи", - "manage_sharing_with_partners": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ОйĐŧĐĩĐŊĐžĐŧ иĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸ĐĩĐš ҁ ĐŋĐ°Ņ€Ņ‚ĐŊĐĩŅ€Đ°Đŧи. Đ­Ņ‚Đ° Ņ„ŅƒĐŊĐēŅ†Đ¸Ņ ĐŋОСвОĐģŅĐĩŅ‚ Đ˛Đ°ŅˆĐĩĐŧ҃ ĐŋĐ°Ņ€Ņ‚ĐŊĐĩŅ€Ņƒ видĐĩŅ‚ŅŒ Đ˛Đ°ŅˆĐ¸ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đ¸ и видĐĩОСаĐŋĐ¸ŅĐ¸, ĐēŅ€ĐžĐŧĐĩ Ņ‚ĐĩŅ…, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ ĐŊĐ°Ņ…ĐžĐ´ŅŅ‚ŅŅ в ĐŅ€Ņ…Đ¸Đ˛Đĩ и ĐšĐžŅ€ĐˇĐ¸ĐŊĐĩ", + "manage_sharing_with_partners": "Đ¤ŅƒĐŊĐēŅ†Đ¸Ņ ŅĐžĐ˛ĐŧĐĩҁ҂ĐŊĐžĐŗĐž Đ´ĐžŅŅ‚ŅƒĐŋа Đē Ņ„ĐžŅ‚Đž и видĐĩĐž, ĐŋОСвОĐģŅŅŽŅ‰Đ°Ņ видĐĩŅ‚ŅŒ ĐžĐąŅŠĐĩĐē҂ҋ ĐŋĐ°Ņ€Ņ‚ĐŊŅ‘Ņ€ĐžĐ˛, а Ņ‚Đ°ĐēĐļĐĩ ĐŋŅ€ĐĩĐ´ĐžŅŅ‚Đ°Đ˛ĐģŅŅ‚ŅŒ Đ´ĐžŅŅ‚ŅƒĐŋ Đē ŅĐ˛ĐžĐ¸Đŧ", "manage_the_app_settings": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēаĐŧи ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸Ņ", "manage_your_account": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ŅƒŅ‡Ņ‘Ņ‚ĐŊОК СаĐŋĐ¸ŅŅŒŅŽ", "manage_your_api_keys": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ API ĐēĐģŅŽŅ‡Đ°Đŧи Đ´ĐģŅ вСаиĐŧОдĐĩĐšŅŅ‚Đ˛Đ¸Ņ ҁ Đ´Ņ€ŅƒĐŗĐ¸Đŧи ĐŋŅ€ĐžĐŗŅ€Đ°ĐŧĐŧаĐŧи", @@ -1306,6 +1325,7 @@ "mark_as_read": "ĐžŅ‚ĐŧĐĩŅ‚Đ¸Ņ‚ŅŒ ĐēаĐē ĐŋŅ€ĐžŅ‡Đ¸Ņ‚Đ°ĐŊĐŊĐžĐĩ", "marked_all_as_read": "ĐžŅ‚ĐŧĐĩ҇ĐĩĐŊŅ‹ ĐēаĐē ĐŋŅ€ĐžŅ‡Đ¸Ņ‚Đ°ĐŊĐŊŅ‹Đĩ", "matches": "ХОвĐŋадĐĩĐŊĐ¸Ņ", + "matching_assets": "ĐĄĐžĐžŅ‚Đ˛ĐĩŅ‚ŅŅ‚Đ˛ŅƒŅŽŅ‰Đ¸Đĩ ĐžĐąŅŠĐĩĐē҂ҋ", "media_type": "ĐĸиĐŋ ĐŧĐĩдиа", "memories": "Đ’ĐžŅĐŋĐžĐŧиĐŊаĐŊĐ¸Ņ", "memories_all_caught_up": "Đ­Ņ‚Đž Đ˛ŅŅ‘ ĐŊа ҁĐĩĐŗĐžĐ´ĐŊŅ", @@ -1317,7 +1337,7 @@ "memory_lane_title": "Đ’ĐžŅĐŋĐžĐŧиĐŊаĐŊиĐĩ {title}", "menu": "МĐĩĐŊŅŽ", "merge": "ĐžĐąŅŠĐĩдиĐŊĐ¸Ņ‚ŅŒ", - "merge_people": "ĐžĐąŅŠĐĩдиĐŊĐ¸Ņ‚ŅŒ ĐģŅŽĐ´ĐĩĐš", + "merge_people": "ĐžĐąŅŠĐĩдиĐŊĐ¸Ņ‚ŅŒ ҁ Đ´Ņ€ŅƒĐŗĐ¸Đŧ", "merge_people_limit": "Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐąŅŠĐĩдиĐŊŅŅ‚ŅŒ Đ´Đž 5 ĐģĐ¸Ņ† Са ОдиĐŊ Ņ€Đ°Đˇ", "merge_people_prompt": "Đ’Ņ‹ Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ĐžĐąŅŠĐĩдиĐŊĐ¸Ņ‚ŅŒ ŅŅ‚Đ¸Ņ… ĐģŅŽĐ´ĐĩĐš? Đ­Ņ‚Đž Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Đĩ ĐŊĐĩĐžĐąŅ€Đ°Ņ‚Đ¸ĐŧĐž.", "merge_people_successfully": "Đ›Đ¸Ņ†Đ° ĐģŅŽĐ´ĐĩĐš ҃ҁĐŋĐĩ҈ĐŊĐž ĐžĐąŅŠĐĩдиĐŊĐĩĐŊŅ‹", @@ -1329,11 +1349,11 @@ "model": "МодĐĩĐģҌ", "month": "МĐĩŅŅŅ†", "monthly_title_text_date_format": "MMMM y", - "more": "БоĐģҌ҈Đĩ", + "more": "ДоĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊŅ‹Đĩ Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Ņ", "move": "ПĐĩŅ€ĐĩĐŧĐĩŅŅ‚Đ¸Ņ‚ŅŒ", - "move_off_locked_folder": "ПĐĩŅ€ĐĩĐŧĐĩŅŅ‚Đ¸Ņ‚ŅŒ иС ĐģĐ¸Ņ‡ĐŊОК ĐŋаĐŋĐēи", + "move_off_locked_folder": "ĐŖĐąŅ€Đ°Ņ‚ŅŒ иС ĐģĐ¸Ņ‡ĐŊОК ĐŋаĐŋĐēи", "move_to_lock_folder_action_prompt": "ĐžĐąŅŠĐĩĐē҂ҋ дОйавĐģĐĩĐŊŅ‹ в ĐģĐ¸Ņ‡ĐŊŅƒŅŽ ĐŋаĐŋĐē҃ ({count} ŅˆŅ‚.)", - "move_to_locked_folder": "ПĐĩŅ€ĐĩĐŧĐĩŅŅ‚Đ¸Ņ‚ŅŒ в ĐģĐ¸Ņ‡ĐŊŅƒŅŽ ĐŋаĐŋĐē҃", + "move_to_locked_folder": "В ĐģĐ¸Ņ‡ĐŊŅƒŅŽ ĐŋаĐŋĐē҃", "move_to_locked_folder_confirmation": "Đ­Ņ‚Đ¸ Ņ„ĐžŅ‚Đž и видĐĩĐž ĐąŅƒĐ´ŅƒŅ‚ ŅƒĐ´Đ°ĐģĐĩĐŊŅ‹ иС Đ˛ŅĐĩŅ… аĐģŅŒĐąĐžĐŧОв и ĐąŅƒĐ´ŅƒŅ‚ Đ´ĐžŅŅ‚ŅƒĐŋĐŊŅ‹ Ņ‚ĐžĐģҌĐēĐž в ĐģĐ¸Ņ‡ĐŊОК ĐŋаĐŋĐēĐĩ", "moved_to_archive": "{count, plural, one {# ĐžĐąŅŠĐĩĐēŅ‚ ĐŋĐĩŅ€ĐĩĐŧĐĩ҉ґĐŊ} many {# ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛ ĐŋĐĩŅ€ĐĩĐŧĐĩ҉ĐĩĐŊŅ‹} other {# ĐžĐąŅŠĐĩĐēŅ‚Đ° ĐŋĐĩŅ€ĐĩĐŧĐĩ҉ĐĩĐŊŅ‹}} в Đ°Ņ€Ņ…Đ¸Đ˛", "moved_to_library": "{count, plural, one {# ĐžĐąŅŠĐĩĐēŅ‚ ĐŋĐĩŅ€ĐĩĐŧĐĩ҉ґĐŊ} many {# ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛ ĐŋĐĩŅ€ĐĩĐŧĐĩ҉ĐĩĐŊŅ‹} other {# ĐžĐąŅŠĐĩĐēŅ‚Đ° ĐŋĐĩŅ€ĐĩĐŧĐĩ҉ĐĩĐŊŅ‹}} в йийĐģĐ¸ĐžŅ‚ĐĩĐē҃", @@ -1346,6 +1366,7 @@ "name_or_nickname": "ИĐŧŅ иĐģи ĐŊиĐē", "network_requirement_photos_upload": "Đ˜ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ ĐŧОйиĐģҌĐŊŅ‹Đš иĐŊŅ‚ĐĩŅ€ĐŊĐĩŅ‚ Đ´ĐģŅ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēи Ņ„ĐžŅ‚Đž", "network_requirement_videos_upload": "Đ˜ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ ĐŧОйиĐģҌĐŊŅ‹Đš иĐŊŅ‚ĐĩŅ€ĐŊĐĩŅ‚ Đ´ĐģŅ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēи видĐĩĐž", + "network_requirements": "ĐĸŅ€ĐĩйОваĐŊĐ¸Ņ Đē ҁĐĩŅ‚Đ¸", "network_requirements_updated": "ĐĸŅ€ĐĩйОваĐŊĐ¸Ņ Đē ҁĐĩŅ‚Đ¸ иСĐŧĐĩĐŊиĐģĐ¸ŅŅŒ, ŅĐąŅ€ĐžŅ ĐžŅ‡ĐĩŅ€Đĩди ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēи", "networking_settings": "ĐĄĐĩŅ‚ŅŒ", "networking_subtitle": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēа ĐŋОдĐēĐģŅŽŅ‡ĐĩĐŊĐ¸Ņ Đē ҁĐĩŅ€Đ˛ĐĩŅ€Ņƒ", @@ -1356,6 +1377,7 @@ "new_person": "ĐĐžĐ˛Ņ‹Đš ҇ĐĩĐģОвĐĩĐē", "new_pin_code": "ĐĐžĐ˛Ņ‹Đš PIN-ĐēОд", "new_pin_code_subtitle": "Đ­Ņ‚Đž Đ˛Đ°Ņˆ ĐŋĐĩŅ€Đ˛Ņ‹Đš Đ´ĐžŅŅ‚ŅƒĐŋ Đē ĐģĐ¸Ņ‡ĐŊОК ĐŋаĐŋĐēĐĩ. ĐĄĐžĐˇĐ´Đ°ĐšŅ‚Đĩ PIN-ĐēОд Đ´ĐģŅ ĐˇĐ°Ņ‰Đ¸Ņ‰ĐĩĐŊĐŊĐžĐŗĐž Đ´ĐžŅŅ‚ŅƒĐŋа Đē ŅŅ‚ĐžĐš ŅŅ‚Ņ€Đ°ĐŊĐ¸Ņ†Đĩ.", + "new_timeline": "ĐĐžĐ˛Đ°Ņ ĐģĐĩĐŊŅ‚Đ°", "new_user_created": "ĐĐžĐ˛Ņ‹Đš ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģҌ ŅĐžĐˇĐ´Đ°ĐŊ", "new_version_available": "ДОСĐĸĐŖĐŸĐĐ ĐĐžĐ’ĐĐ¯ Đ’Đ•Đ ĐĄĐ˜Đ¯", "newest_first": "ĐĄĐŊĐ°Ņ‡Đ°Đģа ĐŊĐžĐ˛Ņ‹Đĩ", @@ -1369,23 +1391,28 @@ "no_assets_message": "НАЖМИĐĸЕ Đ”Đ›Đ¯ Đ—ĐĐ“Đ ĐŖĐ—ĐšĐ˜ ВАШЕГО ПЕРВОГО ФОĐĸО", "no_assets_to_show": "МĐĩдиа ĐžŅ‚ŅŅƒŅ‚ŅŅ‚Đ˛ŅƒŅŽŅ‚", "no_cast_devices_found": "НĐĩ ĐŊаКдĐĩĐŊĐž ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛ Đ´ĐģŅ Ņ‚Ņ€Đ°ĐŊҁĐģŅŅ†Đ¸Đ¸", + "no_checksum_local": "КоĐŊŅ‚Ņ€ĐžĐģҌĐŊŅ‹Đĩ ҁ҃ĐŧĐŧŅ‹ ĐžŅ‚ŅŅƒŅ‚ŅŅ‚Đ˛ŅƒŅŽŅ‚ - ĐŊĐĩвОСĐŧĐžĐļĐŊĐž ĐŋĐžĐģŅƒŅ‡Đ¸Ņ‚ŅŒ ĐžĐąŅŠĐĩĐē҂ҋ ĐŊа ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đĩ", + "no_checksum_remote": "КоĐŊŅ‚Ņ€ĐžĐģҌĐŊŅ‹Đĩ ҁ҃ĐŧĐŧŅ‹ ĐžŅ‚ŅŅƒŅ‚ŅŅ‚Đ˛ŅƒŅŽŅ‚ - ĐŊĐĩвОСĐŧĐžĐļĐŊĐž ĐŋĐžĐģŅƒŅ‡Đ¸Ņ‚ŅŒ ĐžĐąŅŠĐĩĐē҂ҋ ҁ ҁĐĩŅ€Đ˛ĐĩŅ€Đ°", "no_duplicates_found": "Đ”ŅƒĐąĐģиĐēĐ°Ņ‚ĐžĐ˛ ĐŊĐĩ ОйĐŊĐ°Ņ€ŅƒĐļĐĩĐŊĐž.", "no_exif_info_available": "НĐĩŅ‚ Đ´ĐžŅŅ‚ŅƒĐŋĐŊОК иĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Đ¸ exif", "no_explore_results_message": "Đ—Đ°ĐŗŅ€ŅƒĐļĐ°ĐšŅ‚Đĩ йОĐģҌ҈Đĩ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đš, Ņ‡Ņ‚ĐžĐąŅ‹ ĐŊĐ°ŅĐģаĐļĐ´Đ°Ņ‚ŅŒŅŅ Đ˛Đ°ŅˆĐĩĐš ĐēĐžĐģĐģĐĩĐēŅ†Đ¸ĐĩĐš.", - "no_favorites_message": "ДобавĐģŅĐšŅ‚Đĩ в Đ¸ĐˇĐąŅ€Đ°ĐŊĐŊĐžĐĩ, Ņ‡Ņ‚ĐžĐąŅ‹ ĐąŅ‹ŅŅ‚Ņ€Đž ĐŊĐ°ĐšŅ‚Đ¸ ŅĐ˛ĐžĐ¸ ĐģŅƒŅ‡ŅˆĐ¸Đĩ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đ¸ и видĐĩĐž", + "no_favorites_message": "ДобавĐģŅĐšŅ‚Đĩ ĐžĐąŅŠĐĩĐē҂ҋ в Đ¸ĐˇĐąŅ€Đ°ĐŊĐŊĐžĐĩ, Ņ‡Ņ‚ĐžĐąŅ‹ ĐąŅ‹ŅŅ‚Ņ€ĐĩĐĩ ĐŊĐ°Ņ…ĐžĐ´Đ¸Ņ‚ŅŒ ŅĐ˛ĐžĐ¸ ĐģŅƒŅ‡ŅˆĐ¸Đĩ Ņ„ĐžŅ‚Đž и видĐĩĐž", "no_libraries_message": "ĐĄĐžĐˇĐ´Đ°ĐšŅ‚Đĩ вĐŊĐĩ҈ĐŊŅŽŅŽ йийĐģĐ¸ĐžŅ‚ĐĩĐē҃ Đ´ĐģŅ ĐŋŅ€ĐžŅĐŧĐžŅ‚Ņ€Đ° в Immich ŅŅ‚ĐžŅ€ĐžĐŊĐŊĐ¸Ņ… Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đš и видĐĩĐž", + "no_local_assets_found": "На ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đĩ ĐŊĐĩ ĐŊаКдĐĩĐŊĐž ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛ ҁ Ņ‚Đ°ĐēОК ĐēĐžĐŊŅ‚Ņ€ĐžĐģҌĐŊОК ҁ҃ĐŧĐŧОК", "no_locked_photos_message": "Đ¤ĐžŅ‚Đž и видĐĩĐž, ĐŋĐĩŅ€ĐĩĐŧĐĩ҉ĐĩĐŊĐŊŅ‹Đĩ в ĐģĐ¸Ņ‡ĐŊŅƒŅŽ ĐŋаĐŋĐē҃, ҁĐēҀҋ҂ҋ и ĐŊĐĩ ĐžŅ‚ĐžĐąŅ€Đ°ĐļĐ°ŅŽŅ‚ŅŅ ĐŋŅ€Đ¸ ĐŋŅ€ĐžŅĐŧĐžŅ‚Ņ€Đĩ йийĐģĐ¸ĐžŅ‚ĐĩĐēи.", "no_name": "НĐĩŅ‚ иĐŧĐĩĐŊи", "no_notifications": "НĐĩŅ‚ ŅƒĐ˛ĐĩĐ´ĐžĐŧĐģĐĩĐŊиК", "no_people_found": "НиĐēĐžĐŗĐž ĐŊĐĩ ĐŊаКдĐĩĐŊĐž", "no_places": "НĐĩŅ‚ ĐŧĐĩҁ҂", + "no_remote_assets_found": "На ҁĐĩŅ€Đ˛ĐĩŅ€Đĩ ĐŊĐĩ ĐŊаКдĐĩĐŊĐž ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛ ҁ Ņ‚Đ°ĐēОК ĐēĐžĐŊŅ‚Ņ€ĐžĐģҌĐŊОК ҁ҃ĐŧĐŧОК", "no_results": "НĐĩŅ‚ Ņ€ĐĩĐˇŅƒĐģŅŒŅ‚Đ°Ņ‚ĐžĐ˛", "no_results_description": "ПоĐŋŅ€ĐžĐąŅƒĐšŅ‚Đĩ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ ŅĐ¸ĐŊĐžĐŊиĐŧ иĐģи йОĐģĐĩĐĩ ĐžĐąŅ‰ĐĩĐĩ ĐēĐģŅŽŅ‡ĐĩвОĐĩ ҁĐģОвО", "no_shared_albums_message": "ĐĄĐžĐˇĐ´Đ°ĐšŅ‚Đĩ аĐģŅŒĐąĐžĐŧ Đ´ĐģŅ ОйĐŧĐĩĐŊа Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸ŅĐŧи и видĐĩОСаĐŋĐ¸ŅŅĐŧи ҁ ĐģŅŽĐ´ŅŒĐŧи в Đ˛Đ°ŅˆĐĩĐš ҁĐĩŅ‚Đ¸", "no_uploads_in_progress": "НĐĩŅ‚ аĐēŅ‚Đ¸Đ˛ĐŊҋ҅ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐžĐē", + "not_available": "НĐĩŅ‚ даĐŊĐŊҋ҅", "not_in_any_album": "Ни в ОдĐŊĐžĐŧ аĐģŅŒĐąĐžĐŧĐĩ", "not_selected": "НĐĩ Đ˛Ņ‹ĐąŅ€Đ°ĐŊĐž", - "note_apply_storage_label_to_previously_uploaded assets": "ĐŸŅ€Đ¸ĐŧĐĩŅ‡Đ°ĐŊиĐĩ: Đ§Ņ‚ĐžĐąŅ‹ ĐŋŅ€Đ¸ĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ĐŧĐĩŅ‚Đē҃ Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đ° Đē Ņ€Đ°ĐŊĐĩĐĩ ĐˇĐ°ĐŗŅ€ŅƒĐļĐĩĐŊĐŊŅ‹Đŧ Ņ€ĐĩŅŅƒŅ€ŅĐ°Đŧ, СаĐŋŅƒŅŅ‚Đ¸Ņ‚Đĩ", + "note_apply_storage_label_to_previously_uploaded assets": "ĐŸŅ€Đ¸ĐŧĐĩŅ‡Đ°ĐŊиĐĩ: Đ§Ņ‚ĐžĐąŅ‹ ĐŋŅ€Đ¸ĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ĐŧĐĩŅ‚Đē҃ Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đ° Đē Ņ€Đ°ĐŊĐĩĐĩ ĐˇĐ°ĐŗŅ€ŅƒĐļĐĩĐŊĐŊŅ‹Đŧ ĐžĐąŅŠĐĩĐēŅ‚Đ°Đŧ, СаĐŋŅƒŅŅ‚Đ¸Ņ‚Đĩ", "notes": "ĐŸŅ€Đ¸ĐŧĐĩŅ‡Đ°ĐŊиĐĩ", "nothing_here_yet": "ЗдĐĩҁҌ ĐŋĐžĐēа ĐŊĐ¸Ņ‡ĐĩĐŗĐž ĐŊĐĩŅ‚", "notification_permission_dialog_content": "Đ§Ņ‚ĐžĐąŅ‹ вĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ ŅƒĐ˛ĐĩĐ´ĐžĐŧĐģĐĩĐŊĐ¸Ņ, ĐŋĐĩŅ€ĐĩĐšĐ´Đ¸Ņ‚Đĩ в ÂĢĐĐ°ŅŅ‚Ņ€ĐžĐšĐēиÂģ и Đ˛Ņ‹ĐąĐĩŅ€Đ¸Ņ‚Đĩ ÂĢĐ Đ°ĐˇŅ€ĐĩŅˆĐ¸Ņ‚ŅŒÂģ.", @@ -1415,10 +1442,10 @@ "open_in_map_view": "ĐžŅ‚ĐēŅ€Ņ‹Ņ‚ŅŒ в Ņ€ĐĩĐļиĐŧĐĩ ĐŋŅ€ĐžŅĐŧĐžŅ‚Ņ€Đ° ĐēĐ°Ņ€Ņ‚Ņ‹", "open_in_openstreetmap": "ĐžŅ‚ĐēŅ€Ņ‹Ņ‚ŅŒ в OpenStreetMap", "open_the_search_filters": "ĐžŅ‚ĐēŅ€Ņ‹Ņ‚ŅŒ Ņ„Đ¸ĐģŅŒŅ‚Ņ€Ņ‹ ĐŋĐžĐ¸ŅĐēа", - "options": "ОĐŋŅ†Đ¸Đ¸", + "options": "ĐŸĐ°Ņ€Đ°ĐŧĐĩ҂Ҁҋ", "or": "иĐģи", "organize_into_albums": "Đ Đ°ŅĐŋŅ€ĐĩĐ´ĐĩĐģĐ¸Ņ‚ŅŒ ĐŋĐž аĐģŅŒĐąĐžĐŧаĐŧ", - "organize_into_albums_description": "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ ҃ĐļĐĩ ŅŅƒŅ‰ĐĩŅŅ‚Đ˛ŅƒŅŽŅ‰Đ¸Đĩ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đ¸ в аĐģŅŒĐąĐžĐŧŅ‹, Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒŅ Ņ‚ĐĩĐēŅƒŅ‰Đ¸Đĩ ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēи ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Đ¸", + "organize_into_albums_description": "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ ҃ĐļĐĩ ŅŅƒŅ‰ĐĩŅŅ‚Đ˛ŅƒŅŽŅ‰Đ¸Đĩ ĐžĐąŅŠĐĩĐē҂ҋ в аĐģŅŒĐąĐžĐŧŅ‹, Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒŅ Ņ‚ĐĩĐēŅƒŅ‰Đ¸Đĩ ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēи ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Đ¸", "organize_your_library": "ĐŸŅ€Đ¸Đ˛ĐĩĐ´Đ¸Ņ‚Đĩ в ĐŋĐžŅ€ŅĐ´ĐžĐē ŅĐ˛ĐžŅŽ йийĐģĐ¸ĐžŅ‚ĐĩĐē҃", "original": "ĐžŅ€Đ¸ĐŗĐ¸ĐŊаĐģ", "other": "Đ”Ņ€ŅƒĐŗĐžĐĩ", @@ -1427,18 +1454,18 @@ "other_variables": "Đ”Ņ€ŅƒĐŗĐ¸Đĩ ĐŋĐĩŅ€ĐĩĐŧĐĩĐŊĐŊŅ‹Đĩ", "owned": "Мои", "owner": "ВĐģадĐĩĐģĐĩ҆", - "partner": "ĐŸĐ°Ņ€Ņ‚ĐŊĐĩŅ€", - "partner_can_access": "{partner} иĐŧĐĩĐĩŅ‚ Đ´ĐžŅŅ‚ŅƒĐŋ", - "partner_can_access_assets": "Đ’ŅĐĩ Đ˛Đ°ŅˆĐ¸ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đ¸ и видĐĩОСаĐŋĐ¸ŅĐ¸, ĐēŅ€ĐžĐŧĐĩ Ņ‚ĐĩŅ…, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ ĐŊĐ°Ņ…ĐžĐ´ŅŅ‚ŅŅ в ĐŅ€Ņ…Đ¸Đ˛Đĩ и ĐšĐžŅ€ĐˇĐ¸ĐŊĐĩ", - "partner_can_access_location": "МĐĩŅŅ‚ĐžĐŋĐžĐģĐžĐļĐĩĐŊиĐĩ, ĐŗĐ´Đĩ ĐąŅ‹Đģи ŅĐ´ĐĩĐģаĐŊŅ‹ Đ˛Đ°ŅˆĐ¸ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đ¸", - "partner_list_user_photos": "Đ¤ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đ¸ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ {user}", + "partner": "ĐŸĐ°Ņ€Ņ‚ĐŊґҀ", + "partner_can_access": "ПоĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅŽ {partner} Đ´ĐžŅŅ‚ŅƒĐŋĐŊŅ‹", + "partner_can_access_assets": "Đ’ŅĐĩ Đ˛Đ°ŅˆĐ¸ Ņ„ĐžŅ‚Đž и видĐĩĐž, ĐēŅ€ĐžĐŧĐĩ Ņ‚ĐĩŅ…, Ņ‡Ņ‚Đž ĐŊĐ°Ņ…ĐžĐ´ŅŅ‚ŅŅ в Đ°Ņ€Ņ…Đ¸Đ˛Đĩ и ĐēĐžŅ€ĐˇĐ¸ĐŊĐĩ", + "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} йОĐģҌ҈Đĩ ĐŊĐĩ ҁĐŧĐžĐļĐĩŅ‚ ĐŋĐžĐģŅƒŅ‡Đ¸Ņ‚ŅŒ Đ´ĐžŅŅ‚ŅƒĐŋ Đē Đ˛Đ°ŅˆĐ¸Đŧ Ņ„ĐžŅ‚Đž.", + "partner_page_stop_sharing_content": "ПоĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģҌ {partner} йОĐģҌ҈Đĩ ĐŊĐĩ ĐąŅƒĐ´ĐĩŅ‚ иĐŧĐĩŅ‚ŅŒ Đ´ĐžŅŅ‚ŅƒĐŋ Đē Đ˛Đ°ŅˆĐ¸Đŧ Ņ„ĐžŅ‚Đž и видĐĩĐž.", "partner_sharing": "ХОвĐŧĐĩҁ҂ĐŊĐžĐĩ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°ĐŊиĐĩ", "partners": "ĐŸĐ°Ņ€Ņ‚ĐŊґҀҋ", "password": "ĐŸĐ°Ņ€ĐžĐģҌ", @@ -1458,7 +1485,7 @@ "pending": "ОĐļидаĐĩŅ‚", "people": "Đ›ŅŽĐ´Đ¸", "people_edits_count": "{count, plural, one {ИСĐŧĐĩĐŊŅ‘ĐŊ # ҇ĐĩĐģОвĐĩĐē} many {ИСĐŧĐĩĐŊĐĩĐŊĐž # ҇ĐĩĐģОвĐĩĐē} other {ИСĐŧĐĩĐŊĐĩĐŊĐž # ҇ĐĩĐģОвĐĩĐēа}}", - "people_feature_description": "ĐŸŅ€ĐžŅĐŧĐžŅ‚Ņ€ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đš и видĐĩĐž, ŅĐŗŅ€ŅƒĐŋĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐŊҋ҅ ĐŋĐž ĐģŅŽĐ´ŅĐŧ", + "people_feature_description": "ĐŸŅ€ĐžŅĐŧĐžŅ‚Ņ€ Ņ„ĐžŅ‚Đž и видĐĩĐž, ŅĐŗŅ€ŅƒĐŋĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐŊҋ҅ ĐŋĐž ĐģŅŽĐ´ŅĐŧ", "people_sidebar_description": "ĐžŅ‚ĐžĐąŅ€Đ°ĐļĐ°Ņ‚ŅŒ Đŋ҃ĐŊĐēŅ‚ ĐŧĐĩĐŊŅŽ \"Đ›ŅŽĐ´Đ¸\" в йОĐēОвОК ĐŋаĐŊĐĩĐģи", "permanent_deletion_warning": "ĐŸŅ€ĐĩĐ´ŅƒĐŋŅ€ĐĩĐļĐ´ĐĩĐŊиĐĩ Ой ŅƒĐ´Đ°ĐģĐĩĐŊии", "permanent_deletion_warning_setting_description": "ĐŸŅ€ĐĩĐ´ŅƒĐŋŅ€ĐĩĐļĐ´Đ°Ņ‚ŅŒ ĐŋĐĩŅ€ĐĩĐ´ ĐąĐĩĐˇĐ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‚ĐŊŅ‹Đŧ ŅƒĐ´Đ°ĐģĐĩĐŊиĐĩĐŧ ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛", @@ -1504,6 +1531,7 @@ "port": "ĐŸĐžŅ€Ņ‚", "preferences_settings_subtitle": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēа вĐŊĐĩ҈ĐŊĐĩĐŗĐž вида", "preferences_settings_title": "ĐŸĐ°Ņ€Đ°ĐŧĐĩ҂Ҁҋ", + "preparing": "ĐŸĐžĐ´ĐŗĐžŅ‚ĐžĐ˛Đēа", "preset": "ĐŸŅ€ĐĩĐ´ŅƒŅŅ‚Đ°ĐŊОвĐģĐĩĐŊĐŊŅ‹Đĩ Đ˛Đ°Ņ€Đ¸Đ°ĐŊ҂ҋ", "preview": "ĐŸŅ€ĐĩĐ´Đ˛Đ°Ņ€Đ¸Ņ‚ĐĩĐģҌĐŊŅ‹Đš ĐŋŅ€ĐžŅĐŧĐžŅ‚Ņ€", "previous": "ĐŸŅ€ĐĩĐ´Ņ‹Đ´ŅƒŅ‰ĐĩĐĩ", @@ -1515,12 +1543,12 @@ "primary": "ГĐģавĐŊĐžĐĩ", "privacy": "КоĐŊŅ„Đ¸Đ´ĐĩĐŊŅ†Đ¸Đ°ĐģҌĐŊĐžŅŅ‚ŅŒ", "profile": "ĐŸŅ€ĐžŅ„Đ¸ĐģҌ", - "profile_drawer_app_logs": "Đ–ŅƒŅ€ĐŊаĐģ", + "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_github": "GitHub", - "profile_drawer_readonly_mode": "ВĐēĐģŅŽŅ‡Ņ‘ĐŊ Ņ€ĐĩĐļиĐŧ ÂĢŅ‚ĐžĐģҌĐēĐž ĐŋŅ€ĐžŅĐŧĐžŅ‚Ņ€Âģ. ДваĐļĐ´Ņ‹ ĐēĐžŅĐŊĐ¸Ņ‚ĐĩҁҌ СĐŊĐ°Ņ‡Đēа Đ°Đ˛Đ°Ņ‚Đ°Ņ€Đ° ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ, Ņ‡Ņ‚ĐžĐąŅ‹ Đ˛Ņ‹ĐšŅ‚Đ¸.", + "profile_drawer_readonly_mode": "ВĐēĐģŅŽŅ‡Ņ‘ĐŊ Ņ€ĐĩĐļиĐŧ ÂĢŅ‚ĐžĐģҌĐēĐž ĐŋŅ€ĐžŅĐŧĐžŅ‚Ņ€Âģ. ĐŖĐ´ĐĩŅ€ĐļĐ¸Đ˛Đ°ĐšŅ‚Đĩ СĐŊĐ°Ņ‡ĐžĐē Đ°Đ˛Đ°Ņ‚Đ°Ņ€Đ° ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ Đ´ĐģŅ ĐžŅ‚ĐēĐģŅŽŅ‡ĐĩĐŊĐ¸Ņ.", "profile_drawer_server_out_of_date_major": "ВĐĩŅ€ŅĐ¸Ņ ҁĐĩŅ€Đ˛ĐĩŅ€Đ° ŅƒŅŅ‚Đ°Ņ€ĐĩĐģа. ПоĐļаĐģŅƒĐšŅŅ‚Đ°, ОйĐŊĐžĐ˛Đ¸Ņ‚Đĩ ĐĩĐŗĐž.", "profile_drawer_server_out_of_date_minor": "ВĐĩŅ€ŅĐ¸Ņ ҁĐĩŅ€Đ˛ĐĩŅ€Đ° ŅƒŅŅ‚Đ°Ņ€ĐĩĐģа. ПоĐļаĐģŅƒĐšŅŅ‚Đ°, ОйĐŊĐžĐ˛Đ¸Ņ‚Đĩ ĐĩĐŗĐž.", "profile_image_of_user": "Đ˜ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиĐĩ ĐŋŅ€ĐžŅ„Đ¸ĐģŅ {user}", @@ -1561,18 +1589,19 @@ "purchase_settings_server_activated": "КĐģŅŽŅ‡ĐžĐŧ ĐŋŅ€ĐžĐ´ŅƒĐēŅ‚Đ° ҃ĐŋŅ€Đ°Đ˛ĐģŅĐĩŅ‚ адĐŧиĐŊĐ¸ŅŅ‚Ņ€Đ°Ņ‚ĐžŅ€ ҁĐĩŅ€Đ˛ĐĩŅ€Đ°", "query_asset_id": "ИдĐĩĐŊŅ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚ĐžŅ€ Đ¸ŅŅ…ĐžĐ´ĐŊĐžĐŗĐž ĐžĐąŅŠĐĩĐēŅ‚Đ°", "queue_status": "В ĐžŅ‡ĐĩŅ€Đĩди {count}/{total}", - "rating": "Đ ĐĩĐšŅ‚Đ¸ĐŊĐŗ ĐˇĐ˛Ņ‘ĐˇĐ´", + "rating": "Đ ĐĩĐšŅ‚Đ¸ĐŊĐŗ", "rating_clear": "ĐžŅ‡Đ¸ŅŅ‚Đ¸Ņ‚ŅŒ Ņ€ĐĩĐšŅ‚Đ¸ĐŊĐŗ", "rating_count": "{count, plural, one {# СвĐĩСда} many {# СвĐĩСд} other {# СвĐĩĐˇĐ´Ņ‹}}", - "rating_description": "ПоĐēĐ°ĐˇŅ‹Đ˛Đ°Ņ‚ŅŒ Ņ€ĐĩĐšŅ‚Đ¸ĐŊĐŗ в ĐŋаĐŊĐĩĐģи иĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Đ¸", - "reaction_options": "ОĐŋŅ†Đ¸Đ¸ Ņ€ĐĩаĐēŅ†Đ¸Đš", - "read_changelog": "ĐŸŅ€ĐžŅ‡Đ¸Ņ‚Đ°Ņ‚ŅŒ ҁĐŋĐ¸ŅĐžĐē иСĐŧĐĩĐŊĐĩĐŊиК", + "rating_description": "ĐĄĐ¸ŅŅ‚ĐĩĐŧа ĐžŅ†ĐĩĐŊĐēи ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛ в ĐŋаĐŊĐĩĐģи иĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Đ¸", + "reaction_options": "ДĐĩĐšŅŅ‚Đ˛Đ¸Ņ ҁ ĐžŅ‚ĐŧĐĩŅ‚ĐēОК", + "read_changelog": "Đ˜ŅŅ‚ĐžŅ€Đ¸Ņ Ņ€ĐĩĐģиСОв", "readonly_mode_disabled": "Đ ĐĩĐļиĐŧ ÂĢŅ‚ĐžĐģҌĐēĐž ĐŋŅ€ĐžŅĐŧĐžŅ‚Ņ€Âģ ĐžŅ‚ĐēĐģŅŽŅ‡Ņ‘ĐŊ", "readonly_mode_enabled": "Đ ĐĩĐļиĐŧ ÂĢŅ‚ĐžĐģҌĐēĐž ĐŋŅ€ĐžŅĐŧĐžŅ‚Ņ€Âģ вĐēĐģŅŽŅ‡Ņ‘ĐŊ", + "ready_for_upload": "Đ“ĐžŅ‚ĐžĐ˛Đž Đē ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēĐĩ", "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": "НазĐŊĐ°Ņ‡Đ¸Ņ‚ŅŒ Đ˛Ņ‹ĐąŅ€Đ°ĐŊĐŊŅ‹Đĩ Ņ€ĐĩŅŅƒŅ€ŅŅ‹ ҃ĐēаСаĐŊĐŊĐžĐŧ҃ ҇ĐĩĐģОвĐĩĐē҃", + "reassing_hint": "НазĐŊĐ°Ņ‡Đ¸Ņ‚ŅŒ Đ˛Ņ‹ĐąŅ€Đ°ĐŊĐŊŅ‹Đĩ ĐžĐąŅŠĐĩĐē҂ҋ ҃ĐēаСаĐŊĐŊĐžĐŧ҃ ҇ĐĩĐģОвĐĩĐē҃", "recent": "НĐĩдавĐŊиĐĩ", "recent-albums": "НĐĩдавĐŊиĐĩ аĐģŅŒĐąĐžĐŧŅ‹", "recent_searches": "НĐĩдавĐŊиĐĩ ĐŋĐžĐ¸ŅĐēĐžĐ˛Ņ‹Đĩ СаĐŋŅ€ĐžŅŅ‹", @@ -1593,6 +1622,7 @@ "regenerating_thumbnails": "Đ’ĐžŅŅŅ‚Đ°ĐŊОвĐģĐĩĐŊиĐĩ ĐŧиĐŊĐ¸Đ°Ņ‚ŅŽŅ€", "remote": "На ҁĐĩŅ€Đ˛ĐĩŅ€Đĩ", "remote_assets": "ĐžĐąŅŠĐĩĐē҂ҋ ĐŊа ҁĐĩŅ€Đ˛ĐĩŅ€Đĩ", + "remote_media_summary": "ИĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Ņ Ой ĐžĐąŅŠĐĩĐēŅ‚Đĩ ĐŊа ҁĐĩŅ€Đ˛ĐĩŅ€Đĩ", "remove": "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ", "remove_assets_album_confirmation": "Đ’Ņ‹ Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Ņ‚ĐĩĐģҌĐŊĐž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ŅƒĐ´Đ°ĐģĐ¸Ņ‚ŅŒ {count, plural, one {# ĐžĐąŅŠĐĩĐēŅ‚} many {# ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛} other {# ĐžĐąŅŠĐĩĐēŅ‚Đ°}} иС аĐģŅŒĐąĐžĐŧа?", "remove_assets_shared_link_confirmation": "Đ’Ņ‹ Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Ņ‚ĐĩĐģҌĐŊĐž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ŅƒĐ´Đ°ĐģĐ¸Ņ‚ŅŒ {count, plural, one {# ĐžĐąŅŠĐĩĐēŅ‚} many {# ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛} other {# ĐžĐąŅŠĐĩĐēŅ‚Đ°}} иС ĐŋŅƒĐąĐģĐ¸Ņ‡ĐŊĐžĐŗĐž Đ´ĐžŅŅ‚ŅƒĐŋа ĐŋĐž ŅŅ‚ĐžĐš ҁҁҋĐģĐēĐĩ?", @@ -1604,14 +1634,14 @@ "remove_from_favorites": "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ иС Đ¸ĐˇĐąŅ€Đ°ĐŊĐŊĐžĐŗĐž", "remove_from_lock_folder_action_prompt": "ĐžĐąŅŠĐĩĐē҂ҋ ŅƒĐ´Đ°ĐģĐĩĐŊŅ‹ иС ĐģĐ¸Ņ‡ĐŊОК ĐŋаĐŋĐēи ({count} ŅˆŅ‚.)", "remove_from_locked_folder": "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ иС ĐģĐ¸Ņ‡ĐŊОК ĐŋаĐŋĐēи", - "remove_from_locked_folder_confirmation": "Đ’Ņ‹ Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Ņ‚ĐĩĐģҌĐŊĐž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ĐŋĐĩŅ€ĐĩĐŧĐĩŅŅ‚Đ¸Ņ‚ŅŒ ŅŅ‚Đ¸ Ņ„ĐžŅ‚Đž и видĐĩĐž иС ĐģĐ¸Ņ‡ĐŊОК ĐŋаĐŋĐēи? ОĐŊи ŅŅ‚Đ°ĐŊŅƒŅ‚ Đ´ĐžŅŅ‚ŅƒĐŋĐŊŅ‹ в Đ˛Đ°ŅˆĐĩĐš йийĐģĐ¸ĐžŅ‚ĐĩĐēĐĩ.", + "remove_from_locked_folder_confirmation": "Đ’Ņ‹ Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ŅƒĐąŅ€Đ°Ņ‚ŅŒ Đ˛Ņ‹Đ´ĐĩĐģĐĩĐŊĐŊŅ‹Đĩ ĐžĐąŅŠĐĩĐē҂ҋ иС ĐģĐ¸Ņ‡ĐŊОК ĐŋаĐŋĐēи? ОĐŊи ҁĐŊОва ŅŅ‚Đ°ĐŊŅƒŅ‚ Đ´ĐžŅŅ‚ŅƒĐŋĐŊŅ‹ в Đ˛Đ°ŅˆĐĩĐš йийĐģĐ¸ĐžŅ‚ĐĩĐēĐĩ.", "remove_from_shared_link": "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ иС ĐŋŅƒĐąĐģĐ¸Ņ‡ĐŊОК ҁҁҋĐģĐēи", "remove_memory": "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ Đ˛ĐžŅĐŋĐžĐŧиĐŊаĐŊиĐĩ", "remove_photo_from_memory": "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ Ņ„ĐžŅ‚Đž иС Đ˛ĐžŅĐŋĐžĐŧиĐŊаĐŊĐ¸Ņ", "remove_tag": "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ Ņ‚ĐĩĐŗ", "remove_url": "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ URL", "remove_user": "ĐŖĐ´Đ°ĐģĐ¸Ņ‚ŅŒ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ", - "removed_api_key": "ĐŖĐ´Đ°ĐģŅ‘ĐŊ API ĐēĐģŅŽŅ‡ {name}", + "removed_api_key": "API ĐēĐģŅŽŅ‡ \"{name}\" ŅƒĐ´Đ°ĐģŅ‘ĐŊ", "removed_from_archive": "ĐŖĐ´Đ°ĐģĐĩĐŊ иС Đ°Ņ€Ņ…Đ¸Đ˛Đ°", "removed_from_favorites": "ĐŖĐ´Đ°ĐģĐĩĐŊĐž иС Đ¸ĐˇĐąŅ€Đ°ĐŊĐŊĐžĐŗĐž", "removed_from_favorites_count": "{count, plural, one {# ĐžĐąŅŠĐĩĐēŅ‚ ŅƒĐ´Đ°ĐģŅ‘ĐŊ} many {# ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛ ŅƒĐ´Đ°ĐģĐĩĐŊĐž} other {# ĐžĐąŅŠĐĩĐēŅ‚Đ° ŅƒĐ´Đ°ĐģĐĩĐŊĐž}} иС Đ¸ĐˇĐąŅ€Đ°ĐŊĐŊĐžĐŗĐž", @@ -1645,6 +1675,7 @@ "restore_user": "Đ’ĐžŅŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ", "restored_asset": "Đ’ĐžŅŅŅ‚Đ°ĐŊОвĐģĐĩĐŊĐŊŅ‹Đš ĐžĐąŅŠĐĩĐēŅ‚", "resume": "ĐŸŅ€ĐžĐ´ĐžĐģĐļĐ¸Ņ‚ŅŒ", + "resume_paused_jobs": "ВозобĐŊĐžĐ˛Đ¸Ņ‚ŅŒ Đ˛Ņ‹ĐŋĐžĐģĐŊĐĩĐŊиĐĩ {count, plural, one {# ĐˇĐ°Đ´Đ°Ņ‡Đ¸} other {# ĐˇĐ°Đ´Đ°Ņ‡}}", "retry_upload": "ĐŸĐžĐ˛Ņ‚ĐžŅ€Đ¸Ņ‚ŅŒ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐē҃", "review_duplicates": "Đ Đ°ĐˇĐąĐžŅ€ Đ´ŅƒĐąĐģиĐēĐ°Ņ‚ĐžĐ˛", "review_large_files": "ĐžĐąĐˇĐžŅ€ йОĐģŅŒŅˆĐ¸Ņ… Ņ„Đ°ĐšĐģОв", @@ -1657,7 +1688,7 @@ "saved_api_key": "API ĐēĐģŅŽŅ‡ иСĐŧĐĩĐŊŅ‘ĐŊ", "saved_profile": "ĐŸŅ€ĐžŅ„Đ¸ĐģҌ ŅĐžŅ…Ņ€Đ°ĐŊŅ‘ĐŊ", "saved_settings": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи ŅĐžŅ…Ņ€Đ°ĐŊĐĩĐŊŅ‹", - "say_something": "ĐĄĐēаĐļĐ¸Ņ‚Đĩ Ņ‡Ņ‚Đž-ĐŊĐ¸ĐąŅƒĐ´ŅŒ", + "say_something": "НаĐŋĐ¸ŅˆĐ¸Ņ‚Đĩ Ņ‡Ņ‚Đž-ĐŊĐ¸ĐąŅƒĐ´ŅŒ", "scaffold_body_error_occurred": "ВозĐŊиĐēĐģа ĐžŅˆĐ¸ĐąĐēа", "scan_all_libraries": "ĐĄĐēаĐŊĐ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ Đ˛ŅĐĩ йийĐģĐ¸ĐžŅ‚ĐĩĐēи", "scan_library": "ĐĄĐēаĐŊĐ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ", @@ -1678,7 +1709,7 @@ "search_filter_camera_title": "Đ’Ņ‹ĐąĐĩŅ€Đ¸Ņ‚Đĩ Ņ‚Đ¸Đŋ ĐēаĐŧĐĩҀҋ", "search_filter_date": "Đ”Đ°Ņ‚Đ°", "search_filter_date_interval": "{start} — {end}", - "search_filter_date_title": "Đ’Ņ‹ĐąĐĩŅ€Đ¸Ņ‚Đĩ ĐŋŅ€ĐžĐŧĐĩĐļŅƒŅ‚ĐžĐē", + "search_filter_date_title": "Đ’Ņ‹ĐąĐĩŅ€Đ¸Ņ‚Đĩ ĐŋĐĩŅ€Đ¸ĐžĐ´", "search_filter_display_option_not_in_album": "НĐĩ в аĐģŅŒĐąĐžĐŧĐĩ", "search_filter_display_options": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēи ĐžŅ‚ĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ", "search_filter_filename": "ĐŸĐžĐ¸ŅĐē ĐŋĐž иĐŧĐĩĐŊи Ņ„Đ°ĐšĐģа", @@ -1731,7 +1762,7 @@ "select_from_computer": "Đ’Ņ‹ĐąŅ€Đ°Ņ‚ŅŒ ҁ ĐēĐžĐŧĐŋŅŒŅŽŅ‚ĐĩŅ€Đ°", "select_keep_all": "Đ’Ņ‹ĐąŅ€Đ°Ņ‚ŅŒ Đ˛ŅĐĩ Đ´ĐģŅ ŅĐžŅ…Ņ€Đ°ĐŊĐĩĐŊĐ¸Ņ", "select_library_owner": "Đ’Ņ‹ĐąĐĩŅ€Đ¸Ņ‚Đĩ вĐģадĐĩĐģŅŒŅ†Đ° йийĐģĐ¸ĐžŅ‚ĐĩĐēи", - "select_new_face": "Đ’Ņ‹ĐąŅ€Đ°Ņ‚ŅŒ Đ´Ņ€ŅƒĐŗĐžĐĩ ĐģĐ¸Ņ†Đž", + "select_new_face": "Đ’Ņ‹ĐąŅ€Đ°Ņ‚ŅŒ Đ´Ņ€ŅƒĐŗĐžĐŗĐž ҇ĐĩĐģОвĐĩĐēа", "select_person_to_tag": "Đ’Ņ‹Đ´ĐĩĐģĐ¸Ņ‚Đĩ ĐģĐ¸Ņ†Đž ҇ĐĩĐģОвĐĩĐēа, ĐēĐžŅ‚ĐžŅ€ĐžĐŗĐž Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ĐžŅ‚ĐŧĐĩŅ‚Đ¸Ņ‚ŅŒ", "select_photos": "Đ’Ņ‹ĐąĐĩŅ€Đ¸Ņ‚Đĩ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đ¸", "select_trash_all": "Đ’Ņ‹ĐąŅ€Đ°Ņ‚ŅŒ Đ˛ŅĐĩ Đ´ĐģŅ ŅƒĐ´Đ°ĐģĐĩĐŊĐ¸Ņ", @@ -1744,13 +1775,13 @@ "server_endpoint": "ĐĐ´Ņ€Đĩҁ ҁĐĩŅ€Đ˛ĐĩŅ€Đ°", "server_info_box_app_version": "ВĐĩŅ€ŅĐ¸Ņ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸Ņ", "server_info_box_server_url": "URL ҁĐĩŅ€Đ˛ĐĩŅ€Đ°", - "server_offline": "ĐĄĐĩŅ€Đ˛ĐĩŅ€ ĐŊĐĩ в ҁĐĩŅ‚Đ¸", + "server_offline": "ĐžŅ„Ņ„ĐģаКĐŊ", "server_online": "ĐĄĐĩŅ€Đ˛ĐĩŅ€ в ҁĐĩŅ‚Đ¸", "server_privacy": "КоĐŊŅ„Đ¸Đ´ĐĩĐŊŅ†Đ¸Đ°ĐģҌĐŊĐžŅŅ‚ŅŒ ҁĐĩŅ€Đ˛ĐĩŅ€Đ°", "server_stats": "ĐĄŅ‚Đ°Ņ‚Đ¸ŅŅ‚Đ¸Đēа ҁĐĩŅ€Đ˛ĐĩŅ€Đ°", "server_version": "ВĐĩŅ€ŅĐ¸Ņ ҁĐĩŅ€Đ˛ĐĩŅ€Đ°", "set": "ĐŖŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ", - "set_as_album_cover": "ĐŖŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ в ĐēĐ°Ņ‡ĐĩŅŅ‚Đ˛Đĩ ОйĐģĐžĐļĐēи аĐģŅŒĐąĐžĐŧа", + "set_as_album_cover": "ĐŖŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ ОйĐģĐžĐļĐēОК аĐģŅŒĐąĐžĐŧа", "set_as_featured_photo": "ĐŖŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ ĐēаĐē ĐžŅĐŊОвĐŊĐžĐĩ Ņ„ĐžŅ‚Đž", "set_as_profile_picture": "ĐŖŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ ĐēаĐē Ņ„ĐžŅ‚Đž ĐŋŅ€ĐžŅ„Đ¸ĐģŅ", "set_date_of_birth": "ĐŖŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ Đ´Đ°Ņ‚Ņƒ Ņ€ĐžĐļĐ´ĐĩĐŊĐ¸Ņ", @@ -1764,7 +1795,7 @@ "setting_image_viewer_preview_title": "Đ—Đ°ĐŗŅ€ŅƒĐļĐ°Ņ‚ŅŒ ҃ĐŧĐĩĐŊҌ҈ĐĩĐŊĐŊĐžĐĩ Đ¸ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊиĐĩ", "setting_image_viewer_title": "Đ˜ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐ¸Ņ", "setting_languages_apply": "ĐŸŅ€Đ¸ĐŧĐĩĐŊĐ¸Ņ‚ŅŒ", - "setting_languages_subtitle": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ŅĐˇŅ‹Đē ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸Ņ", + "setting_languages_subtitle": "ИСĐŧĐĩĐŊĐĩĐŊиĐĩ ŅĐˇŅ‹Đēа ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸Ņ", "setting_notifications_notify_failures_grace_period": "ĐŖĐ˛ĐĩĐ´ĐžĐŧĐģŅŅ‚ŅŒ Ой ĐžŅˆĐ¸ĐąĐēĐ°Ņ… Ņ„ĐžĐŊĐžĐ˛ĐžĐŗĐž Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ: {duration}", "setting_notifications_notify_hours": "{count} ҇.", "setting_notifications_notify_immediately": "ĐŊĐĩĐŧĐĩĐ´ĐģĐĩĐŊĐŊĐž", @@ -1773,7 +1804,7 @@ "setting_notifications_notify_seconds": "{count} ҁĐĩĐē.", "setting_notifications_single_progress_subtitle": "ĐŸĐžĐ´Ņ€ĐžĐąĐŊĐ°Ņ иĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Ņ Đž Ņ…ĐžĐ´Đĩ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēи Đ´ĐģŅ ĐēаĐļĐ´ĐžĐŗĐž ĐžĐąŅŠĐĩĐēŅ‚Đ°", "setting_notifications_single_progress_title": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ Ņ…ĐžĐ´ Đ˛Ņ‹ĐŋĐžĐģĐŊĐĩĐŊĐ¸Ņ Ņ„ĐžĐŊĐžĐ˛ĐžĐŗĐž Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ", - "setting_notifications_subtitle": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēа ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€ĐžĐ˛ ŅƒĐ˛ĐĩĐ´ĐžĐŧĐģĐĩĐŊиК", + "setting_notifications_subtitle": "ĐŸĐ°Ņ€Đ°ĐŧĐĩ҂Ҁҋ ŅƒĐ˛ĐĩĐ´ĐžĐŧĐģĐĩĐŊиК", "setting_notifications_total_progress_subtitle": "ĐžĐąŅ‰Đ¸Đš ĐŋŅ€ĐžĐŗŅ€Đĩҁҁ ĐˇĐ°ĐŗŅ€ŅƒĐˇĐēи (Đ˛Ņ‹ĐŋĐžĐģĐŊĐĩĐŊĐž/Đ˛ŅĐĩĐŗĐž ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛)", "setting_notifications_total_progress_title": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ ĐžĐąŅ‰Đ¸Đš ĐŋŅ€ĐžĐŗŅ€Đĩҁҁ Ņ„ĐžĐŊĐžĐ˛ĐžĐŗĐž Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ", "setting_video_viewer_looping_title": "ĐĻиĐēĐģĐ¸Ņ‡ĐĩҁĐēĐžĐĩ Đ˛ĐžŅĐŋŅ€ĐžĐ¸ĐˇĐ˛ĐĩĐ´ĐĩĐŊиĐĩ", @@ -1800,23 +1831,23 @@ "shared_by": "ПодĐĩĐģиĐģŅŅ", "shared_by_user": "ВĐģадĐĩĐģĐĩ҆: {user}", "shared_by_you": "Đ’Ņ‹ ĐŋОдĐĩĐģиĐģĐ¸ŅŅŒ", - "shared_from_partner": "Đ¤ĐžŅ‚Đž ĐžŅ‚ {partner}", + "shared_from_partner": "ПоĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģҌ {partner} ĐŋŅ€ĐĩĐ´ĐžŅŅ‚Đ°Đ˛Đ¸Đģ ваĐŧ Đ´ĐžŅŅ‚ŅƒĐŋ", "shared_intent_upload_button_progress_text": "{current} / {total} Đ—Đ°ĐŗŅ€ŅƒĐļĐĩĐŊĐž", "shared_link_app_bar_title": "ĐŸŅƒĐąĐģĐ¸Ņ‡ĐŊŅ‹Đĩ ҁҁҋĐģĐēи", "shared_link_clipboard_copied_massage": "ĐĄĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐž в ĐąŅƒŅ„ĐĩŅ€ ОйĐŧĐĩĐŊа", "shared_link_clipboard_text": "ĐĄŅŅ‹ĐģĐēа: {link}\nĐŸĐ°Ņ€ĐžĐģҌ: {password}", "shared_link_create_error": "ĐžŅˆĐ¸ĐąĐēа ĐŋŅ€Đ¸ ŅĐžĐˇĐ´Đ°ĐŊии ĐŋŅƒĐąĐģĐ¸Ņ‡ĐŊОК ҁҁҋĐģĐēи", - "shared_link_custom_url_description": "Đ”ĐžŅŅ‚ŅƒĐŋ Đē ŅŅ‚ĐžĐš ĐžĐąŅ‰ĐĩĐš ҁҁҋĐģĐēĐĩ ҁ ĐŋĐžĐŧĐžŅ‰ŅŒŅŽ СадаĐŊĐŊĐžĐŗĐž ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģĐĩĐŧ URL-Đ°Đ´Ņ€ĐĩŅĐ°", - "shared_link_edit_description_hint": "ВвĐĩĐ´Đ¸Ņ‚Đĩ ĐžĐŋĐ¸ŅĐ°ĐŊиĐĩ ĐŋŅƒĐąĐģĐ¸Ņ‡ĐŊĐžĐŗĐž Đ´ĐžŅŅ‚ŅƒĐŋа", + "shared_link_custom_url_description": "ПоĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģҌҁĐēиК URL-Đ°Đ´Ņ€Đĩҁ ĐžĐąŅ‰ĐĩĐŗĐž Đ´ĐžŅŅ‚ŅƒĐŋа", + "shared_link_edit_description_hint": "ВвĐĩĐ´Đ¸Ņ‚Đĩ ĐžĐŋĐ¸ŅĐ°ĐŊиĐĩ", "shared_link_edit_expire_after_option_day": "1 Đ´ĐĩĐŊҌ", "shared_link_edit_expire_after_option_days": "{count} Đ´ĐŊĐĩĐš", "shared_link_edit_expire_after_option_hour": "1 Ņ‡Đ°Ņ", "shared_link_edit_expire_after_option_hours": "{count} Ņ‡Đ°ŅĐžĐ˛", "shared_link_edit_expire_after_option_minute": "1 ĐŧиĐŊŅƒŅ‚Ņƒ", "shared_link_edit_expire_after_option_minutes": "{count} ĐŧиĐŊŅƒŅ‚", - "shared_link_edit_expire_after_option_months": "{count} ĐŧĐĩŅŅŅ†Đĩв", + "shared_link_edit_expire_after_option_months": "{count} ĐŧĐĩŅŅŅ†Đ°", "shared_link_edit_expire_after_option_year": "{count} ĐģĐĩŅ‚", - "shared_link_edit_password_hint": "ВвĐĩĐ´Đ¸Ņ‚Đĩ ĐŋĐ°Ņ€ĐžĐģҌ Đ´ĐģŅ ĐŋŅƒĐąĐģĐ¸Ņ‡ĐŊĐžĐŗĐž Đ´ĐžŅŅ‚ŅƒĐŋа", + "shared_link_edit_password_hint": "Đ—Đ°Ņ‰Đ¸Ņ‚Đ¸Ņ‚Đĩ Đ´ĐžŅŅ‚ŅƒĐŋ ĐŋĐ°Ņ€ĐžĐģĐĩĐŧ", "shared_link_edit_submit_button": "ОбĐŊĐžĐ˛Đ¸Ņ‚ŅŒ ҁҁҋĐģĐē҃", "shared_link_error_server_url_fetch": "НĐĩвОСĐŧĐžĐļĐŊĐž СаĐŋŅ€ĐžŅĐ¸Ņ‚ŅŒ URL ҁ ҁĐĩŅ€Đ˛ĐĩŅ€Đ°", "shared_link_expires_day": "Đ˜ŅŅ‚Đĩ҇ґ҂ ҇ĐĩŅ€ĐĩС {count} Đ´ĐĩĐŊҌ", @@ -1831,13 +1862,13 @@ "shared_link_individual_shared": "ИĐŊĐ´Đ¸Đ˛Đ¸Đ´ŅƒĐ°ĐģҌĐŊŅ‹Đš ĐžĐąŅ‰Đ¸Đš Đ´ĐžŅŅ‚ŅƒĐŋ", "shared_link_info_chip_metadata": "EXIF", "shared_link_manage_links": "ĐŖĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ĐŋŅƒĐąĐģĐ¸Ņ‡ĐŊŅ‹Đŧи ҁҁҋĐģĐēаĐŧи", - "shared_link_options": "ĐŸĐ°Ņ€Đ°ĐŧĐĩ҂Ҁҋ ĐŋŅƒĐąĐģĐ¸Ņ‡ĐŊҋ҅ ҁҁҋĐģĐžĐē", - "shared_link_password_description": "ĐĸŅ€ĐĩĐąĐžĐ˛Đ°Ņ‚ŅŒ ĐŋĐ°Ņ€ĐžĐģҌ Đ´ĐģŅ Đ´ĐžŅŅ‚ŅƒĐŋа Đē ŅŅ‚ĐžĐš ĐžĐąŅ‰ĐĩĐš ҁҁҋĐģĐēĐĩ", + "shared_link_options": "ДĐĩĐšŅŅ‚Đ˛Đ¸Ņ ŅĐž ҁҁҋĐģĐēОК", + "shared_link_password_description": "ĐĸŅ€ĐĩĐąĐžĐ˛Đ°Ņ‚ŅŒ ĐŋĐ°Ņ€ĐžĐģҌ Đ´ĐģŅ Đ´ĐžŅŅ‚ŅƒĐŋа Đē ĐžĐąŅŠĐĩĐēŅ‚Đ°Đŧ", "shared_links": "ĐŸŅƒĐąĐģĐ¸Ņ‡ĐŊŅ‹Đĩ ҁҁҋĐģĐēи", "shared_links_description": "ДĐĩĐģĐ¸Ņ‚ĐĩҁҌ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸ŅĐŧи и видĐĩĐž ĐŋĐž ҁҁҋĐģĐēĐĩ", "shared_photos_and_videos_count": "{assetCount, plural, other {# Ņ„ĐžŅ‚Đž и видĐĩĐž.}}", "shared_with_me": "Đ”ĐžŅŅ‚ŅƒĐŋĐŊŅ‹Đĩ ĐŧĐŊĐĩ", - "shared_with_partner": "ХОвĐŧĐĩҁ҂ĐŊĐž ҁ {partner}", + "shared_with_partner": "Đ’Ņ‹ ĐŋŅ€ĐĩĐ´ĐžŅŅ‚Đ°Đ˛Đ¸Đģи Đ´ĐžŅŅ‚ŅƒĐŋ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅŽ {partner}", "sharing": "ĐžĐąŅ‰Đ¸Đĩ", "sharing_enter_password": "ПоĐļаĐģŅƒĐšŅŅ‚Đ°, ввĐĩĐ´Đ¸Ņ‚Đĩ ĐŋĐ°Ņ€ĐžĐģҌ Đ´ĐģŅ ĐŋŅ€ĐžŅĐŧĐžŅ‚Ņ€Đ° ŅŅ‚ĐžĐš ŅŅ‚Ņ€Đ°ĐŊĐ¸Ņ†Ņ‹.", "sharing_page_album": "ĐžĐąŅ‰Đ¸Đĩ аĐģŅŒĐąĐžĐŧŅ‹", @@ -1847,31 +1878,30 @@ "sharing_silver_appbar_create_shared_album": "ĐĄĐžĐˇĐ´Đ°Ņ‚ŅŒ ĐžĐąŅ‰Đ¸Đš аĐģŅŒĐąĐžĐŧ", "sharing_silver_appbar_share_partner": "ПодĐĩĐģĐ¸Ņ‚ŅŒŅŅ ҁ ĐŋĐ°Ņ€Ņ‚ĐŊŅ‘Ņ€ĐžĐŧ", "shift_to_permanent_delete": "ĐŊаĐļĐŧĐ¸Ņ‚Đĩ ⇧ Ņ‡Ņ‚ĐžĐąŅ‹ ŅƒĐ´Đ°ĐģĐ¸Ņ‚ŅŒ ĐžĐąŅŠĐĩĐēŅ‚ ĐŊĐ°Đ˛ŅĐĩĐŗĐ´Đ°", - "show_album_options": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁҋ аĐģŅŒĐąĐžĐŧа", + "show_album_options": "ДĐĩĐšŅŅ‚Đ˛Đ¸Ņ ҁ аĐģŅŒĐąĐžĐŧĐžĐŧ", "show_albums": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ аĐģŅŒĐąĐžĐŧŅ‹", - "show_all_assets": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ Đ˛ŅĐĩ ĐžĐąŅŠĐĩĐē҂ҋ", "show_all_people": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ Đ˛ŅĐĩŅ… ĐģŅŽĐ´ĐĩĐš", "show_and_hide_people": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ и ҁĐēŅ€Ņ‹Ņ‚ŅŒ ĐģŅŽĐ´ĐĩĐš", - "show_assets_without_location": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ ĐžĐąŅŠĐĩĐē҂ҋ ĐąĐĩС ĐēĐžĐžŅ€Đ´Đ¸ĐŊĐ°Ņ‚", "show_file_location": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ Ņ€Đ°ŅĐŋĐžĐģĐžĐļĐĩĐŊиĐĩ Ņ„Đ°ĐšĐģа", "show_gallery": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ ĐŗĐ°ĐģĐĩŅ€ĐĩŅŽ", "show_hidden_people": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ ҁĐēҀҋ҂ҋ҅ ĐģŅŽĐ´ĐĩĐš", "show_in_timeline": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ ĐŊа Đ˛Ņ€ĐĩĐŧĐĩĐŊĐŊОК ҈ĐēаĐģĐĩ", - "show_in_timeline_setting_description": "ПоĐēĐ°ĐˇŅ‹Đ˛Đ°ĐšŅ‚Đĩ Ņ„ĐžŅ‚Đž и видĐĩĐž ŅŅ‚ĐžĐŗĐž ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ в ŅĐ˛ĐžĐĩĐš ĐģĐĩĐŊŅ‚Đĩ", + "show_in_timeline_setting_description": "ĐžŅ‚ĐžĐąŅ€Đ°ĐļĐ°Ņ‚ŅŒ Ņ„ĐžŅ‚Đž и видĐĩĐž ŅŅ‚ĐžĐŗĐž ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ ĐŊа ŅĐ˛ĐžĐĩĐš Đ˛Ņ€ĐĩĐŧĐĩĐŊĐŊОК ҈ĐēаĐģĐĩ", "show_keyboard_shortcuts": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ ŅĐžŅ‡ĐĩŅ‚Đ°ĐŊĐ¸Ņ ĐēĐģĐ°Đ˛Đ¸Ņˆ", "show_metadata": "ПоĐēĐ°ĐˇŅ‹Đ˛Đ°Ņ‚ŅŒ ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐŊŅ‹Đĩ", "show_or_hide_info": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ иĐģи ҁĐēŅ€Ņ‹Ņ‚ŅŒ иĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸ŅŽ", "show_password": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ ĐŋĐ°Ņ€ĐžĐģҌ", - "show_person_options": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ ĐžĐŋŅ†Đ¸Đ¸ ĐŋĐĩŅ€ŅĐžĐŊŅ‹", + "show_person_options": "ДĐĩĐšŅŅ‚Đ˛Đ¸Ņ ҁ ҇ĐĩĐģОвĐĩĐēĐžĐŧ", "show_progress_bar": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ ИĐŊдиĐēĐ°Ņ‚ĐžŅ€ Đ’Ņ‹ĐŋĐžĐģĐŊĐĩĐŊĐ¸Ņ", "show_search_options": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁҋ ĐŋĐžĐ¸ŅĐēа", "show_shared_links": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ ĐŋŅƒĐąĐģĐ¸Ņ‡ĐŊŅ‹Đĩ ҁҁҋĐģĐēи", "show_slideshow_transition": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ ҁĐģаКд-ŅˆĐžŅƒ ĐŋĐĩŅ€ĐĩŅ…ĐžĐ´", "show_supporter_badge": "ЗĐŊĐ°Ņ‡ĐžĐē ĐŋОддĐĩŅ€ĐļĐēи", "show_supporter_badge_description": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ СĐŊĐ°Ņ‡ĐžĐē ĐŋОддĐĩŅ€ĐļĐēи", + "show_text_search_menu": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ ĐŧĐĩĐŊŅŽ Ņ‚ĐĩĐēŅŅ‚ĐžĐ˛ĐžĐŗĐž ĐŋĐžĐ¸ŅĐēа", "shuffle": "ПĐĩŅ€ĐĩĐŧĐĩŅˆĐ°Ņ‚ŅŒ", "sidebar": "БоĐēĐžĐ˛Đ°Ņ ĐŋаĐŊĐĩĐģҌ", - "sidebar_display_description": "ПоĐēĐ°ĐˇŅ‹Đ˛Đ°Ņ‚ŅŒ ҁҁҋĐģĐē҃ ĐŊа ĐŋŅ€ĐĩĐ´ŅŅ‚Đ°Đ˛ĐģĐĩĐŊиĐĩ в йОĐēОвОК ĐŋаĐŊĐĩĐģи", + "sidebar_display_description": "ĐžŅ‚ĐžĐąŅ€Đ°ĐļĐ°Ņ‚ŅŒ Ņ€Đ°ĐˇĐ´ĐĩĐģ ĐŊа йОĐēОвОК ĐŋаĐŊĐĩĐģи", "sign_out": "Đ’Ņ‹Ņ…ĐžĐ´", "sign_up": "Đ—Đ°Ņ€ĐĩĐŗĐ¸ŅŅ‚Ņ€Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒŅŅ", "size": "РаСĐŧĐĩŅ€", @@ -1899,13 +1929,14 @@ "stacktrace": "ĐĸŅ€Đ°ŅŅĐ¸Ņ€ĐžĐ˛Đēа ҁ҂ĐĩĐēа", "start": "ĐĄŅ‚Đ°Ņ€Ņ‚", "start_date": "Đ”Đ°Ņ‚Đ° ĐŊĐ°Ņ‡Đ°Đģа", + "start_date_before_end_date": "Đ”Đ°Ņ‚Đ° ĐŊĐ°Ņ‡Đ°Đģа Đ´ĐžĐģĐļĐŊа ĐąŅ‹Ņ‚ŅŒ ĐŧĐĩĐŊҌ҈Đĩ Đ´Đ°Ņ‚Ņ‹ ĐžĐēĐžĐŊŅ‡Đ°ĐŊĐ¸Ņ", "state": "Đ ĐĩĐŗĐ¸ĐžĐŊ", "status": "ĐĄĐžŅŅ‚ĐžŅĐŊиĐĩ", "stop_casting": "ĐžŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ Ņ‚Ņ€Đ°ĐŊҁĐģŅŅ†Đ¸ŅŽ", "stop_motion_photo": "ПоĐēĐ°Đ´Ņ€ĐžĐ˛Đ°Ņ аĐŊиĐŧĐ°Ņ†Đ¸Ņ", - "stop_photo_sharing": "ЗаĐēŅ€Ņ‹Ņ‚ŅŒ Đ´ĐžŅŅ‚ŅƒĐŋ ĐŋĐ°Ņ€Ņ‚ĐŊŅ‘Ņ€Đ° Đē Đ˛Đ°ŅˆĐ¸Đŧ Ņ„ĐžŅ‚Đž?", - "stop_photo_sharing_description": "{partner} йОĐģҌ҈Đĩ ĐŊĐĩ ҁĐŧĐžĐļĐĩŅ‚ ĐŋĐžĐģŅƒŅ‡Đ¸Ņ‚ŅŒ Đ´ĐžŅŅ‚ŅƒĐŋ Đē Đ˛Đ°ŅˆĐ¸Đŧ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸ŅĐŧ.", - "stop_sharing_photos_with_user": "ĐŸŅ€ĐĩĐēŅ€Đ°Ņ‚Đ¸Ņ‚ŅŒ Đ´ĐĩĐģĐ¸Ņ‚ŅŒŅŅ ŅĐ˛ĐžĐ¸Đŧи Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸ŅĐŧи ҁ ŅŅ‚Đ¸Đŧ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģĐĩĐŧ", + "stop_photo_sharing": "ЗаĐēŅ€Ņ‹Ņ‚ŅŒ Đ´ĐžŅŅ‚ŅƒĐŋ ĐŋĐ°Ņ€Ņ‚ĐŊŅ‘Ņ€Ņƒ?", + "stop_photo_sharing_description": "ПоĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģҌ {partner} йОĐģҌ҈Đĩ ĐŊĐĩ иĐŧĐĩĐĩŅ‚ Đ´ĐžŅŅ‚ŅƒĐŋа Đē Đ˛Đ°ŅˆĐ¸Đŧ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸ŅĐŧ.", + "stop_sharing_photos_with_user": "ĐŸŅ€ĐĩĐēŅ€Đ°Ņ‚Đ¸Ņ‚ŅŒ Đ´ĐĩĐģĐ¸Ņ‚ŅŒŅŅ ŅĐ˛ĐžĐ¸Đŧи Ņ„ĐžŅ‚Đž и видĐĩĐž ҁ ŅŅ‚Đ¸Đŧ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģĐĩĐŧ", "storage": "ĐĨŅ€Đ°ĐŊиĐģĐ¸Ņ‰Đĩ", "storage_label": "МĐĩŅ‚Đēа Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đ°", "storage_quota": "ĐšĐ˛ĐžŅ‚Đ° Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đ°", @@ -1921,9 +1952,11 @@ "sync": "ХиĐŊŅ…Ņ€.", "sync_albums": "ХиĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ аĐģŅŒĐąĐžĐŧŅ‹", "sync_albums_manual_subtitle": "ХиĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ Đ˛ŅĐĩ ĐˇĐ°ĐŗŅ€ŅƒĐļĐĩĐŊĐŊŅ‹Đĩ Ņ„ĐžŅ‚Đž и видĐĩĐž в Đ˛Ņ‹ĐąŅ€Đ°ĐŊĐŊŅ‹Đĩ аĐģŅŒĐąĐžĐŧŅ‹ Đ´ĐģŅ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ", - "sync_local": "ХиĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ ĐģĐžĐēаĐģҌĐŊĐž", + "sync_local": "ЛоĐēаĐģҌĐŊĐ°Ņ ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Ņ", "sync_remote": "ХиĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Ņ ҁ ҁĐĩŅ€Đ˛ĐĩŅ€ĐžĐŧ", - "sync_upload_album_setting_subtitle": "ĐĄĐžĐˇĐ´Đ°Đ˛Đ°ĐšŅ‚Đĩ и ĐˇĐ°ĐŗŅ€ŅƒĐļĐ°ĐšŅ‚Đĩ ŅĐ˛ĐžĐ¸ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Đ¸ и видĐĩĐž в Đ˛Ņ‹ĐąŅ€Đ°ĐŊĐŊŅ‹Đĩ аĐģŅŒĐąĐžĐŧŅ‹ ĐŊа ҁĐĩŅ€Đ˛ĐĩŅ€ Immich", + "sync_status": "ĐĄŅ‚Đ°Ņ‚ŅƒŅ ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Đ¸", + "sync_status_subtitle": "ĐŸŅ€ĐžŅĐŧĐžŅ‚Ņ€ и ҃ĐŋŅ€Đ°Đ˛ĐģĐĩĐŊиĐĩ ŅĐ¸ŅŅ‚ĐĩĐŧОК ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐ¸ĐˇĐ°Ņ†Đ¸Đ¸", + "sync_upload_album_setting_subtitle": "ĐĄĐžĐˇĐ´Đ°Đ˛Đ°Ņ‚ŅŒ ĐŊа ҁĐĩŅ€Đ˛ĐĩŅ€Đĩ Ņ‚Đ°ĐēиĐĩ ĐļĐĩ аĐģŅŒĐąĐžĐŧŅ‹, ĐēаĐē Đ˛Ņ‹ĐąŅ€Đ°ĐŊĐŊŅ‹Đĩ ĐŊа ŅƒŅŅ‚Ņ€ĐžĐšŅŅ‚Đ˛Đĩ, и ĐˇĐ°ĐŗŅ€ŅƒĐļĐ°Ņ‚ŅŒ в ĐŊĐ¸Ņ… Ņ„ĐžŅ‚Đž и видĐĩĐž", "tag": "ĐĸĐĩĐŗ", "tag_assets": "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ Ņ‚ĐĩĐŗĐ¸", "tag_created": "ĐĸĐĩĐŗ {tag} ŅĐžĐˇĐ´Đ°ĐŊ", @@ -1937,8 +1970,8 @@ "template": "ШайĐģĐžĐŊ", "theme": "ĐĸĐĩĐŧа", "theme_selection": "Đ’Ņ‹ĐąĐžŅ€ Ņ‚ĐĩĐŧŅ‹", - "theme_selection_description": "ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐĩҁĐēи ŅƒŅŅ‚Đ°ĐŊавĐģĐ¸Đ˛Đ°Ņ‚ŅŒ Ņ‚ĐĩĐŧ҃ в ĐˇĐ°Đ˛Đ¸ŅĐ¸ĐŧĐžŅŅ‚Đ¸ ĐžŅ‚ ŅĐ¸ŅŅ‚ĐĩĐŧĐŊҋ҅ ĐŊĐ°ŅŅ‚Ņ€ĐžĐĩĐē Đ˛Đ°ŅˆĐĩĐŗĐž ĐąŅ€Đ°ŅƒĐˇĐĩŅ€Đ°", - "theme_setting_asset_list_storage_indicator_title": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ иĐŊдиĐēĐ°Ņ‚ĐžŅ€ Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đ° ĐŊа ĐŋĐģĐ¸Ņ‚ĐēĐ°Ņ… ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛", + "theme_selection_description": "ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐĩҁĐēи ŅƒŅŅ‚Đ°ĐŊавĐģĐ¸Đ˛Đ°Ņ‚ŅŒ ŅĐ˛ĐĩŅ‚ĐģŅƒŅŽ иĐģи ҂ґĐŧĐŊŅƒŅŽ Ņ‚ĐĩĐŧ҃ в ĐˇĐ°Đ˛Đ¸ŅĐ¸ĐŧĐžŅŅ‚Đ¸ ĐžŅ‚ ĐŊĐ°ŅŅ‚Ņ€ĐžĐĩĐē Đ˛Đ°ŅˆĐĩĐŗĐž ĐąŅ€Đ°ŅƒĐˇĐĩŅ€Đ°", + "theme_setting_asset_list_storage_indicator_title": "ĐžŅ‚ĐžĐąŅ€Đ°ĐļĐ°Ņ‚ŅŒ иĐŊдиĐēĐ°Ņ‚ĐžŅ€ Ņ…Ņ€Đ°ĐŊиĐģĐ¸Ņ‰Đ° ĐŊа ĐŋĐģĐ¸Ņ‚ĐēĐ°Ņ… ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛", "theme_setting_asset_list_tiles_per_row_title": "КоĐģĐ¸Ņ‡ĐĩŅŅ‚Đ˛Đž ĐžĐąŅŠĐĩĐēŅ‚ĐžĐ˛ в ŅŅ‚Ņ€ĐžĐēĐĩ ({count})", "theme_setting_colorful_interface_subtitle": "Đ”ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ ĐžŅ‚Ņ‚ĐĩĐŊĐžĐē Đē Ņ„ĐžĐŊ҃.", "theme_setting_colorful_interface_title": "ĐĻвĐĩŅ‚ Ņ„ĐžĐŊа", @@ -1982,6 +2015,7 @@ "trash_page_select_assets_btn": "Đ’Ņ‹ĐąŅ€Đ°ĐŊĐŊŅ‹Đĩ ĐžĐąŅŠĐĩĐē҂ҋ", "trash_page_title": "ĐšĐžŅ€ĐˇĐ¸ĐŊа ({count})", "trashed_items_will_be_permanently_deleted_after": "ĐžĐąŅŠĐĩĐē҂ҋ, Ņ…Ņ€Đ°ĐŊŅŅ‰Đ¸ĐĩŅŅ в ĐēĐžŅ€ĐˇĐ¸ĐŊĐĩ йОĐģĐĩĐĩ {days, plural, one {# Đ´ĐŊŅ} other {# Đ´ĐŊĐĩĐš}}, ŅƒĐ´Đ°ĐģŅŅŽŅ‚ŅŅ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐĩҁĐēи.", + "troubleshoot": "Đ”Đ¸Đ°ĐŗĐŊĐžŅŅ‚Đ¸Đēа", "type": "ĐĸиĐŋ", "unable_to_change_pin_code": "ĐžŅˆĐ¸ĐąĐēа ĐŋŅ€Đ¸ иСĐŧĐĩĐŊĐĩĐŊии PIN-ĐēОда", "unable_to_setup_pin_code": "ĐžŅˆĐ¸ĐąĐēа ĐŋŅ€Đ¸ ŅĐžĐˇĐ´Đ°ĐŊии PIN-ĐēОда", @@ -2037,11 +2071,10 @@ "use_biometric": "Đ˜ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ йиОĐŧĐĩŅ‚Ņ€Đ¸ŅŽ", "use_current_connection": "Đ˜ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ Ņ‚ĐĩĐēŅƒŅ‰ĐĩĐĩ ĐŋОдĐēĐģŅŽŅ‡ĐĩĐŊиĐĩ", "use_custom_date_range": "Đ˜ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģҌҁĐēиК диаĐŋаСОĐŊ Đ´Đ°Ņ‚", - "use_this_location": "Đ’Ņ‹ĐąŅ€Đ°Ņ‚ŅŒ ŅŅ‚Đž ĐŧĐĩŅŅ‚Đž", "user": "ПоĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģҌ", "user_has_been_deleted": "Đ­Ņ‚ĐžŅ‚ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģҌ ĐąŅ‹Đģ ŅƒĐ´Đ°ĐģŅ‘ĐŊ.", "user_id": "ID ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ", - "user_liked": "{user} ĐžŅ‚ĐŧĐĩŅ‚Đ¸Đģ(а) {type, select, photo {ŅŅ‚Đž Ņ„ĐžŅ‚Đž} video {ŅŅ‚Đž видĐĩĐž} asset {ŅŅ‚ĐžŅ‚ Ņ€ĐĩŅŅƒŅ€Ņ} other {ŅŅ‚ĐžŅ‚ аĐģŅŒĐąĐžĐŧ}}", + "user_liked": "ПоĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅŽ {user} ĐŊŅ€Đ°Đ˛Đ¸Ņ‚ŅŅ {type, select, photo {ŅŅ‚Đž Ņ„ĐžŅ‚Đž} video {ŅŅ‚Đž видĐĩĐž} asset {ŅŅ‚ĐžŅ‚ ĐžĐąŅŠĐĩĐēŅ‚} other {ŅŅ‚ĐžŅ‚ аĐģŅŒĐąĐžĐŧ}}", "user_pin_code_settings": "PIN-ĐēОд", "user_pin_code_settings_description": "ĐĐ°ŅŅ‚Ņ€ĐžĐšĐēа PIN-ĐēОда Đ´ĐģŅ Đ´ĐžŅŅ‚ŅƒĐŋа Đē ĐģĐ¸Ņ‡ĐŊОК ĐŋаĐŋĐēĐĩ", "user_privacy": "КоĐŊŅ„Đ¸Đ´ĐĩĐŊŅ†Đ¸Đ°ĐģҌĐŊĐžŅŅ‚ŅŒ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ", @@ -2076,7 +2109,7 @@ "view_in_timeline": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ ĐŊа Đ˛Ņ€ĐĩĐŧĐĩĐŊĐŊОК ҈ĐēаĐģĐĩ", "view_link": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ ҁҁҋĐģĐē҃", "view_links": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ ҁҁҋĐģĐēи", - "view_name": "ĐŸĐžŅĐŧĐžŅ‚Ņ€ĐĩŅ‚ŅŒ", + "view_name": "Вид", "view_next_asset": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ ҁĐģĐĩĐ´ŅƒŅŽŅ‰Đ¸Đš ĐžĐąŅŠĐĩĐēŅ‚", "view_previous_asset": "ПоĐēĐ°ĐˇĐ°Ņ‚ŅŒ ĐŋŅ€ĐĩĐ´Ņ‹Đ´ŅƒŅ‰Đ¸Đš ĐžĐąŅŠĐĩĐēŅ‚", "view_qr_code": "ĐŸĐžŅĐŧĐžŅ‚Ņ€ĐĩŅ‚ŅŒ QR ĐēОд", @@ -2099,5 +2132,6 @@ "yes": "Да", "you_dont_have_any_shared_links": "ĐŖ Đ˛Đ°Ņ ĐŊĐĩŅ‚ ĐŋŅƒĐąĐģĐ¸Ņ‡ĐŊҋ҅ ҁҁҋĐģĐžĐē", "your_wifi_name": "ИĐŧŅ Đ˛Đ°ŅˆĐĩĐš Wi-Fi ҁĐĩŅ‚Đ¸", - "zoom_image": "ĐŸŅ€Đ¸ĐąĐģĐ¸ĐˇĐ¸Ņ‚ŅŒ" + "zoom_image": "ИСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ ĐŧĐ°ŅŅˆŅ‚Đ°Đą", + "zoom_to_bounds": "ĐŖĐ˛ĐĩĐģĐ¸Ņ‡Đ¸Ņ‚ŅŒ Đ´Đž ĐŗŅ€Đ°ĐŊĐ¸Ņ†" } diff --git a/i18n/sk.json b/i18n/sk.json index f769373f90..97f4ca07f4 100644 --- a/i18n/sk.json +++ b/i18n/sk.json @@ -28,10 +28,12 @@ "add_to_album": "PridaÅĨ do albumu", "add_to_album_bottom_sheet_added": "PridanÊ do {album}", "add_to_album_bottom_sheet_already_exists": "UÅž je v {album}", + "add_to_album_bottom_sheet_some_local_assets": "NiektorÊ lokÃĄlne sÃēbory nebolo moÅžnÊ pridaÅĨ do albumu", "add_to_album_toggle": "PrepnÃēÅĨ vÃŊber pre {album}", "add_to_albums": "PridaÅĨ do albumov", "add_to_albums_count": "PridaÅĨ do albumov ({count})", "add_to_shared_album": "PridaÅĨ do zdieÄžanÊho albumu", + "add_upload_to_stack": "PridaÅĨ nahratÊ do zoskupenÃŊch", "add_url": "PridaÅĨ URL", "added_to_archive": "PridanÊ do archívu", "added_to_favorites": "PridanÊ do obÄžÃēbenÃŊch", @@ -123,6 +125,13 @@ "logging_enable_description": "PovoliÅĨ ukladanie zÃĄznamov", "logging_level_description": "Ak je povolenÊ, akÃē Ãēroveň zÃĄznamov pouÅžiÅĨ.", "logging_settings": "Ukladanie zÃĄznamov", + "machine_learning_availability_checks": "Kontroly dostupnosti", + "machine_learning_availability_checks_description": "Automaticky zistiÅĨ a uprednostniÅĨ dostupnÊ servery strojovÊho učenia", + "machine_learning_availability_checks_enabled": "PovoliÅĨ kontroly dostupnosti", + "machine_learning_availability_checks_interval": "Interval kontroly", + "machine_learning_availability_checks_interval_description": "Interval v milisekundÃĄch medzi kontrolami dostupnosti", + "machine_learning_availability_checks_timeout": "ČasovÃŊ limit poÅžiadavky", + "machine_learning_availability_checks_timeout_description": "ČasovÃŊ limit v milisekundÃĄch pre kontroly dostupnosti", "machine_learning_clip_model": "Model CLIP", "machine_learning_clip_model_description": "NÃĄzov modelu CLIP je uvedenÃŊ tu. Pamätajte, Åže pri zmene modelu je nutnÊ znovu spustiÅĨ Ãēlohu 'InteligentnÊ vyhÄžadÃĄvanie' pre vÅĄetky obrÃĄzky.", "machine_learning_duplicate_detection": "Detekcia duplikÃĄtov", @@ -356,7 +365,7 @@ "trash_enabled_description": "PovoliÅĨ funkcie koÅĄa", "trash_number_of_days": "Počet dní", "trash_number_of_days_description": "Počet dní, počas ktorÃŊch sa majÃē mÊdiÃĄ ponechaÅĨ v koÅĄi pred ich trvalÃŊm odstrÃĄnením", - "trash_settings": "KÃ´ÅĄ", + "trash_settings": "Nastavenia koÅĄa", "trash_settings_description": "SpravovaÅĨ nastavenia koÅĄa", "unlink_all_oauth_accounts": "OdpojiÅĨ vÅĄetky Ãēčty OAuth", "unlink_all_oauth_accounts_description": "Nezabudnite odpojiÅĨ vÅĄetky Ãēčty OAuth pred prechodom na novÊho poskytovateÄža.", @@ -387,8 +396,6 @@ "admin_password": "AdministrÃĄtorskÊ heslo", "administration": "AdministrÃĄcia", "advanced": "PokročilÊ", - "advanced_settings_beta_timeline_subtitle": "VyskÃēÅĄajte prostredie novej aplikÃĄcie", - "advanced_settings_beta_timeline_title": "Beta verzia časovej osi", "advanced_settings_enable_alternate_media_filter_subtitle": "TÃēto moÅžnosÅĨ pouÅžite na filtrovanie mÊdií počas synchronizÃĄcie na zÃĄklade alternatívnych kritÊrií. TÃēto moÅžnosÅĨ vyskÃēÅĄajte len vtedy, ak mÃĄte problÊmy s detekciou vÅĄetkÃŊch albumov v aplikÃĄcii.", "advanced_settings_enable_alternate_media_filter_title": "[EXPERIMENTÁLNE] PouÅžiÅĨ alternatívny filter synchronizÃĄcie albumu zariadenia", "advanced_settings_log_level_title": "Úroveň ukladania zÃĄznamov: {level}", @@ -425,6 +432,7 @@ "album_remove_user_confirmation": "Ste si istÃŊ, Åže chcete odstrÃĄniÅĨ pouŞívateÄža {user}?", "album_search_not_found": "Neboli nÃĄjdenÊ Åžiadne albumy zodpovedajÃēce vÃĄÅĄmu hÄžadaniu", "album_share_no_users": "VyzerÃĄ to, Åže ste tento album zdieÄžali so vÅĄetkÃŊmi pouŞívateÄžmi alebo nemÃĄte Åžiadneho pouŞívateÄža, s ktorÃŊm by ste ho mohli zdieÄžaÅĨ.", + "album_summary": "SÃēhrn albumu", "album_updated": "Album bol aktualizovanÃŊ", "album_updated_setting_description": "ObdrÅžaÅĨ e-mailovÊ upozornenie, keď v zdieÄžanom albume pribudnÃē novÊ poloÅžky", "album_user_left": "Opustil {album}", @@ -490,12 +498,14 @@ "asset_list_layout_settings_group_by_month_day": "Mesiac + deň", "asset_list_layout_sub_title": "Rozvrhnutie", "asset_list_settings_subtitle": "Nastavenia rozloÅženia mrieÅžky fotografií", - "asset_list_settings_title": "FotografickÃĄ mrieÅžka", + "asset_list_settings_title": "MrieÅžka fotografií", "asset_offline": "MÊdium je offline", - "asset_offline_description": "Toto externÃŊ obsah sa uÅž nenachÃĄdza na disku. PoÅžiadajte o pomoc svojho sprÃĄvcu Immich.", + "asset_offline_description": "Tento externÃĄ poloÅžka sa uÅž nenachÃĄdza na disku. Pre pomoc sa prosím obrÃĄÅĨte na sprÃĄvcu systÊmu Immich.", "asset_restored_successfully": "PoloÅžky boli ÃēspeÅĄne obnovenÊ", "asset_skipped": "PreskočenÊ", "asset_skipped_in_trash": "V koÅĄi", + "asset_trashed": "PoloÅžka bola vyhodenÃĄ", + "asset_troubleshoot": "RieÅĄenie problÊmov s poloÅžkami", "asset_uploaded": "NahranÊ", "asset_uploading": "NahrÃĄva saâ€Ļ", "asset_viewer_settings_subtitle": "Spravujte nastavenia prehliadača galÊrie", @@ -529,8 +539,10 @@ "autoplay_slideshow": "AutomatickÊ prehrÃĄvanie prezentÃĄcie", "back": "SpäÅĨ", "back_close_deselect": "SpäÅĨ, zavrieÅĨ alebo zruÅĄiÅĨ vÃŊber", + "background_backup_running_error": "V sÃēčasnosti prebieha zÃĄlohovanie na pozadí, nie je moÅžnÊ spustiÅĨ ručnÊ zÃĄlohovanie", "background_location_permission": "Povolenie na určenie polohy na pozadí", "background_location_permission_content": "Aby bolo moÅžnÊ prepínaÅĨ siete pri spustení na pozadí, musí maÅĨ aplikÃĄcia Immich *vÅždy* presnÃŊ prístup k polohe, aby mohla prečítaÅĨ nÃĄzov siete Wi-Fi", + "background_options": "MoÅžnosti pozadia", "backup": "ZÃĄlohovanie", "backup_album_selection_page_albums_device": "Albumy v zariadení ({count})", "backup_album_selection_page_albums_tap": "Ťuknutím na poloÅžku ju zahrniete, dvojitÃŊm ÅĨuknutím ju vylÃēčite", @@ -538,6 +550,7 @@ "backup_album_selection_page_select_albums": "VybraÅĨ albumy", "backup_album_selection_page_selection_info": "InformÃĄcie o vÃŊbere", "backup_album_selection_page_total_assets": "CelkovÃŊ počet jedinečnÃŊch sÃēborov", + "backup_albums_sync": "SynchronizÃĄcia zÃĄlohovanÃŊch albumov", "backup_all": "VÅĄetko", "backup_background_service_backup_failed_message": "ZÃĄlohovanie mÊdií zlyhalo. SkÃēÅĄam to znovaâ€Ļ", "backup_background_service_connection_failed_message": "Nepodarilo sa pripojiÅĨ k serveru. SkÃēÅĄam to znovaâ€Ļ", @@ -587,6 +600,7 @@ "backup_controller_page_turn_on": "PovoliÅĨ zÃĄlohovanie na popredí", "backup_controller_page_uploading_file_info": "NahrÃĄvanÃŊ sÃēbor", "backup_err_only_album": "Nie je moÅžnÊ odstrÃĄniÅĨ jedinÃŊ vybranÃŊ album", + "backup_error_sync_failed": "SynchronizÃĄcia sa nepodarila. Nie je moÅžnÊ spracovaÅĨ zÃĄlohu.", "backup_info_card_assets": "poloÅžiek", "backup_manual_cancelled": "ZruÅĄenÊ", "backup_manual_in_progress": "NahrÃĄvanie uÅž prebieha. VyskÃēÅĄajte neskôr", @@ -597,8 +611,6 @@ "backup_setting_subtitle": "SpravovaÅĨ nastavenia odosielania na pozadí a v popredí", "backup_settings_subtitle": "SpravovaÅĨ nastavenia nahrÃĄvania", "backward": "Dozadu", - "beta_sync": "Stav synchronizÃĄcie verzie Beta", - "beta_sync_subtitle": "SpravovaÅĨ novÃŊ systÊm synchronizÃĄcie", "biometric_auth_enabled": "BiometrickÊ overovanie je povolenÊ", "biometric_locked_out": "Ste vymknutí z biometrickÊho overovania", "biometric_no_options": "Nie sÃē k dispozícii Åžiadne biometrickÊ moÅžnosti", @@ -656,6 +668,8 @@ "change_pin_code": "ZmeniÅĨ PIN kÃŗd", "change_your_password": "ZmeniÅĨ heslo", "changed_visibility_successfully": "ViditeÄžnosÅĨ bola ÃēspeÅĄne zmenenÃĄ", + "charging": "Nabíja sa", + "charging_requirement_mobile_backup": "ZÃĄlohovanie na pozadí vyÅžaduje, aby bolo zariadenie nabíjanÊ", "check_corrupt_asset_backup": "SkontrolovaÅĨ, či nie sÃē poÅĄkodenÊ zÃĄlohy poloÅžiek", "check_corrupt_asset_backup_button": "VykonaÅĨ kontrolu", "check_corrupt_asset_backup_description": "SpustiÅĨ tÃēto kontrolu len cez Wi-Fi a po zÃĄlohovaní vÅĄetkÃŊch poloÅžiek. Tento postup môŞe trvaÅĨ niekoÄžko minÃēt.", @@ -690,10 +704,10 @@ "common_server_error": "Skontrolujte svoje sieÅĨovÊ pripojenie, uistite sa, Åže server je dostupnÃŊ a verzie aplikÃĄcie/server sÃē kompatibilnÊ.", "completed": "DokončenÊ", "confirm": "PotvrdiÅĨ", - "confirm_admin_password": "PotvrdiÅĨ AdministrÃĄtorskÊ Heslo", + "confirm_admin_password": "PotvrdiÅĨ heslo sprÃĄvcu", "confirm_delete_face": "Naozaj chcete z poloÅžky odstrÃĄniÅĨ tvÃĄr osoby {name}?", "confirm_delete_shared_link": "Ste si istÃŊ, Åže chcete odstrÃĄniÅĨ tento zdieÄžanÃŊ odkaz?", - "confirm_keep_this_delete_others": "VÅĄetky ostatnÊ poloÅžky v zÃĄsobníku budÃē odstrÃĄnenÊ okrem tejto poloÅžky. Naozaj chcete pokračovaÅĨ?", + "confirm_keep_this_delete_others": "VÅĄetky ostatnÊ poloÅžky v zoskupení budÃē odstrÃĄnenÊ okrem tejto poloÅžky. Naozaj chcete pokračovaÅĨ?", "confirm_new_pin_code": "PotvrdiÅĨ novÃŊ PIN kÃŗd", "confirm_password": "PotvrdiÅĨ heslo", "confirm_tag_face": "Chcete označiÅĨ tÃēto tvÃĄr ako {name}?", @@ -742,6 +756,7 @@ "create_user": "VytvoriÅĨ pouŞívateÄža", "created": "VytvorenÊ", "created_at": "VytvorenÊ", + "creating_linked_albums": "VytvÃĄranie prepojenÃŊch albumov...", "crop": "OrezaÅĨ", "curated_object_page_title": "Veci", "current_device": "SÃēčasnÊ zariadenie", @@ -891,7 +906,9 @@ "error": "Chyba", "error_change_sort_album": "Nepodarilo sa zmeniÅĨ poradie albumu", "error_delete_face": "Chyba pri odstraňovaní tvÃĄre z poloÅžky", + "error_getting_places": "Chyba pri získavaní polôh", "error_loading_image": "Nepodarilo sa načítaÅĨ obrÃĄzok", + "error_loading_partners": "Chyba pri načítaní partnerov: {error}", "error_saving_image": "Chyba: {error}", "error_tag_face_bounding_box": "Chyba pri označovaní tvÃĄre - nemoÅžno získaÅĨ sÃēradnice ohraničujÃēceho poÄža", "error_title": "Chyba - niečo sa pokazilo", @@ -926,7 +943,7 @@ "failed_to_remove_product_key": "Nepodarilo sa odstrÃĄniÅĨ produktovÃŊ kÄžÃēč", "failed_to_reset_pin_code": "PIN kÃŗd sa nepodarilo obnoviÅĨ", "failed_to_stack_assets": "Nepodarilo sa zoskupiÅĨ poloÅžky", - "failed_to_unstack_assets": "Nepodarilo sa rozdeliÅĨ poloÅžky", + "failed_to_unstack_assets": "Nepodarilo sa zruÅĄiÅĨ zoskupenie poloÅžiek", "failed_to_update_notification_status": "Nepodarilo sa aktualizovaÅĨ stav oznÃĄmenia", "import_path_already_exists": "TÃĄto cesta importu uÅž existuje.", "incorrect_email_or_password": "NesprÃĄvny e-mail alebo heslo", @@ -1040,7 +1057,7 @@ "export_database": "ExportovaÅĨ databÃĄzu", "export_database_description": "ExportovaÅĨ databÃĄzu SQLite", "extension": "Prípona", - "external": "ExternÃŊ", + "external": "ExternÃĄ", "external_libraries": "ExternÊ kniÅžnice", "external_network": "ExternÃĄ sieÅĨ", "external_network_sheet_info": "Ak nie ste v preferovanej sieti Wi-Fi, aplikÃĄcia sa pripojí k serveru prostredníctvom prvej z niÅžÅĄie uvedenÃŊch adries URL, na ktorÃē sa dostane, počnÃēc zhora nadol", @@ -1056,6 +1073,7 @@ "favorites_page_no_favorites": "ÅŊiadne obÄžÃēbenÊ mÊdiÃĄ", "feature_photo_updated": "HlavnÃŊ obrÃĄzok bol aktualizovanÃŊ", "features": "Funkcie", + "features_in_development": "Funkcie vo vÃŊvoji", "features_setting_description": "SpravovaÅĨ funkcie aplikÃĄcie", "file_name": "NÃĄzov sÃēboru", "file_name_or_extension": "NÃĄzov alebo prípona sÃēboru", @@ -1076,10 +1094,7 @@ "gcast_enabled": "Google Cast", "gcast_enabled_description": "TÃĄto funkcia načítava externÊ zdroje zo spoločnosti Google, aby mohla fungovaÅĨ.", "general": "VÅĄeobecnÊ", - "geolocation_instruction_all_have_location": "VÅĄetky poloÅžky pre tento dÃĄtum uÅž majÃē Ãēdaje o polohe. SkÃēste zobraziÅĨ vÅĄetky poloÅžky alebo vyberte inÃŊ dÃĄtum", "geolocation_instruction_location": "Kliknite na poloÅžku s GPS sÃēradnicami, aby ste pouÅžili jej polohu, alebo vyberte polohu priamo z mapy", - "geolocation_instruction_no_date": "Vyberte dÃĄtum, aby ste mohli spravovaÅĨ Ãēdaje o polohe pre fotografie a videÃĄ z danÊho dňa", - "geolocation_instruction_no_photos": "Pre tento dÃĄtum neboli nÃĄjdenÊ Åžiadne fotografie ani videÃĄ. Vyberte inÃŊ dÃĄtum, aby sa zobrazili", "get_help": "ZískaÅĨ pomoc", "get_wifiname_error": "Nepodarilo sa získaÅĨ nÃĄzov Wi-Fi siete. Uistite sa, Åže ste udelili potrebnÊ oprÃĄvnenia a ste pripojení k sieti Wi-Fi", "getting_started": "Začíname", @@ -1184,8 +1199,8 @@ "jobs": "Úlohy", "keep": "PonechaÅĨ", "keep_all": "PonechaÅĨ vÅĄetko", - "keep_this_delete_others": "PonechaÅĨ toto, odstrÃĄniÅĨ ostatnÊ", - "kept_this_deleted_others": "Ponechal tÃēto poloÅžku a odstrÃĄnil {count, plural, one {# poloÅžku} few {# poloÅžky} other {# poloÅžiek}}", + "keep_this_delete_others": "PonechaÅĨ tÃēto, odstrÃĄniÅĨ ostatnÊ", + "kept_this_deleted_others": "TÃĄto poloÅžka bola ponechanÃĄ a {count, plural, one {odstrÃĄnila sa # poloÅžka} few {odstrÃĄnili sa # poloÅžky} other {odstrÃĄnilo sa # poloÅžiek}}", "keyboard_shortcuts": "KlÃĄvesovÊ skratky", "language": "Jazyk", "language_no_results_subtitle": "SkÃēste upraviÅĨ hÄžadanÃŊ vÃŊraz", @@ -1223,6 +1238,7 @@ "local": "LokÃĄlne", "local_asset_cast_failed": "Nie je moÅžnÊ preniesÅĨ mÊdium, ktorÊ nie je nahranÊ na serveri", "local_assets": "LokÃĄlne poloÅžky", + "local_media_summary": "SÃēhrn lokÃĄlnych mÊdií", "local_network": "Miestna sieÅĨ", "local_network_sheet_info": "Pri pouÅžití zadanej siete Wi-Fi sa aplikÃĄcia pripojí k serveru prostredníctvom tejto URL adresy", "location_permission": "Povolenie na určenie polohy", @@ -1234,6 +1250,7 @@ "location_picker_longitude_hint": "Zadajte platnÃē zemepisnÃē dÄēÅžku", "lock": "ZamknÃēÅĨ", "locked_folder": "ZamknutÃŊ priečinok", + "log_detail_title": "Podrobnosti o zÃĄzname", "log_out": "OdhlÃĄsiÅĨ sa", "log_out_all_devices": "OdhlÃĄsiÅĨ vÅĄetky zariadenia", "logged_in_as": "PrihlÃĄsenÃŊ ako {user}", @@ -1264,6 +1281,7 @@ "login_password_changed_success": "AktualizÃĄcia hesla prebehla ÃēspeÅĄne", "logout_all_device_confirmation": "Ste si istÃŊ, Åže sa chcete odhlÃĄsiÅĨ zo vÅĄetkÃŊch zariadení?", "logout_this_device_confirmation": "Ste si istÃŊ, Åže sa chcete odhlÃĄsiÅĨ z tohoto zariadenia?", + "logs": "ZÃĄznamy", "longitude": "ZemepisnÃĄ dÄēÅžka", "look": "VzhÄžad", "loop_videos": "OpakovaÅĨ videÃĄ", @@ -1306,6 +1324,7 @@ "mark_as_read": "OznačiÅĨ ako prečítanÊ", "marked_all_as_read": "OznačenÊ vÅĄetko ako prečítanÊ", "matches": "Zhody", + "matching_assets": "VyhovujÃēce poloÅžky", "media_type": "Typ mÊdia", "memories": "Spomienky", "memories_all_caught_up": "Na dnes to je vÅĄetko", @@ -1346,6 +1365,7 @@ "name_or_nickname": "Meno alebo prezÃŊvka", "network_requirement_photos_upload": "PouÅžiÅĨ mobilnÊ dÃĄta na zÃĄlohovanie fotografií", "network_requirement_videos_upload": "PouÅžiÅĨ mobilnÊ dÃĄta na zÃĄlohovanie videí", + "network_requirements": "PoÅžiadavky na sieÅĨ", "network_requirements_updated": "PoÅžiadavky na sieÅĨ sa zmenili, obnovuje sa poradie zÃĄlohovania", "networking_settings": "SieÅĨ", "networking_subtitle": "SpravovaÅĨ nastavenia koncovÊho bodu servera", @@ -1356,33 +1376,39 @@ "new_person": "NovÃĄ osoba", "new_pin_code": "NovÃŊ PIN kÃŗd", "new_pin_code_subtitle": "Toto je vÃĄÅĄ prvÃŊ prístup k zamknutÊmu priečinku. Vytvorte si PIN kÃŗd na bezpečnÃŊ prístup k tejto strÃĄnke", + "new_timeline": "NovÃĄ časovÃĄ os", "new_user_created": "NovÃŊ pouŞívateÄž vytvorenÃŊ", "new_version_available": "JE DOSTUPNÁ NOVÁ VERZIA", "newest_first": "Najprv najnovÅĄie", "next": "Ďalej", "next_memory": "ĎalÅĄia spomienka", "no": "Nie", - "no_albums_message": "Vytvorí album na organizovanie fotiek a videí", + "no_albums_message": "Vytvorte album na usporiadanie svojich fotiek a videí", "no_albums_with_name_yet": "VyzerÃĄ, Åže zatiaÄž nemÃĄte album s tÃŊmto nÃĄzvom.", "no_albums_yet": "VyzerÃĄ, Åže zatiaÄž nemÃĄte Åžiadne albumy.", "no_archived_assets_message": "Archivujte fotografie a videÃĄ a skryte ich z vÃĄÅĄho zobrazenia fotografií", "no_assets_message": "KLIKNITE A NAHRAJTE SVOJU PRVÚ FOTKU", "no_assets_to_show": "ÅŊiadne poloÅžky", "no_cast_devices_found": "NenaÅĄli sa Åžiadne zariadenia na prenos", + "no_checksum_local": "Kontrola sÃēčtu nie je k dispozícii – nie je moÅžnÊ načítaÅĨ lokÃĄlne poloÅžky", + "no_checksum_remote": "Kontrola sÃēčtu nie je k dispozícii – nie je moÅžnÊ načítaÅĨ vzdialenÊ poloÅžky", "no_duplicates_found": "NenaÅĄli sa Åžiadne duplicity.", "no_exif_info_available": "Nie sÃē dostupnÊ exif Ãēdaje", "no_explore_results_message": "Nahrajte viac fotiek na objavovanie vaÅĄej zbierky.", "no_favorites_message": "Pridajte si obÄžÃēbenÊ, aby ste rÃŊchlo naÅĄli svoje najlepÅĄie obrÃĄzky a videÃĄ", - "no_libraries_message": "Vytvorí externÃē kniÅžnicu na prezeranie fotiek a videí", + "no_libraries_message": "Vytvorte externÃē kniÅžnicu na prezeranie fotiek a videí", + "no_local_assets_found": "Neboli nÃĄjdenÊ Åžiadne lokÃĄlne poloÅžky s touto kontrolnou sumou", "no_locked_photos_message": "Fotografie a videÃĄ v zamknutom priečinku sÃē skrytÊ a nezobrazujÃē sa pri prehÄžadÃĄvaní alebo vyhÄžadÃĄvaní v kniÅžnici.", "no_name": "Bez mena", "no_notifications": "ÅŊiadne oznÃĄmenia", "no_people_found": "NenaÅĄli sa Åžiadni vyhovujÃēci Äžudia", "no_places": "Bez miesta", + "no_remote_assets_found": "Neboli nÃĄjdenÊ Åžiadne vzdialenÊ poloÅžky s touto kontrolnou sumou", "no_results": "ÅŊiadne vÃŊsledky", "no_results_description": "SkÃēste synonymum alebo vÅĄeobecnejÅĄÃ­ vÃŊraz", - "no_shared_albums_message": "Vytvorí album na zdieÄžanie fotiek a videí s Äžuďmi vo vaÅĄej sieti", + "no_shared_albums_message": "Vytvorte album na zdieÄžanie fotiek a videí s Äžuďmi vo vaÅĄej sieti", "no_uploads_in_progress": "ÅŊiadne prebiehajÃēce nahrÃĄvanie", + "not_available": "NedostupnÊ", "not_in_any_album": "Nie je v Åžiadnom albume", "not_selected": "NevybranÊ", "note_apply_storage_label_to_previously_uploaded assets": "PoznÃĄmka: Ak chcete pouÅžiÅĨ Å títok ÃēloÅžiska na predtÃŊm nahranÊ mÊdiÃĄ, spustite príkaz", @@ -1425,7 +1451,7 @@ "other_devices": "ĎalÅĄie zariadenia", "other_entities": "OstatnÊ subjekty", "other_variables": "OstatnÊ premennÊ", - "owned": "VlastnenÊ", + "owned": "VlastnÊ", "owner": "Vlastník", "partner": "Partner", "partner_can_access": "{partner} môŞe pristupovaÅĨ", @@ -1485,7 +1511,7 @@ "person_hidden": "{name}{hidden, select, true { (skrytÊ)} other {}}", "photo_shared_all_users": "VyzerÃĄ, Åže zdieÄžate svoje fotky so vÅĄetkÃŊmi pouŞívateÄžmi alebo nemÃĄte Åžiadnych pouŞívateÄžov.", "photos": "Fotografie", - "photos_and_videos": "Fotografie & Videa", + "photos_and_videos": "Fotografie a videÃĄ", "photos_count": "{count, plural, one {{count, number} fotka} few {{count, number} fotky} other {{count, number} fotiek}}", "photos_from_previous_years": "Fotky z minulÃŊch rokov", "pick_a_location": "Vyberte polohu", @@ -1504,6 +1530,7 @@ "port": "Port", "preferences_settings_subtitle": "SpravovaÅĨ predvoÄžby aplikÃĄcie", "preferences_settings_title": "PredvoÄžby", + "preparing": "Pripravuje sa", "preset": "PredvoÄžba", "preview": "NÃĄhÄžad", "previous": "PredoÅĄlÊ", @@ -1520,7 +1547,7 @@ "profile_drawer_client_out_of_date_minor": "MobilnÃĄ aplikÃĄcia je zastaralÃĄ. Prosím aktualizujte na najnovÅĄiu verziu.", "profile_drawer_client_server_up_to_date": "Klient a server sÃē aktuÃĄlne", "profile_drawer_github": "GitHub", - "profile_drawer_readonly_mode": "ReÅžim iba na čítanie je aktivovanÃŊ. DvojitÃŊm ÅĨuknutím na ikonu obrÃĄzku pouŞívateÄža reÅžim opustíte.", + "profile_drawer_readonly_mode": "ReÅžim iba na čítanie je aktivovanÃŊ. DlhÃŊm stlačením ikony obrÃĄzku pouŞívateÄža reÅžim opustíte.", "profile_drawer_server_out_of_date_major": "Server je zastaralÃŊ. Prosím aktualizujte na najnovÅĄiu verziu.", "profile_drawer_server_out_of_date_minor": "Server je zastaralÃŊ. Prosím aktualizujte na najnovÅĄiu verziu.", "profile_image_of_user": "ProfilovÃŊ obrÃĄzok pouŞívateÄža {user}", @@ -1569,6 +1596,7 @@ "read_changelog": "PrečítaÅĨ zoznam zmien", "readonly_mode_disabled": "ReÅžim iba na čítanie je vypnutÃŊ", "readonly_mode_enabled": "ReÅžim iba na čítanie je zapnutÃŊ", + "ready_for_upload": "PripravenÊ na nahratie", "reassign": "PreradiÅĨ", "reassigned_assets_to_existing_person": "Opätovne {count, plural, one {priradenÃĄ # poloÅžka} few {priradenÊ # poloÅžky} other {priradenÃŊch # poloÅžiek}} k {name, select, null {existujÃēcej osobe} other {{name}}}", "reassigned_assets_to_new_person": "Opätovne {count, plural, one {priradenÃĄ # poloÅžka} few {priradenÊ # poloÅžky} other {priradenÃŊch # poloÅžiek}} novej osobe", @@ -1593,6 +1621,7 @@ "regenerating_thumbnails": "Pregenerovanie nÃĄhÄžadov", "remote": "VzdialenÊ", "remote_assets": "VzdialenÊ poloÅžky", + "remote_media_summary": "SÃēhrn vzdialenÃŊch mÊdií", "remove": "OdstrÃĄniÅĨ", "remove_assets_album_confirmation": "Naozaj chcete odstrÃĄniÅĨ {count, plural, one {# poloÅžku} few {# poloÅžky} other {# poloÅžiek}} z albumu?", "remove_assets_shared_link_confirmation": "Naozaj chcete odstrÃĄniÅĨ {count, plural, one {# poloÅžku} few {# poloÅžky} other {# poloÅžiek}} z tohoto zdieÄžanÊho odkazu?", @@ -1645,6 +1674,7 @@ "restore_user": "NavrÃĄtiÅĨ pouŞívateÄža", "restored_asset": "NavrÃĄtenÃĄ poloÅžka", "resume": "PokračovaÅĨ", + "resume_paused_jobs": "PokračovaÅĨ v {count, plural, one {# pozastavenej Ãēlohe} other {# pozastavenÃŊch ÃēlohÃĄch}}", "retry_upload": "ZopakovaÅĨ nahrÃĄvanie", "review_duplicates": "PreskÃēmaÅĨ duplikÃĄty", "review_large_files": "SkontrolovaÅĨ veÄžkÊ sÃēbory", @@ -1834,7 +1864,7 @@ "shared_link_options": "MoÅžnosti zdieÄžanÃŊch odkazov", "shared_link_password_description": "VyÅžadovaÅĨ heslo pre prístup k tomuto zdieÄžanÊmu odkazu", "shared_links": "ZdieÄžanÊ odkazy", - "shared_links_description": "ZdieÄžanie fotografií a videí pomocou odkazu", + "shared_links_description": "ZdieÄžajte fotografie a videÃĄ pomocou odkazu", "shared_photos_and_videos_count": "{assetCount, plural, few {# zdieÄžanÊ fotky a videÃĄ.} other {# zdieÄžanÃŊch fotiek a videí.}}", "shared_with_me": "ZdieÄžanÊ so mnou", "shared_with_partner": "ZdieÄžanÊ s {partner}", @@ -1849,10 +1879,8 @@ "shift_to_permanent_delete": "stlačte ⇧ na trvalÊ vymazanie poloÅžky", "show_album_options": "ZobraziÅĨ moÅžnosti albumu", "show_albums": "ZobraziÅĨ albumy", - "show_all_assets": "ZobraziÅĨ vÅĄetky poloÅžky", "show_all_people": "ZobraziÅĨ vÅĄetkÃŊch Äžudí", "show_and_hide_people": "ZobraziÅĨ a skryÅĨ Äžudí", - "show_assets_without_location": "ZobraziÅĨ poloÅžky bez polohy", "show_file_location": "ZobraziÅĨ umiestnenie sÃēboru", "show_gallery": "ZobraziÅĨ galÊriu", "show_hidden_people": "ZobraziÅĨ skrytÃŊch Äžudí", @@ -1869,6 +1897,7 @@ "show_slideshow_transition": "ZobraziÅĨ prechody v prezentÃĄcii", "show_supporter_badge": "Odznak podporovateÄža", "show_supporter_badge_description": "ZobraziÅĨ odznak podporovateÄža", + "show_text_search_menu": "ZobraziÅĨ ponuku vyhÄžadÃĄvania textu", "shuffle": "NÃĄhodnÊ poradie", "sidebar": "BočnÃŊ panel", "sidebar_display_description": "ZobraziÅĨ odkaz na zobrazenie v bočnom paneli", @@ -1890,20 +1919,21 @@ "sort_recent": "NajnovÅĄia fotografia", "sort_title": "NÃĄzov", "source": "Zdroj", - "stack": "Zoskupenie", + "stack": "ZoskupiÅĨ", "stack_action_prompt": "{count} zoskupenÃŊch", - "stack_duplicates": "ZoskupiÅĨ duplicity", + "stack_duplicates": "ZoskupiÅĨ duplikÃĄty", "stack_select_one_photo": "Vyberte jednu hlavnÃē fotku pre zoskupenie", "stack_selected_photos": "ZoskupiÅĨ vybratÊ fotky", "stacked_assets_count": "{count, plural, one {ZoskupenÃĄ # poloÅžka} few {ZoskupenÊ # poloÅžky} other {ZoskupenÃŊch # poloÅžiek}}", "stacktrace": "VÃŊpis zÃĄsobníku", "start": "SpustiÅĨ", "start_date": "PočiatočnÃŊ dÃĄtum", + "start_date_before_end_date": "DÃĄtum začiatku musí byÅĨ pred dÃĄtumom ukončenia", "state": "Å tÃĄt", "status": "Stav", "stop_casting": "ZastaviÅĨ prenos", "stop_motion_photo": "Stopmotion fotka", - "stop_photo_sharing": "ZastaviÅĨ zdieÄžanie vaÅĄich fotiek?", + "stop_photo_sharing": "ZastaviÅĨ zdieÄžanie vaÅĄich fotografií?", "stop_photo_sharing_description": "{partner} uÅž nebude maÅĨ prístup k vaÅĄim fotkÃĄm.", "stop_sharing_photos_with_user": "ZastaviÅĨ zdieÄžanie vaÅĄich fotiek s tÃŊmto pouŞívateÄžom", "storage": "Ukladací priestor", @@ -1923,6 +1953,8 @@ "sync_albums_manual_subtitle": "Synchronizujte vÅĄetky nahranÊ videÃĄ a fotografie s vybranÃŊmi zÃĄloÅžnÃŊmi albumami", "sync_local": "SynchronizovaÅĨ lokÃĄlne", "sync_remote": "SynchronizovaÅĨ vzdialenÊ", + "sync_status": "Stav synchronizÃĄcie", + "sync_status_subtitle": "ZobraziÅĨ a spravovaÅĨ systÊm synchronizÃĄcie", "sync_upload_album_setting_subtitle": "VytvÃĄrajte a nahrÃĄvajte svoje fotografie a videÃĄ do vybranÃŊch albumov na Immich", "tag": "Å títok", "tag_assets": "PridaÅĨ ÅĄtítky", @@ -1963,7 +1995,7 @@ "to_multi_select": "na viacnÃĄsobnÃŊ vÃŊber", "to_parent": "PrejsÅĨ k nadradenÊmu", "to_select": "na vÃŊber", - "to_trash": "KÃ´ÅĄ", + "to_trash": "Do koÅĄa", "toggle_settings": "PrepnÃēÅĨ nastavenie", "total": "Celkom", "total_usage": "CelkovÊ vyuÅžitie", @@ -1975,13 +2007,14 @@ "trash_emptied": "KÃ´ÅĄ vyprÃĄzdnenÃŊ", "trash_no_results_message": "VymazanÊ fotografie a videÃĄ sa zobrazia tu.", "trash_page_delete_all": "VymazaÅĨ vÅĄetky", - "trash_page_empty_trash_dialog_content": "Skutočne chcete vyprÃĄzdniÅĨ kÃ´ÅĄ? Tieto poloÅžky budÃē permanentne odstrÃĄnenÊ z aplikÃĄcie Immich", + "trash_page_empty_trash_dialog_content": "Skutočne chcete vyprÃĄzdniÅĨ kÃ´ÅĄ? Tieto poloÅžky budÃē natrvalo odstrÃĄnenÊ z aplikÃĄcie Immich", "trash_page_info": "MÊdiÃĄ v koÅĄi sa permanentne odstrÃĄnia po {days} dňoch", "trash_page_no_assets": "ÅŊiadne mÊdiÃĄ v koÅĄi", "trash_page_restore_all": "ObnoviÅĨ vÅĄetky", "trash_page_select_assets_btn": "VybraÅĨ mÊdiÃĄ", "trash_page_title": "KÃ´ÅĄ ({count})", "trashed_items_will_be_permanently_deleted_after": "PoloÅžky v koÅĄi sa natrvalo vymaÅžÃē po {days, plural, one {# dni} other {# dňoch}}.", + "troubleshoot": "RieÅĄenie problÊmov", "type": "Typ", "unable_to_change_pin_code": "Nie je moÅžnÊ zmeniÅĨ PIN kÃŗd", "unable_to_setup_pin_code": "Nie je moÅžnÊ nastaviÅĨ PIN kÃŗd", @@ -2007,9 +2040,9 @@ "unselect_all": "ZruÅĄiÅĨ vÃŊber vÅĄetkÃŊch", "unselect_all_duplicates": "ZruÅĄiÅĨ vÃŊber vÅĄetkÃŊch duplicít", "unselect_all_in": "ZruÅĄiÅĨ vÃŊber vÅĄetkÃŊch v {group}", - "unstack": "OdskupiÅĨ", + "unstack": "ZruÅĄiÅĨ zoskupenie", "unstack_action_prompt": "{count} nezoskupenÃŊch", - "unstacked_assets_count": "ZruÅĄenie zoskupenia pre {count, plural, one {# poloÅžku} few {# poloÅžky} other {# poloÅžiek}}", + "unstacked_assets_count": "ZruÅĄenÊ zoskupenia pre {count, plural, one {# poloÅžku} few {# poloÅžky} other {# poloÅžiek}}", "untagged": "Bez ÅĄtítku", "up_next": "To je vÅĄetko", "update_location_action_prompt": "AktualizovaÅĨ polohu {count} vybranÃŊch poloÅžiek pomocou:", @@ -2037,7 +2070,6 @@ "use_biometric": "PouÅžiÅĨ biometrickÊ Ãēdaje", "use_current_connection": "pouÅžiÅĨ aktuÃĄlne pripojenie", "use_custom_date_range": "PouÅžiÅĨ radÅĄej vlastnÃŊ rozsah dÃĄtumov", - "use_this_location": "Kliknutím pouÅžite polohu", "user": "PouŞívateÄž", "user_has_been_deleted": "Tento pouŞívateÄž bol vymazanÃŊ.", "user_id": "ID pouŞívateÄža", @@ -2085,7 +2117,7 @@ "view_user": "ZobraziÅĨ pouŞívateÄža", "viewer_remove_from_stack": "OdstrÃĄniÅĨ zo zoskupenia", "viewer_stack_use_as_main_asset": "PouÅžiÅĨ ako hlavnÃē fotku", - "viewer_unstack": "OdskupiÅĨ", + "viewer_unstack": "ZruÅĄiÅĨ zoskupenie", "visibility_changed": "ViditeÄžnosÅĨ zmenenÃĄ pre {count, plural, one {# osobu} few {# osoby} other {# osôb}}", "waiting": "ČakajÃēce", "warning": "Varovanie", @@ -2099,5 +2131,6 @@ "yes": "Áno", "you_dont_have_any_shared_links": "NemÃĄte Åžiadne zdielanÊ odkazy", "your_wifi_name": "VÃĄÅĄ nÃĄzov siete Wi-Fi", - "zoom_image": "PriblíŞiÅĨ obrÃĄzok" + "zoom_image": "PriblíŞiÅĨ obrÃĄzok", + "zoom_to_bounds": "ZvÃ¤ÄÅĄiÅĨ na okraje" } diff --git a/i18n/sl.json b/i18n/sl.json index e456c015b0..3939cdfa52 100644 --- a/i18n/sl.json +++ b/i18n/sl.json @@ -8,7 +8,7 @@ "actions": "Dejanja", "active": "Aktivno", "activity": "Aktivnost", - "activity_changed": "Aktivnost {enabled, select, true {omogočena} other {onemogočena}}", + "activity_changed": "Aktivnost je {enabled, select, true {omogočena} other {onemogočena}}", "add": "Dodaj", "add_a_description": "Dodaj opis", "add_a_location": "Dodaj lokacijo", @@ -28,10 +28,12 @@ "add_to_album": "Dodaj v album", "add_to_album_bottom_sheet_added": "Dodano v {album}", "add_to_album_bottom_sheet_already_exists": "ÅŊe v {album}", + "add_to_album_bottom_sheet_some_local_assets": "Nekaterih lokalnih sredstev ni bilo mogoče dodati v album", "add_to_album_toggle": "Preklopi izbiro za {album}", "add_to_albums": "Dodaj v albume", "add_to_albums_count": "Dodaj v albume ({count})", "add_to_shared_album": "Dodaj k deljenemu albumu", + "add_upload_to_stack": "Dodaj nalaganje v sklad", "add_url": "Dodaj URL", "added_to_archive": "Dodano v arhiv", "added_to_favorites": "Dodano med priljubljene", @@ -39,15 +41,15 @@ "admin": { "add_exclusion_pattern_description": "Dodajte vzorec izključitev. Globiranje z uporabo *, ** in ? je podprto. Če Åželite prezreti vse datoteke v katerem koli imeniku z imenom \"Raw\", uporabite \"**/Raw/**\". Če Åželite prezreti vse datoteke, ki se končajo na \".tif\", uporabite \"**/*.tif\". Če Åželite prezreti absolutno pot, uporabite \"/pot/za/ignoriranje/**\".", "admin_user": "SkrbniÅĄki uporabnik", - "asset_offline_description": "Sredstva zunanje knjiÅžnice ni več mogoče najti na disku in je bilo premaknjeno v koÅĄ. Če je bila datoteka premaknjena znotraj knjiÅžnice, preverite svojo časovnico za novo ustrezno sredstvo. Če Åželite obnoviti to sredstvo, zagotovite, da ima Immich dostop do spodnje poti datoteke, in skenirajte knjiÅžnico.", + "asset_offline_description": "Tega sredstva zunanje knjiÅžnice ni več mogoče najti na disku in je bilo premaknjeno v koÅĄ. Če je bila datoteka premaknjena znotraj knjiÅžnice, preverite svojo časovnico za novo ustrezno sredstvo. Če Åželite obnoviti to sredstvo, zagotovite, da ima Immich dostop do spodnje poti datoteke, in skenirajte knjiÅžnico.", "authentication_settings": "Nastavitve preverjanja pristnosti", "authentication_settings_description": "Upravljanje gesel, OAuth in drugih nastavitev preverjanja pristnosti", "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.", + "authentication_settings_reenable": "Za ponovno omogočanje uporabite streÅžniÅĄki ukaz.", "background_task_job": "Opravila v ozadju", "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_keep_last_amount": "Å tevilo prejÅĄnjih izpisov baze podatkov, ki jih je treba obdrÅžati", "backup_onboarding_1_description": "kopijo zunaj lokacije v oblaku ali na drugi fizični lokaciji.", "backup_onboarding_2_description": "lokalne kopije na različnih napravah. To vključuje glavne datoteke in lokalno varnostno kopijo teh datotek.", "backup_onboarding_3_description": "skupno ÅĄtevilo kopij vaÅĄih podatkov, vključno z izvirnimi datotekami. To vključuje 1 kopijo zunaj lokacije in 2 lokalni kopiji.", @@ -57,7 +59,7 @@ "backup_onboarding_title": "Varnostne kopije", "backup_settings": "Nastavitve izpisa baze podatkov", "backup_settings_description": "Upravljanje nastavitev izpisa podatkovne baze.", - "cleared_jobs": "RazčiÅĄÄeno opravilo za: {job}", + "cleared_jobs": "RazčiÅĄÄena opravila 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 {# vsebovani vir} two {# vsebovana vira} few {# vsebovane vire} other {vseh # vsebovanih virov}} in tega ni moÅžno razveljaviti. Datoteke bodo ostale na disku.", @@ -72,10 +74,10 @@ "disable_login": "Onemogoči prijavo", "duplicate_detection_job_description": "ZaÅženite strojno učenje na sredstvih, da zaznate podobne slike. ZanaÅĄa se na Pametno Iskanje", "exclusion_pattern_description": "Vzorci izključitev vam omogočajo, da prezrete datoteke in mape pri skeniranju knjiÅžnice. To je uporabno, če imate mape z datotekami, ki jih ne Åželite uvoziti, na primer datoteke RAW.", - "external_library_management": "Upravljanje zunanje knjiÅžnice", + "external_library_management": "Upravljanje zunanjih knjiÅžnic", "face_detection": "Zaznavanje obrazov", - "face_detection_description": "Zaznajte obraze v sredstvih s pomočjo strojnega učenja. Pri videoposnetkih se upoÅĄteva samo sličica. \"Vse\" (ponovno) obdela vsa sredstva. \"Manjkajoče\" postavi v čakalno vrsto sredstva, ki ÅĄe niso bila obdelana. Zaznani obrazi bodo postavljeni v čakalno vrsto za prepoznavanje obrazov, ko bo zaznavanje obrazov končano, in jih bodo zdruÅžili v obstoječe ali nove osebe.", - "facial_recognition_job_description": "ZdruÅži zaznane obraze v osebe. Ta korak se izvede po končanem zaznavanju obrazov. \"Vse\" (ponovno) zdruÅžuje vse obraze. \"Manjkajoče\", doda v čakalno vrsto obraze, ki nimajo dodeljene osebe.", + "face_detection_description": "Zaznavanje obrazov v sredstvih z uporabo strojnega učenja. Pri videoposnetkih se upoÅĄteva samo sličica. ÂģOsveÅžiÂĢ (ponovno) obdela vsa sredstva. ÂģPonastaviÂĢ dodatno izbriÅĄe vse trenutne podatke o obrazih. ÂģManjkajočaÂĢ uvrsti sredstva, ki ÅĄe niso bila obdelana, v čakalno vrsto. Zaznani obrazi bodo po končanem zaznavanju obrazov uvrÅĄÄeni v čakalno vrsto za prepoznavanje obrazov, pri čemer bodo zdruÅženi v obstoječe ali nove osebe.", + "facial_recognition_job_description": "ZdruÅži zaznane obraze v osebe. Ta korak se izvede po končanem zaznavanju obrazov. ÂģPonastaviÂĢ (ponovno) zdruÅži vse obraze. ÂģManjkajočaÂĢ uvrsti obraze, ki jim ni dodeljena oseba, v čakalno vrsto.", "failed_job_command": "Za opravilo {job} ukaz {command} ni uspel", "force_delete_user_warning": "OPOZORILO: S tem boste takoj odstranili uporabnika in vsa sredstva. Tega ni mogoče razveljaviti in datotek ni mogoče obnoviti.", "image_format": "Format", @@ -102,12 +104,12 @@ "image_thumbnail_title": "Nastavitve sličic", "job_concurrency": "{job} sočasnost", "job_created": "Opravilo ustvarjeno", - "job_not_concurrency_safe": "To opravilo ni sočasno-varno.", + "job_not_concurrency_safe": "To delo ni varno za sočasnost.", "job_settings": "Nastavitve opravil", "job_settings_description": "Upravljaj sočasnost opravil", "job_status": "Status opravila", - "jobs_delayed": "{jobCount, plural, other {# zadrÅžan}}", - "jobs_failed": "{jobCount, plural, other {# neuspeÅĄen}}", + "jobs_delayed": "{jobCount, plural, other {# zadrÅžani}}", + "jobs_failed": "{jobCount, plural, other {# neuspeÅĄni}}", "library_created": "Ustvarjena knjiÅžnica: {library}", "library_deleted": "KnjiÅžnica izbrisana", "library_import_path_description": "Določi mapo za uvoz. Ta mapa in njene podmape bodo pregledane za slike in video posnetke.", @@ -123,6 +125,13 @@ "logging_enable_description": "Omogoči dnevnik", "logging_level_description": "Nivo dnevnika, ko je le-ta omogočen.", "logging_settings": "Dnevnik", + "machine_learning_availability_checks": "Preverjanja razpoloÅžljivosti", + "machine_learning_availability_checks_description": "Samodejno zaznavanje in dajanje prednosti razpoloÅžljivim streÅžnikom strojnega učenja", + "machine_learning_availability_checks_enabled": "Omogoči preverjanja razpoloÅžljivosti", + "machine_learning_availability_checks_interval": "Interval preverjanja", + "machine_learning_availability_checks_interval_description": "Interval v milisekundah med preverjanji razpoloÅžljivosti", + "machine_learning_availability_checks_timeout": "Zahteva za časovno omejitev", + "machine_learning_availability_checks_timeout_description": "Časovna omejitev v milisekundah za preverjanje razpoloÅžljivosti", "machine_learning_clip_model": "model CLIP", "machine_learning_clip_model_description": "Ime CLIP modela iz seznama tukaj. Vedite, da boste morali po menjavi modela ponovno zagnati opravilo za 'Pametno iskanje' za vse slike.", "machine_learning_duplicate_detection": "Zaznavanje dvojnikov", @@ -131,7 +140,7 @@ "machine_learning_duplicate_detection_setting_description": "Za iskanje verjetnih dvojnikov uporabite vdelave CLIP", "machine_learning_enabled": "Omogoči strojno učenje", "machine_learning_enabled_description": "Če je onemogočeno, bodo vse funkcije strojnega učenja onemogočene ne glede na spodnje nastavitve.", - "machine_learning_facial_recognition": "Zaznavanje obrazov", + "machine_learning_facial_recognition": "Prepoznavanje obrazov", "machine_learning_facial_recognition_description": "Zaznavanje, prepoznavanje in zdruÅževanje obrazov na slikah", "machine_learning_facial_recognition_model": "Model za prepoznavanje obraza", "machine_learning_facial_recognition_model_description": "Modeli so navedeni v padajočem vrstnem redu glede na velikost. Večji modeli so počasnejÅĄi in uporabljajo več pomnilnika, vendar dajejo boljÅĄe rezultate. UpoÅĄtevajte, da morate po spremembi modela znova zagnati opravilo zaznavanja obrazov za vse slike.", @@ -144,7 +153,7 @@ "machine_learning_min_detection_score": "NajmanjÅĄi rezultat zaznavanja", "machine_learning_min_detection_score_description": "NajmanjÅĄi rezultat zaupanja za zaznavanje obraza od 0-1. NiÅžje vrednosti bodo zaznale več obrazov, vendar lahko povzročijo laÅžne pozitivne rezultate.", "machine_learning_min_recognized_faces": "NajmanjÅĄe ÅĄtevilo prepoznanih obrazov", - "machine_learning_min_recognized_faces_description": "NajmanjÅĄe ÅĄtevilo prepoznanih obrazov za osebo, ki se ustvari. Če to povečate, postane prepoznavanje obraza natančnejÅĄe na račun večje moÅžnosti, da obraz ni dodeljen osebi.", + "machine_learning_min_recognized_faces_description": "NajmanjÅĄe ÅĄtevilo prepoznanih obrazov za osebo, da se ustvari. Če to povečate, postane prepoznavanje obraza natančnejÅĄe na račun večje moÅžnosti, da obraz ni dodeljen osebi.", "machine_learning_settings": "Nastavitve strojnega učenja", "machine_learning_settings_description": "Upravljajte funkcije in nastavitve strojnega učenja", "machine_learning_smart_search": "Pametno iskanje", @@ -176,41 +185,41 @@ "metadata_settings": "Nastavitve metapodatkov", "metadata_settings_description": "Upravljanje nastavitev metapodatkov", "migration_job": "Migracija", - "migration_job_description": "Preselite sličice za sredstva in obraze v najnovejÅĄo strukturo map", + "migration_job_description": "Prenesite sličice za sredstva in obraze v najnovejÅĄo strukturo map", "nightly_tasks_cluster_faces_setting_description": "ZaÅženi prepoznavanje obrazov na novo zaznanih obrazih", "nightly_tasks_cluster_new_faces_setting": "ZdruÅžite nove obraze", "nightly_tasks_database_cleanup_setting": "Naloge čiÅĄÄenja baze podatkov", "nightly_tasks_database_cleanup_setting_description": "Očistite stare, potekle podatke iz baze podatkov", - "nightly_tasks_generate_memories_setting": "Ustvarjajte spomine", - "nightly_tasks_generate_memories_setting_description": "Ustvarite nove spomine iz sredstev", + "nightly_tasks_generate_memories_setting": "Ustvari spomine", + "nightly_tasks_generate_memories_setting_description": "Ustvari nove spomine iz sredstev", "nightly_tasks_missing_thumbnails_setting": "Ustvari manjkajoče sličice", "nightly_tasks_missing_thumbnails_setting_description": "Sredstva brez sličic postavite v čakalno vrsto za ustvarjanje sličic", "nightly_tasks_settings": "Nastavitve nočnih opravil", "nightly_tasks_settings_description": "Upravljajte nočne naloge", "nightly_tasks_start_time_setting": "Začetni čas", "nightly_tasks_start_time_setting_description": "Čas, ko streÅžnik začne izvajati nočne naloge", - "nightly_tasks_sync_quota_usage_setting": "Poraba kvote za sinhronizacijo", + "nightly_tasks_sync_quota_usage_setting": "Posodobi kvoto porabljenega prostora", "nightly_tasks_sync_quota_usage_setting_description": "Posodobi kvoto shrambe uporabnikov glede na trenutno uporabo", "no_paths_added": "Ni dodanih poti", - "no_pattern_added": "Brez dodanega vzorca", + "no_pattern_added": "Nobenega dodanega vzorca", "note_apply_storage_label_previous_assets": "Opomba: Če Åželite oznako za shranjevanje uporabiti za predhodno naloÅžena sredstva, zaÅženite", "note_cannot_be_changed_later": "OPOMBA: Tega pozneje ni mogoče spremeniti!", - "notification_email_from_address": "Iz naslova", - "notification_email_from_address_description": "E-poÅĄtni naslov poÅĄiljatelja, na primer: \"Immich Photo Server \". Uporabite naslov, s katerega lahko poÅĄiljate e-poÅĄto.", + "notification_email_from_address": "Od naslova", + "notification_email_from_address_description": "PoÅĄiljateljev e-poÅĄtni naslov, na primer: \"Immich Photo Server \". Uporabite naslov, s katerega lahko poÅĄiljate e-poÅĄto.", "notification_email_host_description": "Gostitelj e-poÅĄtnega streÅžnika (npr. smtp.immich.app)", "notification_email_ignore_certificate_errors": "Prezri napake potrdil", "notification_email_ignore_certificate_errors_description": "Prezri napake pri preverjanju potrdila TLS (ni priporočljivo)", "notification_email_password_description": "Geslo za uporabo pri preverjanju pristnosti z e-poÅĄtnim streÅžnikom", "notification_email_port_description": "Vrata e-poÅĄtnega streÅžnika (npr. 25, 465 ali 587)", - "notification_email_sent_test_email_button": "PoÅĄljite testno e-poÅĄto in shranite", + "notification_email_sent_test_email_button": "PoÅĄljite testno e-poÅĄto in shrani", "notification_email_setting_description": "Nastavitve za poÅĄiljanje e-poÅĄtnih obvestil", "notification_email_test_email": "PoÅĄlji testno e-poÅĄto", - "notification_email_test_email_failed": "PoÅĄiljanje testnega e-poÅĄtnega sporočila ni uspelo, preverite svoje vrednosti", + "notification_email_test_email_failed": "PoÅĄiljanje testnega e-poÅĄtnega sporočila ni uspelo, preverite svoje podatke", "notification_email_test_email_sent": "Testno e-poÅĄtno sporočilo je bilo poslano na {email}. Prosimo, preverite svoj nabiralnik.", "notification_email_username_description": "UporabniÅĄko ime za uporabo pri preverjanju pristnosti z e-poÅĄtnim streÅžnikom", "notification_enable_email_notifications": "Omogoči e-poÅĄtna obvestila", "notification_settings": "Nastavitve obvestil", - "notification_settings_description": "Upravljajte nastavitve obvestil, vključno z e-poÅĄto", + "notification_settings_description": "Upravljaj z nastavitvami obvestil, vključno z e-poÅĄto", "oauth_auto_launch": "Samodejni zagon", "oauth_auto_launch_description": "Samodejno zaÅženite tok prijave OAuth, ko obiÅĄÄete stran za prijavo", "oauth_auto_register": "Samodejna registracija", @@ -221,7 +230,7 @@ "oauth_mobile_redirect_uri": "Mobilni preusmeritveni URI", "oauth_mobile_redirect_uri_override": "Preglasitev URI preusmeritve za mobilne naprave", "oauth_mobile_redirect_uri_override_description": "Omogoči, ko ponudnik OAuth ne dovoli mobilnega URI-ja, kot je ''{callback}''", - "oauth_role_claim": "Zahteva vloge", + "oauth_role_claim": "Zahteva za vlogo", "oauth_role_claim_description": "Samodejno dodeli skrbniÅĄki dostop na podlagi prisotnosti tega zahtevka. Zahtevek ima lahko ÂģuporabnikÂĢ ali ÂģskrbnikÂĢ.", "oauth_settings": "OAuth", "oauth_settings_description": "Upravljanje nastavitev prijave OAuth", @@ -241,13 +250,13 @@ "person_cleanup_job": "ČiÅĄÄenje osebe", "quota_size_gib": "Velikost kvote (GiB)", "refreshing_all_libraries": "OsveÅževanje vseh knjiÅžnic", - "registration": "Administratorska registracija", + "registration": "Registracija administratorja", "registration_description": "Ker ste prvi uporabnik v sistemu, boste dodeljeni kot skrbnik in ste odgovorni za skrbniÅĄka opravila, dodatne uporabnike pa boste ustvarili sami.", "require_password_change_on_login": "Od uporabnika zahtevajte spremembo gesla ob prvi prijavi", "reset_settings_to_default": "Ponastavi nastavitve na privzete", "reset_settings_to_recent_saved": "Ponastavite nastavitve na nedavno shranjene nastavitve", "scanning_library": "Pregledovanje knjiÅžnice", - "search_jobs": "Iskanje opravilâ€Ļ", + "search_jobs": "IÅĄÄi opravilaâ€Ļ", "send_welcome_email": "PoÅĄlji pozdravno e-poÅĄto", "server_external_domain_settings": "Zunanja domena", "server_external_domain_settings_description": "Domena za javne skupne povezave, vključno s http(s)://", @@ -256,7 +265,7 @@ "server_settings": "Nastavitve streÅžnika", "server_settings_description": "Upravljanje nastavitev streÅžnika", "server_welcome_message": "Pozdravno sporočilo", - "server_welcome_message_description": "Sporočilo, ki se prikaÅže na strani za prijavo.", + "server_welcome_message_description": "Sporočilo prikazano na prijavni strani.", "sidecar_job": "Stranski metapodatki", "sidecar_job_description": "Odkrijte ali sinhronizirajte stranske metapodatke iz datotečnega sistema", "slideshow_duration_description": "Å tevilo sekund za prikaz posamezne slike", @@ -264,7 +273,7 @@ "storage_template_date_time_description": "Časovni Åžig ustvarjanja sredstva se uporablja za informacije o datumu in času", "storage_template_date_time_sample": "Vzorec časa {date}", "storage_template_enable_description": "Omogoči mehanizem predloge za shranjevanje", - "storage_template_hash_verification_enabled": "Preverjanje zgoÅĄÄevanja je omogočeno", + "storage_template_hash_verification_enabled": "Omogočeno preverjanje zgoÅĄÄene vrednosti", "storage_template_hash_verification_enabled_description": "Omogoči preverjanje zgoÅĄÄene vrednosti, tega ne onemogočite, razen če niste prepričani o posledicah", "storage_template_migration": "Selitev predloge za shranjevanje", "storage_template_migration_description": "Uporabi trenutno {template} za predhodno naloÅžena sredstva", @@ -283,7 +292,7 @@ "template_email_invite_album": "Predloga povabila v album", "template_email_preview": "Predogled", "template_email_settings": "E-poÅĄtne predloge", - "template_email_update_album": "Predloga posodobitve albuma", + "template_email_update_album": "Posodobi predlogo albuma", "template_email_welcome": "Predloga pozdravnega e-poÅĄtnega sporočila", "template_settings": "Predloge obvestil", "template_settings_description": "Upravljanje predlog po meri za obvestila", @@ -299,14 +308,14 @@ "transcoding_acceleration_qsv": "Hitra sinhronizacija (zahteva procesor Intel 7. generacije ali novejÅĄi)", "transcoding_acceleration_rkmpp": "RKMPP (samo na Rockchip SOC)", "transcoding_acceleration_vaapi": "VAAPI", - "transcoding_accepted_audio_codecs": "Sprejeti zvočni kodeki", + "transcoding_accepted_audio_codecs": "Dovoljeni zvočni kodeki", "transcoding_accepted_audio_codecs_description": "Izberite, katerih zvočnih kodekov ni treba prekodirati. Uporablja se samo za določene politike prekodiranja.", "transcoding_accepted_containers": "Sprejeti zabojniki", "transcoding_accepted_containers_description": "Izberite, katerih formatov zabojnika ni treba ponovno muksirati v MP4. Uporablja se samo za določene politike prekodiranja.", "transcoding_accepted_video_codecs": "Podprti video kodeki", "transcoding_accepted_video_codecs_description": "Izberite, katerih video kodekov ni treba prekodirati. Uporablja se samo za določene politike prekodiranja.", - "transcoding_advanced_options_description": "MoÅžnosti večini uporabnikov ne bi bilo treba spreminjati", - "transcoding_audio_codec": "Avdio kodek", + "transcoding_advanced_options_description": "MoÅžnosti, ki jih večini uporabnikov ne treba spreminjati", + "transcoding_audio_codec": "Zvočni kodek", "transcoding_audio_codec_description": "Opus je najbolj kakovostna moÅžnost, vendar ima slabÅĄo zdruÅžljivost s starimi napravami ali programsko opremo.", "transcoding_bitrate_description": "Videoposnetki, ki presegajo največjo bitno hitrost ali niso v sprejemljivem formatu", "transcoding_codecs_learn_more": "Če Åželite izvedeti več o tukaj uporabljeni terminologiji, glejte dokumentacijo FFmpeg za kodek H.264, kodek HEVC in VP9 kodek.", @@ -387,8 +396,6 @@ "admin_password": "SkrbniÅĄko geslo", "administration": "Administracija", "advanced": "Napredno", - "advanced_settings_beta_timeline_subtitle": "Preizkusite novo izkuÅĄnjo aplikacije", - "advanced_settings_beta_timeline_title": "Časovnica beta različice", "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: {level}", @@ -425,6 +432,7 @@ "album_remove_user_confirmation": "Ali ste prepričani, da Åželite odstraniti {user}?", "album_search_not_found": "Ni najdenih albumov, ki bi ustrezali vaÅĄemu iskanju", "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_summary": "Povzetek albuma", "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}", @@ -496,6 +504,8 @@ "asset_restored_successfully": "Sredstvo uspeÅĄno obnovljeno", "asset_skipped": "Preskočeno", "asset_skipped_in_trash": "V smetnjak", + "asset_trashed": "Sredstvo je bilo premaknjeno v koÅĄ", + "asset_troubleshoot": "Odpravljanje teÅžav s sredstvi", "asset_uploaded": "NaloÅženo", "asset_uploading": "Nalaganjeâ€Ļ", "asset_viewer_settings_subtitle": "Upravljaj nastavitve pregledovalnika galerije", @@ -529,8 +539,10 @@ "autoplay_slideshow": "Samodejno predvajanje diaprojekcije", "back": "Nazaj", "back_close_deselect": "Nazaj, zaprite ali prekličite izbiro", + "background_backup_running_error": "Varnostno kopiranje v ozadju se trenutno izvaja, ročnega varnostnega kopiranja ni mogoče zagnati", "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", + "background_options": "MoÅžnosti ozadja", "backup": "Varnostna kopija", "backup_album_selection_page_albums_device": "Albumi v napravi ({count})", "backup_album_selection_page_albums_tap": "Tapnite za vključitev, dvakrat tapnite za izključitev", @@ -538,6 +550,7 @@ "backup_album_selection_page_select_albums": "Izberi albume", "backup_album_selection_page_selection_info": "Informacije o izbiri", "backup_album_selection_page_total_assets": "Skupaj unikatnih sredstev", + "backup_albums_sync": "Sinhronizacija varnostnih kopij albumov", "backup_all": "Vse", "backup_background_service_backup_failed_message": "Varnostno kopiranje sredstev ni uspelo. Ponovno poskuÅĄamâ€Ļ", "backup_background_service_connection_failed_message": "Povezava s streÅžnikom ni uspela. Ponovno poskuÅĄamâ€Ļ", @@ -587,6 +600,7 @@ "backup_controller_page_turn_on": "Vklopite varnostno kopiranje v ospredju", "backup_controller_page_uploading_file_info": "Nalaganje podatkov o datoteki", "backup_err_only_album": "Edinega albuma ni mogoče odstraniti", + "backup_error_sync_failed": "Sinhronizacija ni uspela. Varnostne kopije ni mogoče obdelati.", "backup_info_card_assets": "sredstva", "backup_manual_cancelled": "Preklicano", "backup_manual_in_progress": "Nalaganje Åže poteka. Poskusite čez nekaj časa", @@ -597,8 +611,6 @@ "backup_setting_subtitle": "Upravljaj nastavitve nalaganja v ozadju in ospredju", "backup_settings_subtitle": "Upravljanje nastavitev nalaganja", "backward": "Nazaj", - "beta_sync": "Stanje sinhronizacije beta različice", - "beta_sync_subtitle": "Upravljanje novega sistema sinhronizacije", "biometric_auth_enabled": "Biometrična avtentikacija omogočena", "biometric_locked_out": "Biometrična avtentikacija vam je onemogočena", "biometric_no_options": "Biometrične moÅžnosti niso na voljo", @@ -656,6 +668,8 @@ "change_pin_code": "Spremeni PIN kodo", "change_your_password": "Spremenite geslo", "changed_visibility_successfully": "UspeÅĄno spremenjena vidnost", + "charging": "Polnjenje", + "charging_requirement_mobile_backup": "Za varnostno kopiranje v ozadju je potrebno polnjenje naprave", "check_corrupt_asset_backup": "Preverite poÅĄkodovane varnostne kopije sredstev", "check_corrupt_asset_backup_button": "Izvedi preverjanje", "check_corrupt_asset_backup_description": "To preverjanje zaÅženite samo prek omreÅžja Wi-Fi in potem, ko so vsa sredstva varnostno kopirana. Postopek lahko traja nekaj minut.", @@ -742,6 +756,7 @@ "create_user": "Ustvari uporabnika", "created": "Ustvarjeno", "created_at": "Ustvarjeno", + "creating_linked_albums": "Ustvarjanje povezanih albumov ...", "crop": "Obrezovanje", "curated_object_page_title": "Stvari", "current_device": "Trenutna naprava", @@ -891,7 +906,9 @@ "error": "Napaka", "error_change_sort_album": "Vrstnega reda albuma ni bilo mogoče spremeniti", "error_delete_face": "Napaka pri brisanju obraza iz sredstva", + "error_getting_places": "Napaka pri pridobivanju mest", "error_loading_image": "Napaka pri nalaganju slike", + "error_loading_partners": "Napaka pri nalaganju partnerjev: {error}", "error_saving_image": "Napaka: {error}", "error_tag_face_bounding_box": "Napaka pri označevanju obraza - ni mogoče pridobiti koordinat omejevalnega okvirja", "error_title": "Napaka - nekaj je ÅĄlo narobe", @@ -1022,6 +1039,7 @@ "exif_bottom_sheet_description_error": "Napaka pri posodabljanju opisa", "exif_bottom_sheet_details": "PODROBNOSTI", "exif_bottom_sheet_location": "LOKACIJA", + "exif_bottom_sheet_no_description": "Ni opisa", "exif_bottom_sheet_people": "OSEBE", "exif_bottom_sheet_person_add_person": "Dodaj ime", "exit_slideshow": "Zapustite diaprojekcijo", @@ -1056,6 +1074,7 @@ "favorites_page_no_favorites": "Ni priljubljenih sredstev", "feature_photo_updated": "Funkcijska fotografija je posodobljena", "features": "Funkcije", + "features_in_development": "Funkcije v razvoju", "features_setting_description": "Upravljaj funkcije aplikacije", "file_name": "Ime datoteke", "file_name_or_extension": "Ime ali končnica datoteke", @@ -1076,10 +1095,7 @@ "gcast_enabled": "Google Cast", "gcast_enabled_description": "Ta funkcija za delovanje nalaga zunanje vire iz Googla.", "general": "SploÅĄno", - "geolocation_instruction_all_have_location": "Vsa sredstva za ta datum Åže imajo podatke o lokaciji. Poskusite prikazati vsa sredstva ali izberite drug datum", "geolocation_instruction_location": "Kliknite na sredstvo z GPS koordinatami, da uporabite njegovo lokacijo, ali pa izberite lokacijo neposredno na zemljevidu", - "geolocation_instruction_no_date": "Izberite datum za upravljanje podatkov o lokaciji za fotografije in videoposnetke s tega dne", - "geolocation_instruction_no_photos": "Za ta datum ni bilo najdenih fotografij ali videoposnetkov. Izberite drug datum, da jih prikaÅžete", "get_help": "PoiÅĄÄite pomoč", "get_wifiname_error": "Imena Wi-Fi ni bilo mogoče dobiti. Prepričajte se, da ste podelili potrebna dovoljenja in ste povezani v omreÅžje Wi-Fi", "getting_started": "Začetek", @@ -1223,6 +1239,7 @@ "local": "Lokalno", "local_asset_cast_failed": "Sredstva, ki niso naloÅžena na streÅžnik, ni mogoče predvajati", "local_assets": "Lokalna sredstva", + "local_media_summary": "Povzetek lokalnih medijev", "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", @@ -1234,6 +1251,7 @@ "location_picker_longitude_hint": "Tukaj vnesi svojo zemljepisno dolÅžino", "lock": "Zaklepanje", "locked_folder": "Zaklenjena mapa", + "log_detail_title": "Podrobnosti dnevnika", "log_out": "Odjava", "log_out_all_devices": "Odjava vseh naprav", "logged_in_as": "Prijavljen kot {user}", @@ -1264,6 +1282,7 @@ "login_password_changed_success": "Geslo je bilo uspeÅĄno posodobljeno", "logout_all_device_confirmation": "Ali ste prepričani, da Åželite odjaviti vse naprave?", "logout_this_device_confirmation": "Ali ste prepričani, da se Åželite odjaviti iz te naprave?", + "logs": "Dnevniki", "longitude": "Zemljepisna dolÅžina", "look": "Izgled", "loop_videos": "Zanka videoposnetkov", @@ -1306,6 +1325,7 @@ "mark_as_read": "Označi kot prebrano", "marked_all_as_read": "Označeno vse kot prebrano", "matches": "Ujemanja", + "matching_assets": "Ujemajoča se sredstva", "media_type": "Vrsta medija", "memories": "Spomini", "memories_all_caught_up": "Vse dohiteno", @@ -1346,6 +1366,7 @@ "name_or_nickname": "Ime ali vzdevek", "network_requirement_photos_upload": "Uporaba mobilnih podatkov za varnostno kopiranje fotografij", "network_requirement_videos_upload": "Uporaba mobilnih podatkov za varnostno kopiranje videoposnetkov", + "network_requirements": "OmreÅžne zahteve", "network_requirements_updated": "OmreÅžne zahteve so se spremenile, ponastavitev čakalne vrste za varnostno kopiranje", "networking_settings": "OmreÅžje", "networking_subtitle": "Upravljaj nastavitve končne točke streÅžnika", @@ -1356,6 +1377,7 @@ "new_person": "Nova oseba", "new_pin_code": "Nova PIN koda", "new_pin_code_subtitle": "To je vaÅĄ prvi dostop do zaklenjene mape. Ustvarite PIN kodo za varen dostop do te strani", + "new_timeline": "Nova časovnica", "new_user_created": "Nov uporabnik ustvarjen", "new_version_available": "NA VOLJO JE NOVA RAZLIČICA", "newest_first": "Najprej najnovejÅĄe", @@ -1369,20 +1391,25 @@ "no_assets_message": "KLIKNITE ZA NALOÅŊITEV SVOJE PRVE FOTOGRAFIJE", "no_assets_to_show": "Ni sredstev za prikaz", "no_cast_devices_found": "Naprav za predvajanje ni bilo mogoče najti", + "no_checksum_local": "Kontrolna vsota ni na voljo – lokalnih sredstev ni mogoče pridobiti", + "no_checksum_remote": "Kontrolna vsota ni na voljo – oddaljenega sredstva ni mogoče pridobiti", "no_duplicates_found": "Najden ni bil noben dvojnik.", "no_exif_info_available": "Podatki o exif niso na voljo", "no_explore_results_message": "NaloÅžite več fotografij, da raziÅĄÄete svojo zbirko.", "no_favorites_message": "Dodajte priljubljene, da hitreje najdete svoje najboljÅĄe slike in videoposnetke", "no_libraries_message": "Ustvarite zunanjo knjiÅžnico za ogled svojih fotografij in videoposnetkov", + "no_local_assets_found": "S to kontrolno vsoto ni bilo najdenih lokalnih sredstev", "no_locked_photos_message": "Fotografije in videoposnetki v zaklenjeni mapi so skriti in se ne bodo prikazali med brskanjem ali iskanjem po knjiÅžnici.", "no_name": "Brez imena", "no_notifications": "Ni obvestil", "no_people_found": "Ni najdenih ustreznih oseb", "no_places": "Ni krajev", + "no_remote_assets_found": "S to kontrolno vsoto ni bilo najdenih oddaljenih sredstev", "no_results": "Brez rezultatov", "no_results_description": "Poskusite s sinonimom ali bolj sploÅĄno ključno besedo", "no_shared_albums_message": "Ustvarite album za skupno rabo fotografij in videoposnetkov z osebami v vaÅĄem omreÅžju", "no_uploads_in_progress": "Ni nalaganj v teku", + "not_available": "Ni na voljo", "not_in_any_album": "Ni v nobenem albumu", "not_selected": "Ni izbrano", "note_apply_storage_label_to_previously_uploaded assets": "Opomba: Če Åželite oznako za shranjevanje uporabiti za predhodno naloÅžena sredstva, zaÅženite", @@ -1504,6 +1531,7 @@ "port": "Vrata", "preferences_settings_subtitle": "Upravljaj nastavitve aplikacije", "preferences_settings_title": "Nastavitve", + "preparing": "Priprava", "preset": "Prednastavitev", "preview": "Predogled", "previous": "PrejÅĄnj-a/-i", @@ -1520,7 +1548,7 @@ "profile_drawer_client_out_of_date_minor": "Mobilna aplikacija je zastarela. Posodobite na najnovejÅĄo manjÅĄo različico.", "profile_drawer_client_server_up_to_date": "Odjemalec in streÅžnik sta posodobljena", "profile_drawer_github": "GitHub", - "profile_drawer_readonly_mode": "Način samo za branje je omogočen. Za izhod dvakrat tapnite ikono uporabniÅĄkega avatarja.", + "profile_drawer_readonly_mode": "Način samo za branje je omogočen. Za izhod dolgo pritisnite ikono uporabniÅĄkega avatarja.", "profile_drawer_server_out_of_date_major": "StreÅžnik je zastarel. Posodobite na najnovejÅĄo glavno različico.", "profile_drawer_server_out_of_date_minor": "StreÅžnik je zastarel. Posodobite na najnovejÅĄo manjÅĄo različico.", "profile_image_of_user": "Profilna slika uporabnika {user}", @@ -1569,6 +1597,7 @@ "read_changelog": "Preberi dnevnik sprememb", "readonly_mode_disabled": "Način samo za branje je onemogočen", "readonly_mode_enabled": "Način samo za branje je omogočen", + "ready_for_upload": "Pripravljeno za nalaganje", "reassign": "Prerazporedi", "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", @@ -1593,6 +1622,7 @@ "regenerating_thumbnails": "Obnavljanje sličic", "remote": "Oddaljeno", "remote_assets": "Oddaljena sredstva", + "remote_media_summary": "Povzetek oddaljenih medijev", "remove": "Odstrani", "remove_assets_album_confirmation": "Ali ste prepričani, da Åželite odstraniti {count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}} iz albuma?", "remove_assets_shared_link_confirmation": "Ali ste prepričani, da Åželite odstraniti {count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}} iz te skupne povezave?", @@ -1645,6 +1675,7 @@ "restore_user": "Obnovi uporabnika", "restored_asset": "Obnovljeno sredstvo", "resume": "Nadaljuj", + "resume_paused_jobs": "Nadaljuj {count, plural, one {# zaustavljeno opravilo} two {# zaustavljeni opravili} few {# zaustavljena opravila} other {# zaustavljenih opravil}}", "retry_upload": "Poskusite znova naloÅžiti", "review_duplicates": "Pregled dvojnikov", "review_large_files": "Pregled velikih datotek", @@ -1849,10 +1880,8 @@ "shift_to_permanent_delete": "pritisni ⇧ za trajno brisanje sredstva", "show_album_options": "PrikaÅži moÅžnosti albuma", "show_albums": "PrikaÅži albume", - "show_all_assets": "PrikaÅži vsa sredstva", "show_all_people": "PrikaÅži vse osebe", "show_and_hide_people": "PrikaÅži & skrij osebe", - "show_assets_without_location": "PrikaÅži sredstva brez lokacije", "show_file_location": "PokaÅži lokacijo datoteke", "show_gallery": "PrikaÅži galerijo", "show_hidden_people": "PrikaÅži skrite osebe", @@ -1869,6 +1898,7 @@ "show_slideshow_transition": "PrikaÅži prehod diaprojekcije", "show_supporter_badge": "Značka podpornika", "show_supporter_badge_description": "PrikaÅži značko podpornika", + "show_text_search_menu": "PrikaÅži meni za iskanje po besedilu", "shuffle": "Naključno", "sidebar": "Stranska vrstica", "sidebar_display_description": "PrikaÅži povezavo do pogleda v stranski vrstici", @@ -1899,6 +1929,7 @@ "stacktrace": "Sled nabora", "start": "Začetek", "start_date": "Datum začetka", + "start_date_before_end_date": "Začetni datum mora biti pred končnim datumom", "state": "DeÅžela", "status": "Status", "stop_casting": "Ustavi predvajanje", @@ -1923,6 +1954,8 @@ "sync_albums_manual_subtitle": "Sinhronizirajte vse naloÅžene videoposnetke in fotografije v izbrane varnostne albume", "sync_local": "Sinhroniziraj lokalno", "sync_remote": "Sinhroniziraj oddaljeno", + "sync_status": "Stanje sinhronizacije", + "sync_status_subtitle": "Ogled in upravljanje sistema sinhronizacije", "sync_upload_album_setting_subtitle": "Ustvarite in naloÅžite svoje fotografije in videoposnetke v izbrane albume na Immich", "tag": "Oznaka", "tag_assets": "Označi sredstva", @@ -1982,6 +2015,7 @@ "trash_page_select_assets_btn": "Izberite sredstva", "trash_page_title": "Smetnjak ({count})", "trashed_items_will_be_permanently_deleted_after": "Elementi v smetnjaku bodo trajno izbrisani po {days, plural, one {# dnevu} two {# dnevih} few {# dnevih} other {# dneh}}.", + "troubleshoot": "Odpravljanje teÅžav", "type": "Vrsta", "unable_to_change_pin_code": "PIN kode ni mogoče spremeniti", "unable_to_setup_pin_code": "PIN kode ni mogoče nastaviti", @@ -2037,7 +2071,6 @@ "use_biometric": "Uporabite biometrične podatke", "use_current_connection": "uporabi trenutno povezavo", "use_custom_date_range": "Namesto tega uporabite časovno obdobje po meri", - "use_this_location": "Kliknite za uporabo lokacije", "user": "Uporabnik", "user_has_been_deleted": "Ta uporabnik je bil izbrisan.", "user_id": "ID uporabnika", @@ -2099,5 +2132,6 @@ "yes": "Da", "you_dont_have_any_shared_links": "Nimate nobenih skupnih povezav", "your_wifi_name": "VaÅĄe ime Wi-Fi", - "zoom_image": "Povečava slike" + "zoom_image": "Povečava slike", + "zoom_to_bounds": "Povečaj do meja" } diff --git a/i18n/sq.json b/i18n/sq.json index 0967ef424b..de7c5faa27 100644 --- a/i18n/sq.json +++ b/i18n/sq.json @@ -1 +1,59 @@ -{} +{ + "about": "Rreth", + "account": "Llogari", + "account_settings": "CilÃĢsimet e LlogarisÃĢ", + "acknowledge": "Prano", + "action": "Aksion", + "action_common_update": "PÃĢrditÃĢso", + "actions": "Aksione", + "active": "Aktiv", + "activity": "Aktivitet", + "activity_changed": "Aktiviteti ÃĢshtÃĢ {enabled, select, true {aktivizuar} other {çaktivizuar}}", + "add": "Shto", + "add_a_description": "Shto njÃĢ pÃĢrshkrim", + "add_a_location": "Shto njÃĢ vendndodhje", + "add_a_name": "Shto njÃĢ emÃĢr", + "add_a_title": "Shto njÃĢ titull", + "add_birthday": "Shto njÃĢ ditÃĢlindje", + "add_endpoint": "Shto njÃĢ endpoint", + "add_exclusion_pattern": "Shto model pÃĢrjashtimi", + "add_import_path": "Shto vÃĢnd importimi", + "add_location": "Shto vendndodhje", + "add_more_users": "Shto mÃĢ shumÃĢ pÃĢrdorues", + "add_partner": "Shto partner", + "add_path": "Shto path", + "add_photos": "Shto foto", + "add_tag": "Shto tag", + "add_to": "Shto nÃĢâ€Ļ", + "add_to_album": "Shto nÃĢ album", + "add_to_album_bottom_sheet_added": "Shtuar nÃĢ {album}", + "add_to_album_bottom_sheet_already_exists": "Existon nÃĢ {album}", + "add_to_album_toggle": "Aktivizo/çaktivizo zgjedhjen pÃĢr {album}", + "add_to_albums": "Shto nÃĢ albume", + "add_to_albums_count": "Shto nÃĢ albume ({count})", + "add_to_shared_album": "Shto nÃĢ album tÃĢ hapur", + "add_url": "Shto URL", + "added_to_archive": "Shtuar nÃĢ arkiv", + "added_to_favorites": "Shtuar tek tÃĢ preferuarat", + "added_to_favorites_count": "Shtuar {count, number} nÃĢ tÃĢ preferuarat", + "admin": { + "add_exclusion_pattern_description": "Shto modele pÃĢrjashtimi. MbÃĢshtetet globimi duke pÃĢrdorur *, ** dhe ?. PÃĢr tÃĢ injoruar tÃĢ gjithÃĢ skedarÃĢt nÃĢ Ã§do drejtori tÃĢ quajtur \"Raw\", pÃĢrdorni \"**/Raw/**\". PÃĢr tÃĢ injoruar tÃĢ gjithÃĢ skedarÃĢt qÃĢ mbarojnÃĢ me \".tif\", pÃĢrdorni \"**/*.tif\". PÃĢr tÃĢ injoruar njÃĢ shteg absolut, pÃĢrdorni \"/path/to/ignore/**\".", + "admin_user": "PÃĢrdorues Administrator", + "asset_offline_description": "Ky aset i bibliotekÃĢs sÃĢ jashtme nuk gjendet mÃĢ nÃĢ disk dhe ÃĢshtÃĢ zhvendosur nÃĢ koshin e plehrave. NÃĢse skedari ÃĢshtÃĢ zhvendosur brenda bibliotekÃĢs, kontrolloni kronologjinÃĢ tuaj pÃĢr asetin e ri pÃĢrkatÃĢs. PÃĢr tÃĢ rivendosur kÃĢtÃĢ aset, sigurohuni qÃĢ shtegu i skedarit mÃĢ poshtÃĢ tÃĢ jetÃĢ i arritshÃĢm nga Immich dhe skanoni bibliotekÃĢn.", + "authentication_settings": "CilÃĢsimet e vÃĢrtetimit tÃĢ pÃĢrdoruesit", + "authentication_settings_description": "Manaxho passwordin, OAuth, dhe cilÃĢsime tÃĢ tjera tÃĢ", + "authentication_settings_disable_all": "Je i sigurt qÃĢ dÃĢshiron tÃĢ Ã§aktivizosh tÃĢ gjitha metodat e hyrjes? Hyrja do tÃĢ Ã§aktivizohet plotÃĢsisht.", + "authentication_settings_reenable": "PÃĢr ta riaktivizuar, pÃĢrdorni njÃĢ KomandÃĢ Serveri.", + "background_task_job": "Detyrat nÃĢ Sfond", + "backup_database": "Krijo demp tÃĢ databaseit", + "backup_database_enable_description": "Aktivizo demp-et e bazÃĢs sÃĢ tÃĢ dhÃĢnave", + "backup_keep_last_amount": "Sasia e deponive tÃĢ mÃĢparshme pÃĢr t'u mbajtur", + "backup_onboarding_1_description": "kopje nÃĢ cloud ose nÃĢ njÃĢ vendndodhje tjetÃĢr fizike.", + "backup_onboarding_2_description": "kopje lokale nÃĢ pajisje tÃĢ ndryshme. Kjo pÃĢrfshin skedarÃĢt kryesorÃĢ dhe njÃĢ kopje rezervÃĢ tÃĢ kÃĢtyre skedarÃĢve lokalisht.", + "backup_onboarding_3_description": "kopje totale tÃĢ tÃĢ dhÃĢnave tuaja, duke pÃĢrfshirÃĢ skedarÃĢt origjinalÃĢ. Kjo pÃĢrfshin 1 kopje jashtÃĢ faqes dhe 2 kopje lokale.", + "backup_onboarding_description": "Rekomandohet njÃĢ strategji 3-2-1 pÃĢr ruajtjen e tÃĢ dhÃĢnave tuaja. Duhet tÃĢ ruani kopje tÃĢ fotove/videove tÃĢ ngarkuara, si dhe tÃĢ bazÃĢs sÃĢ tÃĢ dhÃĢnave tÃĢ Immich pÃĢr njÃĢ zgjidhje gjithÃĢpÃĢrfshirÃĢse tÃĢ ruajtjes sÃĢ tÃĢ dhÃĢnave.", + "backup_onboarding_footer": "PÃĢr mÃĢ shumÃĢ informacion pÃĢr tÃĢ krijuar njÃĢ kopje rezervÃĢ tÃĢ Immich, ju lutem referouni tek dokumentimi.", + "backup_onboarding_parts_title": "NjÃĢ kopje rezervÃĢ 3-2-1 ka:", + "backup_onboarding_title": "Kopje rezervÃĢ" + } +} diff --git a/i18n/sr_Latn.json b/i18n/sr_Latn.json index 5b11aa9a98..4e4afe02f8 100644 --- a/i18n/sr_Latn.json +++ b/i18n/sr_Latn.json @@ -4,6 +4,7 @@ "account_settings": "PodeÅĄavanja za Profil", "acknowledge": "Potvrdi", "action": "Postupak", + "action_common_update": "AÅžuriraj", "actions": "Postupci", "active": "Aktivni", "activity": "Aktivnost", @@ -13,6 +14,7 @@ "add_a_location": "Dodaj Lokaciju", "add_a_name": "Dodaj ime", "add_a_title": "Dodaj naslov", + "add_birthday": "Dodaj rođendan", "add_endpoint": "Dodajte krajnju tačku", "add_exclusion_pattern": "Dodajte obrazac izuzimanja", "add_import_path": "Dodaj putanju za preuzimanje", @@ -21,10 +23,14 @@ "add_partner": "Dodaj partner", "add_path": "Dodaj putanju", "add_photos": "Dodaj fotografije", + "add_tag": "Dodaj oznaku", "add_to": "Dodaj uâ€Ļ", "add_to_album": "Dodaj u album", "add_to_album_bottom_sheet_added": "Dodato u {album}", "add_to_album_bottom_sheet_already_exists": "Već u {album}", + "add_to_album_toggle": "Uključi/isključi izbor za {album}", + "add_to_albums": "Dodaj u albume", + "add_to_albums_count": "Dodaj u albume ({count})", "add_to_shared_album": "Dodaj u deljen album", "add_url": "Dodaj URL", "added_to_archive": "Dodato u arhivu", @@ -32,6 +38,7 @@ "added_to_favorites_count": "Dodato {count, number} u favorite", "admin": { "add_exclusion_pattern_description": "Dodajte obrasce isključenja. KoriÅĄtenje *, ** i ? je podrÅžano. Da biste ignorisali sve datoteke u bilo kom direktorijumu pod nazivom „Rav“, koristite „**/Rav/**“. Da biste ignorisali sve datoteke koje se zavrÅĄavaju na „.tif“, koristite „**/*.tif“. Da biste ignorisali apsolutnu putanju, koristite „/path/to/ignore/**“.", + "admin_user": "Administrator", "asset_offline_description": "Ovo eksterno bibliotečko sredstvo se viÅĄe ne nalazi na disku i premeÅĄteno je u smecˁe. Ako je datoteka premeÅĄtena unutar biblioteke, proverite svoju vremensku liniju za novo odgovarajucˁe sredstvo. Da biste vratili ovo sredstvo, uverite se da Immich moÅže da pristupi dole navedenoj putanji datoteke i skenirajte biblioteku.", "authentication_settings": "PodeÅĄavanja za autentifikaciju", "authentication_settings_description": "Upravljajte lozinkom, OAuth-om i drugim podeÅĄavanjima autentifikacije", @@ -41,8 +48,15 @@ "backup_database": "Kreirajte rezervnu kopiju baze podataka", "backup_database_enable_description": "Omogucˁi dampove baze podataka", "backup_keep_last_amount": "Količina prethodnih dampova koje treba zadrÅžati", + "backup_onboarding_1_description": "kopija na oblaku ili na drugoj fizičkoj lokaciji.", + "backup_onboarding_2_description": "lokalne kopije na različitim uređajima. Ovo uključuje glavne datoteke i rezervnu kopiju tih datoteka lokalno.", + "backup_onboarding_3_description": "ukupno kopija vaÅĄih podataka, uklučujući originalne datoteke. Ovo uključuje 1 udaljenu kopiju i 2 lokalne kopije.", + "backup_onboarding_description": "3-2-1 strategija rezervnih kopija je preporučena da zaÅĄtiti vaÅĄe podatke. Trebali biste čuvati kopije vaÅĄih otpremljenih slika/videa kao i Immich bazu podataka za sveobuhvatno reÅĄenje za rezervne kopije.", + "backup_onboarding_footer": "Za viÅĄe informacija o pravljenju rezervne kopije Immich-a, molimo vas pogledajte dokumentaciju.", + "backup_onboarding_parts_title": "3-2-1 rezervna kopija uključuje:", + "backup_onboarding_title": "Rezervne kopije", "backup_settings": "PodeÅĄavanja dampa baze podataka", - "backup_settings_description": "Upravljajte podeÅĄavanjima dampa baze podataka. Napomena: Ovi poslovi se ne prate i necˁete biti obaveÅĄteni o neuspehu.", + "backup_settings_description": "Upravljajte podeÅĄavanjima dampa baze podataka.", "cleared_jobs": "OčiÅĄcˁeni poslovi za: {job}", "config_set_by_file": "Konfiguraciju trenutno postavlja konfiguracioni fajl", "confirm_delete_library": "Da li stvarno Åželite da izbriÅĄete biblioteku {library} ?", @@ -109,6 +123,10 @@ "logging_enable_description": "Omogucˁi evidentiranje", "logging_level_description": "Kada je omogucˁeno, koji nivo evidencije koristiti.", "logging_settings": "Evidentiranje", + "machine_learning_availability_checks": "Provere dostupnosti", + "machine_learning_availability_checks_enabled": "Omogući provere dostupnosti", + "machine_learning_availability_checks_interval": "Interval provere", + "machine_learning_availability_checks_interval_description": "Interval u milisekundama između provera dostupnosti", "machine_learning_clip_model": "Model CLIP", "machine_learning_clip_model_description": "Naziv CLIP modela je naveden ovde. Imajte na umu da morate ponovo da pokrenete posao „Pametno pretraÅživanje“ za sve slike nakon promene modela.", "machine_learning_duplicate_detection": "Detekcija duplikata", @@ -163,12 +181,25 @@ "metadata_settings_description": "Upravljajte podeÅĄavanjima metapodataka", "migration_job": "Migracije", "migration_job_description": "Prenesite sličice datoteka i lica u najnoviju strukturu direktorijuma", + "nightly_tasks_cluster_faces_setting_description": "Pokreni prepoznavanje lica na novodetektovanim licima", + "nightly_tasks_cluster_new_faces_setting": "ZdruÅži nova lica", + "nightly_tasks_database_cleanup_setting": "Zadaci čiÅĄÄenja baze podataka", + "nightly_tasks_database_cleanup_setting_description": "Očisti stare, istekle podatke iz baze podataka", + "nightly_tasks_generate_memories_setting": "GeneriÅĄi sjećanja", + "nightly_tasks_generate_memories_setting_description": "Stvorite nova sećanja iz imovine", + "nightly_tasks_missing_thumbnails_setting": "GeneriÅĄi nedostajuće sličice", + "nightly_tasks_missing_thumbnails_setting_description": "Dodajte elemente bez sličica u red za generisanje sličica", + "nightly_tasks_settings": "PodeÅĄavanja noćnih zadataka", + "nightly_tasks_settings_description": "Upravljaj noćnim zadacima", + "nightly_tasks_start_time_setting": "Vreme početka", + "nightly_tasks_start_time_setting_description": "Vreme kada server započinje noćne zadatke", + "nightly_tasks_sync_quota_usage_setting_description": "AÅžurirajte kvotu memorijskog prostora korisnika na osnovu trenutne upotrebe", "no_paths_added": "Nema dodatih putanja", "no_pattern_added": "Nije dodat obrazac", "note_apply_storage_label_previous_assets": "Napomena: Da biste primenili oznaku za skladiÅĄtenje na prethodno otpremljena sredstva, pokrenite", "note_cannot_be_changed_later": "NAPOMENA: Ovo se kasnije ne moÅže promeniti!", "notification_email_from_address": "Sa adrese", - "notification_email_from_address_description": "Adresa e-poÅĄte poÅĄiljaoca, na primer: \"Immich foto server \"", + "notification_email_from_address_description": "Adresa e-poÅĄte poÅĄiljaoca, na primer: \"Immich foto server \". Pobrinite se da koristite adresu sa koje vam je dozovljeno slati e-poÅĄtu.", "notification_email_host_description": "Host servera e-poÅĄte (npr. smtp.immich.app)", "notification_email_ignore_certificate_errors": "Zanemarite greÅĄke sertifikata", "notification_email_ignore_certificate_errors_description": "IgnoriÅĄite greÅĄke u validaciji TLS sertifikata (ne preporučuje se)", @@ -201,7 +232,7 @@ "oauth_storage_quota_claim": "Zahtev za kvotu skladiÅĄtenja", "oauth_storage_quota_claim_description": "Automatski podesite kvotu memorijskog prostora korisnika na vrednost ovog zahteva.", "oauth_storage_quota_default": "Podrazumevana kvota za skladiÅĄtenje (GiB)", - "oauth_storage_quota_default_description": "Kvota u GiB koja se koristi kada nema potraÅživanja (unesite 0 za neograničenu kvotu).", + "oauth_storage_quota_default_description": "Kvota u GiB koja se koristi kada nema potraÅživanja.", "oauth_timeout": "Vremensko ograničenje zahteva", "oauth_timeout_description": "Vremensko ograničenje za zahteve u milisekundama", "password_enable_description": "Prijavite se pomocˁu e-poÅĄte i lozinke", @@ -508,7 +539,7 @@ "backup_controller_page_background_turn_off": "Isključi pozadinski servis", "backup_controller_page_background_turn_on": "Uključi pozadinski servis", "backup_controller_page_background_wifi": "Samo na Wi-Fi", - "backup_controller_page_backup": "Napravi rezervnu kopiju", + "backup_controller_page_backup": "Rezervne kopije", "backup_controller_page_backup_selected": "Odabrano: ", "backup_controller_page_backup_sub": "ZavrÅĄeno pravljenje rezervne kopije fotografija i videa", "backup_controller_page_created": "Napravljeno:{date}", @@ -519,8 +550,8 @@ "backup_controller_page_id": "ID:{id}", "backup_controller_page_info": "Informacije", "backup_controller_page_none_selected": "NiÅĄta odabrano", - "backup_controller_page_remainder": "Podsetnik", - "backup_controller_page_remainder_sub": "Ostalo fotografija i videa da se otpremi od selekcije", + "backup_controller_page_remainder": "Ostatak", + "backup_controller_page_remainder_sub": "Ostale fotografije i video snimci za otpremanje od selekcije", "backup_controller_page_server_storage": "Prostor na serveru", "backup_controller_page_start_backup": "Pokreni pravljenje rezervne kopije", "backup_controller_page_status_off": "Automatsko pravljenje rezervnih kopija u prvom planu je isključeno", diff --git a/i18n/sv.json b/i18n/sv.json index 5b663c4d02..4057a6aa56 100644 --- a/i18n/sv.json +++ b/i18n/sv.json @@ -28,10 +28,12 @@ "add_to_album": "Lägg till i album", "add_to_album_bottom_sheet_added": "Tillagd till {album}", "add_to_album_bottom_sheet_already_exists": "Redan i {album}", + "add_to_album_bottom_sheet_some_local_assets": "Vissa lokala tillgÃĨngar kunde inte läggas till i albumet", "add_to_album_toggle": "Växla val fÃļr {album}", "add_to_albums": "Lägg till i album", "add_to_albums_count": "Lägg till i album ({count})", "add_to_shared_album": "Lägg till i delat album", + "add_upload_to_stack": "Lägg till uppladdning till stack", "add_url": "Lägg till URL", "added_to_archive": "Tillagd i arkiv", "added_to_favorites": "Tillagd till favoriter", @@ -123,6 +125,13 @@ "logging_enable_description": "Aktivera loggning", "logging_level_description": "Vilken loggnivÃĨ som ska användas vid aktivering.", "logging_settings": "Loggning", + "machine_learning_availability_checks": "Tillgänglighetskontroller", + "machine_learning_availability_checks_description": "Upptäck och fÃļredrar automatiskt tillgängliga maskininlärningsservrar", + "machine_learning_availability_checks_enabled": "Aktivera tillgänglighetskontroller", + "machine_learning_availability_checks_interval": "Kontrollera intervall", + "machine_learning_availability_checks_interval_description": "Intervall i millisekunder mellan tillgänglighetskontroller", + "machine_learning_availability_checks_timeout": "Begär timeout", + "machine_learning_availability_checks_timeout_description": "Timeout i millisekunder fÃļr tillgänglighetskontroller", "machine_learning_clip_model": "CLIP-modell", "machine_learning_clip_model_description": "Namnet pÃĨ en CLIP-modell listad här . Observera att du mÃĨste kÃļra ett \"Smart SÃļkning\" jobb fÃļr alla bilder när du ändrar modell.", "machine_learning_duplicate_detection": "Dubblettdetektering", @@ -387,8 +396,6 @@ "admin_password": "Admin LÃļsenord", "administration": "Administration", "advanced": "Avancerat", - "advanced_settings_beta_timeline_subtitle": "Testa den nya appupplevelsen", - "advanced_settings_beta_timeline_title": "Tidslinje(BETA)", "advanced_settings_enable_alternate_media_filter_subtitle": "Använd det här alternativet fÃļr att filtrera media under synkronisering baserat pÃĨ alternativa kriterier. Prova detta endast om du har problem med att appen inte hittar alla album.", "advanced_settings_enable_alternate_media_filter_title": "[EXPERIMENTELLT] Använd alternativ enhetsalbum-synkroniseringsfilter", "advanced_settings_log_level_title": "LoggnivÃĨ: {level}", @@ -425,6 +432,7 @@ "album_remove_user_confirmation": "Är du säker pÃĨ att du vill ta bort {user}?", "album_search_not_found": "Inga album hittades som matchade din sÃļkning", "album_share_no_users": "Det verkar som att du har delat det här albumet med alla användare eller sÃĨ har du inte nÃĨgon användare att dela med.", + "album_summary": "Albumsammanfattning", "album_updated": "Albumet uppdaterat", "album_updated_setting_description": "FÃĨ ett e-postmeddelande när ett delat album har nya tillgÃĨngar", "album_user_left": "Lämnade {album}", @@ -496,6 +504,8 @@ "asset_restored_successfully": "Objekt ÃĨterställt", "asset_skipped": "Överhoppad", "asset_skipped_in_trash": "I papperskorgen", + "asset_trashed": "TillgÃĨng kasserad", + "asset_troubleshoot": "FelsÃļkning av tillgÃĨngar", "asset_uploaded": "Uppladdad", "asset_uploading": "Laddar upp...â€Ļ", "asset_viewer_settings_subtitle": "Hantera inställningar fÃļr gallerivisare", @@ -529,8 +539,10 @@ "autoplay_slideshow": "Spela upp bildspel automatiskt", "back": "BakÃĨt", "back_close_deselect": "Tillbaka, stäng eller avmarkera", + "background_backup_running_error": "Bakgrundssäkerhetskopiering kÃļrs fÃļr närvarande, kan inte starta manuell säkerhetskopiering", "background_location_permission": "TillÃĨtelse fÃļr bakgrundsplats", "background_location_permission_content": "FÃļr att kunna byta nätverk när appen kÃļrs i bakgrunden mÃĨste Immich *alltid* ha ÃĨtkomst till exakt plats sÃĨ att appen kan läsa av Wi-Fi-nätverkets namn", + "background_options": "Bakgrundsalternativ", "backup": "Säkerhetskopiera", "backup_album_selection_page_albums_device": "Album pÃĨ enhet ({count})", "backup_album_selection_page_albums_tap": "Tryck en gÃĨng fÃļr att inkludera, tryck tvÃĨ gÃĨnger fÃļr att exkludera", @@ -538,6 +550,7 @@ "backup_album_selection_page_select_albums": "Välj album", "backup_album_selection_page_selection_info": "Info om valda objekt", "backup_album_selection_page_total_assets": "Antal unika objekt", + "backup_albums_sync": "Säkerhetskopiera album synkronisering", "backup_all": "Allt", "backup_background_service_backup_failed_message": "Säkerhetskopiering av foton och videor misslyckades. FÃļrsÃļker igenâ€Ļ", "backup_background_service_connection_failed_message": "Anslutning till servern misslyckades. FÃļrsÃļker igenâ€Ļ", @@ -587,6 +600,7 @@ "backup_controller_page_turn_on": "Aktivera automatisk säkerhetskopiering", "backup_controller_page_uploading_file_info": "Laddar upp filinformation", "backup_err_only_album": "Kan inte ta bort det enda albumet", + "backup_error_sync_failed": "Synkroniseringen misslyckades. Det gÃĨr inte att bearbeta säkerhetskopian.", "backup_info_card_assets": "objekt", "backup_manual_cancelled": "Avbrutet", "backup_manual_in_progress": "Uppladdning pÃĨgÃĨr redan. FÃļrsÃļk igen om en liten stund", @@ -597,8 +611,6 @@ "backup_setting_subtitle": "Hantera inställningar fÃļr fÃļr- och bakgrundsuppladdning", "backup_settings_subtitle": "Hantera uppladdningsinställningar", "backward": "BakÃĨt", - "beta_sync": "Synkroniseringsstatus(BETA)", - "beta_sync_subtitle": "Hantera det nya synkroniseringssystemet", "biometric_auth_enabled": "Biometrisk autentisering aktiverad", "biometric_locked_out": "Du är utelÃĨst frÃĨn biometrisk autentisering", "biometric_no_options": "Inga biometriska alternativ tillgängliga", @@ -656,6 +668,8 @@ "change_pin_code": "Ändra PIN-kod", "change_your_password": "Ändra ditt lÃļsenord", "changed_visibility_successfully": "Synligheten har ändrats", + "charging": "Laddar", + "charging_requirement_mobile_backup": "Bakgrundssäkerhetskopiering kräver att enheten laddas", "check_corrupt_asset_backup": "Kontrollera om det finns korrupta säkerhetskopior av objekt", "check_corrupt_asset_backup_button": "Kontrollera", "check_corrupt_asset_backup_description": "KÃļr kontrollen endast Ãļver Wi-Fi och när alla objekt har säkerhetskopierats. Det kan ta nÃĨgra minuter.", @@ -742,6 +756,7 @@ "create_user": "Skapa användare", "created": "Skapad", "created_at": "Skapad", + "creating_linked_albums": "Skapar länkade album...", "crop": "Beskär", "curated_object_page_title": "Objekt", "current_device": "Aktuell enhet", @@ -873,7 +888,7 @@ "editor_close_without_save_prompt": "Ändringarna kommer inte att sparas", "editor_close_without_save_title": "Stäng redigeraren?", "editor_crop_tool_h2_aspect_ratios": "BildfÃļrhÃĨllande", - "editor_crop_tool_h2_rotation": "Rotation", + "editor_crop_tool_h2_rotation": "Vridning", "email": "Epost", "email_notifications": "E-postaviseringar", "empty_folder": "Mappen är tom", @@ -891,7 +906,9 @@ "error": "Fel", "error_change_sort_album": "Kunde inte ändra sorteringsordning fÃļr album", "error_delete_face": "Fel uppstod när ansikte skulle tas bort frÃĨn objektet", + "error_getting_places": "Det gick inte att hämta platser", "error_loading_image": "Fel vid bildladdning", + "error_loading_partners": "Fel vid inläsning av partner: {error}", "error_saving_image": "Fel: {error}", "error_tag_face_bounding_box": "Fel vid taggning av ansikte – kan inte hämta koordinater fÃļr begränsningsruta", "error_title": "Fel – nÃĨgot gick fel", @@ -1017,7 +1034,7 @@ "unable_to_update_user": "Kunde inte uppdatera användare", "unable_to_upload_file": "Det gÃĨr inte att ladda upp filen" }, - "exif": "Exif", + "exif": "EXIF", "exif_bottom_sheet_description": "Lägg till beskrivning...", "exif_bottom_sheet_description_error": "Fel vid uppdatering av beskrivningen", "exif_bottom_sheet_details": "DETALJER", @@ -1056,6 +1073,7 @@ "favorites_page_no_favorites": "Inga favoritobjekt hittades", "feature_photo_updated": "Funktionsfoto uppdaterad", "features": "Funktioner", + "features_in_development": "Funktioner i utveckling", "features_setting_description": "Hantera appens funktioner", "file_name": "Filnamn", "file_name_or_extension": "Filnamn eller -tillägg", @@ -1073,13 +1091,10 @@ "folders_feature_description": "Bläddra i mappvyn fÃļr foton och videoklipp i filsystemet", "forgot_pin_code_question": "GlÃļmt din pinkod?", "forward": "FramÃĨt", - "gcast_enabled": "Google Cast", + "gcast_enabled": "Google-Cast", "gcast_enabled_description": "Denna funktion läser in externa resurser frÃĨn Google fÃļr att fungera.", "general": "Allmänt", - "geolocation_instruction_all_have_location": "Alla tillgÃĨngar fÃļr detta datum har redan platsdata. FÃļrsÃļk att visa alla tillgÃĨngar eller välj ett annat datum", "geolocation_instruction_location": "Klicka pÃĨ en tillgÃĨng med GPS-koordinater fÃļr att använda dess plats, eller välj en plats direkt frÃĨn kartan", - "geolocation_instruction_no_date": "Välj ett datum fÃļr att hantera platsdata fÃļr foton och videor frÃĨn den dagen", - "geolocation_instruction_no_photos": "Inga foton eller videor hittades fÃļr detta datum. Välj ett annat datum fÃļr att visa dem", "get_help": "FÃĨ hjälp", "get_wifiname_error": "Kunde inte hämta Wi-Fi-namn. Säkerställ att du tillÃĨtit nÃļdvändiga rättigheter och är ansluten till ett Wi-Fi-nätverk", "getting_started": "Komma igÃĨng", @@ -1218,11 +1233,12 @@ "link_to_oauth": "Länk till OAuth", "linked_oauth_account": "Länkat OAuth konto", "list": "Lista", - "loading": "Laddar", + "loading": "Inläsning", "loading_search_results_failed": "Det gick inte att läsa in sÃļkresultat", "local": "Lokalt", "local_asset_cast_failed": "Det gÃĨr inte att casta en tillgÃĨng som inte har laddats upp till servern", "local_assets": "Lokala tillgÃĨngar", + "local_media_summary": "Sammanfattning av lokala medier", "local_network": "Lokalt nätverk", "local_network_sheet_info": "Appen kommer ansluta till servern via denna URL när det specificerade WiFi-nätverket används", "location_permission": "Plats-rättighet", @@ -1234,6 +1250,7 @@ "location_picker_longitude_hint": "Ange din longitud här", "lock": "LÃĨs", "locked_folder": "LÃĨst Mapp", + "log_detail_title": "Loggdetalj", "log_out": "Logga ut", "log_out_all_devices": "Logga ut alla enheter", "logged_in_as": "Inloggad som {user}", @@ -1264,6 +1281,7 @@ "login_password_changed_success": "Uppdatering av lÃļsenord lyckades", "logout_all_device_confirmation": "Är du säker pÃĨ att du vill logga ut frÃĨn alla enheter?", "logout_this_device_confirmation": "Är du säker pÃĨ att du vill logga ut frÃĨn denna enhet?", + "logs": "Loggar", "longitude": "Longitud", "look": "Titta", "loop_videos": "Loopa videor", @@ -1306,6 +1324,7 @@ "mark_as_read": "Markera som läst", "marked_all_as_read": "Markerade alla som lästa", "matches": "Matchar", + "matching_assets": "Matchande tillgÃĨngar", "media_type": "Mediatyp", "memories": "Minnen", "memories_all_caught_up": "Du är ikapp", @@ -1346,6 +1365,7 @@ "name_or_nickname": "Namn eller smeknamn", "network_requirement_photos_upload": "Använd mobildata fÃļr att säkerhetskopiera foton", "network_requirement_videos_upload": "Använd mobildata fÃļr att säkerhetskopiera videor", + "network_requirements": "Nätverkskrav", "network_requirements_updated": "Nätverkskraven har ändrats, ÃĨterställer säkerhetskopieringskÃļn", "networking_settings": "Nätverk", "networking_subtitle": "Hantera inställningar fÃļr server-endpointen", @@ -1356,6 +1376,7 @@ "new_person": "Ny person", "new_pin_code": "Ny PIN-kod", "new_pin_code_subtitle": "Det här är fÃļrsta gÃĨngen du Ãļppnar den lÃĨsta mappen. Skapa en PIN-kod fÃļr att säkert fÃĨ ÃĨtkomst till den här sidan", + "new_timeline": "Ny tidslinje", "new_user_created": "Ny användare skapad", "new_version_available": "NY VERSION TILLGÄNGLIG", "newest_first": "Nyast fÃļrst", @@ -1369,20 +1390,25 @@ "no_assets_message": "KLICKA FÖR ATT LADDA UPP DIN FÖRSTA BILD", "no_assets_to_show": "Inga objekt att visa", "no_cast_devices_found": "Inga Cast-enheter hittades", + "no_checksum_local": "Ingen kontrollsumma tillgänglig - kan inte hämta lokala tillgÃĨngar", + "no_checksum_remote": "Ingen kontrollsumma tillgänglig - kan inte hämta fjärrtillgÃĨng", "no_duplicates_found": "Inga dubbletter hittades.", "no_exif_info_available": "EXIF-information ej tillgänglig", "no_explore_results_message": "Ladda upp fler bilder fÃļr att utforska din samling.", "no_favorites_message": "Lägg till favoriter fÃļr att snabbt hitta dina bästa bilder och videor", "no_libraries_message": "Skapa ett externt bibliotek fÃļr att se dina bilder och videor", + "no_local_assets_found": "Inga lokala tillgÃĨngar hittades med denna kontrollsumma", "no_locked_photos_message": "Foton och videor i den lÃĨsta mappen är dolda och visas inte när du bläddrar eller sÃļker i ditt bibliotek.", "no_name": "Inget namn", "no_notifications": "Inga aviseringar", "no_people_found": "Inga matchande personer hittade", "no_places": "Inga platser", + "no_remote_assets_found": "Inga fjärrtillgÃĨngar hittades med denna kontrollsumma", "no_results": "Inga resultat", "no_results_description": "PrÃļva en synonym eller ett annat mer allmänt sÃļkord", "no_shared_albums_message": "Skapa ett album fÃļr att dela bilder och videor med andra personer", "no_uploads_in_progress": "Inga uppladdningar pÃĨgÃĨr", + "not_available": "N/A", "not_in_any_album": "Inte i nÃĨgot album", "not_selected": "Ej vald", "note_apply_storage_label_to_previously_uploaded assets": "Obs: Om du vill använda lagringsetiketten pÃĨ tidigare uppladdade tillgÃĨngar kÃļr du", @@ -1504,6 +1530,7 @@ "port": "Port", "preferences_settings_subtitle": "Hantera appens inställningar", "preferences_settings_title": "Inställningar", + "preparing": "FÃļrbereder", "preset": "FÃļrinställt värde", "preview": "FÃļrhandsvisning", "previous": "FÃļregÃĨende", @@ -1520,14 +1547,14 @@ "profile_drawer_client_out_of_date_minor": "Mobilappen är fÃļrÃĨldrad. Uppdatera till senaste versionen.", "profile_drawer_client_server_up_to_date": "Klient och server är uppdaterade", "profile_drawer_github": "GitHub", - "profile_drawer_readonly_mode": "Skrivskyddat läge aktiverat. Dubbeltryck pÃĨ användaravatarikonen fÃļr att avsluta", + "profile_drawer_readonly_mode": "Skrivskyddat läge aktiverat. LÃĨngtryck användaravatarikonen fÃļr att avsluta.", "profile_drawer_server_out_of_date_major": "Servern har en fÃļrÃĨldrad mjukvara. Uppdatera till senaste versionen.", "profile_drawer_server_out_of_date_minor": "Servern har en fÃļrÃĨldrad mjukvara. Uppdatera till senaste versionen.", "profile_image_of_user": "{user} profilbild", "profile_picture_set": "Profilbild vald.", "public_album": "Publikt album", "public_share": "Offentlig delning", - "purchase_account_info": "Supporter", + "purchase_account_info": "Anhängare", "purchase_activated_subtitle": "Tack fÃļr att du stÃļdjer Immich och open source-mjukvara", "purchase_activated_time": "Aktiverad {date}", "purchase_activated_title": "Aktiveringan av din nyckel lyckades", @@ -1569,6 +1596,7 @@ "read_changelog": "Läs ändringslogg", "readonly_mode_disabled": "Skrivskyddat läge inaktiverat", "readonly_mode_enabled": "Skrivskyddat läge aktiverat", + "ready_for_upload": "Redo fÃļr uppladdning", "reassign": "OmfÃļrdela", "reassigned_assets_to_existing_person": "Tilldelade om {count, plural, one {# objekt} other {# objekt}} till {name, select, null {an existing person} other {{name}}}", "reassigned_assets_to_new_person": "Tilldelade om {count, plural, one {# objekt} other {# objekt}} till en ny persson", @@ -1593,6 +1621,7 @@ "regenerating_thumbnails": "Uppdaterar miniatyrer", "remote": "Fjärrr", "remote_assets": "FjärrtillgÃĨngar", + "remote_media_summary": "Sammanfattning av fjärrmedia", "remove": "Ta bort", "remove_assets_album_confirmation": "Är du säker pÃĨ att du vill ta bort {count, plural, one {# asset} other {# assets}} frÃĨn albumet?", "remove_assets_shared_link_confirmation": "Är du säker pÃĨ att du vill ta bort {count, plural, one {# asset} other {# assets}} frÃĨn denna delade länk?", @@ -1645,6 +1674,7 @@ "restore_user": "Återställ användare", "restored_asset": "Återställ tillgÃĨng", "resume": "Återuppta", + "resume_paused_jobs": "Återuppta {count, plural, one {# pausat jobb} other {# pausade jobb}}", "retry_upload": "Ladda upp igen", "review_duplicates": "Granska dubbletter", "review_large_files": "Granska stora filer", @@ -1849,10 +1879,8 @@ "shift_to_permanent_delete": "tryck pÃĨ ⇧ fÃļr att permanent radera tillgÃĨngen", "show_album_options": "Visa albumalternativ", "show_albums": "Visa album", - "show_all_assets": "Visa alla tillgÃĨngar", "show_all_people": "Visa alla personer", "show_and_hide_people": "Visa & gÃļm personer", - "show_assets_without_location": "Visa tillgÃĨngar utan plats", "show_file_location": "Visa sÃļkväg", "show_gallery": "Visa galleri", "show_hidden_people": "Visa gÃļmda personer", @@ -1869,6 +1897,7 @@ "show_slideshow_transition": "Visa bildspelsÃļvergÃĨng", "show_supporter_badge": "Supporteremblem", "show_supporter_badge_description": "Visa supporteremblem", + "show_text_search_menu": "Visa textsÃļkningsmeny", "shuffle": "Blanda", "sidebar": "Sidopanel", "sidebar_display_description": "Visa en länk till vyn i sidofältet", @@ -1899,6 +1928,7 @@ "stacktrace": "StapelspÃĨrning", "start": "Starta", "start_date": "Startdatum", + "start_date_before_end_date": "Startdatumet mÃĨste vara fÃļre slutdatumet", "state": "Stat", "status": "Status", "stop_casting": "Sluta casta", @@ -1915,7 +1945,7 @@ "suggestions": "FÃļrslag", "sunrise_on_the_beach": "SoluppgÃĨng pÃĨ stranden", "support": "Support", - "support_and_feedback": "Support & Feedback", + "support_and_feedback": "Support och Feedback", "support_third_party_description": "Din Immich-installation paketerades av en tredje part. Problem som du upplever kan orsakas av det paketet, sÃĨ vänligen ta upp problem med dem i fÃļrsta hand med hjälp av länkarna nedan.", "swap_merge_direction": "Byt sammanfogningsriktning", "sync": "Synka", @@ -1923,6 +1953,8 @@ "sync_albums_manual_subtitle": "Synka alla uppladdade videor och foton till valda backup-album", "sync_local": "Synkronisera lokalt", "sync_remote": "Synkronisera fjärrserver", + "sync_status": "Synk Status", + "sync_status_subtitle": "Visa och hantera synkroniseringssystemet", "sync_upload_album_setting_subtitle": "Skapa och ladda upp dina foton och videor till de valda albumen pÃĨ Immich", "tag": "Tagg", "tag_assets": "Tagga tillgÃĨngar", @@ -1982,6 +2014,7 @@ "trash_page_select_assets_btn": "Välj objekt", "trash_page_title": "Papperskorg ({count})", "trashed_items_will_be_permanently_deleted_after": "Objekt i papperskorgen raderas permanent efter {days, plural, one {# dag} other {# dagar}}.", + "troubleshoot": "FelsÃļk", "type": "Typ", "unable_to_change_pin_code": "Kunde inte ändra pinkod", "unable_to_setup_pin_code": "Kunde inte konfigurera pinkod", @@ -2037,7 +2070,6 @@ "use_biometric": "Använd biometri", "use_current_connection": "Använd aktuell anslutning", "use_custom_date_range": "Använd anpassat datumintervall istället", - "use_this_location": "Klicka fÃļr att använda plats", "user": "Användare", "user_has_been_deleted": "Den här användaren har raderats.", "user_id": "Användar-ID", @@ -2099,5 +2131,6 @@ "yes": "Ja", "you_dont_have_any_shared_links": "Du har inga delade länkar", "your_wifi_name": "Ditt Wi-Fi-namn", - "zoom_image": "Zooma bild" + "zoom_image": "Zooma bild", + "zoom_to_bounds": "Zooma till gränser" } diff --git a/i18n/ta.json b/i18n/ta.json index d2b20ed7c2..978a36ab64 100644 --- a/i18n/ta.json +++ b/i18n/ta.json @@ -8,7 +8,7 @@ "actions": "āŽšā¯†āŽ¯āŽ˛ā¯āŽ•āŽŗā¯", "active": "āŽšā¯†āŽ¯āŽ˛ā¯āŽĒāŽžāŽŸā¯āŽŸāŽŋāŽ˛ā¯", "activity": "āŽšā¯†āŽ¯āŽ˛ā¯āŽĒāŽžāŽŸā¯āŽ•āŽŗā¯", - "activity_changed": "āŽšā¯†āŽ¯āŽ˛ā¯āŽĒāŽžāŽŸā¯ {āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯, āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯, āŽšāŽ°āŽŋ {enabled} āŽŽāŽąā¯āŽąāŽ¤ā¯ {disabled}}", + "activity_changed": "āŽšā¯†āŽ¯āŽ˛ā¯āŽĒāŽžāŽŸā¯ {enabled, select, true {āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯} other {āŽŽā¯āŽŸāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯}}", "add": "āŽšā¯‡āŽ°ā¯", "add_a_description": "āŽĩāŽŋāŽĩāŽ°āŽŽā¯ āŽšā¯‡āŽ°ā¯", "add_a_location": "āŽ‡āŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", @@ -24,39 +24,41 @@ "add_path": "āŽĒāŽžāŽ¤ā¯ˆ (āŽĒāŽžāŽ¤ā¯) āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "add_photos": "āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "add_tag": "āŽ•ā¯āŽąāŽŋāŽ¯ā¯ˆāŽšā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•", - "add_to": "āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•â€Ļ", + "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_some_local_assets": "āŽšāŽŋāŽ˛ āŽ‰āŽŗā¯āŽŗāŽ• āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "add_to_album_toggle": "{album} āŽ•ā¯āŽ•āŽžāŽŠ āŽ¤ā¯‡āŽ°ā¯āŽĩ❈ āŽŽāŽžāŽąā¯āŽąā¯", "add_to_albums": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽšā¯‡āŽ°ā¯", "add_to_albums_count": "āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽšā¯‡āŽ°ā¯({count})", "add_to_shared_album": "āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ†āŽ˛ā¯āŽĒāŽŽāŽŋāŽ˛ā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•", + "add_upload_to_stack": "āŽ…āŽŸā¯āŽ•ā¯āŽ•āŽŋāŽ˛ā¯ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąāŽ¤ā¯āŽ¤ā¯ˆāŽšā¯ āŽšā¯‡āŽ°ā¯", "add_url": "URL āŽāŽšā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "added_to_archive": "āŽ•āŽžāŽĒā¯āŽĒāŽ•āŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "added_to_favorites": "āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗāŽŋāŽ˛ā¯ (āŽĒ❇āŽĩāŽ°āŽŋāŽŸā¯āŽ¸ā¯) āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", - "added_to_favorites_count": "āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗāŽŋāŽ˛ā¯ (āŽĒ❇āŽĩāŽ°āŽŋāŽŸā¯āŽ¸ā¯) {count} āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "added_to_favorites_count": "āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗāŽŋāŽ˛ā¯ {count, number} āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "admin": { "add_exclusion_pattern_description": "āŽĩāŽŋāŽ˛āŽ•ā¯āŽ•ā¯ āŽĩāŽŸāŽŋāŽĩāŽ™ā¯āŽ•āŽŗā¯ˆāŽšā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯. *, **, āŽŽāŽąā¯āŽąā¯āŽŽā¯ ? āŽ†āŽ¤āŽ°āŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽ•āŽŋāŽąāŽ¤ā¯. \"Raw\" āŽŽāŽŠā¯āŽą āŽĒā¯†āŽ¯āŽ°āŽŋāŽŸāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽŽāŽ¨ā¯āŽ¤ āŽ•ā¯‹āŽĒā¯āŽĒāŽ•āŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯āŽŽā¯ āŽ‰āŽŗā¯āŽŗ āŽŽāŽ˛ā¯āŽ˛āŽž āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽĒā¯āŽąāŽ•ā¯āŽ•āŽŖāŽŋāŽ•ā¯āŽ•, \"**/Raw/**\" āŽāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯. \".tif\" āŽ‡āŽ˛ā¯ āŽŽā¯āŽŸāŽŋāŽ¯ā¯āŽŽā¯ āŽŽāŽ˛ā¯āŽ˛āŽž āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽĒā¯āŽąāŽ•ā¯āŽ•āŽŖāŽŋāŽ•ā¯āŽ•, \"**/*.tif\" āŽāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯. āŽ’āŽ°ā¯ āŽŽā¯āŽ´ā¯āŽŽā¯ˆāŽ¯āŽžāŽŠ āŽĒāŽžāŽ¤ā¯ˆāŽ¯ā¯ˆ āŽĒā¯āŽąāŽ•ā¯āŽ•āŽŖāŽŋāŽ•ā¯āŽ•, \"/path/to/ignore/**\" āŽāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯.", "admin_user": "āŽ¨āŽŋāŽ°ā¯āŽĩāŽžāŽ• āŽĒāŽ¯āŽŠāŽ°ā¯", - "asset_offline_description": "āŽ‡āŽ¨ā¯āŽ¤ āŽĩā¯†āŽŗāŽŋāŽĒā¯āŽĒā¯āŽą āŽ¨ā¯‚āŽ˛āŽ• āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ āŽ‡āŽŠāŽŋ āŽĩāŽŸā¯āŽŸāŽŋāŽ˛ā¯ āŽ•āŽžāŽŖāŽĒā¯āŽĒāŽŸāŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽ•ā¯āŽĒā¯āŽĒā¯ˆāŽ•ā¯āŽ•ā¯ āŽ¨āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗāŽ¤ā¯. āŽ•ā¯‹āŽĒā¯āŽĒ❁ āŽ¨ā¯‚āŽ˛āŽ•āŽ¤ā¯āŽ¤āŽŋāŽąā¯āŽ•ā¯āŽŗā¯ āŽ¨āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŸāŽŋāŽ°ā¯āŽ¨ā¯āŽ¤āŽžāŽ˛ā¯, āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ¤ā¯ŠāŽŸāŽ°ā¯āŽĒā¯āŽŸā¯ˆāŽ¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽžāŽŠ āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ•āŽžāŽ˛āŽĩāŽ°āŽŋāŽšā¯ˆāŽ¯ā¯ˆ āŽšāŽ°āŽŋāŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯. āŽ‡āŽ¨ā¯āŽ¤ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆ āŽŽā¯€āŽŸā¯āŽŸā¯†āŽŸā¯āŽ•ā¯āŽ•, āŽ•ā¯€āŽ´ā¯‡āŽ¯ā¯āŽŗā¯āŽŗ āŽ•ā¯‹āŽĒā¯āŽĒ❁ āŽĒāŽžāŽ¤ā¯ˆāŽ¯ā¯ˆ āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯ āŽŽā¯‚āŽ˛āŽŽā¯ āŽ…āŽŖā¯āŽ•āŽ˛āŽžāŽŽā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽ¨ā¯‚āŽ˛āŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽšā¯āŽ•ā¯‡āŽŠā¯ āŽšā¯†āŽ¯ā¯āŽ¯ āŽŽā¯āŽŸāŽŋāŽ¯ā¯āŽŽā¯ āŽŽāŽŠā¯āŽĒāŽ¤ā¯ˆ āŽ‰āŽąā¯āŽ¤āŽŋāŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯.", - "authentication_settings": "āŽ…āŽŸā¯ˆāŽ¯āŽžāŽŗ āŽ‰āŽąā¯āŽ¤āŽŋāŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽ˛ā¯ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ (āŽšā¯†āŽŸā¯āŽŸāŽŋāŽ™ā¯āŽ¸ā¯)", - "authentication_settings_description": "āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯, OAuth, āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĒāŽŋāŽą āŽ…āŽŸā¯ˆāŽ¯āŽžāŽŗ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", - "authentication_settings_disable_all": "āŽŽāŽ˛ā¯āŽ˛āŽž āŽ‰āŽŗā¯āŽ¨ā¯āŽ´ā¯ˆāŽĩ❁ āŽŽā¯āŽąā¯ˆāŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¨āŽŋāŽšā¯āŽšāŽ¯āŽŽāŽžāŽ• āŽŽā¯āŽŸāŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž? āŽ‰āŽŗā¯āŽ¨ā¯āŽ´ā¯ˆāŽĩ❁ āŽŽā¯āŽąā¯āŽąāŽŋāŽ˛ā¯āŽŽā¯ āŽŽā¯āŽŸāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŽā¯.", - "authentication_settings_reenable": "āŽŽā¯€āŽŖā¯āŽŸā¯āŽŽā¯ āŽ‡āŽ¯āŽ•ā¯āŽ•, āŽšāŽ°ā¯āŽĩāŽ°ā¯ āŽ•āŽŸā¯āŽŸāŽŗā¯ˆ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯.", + "asset_offline_description": "āŽ‡āŽ¨ā¯āŽ¤ āŽĩā¯†āŽŗāŽŋāŽĒā¯āŽĒā¯āŽą āŽ¨ā¯‚āŽ˛āŽ•āŽšā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ (external library asset) āŽ‡āŽŠāŽŋ āŽ•ā¯‹āŽĒā¯āŽĒ❁āŽĒā¯ āŽĒāŽ¤āŽŋāŽĒā¯āŽĒāŽŋāŽ˛ā¯ āŽ•āŽžāŽŖāŽĒā¯āŽĒāŽŸāŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽ•ā¯āŽĒā¯āŽĒā¯ˆāŽ¤ā¯āŽ¤ā¯ŠāŽŸā¯āŽŸāŽŋāŽ¯āŽŋāŽ˛ā¯ (trash) āŽ¨āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗāŽ¤ā¯.āŽ•ā¯‹āŽĒā¯āŽĒ❁ āŽ¨ā¯‚āŽ˛āŽ•āŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ‰āŽŗā¯āŽŗā¯‡ āŽ¨āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŸāŽŋāŽ°ā¯āŽ¨ā¯āŽ¤āŽžāŽ˛ā¯, āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ‡āŽŖā¯ˆ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆ (corresponding asset) āŽ•āŽŖā¯āŽŸā¯āŽĒāŽŋāŽŸāŽŋāŽ•ā¯āŽ• āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ•āŽžāŽ˛āŽĩāŽ°āŽŋāŽšā¯ˆāŽ¯ā¯ˆ (timeline) āŽšāŽ°āŽŋāŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯. āŽ‡āŽ¨ā¯āŽ¤ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆ āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆāŽ•ā¯āŽ•, āŽ•ā¯€āŽ´ā¯‡ āŽ‰āŽŗā¯āŽŗ āŽ•ā¯‹āŽĒā¯āŽĒ❁āŽĒā¯ āŽĒāŽžāŽ¤ā¯ˆ Immich āŽŽā¯‚āŽ˛āŽŽā¯ āŽ…āŽŖā¯āŽ•āŽ•ā¯āŽ•ā¯‚āŽŸāŽŋāŽ¯āŽ¤āŽž āŽŽāŽŠā¯āŽĒāŽ¤ā¯ˆ āŽ‰āŽąā¯āŽ¤āŽŋ āŽšā¯†āŽ¯ā¯āŽ¤ā¯, āŽ¨ā¯‚āŽ˛āŽ•āŽ¤ā¯āŽ¤ā¯ˆ (library) āŽŽā¯€āŽŖā¯āŽŸā¯āŽŽā¯ āŽ¸ā¯āŽ•ā¯‡āŽŠā¯ āŽšā¯†āŽ¯ā¯āŽ¯āŽĩā¯āŽŽā¯.", + "authentication_settings": "āŽ…āŽ™ā¯āŽ•ā¯€āŽ•āŽžāŽ° āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", + "authentication_settings_description": "āŽ…āŽŸā¯ˆāŽ¯āŽžāŽŗāŽšā¯ āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯āŽ•āŽŗā¯ (Password), OAuth āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĒāŽŋāŽą āŽ…āŽ™ā¯āŽ•ā¯€āŽ•āŽžāŽ° āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "authentication_settings_disable_all": "āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽ‰āŽŖā¯āŽŽā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ āŽ‰āŽŗā¯āŽ¨ā¯āŽ´ā¯ˆāŽĩ❁ āŽŽā¯āŽąā¯ˆāŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽŽā¯āŽŸāŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž? āŽ‰āŽŗā¯āŽ¨ā¯āŽ´ā¯ˆāŽĩ❁ āŽŽā¯āŽ´ā¯āŽŽā¯ˆāŽ¯āŽžāŽ• āŽŽā¯āŽŸāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŽā¯.", + "authentication_settings_reenable": "āŽŽā¯€āŽŖā¯āŽŸā¯āŽŽā¯ āŽšā¯†āŽ¯āŽ˛ā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤, āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽŽā¯ āŽ•āŽŸā¯āŽŸāŽŗā¯ˆ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯.", "background_task_job": "āŽĒāŽŋāŽŠā¯āŽŠāŽŖāŽŋ āŽĒāŽŖāŽŋāŽ•āŽŗā¯", - "backup_database": "āŽ¤āŽ°āŽĩā¯āŽ¤ā¯āŽ¤āŽŗ āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋāŽ¯ā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•ā¯", - "backup_database_enable_description": "āŽ¤āŽ°āŽĩā¯āŽ¤ā¯āŽ¤āŽŗ āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋāŽ•āŽŗā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", - "backup_keep_last_amount": "āŽĩā¯ˆāŽ¤ā¯āŽ¤āŽŋāŽ°ā¯āŽ•ā¯āŽ• āŽŽā¯āŽ¨ā¯āŽ¤ā¯ˆāŽ¯ āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋāŽ•āŽŗāŽŋāŽŠā¯ āŽ…āŽŗāŽĩ❁", - "backup_onboarding_1_description": "āŽ•āŽŋāŽŗāŽĩā¯āŽŸā¯ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽĩā¯‡āŽąā¯ āŽ‡āŽŸāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ†āŽƒāŽĒā¯āŽšā¯ˆāŽŸā¯ āŽ¨āŽ•āŽ˛ā¯.", + "backup_database": "āŽ¤āŽ°āŽĩā¯āŽ¤ā¯āŽ¤āŽŗ āŽ¨āŽ•āŽ˛ā¯ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "backup_database_enable_description": "āŽ¤āŽ°āŽĩā¯āŽ¤ā¯āŽ¤āŽŗ āŽ¨āŽ•āŽ˛ā¯āŽ•āŽŗā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "backup_keep_last_amount": "āŽĩā¯ˆāŽ¤ā¯āŽ¤āŽŋāŽ°ā¯āŽ•ā¯āŽ• āŽŽā¯āŽ¨ā¯āŽ¤ā¯ˆāŽ¯ āŽ¨āŽ•āŽ˛ā¯āŽ•āŽŗāŽŋāŽŠā¯ āŽ…āŽŗāŽĩ❁", + "backup_onboarding_1_description": "āŽŽā¯‡āŽ•āŽŽā¯ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽĩā¯‡āŽąā¯ āŽ‡āŽŸāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ¨āŽ•āŽ˛ā¯.", "backup_onboarding_2_description": "āŽĩ❆āŽĩā¯āŽĩā¯‡āŽąā¯ āŽšāŽžāŽ¤āŽŠāŽ™ā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽ‰āŽŗā¯āŽŗ āŽ¨āŽ•āŽ˛ā¯ āŽĒāŽŋāŽ°āŽ¤āŽŋāŽ•āŽŗā¯. āŽ‡āŽ¤āŽŋāŽ˛ā¯ āŽŽā¯āŽ•ā¯āŽ•āŽŋāŽ¯ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽ…āŽ¨ā¯āŽ¤āŽ•ā¯ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽ•āŽŗāŽŋāŽŠā¯ āŽ¨āŽ•āŽ˛ā¯ āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋ āŽ†āŽ•āŽŋāŽ¯āŽĩ❈ āŽ…āŽŸāŽ™ā¯āŽ•ā¯āŽŽā¯.", "backup_onboarding_3_description": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ¤āŽ°āŽĩāŽŋāŽŠā¯ āŽŽā¯ŠāŽ¤ā¯āŽ¤ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽ•āŽŗā¯ āŽ…āŽšāŽ˛ā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽ¨āŽ•āŽ˛ā¯āŽ•āŽŗā¯ āŽ‰āŽŸā¯āŽĒāŽŸ. āŽ‡āŽ¤āŽŋāŽ˛ā¯ 1 āŽĩā¯†āŽŗāŽŋāŽĒā¯āŽĒā¯āŽą āŽ¨āŽ•āŽ˛ā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ 2 āŽšāŽžāŽ¤āŽŠāŽĒā¯ āŽĒāŽŋāŽ°āŽ¤āŽŋāŽ•āŽŗā¯ āŽ…āŽŸāŽ™ā¯āŽ•ā¯āŽŽā¯.", "backup_onboarding_description": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ¤āŽ°āŽĩ❈ āŽĒāŽžāŽ¤ā¯āŽ•āŽžāŽĒā¯āŽĒāŽ¤āŽąā¯āŽ•āŽžāŽ• āŽ’āŽ°ā¯ 3-2-1 āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯ āŽĒāŽŋāŽ°āŽ¤āŽŋ āŽĒāŽ°āŽŋāŽ¨ā¯āŽ¤ā¯āŽ°ā¯ˆāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽ•āŽŋāŽąāŽ¤ā¯. āŽŽā¯āŽ´ā¯āŽŽā¯ˆāŽ¯āŽžāŽŠ āŽ•āŽžāŽĒā¯āŽĒ❁ āŽĒāŽžāŽ¤ā¯āŽ•āŽžāŽĒā¯āŽĒ❁ āŽ¤ā¯€āŽ°ā¯āŽĩāŽŋāŽąā¯āŽ•āŽžāŽ•, āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąāŽŋāŽ¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯/āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ Immich āŽ¤āŽ°āŽĩā¯āŽ¤ā¯āŽ¤āŽŗāŽ¤ā¯āŽ¤āŽŋāŽŠā¯ āŽ¨āŽ•āŽ˛ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽĩā¯ˆāŽ¤ā¯āŽ¤āŽŋāŽ°ā¯āŽ•ā¯āŽ• āŽĩā¯‡āŽŖā¯āŽŸā¯āŽŽā¯.", "backup_onboarding_footer": "Immich-āŽ āŽ¤āŽ°āŽĩ❁ āŽ¨āŽ•āŽ˛ā¯ āŽ•āŽžāŽĒā¯āŽĒ❁ āŽŽāŽŸā¯āŽĒā¯āŽĒāŽ¤ā¯ āŽĒāŽąā¯āŽąāŽŋāŽ¯ āŽŽā¯‡āŽ˛ā¯āŽŽā¯ āŽ¤āŽ•āŽĩāŽ˛ā¯āŽ•ā¯āŽ•ā¯, āŽ¤āŽ¯āŽĩā¯āŽšā¯†āŽ¯ā¯āŽ¤ā¯ āŽ†āŽĩāŽŖāŽ¤ā¯āŽ¤ā¯ˆ āŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯.", "backup_onboarding_parts_title": "3-2-1 āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋāŽ¯āŽŋāŽ˛ā¯ āŽĒāŽŋāŽŠā¯āŽĩāŽ°ā¯āŽĩāŽŠ āŽ…āŽŸāŽ™ā¯āŽ•ā¯āŽŽā¯:", "backup_onboarding_title": "āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋāŽ•āŽŗā¯", - "backup_settings": "āŽ•āŽžāŽĒā¯āŽĒ❁ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", - "backup_settings_description": "āŽ¤āŽ°āŽĩā¯āŽ¤ā¯āŽ¤āŽŗ āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "backup_settings": "āŽ¤āŽ°āŽĩā¯āŽ¤ā¯āŽ¤āŽŗ āŽ¤āŽŋāŽŖāŽŋāŽĒā¯āŽĒ❁ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", + "backup_settings_description": "āŽ¤āŽ°āŽĩā¯āŽ¤ā¯āŽ¤āŽŗ āŽ¨āŽ•āŽ˛ā¯ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋ.", "cleared_jobs": "āŽŽā¯āŽŸāŽŋāŽ¤ā¯āŽ¤ āŽĩā¯‡āŽ˛ā¯ˆāŽ•āŽŗā¯: {job}", "config_set_by_file": "āŽ•āŽŸā¯āŽŸāŽŽā¯ˆāŽĒā¯āŽĒ❁, āŽ¤āŽąā¯āŽĒā¯‹āŽ¤ā¯ āŽ’āŽ°ā¯ āŽ•āŽŸā¯āŽŸāŽŽā¯ˆāŽĒā¯āŽĒ❁ āŽ•ā¯‹āŽĒā¯āŽĒ❁ āŽŽā¯‚āŽ˛āŽŽā¯ āŽ…āŽŽā¯ˆāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗāŽ¤ā¯", "confirm_delete_library": "{library} āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽ¨ā¯‚āŽ˛āŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽ¨āŽŋāŽšā¯āŽšāŽ¯āŽŽāŽžāŽ• āŽ¨ā¯€āŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", @@ -67,7 +69,7 @@ "confirm_user_pin_code_reset": "{user} āŽ‡āŽŠā¯ āŽĒāŽŋāŽŠā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ˆ āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆāŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", "create_job": "āŽĩā¯‡āŽ˛ā¯ˆāŽ¯ā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•ā¯", "cron_expression": "āŽ•ā¯āŽ°ā¯‹āŽŠā¯ āŽĩā¯†āŽŗāŽŋāŽĒā¯āŽĒāŽžāŽŸā¯", - "cron_expression_description": "CRON āŽĩāŽŸāŽŋāŽĩāŽŽā¯ˆāŽĒā¯āŽĒ❈āŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽŋ āŽšā¯āŽ•ā¯‡āŽŠāŽŋāŽ™ā¯ āŽ‡āŽŸā¯ˆāŽĩā¯†āŽŗāŽŋāŽ¯ā¯ˆ āŽ…āŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯. āŽŽā¯‡āŽ˛ā¯āŽŽā¯ āŽ¤āŽ•āŽĩāŽ˛ā¯āŽ•ā¯āŽ•ā¯ āŽŽ.āŽ•āŽž. <āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❁> āŽ•ā¯āŽ°ā¯‹āŽŠā¯āŽŸāŽžāŽĒā¯ āŽ•ā¯āŽ°ā¯ ", + "cron_expression_description": "CRON āŽĩāŽŸāŽŋāŽĩāŽŽā¯ˆāŽĒā¯āŽĒ❈āŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽŋ āŽšā¯āŽ•ā¯‡āŽŠāŽŋāŽ™ā¯ āŽ‡āŽŸā¯ˆāŽĩā¯†āŽŗāŽŋāŽ¯ā¯ˆ āŽ…āŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯. āŽŽā¯‡āŽ˛ā¯āŽŽā¯ āŽ¤āŽ•āŽĩāŽ˛ā¯āŽ•ā¯āŽ•ā¯ āŽŽ.āŽ•āŽž. āŽ•ā¯āŽ°ā¯‹āŽŠā¯āŽŸāŽžāŽĒā¯ āŽ•ā¯āŽ°ā¯ ", "cron_expression_presets": "āŽ•ā¯āŽ°ā¯‹āŽŠā¯ āŽĩā¯†āŽŗāŽŋāŽĒā¯āŽĒāŽžāŽŸā¯ āŽŽā¯āŽŠā¯āŽŠāŽŽā¯ˆāŽĩā¯āŽ•āŽŗā¯", "disable_login": "āŽ‰āŽŗā¯āŽ¨ā¯āŽ´ā¯ˆāŽĩ❈ āŽŽā¯āŽŸāŽ•ā¯āŽ•ā¯", "duplicate_detection_job_description": "āŽ’āŽ¤ā¯āŽ¤ āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆāŽ•ā¯ āŽ•āŽŖā¯āŽŸāŽąāŽŋāŽ¯, āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽ‡āŽ¯āŽ¨ā¯āŽ¤āŽŋāŽ°āŽ•ā¯ āŽ•āŽąā¯āŽąāŽ˛ā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯. āŽ¸ā¯āŽŽāŽžāŽ°ā¯āŽŸā¯ āŽ¤ā¯‡āŽŸāŽ˛ā¯ˆ āŽ¨āŽŽā¯āŽĒāŽŋāŽ¯ā¯āŽŗā¯āŽŗāŽ¤ā¯", @@ -86,7 +88,7 @@ "image_fullsize_quality_description": "āŽŽā¯āŽ´ā¯ āŽ…āŽŗāŽĩāŽŋāŽ˛āŽžāŽŠ āŽĒāŽŸāŽ¤ā¯ āŽ¤āŽ°āŽŽā¯ 1-100 āŽĩāŽ°ā¯ˆ. āŽ…āŽ¤āŽŋāŽ•āŽŽāŽžāŽŠ āŽŽāŽŖā¯ āŽšāŽŋāŽąāŽ¨ā¯āŽ¤āŽ¤ā¯, āŽ†āŽŠāŽžāŽ˛ā¯ āŽĒā¯†āŽ°āŽŋāŽ¯ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•ā¯āŽŽā¯.", "image_fullsize_title": "āŽŽā¯āŽ´ā¯ āŽ…āŽŗāŽĩāŽŋāŽ˛āŽžāŽŠ āŽĒāŽŸ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", "image_prefer_embedded_preview": "āŽ‰āŽŸā¯āŽĒā¯ŠāŽ¤āŽŋāŽ¨ā¯āŽ¤ āŽĒāŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽŽā¯āŽŠā¯āŽŠāŽŋāŽŸā¯", - "image_prefer_embedded_preview_setting_description": "āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•ā¯āŽŽā¯āŽĒā¯‹āŽ¤ā¯ āŽĒāŽŸ āŽšā¯†āŽ¯āŽ˛āŽžāŽ•ā¯āŽ•āŽ¤ā¯āŽ¤āŽŋāŽąā¯āŽ•āŽžāŽŠ āŽ‰āŽŗā¯āŽŗā¯€āŽŸāŽžāŽ• āŽŽā¯‚āŽ˛ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽ‰āŽŸā¯āŽĒā¯ŠāŽ¤āŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽŽāŽžāŽ¤āŽŋāŽ°āŽŋāŽ•ā¯āŽ•āŽžāŽŸā¯āŽšāŽŋāŽ•āŽŗā¯ˆāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯. āŽ‡āŽ¤ā¯ āŽšāŽŋāŽ˛ āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽŽāŽŋāŽ•āŽĩā¯āŽŽā¯ āŽ¤ā¯āŽ˛ā¯āŽ˛āŽŋāŽ¯āŽŽāŽžāŽŠ āŽĩāŽŖā¯āŽŖāŽ™ā¯āŽ•āŽŗā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯ā¯āŽŽā¯, āŽ†āŽŠāŽžāŽ˛ā¯ āŽŽā¯āŽŠā¯āŽŠā¯‹āŽŸā¯āŽŸāŽ¤ā¯āŽ¤āŽŋāŽŠā¯ āŽ¤āŽ•ā¯āŽ¤āŽŋ āŽ•ā¯‡āŽŽāŽ°āŽž āŽšāŽžāŽ°ā¯āŽ¨ā¯āŽ¤āŽ¤ā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĒāŽŸāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ…āŽ¤āŽŋāŽ• āŽšā¯āŽ°ā¯āŽ•ā¯āŽ• āŽ•āŽ˛ā¯ˆāŽĒā¯āŽĒā¯ŠāŽ°ā¯āŽŸā¯āŽ•āŽŗā¯ āŽ‡āŽ°ā¯āŽ•ā¯āŽ•āŽ˛āŽžāŽŽā¯.", + "image_prefer_embedded_preview_setting_description": "āŽĒāŽŸ āŽšā¯†āŽ¯āŽ˛āŽžāŽ•ā¯āŽ•āŽ¤ā¯āŽ¤āŽŋāŽąā¯āŽ•āŽžāŽŠ āŽ‰āŽŗā¯āŽŗā¯€āŽŸāŽžāŽ• āŽŽā¯‚āŽ˛ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽ‰āŽŸā¯āŽĒā¯ŠāŽ¤āŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽŽā¯āŽŠā¯āŽŠā¯‹āŽŸā¯āŽŸāŽ™ā¯āŽ•āŽŗā¯ˆ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯, āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•ā¯āŽŽā¯āŽĒā¯‹āŽ¤ā¯. āŽ‡āŽ¤ā¯ āŽšāŽŋāŽ˛ āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽŽāŽŋāŽ•āŽĩā¯āŽŽā¯ āŽ¤ā¯āŽ˛ā¯āŽ˛āŽŋāŽ¯āŽŽāŽžāŽŠ āŽĩāŽŖā¯āŽŖāŽ™ā¯āŽ•āŽŗā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯ā¯āŽŽā¯, āŽ†āŽŠāŽžāŽ˛ā¯ āŽŽā¯āŽŠā¯āŽŠā¯‹āŽŸā¯āŽŸāŽ¤ā¯āŽ¤āŽŋāŽŠā¯ āŽ¤āŽ•ā¯āŽ¤āŽŋ āŽ•ā¯‡āŽŽāŽ°āŽž āŽšāŽžāŽ°ā¯āŽ¨ā¯āŽ¤āŽ¤ā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĒāŽŸāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ…āŽ¤āŽŋāŽ• āŽšā¯āŽ°ā¯āŽ•ā¯āŽ• āŽ•āŽ˛ā¯ˆāŽĒā¯āŽĒā¯ŠāŽ°ā¯āŽŸā¯āŽ•āŽŗā¯ āŽ‡āŽ°ā¯āŽ•ā¯āŽ•āŽ˛āŽžāŽŽā¯.", "image_prefer_wide_gamut": "āŽ…āŽ•āŽŠā¯āŽą āŽĩāŽŖā¯āŽŖāŽĩāŽ°āŽŽā¯āŽĒ❁ āŽ¤ā¯‡āŽ°ā¯āŽĩ❁", "image_prefer_wide_gamut_setting_description": "āŽšāŽŋāŽąā¯ āŽ‰āŽ°ā¯āŽĩāŽ™ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽ•āŽžāŽŸā¯āŽšāŽŋ āŽĒāŽŋ 3 āŽāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯. āŽ‡āŽ¤ā¯ āŽĒāŽ°āŽ¨ā¯āŽ¤ āŽĩāŽŖā¯āŽŖāŽ™ā¯āŽ•āŽŗā¯ˆāŽ•ā¯ āŽ•ā¯ŠāŽŖā¯āŽŸ āŽĒāŽŸāŽ™ā¯āŽ•āŽŗāŽŋāŽŠā¯ āŽ…āŽ¤āŽŋāŽ°ā¯āŽĩā¯āŽ•āŽŗā¯ˆ āŽšāŽŋāŽąāŽĒā¯āŽĒāŽžāŽ• āŽĒāŽžāŽ¤ā¯āŽ•āŽžāŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯, āŽ†āŽŠāŽžāŽ˛ā¯ āŽĒāŽ´ā¯ˆāŽ¯ āŽ‰āŽ˛āŽžāŽĩāŽŋ āŽĒāŽ¤āŽŋāŽĒā¯āŽĒā¯ˆāŽ•ā¯ āŽ•ā¯ŠāŽŖā¯āŽŸ āŽĒāŽ´ā¯ˆāŽ¯ āŽšāŽžāŽ¤āŽŠāŽ™ā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽĩāŽŋāŽ¤ā¯āŽ¤āŽŋāŽ¯āŽžāŽšāŽŽāŽžāŽ• āŽ¤ā¯‹āŽŠā¯āŽąāŽ•ā¯āŽ•ā¯‚āŽŸā¯āŽŽā¯. āŽĩāŽŖā¯āŽŖ āŽŽāŽžāŽąā¯āŽąāŽ™ā¯āŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤āŽĩāŽŋāŽ°ā¯āŽ•ā¯āŽ• SRGB āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ SRGB āŽ†āŽ• āŽĩā¯ˆāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽ•āŽŋāŽŠā¯āŽąāŽŠ.", "image_preview_description": "āŽ…āŽ•āŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽŽā¯†āŽŸā¯āŽŸāŽžāŽŸā¯‡āŽŸā¯āŽŸāŽžāŽĩā¯āŽŸāŽŠā¯ āŽ¨āŽŸā¯āŽ¤ā¯āŽ¤āŽ° āŽ…āŽŗāŽĩāŽŋāŽ˛āŽžāŽŠ āŽĒāŽŸāŽŽā¯, āŽ’āŽąā¯āŽąā¯ˆ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆāŽĒā¯ āŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•ā¯āŽŽā¯āŽĒā¯‹āŽ¤ā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽ‡āŽ¯āŽ¨ā¯āŽ¤āŽŋāŽ° āŽ•āŽąā¯āŽąāŽ˛ā¯āŽ•ā¯āŽ•āŽžāŽ•āŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽ•āŽŋāŽąāŽ¤ā¯", @@ -106,8 +108,8 @@ "job_settings": "āŽĩā¯‡āŽ˛ā¯ˆ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", "job_settings_description": "āŽĩā¯‡āŽ˛ā¯ˆ āŽ’āŽ¤ā¯āŽ¤āŽŋāŽšā¯ˆāŽĩ❈ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "job_status": "āŽĩā¯‡āŽ˛ā¯ˆ āŽ¨āŽŋāŽ˛ā¯ˆ", - "jobs_delayed": "{JobCount, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽĒāŽŋāŽą {# āŽ¤āŽžāŽŽāŽ¤āŽŽāŽžāŽŠāŽ¤ā¯}}", - "jobs_failed": "{JobCount, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽĒāŽŋāŽą {# āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋāŽ¯ā¯āŽąā¯āŽąāŽ¤ā¯}}", + "jobs_delayed": "{jobCount, plural, other {# āŽ¤āŽžāŽŽāŽ¤āŽŽāŽžāŽŠāŽ¤ā¯}}", + "jobs_failed": "{jobCount, plural, other {# āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋāŽ¯ā¯āŽąā¯āŽąāŽ¤ā¯}}", "library_created": "āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸ āŽ¨ā¯‚āŽ˛āŽ•āŽŽā¯: {library}", "library_deleted": "āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸ āŽ¨ā¯‚āŽ˛āŽ•āŽŽā¯ āŽ¨ā¯€āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "library_import_path_description": "āŽ‡āŽąāŽ•ā¯āŽ•ā¯āŽŽāŽ¤āŽŋ āŽšā¯†āŽ¯ā¯āŽ¯ āŽ’āŽ°ā¯ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆāŽ¯ā¯ˆāŽ•ā¯ āŽ•ā¯āŽąāŽŋāŽĒā¯āŽĒāŽŋāŽŸāŽĩā¯āŽŽā¯. āŽ¤ā¯āŽŖā¯ˆāŽ•ā¯ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆāŽ•āŽŗā¯ āŽ‰āŽŸā¯āŽĒāŽŸ āŽ‡āŽ¨ā¯āŽ¤āŽ•ā¯ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆ āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•āŽžāŽ• āŽ¸ā¯āŽ•ā¯‡āŽŠā¯ āŽšā¯†āŽ¯ā¯āŽ¯āŽĒā¯āŽĒāŽŸā¯āŽŽā¯.", @@ -116,13 +118,20 @@ "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": "āŽŽāŽžāŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤āŽžāŽŠāŽžāŽ•āŽĩ❇ āŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "logging_enable_description": "āŽĒāŽ¤āŽŋāŽĩ❁ āŽšā¯†āŽ¯ā¯āŽĩāŽ¤ā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ•ā¯", "logging_level_description": "āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽžāŽ˛ā¯, āŽŽāŽ¨ā¯āŽ¤āŽĒā¯ āŽĒāŽ¤āŽŋāŽĩ❁ āŽ¨āŽŋāŽ˛ā¯ˆ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ āŽĩā¯‡āŽŖā¯āŽŸā¯āŽŽā¯.", "logging_settings": "āŽĒāŽ¤āŽŋāŽĩ❁ āŽšā¯†āŽ¯ā¯āŽ¤āŽ˛ā¯", + "machine_learning_availability_checks": "āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•ā¯āŽŽā¯ āŽ•āŽžāŽšā¯‹āŽ˛ā¯ˆāŽ•āŽŗā¯", + "machine_learning_availability_checks_description": "āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•āŽ•ā¯āŽ•ā¯‚āŽŸāŽŋāŽ¯ āŽ‡āŽ¯āŽ¨ā¯āŽ¤āŽŋāŽ° āŽ•āŽąā¯āŽąāŽ˛ā¯ āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽ™ā¯āŽ•āŽŗā¯ˆ āŽ¤āŽžāŽŠāŽžāŽ• āŽ•āŽŖā¯āŽŸāŽąāŽŋāŽ¨ā¯āŽ¤ā¯ āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ™ā¯āŽ•āŽŗā¯", + "machine_learning_availability_checks_enabled": "āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•ā¯āŽŽā¯ āŽ•āŽžāŽšā¯‹āŽ˛ā¯ˆāŽ•āŽŗā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "machine_learning_availability_checks_interval": "āŽ‡āŽŸā¯ˆāŽĩā¯†āŽŗāŽŋāŽ¯ā¯ˆ āŽšāŽ°āŽŋāŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "machine_learning_availability_checks_interval_description": "āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•ā¯āŽŽā¯ āŽ•āŽžāŽšā¯‹āŽ˛ā¯ˆāŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽ‡āŽŸā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽŽāŽŋāŽ˛ā¯āŽ˛āŽŋ āŽĩāŽŋāŽ¨āŽžāŽŸāŽŋāŽ•āŽŗāŽŋāŽ˛ā¯ āŽ‡āŽŸā¯ˆāŽĩā¯†āŽŗāŽŋ", + "machine_learning_availability_checks_timeout": "āŽ¨ā¯‡āŽ°āŽŽā¯ āŽŽā¯āŽŸāŽŋāŽ¨ā¯āŽ¤āŽ¤ā¯", + "machine_learning_availability_checks_timeout_description": "āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•ā¯āŽŽā¯ āŽ•āŽžāŽšā¯‹āŽ˛ā¯ˆāŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽŽāŽŋāŽ˛ā¯āŽ˛āŽŋ āŽĩāŽŋāŽ¨āŽžāŽŸāŽŋāŽ•āŽŗāŽŋāŽ˛ā¯ āŽ¨ā¯‡āŽ°āŽŽā¯ āŽŽā¯āŽŸāŽŋāŽ¨ā¯āŽ¤āŽ¤ā¯", "machine_learning_clip_model": "āŽ•āŽŋāŽŗāŽŋāŽĒā¯ āŽŽāŽžāŽŸāŽ˛ā¯", "machine_learning_clip_model_description": "CLIP āŽŽāŽžāŽŸāŽ˛ā¯ āŽĒā¯†āŽ¯āŽ°ā¯ āŽ‡āŽ™ā¯āŽ•ā¯‡ āŽĒāŽŸā¯āŽŸāŽŋāŽ¯āŽ˛āŽŋāŽŸāŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗāŽ¤ā¯. āŽ’āŽ°ā¯ āŽŽāŽžāŽŸāŽ¯āŽ˛ā¯ˆ āŽŽāŽžāŽąā¯āŽąāŽŋāŽ¯āŽĩā¯āŽŸāŽŠā¯ āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯āŽŽā¯ 'āŽ¸ā¯āŽŽāŽžāŽ°ā¯āŽŸā¯ āŽ¤ā¯‡āŽŸāŽ˛ā¯' āŽĩā¯‡āŽ˛ā¯ˆāŽ¯ā¯ˆ āŽŽā¯€āŽŖā¯āŽŸā¯āŽŽā¯ āŽ‡āŽ¯āŽ•ā¯āŽ• āŽĩā¯‡āŽŖā¯āŽŸā¯āŽŽā¯ āŽŽāŽŠā¯āŽĒāŽ¤ā¯ˆ āŽ¨āŽŋāŽŠā¯ˆāŽĩāŽŋāŽ˛ā¯ āŽ•ā¯ŠāŽŗā¯āŽŗāŽĩā¯āŽŽā¯.", "machine_learning_duplicate_detection": "āŽ¨āŽ•āŽ˛ā¯ (āŽŸā¯‚āŽĒā¯āŽŗāŽŋāŽ•ā¯‡āŽŸā¯) āŽ•āŽŖā¯āŽŸāŽąāŽŋāŽ¤āŽ˛ā¯", @@ -151,7 +160,7 @@ "machine_learning_smart_search_description": "CLIP āŽŽāŽžāŽŸā¯†āŽ˛ā¯ˆāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽŋ āŽšā¯ŠāŽąā¯āŽĒā¯ŠāŽ°ā¯āŽŗāŽŋāŽ˛ā¯ āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽŸā¯āŽ™ā¯āŽ•āŽŗā¯", "machine_learning_smart_search_enabled": "āŽ¸ā¯āŽŽāŽžāŽ°ā¯āŽŸā¯ āŽ¤ā¯‡āŽŸāŽ˛ā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ•ā¯", "machine_learning_smart_search_enabled_description": "āŽŽā¯āŽŸāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽŋāŽ°ā¯āŽ¨ā¯āŽ¤āŽžāŽ˛ā¯, āŽ¸ā¯āŽŽāŽžāŽ°ā¯āŽŸā¯ āŽ¤ā¯‡āŽŸāŽ˛ā¯āŽ•ā¯āŽ•āŽžāŽ• āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽ•ā¯āŽąāŽŋāŽ¯āŽžāŽ•ā¯āŽ•āŽŽā¯ āŽšā¯†āŽ¯ā¯āŽ¯āŽĒā¯āŽĒāŽŸāŽžāŽ¤ā¯.", - "machine_learning_url_description": "āŽ‡āŽ¯āŽ¨ā¯āŽ¤āŽŋāŽ° āŽ•āŽąā¯āŽąāŽ˛ā¯ āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽ¤ā¯āŽ¤āŽŋāŽŠā¯ āŽŽā¯āŽ•āŽĩāŽ°āŽŋ. āŽ’āŽŠā¯āŽąā¯āŽ•ā¯āŽ•ā¯ āŽŽā¯‡āŽąā¯āŽĒāŽŸā¯āŽŸ āŽŽā¯āŽ•āŽĩāŽ°āŽŋ āŽĩāŽ´āŽ™ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽžāŽ˛ā¯, āŽ’āŽĩā¯āŽĩā¯ŠāŽ°ā¯ āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽŽā¯āŽŽā¯ āŽĩā¯†āŽąā¯āŽąāŽŋāŽ•āŽ°āŽŽāŽžāŽ• āŽĒāŽ¤āŽŋāŽ˛āŽŗāŽŋāŽ•ā¯āŽ•ā¯āŽŽā¯ āŽĩāŽ°ā¯ˆ, āŽŽā¯āŽ¤āŽ˛ā¯ āŽŽā¯āŽ¤āŽ˛ā¯ āŽ•āŽŸā¯ˆāŽšāŽŋ āŽĩāŽ°ā¯ˆ āŽŽā¯āŽ¯āŽąā¯āŽšāŽŋāŽ•ā¯āŽ•ā¯āŽŽā¯.", + "machine_learning_url_description": "āŽ‡āŽ¯āŽ¨ā¯āŽ¤āŽŋāŽ° āŽ•āŽąā¯āŽąāŽ˛ā¯ āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽ¤ā¯āŽ¤āŽŋāŽŠā¯ āŽŽā¯āŽ•āŽĩāŽ°āŽŋ. āŽ’āŽŠā¯āŽąā¯āŽ•ā¯āŽ•ā¯ āŽŽā¯‡āŽąā¯āŽĒāŽŸā¯āŽŸ āŽŽā¯āŽ•āŽĩāŽ°āŽŋ āŽĩāŽ´āŽ™ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽžāŽ˛ā¯, āŽ’āŽĩā¯āŽĩā¯ŠāŽ°ā¯ āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽŽā¯āŽŽā¯ āŽ’āŽĩā¯āŽĩā¯ŠāŽŠā¯āŽąāŽžāŽ• āŽĩā¯†āŽąā¯āŽąāŽŋāŽ•āŽ°āŽŽāŽžāŽ• āŽĒāŽ¤āŽŋāŽ˛āŽŗāŽŋāŽ•ā¯āŽ•ā¯āŽŽā¯ āŽĩāŽ°ā¯ˆ, āŽŽā¯āŽ¤āŽ˛āŽŋāŽ˛ā¯ āŽ‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ•āŽŸā¯ˆāŽšāŽŋ āŽĩāŽ°ā¯ˆ āŽŽā¯āŽ¯āŽąā¯āŽšāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŽā¯. āŽĒāŽ¤āŽŋāŽ˛āŽŗāŽŋāŽ•ā¯āŽ•āŽžāŽ¤ āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽ™ā¯āŽ•āŽŗā¯ āŽŽā¯€āŽŖā¯āŽŸā¯āŽŽā¯ āŽ†āŽŠā¯āŽ˛ā¯ˆāŽŠāŽŋāŽ˛ā¯ āŽĩāŽ°ā¯āŽŽā¯ āŽĩāŽ°ā¯ˆ āŽ¤āŽąā¯āŽ•āŽžāŽ˛āŽŋāŽ•āŽŽāŽžāŽ•āŽĒā¯ āŽĒā¯āŽąāŽ•ā¯āŽ•āŽŖāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŽā¯.", "manage_concurrency": "āŽ’āŽ¤ā¯āŽ¤āŽŋāŽšā¯ˆāŽĩ❈ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "manage_log_settings": "āŽĒāŽ¤āŽŋāŽĩ❁ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "map_dark_style": "āŽ‡āŽ°ā¯āŽŖā¯āŽŸ āŽ¤ā¯€āŽŽā¯", @@ -167,6 +176,8 @@ "map_settings": "āŽŽā¯‡āŽĒā¯ & āŽœāŽŋāŽĒāŽŋāŽŽāŽ¸ā¯ (GPS) āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", "map_settings_description": "āŽŽā¯‡āŽĒā¯ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "map_style_description": "style.json āŽŽā¯‡āŽĒā¯ āŽ¤ā¯€āŽŽā¯āŽ•ā¯āŽ•āŽžāŽŠ URL", + "memory_cleanup_job": "āŽ¨āŽŋāŽŠā¯ˆāŽĩāŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽšā¯āŽ¤ā¯āŽ¤āŽŽā¯ āŽšā¯†āŽ¯ā¯āŽ¤āŽ˛ā¯", + "memory_generate_job": "āŽ¨āŽŋāŽŠā¯ˆāŽĩāŽ• āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽŽā¯", "metadata_extraction_job": "āŽŽā¯†āŽŸā¯āŽŸāŽžāŽŸā¯‡āŽŸā¯āŽŸāŽžāŽĩ❈āŽĒā¯ āŽĒāŽŋāŽ°āŽŋāŽ¤ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "metadata_extraction_job_description": "āŽœāŽŋāŽĒāŽŋāŽŽāŽ¸ā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽ¤ā¯†āŽŗāŽŋāŽĩā¯āŽ¤ā¯āŽ¤āŽŋāŽąāŽŠā¯ āŽĒā¯‹āŽŠā¯āŽą āŽ’āŽĩā¯āŽĩā¯ŠāŽ°ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯āŽŽā¯ āŽŽā¯†āŽŸā¯āŽŸāŽžāŽŸā¯‡āŽŸā¯āŽŸāŽž āŽ¤āŽ•āŽĩāŽ˛ā¯ˆāŽĒā¯ āŽĒāŽŋāŽ°āŽŋāŽ¤ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "metadata_faces_import_setting": "āŽŽā¯āŽ• āŽ‡āŽąāŽ•ā¯āŽ•ā¯āŽŽāŽ¤āŽŋāŽ¯ā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", @@ -175,12 +186,26 @@ "metadata_settings_description": "āŽŽā¯‡āŽŠāŽŋāŽ˛ā¯ˆ āŽ¤āŽ°āŽĩ❁ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "migration_job": "āŽ‡āŽŸāŽŽā¯āŽĒā¯†āŽ¯āŽ°ā¯āŽ¤āŽ˛ā¯", "migration_job_description": "āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽŽā¯āŽ•āŽ™ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•āŽžāŽŠ āŽšāŽŋāŽąā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆ (āŽ¤āŽŽā¯āŽĒā¯āŽŠā¯†āŽ¯āŽŋāŽ˛ā¯) āŽšāŽŽā¯€āŽĒāŽ¤ā¯āŽ¤āŽŋāŽ¯ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒāŽŋāŽąā¯āŽ•ā¯ āŽŽāŽžāŽąā¯āŽąāŽĩā¯āŽŽā¯", + "nightly_tasks_cluster_faces_setting_description": "āŽĒā¯āŽ¤āŽŋāŽ¤āŽžāŽ•āŽ•ā¯ āŽ•āŽŖā¯āŽŸāŽąāŽŋāŽ¯āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽŽā¯āŽ•āŽ™ā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽŽā¯āŽ• āŽ…āŽ™ā¯āŽ•ā¯€āŽ•āŽžāŽ°āŽ¤ā¯āŽ¤ā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ•ā¯", + "nightly_tasks_cluster_new_faces_setting": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽŽā¯āŽ•āŽ™ā¯āŽ•āŽŗā¯ˆāŽ•ā¯ āŽ¤ā¯ŠāŽ•ā¯āŽ¤āŽŋāŽĒāŽŸā¯āŽ¤ā¯āŽ¤ā¯", + "nightly_tasks_database_cleanup_setting": "āŽ¤āŽ°āŽĩā¯āŽ¤ā¯āŽ¤āŽŗāŽ¤ā¯āŽ¤ā¯ˆ āŽšā¯āŽ¤ā¯āŽ¤āŽŽā¯ āŽšā¯†āŽ¯ā¯āŽ¯ā¯āŽŽā¯ āŽĒāŽŖāŽŋāŽ•āŽŗā¯", + "nightly_tasks_database_cleanup_setting_description": "āŽ¤āŽ°āŽĩā¯āŽ¤ā¯āŽ¤āŽŗāŽ¤ā¯āŽ¤āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽĒāŽ´ā¯ˆāŽ¯, āŽ•āŽžāŽ˛āŽžāŽĩāŽ¤āŽŋāŽ¯āŽžāŽŠ āŽ¤āŽ°āŽĩ❈ āŽšā¯āŽ¤ā¯āŽ¤āŽŽā¯ āŽšā¯†āŽ¯ā¯āŽ¯āŽĩā¯āŽŽā¯", + "nightly_tasks_generate_memories_setting": "āŽ¨āŽŋāŽŠā¯ˆāŽĩā¯āŽ•āŽŗā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•ā¯", + "nightly_tasks_generate_memories_setting_description": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗāŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ¨āŽŋāŽŠā¯ˆāŽĩā¯āŽ•āŽŗā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•ā¯", + "nightly_tasks_missing_thumbnails_setting": "āŽĩāŽŋāŽŸā¯āŽĒāŽŸā¯āŽŸ āŽšāŽŋāŽąā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•ā¯", + "nightly_tasks_missing_thumbnails_setting_description": "āŽšāŽŋāŽąā¯āŽĒāŽŸ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽ¤ā¯āŽ¤āŽŋāŽąā¯āŽ•āŽžāŽ• āŽšāŽŋāŽąā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽ‡āŽ˛ā¯āŽ˛āŽžāŽŽāŽ˛ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽĩāŽ°āŽŋāŽšā¯ˆāŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", + "nightly_tasks_settings": "āŽ‡āŽ°āŽĩ❁ āŽ¨ā¯‡āŽ°āŽĒā¯ āŽĒāŽŖāŽŋāŽ•āŽŗā¯ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", + "nightly_tasks_settings_description": "āŽ‡āŽ°āŽĩ❁ āŽ¨ā¯‡āŽ° āŽĒāŽŖāŽŋāŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋ", + "nightly_tasks_start_time_setting": "āŽ¤ā¯ŠāŽŸāŽ•ā¯āŽ• āŽ¨ā¯‡āŽ°āŽŽā¯", + "nightly_tasks_start_time_setting_description": "āŽšāŽ°ā¯āŽĩāŽ°ā¯ āŽ‡āŽ°āŽĩ❁ āŽ¨ā¯‡āŽ° āŽĒāŽŖāŽŋāŽ•āŽŗā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽ¤ā¯ āŽ¤ā¯ŠāŽŸāŽ™ā¯āŽ•ā¯āŽŽā¯ āŽ¨ā¯‡āŽ°āŽŽā¯", + "nightly_tasks_sync_quota_usage_setting": "āŽ’āŽ¤ā¯āŽ¤āŽŋāŽšā¯ˆāŽĩ❁ āŽ’āŽ¤ā¯āŽ•ā¯āŽ•ā¯€āŽŸā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯", + "nightly_tasks_sync_quota_usage_setting_description": "āŽ¤āŽąā¯āŽĒā¯‹āŽ¤ā¯ˆāŽ¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯āŽŸāŽŋāŽŠā¯ āŽ…āŽŸāŽŋāŽĒā¯āŽĒāŽŸā¯ˆāŽ¯āŽŋāŽ˛ā¯, āŽĒāŽ¯āŽŠāŽ°ā¯ āŽšā¯‡āŽŽāŽŋāŽĒā¯āŽĒāŽ• āŽ’āŽ¤ā¯āŽ•ā¯āŽ•ā¯€āŽŸā¯āŽŸā¯ˆāŽĒā¯ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "no_paths_added": "āŽƒāŽĒā¯‹āŽ˛ā¯āŽŸā¯āŽŸāŽ°ā¯ āŽĒāŽžāŽ¤ā¯ˆāŽ•āŽŗā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸāŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "no_pattern_added": "āŽĒā¯‡āŽŸā¯āŽŸāŽ°ā¯āŽŠā¯ā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸāŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "note_apply_storage_label_previous_assets": "āŽ•ā¯āŽąāŽŋāŽĒā¯āŽĒ❁: āŽŽā¯āŽŠā¯āŽĒ❁ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąāŽŋāŽ¯ āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽšā¯‡āŽŽāŽŋāŽĒā¯āŽĒāŽ• āŽ˛ā¯‡āŽĒāŽŋāŽŗā¯ˆāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤, āŽ‡āŽ¤ā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "note_cannot_be_changed_later": "āŽ•ā¯āŽąāŽŋāŽĒā¯āŽĒ❁: āŽ‡āŽ¤ā¯ˆ āŽĒāŽŋāŽŠā¯āŽŠāŽ°ā¯ āŽŽāŽžāŽąā¯āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯!", "notification_email_from_address": "āŽŽā¯āŽ•āŽĩāŽ°āŽŋāŽ¯āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯", - "notification_email_from_address_description": "āŽ…āŽŠā¯āŽĒā¯āŽĒā¯āŽ¨āŽ°āŽŋāŽŠā¯ āŽŽāŽŋāŽŠā¯āŽŠāŽžā¯āŽšāŽ˛ā¯ āŽŽā¯āŽ•āŽĩāŽ°āŽŋ, āŽŽāŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽžāŽŸā¯āŽŸāŽžāŽ•: \"āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸ āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽŽā¯ \"", + "notification_email_from_address_description": "āŽ…āŽŠā¯āŽĒā¯āŽĒā¯āŽ¨āŽ°āŽŋāŽŠā¯ āŽŽāŽŋāŽŠā¯āŽŠāŽžā¯āŽšāŽ˛ā¯ āŽŽā¯āŽ•āŽĩāŽ°āŽŋ, āŽŽāŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽžāŽŸā¯āŽŸāŽžāŽ•: \"āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸ āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽŽā¯ \". āŽŽāŽŋāŽŠā¯āŽŠāŽžā¯āŽšāŽ˛ā¯āŽ•āŽŗā¯ˆ āŽ…āŽŠā¯āŽĒā¯āŽĒ āŽ…āŽŠā¯āŽŽāŽ¤āŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽŽā¯āŽ•āŽĩāŽ°āŽŋāŽ¯ā¯ˆāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽĩāŽ¤ā¯ˆ āŽ‰āŽąā¯āŽ¤āŽŋāŽšā¯†āŽ¯ā¯āŽ¤ā¯ āŽ•ā¯ŠāŽŗā¯āŽŗā¯āŽ™ā¯āŽ•āŽŗā¯.", "notification_email_host_description": "āŽŽāŽŋāŽŠā¯āŽŠāŽžā¯āŽšāŽ˛ā¯ āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽ¤ā¯āŽ¤āŽŋāŽŠā¯ āŽšā¯‹āŽ¸ā¯āŽŸā¯ (āŽŽāŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽžāŽŸā¯āŽŸāŽžāŽ•: smtp.immich.app)", "notification_email_ignore_certificate_errors": "āŽšāŽžāŽŠā¯āŽąāŽŋāŽ¤āŽ´ā¯ āŽĒāŽŋāŽ´ā¯ˆāŽ•āŽŗā¯ˆ āŽĒā¯āŽąāŽ•ā¯āŽ•āŽŖāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "notification_email_ignore_certificate_errors_description": "TLS āŽšāŽžāŽŠā¯āŽąāŽŋāŽ¤āŽ´ā¯ āŽšāŽ°āŽŋāŽĒāŽžāŽ°ā¯āŽĒā¯āŽĒ❁ āŽĒāŽŋāŽ´ā¯ˆāŽ•āŽŗā¯ˆ āŽĒā¯āŽąāŽ•ā¯āŽ•āŽŖāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯ (āŽĒāŽ°āŽŋāŽ¨ā¯āŽ¤ā¯āŽ°ā¯ˆāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸāŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ)", @@ -200,11 +225,14 @@ "oauth_auto_register": "āŽ¤āŽžāŽŠāŽŋāŽ¯āŽ™ā¯āŽ•ā¯ āŽĒāŽ¤āŽŋāŽĩ❁", "oauth_auto_register_description": "OAuth āŽ‰āŽŸāŽŠā¯ āŽ‰āŽŗā¯āŽ¨ā¯āŽ´ā¯ˆāŽ¨ā¯āŽ¤ āŽĒāŽŋāŽąāŽ•ā¯ āŽ¤āŽžāŽŠāŽžāŽ•āŽĩ❇ āŽĒā¯āŽ¤āŽŋāŽ¯ āŽĒāŽ¯āŽŠāŽ°ā¯āŽ•āŽŗā¯ˆāŽĒā¯ āŽĒāŽ¤āŽŋāŽĩā¯āŽšā¯†āŽ¯ā¯āŽ¯āŽĩā¯āŽŽā¯", "oauth_button_text": "āŽĒāŽŸā¯āŽŸāŽŠā¯ āŽ‰āŽ°ā¯ˆ", + "oauth_client_secret_description": "āŽ…āŽĩāŽšāŽŋāŽ¯āŽŽā¯, OAuth āŽĩāŽ´āŽ™ā¯āŽ•ā¯āŽ¨āŽ°āŽžāŽ˛ā¯ PKCE (āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯āŽĒā¯ āŽĒāŽ°āŽŋāŽŽāŽžāŽąā¯āŽąāŽ¤ā¯āŽ¤āŽŋāŽąā¯āŽ•āŽžāŽŠ āŽ†āŽ¤āŽžāŽ° āŽĩāŽŋāŽšā¯ˆ) āŽ†āŽ¤āŽ°āŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸāŽžāŽĩāŽŋāŽŸā¯āŽŸāŽžāŽ˛ā¯", "oauth_enable_description": "OAuth āŽŽā¯‚āŽ˛āŽŽā¯ āŽ‰āŽŗā¯āŽ¨ā¯āŽ´ā¯ˆāŽ•", "oauth_mobile_redirect_uri": "āŽŽā¯ŠāŽĒā¯ˆāŽ˛ā¯ āŽĩāŽ´āŽŋāŽŽāŽžāŽąā¯āŽąā¯ URI", "oauth_mobile_redirect_uri_override": "āŽŽā¯ŠāŽĒā¯ˆāŽ˛ā¯ āŽĩāŽ´āŽŋāŽŽāŽžāŽąā¯āŽąā¯ URI āŽŽā¯‡āŽ˛ā¯†āŽ´ā¯āŽ¤ā¯āŽ¤āŽ˛ā¯", - "oauth_mobile_redirect_uri_override_description": "'app.immich:/' āŽ¤āŽĩāŽąāŽžāŽŠ āŽĩāŽ´āŽŋāŽŽāŽžāŽąā¯āŽąā¯ URI āŽ†āŽ• āŽ‡āŽ°ā¯āŽ•ā¯āŽ•ā¯āŽŽā¯āŽĒā¯‹āŽ¤ā¯ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯.", - "oauth_settings": "Oauth", + "oauth_mobile_redirect_uri_override_description": "''{callback}'' āŽĒā¯‹āŽŠā¯āŽą āŽŽā¯ŠāŽĒā¯ˆāŽ˛ā¯ URI āŽ OAuth āŽĩāŽ´āŽ™ā¯āŽ•ā¯āŽ¨āŽ°ā¯ āŽ…āŽŠā¯āŽŽāŽ¤āŽŋāŽ•ā¯āŽ•āŽžāŽ¤āŽĒā¯‹āŽ¤ā¯ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "oauth_role_claim": "āŽĒāŽ¤āŽĩāŽŋ āŽ‰āŽ°āŽŋāŽŽā¯ˆāŽ•ā¯‹āŽ°āŽ˛ā¯", + "oauth_role_claim_description": "āŽ‡āŽ¨ā¯āŽ¤āŽ•ā¯ āŽ•ā¯‹āŽ°āŽŋāŽ•ā¯āŽ•ā¯ˆāŽ¯āŽŋāŽŠā¯ āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽŋāŽŠā¯ āŽ…āŽŸāŽŋāŽĒā¯āŽĒāŽŸā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽ¤āŽžāŽŠāŽžāŽ•āŽĩ❇ āŽ¨āŽŋāŽ°ā¯āŽĩāŽžāŽ•āŽŋ āŽ…āŽŖā¯āŽ•āŽ˛ā¯ˆ āŽĩāŽ´āŽ™ā¯āŽ•āŽĩā¯āŽŽā¯. āŽ•ā¯‹āŽ°āŽŋāŽ•ā¯āŽ•ā¯ˆāŽ¯āŽŋāŽ˛ā¯ 'āŽĒāŽ¯āŽŠāŽ°ā¯' āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ 'āŽ¨āŽŋāŽ°ā¯āŽĩāŽžāŽ•āŽŋ' āŽ‡āŽ°ā¯āŽ•ā¯āŽ•āŽ˛āŽžāŽŽā¯.", + "oauth_settings": "āŽ“āŽ†āŽ¤ā¯", "oauth_settings_description": "OAuth āŽ‰āŽŗā¯āŽ¨ā¯āŽ´ā¯ˆāŽĩ❁ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "oauth_settings_more_details": "āŽ‡āŽ¨ā¯āŽ¤ āŽ…āŽŽā¯āŽšāŽ¤ā¯āŽ¤ā¯ˆāŽĒā¯ āŽĒāŽąā¯āŽąāŽŋāŽ¯ āŽ•ā¯‚āŽŸā¯āŽ¤āŽ˛ā¯ āŽĩāŽŋāŽĩāŽ°āŽ™ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯, āŽŸāŽžāŽ•ā¯āŽ¸ā¯ āŽāŽĒā¯ āŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯.", "oauth_storage_label_claim": "āŽšā¯‡āŽŽāŽŋāŽĒā¯āŽĒāŽ• āŽ˛ā¯‡āŽĒāŽŋāŽŗā¯ āŽ‰āŽ°āŽŋāŽŽā¯ˆāŽ•ā¯‹āŽ°āŽ˛ā¯", @@ -212,7 +240,9 @@ "oauth_storage_quota_claim": "āŽšā¯‡āŽŽāŽŋāŽĒā¯āŽĒāŽ• āŽ’āŽ¤ā¯āŽ•ā¯āŽ•ā¯€āŽŸā¯ āŽ‰āŽ°āŽŋāŽŽā¯ˆāŽ•ā¯‹āŽ°āŽ˛ā¯", "oauth_storage_quota_claim_description": "āŽ‡āŽ¨ā¯āŽ¤ āŽ‰āŽ°āŽŋāŽŽā¯ˆāŽ•ā¯‹āŽ°āŽ˛āŽŋāŽŠā¯ āŽŽāŽ¤āŽŋāŽĒā¯āŽĒāŽŋāŽąā¯āŽ•ā¯ āŽĒāŽ¯āŽŠāŽ°āŽŋāŽŠā¯ āŽšā¯‡āŽŽāŽŋāŽĒā¯āŽĒāŽ• āŽ’āŽ¤ā¯āŽ•ā¯āŽ•ā¯€āŽŸā¯āŽŸā¯ˆ āŽ¤āŽžāŽŠāŽžāŽ• āŽ…āŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯.", "oauth_storage_quota_default": "āŽ‡āŽ¯āŽ˛ā¯āŽĒā¯āŽ¨āŽŋāŽ˛ā¯ˆ āŽšā¯‡āŽŽāŽŋāŽĒā¯āŽĒāŽ• āŽ’āŽ¤ā¯āŽ•ā¯āŽ•ā¯€āŽŸā¯ (GiB)", - "oauth_storage_quota_default_description": "GiB āŽ‡āŽ˛ā¯ āŽ‰āŽŗā¯āŽŗ āŽ’āŽ¤ā¯āŽ•ā¯āŽ•ā¯€āŽŸā¯ āŽŽāŽ¨ā¯āŽ¤ āŽ‰āŽ°āŽŋāŽŽā¯ˆāŽ•ā¯‹āŽ°āŽ˛ā¯āŽŽā¯ āŽĩāŽ´āŽ™ā¯āŽ•āŽĒā¯āŽĒāŽŸāŽžāŽ¤āŽĒā¯‹āŽ¤ā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŽā¯ (āŽĩāŽ°āŽŽā¯āŽĒāŽąā¯āŽą āŽ’āŽ¤ā¯āŽ•ā¯āŽ•ā¯€āŽŸā¯āŽŸāŽŋāŽąā¯āŽ•ā¯ 0 āŽ āŽ‰āŽŗā¯āŽŗāŽŋāŽŸāŽĩā¯āŽŽā¯).", + "oauth_storage_quota_default_description": "GiB āŽ‡āŽ˛ā¯ āŽ‰āŽŗā¯āŽŗ āŽ’āŽ¤ā¯āŽ•ā¯āŽ•ā¯€āŽŸā¯ āŽŽāŽ¨ā¯āŽ¤ āŽ‰āŽ°āŽŋāŽŽā¯ˆāŽ•ā¯‹āŽ°āŽ˛ā¯āŽŽā¯ āŽĩāŽ´āŽ™ā¯āŽ•āŽĒā¯āŽĒāŽŸāŽžāŽ¤āŽĒā¯‹āŽ¤ā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŽā¯ .", + "oauth_timeout": "āŽ•ā¯‹āŽ°āŽŋāŽ•ā¯āŽ•ā¯ˆ āŽ¨ā¯‡āŽ°āŽŽā¯ āŽŽā¯āŽŸāŽŋāŽ¨ā¯āŽ¤āŽ¤ā¯", + "oauth_timeout_description": "āŽ•ā¯‹āŽ°āŽŋāŽ•ā¯āŽ•ā¯ˆāŽ•āŽŗā¯āŽ•ā¯āŽ•āŽžāŽŠ āŽ•āŽžāŽ˛āŽ•ā¯āŽ•ā¯†āŽŸā¯ āŽŽāŽŋāŽ˛ā¯āŽ˛āŽŋ āŽĩāŽŋāŽŠāŽžāŽŸāŽŋāŽ•āŽŗāŽŋāŽ˛ā¯", "password_enable_description": "āŽŽāŽŋāŽŠā¯āŽŠāŽžā¯āŽšāŽ˛ā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯ āŽŽā¯‚āŽ˛āŽŽā¯ āŽ‰āŽŗā¯āŽ¨ā¯āŽ´ā¯ˆāŽ¯āŽĩā¯āŽŽā¯", "password_settings": "āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯ āŽ‰āŽŗā¯āŽ¨ā¯āŽ´ā¯ˆāŽĩ❁", "password_settings_description": "āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯ āŽ‰āŽŗā¯āŽ¨ā¯āŽ´ā¯ˆāŽĩ❁ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", @@ -226,7 +256,7 @@ "reset_settings_to_default": "āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽ‡āŽ¯āŽ˛ā¯āŽĒā¯āŽ¨āŽŋāŽ˛ā¯ˆāŽ•ā¯āŽ•ā¯ āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "reset_settings_to_recent_saved": "āŽ…āŽŖā¯āŽŽā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽšā¯‡āŽŽāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "scanning_library": "āŽšā¯āŽ•ā¯‡āŽŠāŽŋāŽ™ā¯ āŽ¨ā¯‚āŽ˛āŽ•āŽŽā¯", - "search_jobs": "āŽĩā¯‡āŽ˛ā¯ˆāŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽŸā¯āŽ™ā¯āŽ•āŽŗā¯ ...", + "search_jobs": "āŽĩā¯‡āŽ˛ā¯ˆāŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽŸā¯āŽ™ā¯āŽ•āŽŗā¯â€Ļ", "send_welcome_email": "āŽĩāŽ°āŽĩā¯‡āŽąā¯āŽĒ❁ āŽŽāŽŋāŽŠā¯āŽŠāŽžā¯āŽšāŽ˛ā¯ˆ āŽ…āŽŠā¯āŽĒā¯āŽĒāŽĩā¯āŽŽā¯", "server_external_domain_settings": "āŽĩā¯†āŽŗāŽŋāŽĒā¯āŽĒā¯āŽą āŽ•āŽŗāŽŽā¯", "server_external_domain_settings_description": "HTTP (āŽ•āŽŗā¯) āŽ‰āŽŸā¯āŽĒāŽŸ āŽĒā¯ŠāŽ¤ā¯ āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•āŽžāŽŠ āŽŸā¯ŠāŽŽā¯ˆāŽŠā¯: //", @@ -247,9 +277,10 @@ "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 āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽ…āŽ¤āŽŠā¯ āŽ¤āŽžāŽ•ā¯āŽ•āŽ™ā¯āŽ•āŽŗā¯ āŽāŽĒā¯ āŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "storage_template_onboarding_description_v2": "āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽžāŽ˛ā¯, āŽ‡āŽ¨ā¯āŽ¤ āŽ…āŽŽā¯āŽšāŽŽā¯ āŽĒāŽ¯āŽŠāŽ°ā¯ āŽĩāŽ°ā¯ˆāŽ¯āŽąā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽŸā¯†āŽŽā¯āŽĒā¯āŽŗā¯‡āŽŸā¯āŽŸāŽŋāŽŠā¯ āŽ…āŽŸāŽŋāŽĒā¯āŽĒāŽŸā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽ¤āŽžāŽŠāŽžāŽ• āŽ’āŽ´ā¯āŽ™ā¯āŽ•āŽŽā¯ˆāŽ•ā¯āŽ•ā¯āŽŽā¯. āŽŽā¯‡āŽ˛ā¯āŽŽā¯ āŽ¤āŽ•āŽĩāŽ˛ā¯āŽ•ā¯āŽ•ā¯, āŽ†āŽĩāŽŖāŽ™ā¯āŽ•āŽŗā¯ āŽāŽĒā¯ āŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯.", "storage_template_path_length": "āŽ¤ā¯‹āŽ°āŽžāŽ¯āŽŽāŽžāŽŠ āŽĒāŽžāŽ¤ā¯ˆ āŽ¨ā¯€āŽŗ āŽĩāŽ°āŽŽā¯āŽĒ❁: {length, number}/{limit, number}", "storage_template_settings": "āŽ¸ā¯āŽŸā¯‹āŽ°ā¯‡āŽœā¯ āŽŸā¯†āŽŽā¯āŽĒā¯āŽŗā¯‡āŽŸā¯", "storage_template_settings_description": "āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽą āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗāŽŋāŽŠā¯ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒ❁ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽ•ā¯‹āŽĒā¯āŽĒ❁ āŽĒā¯†āŽ¯āŽ°ā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", @@ -264,7 +295,7 @@ "template_email_update_album": "āŽ†āŽ˛ā¯āŽĒāŽŽā¯ āŽĩāŽžāŽ°ā¯āŽĒā¯āŽĒā¯āŽ°ā¯āŽĩ❈āŽĒā¯ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "template_email_welcome": "āŽŽāŽŋāŽŠā¯āŽŠāŽžā¯āŽšāŽ˛ā¯ āŽĩāŽžāŽ°ā¯āŽĒā¯āŽĒā¯āŽ°ā¯āŽĩ❈ āŽĩāŽ°āŽĩā¯‡āŽąā¯āŽ•āŽŋāŽąā¯‹āŽŽā¯", "template_settings": "āŽ…āŽąāŽŋāŽĩāŽŋāŽĒā¯āŽĒ❁ āŽĩāŽžāŽ°ā¯āŽĒā¯āŽĒā¯āŽ°ā¯āŽ•ā¯āŽ•āŽŗā¯", - "template_settings_description": "āŽ…āŽąāŽŋāŽĩāŽŋāŽĒā¯āŽĒā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽ¤āŽŠāŽŋāŽĒā¯āŽĒāŽ¯āŽŠā¯ āŽĩāŽžāŽ°ā¯āŽĒā¯āŽĒā¯āŽ°ā¯āŽ•ā¯āŽ•āŽŗā¯ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯.", + "template_settings_description": "āŽ…āŽąāŽŋāŽĩāŽŋāŽĒā¯āŽĒā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽ¤āŽŠāŽŋāŽĒā¯āŽĒāŽ¯āŽŠā¯ āŽĩāŽžāŽ°ā¯āŽĒā¯āŽĒā¯āŽ°ā¯āŽ•ā¯āŽ•āŽŗā¯ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "theme_custom_css_settings": "āŽ¤āŽŠāŽŋāŽĒā¯āŽĒāŽ¯āŽŠā¯ CSS", "theme_custom_css_settings_description": "CSS āŽ…āŽŽā¯āŽšāŽŽā¯ Immich āŽĩāŽŸāŽŋāŽĩāŽŽā¯ˆāŽĒā¯āŽĒ❈ āŽ¤āŽŠāŽŋāŽĒā¯āŽĒāŽ¯āŽŠāŽžāŽ•ā¯āŽ• āŽ…āŽŠā¯āŽŽāŽ¤āŽŋāŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯.", "theme_settings": "āŽ¤ā¯€āŽŽā¯ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", @@ -287,14 +318,16 @@ "transcoding_audio_codec": "āŽ†āŽŸāŽŋāŽ¯ā¯‹ āŽ•ā¯‹āŽŸā¯†āŽ•ā¯", "transcoding_audio_codec_description": "āŽ“āŽĒāŽšā¯ āŽŽāŽŋāŽ• āŽ‰āŽ¯āŽ°ā¯āŽ¨ā¯āŽ¤ āŽ¤āŽ°āŽŽāŽžāŽŠ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽŽāŽžāŽ•ā¯āŽŽā¯, āŽ†āŽŠāŽžāŽ˛ā¯ āŽĒāŽ´ā¯ˆāŽ¯ āŽšāŽžāŽ¤āŽŠāŽ™ā¯āŽ•āŽŗā¯ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽŽā¯†āŽŠā¯āŽĒā¯ŠāŽ°ā¯āŽŗā¯āŽŸāŽŠā¯ āŽ•ā¯āŽąā¯ˆāŽ¨ā¯āŽ¤ āŽĒā¯ŠāŽ°ā¯āŽ¨ā¯āŽ¤āŽ•ā¯āŽ•ā¯‚āŽŸāŽŋāŽ¯ āŽ¤āŽŠā¯āŽŽā¯ˆāŽ¯ā¯ˆāŽ•ā¯ āŽ•ā¯ŠāŽŖā¯āŽŸā¯āŽŗā¯āŽŗāŽ¤ā¯.", "transcoding_bitrate_description": "āŽŽā¯‡āŽ•ā¯āŽšā¯ āŽĒāŽŋāŽŸā¯āŽ°ā¯‡āŽŸā¯āŽŸā¯ˆ āŽĩāŽŋāŽŸ āŽ…āŽ¤āŽŋāŽ•āŽŽāŽžāŽŠ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽāŽąā¯āŽąā¯āŽ•ā¯āŽ•ā¯ŠāŽŗā¯āŽŗāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽĩāŽŸāŽŋāŽĩāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ", - "transcoding_codecs_learn_more": "āŽ‡āŽ™ā¯āŽ•ā¯‡ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŽā¯ āŽšā¯ŠāŽąā¯āŽ•āŽŗā¯ˆāŽĒā¯ āŽĒāŽąā¯āŽąāŽŋ āŽŽā¯‡āŽ˛ā¯āŽŽā¯ āŽ…āŽąāŽŋāŽ¯, H.264 āŽ•ā¯‹āŽŸā¯†āŽ•ā¯ , HEVC āŽ•ā¯‹āŽŸā¯†āŽ•ā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ VP9 āŽ•ā¯āŽ•āŽžāŽŠ FFMPEG āŽ†āŽĩāŽŖāŽ™ā¯āŽ•āŽŗā¯ˆāŽĒā¯ āŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯ āŽ•ā¯‹āŽŸā¯†āŽ•ā¯ .", + "transcoding_codecs_learn_more": "āŽ‡āŽ™ā¯āŽ•ā¯‡ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŽā¯ āŽšā¯ŠāŽąā¯āŽ•āŽŗā¯ˆāŽĒā¯ āŽĒāŽąā¯āŽąāŽŋ āŽŽā¯‡āŽ˛ā¯āŽŽā¯ āŽ…āŽąāŽŋāŽ¯, H.264 āŽ•ā¯‹āŽŸā¯†āŽ•ā¯, HEVC āŽ•ā¯‹āŽŸā¯†āŽ•ā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ VP9 āŽ•ā¯āŽ•āŽžāŽŠ āŽ•ā¯‹āŽŸā¯†āŽ•ā¯ FFMPEG āŽ†āŽĩāŽŖāŽ™ā¯āŽ•āŽŗā¯ˆāŽĒā¯ āŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯.", "transcoding_constant_quality_mode": "āŽ¨āŽŋāŽ˛ā¯ˆāŽ¯āŽžāŽŠ āŽ¤āŽ° āŽŽā¯āŽąā¯ˆ", "transcoding_constant_quality_mode_description": "CQP āŽ āŽĩāŽŋāŽŸ ICQ āŽšāŽŋāŽąāŽ¨ā¯āŽ¤āŽ¤ā¯, āŽ†āŽŠāŽžāŽ˛ā¯ āŽšāŽŋāŽ˛ āŽĩāŽŠā¯āŽĒā¯ŠāŽ°ā¯āŽŗā¯ āŽŽā¯āŽŸā¯āŽ•ā¯āŽ•āŽŽā¯ āŽšāŽžāŽ¤āŽŠāŽ™ā¯āŽ•āŽŗā¯ āŽ‡āŽ¨ā¯āŽ¤ āŽĒāŽ¯āŽŠā¯āŽŽā¯āŽąā¯ˆāŽ¯ā¯ˆ āŽ†āŽ¤āŽ°āŽŋāŽ•ā¯āŽ•āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ. āŽ‡āŽ¨ā¯āŽ¤ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ¤ā¯āŽ¤ā¯ˆ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒāŽ¤ā¯ āŽ¤āŽ° āŽ…āŽŸāŽŋāŽĒā¯āŽĒāŽŸā¯ˆāŽ¯āŽŋāŽ˛āŽžāŽŠ āŽ•ā¯āŽąāŽŋāŽ¯āŽžāŽ•ā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽŽā¯ āŽĒā¯‹āŽ¤ā¯ āŽ•ā¯āŽąāŽŋāŽĒā¯āŽĒāŽŋāŽŸā¯āŽŸ āŽĒāŽ¯āŽŠā¯āŽŽā¯āŽąā¯ˆāŽ¯ā¯ˆ āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąāŽ¤ā¯. NVENC āŽ†āŽ˛ā¯ āŽĒā¯āŽąāŽ•ā¯āŽ•āŽŖāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯, āŽāŽŠā¯†āŽŠāŽŋāŽ˛ā¯ āŽ‡āŽ¤ā¯ ICQ āŽ āŽ†āŽ¤āŽ°āŽŋāŽ•ā¯āŽ•āŽžāŽ¤ā¯.", "transcoding_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_hardware_acceleration": "āŽĩāŽŠā¯āŽĒā¯ŠāŽ°ā¯āŽŗā¯ āŽŽā¯āŽŸā¯āŽ•ā¯āŽ•āŽŽā¯", - "transcoding_hardware_acceleration_description": "āŽšā¯‹āŽ¤āŽŠā¯ˆ; āŽŽāŽŋāŽ• āŽĩā¯‡āŽ•āŽŽāŽžāŽ•, āŽ†āŽŠāŽžāŽ˛ā¯ āŽ…āŽ¤ā¯‡ āŽĒāŽŋāŽŸā¯āŽ°ā¯‡āŽŸā¯āŽŸāŽŋāŽ˛ā¯ āŽ•ā¯āŽąā¯ˆāŽ¨ā¯āŽ¤ āŽ¤āŽ•ā¯āŽ¤āŽŋ āŽ‡āŽ°ā¯āŽ•ā¯āŽ•ā¯āŽŽā¯", + "transcoding_hardware_acceleration_description": "āŽĒāŽ°āŽŋāŽšā¯‹āŽ¤āŽŠā¯ˆ: āŽĩā¯‡āŽ•āŽŽāŽžāŽŠ āŽŸāŽŋāŽ°āŽžāŽŠā¯āŽ¸ā¯āŽ•ā¯‹āŽŸāŽŋāŽ™ā¯ āŽ†āŽŠāŽžāŽ˛ā¯ āŽ…āŽ¤ā¯‡ āŽĒāŽŋāŽŸā¯āŽ°ā¯‡āŽŸā¯āŽŸāŽŋāŽ˛ā¯ āŽ¤āŽ°āŽ¤ā¯āŽ¤ā¯ˆāŽ•ā¯ āŽ•ā¯āŽąā¯ˆāŽ•ā¯āŽ•āŽ˛āŽžāŽŽā¯", "transcoding_hardware_decoding": "āŽĩāŽŠā¯āŽĒā¯ŠāŽ°ā¯āŽŗā¯ āŽŸāŽŋāŽ•ā¯‹āŽŸāŽŋāŽ™ā¯", "transcoding_hardware_decoding_setting_description": "āŽ•ā¯āŽąāŽŋāŽ¯āŽžāŽ•ā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽĩāŽŋāŽ°ā¯ˆāŽĩ❁āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽĩāŽ¤āŽąā¯āŽ•ā¯ āŽĒāŽ¤āŽŋāŽ˛āŽžāŽ• āŽ‡āŽąā¯āŽ¤āŽŋ āŽŽā¯āŽ¤āŽ˛ā¯ āŽ‡āŽąā¯āŽ¤āŽŋ āŽŽā¯āŽŸā¯āŽ•ā¯āŽ•āŽŽā¯ āŽ†āŽ•āŽŋāŽ¯āŽĩāŽąā¯āŽąā¯ˆ āŽšā¯†āŽ¯āŽ˛ā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽ•āŽŋāŽąāŽ¤ā¯. āŽŽāŽ˛ā¯āŽ˛āŽž āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗāŽŋāŽ˛ā¯āŽŽā¯ āŽĩā¯‡āŽ˛ā¯ˆ āŽšā¯†āŽ¯ā¯āŽ¯āŽ•ā¯āŽ•ā¯‚āŽŸāŽžāŽ¤ā¯.", "transcoding_max_b_frames": "āŽ…āŽ¤āŽŋāŽ•āŽĒāŽŸā¯āŽš āŽĒāŽŋ-āŽĒāŽŋāŽ°ā¯‡āŽŽā¯āŽ•āŽŗā¯", @@ -304,6 +337,8 @@ "transcoding_max_keyframe_interval": "āŽ…āŽ¤āŽŋāŽ•āŽĒāŽŸā¯āŽš āŽ•ā¯€āŽƒāŽĒā¯āŽ°ā¯‡āŽŽā¯ āŽ‡āŽŸā¯ˆāŽĩā¯†āŽŗāŽŋ", "transcoding_max_keyframe_interval_description": "āŽ•ā¯€āŽƒāŽĒā¯āŽ°ā¯‡āŽŽā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽ‡āŽŸā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽ…āŽ¤āŽŋāŽ•āŽĒāŽŸā¯āŽš āŽĒāŽŋāŽ°ā¯‡āŽŽā¯ āŽ¤ā¯‚āŽ°āŽ¤ā¯āŽ¤ā¯ˆ āŽ…āŽŽā¯ˆāŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯. āŽ•ā¯āŽąā¯ˆāŽ¨ā¯āŽ¤ āŽŽāŽ¤āŽŋāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ āŽšā¯āŽ°ā¯āŽ•ā¯āŽ• āŽšā¯†āŽ¯āŽ˛ā¯āŽ¤āŽŋāŽąāŽŠā¯ˆ āŽŽā¯‹āŽšāŽŽāŽžāŽ•ā¯āŽ•ā¯āŽ•āŽŋāŽŠā¯āŽąāŽŠ, āŽ†āŽŠāŽžāŽ˛ā¯ āŽ¤ā¯‡āŽŸāŽ˛ā¯ āŽ¨ā¯‡āŽ°āŽ™ā¯āŽ•āŽŗā¯ˆ āŽŽā¯‡āŽŽā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽ•āŽŋāŽŠā¯āŽąāŽŠ, āŽŽā¯‡āŽ˛ā¯āŽŽā¯ āŽĩā¯‡āŽ•āŽŽāŽžāŽŠ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽ¤ā¯āŽ¤ā¯āŽŸāŽŠā¯ āŽ•āŽžāŽŸā¯āŽšāŽŋāŽ•āŽŗāŽŋāŽ˛ā¯ āŽ¤āŽ°āŽ¤ā¯āŽ¤ā¯ˆ āŽŽā¯‡āŽŽā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽ˛āŽžāŽŽā¯. 0 āŽ‡āŽ¨ā¯āŽ¤ āŽŽāŽ¤āŽŋāŽĒā¯āŽĒ❈ āŽ¤āŽžāŽŠāŽžāŽ• āŽ…āŽŽā¯ˆāŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯.", "transcoding_optimal_description": "āŽ‡āŽ˛āŽ•ā¯āŽ•ā¯ āŽ¤ā¯€āŽ°ā¯āŽŽāŽžāŽŠāŽ¤ā¯āŽ¤ā¯ˆ āŽĩāŽŋāŽŸ āŽ‰āŽ¯āŽ°ā¯āŽ¨ā¯āŽ¤ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽāŽąā¯āŽąā¯āŽ•ā¯āŽ•ā¯ŠāŽŗā¯āŽŗāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽĩāŽŸāŽŋāŽĩāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ", + "transcoding_policy": "āŽ•ā¯āŽąāŽŋāŽŽāŽžāŽąā¯āŽąāŽ•ā¯ āŽ•ā¯ŠāŽŗā¯āŽ•ā¯ˆ", + "transcoding_policy_description": "āŽ’āŽ°ā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹ āŽŽāŽĒā¯āŽĒā¯‹āŽ¤ā¯ āŽ•ā¯āŽąāŽŋāŽŽāŽžāŽąā¯āŽąāŽŽā¯ āŽšā¯†āŽ¯ā¯āŽ¯āŽĒā¯āŽĒāŽŸā¯āŽŽā¯ āŽŽāŽŠā¯āŽĒāŽ¤ā¯ˆ āŽ…āŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "transcoding_preferred_hardware_device": "āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽŽāŽžāŽŠ āŽĩāŽŠā¯āŽĒā¯ŠāŽ°ā¯āŽŗā¯ āŽšāŽžāŽ¤āŽŠāŽŽā¯", "transcoding_preferred_hardware_device_description": "VAAPI āŽŽāŽąā¯āŽąā¯āŽŽā¯ QSV āŽ•ā¯āŽ•ā¯ āŽŽāŽŸā¯āŽŸā¯āŽŽā¯‡ āŽĒā¯ŠāŽ°ā¯āŽ¨ā¯āŽ¤ā¯āŽŽā¯. āŽĩāŽŠā¯āŽĒā¯ŠāŽ°ā¯āŽŗā¯ āŽŸāŽŋāŽ°āŽžāŽŠā¯āŽšā¯āŽ•ā¯‹āŽŸāŽŋāŽ™ā¯āŽ•āŽŋāŽąā¯āŽ•ā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŽā¯ āŽŸā¯āŽ°ā¯ˆ āŽŽā¯āŽŠā¯ˆāŽ¯ā¯ˆ āŽ…āŽŽā¯ˆāŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯.", "transcoding_preset_preset": "āŽŽā¯āŽŠā¯āŽŠāŽŽā¯ˆāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ (-āŽĒāŽŋāŽ°āŽšā¯†āŽŸā¯)", @@ -312,6 +347,7 @@ "transcoding_reference_frames_description": "āŽ•ā¯ŠāŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽšāŽŸā¯āŽŸāŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽšā¯āŽ°ā¯āŽ•ā¯āŽ•ā¯āŽŽā¯āŽĒā¯‹āŽ¤ā¯ āŽ•ā¯āŽąāŽŋāŽĒā¯āŽĒāŽŋāŽŸ āŽĩā¯‡āŽŖā¯āŽŸāŽŋāŽ¯ āŽĒāŽŋāŽ°ā¯‡āŽŽā¯āŽ•āŽŗāŽŋāŽŠā¯ āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ. āŽ…āŽ¤āŽŋāŽ• āŽŽāŽ¤āŽŋāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ āŽšā¯āŽ°ā¯āŽ•ā¯āŽ• āŽšā¯†āŽ¯āŽ˛ā¯āŽ¤āŽŋāŽąāŽŠā¯ˆ āŽŽā¯‡āŽŽā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽ•āŽŋāŽŠā¯āŽąāŽŠ, āŽ†āŽŠāŽžāŽ˛ā¯ āŽ•ā¯āŽąāŽŋāŽ¯āŽžāŽ•ā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽŽā¯†āŽ¤ā¯āŽĩāŽžāŽ•ā¯āŽ•ā¯āŽ•āŽŋāŽŠā¯āŽąāŽŠ. 0 āŽ‡āŽ¨ā¯āŽ¤ āŽŽāŽ¤āŽŋāŽĒā¯āŽĒ❈ āŽ¤āŽžāŽŠāŽžāŽ• āŽ…āŽŽā¯ˆāŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯.", "transcoding_required_description": "āŽāŽąā¯āŽąā¯āŽ•ā¯āŽ•ā¯ŠāŽŗā¯āŽŗāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽĩāŽŸāŽŋāŽĩāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ‡āŽ˛ā¯āŽ˛āŽžāŽ¤ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ āŽŽāŽŸā¯āŽŸā¯āŽŽā¯‡", "transcoding_settings": "āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹ āŽŸāŽŋāŽ°āŽžāŽŠā¯āŽšā¯āŽ•ā¯‹āŽŸāŽŋāŽ™ā¯ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", + "transcoding_settings_description": "āŽŽāŽ¨ā¯āŽ¤ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ˆ āŽŸāŽŋāŽ°āŽžāŽŠā¯āŽ¸ā¯āŽ•ā¯‹āŽŸā¯ āŽšā¯†āŽ¯ā¯āŽ¯ āŽĩā¯‡āŽŖā¯āŽŸā¯āŽŽā¯, āŽ…āŽĩāŽąā¯āŽąā¯ˆ āŽŽāŽĩā¯āŽĩāŽžāŽąā¯ āŽšā¯†āŽ¯āŽ˛āŽžāŽ•ā¯āŽ• āŽĩā¯‡āŽŖā¯āŽŸā¯āŽŽā¯ āŽŽāŽŠā¯āŽĒāŽ¤ā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "transcoding_target_resolution": "āŽ‡āŽ˛āŽ•ā¯āŽ•ā¯ āŽ¤ā¯€āŽ°ā¯āŽŽāŽžāŽŠāŽŽā¯", "transcoding_target_resolution_description": "āŽ…āŽ¤āŽŋāŽ• āŽ¤ā¯€āŽ°ā¯āŽŽāŽžāŽŠāŽ™ā¯āŽ•āŽŗā¯ āŽ…āŽ¤āŽŋāŽ• āŽĩāŽŋāŽĩāŽ°āŽ™ā¯āŽ•āŽŗā¯ˆ āŽĒāŽžāŽ¤ā¯āŽ•āŽžāŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯ā¯āŽŽā¯, āŽ†āŽŠāŽžāŽ˛ā¯ āŽ•ā¯āŽąāŽŋāŽ¯āŽžāŽ•ā¯āŽ• āŽ…āŽ¤āŽŋāŽ• āŽ¨ā¯‡āŽ°āŽŽā¯ āŽŽāŽŸā¯āŽ•ā¯āŽ•ā¯āŽŽā¯, āŽĒā¯†āŽ°āŽŋāŽ¯ āŽ•ā¯‹āŽĒā¯āŽĒ❁ āŽ…āŽŗāŽĩā¯āŽ•āŽŗā¯ˆāŽ•ā¯ āŽ•ā¯ŠāŽŖā¯āŽŸāŽŋāŽ°ā¯āŽ•ā¯āŽ•āŽ˛āŽžāŽŽā¯, āŽŽā¯‡āŽ˛ā¯āŽŽā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯āŽŸā¯ āŽŽāŽąā¯āŽŽā¯ŠāŽ´āŽŋāŽ¯ā¯ˆāŽ•ā¯ āŽ•ā¯āŽąā¯ˆāŽ•ā¯āŽ•āŽ˛āŽžāŽŽā¯.", "transcoding_temporal_aq": "āŽ¤āŽŽā¯āŽĒā¯‹āŽ°ā¯āŽ˛ā¯", @@ -324,23 +360,28 @@ "transcoding_transcode_policy_description": "āŽ’āŽ°ā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹ āŽŽāŽĒā¯āŽĒā¯‹āŽ¤ā¯ āŽŽāŽžāŽąā¯āŽąāŽĒā¯āŽĒāŽŸ āŽĩā¯‡āŽŖā¯āŽŸā¯āŽŽā¯ āŽŽāŽŠā¯āŽĒāŽ¤āŽąā¯āŽ•āŽžāŽŠ āŽ•ā¯ŠāŽŗā¯āŽ•ā¯ˆ. āŽŽāŽšā¯.āŽŸāŽŋ.āŽ†āŽ°ā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ āŽŽāŽĒā¯āŽĒā¯‹āŽ¤ā¯āŽŽā¯ āŽŸāŽŋāŽ°āŽžāŽŠā¯āŽšā¯āŽ•ā¯‹āŽŸā¯ āŽšā¯†āŽ¯ā¯āŽ¯āŽĒā¯āŽĒāŽŸā¯āŽŽā¯ (āŽŸāŽŋāŽ°āŽžāŽŠā¯āŽšā¯āŽ•ā¯‹āŽŸāŽŋāŽ™ā¯ āŽŽā¯āŽŸāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽŋāŽ°ā¯āŽ¨ā¯āŽ¤āŽžāŽ˛ā¯ āŽ¤āŽĩāŽŋāŽ°).", "transcoding_two_pass_encoding": "āŽ‡āŽ°āŽŖā¯āŽŸā¯-āŽĒāŽžāŽšā¯ āŽ•ā¯āŽąāŽŋāŽ¯āŽžāŽ•ā¯āŽ•āŽŽā¯", "transcoding_two_pass_encoding_setting_description": "āŽšāŽŋāŽąāŽ¨ā¯āŽ¤ āŽ•ā¯āŽąāŽŋāŽ¯āŽžāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ• āŽ‡āŽ°āŽŖā¯āŽŸā¯ āŽĒāŽžāŽšā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽŸāŽŋāŽ°āŽžāŽŠā¯āŽšā¯āŽ•ā¯‹āŽŸā¯. āŽŽā¯‡āŽ•ā¯āŽšā¯ āŽĒāŽŋāŽŸā¯āŽ°ā¯‡āŽŸā¯ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽŋāŽ°ā¯āŽ•ā¯āŽ•ā¯āŽŽā¯āŽĒā¯‹āŽ¤ā¯ (H.264 āŽŽāŽąā¯āŽąā¯āŽŽā¯ HEVC āŽ‰āŽŸāŽŠā¯ āŽĩā¯‡āŽ˛ā¯ˆ āŽšā¯†āŽ¯ā¯āŽ¯ āŽ‡āŽ¤ā¯ āŽ¤ā¯‡āŽĩ❈āŽĒā¯āŽĒāŽŸā¯āŽ•āŽŋāŽąāŽ¤ā¯), āŽ‡āŽ¨ā¯āŽ¤ āŽĒāŽ¯āŽŠā¯āŽŽā¯āŽąā¯ˆ āŽ…āŽ¤āŽŋāŽ•āŽĒāŽŸā¯āŽš āŽĒāŽŋāŽŸā¯āŽ°ā¯‡āŽŸā¯āŽŸā¯ˆ āŽ…āŽŸāŽŋāŽĒā¯āŽĒāŽŸā¯ˆāŽ¯āŽžāŽ•āŽ•ā¯ āŽ•ā¯ŠāŽŖā¯āŽŸ āŽĒāŽŋāŽŸā¯āŽ°ā¯‡āŽŸā¯ āŽĩāŽ°āŽŽā¯āŽĒ❈āŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽ•āŽŋāŽąāŽ¤ā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ CRF āŽ āŽĒā¯āŽąāŽ•ā¯āŽ•āŽŖāŽŋāŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯. VP9 āŽāŽĒā¯ āŽĒā¯ŠāŽąā¯āŽ¤ā¯āŽ¤āŽĩāŽ°ā¯ˆ, āŽ…āŽ¤āŽŋāŽ•āŽĒāŽŸā¯āŽš āŽĒāŽŋāŽŸā¯āŽ°ā¯‡āŽŸā¯ āŽŽā¯āŽŸāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽŋāŽ°ā¯āŽ¨ā¯āŽ¤āŽžāŽ˛ā¯ CRF āŽāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽ˛āŽžāŽŽā¯.", + "transcoding_video_codec": "āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹ āŽ•ā¯‹āŽŸā¯†āŽ•ā¯", "transcoding_video_codec_description": "VP9 āŽ…āŽ¤āŽŋāŽ• āŽšā¯†āŽ¯āŽ˛ā¯āŽ¤āŽŋāŽąāŽŠā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĩāŽ˛ā¯ˆ āŽĒā¯ŠāŽ°ā¯āŽ¨ā¯āŽ¤āŽ•ā¯āŽ•ā¯‚āŽŸāŽŋāŽ¯ āŽ¤āŽŠā¯āŽŽā¯ˆāŽ¯ā¯ˆāŽ•ā¯ āŽ•ā¯ŠāŽŖā¯āŽŸā¯āŽŗā¯āŽŗāŽ¤ā¯, āŽ†āŽŠāŽžāŽ˛ā¯ āŽŸāŽŋāŽ°āŽžāŽŠā¯āŽšā¯āŽ•ā¯‹āŽŸāŽŋāŽąā¯āŽ•ā¯ āŽ…āŽ¤āŽŋāŽ• āŽ¨ā¯‡āŽ°āŽŽā¯ āŽŽāŽŸā¯āŽ•ā¯āŽ•ā¯āŽŽā¯. HEVC āŽ‡āŽ¤ā¯‡āŽĒā¯‹āŽ˛ā¯ āŽšā¯†āŽ¯āŽ˛ā¯āŽĒāŽŸā¯āŽ•āŽŋāŽąāŽ¤ā¯, āŽ†āŽŠāŽžāŽ˛ā¯ āŽ•ā¯āŽąā¯ˆāŽ¨ā¯āŽ¤ āŽĩāŽ˛ā¯ˆ āŽĒā¯ŠāŽ°ā¯āŽ¨ā¯āŽ¤āŽ•ā¯āŽ•ā¯‚āŽŸāŽŋāŽ¯ āŽ¤āŽŠā¯āŽŽā¯ˆāŽ¯ā¯ˆāŽ•ā¯ āŽ•ā¯ŠāŽŖā¯āŽŸā¯āŽŗā¯āŽŗāŽ¤ā¯. H.264 āŽĒāŽ°āŽĩāŽ˛āŽžāŽ• āŽ‡āŽŖāŽ•ā¯āŽ•āŽŽāŽžāŽŠāŽ¤ā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽŸāŽŋāŽ°āŽžāŽŠā¯āŽšā¯āŽ•ā¯‹āŽŸā¯ āŽĩāŽŋāŽ°ā¯ˆāŽĩāŽžāŽŠāŽ¤ā¯, āŽ†āŽŠāŽžāŽ˛ā¯ āŽŽāŽŋāŽ•āŽĒā¯ āŽĒā¯†āŽ°āŽŋāŽ¯ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯. āŽ.āŽĩāŽŋ 1 āŽŽāŽŋāŽ•āŽĩā¯āŽŽā¯ āŽ¤āŽŋāŽąāŽŽā¯ˆāŽ¯āŽžāŽŠ āŽ•ā¯‹āŽŸā¯†āŽ•ā¯ āŽ†āŽŠāŽžāŽ˛ā¯ āŽĒāŽ´ā¯ˆāŽ¯ āŽšāŽžāŽ¤āŽŠāŽ™ā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽ‰āŽ¤āŽĩāŽŋ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ.", "trash_enabled_description": "āŽ•ā¯āŽĒā¯āŽĒ❈ āŽ…āŽŽā¯āŽšāŽ™ā¯āŽ•āŽŗā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "trash_number_of_days": "āŽ¨āŽžāŽŸā¯āŽ•āŽŗāŽŋāŽŠā¯ āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ", "trash_number_of_days_description": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ…āŽ•āŽąā¯āŽąā¯āŽĩāŽ¤āŽąā¯āŽ•ā¯ āŽŽā¯āŽŠā¯ āŽ•ā¯āŽĒā¯āŽĒā¯ˆāŽ¤ā¯āŽ¤ā¯ŠāŽŸā¯āŽŸāŽŋāŽ¯āŽŋāŽ˛ā¯ āŽĩā¯ˆāŽ¤ā¯āŽ¤āŽŋāŽ°ā¯āŽ•ā¯āŽ• āŽ¨āŽžāŽŸā¯āŽ•āŽŗā¯ āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ", "trash_settings": "āŽ•ā¯āŽĒā¯āŽĒ❈ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", "trash_settings_description": "āŽ•ā¯āŽĒā¯āŽĒ❈ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "unlink_all_oauth_accounts": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ OAuth āŽ•āŽŖāŽ•ā¯āŽ•ā¯āŽ•āŽŗāŽŋāŽŠā¯ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯", + "unlink_all_oauth_accounts_description": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽĩāŽ´āŽ™ā¯āŽ•ā¯āŽ¨āŽ°ā¯āŽ•ā¯āŽ•ā¯ āŽŽāŽžāŽąā¯āŽĩāŽ¤āŽąā¯āŽ•ā¯ āŽŽā¯āŽŠā¯, āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ OAuth āŽ•āŽŖāŽ•ā¯āŽ•ā¯āŽ•āŽŗāŽŋāŽŠā¯ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¨ā¯€āŽ•ā¯āŽ• āŽ¨āŽŋāŽŠā¯ˆāŽĩāŽŋāŽ˛ā¯ āŽ•ā¯ŠāŽŗā¯āŽŗā¯āŽ™ā¯āŽ•āŽŗā¯.", + "unlink_all_oauth_accounts_prompt": "āŽŽāŽ˛ā¯āŽ˛āŽž OAuth āŽ•āŽŖāŽ•ā¯āŽ•ā¯āŽ•āŽŗāŽŋāŽŠā¯ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¨ā¯€āŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž? āŽ‡āŽ¤ā¯ āŽ’āŽĩā¯āŽĩā¯ŠāŽ°ā¯ āŽĒāŽ¯āŽŠāŽ°ā¯āŽ•ā¯āŽ•ā¯āŽŽā¯ OAuth āŽāŽŸāŽŋāŽ¯ā¯ˆ āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆāŽ•ā¯āŽ•ā¯āŽŽā¯, āŽŽā¯‡āŽ˛ā¯āŽŽā¯ āŽ‡āŽ¤ā¯ˆ āŽ¤āŽŋāŽ°ā¯āŽŽā¯āŽĒāŽĒā¯ āŽĒā¯†āŽąā¯ āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯.", "user_cleanup_job": "āŽĒāŽ¯āŽŠāŽ°ā¯ āŽ¤ā¯‚āŽ¯ā¯āŽŽā¯ˆāŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽ¤āŽ˛ā¯", - "user_delete_delay": " {user} āŽ‡āŽŠā¯ āŽ•āŽŖāŽ•ā¯āŽ•ā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ {āŽ¤āŽžāŽŽāŽ¤āŽŽā¯, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽ¨āŽžāŽŗā¯} āŽŽāŽąā¯āŽą {# āŽ¨āŽžāŽŸā¯āŽ•āŽŗā¯}} āŽ‡āŽ˛ā¯ āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ° āŽ¨ā¯€āŽ•ā¯āŽ• āŽ¤āŽŋāŽŸā¯āŽŸāŽŽāŽŋāŽŸāŽĒā¯āŽĒāŽŸā¯āŽŽā¯.", + "user_delete_delay": "{user}āŽ‡āŽŠā¯ āŽ•āŽŖāŽ•ā¯āŽ•ā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ {delay, plural, one {# āŽ¨āŽžāŽŗā¯} other {# āŽ¨āŽžāŽŗā¯āŽ•āŽŗā¯}}āŽ‡āŽ˛ā¯ āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ° āŽ¨ā¯€āŽ•ā¯āŽ•āŽ¤ā¯ āŽ¤āŽŋāŽŸā¯āŽŸāŽŽāŽŋāŽŸāŽĒā¯āŽĒāŽŸā¯āŽŽā¯.", "user_delete_delay_settings": "āŽ¤āŽžāŽŽāŽ¤āŽ¤ā¯āŽ¤ā¯ˆ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯", "user_delete_delay_settings_description": "āŽŽāŽŖā¯ of days after āŽ¨ā¯€āŽ•ā¯āŽ•ā¯āŽŽā¯ āŽĒā¯†āŽąā¯āŽ¨āŽ°ā¯ permanently āŽ¨ā¯€āŽ•ā¯āŽ•ā¯ a user's account and assets. āŽ¨ā¯€āŽ•ā¯āŽ•ā¯āŽĩāŽ¤āŽąā¯āŽ•ā¯ āŽ¤āŽ¯āŽžāŽ°āŽžāŽ• āŽ‡āŽ°ā¯āŽ•ā¯āŽ•ā¯āŽŽā¯ āŽĒāŽ¯āŽŠāŽ°ā¯āŽ•āŽŗā¯ˆāŽšā¯ āŽšāŽ°āŽŋāŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ• āŽĒāŽ¯āŽŠāŽ°ā¯ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯āŽ¤āŽ˛ā¯ āŽĩā¯‡āŽ˛ā¯ˆ āŽ¨āŽŗā¯āŽŗāŽŋāŽ°āŽĩāŽŋāŽ˛ā¯ āŽ‡āŽ¯āŽ™ā¯āŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯. āŽ‡āŽ¨ā¯āŽ¤ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒāŽŋāŽ˛ā¯ āŽŽāŽžāŽąā¯āŽąāŽ™ā¯āŽ•āŽŗā¯ āŽ…āŽŸā¯āŽ¤ā¯āŽ¤ āŽŽāŽ°āŽŖāŽ¤āŽŖā¯āŽŸāŽŠā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽŽāŽ¤āŽŋāŽĒā¯āŽĒā¯€āŽŸā¯ āŽšā¯†āŽ¯ā¯āŽ¯āŽĒā¯āŽĒāŽŸā¯āŽŽā¯.", "user_delete_immediately": " {user} āŽ‡āŽŠā¯ āŽ•āŽŖāŽ•ā¯āŽ•ā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ° āŽ¨ā¯€āŽ•ā¯āŽ•ā¯āŽ¤āŽ˛ā¯āŽ•ā¯āŽ•āŽžāŽ• āŽĩāŽ°āŽŋāŽšā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽ¨āŽŋāŽąā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŽā¯ āŽ‰āŽŸāŽŠāŽŸāŽŋāŽ¯āŽžāŽ• .", "user_delete_immediately_checkbox": "āŽ‰āŽŸāŽŠāŽŸāŽŋāŽ¯āŽžāŽ• āŽ¨ā¯€āŽ•ā¯āŽ• āŽĒāŽ¯āŽŠāŽ°ā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯", + "user_details": "āŽĒāŽ¯āŽŠāŽ°ā¯ āŽĩāŽŋāŽĩāŽ°āŽ™ā¯āŽ•āŽŗā¯", "user_management": "āŽĒāŽ¯āŽŠāŽ°ā¯ āŽŽā¯‡āŽ˛āŽžāŽŖā¯āŽŽā¯ˆ", "user_password_has_been_reset": "āŽĒāŽ¯āŽŠāŽ°āŽŋāŽŠā¯ āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯ āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗāŽ¤ā¯:", "user_password_reset_description": "āŽ¤āŽ¯āŽĩā¯āŽšā¯†āŽ¯ā¯āŽ¤ā¯ āŽ¤āŽąā¯āŽ•āŽžāŽ˛āŽŋāŽ• āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽĒāŽ¯āŽŠāŽ°ā¯āŽ•ā¯āŽ•ā¯ āŽĩāŽ´āŽ™ā¯āŽ•āŽĩā¯āŽŽā¯, āŽ…āŽĩāŽ°ā¯āŽ•āŽŗāŽŋāŽŠā¯ āŽ…āŽŸā¯āŽ¤ā¯āŽ¤ āŽ‰āŽŗā¯āŽ¨ā¯āŽ´ā¯ˆāŽĩāŽŋāŽ˛ā¯ āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽŽāŽžāŽąā¯āŽą āŽĩā¯‡āŽŖā¯āŽŸā¯āŽŽā¯ āŽŽāŽŠā¯āŽąā¯ āŽ…āŽĩāŽ°ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯āŽ¤ā¯ āŽ¤ā¯†āŽ°āŽŋāŽĩāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯.", "user_restore_description": " {user} āŽ‡āŽŠā¯ āŽ•āŽŖāŽ•ā¯āŽ•ā¯ āŽŽā¯€āŽŸā¯āŽŸā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŽā¯.", - "user_restore_scheduled_removal": "āŽĒāŽ¯āŽŠāŽ°ā¯ˆ āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆ - {āŽ¤ā¯‡āŽ¤āŽŋ, āŽ¤ā¯‡āŽ¤āŽŋ, āŽ¨ā¯€āŽŖā¯āŽŸ} āŽ‡āŽ˛ā¯ āŽ¤āŽŋāŽŸā¯āŽŸāŽŽāŽŋāŽŸāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯āŽ¤āŽ˛ā¯", + "user_restore_scheduled_removal": "āŽĒāŽ¯āŽŠāŽ°ā¯ˆ āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆ - {date, date, long} āŽ‡āŽ˛ā¯ āŽ¤āŽŋāŽŸā¯āŽŸāŽŽāŽŋāŽŸāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯āŽ¤āŽ˛ā¯", "user_settings": "āŽĒāŽ¯āŽŠāŽ°ā¯ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", "user_settings_description": "āŽĒāŽ¯āŽŠāŽ°ā¯ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "user_successfully_removed": "āŽĒāŽ¯āŽŠāŽ°ā¯ {email} āŽĩā¯†āŽąā¯āŽąāŽŋāŽ•āŽ°āŽŽāŽžāŽ• āŽ…āŽ•āŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯.", @@ -355,29 +396,62 @@ "admin_password": "āŽ¨āŽŋāŽ°ā¯āŽĩāŽžāŽ•āŽŋ āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯", "administration": "āŽ¨āŽŋāŽ°ā¯āŽĩāŽžāŽ•āŽŽā¯", "advanced": "āŽŽā¯‡āŽŽā¯āŽĒāŽŸā¯āŽŸ", - "age_months": "āŽ…āŽ•āŽĩ❈ {āŽŽāŽžāŽ¤āŽ™ā¯āŽ•āŽŗā¯, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽŽāŽžāŽ¤āŽŽā¯} āŽŽāŽąā¯āŽą {# āŽŽāŽžāŽ¤āŽ™ā¯āŽ•āŽŗā¯}}", - "age_year_months": "āŽ…āŽ•āŽĩ❈ 1 āŽ…āŽ•āŽĩ❈, {āŽŽāŽžāŽ¤āŽ™ā¯āŽ•āŽŗā¯, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽŽāŽžāŽ¤āŽŽā¯} āŽŽāŽąā¯āŽą {# āŽŽāŽžāŽ¤āŽ™ā¯āŽ•āŽŗā¯}}", - "age_years": "{āŽ†āŽŖā¯āŽŸā¯āŽ•āŽŗā¯, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽĒāŽŋāŽą {āŽĩāŽ¯āŽ¤ā¯ #}}", + "advanced_settings_enable_alternate_media_filter_subtitle": "āŽŽāŽžāŽąā¯āŽąā¯ āŽ…āŽŗāŽĩā¯āŽ•ā¯‹āŽ˛ā¯āŽ•āŽŗāŽŋāŽŠā¯ āŽ…āŽŸāŽŋāŽĒā¯āŽĒāŽŸā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽ’āŽ¤ā¯āŽ¤āŽŋāŽšā¯ˆāŽĩāŽŋāŽŠā¯ āŽĒā¯‹āŽ¤ā¯ āŽŽā¯€āŽŸāŽŋāŽ¯āŽžāŽĩ❈ āŽĩāŽŸāŽŋāŽ•āŽŸā¯āŽŸ āŽ‡āŽ¨ā¯āŽ¤ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ¤ā¯āŽ¤ā¯ˆāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯. āŽŽāŽ˛ā¯āŽ˛āŽž āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽ†āŽĒā¯āŽ¸ā¯ āŽ•āŽŖā¯āŽŸāŽąāŽŋāŽĩāŽ¤āŽŋāŽ˛ā¯ āŽšāŽŋāŽ•ā¯āŽ•āŽ˛ā¯āŽ•āŽŗā¯ āŽ‡āŽ°ā¯āŽ¨ā¯āŽ¤āŽžāŽ˛ā¯ āŽŽāŽŸā¯āŽŸā¯āŽŽā¯‡ āŽ‡āŽ¤ā¯ˆ āŽŽā¯āŽ¯āŽąā¯āŽšāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯.", + "advanced_settings_enable_alternate_media_filter_title": "[āŽĒāŽ°āŽŋāŽšā¯‹āŽ¤āŽŠā¯ˆāŽ•ā¯āŽ•ā¯ āŽ‰āŽŸā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯] āŽŽāŽžāŽąā¯āŽąā¯ āŽšāŽžāŽ¤āŽŠ āŽ†āŽ˛ā¯āŽĒ āŽ’āŽ¤ā¯āŽ¤āŽŋāŽšā¯ˆāŽĩ❁ āŽĩāŽŸāŽŋāŽĒā¯āŽĒāŽžāŽŠā¯ˆāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", + "advanced_settings_log_level_title": "āŽĒāŽ¤āŽŋāŽĩ❁ āŽ¨āŽŋāŽ˛ā¯ˆ: {level}", + "advanced_settings_prefer_remote_subtitle": "āŽšāŽŋāŽ˛ āŽšāŽžāŽ¤āŽŠāŽ™ā¯āŽ•āŽŗā¯ āŽ‰āŽŗā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗāŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽšāŽŋāŽąā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆ āŽāŽąā¯āŽąā¯āŽĩāŽ¤āŽŋāŽ˛ā¯ āŽŽāŽŋāŽ•āŽĩā¯āŽŽā¯ āŽŽā¯†āŽ¤ā¯āŽĩāŽžāŽ• āŽ‡āŽ°ā¯āŽ•ā¯āŽ•ā¯āŽŽā¯. āŽ…āŽ¤āŽąā¯āŽ•ā¯ āŽĒāŽ¤āŽŋāŽ˛āŽžāŽ• āŽšāŽ°ā¯āŽĩāŽ°ā¯ āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆ āŽāŽąā¯āŽą āŽ‡āŽ¨ā¯āŽ¤ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯ˆāŽšā¯ āŽšā¯†āŽ¯āŽ˛ā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯.", + "advanced_settings_prefer_remote_title": "āŽ°āŽŋāŽŽā¯‹āŽŸā¯ āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽŽā¯āŽŠā¯āŽŠā¯āŽ°āŽŋāŽŽā¯ˆ āŽ•ā¯ŠāŽŸā¯", + "advanced_settings_proxy_headers_subtitle": "āŽ’āŽĩā¯āŽĩā¯ŠāŽ°ā¯ āŽ¨ā¯†āŽŸā¯āŽĩā¯ŠāŽ°ā¯āŽ•ā¯ āŽ•ā¯‹āŽ°āŽŋāŽ•ā¯āŽ•ā¯ˆāŽ¯ā¯āŽŸāŽŠā¯āŽŽā¯ āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯ āŽ…āŽŠā¯āŽĒā¯āŽĒ āŽĩā¯‡āŽŖā¯āŽŸāŽŋāŽ¯ āŽĒā¯āŽ°āŽžāŽ•ā¯āŽ¸āŽŋ āŽ¤āŽ˛ā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽĩāŽ°ā¯ˆāŽ¯āŽąā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "advanced_settings_proxy_headers_title": "āŽĒā¯āŽ°āŽžāŽ•ā¯āŽ¸āŽŋ āŽ¤āŽ˛ā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", + "advanced_settings_readonly_mode_subtitle": "āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆ āŽĒāŽžāŽ°ā¯āŽĒā¯āŽĒāŽ¤āŽąā¯āŽ•ā¯ āŽŽāŽŸā¯āŽŸā¯āŽŽā¯‡ āŽ…āŽŠā¯āŽŽāŽ¤āŽŋāŽ•ā¯āŽ•ā¯āŽŽā¯ āŽĒāŽŸāŽŋāŽĒā¯āŽĒāŽ¤āŽąā¯āŽ•ā¯ āŽŽāŽŸā¯āŽŸā¯āŽŽā¯ āŽĒāŽ¯āŽŠā¯āŽŽā¯āŽąā¯ˆāŽ¯ā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯, āŽĒāŽ˛ āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽĒā¯āŽĒāŽ¤ā¯, āŽĒāŽ•āŽŋāŽ°ā¯āŽ¤āŽ˛ā¯, āŽ…āŽŠā¯āŽĒā¯āŽĒā¯āŽ¤āŽ˛ā¯, āŽ¨ā¯€āŽ•ā¯āŽ•ā¯āŽ¤āŽ˛ā¯ āŽĒā¯‹āŽŠā¯āŽą āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯āŽŽā¯ āŽŽā¯āŽŸāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗāŽŠ. āŽĒāŽŋāŽ°āŽ¤āŽžāŽŠ āŽ¤āŽŋāŽ°ā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽ‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽĒāŽ¯āŽŠāŽ°ā¯ āŽ…āŽĩāŽ¤āŽžāŽ°ā¯ āŽĩāŽ´āŽŋāŽ¯āŽžāŽ• āŽĒāŽŸāŽŋāŽ•ā¯āŽ• āŽŽāŽŸā¯āŽŸā¯āŽŽā¯ āŽŽāŽŠā¯āŽĒāŽ¤ā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ•ā¯/āŽŽā¯āŽŸāŽ•ā¯āŽ•ā¯", + "advanced_settings_readonly_mode_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": "āŽšāŽ°āŽŋāŽšā¯†āŽ¯ā¯āŽ¤āŽ˛ā¯", + "age_months": "āŽ…āŽ•āŽĩ❈ {months, plural, one {# āŽ¤āŽŋāŽ™ā¯āŽ•āŽŗā¯} other {# āŽ¤āŽŋāŽ™ā¯āŽ•āŽŗā¯āŽ•āŽŗā¯}}", + "age_year_months": "āŽ…āŽ•āŽĩ❈ 1 āŽ†āŽŖā¯āŽŸā¯, {months, plural, one {# āŽ¤āŽŋāŽ™ā¯āŽ•āŽŗā¯} other {# āŽ¤āŽŋāŽ™ā¯āŽ•āŽŗā¯āŽ•āŽŗā¯}}", + "age_years": "{years, plural, other {āŽ…āŽ•āŽĩ❈ #}}", "album_added": "āŽ†āŽ˛ā¯āŽĒāŽŽā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "album_added_notification_setting_description": "āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŽā¯āŽĒā¯‹āŽ¤ā¯ āŽŽāŽŋāŽŠā¯āŽŠāŽžā¯āŽšāŽ˛ā¯ āŽ…āŽąāŽŋāŽĩāŽŋāŽĒā¯āŽĒ❈āŽĒā¯ āŽĒā¯†āŽąā¯āŽ™ā¯āŽ•āŽŗā¯", "album_cover_updated": "āŽ†āŽ˛ā¯āŽĒāŽŽā¯ āŽ•āŽĩāŽ°ā¯ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "album_delete_confirmation": "{album} āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤ā¯ˆ āŽ¨ā¯€āŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", "album_delete_confirmation_description": "āŽ‡āŽ¨ā¯āŽ¤ āŽ†āŽ˛ā¯āŽĒāŽŽā¯ āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸāŽžāŽ˛ā¯, āŽŽāŽąā¯āŽą āŽĒāŽ¯āŽŠāŽ°ā¯āŽ•āŽŗāŽžāŽ˛ā¯ āŽ‡āŽ¤ā¯ˆ āŽ…āŽŖā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯.", + "album_deleted": "āŽ†āŽ˛ā¯āŽĒāŽŽā¯ āŽ¨ā¯€āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "album_info_card_backup_album_excluded": "āŽĩāŽŋāŽ˛āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "album_info_card_backup_album_included": "āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗāŽ¤ā¯", "album_info_updated": "āŽ†āŽ˛ā¯āŽĒāŽŽā¯ āŽšā¯†āŽ¯ā¯āŽ¤āŽŋ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "album_leave": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤ā¯ˆ āŽĩāŽŋāŽŸā¯āŽ™ā¯āŽ•āŽŗā¯?", - "album_leave_confirmation": "āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽ¨āŽŋāŽšā¯āŽšāŽ¯āŽŽāŽžāŽ• {āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤ā¯ˆ āŽĩāŽŋāŽŸā¯āŽŸā¯ āŽĩā¯†āŽŗāŽŋāŽ¯ā¯‡āŽą āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", + "album_leave_confirmation": "āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽ¨āŽŋāŽšā¯āŽšāŽ¯āŽŽāŽžāŽ• {album}āŽ āŽĩāŽŋāŽŸā¯āŽŸā¯ āŽĩā¯†āŽŗāŽŋāŽ¯ā¯‡āŽą āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", "album_name": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽŠā¯ āŽĒā¯†āŽ¯āŽ°ā¯", "album_options": "āŽ†āŽ˛ā¯āŽĒāŽŽā¯ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯", "album_remove_user": "āŽĒāŽ¯āŽŠāŽ°ā¯ˆ āŽ…āŽ•āŽąā¯āŽąāŽĩāŽž?", "album_remove_user_confirmation": "{user} āŽ āŽ…āŽ•āŽąā¯āŽą āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", + "album_search_not_found": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ¤ā¯‡āŽŸāŽ˛ā¯āŽŸāŽŠā¯ āŽĒā¯ŠāŽ°ā¯āŽ¨ā¯āŽ¤āŽ•ā¯āŽ•ā¯‚āŽŸāŽŋāŽ¯ āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽ¤ā¯āŽĩā¯āŽŽā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ", "album_share_no_users": "āŽ‡āŽ¨ā¯āŽ¤ āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤ā¯ˆ āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽ˛ā¯āŽ˛āŽž āŽĒāŽ¯āŽŠāŽ°ā¯āŽ•āŽŗā¯āŽŸāŽŠā¯āŽŽā¯ āŽĒāŽ•āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ•ā¯ŠāŽŖā¯āŽŸāŽ¤āŽžāŽ•āŽ¤ā¯ āŽ¤ā¯†āŽ°āŽŋāŽ•āŽŋāŽąāŽ¤ā¯ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽĒāŽ•āŽŋāŽ°ā¯āŽĩāŽ¤āŽąā¯āŽ•ā¯ āŽ‰āŽ™ā¯āŽ•āŽŗāŽŋāŽŸāŽŽā¯ āŽŽāŽ¨ā¯āŽ¤ āŽĒāŽ¯āŽŠāŽ°ā¯āŽŽā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ.", + "album_summary": "āŽ†āŽ˛ā¯āŽĒāŽŽā¯ āŽšā¯āŽ°ā¯āŽ•ā¯āŽ•āŽŽā¯", "album_updated": "āŽ†āŽ˛ā¯āŽĒāŽŽā¯ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "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_title": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽŠā¯ āŽ¤āŽ˛ā¯ˆāŽĒā¯āŽĒ❈ āŽŽāŽžāŽąā¯āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", + "album_viewer_appbar_share_leave": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤ā¯ˆ āŽĩāŽŋāŽŸā¯āŽŸā¯ āŽĩā¯†āŽŗāŽŋāŽ¯ā¯‡āŽąā¯", + "album_viewer_appbar_share_to": "āŽĒāŽ•āŽŋāŽ°ā¯", + "album_viewer_page_share_add_users": "āŽĒāŽ¯āŽŠāŽ°ā¯āŽ•āŽŗā¯ˆāŽšā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "album_with_link_access": "āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❁ āŽ‰āŽŗā¯āŽŗ āŽŽāŽĩāŽ°ā¯āŽŽā¯ āŽ‡āŽ¨ā¯āŽ¤ āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¨āŽĒāŽ°ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽŸā¯āŽŸā¯āŽŽā¯.", "albums": "āŽ†āŽ˛ā¯āŽĒāŽŽā¯", - "albums_count": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽŽāŽŖā¯} āŽ†āŽ˛ā¯āŽĒāŽŽā¯} āŽĒāŽŋāŽą {{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽŽāŽŖā¯} āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯}}", + "albums_count": "{count, plural, one {{count, number} āŽ¤ā¯ŠāŽ•ā¯āŽĒā¯āŽĒ❁} other {{count, number} āŽ¤ā¯ŠāŽ•ā¯āŽĒā¯āŽĒā¯āŽ•āŽŗā¯}}", + "albums_default_sort_order": "āŽ‡āŽ¯āŽ˛ā¯āŽĒā¯āŽ¨āŽŋāŽ˛ā¯ˆ āŽ†āŽ˛ā¯āŽĒāŽŽā¯ āŽĩāŽ°āŽŋāŽšā¯ˆāŽ¯āŽžāŽ•ā¯āŽ•āŽŽā¯", + "albums_default_sort_order_description": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•ā¯āŽŽā¯āŽĒā¯‹āŽ¤ā¯ āŽ†āŽ°āŽŽā¯āŽĒ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ āŽĩāŽ°āŽŋāŽšā¯ˆāŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽ˛ā¯ āŽĩāŽ°āŽŋāŽšā¯ˆ.", + "albums_feature_description": "āŽĒāŽŋāŽą āŽĒāŽ¯āŽŠāŽ°ā¯āŽ•āŽŗā¯āŽŸāŽŠā¯ āŽĒāŽ•āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ•ā¯ŠāŽŗā¯āŽŗāŽ•ā¯āŽ•ā¯‚āŽŸāŽŋāŽ¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗāŽŋāŽŠā¯ āŽ¤ā¯ŠāŽ•ā¯āŽĒā¯āŽĒā¯āŽ•āŽŗā¯.", + "albums_on_device_count": "āŽšāŽžāŽ¤āŽŠāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯ ({count})", "all": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯āŽŽā¯", "all_albums": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯āŽŽā¯", "all_people": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ āŽŽāŽ•ā¯āŽ•āŽŗā¯āŽŽā¯", @@ -386,82 +460,236 @@ "allow_edits": "āŽ¤āŽŋāŽ°ā¯āŽ¤ā¯āŽ¤āŽ™ā¯āŽ•āŽŗā¯ˆ āŽ…āŽŠā¯āŽŽāŽ¤āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "allow_public_user_to_download": "āŽĒā¯ŠāŽ¤ā¯ āŽĒāŽ¯āŽŠāŽ°ā¯ˆ āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•āŽŽā¯ āŽšā¯†āŽ¯ā¯āŽ¯ āŽ…āŽŠā¯āŽŽāŽ¤āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "allow_public_user_to_upload": "āŽĒā¯ŠāŽ¤ā¯ āŽĒāŽ¯āŽŠāŽ°ā¯ˆ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽą āŽ…āŽŠā¯āŽŽāŽ¤āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "alt_text_qr_code": "QR āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯ āŽĒāŽŸāŽŽā¯", "anti_clockwise": "āŽ•āŽŸāŽŋāŽ•āŽžāŽ° āŽŽāŽ¤āŽŋāŽ°ā¯āŽĒā¯āŽĒ❁", "api_key": "āŽĒāŽ¨āŽŋāŽ‡ āŽĩāŽŋāŽšā¯ˆ", "api_key_description": "āŽ‡āŽ¨ā¯āŽ¤ āŽŽāŽ¤āŽŋāŽĒā¯āŽĒ❁ āŽ’āŽ°ā¯ āŽŽā¯āŽąā¯ˆ āŽŽāŽŸā¯āŽŸā¯āŽŽā¯‡ āŽ•āŽžāŽŖā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŽā¯. āŽšāŽžāŽŗāŽ°āŽ¤ā¯āŽ¤ā¯ˆ āŽŽā¯‚āŽŸā¯āŽĩāŽ¤āŽąā¯āŽ•ā¯ āŽŽā¯āŽŠā¯ āŽ…āŽ¤ā¯ˆ āŽ¨āŽ•āŽ˛ā¯†āŽŸā¯āŽ•ā¯āŽ• āŽŽāŽąāŽ•ā¯āŽ•āŽžāŽ¤ā¯€āŽ°ā¯āŽ•āŽŗā¯.", "api_key_empty": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽĒāŽ¨āŽŋāŽ‡ āŽĩāŽŋāŽšā¯ˆ āŽĒā¯†āŽ¯āŽ°ā¯ āŽ•āŽžāŽ˛āŽŋāŽ¯āŽžāŽ• āŽ‡āŽ°ā¯āŽ•ā¯āŽ•āŽ•ā¯āŽ•ā¯‚āŽŸāŽžāŽ¤ā¯", "api_keys": "āŽĒāŽ¨āŽŋāŽ‡ āŽĩāŽŋāŽšā¯ˆāŽ•āŽŗā¯", + "app_bar_signout_dialog_content": "āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽ¨āŽŋāŽšā¯āŽšāŽ¯āŽŽāŽžāŽ• āŽĩā¯†āŽŗāŽŋāŽ¯ā¯‡āŽą āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", + "app_bar_signout_dialog_ok": "āŽ†āŽŽā¯", + "app_bar_signout_dialog_title": "āŽĩā¯†āŽŗāŽŋāŽ¯ā¯‡āŽąā¯", "app_settings": "āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯āŽŸā¯ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", "appears_in": "āŽ¤ā¯‹āŽŠā¯āŽąā¯āŽŽā¯", + "apply_count": "āŽĒā¯‹āŽŸā¯ ({count, number})", "archive": "āŽ•āŽžāŽĒā¯āŽĒāŽ•āŽŽā¯", + "archive_action_prompt": "{count} āŽ•āŽžāŽĒā¯āŽĒāŽ•āŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "archive_or_unarchive_photo": "āŽ•āŽžāŽĒā¯āŽĒāŽ•āŽŽā¯ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽšā¯†āŽ¯āŽ˛āŽąā¯āŽą āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽŽā¯", + "archive_page_no_archived_assets": "āŽ•āŽžāŽĒā¯āŽĒāŽ•āŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ āŽŽāŽ¤ā¯āŽĩā¯āŽŽā¯ āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", + "archive_page_title": "āŽ•āŽžāŽĒā¯āŽĒāŽ•āŽŽā¯ ({count})", "archive_size": "āŽ•āŽžāŽĒā¯āŽĒāŽ• āŽ…āŽŗāŽĩ❁", "archive_size_description": "āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•āŽ™ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•āŽžāŽŠ āŽ•āŽžāŽĒā¯āŽĒāŽ• āŽ…āŽŗāŽĩ❈ āŽ‰āŽŗā¯āŽŗāŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯ (āŽ•āŽŋāŽĒāŽŋāŽ˛ā¯)", - "archived_count": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽĒāŽŋāŽą {āŽ•āŽžāŽĒā¯āŽĒāŽ•āŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŸ #}}", + "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_added_to_album": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", - "asset_adding_to_album": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯ ...", + "asset_adding_to_album": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯â€Ļ", "asset_description_updated": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ āŽĩāŽŋāŽŗāŽ•ā¯āŽ•āŽŽā¯ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗāŽ¤ā¯", "asset_filename_is_offline": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ {filename} āŽ†āŽƒāŽĒā¯āŽ˛ā¯ˆāŽŠāŽŋāŽ˛ā¯ āŽ‰āŽŗā¯āŽŗāŽ¤ā¯", "asset_has_unassigned_faces": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ āŽ’āŽ¤ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸāŽžāŽ¤ āŽŽā¯āŽ•āŽ™ā¯āŽ•āŽŗā¯ˆāŽ•ā¯ āŽ•ā¯ŠāŽŖā¯āŽŸā¯āŽŗā¯āŽŗāŽ¤ā¯", - "asset_hashing": "āŽāŽšāŽŋāŽ™ā¯ ...", + "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_month_day": "āŽŽāŽžāŽ¤āŽŽā¯ + āŽ¨āŽžāŽŗā¯", + "asset_list_layout_sub_title": "āŽŽāŽŠā¯ˆāŽ¯āŽŽā¯ˆāŽĩ❁", + "asset_list_settings_subtitle": "āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸ āŽ•āŽŸā¯āŽŸāŽŽā¯ āŽ¤āŽŗāŽĩāŽŽā¯ˆāŽĒā¯āŽĒ❁ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", + "asset_list_settings_title": "āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸ āŽ•āŽŸā¯āŽŸāŽŽā¯", "asset_offline": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ āŽ†āŽƒāŽĒā¯āŽ˛ā¯ˆāŽŠāŽŋāŽ˛ā¯", "asset_offline_description": "āŽ‡āŽ¨ā¯āŽ¤ āŽĩā¯†āŽŗāŽŋāŽĒā¯āŽĒā¯āŽą āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ āŽ‡āŽŠāŽŋ āŽĩāŽŸā¯āŽŸāŽŋāŽ˛ā¯ āŽ•āŽžāŽŖāŽĒā¯āŽĒāŽŸāŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ. āŽ‰āŽ¤āŽĩāŽŋāŽ•ā¯āŽ•ā¯ āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯ āŽ¨āŽŋāŽ°ā¯āŽĩāŽžāŽ•āŽŋāŽ¯ā¯ˆ āŽ¤ā¯ŠāŽŸāŽ°ā¯āŽĒ❁ āŽ•ā¯ŠāŽŗā¯āŽŗāŽĩā¯āŽŽā¯.", + "asset_restored_successfully": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ āŽĩā¯†āŽąā¯āŽąāŽŋāŽ•āŽ°āŽŽāŽžāŽ• āŽŽā¯€āŽŸā¯āŽŸā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "asset_skipped": "āŽ¤āŽĩāŽŋāŽ°ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "asset_skipped_in_trash": "āŽ•ā¯āŽĒā¯āŽĒā¯ˆāŽ¯āŽŋāŽ˛ā¯", + "asset_trashed": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ āŽ•ā¯āŽĒā¯āŽĒ❈", + "asset_troubleshoot": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ āŽšāŽ°āŽŋāŽšā¯†āŽ¯ā¯āŽ¤āŽ˛ā¯", "asset_uploaded": "āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", - "asset_uploading": "āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąā¯āŽ¤āŽ˛ā¯ ...", + "asset_uploading": "āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąā¯āŽ¤āŽ˛ā¯â€Ļ", + "asset_viewer_settings_subtitle": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ•ā¯‡āŽ˛āŽ°āŽŋ āŽĒāŽžāŽ°ā¯āŽĩā¯ˆāŽ¯āŽžāŽŗāŽ°ā¯ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "asset_viewer_settings_title": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ āŽĒāŽžāŽ°ā¯āŽĩā¯ˆāŽ¯āŽžāŽŗāŽ°ā¯", "assets": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯", - "assets_added_count": "āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯ {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} āŽŽāŽąā¯āŽą {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}}", - "assets_added_to_album_count": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} āŽŽāŽąā¯āŽą {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}}", - "assets_count": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} āŽŽāŽąā¯āŽą {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}}", - "assets_moved_to_trash_count": "āŽ¨āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯ {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} āŽŽāŽąā¯āŽą {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}}}", - "assets_permanently_deleted_count": "āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ¨ā¯€āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯ {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} āŽĒāŽŋāŽą {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}}", - "assets_removed_count": "āŽ…āŽ•āŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯ {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} āŽŽāŽąā¯āŽą {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}}", + "assets_added_count": "āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯ {count, plural, one {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} other {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}}", + "assets_added_to_album_count": "āŽ¤ā¯ŠāŽ•ā¯āŽĒā¯āŽĒāŽŋāŽ˛ā¯ {count, plural, one {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} other {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}} āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "assets_added_to_albums_count": "Added {assetTotal, plural, one {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} other {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}} to {albumTotal, plural, one {# āŽ¤ā¯ŠāŽ•ā¯āŽĒā¯āŽĒ❁} other {# āŽ¤ā¯ŠāŽ•ā¯āŽĒā¯āŽĒā¯āŽ•āŽŗā¯}}āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "assets_cannot_be_added_to_album_count": "{count, plural, one {āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} other {āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}} āŽšā¯†āŽ°ā¯āŽ•ā¯‡āŽŸā¯āŽŸāŽŋāŽ˛ā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", + "assets_cannot_be_added_to_albums": "{count, plural, one {Asset} other {Assets}} āŽŽāŽ¨ā¯āŽ¤āŽšā¯ āŽšā¯†āŽ°ā¯āŽ•ā¯‡āŽŸā¯āŽŸāŽŋāŽ˛ā¯āŽŽā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", + "assets_count": "{count, plural, one {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} other {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}}", + "assets_deleted_permanently": "{count} āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ (āŽ•āŽŗā¯) āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ¨ā¯€āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "assets_deleted_permanently_from_server": "{count} āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ (āŽ•āŽŗā¯) āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯ āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽ¤ā¯āŽ¤āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ¨ā¯€āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "assets_downloaded_failed": "{count, plural, one {# āŽ•ā¯‹āŽĒā¯āŽĒ❁ āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯ - {error} āŽ•ā¯‹āŽĒā¯āŽĒ❁ āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋāŽ¯āŽŸā¯ˆāŽ¨ā¯āŽ¤āŽ¤ā¯} other {# āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽ•āŽŗā¯ āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽŠ - {error} āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽ•āŽŗā¯ āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋāŽ¯āŽŸā¯ˆāŽ¨ā¯āŽ¤āŽŠ}}", + "assets_downloaded_successfully": "{count, plural, one {# āŽ•ā¯‹āŽĒā¯āŽĒ❁ āŽĩā¯†āŽąā¯āŽąāŽŋāŽ•āŽ°āŽŽāŽžāŽ•āŽĒā¯ āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•āŽŽā¯} other {# āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽ•āŽŗā¯ āŽĩā¯†āŽąā¯āŽąāŽŋāŽ•āŽ°āŽŽāŽžāŽ•āŽĒā¯ āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•āŽŽā¯}}", + "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": "{count} āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ (āŽ•āŽŗā¯) āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽšāŽžāŽ¤āŽŠāŽ¤ā¯āŽ¤āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ…āŽ•āŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "assets_restore_confirmation": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ•ā¯āŽĒā¯āŽĒā¯ˆāŽ¤ā¯ āŽ¤ā¯ŠāŽŸā¯āŽŸāŽŋāŽ•āŽŗā¯ āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ˆāŽ¯ā¯āŽŽā¯ āŽŽā¯€āŽŸā¯āŽŸā¯†āŽŸā¯āŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž? āŽ‡āŽ¨ā¯āŽ¤ āŽšā¯†āŽ¯āŽ˛ā¯ˆ āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽšā¯†āŽ¯āŽ˛ā¯āŽ¤āŽĩāŽŋāŽ°ā¯āŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯! āŽŽāŽ¨ā¯āŽ¤āŽĩā¯ŠāŽ°ā¯ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒāŽŋāŽ˛ā¯āŽ˛āŽžāŽ¤ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽ‡āŽ¨ā¯āŽ¤ āŽĩāŽ´āŽŋāŽ¯āŽŋāŽ˛ā¯ āŽŽā¯€āŽŸā¯āŽŸā¯†āŽŸā¯āŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯ āŽŽāŽŠā¯āŽĒāŽ¤ā¯ˆ āŽ¨āŽŋāŽŠā¯ˆāŽĩāŽŋāŽ˛ā¯ āŽ•ā¯ŠāŽŗā¯āŽ•.", - "assets_restored_count": "āŽŽā¯€āŽŸā¯āŽŸā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯ {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} āŽŽāŽąā¯āŽą {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}}", - "assets_trashed_count": "āŽ•ā¯āŽĒā¯āŽĒā¯ˆāŽ¤ā¯āŽ¤ā¯ŠāŽŸā¯āŽŸāŽŋāŽ¯āŽžāŽŠ {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} āŽŽāŽąā¯āŽą {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}}", - "assets_were_part_of_album_count": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽ°ā¯ {Asset was} āŽŽāŽąā¯āŽą {Assets were}} āŽāŽąā¯āŽ•āŽŠāŽĩ❇ āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽŠā¯ āŽ’āŽ°ā¯ āŽĒāŽ•ā¯āŽ¤āŽŋ", + "assets_restored_count": "{count, plural, one {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} other {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}}āŽŽā¯€āŽŸā¯āŽŸā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "assets_restored_successfully": "{count} āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ (āŽ•āŽŗā¯) āŽĩā¯†āŽąā¯āŽąāŽŋāŽ•āŽ°āŽŽāŽžāŽ• āŽŽā¯€āŽŸā¯āŽŸā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "assets_trashed": "{count} āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ (āŽ•āŽŗā¯) āŽ•ā¯āŽĒā¯āŽĒ❈", + "assets_trashed_count": "{count, plural, one {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} other {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}} āŽ•ā¯āŽĒā¯āŽĒā¯ˆāŽ¯āŽžāŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "assets_trashed_from_server": "{count} āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ (āŽ•āŽŗā¯) āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯ āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽ¤ā¯āŽ¤āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ•ā¯āŽĒā¯āŽĒā¯ˆāŽ¤ā¯ āŽ¤ā¯ŠāŽŸā¯āŽŸāŽŋāŽ¯āŽŋāŽ˛ā¯", + "assets_were_part_of_album_count": "{count, plural, one {āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} other {āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}} āŽāŽąā¯āŽ•āŽŠāŽĩ❇ āŽ¤ā¯ŠāŽ•ā¯āŽĒā¯āŽĒāŽŋāŽŠā¯ āŽ’āŽ°ā¯ āŽĒāŽ•ā¯āŽ¤āŽŋ", + "assets_were_part_of_albums_count": "{count, plural, one {āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} other {āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}} āŽāŽąā¯āŽ•āŽŠāŽĩ❇ āŽ¤ā¯ŠāŽ•ā¯āŽĒā¯āŽĒā¯āŽ•āŽŗāŽŋāŽŠā¯ āŽ’āŽ°ā¯ āŽĒāŽ•ā¯āŽ¤āŽŋ", "authorized_devices": "āŽ…āŽ™ā¯āŽ•ā¯€āŽ•āŽ°āŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽšāŽžāŽ¤āŽŠāŽ™ā¯āŽ•āŽŗā¯", + "automatic_endpoint_switching_subtitle": "āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•ā¯āŽŽā¯āŽĒā¯‹āŽ¤ā¯ āŽ¨āŽŋāŽ¯āŽŽāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽĩā¯ˆāŽƒāŽĒ❈ āŽŽā¯€āŽ¤ā¯ āŽ‰āŽŗā¯āŽŗā¯‚āŽ°āŽŋāŽ˛ā¯ āŽ‡āŽŖā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯, āŽĩā¯‡āŽąā¯ āŽ‡āŽŸāŽ™ā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽŽāŽžāŽąā¯āŽąā¯ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", + "automatic_endpoint_switching_title": "āŽ¤āŽžāŽŠāŽŋāŽ¯āŽ™ā¯āŽ•āŽŋ āŽŽā¯āŽ•āŽĩāŽ°āŽŋ āŽŽāŽžāŽąā¯āŽ¤āŽ˛ā¯", + "autoplay_slideshow": "āŽ†āŽŸā¯āŽŸā¯‹āŽĒāŽŋāŽŗā¯‡ āŽšā¯āŽ˛ā¯ˆāŽŸā¯āŽšā¯‹", "back": "āŽĒāŽŋāŽŠā¯", "back_close_deselect": "āŽĒāŽŋāŽŠā¯, āŽŽā¯‚āŽŸā¯ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽĩā¯āŽ¨ā¯€āŽ•ā¯āŽ•āŽŽā¯", + "background_backup_running_error": "āŽĒāŽŋāŽŠā¯āŽŠāŽŖāŽŋ āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋ āŽ¤āŽąā¯āŽĒā¯‹āŽ¤ā¯ āŽ‡āŽ¯āŽ™ā¯āŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯, āŽ•ā¯ˆāŽŽā¯āŽąā¯ˆ āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋāŽ¯ā¯ˆāŽ¤ā¯ āŽ¤ā¯ŠāŽŸāŽ™ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", + "background_location_permission": "āŽĒāŽŋāŽŠā¯āŽŠāŽŖāŽŋ āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽŋāŽŸ āŽ‡āŽšā¯ˆāŽĩ❁", + "background_location_permission_content": "āŽĒāŽŋāŽŠā¯āŽŠāŽŖāŽŋāŽ¯āŽŋāŽ˛ā¯ āŽ‡āŽ¯āŽ™ā¯āŽ•ā¯āŽŽā¯ āŽĒā¯‹āŽ¤ā¯ āŽ¨ā¯†āŽŸā¯āŽĩā¯ŠāŽ°ā¯āŽ•ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽŽāŽžāŽąā¯āŽą, āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯ *āŽŽāŽĒā¯āŽĒā¯‹āŽ¤ā¯āŽŽā¯* āŽ¤ā¯āŽ˛ā¯āŽ˛āŽŋāŽ¯āŽŽāŽžāŽŠ āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽŋāŽŸ āŽ…āŽŖā¯āŽ•āŽ˛ā¯ˆāŽ•ā¯ āŽ•ā¯ŠāŽŖā¯āŽŸāŽŋāŽ°ā¯āŽ•ā¯āŽ• āŽĩā¯‡āŽŖā¯āŽŸā¯āŽŽā¯, āŽŽāŽŠāŽĩ❇ āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯ āŽĩā¯ˆāŽƒāŽĒ❈ āŽ¨ā¯†āŽŸā¯āŽĩā¯ŠāŽ°ā¯āŽ•ā¯āŽ•āŽŋāŽŠā¯ āŽĒā¯†āŽ¯āŽ°ā¯ˆāŽĒā¯ āŽĒāŽŸāŽŋāŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯ā¯āŽŽā¯", + "background_options": "āŽĒāŽŋāŽŠā¯āŽŠāŽŖāŽŋ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯", + "backup": "āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋ", + "backup_album_selection_page_albums_device": "āŽšāŽžāŽ¤āŽŠāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯ ({count})", + "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_albums_sync": "āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋ āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯ āŽ’āŽ¤ā¯āŽ¤āŽŋāŽšā¯ˆāŽĩ❁", + "backup_all": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯āŽŽā¯", + "backup_background_service_backup_failed_message": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋ āŽŽāŽŸā¯āŽ•ā¯āŽ•āŽ¤ā¯ āŽ¤āŽĩāŽąāŽŋāŽĩāŽŋāŽŸā¯āŽŸāŽ¤ā¯. āŽŽā¯€āŽŖā¯āŽŸā¯āŽŽā¯ āŽŽā¯āŽ¯āŽąā¯āŽšāŽŋāŽĒā¯āŽĒāŽ¤ā¯â€Ļ", + "backup_background_service_connection_failed_message": "āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽ¤ā¯āŽ¤ā¯āŽŸāŽŠā¯ āŽ‡āŽŖā¯ˆāŽ•ā¯āŽ•āŽ¤ā¯ āŽ¤āŽĩāŽąāŽŋāŽĩāŽŋāŽŸā¯āŽŸāŽ¤ā¯. āŽŽā¯€āŽŖā¯āŽŸā¯āŽŽā¯ āŽŽā¯āŽ¯āŽąā¯āŽšāŽŋāŽĒā¯āŽĒāŽ¤ā¯â€Ļ", + "backup_background_service_current_upload_notification": "āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąā¯āŽ¤āŽ˛ā¯ {filename}", + "backup_background_service_default_notification": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆāŽšā¯ āŽšāŽ°āŽŋāŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯â€Ļ", + "backup_background_service_error_title": "āŽ•āŽžāŽĒā¯āŽĒ❁ āŽĒāŽŋāŽ´ā¯ˆ", + "backup_background_service_in_progress_notification": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯ āŽĒāŽŋāŽ°āŽ¤āŽŋ āŽŽāŽŸā¯āŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯â€Ļ", + "backup_background_service_upload_failure_notification": "{filename} āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąā¯āŽĩāŽ¤āŽŋāŽ˛ā¯ āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋ", + "backup_controller_page_albums": "āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋ āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯", + "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": "āŽŽāŽĒā¯āŽĒāŽŸāŽŋ āŽŽāŽŠā¯āŽąā¯ āŽŽāŽŠāŽ•ā¯āŽ•ā¯āŽ•ā¯ āŽ•āŽžāŽŸā¯āŽŸā¯", + "backup_controller_page_background_battery_info_message": "āŽšāŽŋāŽąāŽ¨ā¯āŽ¤ āŽĒāŽŋāŽŠā¯āŽŠāŽŖāŽŋ āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋ āŽ…āŽŠā¯āŽĒāŽĩāŽ¤ā¯āŽ¤āŽŋāŽąā¯āŽ•ā¯, āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯āŽšāŽŋāŽąā¯āŽ•āŽžāŽŠ āŽĒāŽŋāŽŠā¯āŽŠāŽŖāŽŋ āŽšā¯†āŽ¯āŽ˛ā¯āŽĒāŽžāŽŸā¯āŽŸā¯ˆāŽ•ā¯ āŽ•āŽŸā¯āŽŸā¯āŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽŽā¯ āŽŽāŽ¨ā¯āŽ¤ āŽĒā¯‡āŽŸā¯āŽŸāŽ°āŽŋ āŽŽā¯‡āŽŽā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽ˛ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽŽā¯āŽŸāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯. \n\nāŽ‡āŽ¤ā¯ āŽšāŽžāŽ¤āŽŠāŽŽā¯ āŽšāŽžāŽ°ā¯āŽ¨ā¯āŽ¤āŽ¤āŽžāŽ• āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽ¤āŽžāŽ˛ā¯, āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽšāŽžāŽ¤āŽŠ āŽ‰āŽąā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽ¯āŽžāŽŗāŽ°ā¯āŽ•ā¯āŽ•ā¯ āŽ¤ā¯‡āŽĩā¯ˆāŽ¯āŽžāŽŠ āŽ¤āŽ•āŽĩāŽ˛ā¯āŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽŸā¯āŽ™ā¯āŽ•āŽŗā¯.", + "backup_controller_page_background_battery_info_ok": "āŽšāŽ°āŽŋ", + "backup_controller_page_background_battery_info_title": "āŽĒā¯‡āŽŸā¯āŽŸāŽ°āŽŋ āŽŽā¯‡āŽŽā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽ˛ā¯āŽ•āŽŗā¯", + "backup_controller_page_background_charging": "āŽ•āŽŸā¯āŽŸāŽŖāŽŽā¯ āŽĩāŽšā¯‚āŽ˛āŽŋāŽ•ā¯āŽ•ā¯āŽŽā¯ āŽĒā¯‹āŽ¤ā¯ āŽŽāŽŸā¯āŽŸā¯āŽŽā¯‡", + "backup_controller_page_background_configure_error": "āŽĒāŽŋāŽŠā¯āŽŠāŽŖāŽŋ āŽšā¯‡āŽĩā¯ˆāŽ¯ā¯ˆ āŽ‰āŽŗā¯āŽŗāŽŽā¯ˆāŽ•ā¯āŽ•āŽ¤ā¯ āŽ¤āŽĩāŽąāŽŋāŽĩāŽŋāŽŸā¯āŽŸāŽ¤ā¯", + "backup_controller_page_background_delay": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽ¤āŽžāŽŽāŽ¤āŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽ™ā¯āŽ•āŽŗā¯: {duration}", + "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": "āŽĩā¯ˆāŽƒāŽĒ❈ āŽŽāŽŸā¯āŽŸā¯āŽŽā¯‡", + "backup_controller_page_backup": "āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋ", + "backup_controller_page_backup_selected": "āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯: ", + "backup_controller_page_backup_sub": "āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ˆ āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯ āŽĒāŽŋāŽ°āŽ¤āŽŋ āŽŽāŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "backup_controller_page_created": "āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯: {date}", + "backup_controller_page_desc_backup": "āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯āŽŸā¯ˆāŽ¤ā¯ āŽ¤āŽŋāŽąāŽ•ā¯āŽ•ā¯āŽŽā¯āŽĒā¯‹āŽ¤ā¯ āŽĒā¯āŽ¤āŽŋāŽ¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ¤āŽžāŽŠāŽžāŽ• āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽą āŽŽā¯āŽŠā¯āŽĒā¯āŽą āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋāŽ¯ā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯.", + "backup_controller_page_excluded": "āŽĩāŽŋāŽ˛āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯: ", + "backup_controller_page_failed": "āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋāŽ¯ā¯āŽąā¯āŽąāŽ¤ā¯ ({count})", + "backup_controller_page_filename": "āŽ•ā¯‹āŽĒā¯āŽĒ❁ āŽĒā¯†āŽ¯āŽ°ā¯: {filename} [{size}]", + "backup_controller_page_id": "āŽāŽŸāŽŋ: {id}", + "backup_controller_page_info": "āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋ āŽšā¯†āŽ¯ā¯āŽ¤āŽŋ", + "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_storage_format": "{total} āŽ‡āŽ˛ā¯ {used} āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "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_error_sync_failed": "āŽ’āŽ¤ā¯āŽ¤āŽŋāŽšā¯ˆāŽĩ❁ āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋāŽ¯ā¯āŽąā¯āŽąāŽ¤ā¯. āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋāŽ¯ā¯ˆ āŽšā¯†āŽ¯āŽ˛āŽžāŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯.", + "backup_info_card_assets": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯", + "backup_manual_cancelled": "āŽ°āŽ¤ā¯āŽ¤ā¯ āŽšā¯†āŽ¯ā¯āŽ¯āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "backup_manual_in_progress": "āŽāŽąā¯āŽ•āŽŠāŽĩ❇ āŽŽā¯āŽŠā¯āŽŠā¯‡āŽąā¯āŽąāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąāŽĩā¯āŽŽā¯. āŽšāŽŋāŽąāŽŋāŽ¤ā¯ āŽ¨ā¯‡āŽ°āŽŽā¯ āŽ•āŽ´āŽŋāŽ¤ā¯āŽ¤ā¯ āŽŽā¯āŽ¯āŽąā¯āŽšāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "backup_manual_success": "āŽšā¯†āŽ¯ā¯", + "backup_manual_title": "āŽ¨āŽŋāŽ˛ā¯ˆ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąā¯āŽŽā¯ āŽ¨āŽŋāŽ˛ā¯ˆ", + "backup_options": "āŽ•āŽžāŽĒā¯āŽĒ❁ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯", + "backup_options_page_title": "āŽ•āŽžāŽĒā¯āŽĒ❁ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯", + "backup_setting_subtitle": "āŽĒāŽŋāŽŠā¯āŽŠāŽŖāŽŋ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽŽā¯āŽŠā¯āŽĒā¯āŽą āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽą āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "backup_settings_subtitle": "āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽą āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "backward": "āŽĒāŽŋāŽŠā¯āŽŠā¯‹āŽ•ā¯āŽ•ā¯", + "biometric_auth_enabled": "āŽĒāŽ¯ā¯‹āŽŽā¯†āŽŸā¯āŽ°āŽŋāŽ•ā¯ āŽāŽąā¯āŽĒ❁ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "biometric_locked_out": "āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽĒāŽ¯ā¯‹āŽŽā¯†āŽŸā¯āŽ°āŽŋāŽ•ā¯ āŽ…āŽ™ā¯āŽ•ā¯€āŽ•āŽžāŽ°āŽ¤ā¯āŽ¤āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽĒā¯‚āŽŸā¯āŽŸāŽĒā¯āŽĒāŽŸā¯āŽŸāŽŋāŽ°ā¯āŽ•ā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗā¯", + "biometric_no_options": "āŽĒāŽ¯ā¯‹āŽŽā¯†āŽŸā¯āŽ°āŽŋāŽ•ā¯ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽ¤ā¯āŽĩā¯āŽŽā¯ āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", + "biometric_not_available": "āŽ‡āŽ¨ā¯āŽ¤ āŽšāŽžāŽ¤āŽŠāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽĒāŽ¯ā¯‹āŽŽā¯†āŽŸā¯āŽ°āŽŋāŽ•ā¯ āŽāŽąā¯āŽĒ❁ āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "birthdate_saved": "āŽĒāŽŋāŽąāŽ¨ā¯āŽ¤ āŽ¤ā¯‡āŽ¤āŽŋ āŽĩā¯†āŽąā¯āŽąāŽŋāŽ•āŽ°āŽŽāŽžāŽ• āŽšā¯‡āŽŽāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "birthdate_set_description": "āŽ’āŽ°ā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ¤ā¯āŽ¤āŽŋāŽŠā¯ āŽĒā¯‹āŽ¤ā¯ āŽ‡āŽ¨ā¯āŽ¤ āŽ¨āŽĒāŽ°āŽŋāŽŠā¯ āŽĩāŽ¯āŽ¤ā¯ˆāŽ•ā¯ āŽ•āŽŖāŽ•ā¯āŽ•āŽŋāŽŸ āŽĒāŽŋāŽąāŽ¨ā¯āŽ¤ āŽ¤ā¯‡āŽ¤āŽŋ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽ•āŽŋāŽąāŽ¤ā¯.", "blurred_background": "āŽŽāŽ™ā¯āŽ•āŽ˛āŽžāŽŠ āŽĒāŽŋāŽŠā¯āŽŠāŽŖāŽŋ", "bugs_and_feature_requests": "āŽĒāŽŋāŽ´ā¯ˆāŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽ…āŽŽā¯āŽš āŽ•ā¯‹āŽ°āŽŋāŽ•ā¯āŽ•ā¯ˆāŽ•āŽŗā¯", "build": "āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•ā¯", "build_image": "āŽĒāŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•ā¯āŽ™ā¯āŽ•āŽŗā¯", - "bulk_delete_duplicates_confirmation": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽ¨āŽ•āŽ˛ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} āŽĒāŽŋāŽą {# āŽ¨āŽ•āŽ˛ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}}}}}}}}} {{# āŽ¨āŽ•āŽ˛ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ āŽ†āŽ•āŽŋāŽ¯āŽĩāŽąā¯āŽąā¯ˆ āŽŽā¯ŠāŽ¤ā¯āŽ¤āŽŽāŽžāŽ• āŽ¨ā¯€āŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž? āŽ‡āŽ¤ā¯ āŽ’āŽĩā¯āŽĩā¯ŠāŽ°ā¯ āŽ•ā¯āŽ´ā¯āŽĩāŽŋāŽŠā¯ āŽŽāŽŋāŽ•āŽĒā¯āŽĒā¯†āŽ°āŽŋāŽ¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆ āŽĩā¯ˆāŽ¤ā¯āŽ¤āŽŋāŽ°ā¯āŽ•ā¯āŽ•ā¯āŽŽā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽŽāŽąā¯āŽą āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ āŽ¨āŽ•āŽ˛ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ¨ā¯€āŽ•ā¯āŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯. āŽ‡āŽ¨ā¯āŽ¤ āŽšā¯†āŽ¯āŽ˛ā¯ˆ āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽšā¯†āŽ¯āŽ˛ā¯āŽ¤āŽĩāŽŋāŽ°ā¯āŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯!", - "bulk_keep_duplicates_confirmation": "āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽ¨āŽ•āŽ˛ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} āŽĒāŽŋāŽą {# āŽ¨āŽ•āŽ˛ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯} be āŽĩā¯ˆāŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž? āŽ‡āŽ¤ā¯ āŽŽāŽ¤ā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¨ā¯€āŽ•ā¯āŽ•āŽžāŽŽāŽ˛ā¯ āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ āŽ¨āŽ•āŽ˛ā¯ āŽ•ā¯āŽ´ā¯āŽ•ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¤ā¯€āŽ°ā¯āŽ•ā¯āŽ•ā¯āŽŽā¯.", - "bulk_trash_duplicates_confirmation": "āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽŽā¯ŠāŽ¤ā¯āŽ¤āŽŽāŽžāŽ• āŽ•ā¯āŽĒā¯āŽĒ❈ {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽ¨āŽ•āŽ˛ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} āŽĒāŽŋāŽą {# āŽ¨āŽ•āŽ˛ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}}}} āŽšā¯†āŽ¯ā¯āŽ¯ āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž? āŽ‡āŽ¤ā¯ āŽ’āŽĩā¯āŽĩā¯ŠāŽ°ā¯ āŽ•ā¯āŽ´ā¯āŽĩāŽŋāŽŠā¯ āŽŽāŽŋāŽ•āŽĒā¯āŽĒā¯†āŽ°āŽŋāŽ¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆ āŽĩā¯ˆāŽ¤ā¯āŽ¤āŽŋāŽ°ā¯āŽ•ā¯āŽ•ā¯āŽŽā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽŽāŽąā¯āŽą āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ āŽ¨āŽ•āŽ˛ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽ•ā¯āŽĒā¯āŽĒā¯ˆāŽ¤ā¯ āŽ¤ā¯ŠāŽŸā¯āŽŸāŽŋāŽ¯āŽžāŽ• āŽ‡āŽ°ā¯āŽ•ā¯āŽ•ā¯āŽŽā¯.", + "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": "āŽ‡āŽŽā¯āŽŽāŽŋāŽ¯ā¯ˆ āŽĩāŽžāŽ™ā¯āŽ•āŽĩā¯āŽŽā¯", + "cache_settings_clear_cache_button": "āŽ¤ā¯†āŽŗāŽŋāŽĩāŽžāŽŠ āŽ¤āŽąā¯āŽ•āŽžāŽ˛āŽŋāŽ• āŽšā¯‡āŽŽāŽŋāŽĒā¯āŽĒ❁", + "cache_settings_clear_cache_button_title": "āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯āŽŸāŽŋāŽŠā¯ āŽ¤āŽąā¯āŽ•āŽžāŽ˛āŽŋāŽ• āŽšā¯‡āŽŽāŽŋāŽĒā¯āŽĒ❈ āŽ…āŽ´āŽŋāŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯. āŽ•ā¯‡āŽšā¯ āŽŽā¯€āŽŖā¯āŽŸā¯āŽŽā¯ āŽ•āŽŸā¯āŽŸāŽĒā¯āŽĒāŽŸā¯āŽŽā¯ āŽĩāŽ°ā¯ˆ āŽ‡āŽ¤ā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯āŽŸāŽŋāŽŠā¯ āŽšā¯†āŽ¯āŽ˛ā¯āŽ¤āŽŋāŽąāŽŠā¯ˆ āŽ•āŽŖāŽŋāŽšāŽŽāŽžāŽ• āŽĒāŽžāŽ¤āŽŋāŽ•ā¯āŽ•ā¯āŽŽā¯.", + "cache_settings_duplicated_assets_clear_button": "āŽ¤ā¯†āŽŗāŽŋāŽĩāŽžāŽŠ", + "cache_settings_duplicated_assets_subtitle": "āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯āŽŸāŽžāŽ˛ā¯ āŽĒāŽŸā¯āŽŸāŽŋāŽ¯āŽ˛āŽŋāŽŸāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽĒā¯āŽąāŽ•ā¯āŽ•āŽŖāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯", + "cache_settings_duplicated_assets_title": "āŽ¨āŽ•āŽ˛ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ ({count})", + "cache_settings_statistics_album": "āŽ¨ā¯‚āŽ˛āŽ• āŽšāŽŋāŽąā¯ āŽ‰āŽ°ā¯āŽĩāŽ™ā¯āŽ•āŽŗā¯", + "cache_settings_statistics_full": "āŽŽā¯āŽ´ā¯ āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯", + "cache_settings_statistics_shared": "āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ†āŽ˛ā¯āŽĒāŽŽā¯ āŽšāŽŋāŽąā¯āŽĒāŽŸāŽŽā¯", + "cache_settings_statistics_thumbnail": "āŽšāŽŋāŽąā¯ āŽ‰āŽ°ā¯āŽĩāŽ™ā¯āŽ•āŽŗā¯", + "cache_settings_statistics_title": "āŽ•ā¯‡āŽšā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯", + "cache_settings_subtitle": "āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯ āŽŽā¯ŠāŽĒā¯ˆāŽ˛ā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯āŽŸāŽŋāŽŠā¯ āŽ¤āŽąā¯āŽ•āŽžāŽ˛āŽŋāŽ• āŽšā¯‡āŽŽāŽŋāŽĒā¯āŽĒ❁ āŽ¨āŽŸāŽ¤ā¯āŽ¤ā¯ˆāŽ¯ā¯ˆ āŽ•āŽŸā¯āŽŸā¯āŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", + "cache_settings_tile_subtitle": "āŽ‰āŽŗā¯āŽŗāŽ• āŽšā¯‡āŽŽāŽŋāŽĒā¯āŽĒāŽ• āŽ¨āŽŸāŽ¤ā¯āŽ¤ā¯ˆāŽ¯ā¯ˆ āŽ•āŽŸā¯āŽŸā¯āŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", + "cache_settings_tile_title": "āŽ‰āŽŗā¯āŽŗāŽ• āŽšā¯‡āŽŽāŽŋāŽĒā¯āŽĒ❁", + "cache_settings_title": "āŽ¤ā¯‡āŽ•ā¯āŽ•āŽ• āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", "camera": "āŽ•ā¯‡āŽŽāŽ°āŽž", "camera_brand": "āŽ•ā¯‡āŽŽāŽ°āŽž āŽšā¯‚āŽŸā¯āŽŸā¯āŽ•ā¯āŽ•ā¯āŽąāŽŋ", "camera_model": "āŽ•ā¯‡āŽŽāŽ°āŽž āŽŽāŽžāŽ¤āŽŋāŽ°āŽŋ", "cancel": "āŽ°āŽ¤ā¯āŽ¤ā¯āŽšā¯†āŽ¯ā¯", "cancel_search": "āŽ¤ā¯‡āŽŸāŽ˛ā¯ˆ āŽ°āŽ¤ā¯āŽ¤ā¯āŽšā¯†āŽ¯ā¯", + "canceled": "āŽ°āŽ¤ā¯āŽ¤ā¯ āŽšā¯†āŽ¯ā¯āŽ¯āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "canceling": "āŽ°āŽ¤ā¯āŽ¤ā¯āŽšā¯†āŽ¯ā¯āŽ¯ā¯āŽŽā¯", "cannot_merge_people": "āŽŽāŽ•ā¯āŽ•āŽŗā¯ˆ āŽ’āŽŠā¯āŽąāŽŋāŽŖā¯ˆāŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", "cannot_undo_this_action": "āŽ‡āŽ¨ā¯āŽ¤ āŽšā¯†āŽ¯āŽ˛ā¯ˆ āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽšā¯†āŽ¯āŽ˛ā¯āŽ¤āŽĩāŽŋāŽ°ā¯āŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯!", "cannot_update_the_description": "āŽĩāŽŋāŽŗāŽ•ā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", + "cast": "āŽ¨āŽŸāŽŋāŽ•āŽ°ā¯āŽ•āŽŗā¯", + "cast_description": "āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•āŽ•ā¯āŽ•ā¯‚āŽŸāŽŋāŽ¯ āŽĩāŽžāŽ°ā¯āŽĒā¯āŽĒ❁ āŽ‡āŽŸāŽ™ā¯āŽ•āŽŗā¯ˆ āŽ‰āŽŗā¯āŽŗāŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "change_date": "āŽ¤ā¯‡āŽ¤āŽŋāŽ¯ā¯ˆ āŽŽāŽžāŽąā¯āŽąāŽĩā¯āŽŽā¯", + "change_description": "āŽĩāŽŋāŽŗāŽ•ā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽŽāŽžāŽąā¯āŽąāŽĩā¯āŽŽā¯", + "change_display_order": "āŽ•āŽžāŽŸā¯āŽšāŽŋ āŽĩāŽ°āŽŋāŽšā¯ˆāŽ¯ā¯ˆ āŽŽāŽžāŽąā¯āŽąāŽĩā¯āŽŽā¯", "change_expiration_time": "āŽ•āŽžāŽ˛āŽžāŽĩāŽ¤āŽŋ āŽ¨ā¯‡āŽ°āŽ¤ā¯āŽ¤ā¯ˆ āŽŽāŽžāŽąā¯āŽąāŽĩā¯āŽŽā¯", "change_location": "āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽŋāŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽŽāŽžāŽąā¯āŽąāŽĩā¯āŽŽā¯", "change_name": "āŽĒā¯†āŽ¯āŽ°ā¯ˆ āŽŽāŽžāŽąā¯āŽąāŽĩā¯āŽŽā¯", - "change_name_successfully": "āŽĒā¯†āŽ¯āŽ°ā¯ˆ āŽĩā¯†āŽąā¯āŽąāŽŋāŽ•āŽ°āŽŽāŽžāŽ• āŽŽāŽžāŽąā¯āŽąāŽĩā¯āŽŽā¯", + "change_name_successfully": "āŽĒā¯†āŽ¯āŽ°ā¯ āŽĩā¯†āŽąā¯āŽąāŽŋāŽ•āŽ°āŽŽāŽžāŽ• āŽŽāŽžāŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "change_password": "āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽŽāŽžāŽąā¯āŽąāŽĩā¯āŽŽā¯", "change_password_description": "āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽ•āŽŖāŽŋāŽŠāŽŋāŽ¯āŽŋāŽ˛ā¯ āŽ•ā¯ˆāŽ¯ā¯ŠāŽĒā¯āŽĒāŽŽāŽŋāŽŸā¯āŽĩāŽ¤ā¯ āŽ‡āŽ¤ā¯āŽĩ❇ āŽŽā¯āŽ¤āŽ˛ā¯ āŽŽā¯āŽąā¯ˆ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽŽāŽžāŽąā¯āŽąā¯āŽĩāŽ¤āŽąā¯āŽ•āŽžāŽŠ āŽ•ā¯‹āŽ°āŽŋāŽ•ā¯āŽ•ā¯ˆ āŽšā¯†āŽ¯ā¯āŽ¯āŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗāŽ¤ā¯. āŽ•ā¯€āŽ´ā¯‡ āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽ‰āŽŗā¯āŽŗāŽŋāŽŸāŽĩā¯āŽŽā¯.", + "change_password_form_confirm_password": "āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽ‰āŽąā¯āŽ¤āŽŋāŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", + "change_password_form_description": "āŽ†āŽ¯ā¯ {name}, \n\nāŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽ•āŽŖāŽŋāŽŠāŽŋāŽ¯āŽŋāŽ˛ā¯ āŽ•ā¯ˆāŽ¯ā¯ŠāŽĒā¯āŽĒāŽŽāŽŋāŽŸā¯āŽĩāŽ¤ā¯ āŽ‡āŽ¤ā¯āŽĩ❇ āŽŽā¯āŽ¤āŽ˛ā¯ āŽŽā¯āŽąā¯ˆ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽŽāŽžāŽąā¯āŽąā¯āŽĩāŽ¤āŽąā¯āŽ•āŽžāŽŠ āŽ•ā¯‹āŽ°āŽŋāŽ•ā¯āŽ•ā¯ˆ āŽšā¯†āŽ¯ā¯āŽ¯āŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗāŽ¤ā¯. āŽ•ā¯€āŽ´ā¯‡ āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽ‰āŽŗā¯āŽŗāŽŋāŽŸāŽĩā¯āŽŽā¯.", + "change_password_form_new_password": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯", + "change_password_form_password_mismatch": "āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽąā¯āŽ•āŽŗā¯ āŽĒā¯ŠāŽ°ā¯āŽ¨ā¯āŽ¤āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", + "change_password_form_reenter_new_password": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽŽā¯€āŽŖā¯āŽŸā¯āŽŽā¯ āŽ‰āŽŗā¯āŽŗāŽŋāŽŸāŽĩā¯āŽŽā¯", + "change_pin_code": "āŽŽā¯āŽŗā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ˆ āŽŽāŽžāŽąā¯āŽąāŽĩā¯āŽŽā¯", "change_your_password": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽŽāŽžāŽąā¯āŽąāŽĩā¯āŽŽā¯", "changed_visibility_successfully": "āŽ¤ā¯†āŽ°āŽŋāŽĩā¯āŽ¨āŽŋāŽ˛ā¯ˆ āŽĩā¯†āŽąā¯āŽąāŽŋāŽ•āŽ°āŽŽāŽžāŽ• āŽŽāŽžāŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "charging": "āŽšāŽžāŽ°ā¯āŽšāŽŋāŽ™ā¯", + "charging_requirement_mobile_backup": "āŽĒāŽŋāŽŠā¯āŽŠāŽŖāŽŋ āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋāŽ•ā¯āŽ•ā¯ āŽšāŽžāŽ¤āŽŠāŽŽā¯ āŽšāŽžāŽ°ā¯āŽšā¯ āŽšā¯†āŽ¯ā¯āŽ¯ āŽĩā¯‡āŽŖā¯āŽŸā¯āŽŽā¯", + "check_corrupt_asset_backup": "āŽŠāŽ´āŽ˛ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋāŽ•āŽŗā¯ˆ āŽšāŽ°āŽŋāŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "check_corrupt_asset_backup_button": "āŽ•āŽžāŽšā¯‹āŽ˛ā¯ˆ āŽšā¯†āŽ¯ā¯āŽ¯ā¯āŽ™ā¯āŽ•āŽŗā¯", + "check_corrupt_asset_backup_description": "āŽ‡āŽ¨ā¯āŽ¤ āŽ•āŽžāŽšā¯‹āŽ˛ā¯ˆāŽ¯ā¯ˆ āŽĩā¯ˆāŽƒāŽĒ❈ āŽŽā¯€āŽ¤ā¯ āŽŽāŽŸā¯āŽŸā¯āŽŽā¯‡ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯, āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯āŽŽā¯ āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯ āŽĒāŽŋāŽ°āŽ¤āŽŋ āŽŽāŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽĩā¯āŽŸāŽŠā¯. āŽšā¯†āŽ¯āŽ˛ā¯āŽŽā¯āŽąā¯ˆ āŽšāŽŋāŽ˛ āŽ¨āŽŋāŽŽāŽŋāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽ†āŽ•āŽ˛āŽžāŽŽā¯.", "check_logs": "āŽĒāŽ¤āŽŋāŽĩā¯āŽ•āŽŗā¯ˆ āŽšāŽ°āŽŋāŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "choose_matching_people_to_merge": "āŽ’āŽŠā¯āŽąāŽŋāŽŖā¯ˆāŽ•ā¯āŽ• āŽĒā¯ŠāŽ°ā¯āŽ¨ā¯āŽ¤āŽ•ā¯āŽ•ā¯‚āŽŸāŽŋāŽ¯ āŽ¨āŽĒāŽ°ā¯āŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽĩā¯āŽšā¯†āŽ¯ā¯āŽ•", "city": "āŽ¨āŽ•āŽ°āŽŽā¯", "clear": "āŽ¤ā¯†āŽŗāŽŋāŽĩāŽžāŽŠ", "clear_all": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ˆāŽ¯ā¯āŽŽā¯ āŽ…āŽ´āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "clear_all_recent_searches": "āŽ…āŽŖā¯āŽŽā¯ˆāŽ•ā¯ āŽ•āŽžāŽ˛ āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ āŽ¤ā¯‡āŽŸāŽ˛ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽ…āŽ´āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "clear_file_cache": "āŽ•ā¯‹āŽĒā¯āŽĒ❁ āŽ¤āŽąā¯āŽ•āŽžāŽ˛āŽŋāŽ• āŽšā¯‡āŽŽāŽŋāŽĒā¯āŽĒ❈ āŽ…āŽ´āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "clear_message": "āŽ¤ā¯†āŽŗāŽŋāŽĩāŽžāŽŠ āŽšā¯†āŽ¯ā¯āŽ¤āŽŋ", "clear_value": "āŽ¤ā¯†āŽŗāŽŋāŽĩāŽžāŽŠ āŽŽāŽ¤āŽŋāŽĒā¯āŽĒ❁", + "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_title": "āŽŽāŽšā¯āŽŽāŽšā¯āŽŽāŽ˛ā¯ āŽ•āŽŋāŽŗā¯ˆāŽ¯āŽŠā¯āŽŸā¯ āŽšāŽžāŽŠā¯āŽąāŽŋāŽ¤āŽ´ā¯", "clockwise": "Locklowsy", "close": "āŽŽā¯‚āŽŸā¯", "collapse": "āŽšāŽ°āŽŋāŽĩ❁", @@ -472,14 +700,31 @@ "comment_options": "āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤ā¯ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯", "comments_and_likes": "āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤ā¯āŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯", "comments_are_disabled": "āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤ā¯āŽ•āŽŗā¯ āŽŽā¯āŽŸāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗāŽŠ", + "common_create_new_album": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤ā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "common_server_error": "āŽ¤āŽ¯āŽĩā¯āŽšā¯†āŽ¯ā¯āŽ¤ā¯ āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽĒāŽŋāŽŖā¯ˆāŽ¯ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒā¯ˆāŽšā¯ āŽšāŽ°āŽŋāŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯, āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽŽā¯ āŽ…āŽŸā¯ˆāŽ¯āŽ•ā¯āŽ•ā¯‚āŽŸāŽŋāŽ¯āŽ¤ā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯/āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ• āŽĒāŽ¤āŽŋāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ āŽ‡āŽŖāŽ•ā¯āŽ•āŽŽāŽžāŽŠāŽĩ❈ āŽŽāŽŠā¯āŽĒāŽ¤ā¯ˆ āŽ‰āŽąā¯āŽ¤āŽŋāŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯.", + "completed": "āŽŽā¯āŽŸāŽŋāŽ¨ā¯āŽ¤āŽ¤ā¯", "confirm": "āŽ‰āŽąā¯āŽ¤āŽŋāŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", "confirm_admin_password": "āŽ¨āŽŋāŽ°ā¯āŽĩāŽžāŽ•āŽŋ āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽ‰āŽąā¯āŽ¤āŽŋāŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", + "confirm_delete_face": "āŽšā¯ŠāŽ¤ā¯āŽ¤āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ {name} āŽŽā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽ¨ā¯€āŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", "confirm_delete_shared_link": "āŽ‡āŽ¨ā¯āŽ¤ āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❈ āŽ¨ā¯€āŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", "confirm_keep_this_delete_others": "āŽ‡āŽ¨ā¯āŽ¤ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆāŽ¤ā¯ āŽ¤āŽĩāŽŋāŽ° āŽ…āŽŸā¯āŽ•ā¯āŽ•āŽŋāŽ˛ā¯ āŽ‰āŽŗā¯āŽŗ āŽŽāŽąā¯āŽą āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•āŽŗā¯āŽŽā¯ āŽ¨ā¯€āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŽā¯. āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽ¤ā¯ŠāŽŸāŽ° āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", + "confirm_new_pin_code": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽŽā¯āŽŗā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ˆ āŽ‰āŽąā¯āŽ¤āŽŋāŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", "confirm_password": "āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽ‰āŽąā¯āŽ¤āŽŋāŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", + "confirm_tag_face": "āŽ‡āŽ¨ā¯āŽ¤ āŽŽā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆ {name} āŽŽāŽŠāŽ•ā¯ āŽ•ā¯āŽąāŽŋāŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", + "confirm_tag_face_unnamed": "āŽ‡āŽ¨ā¯āŽ¤ āŽŽā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽ•ā¯āŽąāŽŋāŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", + "connected_device": "āŽ‡āŽŖā¯ˆāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽšāŽžāŽ¤āŽŠāŽŽā¯", + "connected_to": "āŽ‡āŽŖā¯ˆāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗāŽ¤ā¯", "contain": "āŽ•āŽŸā¯āŽŸā¯āŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", "context": "āŽšā¯‚āŽ´āŽ˛ā¯", "continue": "āŽ¤ā¯ŠāŽŸāŽ°āŽĩā¯āŽŽā¯", + "control_bottom_app_bar_create_new_album": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤ā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "control_bottom_app_bar_delete_from_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": "āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❈āŽĒā¯ āŽĒāŽ•āŽŋāŽ°āŽĩā¯āŽŽā¯", + "control_bottom_app_bar_share_to": "āŽĒāŽ•āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ•ā¯ŠāŽŗā¯āŽŗā¯āŽ™ā¯āŽ•āŽŗā¯", + "control_bottom_app_bar_trash_from_immich": "āŽ•ā¯āŽĒā¯āŽĒā¯ˆāŽ•ā¯āŽ•ā¯ āŽ¨āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", "copied_image_to_clipboard": "āŽ‡āŽŸā¯ˆāŽ¨āŽŋāŽ˛ā¯ˆāŽĒā¯āŽĒāŽ˛āŽ•ā¯ˆāŽ•ā¯āŽ•ā¯ āŽĒāŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽ¨āŽ•āŽ˛ā¯†āŽŸā¯āŽ¤ā¯āŽ¤āŽ¤ā¯.", "copied_to_clipboard": "āŽ‡āŽŸā¯ˆāŽ¨āŽŋāŽ˛ā¯ˆāŽĒā¯āŽĒāŽ˛āŽ•ā¯ˆāŽ•ā¯āŽ•ā¯ āŽ¨āŽ•āŽ˛ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯!", "copy_error": "āŽ¨āŽ•āŽ˛ā¯ āŽĒāŽŋāŽ´ā¯ˆ", @@ -494,51 +739,91 @@ "covers": "āŽŽāŽąā¯ˆāŽ¯āŽŽā¯", "create": "āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•ā¯", "create_album": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤ā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "create_album_page_untitled": "āŽ¤āŽ˛ā¯ˆāŽĒā¯āŽĒāŽŋāŽŸāŽĒā¯āŽĒāŽŸāŽžāŽ¤", "create_library": "āŽ¨ā¯‚āŽ˛āŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "create_link": "āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❈ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "create_link_to_share": "āŽĒāŽ•āŽŋāŽ°ā¯āŽĩā¯āŽ•ā¯āŽ•ā¯ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❈ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "create_link_to_share_description": "āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❁ āŽ‰āŽŗā¯āŽŗ āŽŽāŽĩāŽ°ā¯āŽŽā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆāŽ•ā¯ āŽ•āŽžāŽŖāŽŸā¯āŽŸā¯āŽŽā¯)", + "create_new": "āŽĒā¯āŽ¤āŽŋāŽ¯āŽ¤ā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "create_new_person": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ¨āŽĒāŽ°ā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "create_new_person_hint": "āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ¨āŽĒāŽ°ā¯āŽ•ā¯āŽ•ā¯ āŽ’āŽ¤ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "create_new_user": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽĒāŽ¯āŽŠāŽ°ā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "create_shared_album_page_share_add_assets": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆāŽšā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "create_shared_album_page_share_select_photos": "āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "create_shared_link": "āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❈ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "create_tag": "āŽ•ā¯āŽąāŽŋāŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "create_tag_description": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ•ā¯āŽąāŽŋāŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯. āŽ‰āŽŗā¯āŽŗāŽŽā¯ˆāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ•ā¯āŽąāŽŋāŽšā¯āŽšā¯ŠāŽąā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯, āŽŽā¯āŽŠā¯āŽŠā¯‹āŽ•ā¯āŽ•āŽŋ āŽšā¯āŽ˛āŽžāŽšā¯āŽ•āŽŗā¯ āŽ‰āŽŸā¯āŽĒāŽŸ āŽ•ā¯āŽąāŽŋāŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛āŽŋāŽŠā¯ āŽŽā¯āŽ´ā¯ āŽĒāŽžāŽ¤ā¯ˆāŽ¯ā¯ˆāŽ¯ā¯āŽŽā¯ āŽ‰āŽŗā¯āŽŗāŽŋāŽŸāŽĩā¯āŽŽā¯.", "create_user": "āŽĒāŽ¯āŽŠāŽ°ā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•ā¯", "created": "āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "created_at": "āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "creating_linked_albums": "āŽ‡āŽŖā¯ˆāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•ā¯āŽ¤āŽ˛ā¯ ...", + "crop": "āŽĒāŽ¯āŽŋāŽ°ā¯", + "curated_object_page_title": "āŽĩāŽŋāŽšāŽ¯āŽ™ā¯āŽ•āŽŗā¯", "current_device": "āŽ¤āŽąā¯āŽĒā¯‹āŽ¤ā¯ˆāŽ¯ āŽšāŽžāŽ¤āŽŠāŽŽā¯", + "current_pin_code": "āŽ¤āŽąā¯āŽĒā¯‹āŽ¤ā¯ˆāŽ¯ āŽŽā¯āŽŗā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯", + "current_server_address": "āŽ¤āŽąā¯āŽĒā¯‹āŽ¤ā¯ˆāŽ¯ āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ• āŽŽā¯āŽ•āŽĩāŽ°āŽŋ", "custom_locale": "āŽ¤āŽŠāŽŋāŽĒā¯āŽĒāŽ¯āŽŠā¯ āŽ‡āŽŸāŽŽā¯", "custom_locale_description": "āŽŽā¯ŠāŽ´āŽŋ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĒāŽŋāŽ°āŽžāŽ¨ā¯āŽ¤āŽŋāŽ¯āŽ¤ā¯āŽ¤āŽŋāŽŠā¯ āŽ…āŽŸāŽŋāŽĒā¯āŽĒāŽŸā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽĩāŽŸāŽŋāŽĩāŽŽā¯ˆāŽĒā¯āŽĒ❁ āŽ¤ā¯‡āŽ¤āŽŋāŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽŽāŽŖā¯āŽ•āŽŗā¯", + "custom_url": "āŽ¤āŽŠāŽŋāŽĒā¯āŽĒāŽ¯āŽŠā¯ āŽŽā¯āŽ•āŽĩāŽ°āŽŋ", + "daily_title_text_date": "E, mmm dd", + "daily_title_text_date_year": "E, mmm dd, yyyy", "dark": "āŽ‡āŽ°ā¯āŽŖā¯āŽŸ", + "dark_theme": "āŽ‡āŽ°ā¯āŽŖā¯āŽŸ āŽ•āŽ°ā¯āŽĒā¯āŽĒā¯ŠāŽ°ā¯āŽŗā¯ˆ āŽŽāŽžāŽąā¯āŽąāŽĩā¯āŽŽā¯", "date_after": "āŽ¤ā¯‡āŽ¤āŽŋ", "date_and_time": "āŽ¤ā¯‡āŽ¤āŽŋ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽ¨ā¯‡āŽ°āŽŽā¯", "date_before": "āŽŽā¯āŽŠā¯ āŽ¤ā¯‡āŽ¤āŽŋ", + "date_format": "E, lll d, āŽ’āŽ¯ā¯ â€ĸ h: mm a", "date_of_birth_saved": "āŽĒāŽŋāŽąāŽ¨ā¯āŽ¤ āŽ¤ā¯‡āŽ¤āŽŋ āŽĩā¯†āŽąā¯āŽąāŽŋāŽ•āŽ°āŽŽāŽžāŽ• āŽšā¯‡āŽŽāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "date_range": "āŽ¤ā¯‡āŽ¤āŽŋ āŽĩāŽ°āŽŽā¯āŽĒ❁", "day": "āŽ¨āŽžāŽŗā¯", + "days": "āŽ¨āŽžāŽŸā¯āŽ•āŽŗā¯", "deduplicate_all": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ˆāŽ¯ā¯āŽŽā¯ āŽ•āŽ´āŽŋāŽ¤ā¯āŽ¤āŽ˛ā¯", + "deduplication_criteria_1": "āŽĒā¯ˆāŽŸā¯āŽŸā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽĒāŽŸ āŽ…āŽŗāŽĩ❁", + "deduplication_criteria_2": "EXIF āŽ¤āŽ°āŽĩāŽŋāŽŠā¯ āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ", + "deduplication_info": "āŽ•āŽ´āŽŋāŽ¤ā¯āŽ¤āŽ˛ā¯ āŽšā¯†āŽ¯ā¯āŽ¤āŽŋ", + "deduplication_info_description": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽ¤āŽžāŽŠāŽžāŽ• āŽŽā¯āŽŠā¯āŽŠā¯†āŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽšā¯ āŽšā¯†āŽ˛ā¯āŽ˛āŽĩā¯āŽŽā¯, āŽŽā¯ŠāŽ¤ā¯āŽ¤āŽŽāŽžāŽ• āŽ¨āŽ•āŽ˛ā¯āŽ•āŽŗā¯ˆ āŽ…āŽ•āŽąā¯āŽąāŽĩā¯āŽŽā¯, āŽ¨āŽžāŽ™ā¯āŽ•āŽŗā¯ āŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽŋāŽąā¯‹āŽŽā¯:", "default_locale": "āŽ‡āŽ¯āŽ˛ā¯āŽĒā¯āŽ¨āŽŋāŽ˛ā¯ˆ āŽ‡āŽŸāŽŽā¯", "default_locale_description": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ‰āŽ˛āŽžāŽĩāŽŋ āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽŋāŽŸāŽ¤ā¯āŽ¤āŽŋāŽŠā¯ āŽ…āŽŸāŽŋāŽĒā¯āŽĒāŽŸā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽĩāŽŸāŽŋāŽĩāŽŽā¯ˆāŽĒā¯āŽĒ❁ āŽ¤ā¯‡āŽ¤āŽŋāŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽŽāŽŖā¯āŽ•āŽŗā¯", "delete": "āŽ¨ā¯€āŽ•ā¯āŽ•ā¯", + "delete_action_confirmation_message": "āŽ‡āŽ¨ā¯āŽ¤ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆ āŽ¨ā¯€āŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž? āŽ‡āŽ¨ā¯āŽ¤ āŽ¨āŽŸāŽĩāŽŸāŽŋāŽ•ā¯āŽ•ā¯ˆ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆ āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽ¤ā¯āŽ¤āŽŋāŽŠā¯ āŽ•ā¯āŽĒā¯āŽĒā¯ˆāŽ•ā¯āŽ•ā¯ āŽ¨āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤ā¯āŽŽā¯, āŽŽā¯‡āŽ˛ā¯āŽŽā¯ āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽ…āŽ¤ā¯ˆ āŽ‰āŽŗā¯āŽ¨āŽžāŽŸā¯āŽŸāŽŋāŽ˛ā¯ āŽ¨ā¯€āŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒāŽŋāŽŠāŽžāŽ˛ā¯ āŽ•ā¯‡āŽŸā¯āŽ•ā¯āŽŽā¯", + "delete_action_prompt": "{count} āŽ¨ā¯€āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "delete_album": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤ā¯ˆ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯", "delete_api_key_prompt": "āŽ‡āŽ¨ā¯āŽ¤ āŽĒāŽ¨āŽŋāŽ‡ āŽĩāŽŋāŽšā¯ˆāŽ¯ā¯ˆ āŽ¨ā¯€āŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", + "delete_dialog_alert": "āŽ‡āŽ¨ā¯āŽ¤ āŽ‰āŽ°ā¯āŽĒā¯āŽĒāŽŸāŽŋāŽ•āŽŗā¯ āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯āŽšāŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯āŽŽā¯ āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽšāŽžāŽ¤āŽŠāŽ¤ā¯āŽ¤āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯āŽŽā¯ āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ¨ā¯€āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŽā¯", + "delete_dialog_alert_local": "āŽ‡āŽ¨ā¯āŽ¤ āŽ‰āŽ°ā¯āŽĒā¯āŽĒāŽŸāŽŋāŽ•āŽŗā¯ āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽšāŽžāŽ¤āŽŠāŽ¤ā¯āŽ¤āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ…āŽ•āŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŽā¯, āŽ†āŽŠāŽžāŽ˛ā¯ āŽ‡āŽŠā¯āŽŠā¯āŽŽā¯ āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯ āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•ā¯āŽŽā¯", + "delete_dialog_alert_local_non_backed_up": "āŽšāŽŋāŽ˛ āŽ‰āŽ°ā¯āŽĒā¯āŽĒāŽŸāŽŋāŽ•āŽŗā¯ āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯ āŽĩāŽ°ā¯ˆ āŽ†āŽ¤āŽ°āŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸāŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ, āŽŽā¯‡āŽ˛ā¯āŽŽā¯ āŽ…āŽĩ❈ āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽšāŽžāŽ¤āŽŠāŽ¤ā¯āŽ¤āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ…āŽ•āŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŽā¯", + "delete_dialog_alert_remote": "āŽ‡āŽ¨ā¯āŽ¤ āŽ‰āŽ°ā¯āŽĒā¯āŽĒāŽŸāŽŋāŽ•āŽŗā¯ āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯ āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽ¤ā¯āŽ¤āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ¨ā¯€āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŽā¯", + "delete_dialog_ok_force": "āŽŽāŽĒā¯āŽĒāŽŸāŽŋāŽ¯ā¯āŽŽā¯ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯", + "delete_dialog_title": "āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ¨ā¯€āŽ•ā¯āŽ•ā¯", "delete_duplicates_confirmation": "āŽ‡āŽ¨ā¯āŽ¤ āŽ¨āŽ•āŽ˛ā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ¨ā¯€āŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", + "delete_face": "āŽŽā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯", "delete_key": "āŽĩāŽŋāŽšā¯ˆāŽ¯ā¯ˆ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯", "delete_library": "āŽ¨ā¯‚āŽ˛āŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯", "delete_link": "āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❈ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯", + "delete_local_action_prompt": "{count} āŽ‰āŽŗā¯āŽ¨āŽžāŽŸā¯āŽŸāŽŋāŽ˛ā¯ āŽ¨ā¯€āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "delete_local_dialog_ok_backed_up_only": "āŽ¨ā¯€āŽ•ā¯āŽ•ā¯ āŽŽāŽŸā¯āŽŸā¯āŽŽā¯‡ āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋ āŽŽāŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "delete_local_dialog_ok_force": "āŽŽāŽĒā¯āŽĒāŽŸāŽŋāŽ¯ā¯āŽŽā¯ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯", "delete_others": "āŽŽāŽąā¯āŽąāŽĩāŽ°ā¯āŽ•āŽŗā¯ˆ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯", + "delete_permanently": "āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ¨ā¯€āŽ•ā¯āŽ•ā¯", + "delete_permanently_action_prompt": "{count} āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ¨ā¯€āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "delete_shared_link": "āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❈ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯", + "delete_shared_link_dialog_title": "āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❈ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯", "delete_tag": "āŽ•ā¯āŽąāŽŋāŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯", "delete_tag_confirmation_prompt": "{tagName} āŽ•ā¯āŽąāŽŋāŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽ¨ā¯€āŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", "delete_user": "āŽĒāŽ¯āŽŠāŽ°ā¯ˆ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯", "deleted_shared_link": "āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❈ āŽ¨ā¯€āŽ•ā¯āŽ•āŽŋāŽ¯āŽ¤ā¯", "deletes_missing_assets": "āŽĩāŽŸā¯āŽŸāŽŋāŽ˛ā¯ āŽ‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ•āŽžāŽŖāŽžāŽŽāŽ˛ā¯ āŽĒā¯‹āŽŠ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯", "description": "āŽĩāŽŋāŽĩāŽ°āŽŽā¯", + "description_input_hint_text": "āŽĩāŽŋāŽŗāŽ•ā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆāŽšā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯ ...", + "description_input_submit_error": "āŽĩāŽŋāŽŗāŽ•ā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽĒā¯āŽĒāŽ¤āŽŋāŽ˛ā¯ āŽĒāŽŋāŽ´ā¯ˆ, āŽŽā¯‡āŽ˛ā¯āŽŽā¯ āŽĩāŽŋāŽĩāŽ°āŽ™ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽĒāŽ¤āŽŋāŽĩā¯ˆāŽšā¯ āŽšāŽ°āŽŋāŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "deselect_all": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¤ā¯‡āŽ°ā¯āŽĩ❁ āŽšā¯†āŽ¯ā¯āŽ¯ā¯āŽ™ā¯āŽ•āŽŗā¯", "details": "āŽĩāŽŋāŽĩāŽ°āŽ™ā¯āŽ•āŽŗā¯", "direction": "āŽ¤āŽŋāŽšā¯ˆ", "disabled": "āŽŽā¯āŽŸāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "disallow_edits": "āŽ¤āŽŋāŽ°ā¯āŽ¤ā¯āŽ¤āŽ™ā¯āŽ•āŽŗā¯ˆ āŽ…āŽŠā¯āŽŽāŽ¤āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "discord": "āŽŽā¯āŽ°āŽŖā¯āŽĒāŽžāŽŸā¯", "discover": "āŽ•āŽŖā¯āŽŸā¯āŽĒāŽŋāŽŸāŽŋ", + "discovered_devices": "āŽ•āŽŖā¯āŽŸā¯āŽĒāŽŋāŽŸāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽšāŽžāŽ¤āŽŠāŽ™ā¯āŽ•āŽŗā¯", "dismiss_all_errors": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ āŽĒāŽŋāŽ´ā¯ˆāŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¨āŽŋāŽ°āŽžāŽ•āŽ°āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "dismiss_error": "āŽĒāŽŋāŽ´ā¯ˆāŽ¯ā¯ˆ āŽ¨āŽŋāŽ°āŽžāŽ•āŽ°āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "display_options": "āŽ•āŽžāŽŸā¯āŽšāŽŋ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯", @@ -549,12 +834,26 @@ "documentation": "āŽ†āŽĩāŽŖāŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽ¤āŽ˛ā¯", "done": "āŽŽā¯āŽŸāŽŋāŽ¨ā¯āŽ¤āŽ¤ā¯", "download": "āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•āŽŽā¯", + "download_action_prompt": "āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•āŽŽā¯ {count} āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯", + "download_canceled": "āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•āŽŽā¯ āŽ°āŽ¤ā¯āŽ¤ā¯ āŽšā¯†āŽ¯ā¯āŽ¯āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "download_complete": "āŽŽā¯āŽ´ā¯āŽŽā¯ˆāŽ¯āŽžāŽŠ āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•āŽŽā¯", + "download_enqueue": "Enqueuted āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•", + "download_error": "āŽĒāŽŋāŽ´ā¯ˆāŽ¯ā¯ˆāŽĒā¯ āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "download_failed": "āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•āŽŽā¯ āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋāŽ¯āŽŸā¯ˆāŽ¨ā¯āŽ¤āŽ¤ā¯", + "download_finished": "āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•āŽŽā¯ āŽŽā¯āŽŸāŽŋāŽ¨ā¯āŽ¤āŽ¤ā¯", "download_include_embedded_motion_videos": "āŽ‰āŽŸā¯āŽĒā¯ŠāŽ¤āŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯", "download_include_embedded_motion_videos_description": "āŽŽā¯‹āŽšāŽŠā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽ‰āŽŸā¯āŽĒā¯ŠāŽ¤āŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ˆ āŽ¤āŽŠāŽŋ āŽ•ā¯‹āŽĒā¯āŽĒāŽžāŽ• āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "download_notfound": "āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•āŽŽā¯ āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", + "download_paused": "āŽ‡āŽŸā¯ˆāŽ¨āŽŋāŽąā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "download_settings": "āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•āŽŽā¯", "download_settings_description": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•āŽŽā¯ āŽ¤ā¯ŠāŽŸāŽ°ā¯āŽĒāŽžāŽŠ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "download_started": "āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•āŽŽā¯ āŽ¤ā¯ŠāŽŸāŽ™ā¯āŽ•āŽŋāŽ¯āŽ¤ā¯", + "download_sucess": "āŽĩā¯†āŽąā¯āŽąāŽŋāŽ¯ā¯ˆāŽĒā¯ āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "download_sucess_android": "āŽŠāŽŸāŽ•āŽ™ā¯āŽ•āŽŗā¯ DCIM/IMMich āŽ•ā¯āŽ•ā¯ āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•āŽŽā¯ āŽšā¯†āŽ¯ā¯āŽ¯āŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗāŽŠ", + "download_waiting_to_retry": "āŽŽā¯€āŽŖā¯āŽŸā¯āŽŽā¯ āŽŽā¯āŽ¯āŽąā¯āŽšāŽŋāŽ•ā¯āŽ• āŽ•āŽžāŽ¤ā¯āŽ¤āŽŋāŽ°ā¯āŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯", "downloading": "āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯", "downloading_asset_filename": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•āŽŽā¯ {filename}", + "downloading_media": "āŽŠāŽŸāŽ•āŽ™ā¯āŽ•āŽŗā¯ˆāŽĒā¯ āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯", "drop_files_to_upload": "āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽą āŽŽāŽ™ā¯āŽ•ā¯āŽŽā¯ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽĩāŽŋāŽŸā¯āŽ™ā¯āŽ•āŽŗā¯", "duplicates": "āŽ¨āŽ•āŽ˛ā¯āŽ•āŽŗā¯", "duplicates_description": "āŽ’āŽĩā¯āŽĩā¯ŠāŽ°ā¯ āŽ•ā¯āŽ´ā¯āŽĩā¯ˆāŽ¯ā¯āŽŽā¯ āŽŽāŽ¨ā¯āŽ¤ āŽ¨āŽ•āŽ˛ā¯āŽ•āŽŗāŽŋāŽ˛ā¯āŽŽā¯ āŽ•ā¯āŽąāŽŋāŽĒā¯āŽĒāŽŋāŽŸā¯āŽĩāŽ¤āŽŠā¯ āŽŽā¯‚āŽ˛āŽŽā¯ āŽ¤ā¯€āŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", @@ -562,8 +861,14 @@ "edit": "āŽ¤ā¯†āŽžāŽ•ā¯", "edit_album": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤ā¯ˆāŽ¤ā¯ āŽ¤āŽŋāŽ°ā¯āŽ¤ā¯āŽ¤ā¯", "edit_avatar": "āŽ…āŽĩāŽ¤āŽžāŽ°āŽ¤ā¯āŽ¤ā¯ˆāŽ¤ā¯ āŽ¤āŽŋāŽ°ā¯āŽ¤ā¯āŽ¤ā¯", + "edit_birthday": "āŽĒāŽŋāŽąāŽ¨ā¯āŽ¤āŽ¨āŽžāŽŗā¯ˆāŽ¤ā¯ āŽ¤āŽŋāŽ°ā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", "edit_date": "āŽ¤ā¯‡āŽ¤āŽŋāŽ¯ā¯ˆāŽ¤ā¯ āŽ¤āŽŋāŽ°ā¯āŽ¤ā¯āŽ¤ā¯", "edit_date_and_time": "āŽ¤ā¯‡āŽ¤āŽŋ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽ¨ā¯‡āŽ°āŽ¤ā¯āŽ¤ā¯ˆāŽ¤ā¯ āŽ¤āŽŋāŽ°ā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", + "edit_date_and_time_action_prompt": "{count} āŽ¤ā¯‡āŽ¤āŽŋ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽ¨ā¯‡āŽ°āŽŽā¯ āŽ¤āŽŋāŽ°ā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "edit_date_and_time_by_offset": "āŽ†āŽƒāŽĒā¯āŽšā¯†āŽŸā¯ āŽŽā¯‚āŽ˛āŽŽā¯ āŽ¤ā¯‡āŽ¤āŽŋāŽ¯ā¯ˆ āŽŽāŽžāŽąā¯āŽąāŽĩā¯āŽŽā¯", + "edit_date_and_time_by_offset_interval": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ¤ā¯‡āŽ¤āŽŋ āŽĩāŽ°āŽŽā¯āŽĒ❁: {from} - {to}", + "edit_description": "āŽĩāŽŋāŽŗāŽ•ā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆāŽ¤ā¯ āŽ¤āŽŋāŽ°ā¯āŽ¤ā¯āŽ¤ā¯", + "edit_description_prompt": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽĩāŽŋāŽŗāŽ•ā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯:", "edit_exclusion_pattern": "āŽĩāŽŋāŽ˛āŽ•ā¯āŽ•ā¯ āŽŽā¯āŽąā¯ˆāŽ¯ā¯ˆāŽ¤ā¯ āŽ¤āŽŋāŽ°ā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", "edit_faces": "āŽŽā¯āŽ•āŽ™ā¯āŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤āŽŋāŽ°ā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", "edit_import_path": "āŽ‡āŽąāŽ•ā¯āŽ•ā¯āŽŽāŽ¤āŽŋ āŽĒāŽžāŽ¤ā¯ˆāŽ¯ā¯ˆāŽ¤ā¯ āŽ¤āŽŋāŽ°ā¯āŽ¤ā¯āŽ¤ā¯", @@ -571,6 +876,8 @@ "edit_key": "āŽ¤āŽŋāŽąāŽŠā¯ˆāŽ¤ā¯ āŽ¤āŽŋāŽ°ā¯āŽ¤ā¯āŽ¤ā¯", "edit_link": "āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒā¯ˆāŽ¤ā¯ āŽ¤āŽŋāŽ°ā¯āŽ¤ā¯āŽ¤ā¯", "edit_location": "āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽŋāŽŸāŽ¤ā¯āŽ¤ā¯ˆāŽ¤ā¯ āŽ¤āŽŋāŽ°ā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", + "edit_location_action_prompt": "{count} āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽŋāŽŸāŽŽā¯ āŽ¤āŽŋāŽ°ā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "edit_location_dialog_title": "āŽ‡āŽŸāŽŽā¯", "edit_name": "āŽĒā¯†āŽ¯āŽ°ā¯ˆāŽ¤ā¯ āŽ¤āŽŋāŽ°ā¯āŽ¤ā¯āŽ¤ā¯", "edit_people": "āŽŽāŽ•ā¯āŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤āŽŋāŽ°ā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", "edit_tag": "āŽ•ā¯āŽąāŽŋāŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆāŽ¤ā¯ āŽ¤āŽŋāŽ°ā¯āŽ¤ā¯āŽ¤ā¯", @@ -583,21 +890,35 @@ "editor_crop_tool_h2_aspect_ratios": "āŽ…āŽŽā¯āŽš āŽĩāŽŋāŽ•āŽŋāŽ¤āŽ™ā¯āŽ•āŽŗā¯", "editor_crop_tool_h2_rotation": "āŽšā¯āŽ´āŽąā¯āŽšāŽŋ", "email": "āŽŽāŽŋāŽŠā¯āŽŠāŽžā¯āŽšāŽ˛ā¯", + "email_notifications": "āŽŽāŽŋāŽŠā¯āŽŠāŽžā¯āŽšāŽ˛ā¯ āŽ…āŽąāŽŋāŽĩāŽŋāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", + "empty_folder": "āŽ‡āŽ¨ā¯āŽ¤ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆ āŽ•āŽžāŽ˛āŽŋāŽ¯āŽžāŽ• āŽ‰āŽŗā¯āŽŗāŽ¤ā¯", "empty_trash": "āŽĩā¯†āŽąā¯āŽąā¯ āŽ•ā¯āŽĒā¯āŽĒ❈", "empty_trash_confirmation": "āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽ•ā¯āŽĒā¯āŽĒā¯ˆāŽ•āŽŗā¯ˆ āŽĩā¯†āŽąā¯āŽŽā¯ˆ āŽšā¯†āŽ¯ā¯āŽ¯ āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž? āŽ‡āŽ¤ā¯ āŽ•ā¯āŽĒā¯āŽĒā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽ‰āŽŗā¯āŽŗ āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯āŽšāŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ…āŽ•āŽąā¯āŽąā¯āŽŽā¯.\n āŽ‡āŽ¨ā¯āŽ¤ āŽšā¯†āŽ¯āŽ˛ā¯ˆ āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽšā¯†āŽ¯āŽ˛ā¯āŽ¤āŽĩāŽŋāŽ°ā¯āŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯!", "enable": "āŽ‡āŽ¯āŽ•ā¯āŽ•ā¯", + "enable_backup": "āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋāŽ¯ā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "enable_biometric_auth_description": "āŽĒāŽ¯ā¯‹āŽŽā¯†āŽŸā¯āŽ°āŽŋāŽ•ā¯ āŽ…āŽ™ā¯āŽ•ā¯€āŽ•āŽžāŽ°āŽ¤ā¯āŽ¤ā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ• āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽŽā¯āŽŗā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ˆ āŽ‰āŽŗā¯āŽŗāŽŋāŽŸāŽĩā¯āŽŽā¯", "enabled": "āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "end_date": "āŽ‡āŽąā¯āŽ¤āŽŋ āŽ¤ā¯‡āŽ¤āŽŋ", + "enqueued": "Enqueuted", + "enter_wifi_name": "āŽĩā¯ˆāŽƒāŽĒ❈ āŽĒā¯†āŽ¯āŽ°ā¯ˆ āŽ‰āŽŗā¯āŽŗāŽŋāŽŸāŽĩā¯āŽŽā¯", + "enter_your_pin_code": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽŽā¯āŽŗā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ˆ āŽ‰āŽŗā¯āŽŗāŽŋāŽŸāŽĩā¯āŽŽā¯", + "enter_your_pin_code_subtitle": "āŽĒā¯‚āŽŸā¯āŽŸāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆāŽ¯ā¯ˆ āŽ…āŽŖā¯āŽ• āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽŽā¯āŽŗā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ˆ āŽ‰āŽŗā¯āŽŗāŽŋāŽŸāŽĩā¯āŽŽā¯", "error": "āŽĒāŽŋāŽ´ā¯ˆ", + "error_change_sort_album": "āŽ†āŽ˛ā¯āŽĒāŽŽā¯ āŽĩāŽ°āŽŋāŽšā¯ˆ āŽĩāŽ°āŽŋāŽšā¯ˆāŽ¯ā¯ˆ āŽŽāŽžāŽąā¯āŽąāŽ¤ā¯ āŽ¤āŽĩāŽąāŽŋāŽĩāŽŋāŽŸā¯āŽŸāŽ¤ā¯", + "error_delete_face": "āŽšā¯ŠāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽŽā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯āŽĩāŽ¤āŽŋāŽ˛ā¯ āŽĒāŽŋāŽ´ā¯ˆ", + "error_getting_places": "āŽ‡āŽŸāŽ™ā¯āŽ•āŽŗā¯ˆāŽĒā¯ āŽĒā¯†āŽąā¯āŽĩāŽ¤āŽŋāŽ˛ā¯ āŽĒāŽŋāŽ´ā¯ˆ", "error_loading_image": "āŽĒāŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽāŽąā¯āŽąā¯āŽĩāŽ¤āŽŋāŽ˛ā¯ āŽĒāŽŋāŽ´ā¯ˆ", + "error_loading_partners": "āŽ•ā¯‚āŽŸā¯āŽŸāŽžāŽŗāŽ°ā¯āŽ•āŽŗā¯ˆ āŽāŽąā¯āŽąā¯āŽĩāŽ¤āŽŋāŽ˛ā¯ āŽĒāŽŋāŽ´ā¯ˆ: {error}", + "error_saving_image": "āŽĒāŽŋāŽ´ā¯ˆ: {error}", + "error_tag_face_bounding_box": "āŽŽā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽ•ā¯āŽąāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯ āŽĒāŽŋāŽ´ā¯ˆ - āŽŽāŽ˛ā¯āŽ˛ā¯ˆ āŽĒā¯†āŽŸā¯āŽŸāŽŋ āŽ†āŽ¯āŽ¤ā¯āŽ¤ā¯ŠāŽ˛ā¯ˆāŽĩā¯āŽ•āŽŗā¯ˆāŽĒā¯ āŽĒā¯†āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", "error_title": "āŽĒāŽŋāŽ´ā¯ˆ - āŽāŽ¤ā¯‹ āŽ¤āŽĩāŽąā¯ āŽ¨āŽŸāŽ¨ā¯āŽ¤āŽ¤ā¯", "errors": { "cannot_navigate_next_asset": "āŽ…āŽŸā¯āŽ¤ā¯āŽ¤ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•ā¯ āŽšā¯†āŽ˛ā¯āŽ˛ āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", "cannot_navigate_previous_asset": "āŽŽā¯āŽ¨ā¯āŽ¤ā¯ˆāŽ¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•ā¯ āŽšā¯†āŽ˛ā¯āŽ˛ āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", "cant_apply_changes": "āŽŽāŽžāŽąā¯āŽąāŽ™ā¯āŽ•āŽŗā¯ˆāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", - "cant_change_activity": "{āŽšā¯†āŽ¯āŽ˛ā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯, āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯, āŽ‰āŽŖā¯āŽŽā¯ˆ {disable} āŽĒāŽŋāŽą {enable}} āŽšā¯†āŽ¯āŽ˛ā¯āŽĒāŽžāŽŸā¯", + "cant_change_activity": "āŽšā¯†āŽ¯āŽ˛ā¯āŽĒāŽžāŽŸā¯āŽŸā¯ˆ {enabled, select, true {āŽŽā¯āŽŸāŽ•ā¯āŽ•} other {āŽ‡āŽ¯āŽ•ā¯āŽ•}} āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", "cant_change_asset_favorite": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•ā¯ āŽĒāŽŋāŽŸāŽŋāŽ¤ā¯āŽ¤āŽ¤ā¯ˆ āŽŽāŽžāŽąā¯āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", - "cant_change_metadata_assets_count": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} āŽĒāŽŋāŽą {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}} āŽ‡āŽŠā¯ āŽŽā¯†āŽŸā¯āŽŸāŽžāŽŸā¯‡āŽŸā¯āŽŸāŽžāŽĩ❈ āŽŽāŽžāŽąā¯āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", + "cant_change_metadata_assets_count": "{count, plural, one {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} other {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}}āŽ‡āŽŠā¯ āŽŽā¯€āŽŗā¯āŽ¤āŽ°āŽĩ❈ āŽŽāŽžāŽąā¯āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", "cant_get_faces": "āŽŽā¯āŽ•āŽ™ā¯āŽ•āŽŗā¯ˆāŽĒā¯ āŽĒā¯†āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", "cant_get_number_of_comments": "āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤ā¯āŽ•āŽŗāŽŋāŽŠā¯ āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆāŽ¯ā¯ˆāŽĒā¯ āŽĒā¯†āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", "cant_search_people": "āŽŽāŽ•ā¯āŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽŸ āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", @@ -617,26 +938,31 @@ "failed_to_keep_this_delete_others": "āŽ‡āŽ¨ā¯āŽ¤ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆ āŽĩā¯ˆāŽ¤ā¯āŽ¤ā¯ āŽŽāŽąā¯āŽą āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯āŽĩāŽ¤āŽŋāŽ˛ā¯ āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋ", "failed_to_load_asset": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆ āŽāŽąā¯āŽąā¯āŽĩāŽ¤āŽŋāŽ˛ā¯ āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋ", "failed_to_load_assets": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽāŽąā¯āŽąā¯āŽĩāŽ¤āŽŋāŽ˛ā¯ āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋ", + "failed_to_load_notifications": "āŽ…āŽąāŽŋāŽĩāŽŋāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽāŽąā¯āŽąā¯āŽĩāŽ¤āŽŋāŽ˛ā¯ āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋ", "failed_to_load_people": "āŽŽāŽ•ā¯āŽ•āŽŗā¯ˆ āŽāŽąā¯āŽąā¯āŽĩāŽ¤āŽŋāŽ˛ā¯ āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋ", "failed_to_remove_product_key": "āŽ¤āŽ¯āŽžāŽ°āŽŋāŽĒā¯āŽĒ❁ āŽĩāŽŋāŽšā¯ˆāŽ¯ā¯ˆ āŽ…āŽ•āŽąā¯āŽąā¯āŽĩāŽ¤āŽŋāŽ˛ā¯ āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋ", + "failed_to_reset_pin_code": "āŽŽā¯āŽŗā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ˆ āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆāŽ•ā¯āŽ•āŽ¤ā¯ āŽ¤āŽĩāŽąāŽŋāŽĩāŽŋāŽŸā¯āŽŸāŽ¤ā¯", "failed_to_stack_assets": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽ…āŽŸā¯āŽ•ā¯āŽ•āŽŋ āŽĩ❈āŽĒā¯āŽĒāŽ¤āŽŋāŽ˛ā¯ āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋ", "failed_to_unstack_assets": "āŽ…āŽŠā¯-āŽšā¯āŽŸāŽžāŽ•ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋāŽ¯ā¯āŽąā¯āŽąāŽ¤ā¯", + "failed_to_update_notification_status": "āŽ…āŽąāŽŋāŽĩāŽŋāŽĒā¯āŽĒ❁ āŽ¨āŽŋāŽ˛ā¯ˆāŽ¯ā¯ˆāŽĒā¯ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽ¤ā¯ āŽ¤āŽĩāŽąāŽŋāŽĩāŽŋāŽŸā¯āŽŸāŽ¤ā¯", "import_path_already_exists": "āŽ‡āŽ¨ā¯āŽ¤ āŽ‡āŽąāŽ•ā¯āŽ•ā¯āŽŽāŽ¤āŽŋ āŽĒāŽžāŽ¤ā¯ˆ āŽāŽąā¯āŽ•āŽŠāŽĩ❇ āŽ‰āŽŗā¯āŽŗāŽ¤ā¯.", "incorrect_email_or_password": "āŽ¤āŽĩāŽąāŽžāŽŠ āŽŽāŽŋāŽŠā¯āŽŠāŽžā¯āŽšāŽ˛ā¯ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯", - "paths_validation_failed": "{āŽĒāŽžāŽ¤ā¯ˆāŽ•āŽŗā¯, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽĒāŽžāŽ¤ā¯ˆ} āŽŽāŽąā¯āŽą {# āŽĒāŽžāŽ¤ā¯ˆāŽ•āŽŗā¯}} āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋāŽ¯ā¯āŽąā¯āŽą āŽšāŽ°āŽŋāŽĒāŽžāŽ°ā¯āŽĒā¯āŽĒ❁", + "paths_validation_failed": "āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋāŽ¯ā¯āŽąā¯āŽą āŽšāŽ°āŽŋāŽĒāŽžāŽ°ā¯āŽĒā¯āŽĒ❁ {paths, plural, one {# āŽĒāŽžāŽ¤ā¯ˆ} other {# āŽĒāŽžāŽ¤ā¯ˆāŽ•āŽŗā¯}}", "profile_picture_transparent_pixels": "āŽšā¯āŽ¯āŽĩāŽŋāŽĩāŽ°āŽĒā¯ āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽĩā¯†āŽŗāŽŋāŽĒā¯āŽĒāŽŸā¯ˆāŽ¯āŽžāŽŠ āŽĒāŽŸāŽĒā¯āŽĒā¯āŽŗā¯āŽŗāŽŋāŽ•āŽŗā¯ āŽ‡āŽ°ā¯āŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯. āŽ¤āŽ¯āŽĩā¯āŽšā¯†āŽ¯ā¯āŽ¤ā¯ āŽĒā¯†āŽ°āŽŋāŽ¤āŽžāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯/āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽĒāŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽ¨āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯.", "quota_higher_than_disk_size": "āŽĩāŽŸā¯āŽŸā¯ āŽ…āŽŗāŽĩ❈ āŽĩāŽŋāŽŸ āŽ…āŽ¤āŽŋāŽ•āŽŽāŽžāŽ• āŽ’āŽ¤ā¯āŽ•ā¯āŽ•ā¯€āŽŸā¯āŽŸā¯ˆ āŽ…āŽŽā¯ˆāŽ¤ā¯āŽ¤ā¯āŽŗā¯āŽŗā¯€āŽ°ā¯āŽ•āŽŗā¯", + "something_went_wrong": "āŽāŽ¤ā¯‹ āŽ¤āŽĩāŽąā¯ āŽ¨āŽŸāŽ¨ā¯āŽ¤āŽ¤ā¯", "unable_to_add_album_users": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽĒāŽ¯āŽŠāŽ°ā¯āŽ•āŽŗā¯ˆāŽšā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "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": "{āŽ•āŽžāŽĒā¯āŽĒāŽ•āŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ, āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯, āŽ‰āŽŖā¯āŽŽā¯ˆāŽ¯āŽžāŽ•āŽĩā¯āŽŽā¯} āŽĒāŽŋāŽą {remove asset from}}} āŽ•āŽžāŽĒā¯āŽĒāŽ•āŽ¤ā¯āŽ¤āŽŋāŽąā¯āŽ•ā¯āŽšā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", - "unable_to_add_remove_favorites": "{āŽĒāŽŋāŽŸāŽŋāŽ¤ā¯āŽ¤, āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯, āŽ‰āŽŖā¯āŽŽā¯ˆāŽ¯āŽžāŽ•āŽĩā¯āŽŽā¯}}} āŽĒāŽŋāŽŸāŽŋāŽ¤ā¯āŽ¤āŽĩā¯ˆāŽ•āŽŗāŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆ āŽ…āŽ•āŽąā¯āŽąā¯", - "unable_to_archive_unarchive": "{āŽ•āŽžāŽĒā¯āŽĒāŽ•āŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ, āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ, āŽ‰āŽŖā¯āŽŽā¯ˆ {archive} āŽĒāŽŋāŽą {unarchive}}", + "unable_to_add_remove_archive": "āŽ•āŽžāŽĒā¯āŽĒāŽ•āŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ {archived, select, true {āŽ‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆ āŽ…āŽ•āŽąā¯āŽą} other {āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆāŽšā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•}} āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", + "unable_to_add_remove_favorites": "āŽĒāŽŋāŽŸāŽŋāŽ¤ā¯āŽ¤āŽĩā¯ˆāŽ¯āŽŋāŽ˛ā¯ {āŽĒāŽŋāŽŸāŽŋāŽ¤ā¯āŽ¤āŽ¤ā¯, āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯, āŽ‰āŽŖā¯āŽŽā¯ˆ {āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆāŽšā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•} āŽŽāŽąā¯āŽą {āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆ āŽ…āŽ•āŽąā¯āŽą}} āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", + "unable_to_archive_unarchive": "{āŽ•āŽžāŽĒā¯āŽĒāŽ•āŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ, āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯, āŽ‰āŽŖā¯āŽŽā¯ˆ {āŽ•āŽžāŽĒā¯āŽĒāŽ•āŽŽā¯} āŽŽāŽąā¯āŽąāŽĩ❈ {āŽ•āŽžāŽĒā¯āŽĒāŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽ…āŽ•āŽąā¯āŽąā¯}}", "unable_to_change_album_user_role": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽŠā¯ āŽĒāŽ¯āŽŠāŽ°āŽŋāŽŠā¯ āŽĒāŽžāŽ¤ā¯āŽ¤āŽŋāŽ°āŽ¤ā¯āŽ¤ā¯ˆ āŽŽāŽžāŽąā¯āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "unable_to_change_date": "āŽ¤ā¯‡āŽ¤āŽŋāŽ¯ā¯ˆ āŽŽāŽžāŽąā¯āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", + "unable_to_change_description": "āŽĩāŽŋāŽŗāŽ•ā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽŽāŽžāŽąā¯āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "unable_to_change_favorite": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•ā¯ āŽĒāŽŋāŽŸāŽŋāŽ¤ā¯āŽ¤āŽ¤ā¯ˆ āŽŽāŽžāŽąā¯āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "unable_to_change_location": "āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽŋāŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽŽāŽžāŽąā¯āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "unable_to_change_password": "āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽŽāŽžāŽąā¯āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", @@ -680,6 +1006,7 @@ "unable_to_remove_partner": "āŽ•ā¯‚āŽŸā¯āŽŸāŽžāŽŗāŽ°ā¯ˆ āŽ…āŽ•āŽąā¯āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "unable_to_remove_reaction": "āŽŽāŽ¤āŽŋāŽ°ā¯āŽĩāŽŋāŽŠā¯ˆāŽ¯ā¯ˆ āŽ…āŽ•āŽąā¯āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "unable_to_reset_password": "āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆāŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", + "unable_to_reset_pin_code": "āŽŽā¯āŽŗā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ˆ āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆāŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "unable_to_resolve_duplicate": "āŽ¨āŽ•āŽ˛ā¯ āŽ¤ā¯€āŽ°ā¯āŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "unable_to_restore_assets": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽŽā¯€āŽŸā¯āŽŸā¯†āŽŸā¯āŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "unable_to_restore_trash": "āŽ•ā¯āŽĒā¯āŽĒā¯ˆāŽ•āŽŗā¯ˆ āŽŽā¯€āŽŸā¯āŽŸā¯†āŽŸā¯āŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", @@ -707,8 +1034,19 @@ "unable_to_update_user": "āŽĒāŽ¯āŽŠāŽ°ā¯ˆāŽĒā¯ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "unable_to_upload_file": "āŽ•ā¯‹āŽĒā¯āŽĒ❈āŽĒā¯ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ" }, + "exif": "Exif", + "exif_bottom_sheet_description": "āŽĩāŽŋāŽŗāŽ•ā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆāŽšā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯ ...", + "exif_bottom_sheet_description_error": "āŽĩāŽŋāŽŗāŽ•ā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽĒā¯āŽĒāŽ¤āŽŋāŽ˛ā¯ āŽĒāŽŋāŽ´ā¯ˆ", + "exif_bottom_sheet_details": "āŽĩāŽŋāŽĩāŽ°āŽ™ā¯āŽ•āŽŗā¯", + "exif_bottom_sheet_location": "āŽ‡āŽŸāŽŽā¯", + "exif_bottom_sheet_people": "āŽŽāŽ•ā¯āŽ•āŽŗā¯", + "exif_bottom_sheet_person_add_person": "āŽĒā¯†āŽ¯āŽ°ā¯ˆāŽšā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "exit_slideshow": "āŽšā¯āŽ˛ā¯ˆāŽŸā¯āŽšā¯‹āŽĩāŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽĩā¯†āŽŗāŽŋāŽ¯ā¯‡āŽąāŽĩā¯āŽŽā¯", "expand_all": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ˆāŽ¯ā¯āŽŽā¯ āŽĩāŽŋāŽ°āŽŋāŽĩāŽžāŽ•ā¯āŽ•ā¯āŽ™ā¯āŽ•āŽŗā¯", + "experimental_settings_new_asset_list_subtitle": "āŽĩā¯‡āŽ˛ā¯ˆ āŽŽā¯āŽŠā¯āŽŠā¯‡āŽąā¯āŽąāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ‰āŽŗā¯āŽŗāŽ¤ā¯", + "experimental_settings_new_asset_list_title": "āŽšā¯‹āŽ¤āŽŠā¯ˆ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸ āŽ•āŽŸā¯āŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "experimental_settings_subtitle": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽšā¯ŠāŽ¨ā¯āŽ¤ āŽ†āŽĒāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯!", + "experimental_settings_title": "āŽšā¯‹āŽ¤āŽŠā¯ˆ", "expire_after": "āŽĒāŽŋāŽŠā¯āŽŠāŽ°ā¯ āŽ•āŽžāŽ˛āŽžāŽĩāŽ¤āŽŋāŽ¯āŽžāŽ•ā¯āŽ™ā¯āŽ•āŽŗā¯", "expired": "āŽ•āŽžāŽ˛āŽžāŽĩāŽ¤āŽŋāŽ¯āŽžāŽŠ", "expires_date": "{date} āŽ•āŽžāŽ˛āŽžāŽĩāŽ¤āŽŋāŽ¯āŽžāŽ•āŽŋāŽąāŽ¤ā¯", @@ -716,37 +1054,74 @@ "explorer": "āŽŽāŽ•ā¯āŽšā¯āŽĒā¯āŽŗā¯‹āŽ°āŽ°ā¯", "export": "āŽāŽąā¯āŽąā¯āŽŽāŽ¤āŽŋ", "export_as_json": "āŽšāŽžāŽ¤ā¯ŠāŽĒā¯ŠāŽ•ā¯ āŽ†āŽ• āŽāŽąā¯āŽąā¯āŽŽāŽ¤āŽŋ", + "export_database": "āŽāŽąā¯āŽąā¯āŽŽāŽ¤āŽŋ āŽ¤āŽ°āŽĩā¯āŽ¤ā¯āŽ¤āŽŗāŽŽā¯", + "export_database_description": "SQLITE āŽ¤āŽ°āŽĩā¯āŽ¤ā¯āŽ¤āŽŗāŽ¤ā¯āŽ¤ā¯ˆ āŽāŽąā¯āŽąā¯āŽŽāŽ¤āŽŋ āŽšā¯†āŽ¯ā¯āŽ¯ā¯āŽ™ā¯āŽ•āŽŗā¯", "extension": "āŽ¨ā¯€āŽŸā¯āŽŸāŽŋāŽĒā¯āŽĒ❁", "external": "āŽĩā¯†āŽŗāŽŋāŽĒā¯āŽĒā¯āŽąāŽŽā¯", "external_libraries": "āŽĩā¯†āŽŗāŽŋāŽĒā¯āŽĒā¯āŽą āŽ¨ā¯‚āŽ˛āŽ•āŽ™ā¯āŽ•āŽŗā¯", + "external_network": "āŽĩā¯†āŽŗāŽŋāŽĒā¯āŽĒā¯āŽą āŽĒāŽŋāŽŖā¯ˆāŽ¯āŽŽā¯", + "external_network_sheet_info": "āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽŽāŽžāŽŠ āŽĩā¯ˆāŽƒāŽĒ❈ āŽ¨ā¯†āŽŸā¯āŽĩā¯ŠāŽ°ā¯āŽ•ā¯āŽ•āŽŋāŽ˛ā¯ āŽ‡āŽ˛ā¯āŽ˛āŽžāŽ¤āŽĒā¯‹āŽ¤ā¯, āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯ āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽ¤ā¯āŽ¤ā¯āŽŸāŽŠā¯ āŽ•ā¯€āŽ´ā¯‡ āŽ‰āŽŗā¯āŽŗ āŽŽā¯āŽ•āŽĩāŽ°āŽŋ āŽ•āŽŗāŽŋāŽŠā¯ āŽŽā¯āŽ¤āŽ˛ā¯ āŽĩāŽ´āŽŋāŽ¯āŽžāŽ• āŽ‡āŽŖā¯ˆāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŽā¯, āŽ‡āŽ¤ā¯ āŽŽā¯‡āŽ˛ā¯‡ āŽ‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ•ā¯€āŽ´ā¯‡ āŽ¤ā¯ŠāŽŸāŽ™ā¯āŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯", "face_unassigned": "āŽ’āŽ¤ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸāŽžāŽ¤āŽ¤ā¯", + "failed": "āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋāŽ¯ā¯āŽąā¯āŽąāŽ¤ā¯", + "failed_to_authenticate": "āŽ…āŽ™ā¯āŽ•ā¯€āŽ•āŽ°āŽŋāŽ•ā¯āŽ•āŽ¤ā¯ āŽ¤āŽĩāŽąāŽŋāŽĩāŽŋāŽŸā¯āŽŸāŽ¤ā¯", "failed_to_load_assets": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽāŽąā¯āŽąā¯āŽĩāŽ¤āŽŋāŽ˛ā¯ āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋ", + "failed_to_load_folder": "āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆāŽ¯ā¯ˆ āŽāŽąā¯āŽąā¯āŽĩāŽ¤āŽŋāŽ˛ā¯ āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋ", "favorite": "āŽĒāŽŋāŽŸāŽŋāŽ¤ā¯āŽ¤", + "favorite_action_prompt": "{count} āŽĒāŽŋāŽŸāŽŋāŽ¤ā¯āŽ¤āŽĩā¯ˆāŽ•āŽŗāŽŋāŽ˛ā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "favorite_or_unfavorite_photo": "āŽĒāŽŋāŽŸāŽŋāŽ¤ā¯āŽ¤ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽšāŽžāŽ¤āŽ•āŽŽāŽąā¯āŽą āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽŽā¯", "favorites": "āŽĒāŽŋāŽŸāŽŋāŽ¤ā¯āŽ¤āŽĩ❈", + "favorites_page_no_favorites": "āŽĒāŽŋāŽŸāŽŋāŽ¤ā¯āŽ¤ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ āŽŽāŽ¤ā¯āŽĩā¯āŽŽā¯ āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "feature_photo_updated": "āŽ…āŽŽā¯āŽš āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽŽā¯ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "features": "āŽ¨āŽąā¯āŽĒā¯ŠāŽ°ā¯āŽ¤ā¯āŽ¤āŽ™ā¯āŽ•āŽŗā¯", + "features_in_development": "āŽĩāŽŗāŽ°ā¯āŽšā¯āŽšāŽŋāŽ¯āŽŋāŽ˛ā¯ āŽ¨āŽąā¯āŽĒā¯ŠāŽ°ā¯āŽ¤ā¯āŽ¤āŽ™ā¯āŽ•āŽŗā¯", "features_setting_description": "āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯āŽŸā¯ āŽ…āŽŽā¯āŽšāŽ™ā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "file_name": "āŽ•ā¯‹āŽĒā¯āŽĒ❁ āŽĒā¯†āŽ¯āŽ°ā¯", "file_name_or_extension": "āŽ•ā¯‹āŽĒā¯āŽĒ❁ āŽĒā¯†āŽ¯āŽ°ā¯ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽ¨ā¯€āŽŸā¯āŽŸāŽŋāŽĒā¯āŽĒ❁", "filename": "āŽ•ā¯‹āŽĒā¯āŽĒ❁āŽĒā¯āŽĒā¯†āŽ¯āŽ°ā¯", "filetype": "āŽĒā¯ˆāŽ˛ā¯āŽŸā¯ˆāŽĒā¯", + "filter": "āŽĩāŽŸāŽŋāŽĒā¯āŽĒāŽŋ", "filter_people": "āŽŽāŽ•ā¯āŽ•āŽŗā¯ˆ āŽĩāŽŸāŽŋāŽ•āŽŸā¯āŽŸāŽĩā¯āŽŽā¯", + "filter_places": "āŽ‡āŽŸāŽ™ā¯āŽ•āŽŗā¯ˆ āŽĩāŽŸāŽŋāŽ•āŽŸā¯āŽŸāŽĩā¯āŽŽā¯", "find_them_fast": "āŽ¤ā¯‡āŽŸāŽ˛ā¯āŽŸāŽŠā¯ āŽĒā¯†āŽ¯āŽ°āŽžāŽ˛ā¯ āŽĩā¯‡āŽ•āŽŽāŽžāŽ• āŽ…āŽĩāŽąā¯āŽąā¯ˆāŽ•ā¯ āŽ•āŽŖā¯āŽŸāŽąāŽŋāŽ¯āŽĩā¯āŽŽā¯", + "first": "āŽŽā¯āŽ¤āŽ˛ā¯", "fix_incorrect_match": "āŽ¤āŽĩāŽąāŽžāŽŠ āŽĒā¯‹āŽŸā¯āŽŸāŽŋāŽ¯ā¯ˆ āŽšāŽ°āŽŋāŽšā¯†āŽ¯ā¯āŽ¯āŽĩā¯āŽŽā¯", + "folder": "āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆ", + "folder_not_found": "āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆ āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "folders": "āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆāŽ•āŽŗā¯", "folders_feature_description": "āŽ•ā¯‹āŽĒā¯āŽĒ❁ āŽŽā¯āŽąā¯ˆāŽŽā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽ‰āŽŗā¯āŽŗ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•āŽžāŽŠ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆ āŽ•āŽžāŽŸā¯āŽšāŽŋāŽ¯ā¯ˆ āŽ‰āŽ˛āŽžāŽĩā¯āŽ¤āŽ˛ā¯", + "forgot_pin_code_question": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽŽā¯āŽŗā¯ āŽŽāŽąāŽ¨ā¯āŽ¤ā¯āŽĩāŽŋāŽŸā¯āŽŸā¯€āŽ°ā¯āŽ•āŽŗāŽž?", "forward": "āŽŽā¯āŽŠā¯āŽŠā¯‹āŽ•ā¯āŽ•āŽŋ", + "gcast_enabled": "āŽ•ā¯‚āŽ•āŽŋāŽŗā¯ āŽ¨āŽŸāŽŋāŽ•āŽ°ā¯āŽ•āŽŗā¯", + "gcast_enabled_description": "āŽ‡āŽ¨ā¯āŽ¤ āŽ¨āŽąā¯āŽĒā¯ŠāŽ°ā¯āŽ¤ā¯āŽ¤āŽŽā¯ āŽĩā¯‡āŽ˛ā¯ˆ āŽšā¯†āŽ¯ā¯āŽĩāŽ¤āŽąā¯āŽ•āŽžāŽ• Google āŽ‡āŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽĩā¯†āŽŗāŽŋāŽĒā¯āŽĒā¯āŽą āŽĩāŽŗāŽ™ā¯āŽ•āŽŗā¯ˆ āŽāŽąā¯āŽąā¯āŽ•āŽŋāŽąāŽ¤ā¯.", "general": "āŽĒā¯†āŽžāŽ¤ā¯", + "geolocation_instruction_location": "āŽ…āŽ¤āŽŠā¯ āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽŋāŽŸāŽ¤ā¯āŽ¤ā¯ˆāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ āŽšāŽŋ.āŽĒāŽŋ.āŽŽāŽšā¯ āŽ†āŽ¯āŽ¤ā¯āŽ¤ā¯ŠāŽ˛ā¯ˆāŽĩā¯āŽ•āŽŗā¯āŽŸāŽŠā¯ āŽ’āŽ°ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽšā¯ŠāŽŸā¯āŽ•ā¯āŽ•ā¯ āŽšā¯†āŽ¯ā¯āŽ• āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽĩāŽ°ā¯ˆāŽĒāŽŸāŽ¤ā¯āŽ¤āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ¨ā¯‡āŽ°āŽŸāŽŋāŽ¯āŽžāŽ• āŽ’āŽ°ā¯ āŽ‡āŽŸāŽ¤ā¯āŽ¤ā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "get_help": "āŽ‰āŽ¤āŽĩāŽŋ āŽĒā¯†āŽąā¯", + "get_wifiname_error": "āŽĩā¯ˆāŽƒāŽĒ❈ āŽĒā¯†āŽ¯āŽ°ā¯ˆāŽĒā¯ āŽĒā¯†āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ. āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽ¤ā¯‡āŽĩā¯ˆāŽ¯āŽžāŽŠ āŽ…āŽŠā¯āŽŽāŽ¤āŽŋāŽ•āŽŗā¯ˆ āŽĩāŽ´āŽ™ā¯āŽ•āŽŋāŽ¯ā¯āŽŗā¯āŽŗā¯€āŽ°ā¯āŽ•āŽŗā¯ āŽŽāŽŠā¯āŽĒāŽ¤ā¯ˆ āŽ‰āŽąā¯āŽ¤āŽŋāŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽŋāŽ•ā¯ āŽ•ā¯ŠāŽŗā¯āŽŗā¯āŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĩā¯ˆāŽƒāŽĒ❈ āŽ¨ā¯†āŽŸā¯āŽĩā¯ŠāŽ°ā¯āŽ•ā¯āŽ•ā¯āŽŸāŽŠā¯ āŽ‡āŽŖā¯ˆāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗā¯€āŽ°ā¯āŽ•āŽŗā¯", "getting_started": "āŽ¤ā¯ŠāŽŸāŽ™ā¯āŽ•ā¯āŽ¤āŽ˛ā¯", "go_back": "āŽ¤āŽŋāŽ°ā¯āŽŽā¯āŽĒāŽŋāŽšā¯ āŽšā¯†āŽ˛ā¯āŽ˛ā¯āŽ™ā¯āŽ•āŽŗā¯", + "go_to_folder": "āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆāŽ•ā¯āŽ•ā¯āŽšā¯ āŽšā¯†āŽ˛ā¯āŽ˛ā¯āŽ™ā¯āŽ•āŽŗā¯", "go_to_search": "āŽ¤ā¯‡āŽŸāŽšā¯ āŽšā¯†āŽ˛ā¯āŽ˛āŽĩā¯āŽŽā¯", + "gps": "āŽ‰āŽ˛āŽ• āŽ‡āŽŸāŽŽā¯ āŽ•āŽžāŽŸā¯āŽŸā¯āŽŽā¯ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒ❁ (āŽ‡āŽŸāŽŽā¯ āŽ•āŽžāŽŸā¯āŽŸāŽŋ)", + "gps_missing": "āŽšāŽŋ.āŽĒāŽŋ.āŽŽāŽšā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ", + "grant_permission": "āŽ‡āŽšā¯ˆāŽĩ❁ āŽĩāŽ´āŽ™ā¯āŽ•āŽĩā¯āŽŽā¯", "group_albums_by": "āŽ•ā¯āŽ´ā¯ āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯ āŽĩāŽ´āŽ™ā¯āŽ•āŽŋāŽ¯āŽĩāŽ°ā¯ ...", + "group_country": "āŽ¨āŽžāŽŸā¯ āŽŽā¯‚āŽ˛āŽŽā¯ āŽ•ā¯āŽ´ā¯", "group_no": "āŽ•ā¯āŽ´ā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ", "group_owner": "āŽ‰āŽ°āŽŋāŽŽā¯ˆāŽ¯āŽžāŽŗāŽ°āŽžāŽ˛ā¯ āŽ•ā¯āŽ´ā¯", + "group_places_by": "āŽ•ā¯āŽ´ā¯ āŽ‡āŽŸāŽ™ā¯āŽ•āŽŗā¯ ...", "group_year": "āŽ†āŽŖā¯āŽŸā¯āŽ•ā¯āŽ•ā¯ āŽ•ā¯āŽ´ā¯", + "haptic_feedback_switch": "āŽ†āŽĒā¯āŽŸāŽŋāŽ•ā¯ āŽĒāŽŋāŽŠā¯āŽŠā¯‚āŽŸā¯āŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "haptic_feedback_title": "āŽ†āŽĒā¯āŽŸāŽŋāŽ•ā¯ āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤ā¯", "has_quota": "āŽ’āŽ¤ā¯āŽ•ā¯āŽ•ā¯€āŽŸā¯ āŽ‰āŽŗā¯āŽŗāŽ¤ā¯", + "hash_asset": "āŽ†āŽšā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯", + "hashed_assets": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯", + "hashing": "āŽāŽšāŽŋāŽ™ā¯", + "header_settings_add_header_tip": "āŽ¤āŽ˛ā¯ˆāŽĒā¯āŽĒā¯āŽšā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "header_settings_field_validator_msg": "āŽŽāŽ¤āŽŋāŽĒā¯āŽĒ❁ āŽ•āŽžāŽ˛āŽŋāŽ¯āŽžāŽ• āŽ‡āŽ°ā¯āŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", + "header_settings_header_name_input": "āŽ¤āŽ˛ā¯ˆāŽĒā¯āŽĒ❁ āŽĒā¯†āŽ¯āŽ°ā¯", + "header_settings_header_value_input": "āŽ¤āŽ˛ā¯ˆāŽĒā¯āŽĒ❁ āŽŽāŽ¤āŽŋāŽĒā¯āŽĒ❁", + "headers_settings_tile_subtitle": "āŽ’āŽĩā¯āŽĩā¯ŠāŽ°ā¯ āŽĒāŽŋāŽŖā¯ˆāŽ¯ āŽ•ā¯‹āŽ°āŽŋāŽ•ā¯āŽ•ā¯ˆāŽ¯ā¯āŽŸāŽŠā¯āŽŽā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯ āŽ…āŽŠā¯āŽĒā¯āŽĒ āŽĩā¯‡āŽŖā¯āŽŸāŽŋāŽ¯ āŽĒāŽ¤āŽŋāŽ˛āŽžāŽŗā¯ āŽ¤āŽ˛ā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽĩāŽ°ā¯ˆāŽ¯āŽąā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "headers_settings_tile_title": "āŽ¤āŽŠāŽŋāŽĒā¯āŽĒāŽ¯āŽŠā¯ āŽĒāŽ¤āŽŋāŽ˛āŽžāŽŗā¯ āŽ¤āŽ˛ā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", "hi_user": "āŽ†āŽ¯ā¯ {name} ({email})", "hide_all_people": "āŽŽāŽ˛ā¯āŽ˛āŽž āŽŽāŽ•ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽŽāŽąā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "hide_gallery": "āŽ•ā¯‡āŽ˛āŽ°āŽŋāŽ¯ā¯ˆ āŽŽāŽąā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", @@ -754,11 +1129,32 @@ "hide_password": "āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽŽāŽąā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "hide_person": "āŽ¨āŽĒāŽ°ā¯ˆ āŽŽāŽąā¯ˆāŽ•ā¯āŽ•", "hide_unnamed_people": "āŽĒā¯†āŽ¯āŽ°āŽŋāŽŸāŽĒā¯āŽĒāŽŸāŽžāŽ¤āŽĩāŽ°ā¯āŽ•āŽŗā¯ˆ āŽŽāŽąā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "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_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_first_time_notice": "āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯āŽŸā¯ˆāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽĩāŽ¤ā¯ āŽ‡āŽ¤ā¯ āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽŽā¯āŽ¤āŽ˛ā¯ āŽŽā¯āŽąā¯ˆāŽ¯āŽžāŽ• āŽ‡āŽ°ā¯āŽ¨ā¯āŽ¤āŽžāŽ˛ā¯, āŽ¤āŽ¯āŽĩā¯āŽšā¯†āŽ¯ā¯āŽ¤ā¯ āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋ āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤ā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽĩā¯āŽšā¯†āŽ¯ā¯āŽ•, āŽ‡āŽ¤āŽŠā¯ āŽŽā¯‚āŽ˛āŽŽā¯ āŽ•āŽžāŽ˛āŽĩāŽ°āŽŋāŽšā¯ˆ āŽ…āŽ¤āŽŋāŽ˛ā¯ āŽ‰āŽŗā¯āŽŗ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽĩāŽŋāŽ°āŽŋāŽĩ❁āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ āŽŽā¯āŽŸāŽŋāŽ¯ā¯āŽŽā¯", + "home_page_locked_error_local": "āŽ‰āŽŗā¯āŽŗāŽ• āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽĒā¯‚āŽŸā¯āŽŸāŽŋāŽ¯ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆāŽ•ā¯āŽ•ā¯ āŽ¨āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤ āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯, āŽ¤āŽĩāŽŋāŽ°ā¯āŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯", + "home_page_locked_error_partner": "āŽĒāŽ™ā¯āŽ•ā¯āŽ¤āŽžāŽ°āŽ°ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽĒā¯‚āŽŸā¯āŽŸāŽŋāŽ¯ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽ¨āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤ āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯, āŽ¤āŽĩāŽŋāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "home_page_share_err_local": "āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❁, āŽšā¯āŽ•āŽŋāŽĒā¯āŽĒāŽŋāŽ™ā¯ āŽĩāŽ´āŽŋāŽ¯āŽžāŽ• āŽ‰āŽŗā¯āŽŗāŽ• āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽĒāŽ•āŽŋāŽ° āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", + "home_page_upload_err_limit": "āŽ’āŽ°ā¯ āŽ¨ā¯‡āŽ°āŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ…āŽ¤āŽŋāŽ•āŽĒāŽŸā¯āŽšāŽŽā¯ 30 āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽŽāŽŸā¯āŽŸā¯āŽŽā¯‡ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽą āŽŽā¯āŽŸāŽŋāŽ¯ā¯āŽŽā¯, āŽ¤āŽĩāŽŋāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "host": "āŽĩāŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯‹āŽŽā¯āŽĒāŽŋ", "hour": "āŽŽāŽŖāŽŋ", + "hours": "āŽŽāŽŖāŽŋ", + "id": "āŽāŽŸāŽŋ", + "idle": "āŽ¨āŽŋāŽ˛ā¯ˆāŽ¯āŽŋāŽ•ā¯āŽ•āŽŽā¯", + "ignore_icloud_photos": "ICloud āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆ āŽĒā¯āŽąāŽ•ā¯āŽ•āŽŖāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "ignore_icloud_photos_description": "ICloud āŽ‡āŽ˛ā¯ āŽšā¯‡āŽŽāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŽā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯ āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąāŽĒā¯āŽĒāŽŸāŽžāŽ¤ā¯", "image": "āŽĒāŽŸāŽŽā¯", - "image_alt_text_date": "{isvideo, āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯, āŽ‰āŽŖā¯āŽŽā¯ˆ {Video} āŽĒāŽŋāŽą {Image}} {date} āŽ‡āŽ˛ā¯ āŽŽāŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", - "image_alt_text_date_1_person": "{isvideo, āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯, āŽ‰āŽŖā¯āŽŽā¯ˆ {Video} āŽĒāŽŋāŽą {Image}} {{person1} āŽ‡āŽ˛ā¯ {date}", + "image_alt_text_date": "{isVideo, select, true {Video} āŽŽāŽąā¯āŽą {Image}} {date} āŽ…āŽŠā¯āŽąā¯ āŽŽāŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "image_alt_text_date_1_person": "{isVideo, āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯, āŽ‰āŽŖā¯āŽŽā¯ˆ {Video} āŽĒāŽŋāŽą {Image}} {person1} āŽ‡āŽ˛ā¯ {date}", "image_alt_text_date_2_people": "{isvideo, āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯, āŽ‰āŽŖā¯āŽŽā¯ˆ {Video} āŽĒāŽŋāŽą {Image}} {{person1} āŽŽāŽąā¯āŽąā¯āŽŽā¯ {person2} {date} āŽ‡āŽ˛ā¯ āŽŽāŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "image_alt_text_date_3_people": "{isvideo, āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯, āŽ‰āŽŖā¯āŽŽā¯ˆ {Video} āŽĒāŽŋāŽą {Image} the {person1}, {person2}, āŽŽāŽąā¯āŽąā¯āŽŽā¯ {person3} āŽ‡āŽ˛ā¯ āŽŽāŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯ {date}", "image_alt_text_date_4_or_more_people": "{isvideo, āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯, āŽ‰āŽŖā¯āŽŽā¯ˆ {Video} āŽĒāŽŋāŽą {Image} the {person1}, {person2}, āŽŽāŽąā¯āŽąā¯āŽŽā¯ {āŽ•ā¯‚āŽŸā¯āŽ¤āŽ˛ā¯ COUNT, āŽŽāŽŖā¯} āŽŽāŽąā¯āŽąāŽĩāŽ°ā¯āŽ•āŽŗā¯ {date}", @@ -766,7 +1162,11 @@ "image_alt_text_date_place_1_person": "{isvideo, āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯, āŽ‰āŽŖā¯āŽŽā¯ˆ {Video} āŽĒāŽŋāŽą {Image}} {city}, {country} {person1} āŽ‰āŽŸāŽŠā¯ {date}", "image_alt_text_date_place_2_people": "{isvideo, āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯, āŽ‰āŽŖā¯āŽŽā¯ˆ {Video} āŽĒāŽŋāŽą {Image}} {city}, {country} āŽ‰āŽŸāŽŠā¯ {person1} āŽŽāŽąā¯āŽąā¯āŽŽā¯ {person2} {date}", "image_alt_text_date_place_3_people": "{isvideo, āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯, āŽ‰āŽŖā¯āŽŽā¯ˆ {Video} āŽĒāŽŋāŽą {Image}} {city}, {country} {person1}, {person2}, āŽŽāŽąā¯āŽąā¯āŽŽā¯ {person3} āŽ‡āŽ˛ā¯ āŽŽāŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯ {date}", - "image_alt_text_date_place_4_or_more_people": "{isvideo, āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯, āŽ‰āŽŖā¯āŽŽā¯ˆ {Video} āŽĒāŽŋāŽą {Image}} {city}, {country} {person1}, {person2}, āŽŽāŽąā¯āŽąā¯āŽŽā¯ {āŽ•ā¯‚āŽŸā¯āŽ¤āŽ˛ā¯ āŽ•āŽĩā¯āŽŠā¯āŽŸā¯, āŽŽāŽŖā¯} āŽŽāŽąā¯āŽąāŽĩāŽ°ā¯āŽ•āŽŗā¯ {date}", + "image_alt_text_date_place_4_or_more_people": "{isvideo, āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯, āŽ‰āŽŖā¯āŽŽā¯ˆ {Video} āŽĒāŽŋāŽą {Image}} {city}, {country} {person1}, {person2}, āŽŽāŽąā¯āŽąā¯āŽŽā¯ {āŽ•ā¯‚āŽŸā¯āŽ¤āŽ˛ā¯ āŽ…āŽ•ā¯āŽ•āŽĩā¯āŽŖā¯āŽŸā¯, āŽŽāŽŖā¯} āŽŽāŽąā¯āŽąāŽĩāŽ°ā¯āŽ•āŽŗā¯ {date}", + "image_saved_successfully": "āŽĒāŽŸāŽŽā¯ āŽšā¯‡āŽŽāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "image_viewer_page_state_provider_download_started": "āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•āŽŽā¯ āŽ¤ā¯ŠāŽŸāŽ™ā¯āŽ•āŽŋāŽ¯āŽ¤ā¯", + "image_viewer_page_state_provider_download_success": "āŽĩā¯†āŽąā¯āŽąāŽŋāŽ¯ā¯ˆāŽĒā¯ āŽĒāŽ¤āŽŋāŽĩāŽŋāŽąāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "image_viewer_page_state_provider_share_error": "āŽĒāŽŋāŽ´ā¯ˆ āŽĒāŽ•āŽŋāŽ°ā¯āŽĩ❁", "immich_logo": "āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯ āŽ˛ā¯‹āŽ•ā¯‹", "immich_web_interface": "āŽ‡āŽŽā¯āŽ°āŽŋāŽšā¯ āŽĩāŽ˛ā¯ˆ āŽ‡āŽŸā¯ˆāŽŽā¯āŽ•āŽŽā¯", "import_from_json": "āŽšāŽžāŽ¤ā¯ŠāŽĒā¯ŠāŽ•ā¯ āŽ‡āŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ‡āŽąāŽ•ā¯āŽ•ā¯āŽŽāŽ¤āŽŋ", @@ -777,6 +1177,7 @@ "include_shared_albums": "āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯ˆāŽšā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "include_shared_partner_assets": "āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ•ā¯‚āŽŸā¯āŽŸāŽžāŽŗāŽ°ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆāŽšā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "individual_share": "āŽ¤āŽŠāŽŋāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽĒāŽ™ā¯āŽ•ā¯", + "individual_shares": "āŽ¤āŽŠāŽŋāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽĒāŽ™ā¯āŽ•ā¯āŽ•āŽŗā¯", "info": "āŽ¤āŽ•āŽĩāŽ˛ā¯", "interval": { "day_at_onepm": "āŽ’āŽĩā¯āŽĩā¯ŠāŽ°ā¯ āŽ¨āŽžāŽŗā¯āŽŽā¯ āŽŽāŽ¤āŽŋāŽ¯āŽŽā¯ 1 āŽŽāŽŖāŽŋāŽ•ā¯āŽ•ā¯", @@ -784,8 +1185,16 @@ "night_at_midnight": "āŽ’āŽĩā¯āŽĩā¯ŠāŽ°ā¯ āŽ‡āŽ°āŽĩā¯āŽŽā¯ āŽ¨āŽŗā¯āŽŗāŽŋāŽ°āŽĩāŽŋāŽ˛ā¯", "night_at_twoam": "āŽ’āŽĩā¯āŽĩā¯ŠāŽ°ā¯ āŽ‡āŽ°āŽĩā¯āŽŽā¯ āŽ…āŽ¤āŽŋāŽ•āŽžāŽ˛ā¯ˆ 2 āŽŽāŽŖāŽŋāŽ•ā¯āŽ•ā¯" }, + "invalid_date": "āŽ¤āŽĩāŽąāŽžāŽŠ āŽ¤ā¯‡āŽ¤āŽŋ", + "invalid_date_format": "āŽ¤āŽĩāŽąāŽžāŽŠ āŽ¤ā¯‡āŽ¤āŽŋ āŽĩāŽŸāŽŋāŽĩāŽŽā¯", "invite_people": "āŽŽāŽ•ā¯āŽ•āŽŗā¯ˆ āŽ…āŽ´ā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "invite_to_album": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽąā¯āŽ•ā¯ āŽ…āŽ´ā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "ios_debug_info_fetch_ran_at": "āŽ“āŽŸāŽŋāŽ¯āŽ¤ā¯ {dateTime}", + "ios_debug_info_last_sync_at": "āŽ•āŽŸā¯ˆāŽšāŽŋ āŽ’āŽ¤ā¯āŽ¤āŽŋāŽšā¯ˆāŽĩ❁ {dateTime}", + "ios_debug_info_no_processes_queued": "āŽĒāŽŋāŽŠā¯āŽŠāŽŖāŽŋ āŽšā¯†āŽ¯āŽ˛ā¯āŽŽā¯āŽąā¯ˆāŽ•āŽŗā¯ āŽĩāŽ°āŽŋāŽšā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ", + "ios_debug_info_no_sync_yet": "āŽĒāŽŋāŽŠā¯āŽŠāŽŖāŽŋ āŽ’āŽ¤ā¯āŽ¤āŽŋāŽšā¯ˆāŽĩ❁ āŽĩā¯‡āŽ˛ā¯ˆ āŽ‡āŽŠā¯āŽŠā¯āŽŽā¯ āŽ‡āŽ¯āŽ™ā¯āŽ•āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", + "ios_debug_info_processes_queued": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {{count} āŽĒāŽŋāŽŠā¯āŽŠāŽŖāŽŋ āŽšā¯†āŽ¯āŽ˛ā¯āŽŽā¯āŽąā¯ˆ āŽĩāŽ°āŽŋāŽšā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽĩāŽ°āŽŋāŽšā¯ˆāŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯} āŽĒāŽŋāŽą {{count} āŽĒāŽŋāŽŠā¯āŽŠāŽŖāŽŋ āŽšā¯†āŽ¯āŽ˛ā¯āŽŽā¯āŽąā¯ˆāŽ•āŽŗā¯ āŽĩāŽ°āŽŋāŽšā¯ˆāŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŸāŽŠ", + "ios_debug_info_processing_ran_at": "āŽšā¯†āŽ¯āŽ˛āŽžāŽ•ā¯āŽ•āŽŽā¯ {dateTime}", "items_count": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽ‰āŽ°ā¯āŽĒā¯āŽĒāŽŸāŽŋ} āŽĒāŽŋāŽą {# āŽ‰āŽ°ā¯āŽĒā¯āŽĒāŽŸāŽŋāŽ•āŽŗā¯}}", "jobs": "āŽĩā¯‡āŽ˛ā¯ˆāŽ•āŽŗā¯", "keep": "āŽĩā¯ˆāŽ¤ā¯āŽ¤āŽŋāŽ°ā¯āŽ™ā¯āŽ•āŽŗā¯", @@ -794,16 +1203,31 @@ "kept_this_deleted_others": "āŽ‡āŽ¨ā¯āŽ¤ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆ āŽĩā¯ˆāŽ¤ā¯āŽ¤ā¯ āŽ¨ā¯€āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯ {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} āŽĒāŽŋāŽą {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}}", "keyboard_shortcuts": "āŽĩāŽŋāŽšā¯ˆāŽĒā¯āŽĒāŽ˛āŽ•ā¯ˆ āŽ•ā¯āŽąā¯āŽ•ā¯āŽ•ā¯āŽĩāŽ´āŽŋāŽ•āŽŗā¯", "language": "āŽŽā¯ŠāŽ´āŽŋ", + "language_no_results_subtitle": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ¤ā¯‡āŽŸāŽ˛ā¯ āŽ•āŽžāŽ˛āŽ¤ā¯āŽ¤ā¯ˆ āŽšāŽ°āŽŋāŽšā¯†āŽ¯ā¯āŽ¯ āŽŽā¯āŽ¯āŽąā¯āŽšāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "language_no_results_title": "āŽŽāŽ¨ā¯āŽ¤ āŽŽā¯ŠāŽ´āŽŋāŽ•āŽŗā¯āŽŽā¯ āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", + "language_search_hint": "āŽŽā¯ŠāŽ´āŽŋāŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽŸā¯āŽ™ā¯āŽ•āŽŗā¯ ...", "language_setting_description": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽŽāŽžāŽŠ āŽŽā¯ŠāŽ´āŽŋāŽ¯ā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "large_files": "āŽĒā¯†āŽ°āŽŋāŽ¯ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽ•āŽŗā¯", + "last": "āŽ•āŽŸā¯ˆāŽšāŽŋ", "last_seen": "āŽ•āŽŸā¯ˆāŽšāŽŋāŽ¯āŽžāŽ• āŽĒāŽžāŽ°ā¯āŽ¤ā¯āŽ¤ā¯‡āŽŠā¯", "latest_version": "āŽ…āŽŖā¯āŽŽā¯ˆāŽ•ā¯ āŽ•āŽžāŽ˛ āŽĒāŽ¤āŽŋāŽĒā¯āŽĒ❁", "latitude": "āŽ…āŽ•āŽ˛āŽžāŽ™ā¯āŽ•ā¯", "leave": "āŽĩāŽŋāŽŸā¯āŽĒā¯āŽĒ❁", + "leave_album": "āŽĩāŽŋāŽŸā¯āŽĒā¯āŽĒ❁ āŽ†āŽ˛ā¯āŽĒāŽŽā¯", + "lens_model": "āŽ˛ā¯†āŽŠā¯āŽšā¯ āŽŽāŽžāŽ¤āŽŋāŽ°āŽŋ", "let_others_respond": "āŽŽāŽąā¯āŽąāŽĩāŽ°ā¯āŽ•āŽŗā¯ āŽĒāŽ¤āŽŋāŽ˛āŽŗāŽŋāŽ•ā¯āŽ•āŽŸā¯āŽŸā¯āŽŽā¯", "level": "āŽ¨āŽŋāŽ˛ā¯ˆ", "library": "āŽ¨ā¯‚āŽ˛āŽ•āŽŽā¯", "library_options": "āŽ¨ā¯‚āŽ˛āŽ• āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯", + "library_page_device_albums": "āŽšāŽžāŽ¤āŽŠāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯", + "library_page_new_album": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ†āŽ˛ā¯āŽĒāŽŽā¯", + "library_page_sort_asset_count": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗāŽŋāŽŠā¯ āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ", + "library_page_sort_created": "āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ¤ā¯‡āŽ¤āŽŋ", + "library_page_sort_last_modified": "āŽ•āŽŸā¯ˆāŽšāŽŋāŽ¯āŽžāŽ• āŽŽāŽžāŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "library_page_sort_title": "āŽ†āŽ˛ā¯āŽĒāŽŽā¯ āŽ¤āŽ˛ā¯ˆāŽĒā¯āŽĒ❁", + "licenses": "āŽ‰āŽ°āŽŋāŽŽāŽ™ā¯āŽ•āŽŗā¯", "light": "āŽ’āŽŗāŽŋ", + "like": "āŽĒā¯‹āŽŠā¯āŽą", "like_deleted": "āŽ¨ā¯€āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯ˆāŽĒā¯ āŽĒā¯‹āŽ˛", "link_motion_video": "āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❁ āŽ‡āŽ¯āŽ•ā¯āŽ• āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹", "link_to_oauth": "OAUTH āŽ‰āŽŸāŽŠā¯ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❁", @@ -811,20 +1235,61 @@ "list": "āŽĒāŽŸā¯āŽŸāŽŋāŽ¯āŽ˛ā¯", "loading": "āŽāŽąā¯āŽąā¯āŽ•āŽŋāŽąāŽ¤ā¯", "loading_search_results_failed": "āŽ¤ā¯‡āŽŸāŽ˛ā¯ āŽŽā¯āŽŸāŽŋāŽĩā¯āŽ•āŽŗā¯ˆ āŽāŽąā¯āŽąā¯āŽĩāŽ¤ā¯ āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋāŽ¯āŽŸā¯ˆāŽ¨ā¯āŽ¤āŽ¤ā¯", + "local": "āŽ‰āŽŗā¯āŽŗāŽ•", + "local_asset_cast_failed": "āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąāŽĒā¯āŽĒāŽŸāŽžāŽ¤ āŽ’āŽ°ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆ āŽ…āŽŠā¯āŽĒā¯āŽĒ āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", + "local_assets": "āŽ‰āŽŗā¯āŽŗāŽ• āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯", + "local_media_summary": "āŽ‰āŽŗā¯āŽŗāŽ• āŽŠāŽŸāŽ• āŽšā¯āŽ°ā¯āŽ•ā¯āŽ•āŽŽā¯", + "local_network": "āŽ‰āŽŗā¯āŽŗāŽ• āŽĒāŽŋāŽŖā¯ˆāŽ¯āŽŽā¯", + "local_network_sheet_info": "āŽ•ā¯āŽąāŽŋāŽĒā¯āŽĒāŽŋāŽŸā¯āŽŸ āŽĩā¯ˆāŽƒāŽĒ❈ āŽ¨ā¯†āŽŸā¯āŽĩā¯ŠāŽ°ā¯āŽ•ā¯āŽ•ā¯ˆāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽŽā¯ āŽĒā¯‹āŽ¤ā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯ āŽ‡āŽ¨ā¯āŽ¤ āŽŽā¯āŽ•āŽĩāŽ°āŽŋ āŽŽā¯‚āŽ˛āŽŽā¯ āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽ¤ā¯āŽ¤ā¯āŽŸāŽŠā¯ āŽ‡āŽŖā¯ˆāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŽā¯", + "location_permission": "āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽŋāŽŸ āŽ‡āŽšā¯ˆāŽĩ❁", + "location_permission_content": "āŽ†āŽŸā¯āŽŸā¯‹-āŽšā¯āŽĩāŽŋāŽŸā¯āŽšāŽŋāŽ™ā¯ āŽ…āŽŽā¯āŽšāŽ¤ā¯āŽ¤ā¯ˆāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤, āŽ‡āŽŽā¯āŽŽāŽŋāŽ•ā¯āŽ•ā¯ āŽ¤ā¯āŽ˛ā¯āŽ˛āŽŋāŽ¯āŽŽāŽžāŽŠ āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽŋāŽŸ āŽ‡āŽšā¯ˆāŽĩ❁ āŽ¤ā¯‡āŽĩ❈, āŽŽāŽŠāŽĩ❇ āŽ‡āŽ¤ā¯ āŽ¤āŽąā¯āŽĒā¯‹āŽ¤ā¯ˆāŽ¯ āŽĩā¯ˆāŽƒāŽĒ❈ āŽ¨ā¯†āŽŸā¯āŽĩā¯ŠāŽ°ā¯āŽ•ā¯āŽ•āŽŋāŽŠā¯ āŽĒā¯†āŽ¯āŽ°ā¯ˆāŽĒā¯ āŽĒāŽŸāŽŋāŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯ā¯āŽŽā¯", + "location_picker_choose_on_map": "āŽĩāŽ°ā¯ˆāŽĒāŽŸāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ¤ā¯‡āŽ°ā¯āŽĩ❁ āŽšā¯†āŽ¯ā¯āŽ¯āŽĩā¯āŽŽā¯", + "location_picker_latitude_error": "āŽšā¯†āŽ˛ā¯āŽ˛ā¯āŽĒāŽŸāŽŋāŽ¯āŽžāŽ•ā¯āŽŽā¯ āŽ…āŽŸā¯āŽšāŽ°ā¯‡āŽ•ā¯ˆ āŽ‰āŽŗā¯āŽŗāŽŋāŽŸāŽĩā¯āŽŽā¯", + "location_picker_latitude_hint": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ…āŽŸā¯āŽšāŽ°ā¯‡āŽ•ā¯ˆāŽ¯ā¯ˆ āŽ‡āŽ™ā¯āŽ•ā¯‡ āŽ‰āŽŗā¯āŽŗāŽŋāŽŸāŽĩā¯āŽŽā¯", + "location_picker_longitude_error": "āŽšā¯†āŽ˛ā¯āŽ˛ā¯āŽĒāŽŸāŽŋāŽ¯āŽžāŽ•ā¯āŽŽā¯ āŽ¤ā¯€āŽ°ā¯āŽ•ā¯āŽ•āŽ°ā¯‡āŽ•ā¯ˆāŽ¯ā¯ˆ āŽ‰āŽŗā¯āŽŗāŽŋāŽŸāŽĩā¯āŽŽā¯", + "location_picker_longitude_hint": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ¤ā¯€āŽ°ā¯āŽ•ā¯āŽ•āŽ°ā¯‡āŽ•ā¯ˆāŽ¯ā¯ˆ āŽ‡āŽ™ā¯āŽ•ā¯‡ āŽ‰āŽŗā¯āŽŗāŽŋāŽŸāŽĩā¯āŽŽā¯", + "lock": "āŽĒā¯‚āŽŸā¯āŽŸā¯", + "locked_folder": "āŽĒā¯‚āŽŸā¯āŽŸāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆ", + "log_detail_title": "āŽĒāŽ¤āŽŋāŽĩ❁ āŽĩāŽŋāŽĩāŽ°āŽŽā¯", "log_out": "āŽĩāŽŋāŽŸā¯āŽĒāŽ¤āŽŋāŽ•ā¯ˆ", "log_out_all_devices": "āŽŽāŽ˛ā¯āŽ˛āŽž āŽšāŽžāŽ¤āŽŠāŽ™ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽĩāŽŋāŽŸā¯āŽŸā¯ āŽĩā¯†āŽŗāŽŋāŽ¯ā¯‡āŽąāŽĩā¯āŽŽā¯", + "logged_in_as": "{user}", "logged_out_all_devices": "āŽŽāŽ˛ā¯āŽ˛āŽž āŽšāŽžāŽ¤āŽŠāŽ™ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽĩā¯†āŽŗāŽŋāŽ¯ā¯‡āŽąā¯āŽąāŽŋāŽŠā¯‡āŽŠā¯", "logged_out_device": "āŽ‰āŽŗā¯āŽ¨ā¯āŽ´ā¯ˆāŽ¨ā¯āŽ¤ āŽšāŽžāŽ¤āŽŠāŽŽā¯", "login": "āŽĒā¯āŽ•ā¯āŽĒāŽ¤āŽŋāŽĩ❁", + "login_disabled": "āŽ‰āŽŗā¯āŽ¨ā¯āŽ´ā¯ˆāŽĩ❁ āŽŽā¯āŽŸāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗāŽ¤ā¯", + "login_form_api_exception": "āŽĒāŽ¨āŽŋāŽ‡ āŽĩāŽŋāŽ¤āŽŋāŽĩāŽŋāŽ˛āŽ•ā¯āŽ•ā¯. āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ• āŽŽā¯āŽ•āŽĩāŽ°āŽŋ āŽ āŽšāŽ°āŽŋāŽĒāŽžāŽ°ā¯āŽ¤ā¯āŽ¤ā¯ āŽŽā¯€āŽŖā¯āŽŸā¯āŽŽā¯ āŽŽā¯āŽ¯āŽąā¯āŽšāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯.", + "login_form_back_button_text": "āŽĒāŽŋāŽŠā¯", + "login_form_email_hint": "youremail@email.com", + "login_form_endpoint_hint": "http: // your-server-ip: āŽ¤ā¯āŽąā¯ˆāŽŽā¯āŽ•āŽŽā¯", + "login_form_endpoint_url": "āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ• āŽŽāŽŖā¯āŽŸā¯āŽĒāŽžāŽ¯āŽŋāŽŖā¯āŽŸā¯ āŽŽā¯āŽ•āŽĩāŽ°āŽŋ", + "login_form_err_http": "Http: // āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ https: // āŽāŽ•ā¯ āŽ•ā¯āŽąāŽŋāŽĒā¯āŽĒāŽŋāŽŸāŽĩā¯āŽŽā¯", + "login_form_err_invalid_email": "āŽ¤āŽĩāŽąāŽžāŽŠ āŽŽāŽŋāŽŠā¯āŽŠāŽžā¯āŽšāŽ˛ā¯", + "login_form_err_invalid_url": "āŽ¤āŽĩāŽąāŽžāŽŠ āŽŽā¯āŽ•āŽĩāŽ°āŽŋ", + "login_form_err_leading_whitespace": "āŽŽā¯āŽŠā¯āŽŠāŽŖāŽŋ āŽĩāŽŋāŽŸā¯āŽšā¯āŽĒā¯‡āŽšā¯", + "login_form_err_trailing_whitespace": "āŽĒāŽŋāŽŠā¯āŽ¤āŽŋāŽ™ā¯ āŽĩā¯ˆāŽŸā¯āŽšā¯āŽĒā¯‡āŽšā¯", + "login_form_failed_get_oauth_server_config": "OAuth āŽāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽŋ āŽĒāŽ¤āŽŋāŽĩā¯āŽšā¯†āŽ¯ā¯āŽ¤āŽ˛ā¯, āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ• āŽŽā¯āŽ•āŽĩāŽ°āŽŋ āŽ āŽšāŽ°āŽŋāŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "login_form_failed_get_oauth_server_disable": "āŽ‡āŽ¨ā¯āŽ¤ āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ OAuth āŽ¨āŽąā¯āŽĒā¯ŠāŽ°ā¯āŽ¤ā¯āŽ¤āŽŽā¯ āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", + "login_form_failed_login": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ˆ āŽ‰āŽŗā¯āŽ¨ā¯āŽ´ā¯ˆāŽĩāŽ¤āŽŋāŽ˛ā¯ āŽĒāŽŋāŽ´ā¯ˆ, āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ• URL, āŽŽāŽŋāŽŠā¯āŽŠāŽžā¯āŽšāŽ˛ā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽšāŽ°āŽŋāŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "login_form_handshake_exception": "āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽ¤ā¯āŽ¤ā¯āŽŸāŽŠā¯ āŽāŽŖā¯āŽŸā¯āŽšā¯‡āŽ•ā¯ āŽĩāŽŋāŽ¤āŽŋāŽĩāŽŋāŽ˛āŽ•ā¯āŽ•ā¯ āŽ‡āŽ°ā¯āŽ¨ā¯āŽ¤āŽ¤ā¯. āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽ¤āŽŠā¯āŽĩāŽ¯ āŽ•ā¯ˆāŽ¯ā¯ŠāŽĒā¯āŽĒāŽŽāŽŋāŽŸāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽšāŽžāŽŠā¯āŽąāŽŋāŽ¤āŽ´ā¯ˆāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗā¯ āŽŽāŽŠā¯āŽąāŽžāŽ˛ā¯ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽ¤āŽŠā¯āŽĩāŽ¯ āŽ•ā¯ˆāŽ¯ā¯ŠāŽĒā¯āŽĒāŽŽāŽŋāŽŸāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽšāŽžāŽŠā¯āŽąāŽŋāŽ¤āŽ´ā¯ āŽ†āŽ¤āŽ°āŽĩ❈ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯.", + "login_form_password_hint": "āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯", + "login_form_save_login": "āŽ‰āŽŗā¯āŽ¨ā¯āŽ´ā¯ˆāŽ¨ā¯āŽ¤āŽŋāŽ°ā¯āŽ™ā¯āŽ•āŽŗā¯", + "login_form_server_empty": "āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ• āŽŽā¯āŽ•āŽĩāŽ°āŽŋ āŽ āŽ‰āŽŗā¯āŽŗāŽŋāŽŸāŽĩā¯āŽŽā¯.", + "login_form_server_error": "āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽ¤ā¯āŽ¤ā¯āŽŸāŽŠā¯ āŽ‡āŽŖā¯ˆāŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ.", "login_has_been_disabled": "āŽ‰āŽŗā¯āŽ¨ā¯āŽ´ā¯ˆāŽĩ❁ āŽŽā¯āŽŸāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗāŽ¤ā¯.", + "login_password_changed_error": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆāŽĒā¯ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽĒā¯āŽĒāŽ¤āŽŋāŽ˛ā¯ āŽĒāŽŋāŽ´ā¯ˆ āŽāŽąā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "login_password_changed_success": "āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯ āŽĩā¯†āŽąā¯āŽąāŽŋāŽ•āŽ°āŽŽāŽžāŽ• āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "logout_all_device_confirmation": "āŽŽāŽ˛ā¯āŽ˛āŽž āŽšāŽžāŽ¤āŽŠāŽ™ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽĩāŽŋāŽŸā¯āŽŸā¯ āŽĩā¯†āŽŗāŽŋāŽ¯ā¯‡āŽą āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", "logout_this_device_confirmation": "āŽ‡āŽ¨ā¯āŽ¤ āŽšāŽžāŽ¤āŽŠāŽ¤ā¯āŽ¤ā¯ˆ āŽĩāŽŋāŽŸā¯āŽŸā¯ āŽĩā¯†āŽŗāŽŋāŽ¯ā¯‡āŽą āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", + "logs": "āŽĒāŽ¤āŽŋāŽĩā¯āŽ•āŽŗā¯", "longitude": "āŽ¨ā¯†āŽŸā¯āŽŸāŽžāŽ™ā¯āŽ•ā¯", "look": "āŽĒāŽžāŽ°ā¯", "loop_videos": "āŽ˛ā¯‚āŽĒā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯", "loop_videos_description": "āŽĩāŽŋāŽ°āŽŋāŽĩāŽžāŽŠ āŽĒāŽžāŽ°ā¯āŽĩā¯ˆāŽ¯āŽžāŽŗāŽ°āŽŋāŽ˛ā¯ āŽ’āŽ°ā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽĩ❈ āŽ¤āŽžāŽŠāŽžāŽ• āŽĩāŽŗā¯ˆāŽ¯āŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯.", - "main_branch_warning": "āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽŽā¯‡āŽŽā¯āŽĒāŽžāŽŸā¯āŽŸā¯ āŽĒāŽ¤āŽŋāŽĒā¯āŽĒ❈āŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗā¯; āŽĩā¯†āŽŗāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ āŽĒāŽ¤āŽŋāŽĒā¯āŽĒ❈āŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ āŽ¨āŽžāŽ™ā¯āŽ•āŽŗā¯ āŽ•āŽŸā¯āŽŽā¯ˆāŽ¯āŽžāŽ• āŽĒāŽ°āŽŋāŽ¨ā¯āŽ¤ā¯āŽ°ā¯ˆāŽ•ā¯āŽ•āŽŋāŽąā¯‹āŽŽā¯!", + "main_branch_warning": "āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽ’āŽ°ā¯ āŽŽā¯‡āŽŽā¯āŽĒāŽžāŽŸā¯āŽŸā¯ āŽĒāŽ¤āŽŋāŽĒā¯āŽĒ❈āŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗā¯; āŽĩā¯†āŽŗāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ āŽĒāŽ¤āŽŋāŽĒā¯āŽĒ❈āŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ āŽ¨āŽžāŽ™ā¯āŽ•āŽŗā¯ āŽ•āŽŸā¯āŽŽā¯ˆāŽ¯āŽžāŽ• āŽĒāŽ°āŽŋāŽ¨ā¯āŽ¤ā¯āŽ°ā¯ˆāŽ•ā¯āŽ•āŽŋāŽąā¯‹āŽŽā¯!", + "main_menu": "āŽĒāŽŸā¯āŽŸāŽŋāŽ¯āŽ˛ā¯ āŽĩāŽŋāŽŗā¯ˆāŽ¯āŽžāŽŸā¯āŽ™ā¯āŽ•āŽŗā¯", "make": "āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•ā¯", + "manage_geolocation": "āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽŋāŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "manage_shared_links": "āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "manage_sharing_with_partners": "āŽ•ā¯‚āŽŸā¯āŽŸāŽžāŽŗāŽ°ā¯āŽ•āŽŗā¯āŽŸāŽŠā¯ āŽĒāŽ•āŽŋāŽ°ā¯āŽĩ❈ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "manage_the_app_settings": "āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯āŽŸā¯ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", @@ -833,13 +1298,40 @@ "manage_your_devices": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ‰āŽŗā¯āŽ¨ā¯āŽ´ā¯ˆāŽ¨ā¯āŽ¤ āŽšāŽžāŽ¤āŽŠāŽ™ā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "manage_your_oauth_connection": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ OAuth āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❈ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "map": "āŽĩāŽ°ā¯ˆāŽĒāŽŸāŽŽā¯", + "map_assets_in_bounds": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, = 0 {No photos in this area} āŽ’āŽŠā¯āŽąā¯ {# āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽŽā¯} āŽŽāŽąā¯āŽą {# āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯}}", + "map_cannot_get_user_location": "āŽĒāŽ¯āŽŠāŽ°āŽŋāŽŠā¯ āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽŋāŽŸāŽ¤ā¯āŽ¤ā¯ˆāŽĒā¯ āŽĒā¯†āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", + "map_location_dialog_yes": "āŽ†āŽŽā¯", + "map_location_picker_page_use_location": "āŽ‡āŽ¨ā¯āŽ¤ āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽŋāŽŸāŽ¤ā¯āŽ¤ā¯ˆāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", + "map_location_service_disabled_content": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ¤āŽąā¯āŽĒā¯‹āŽ¤ā¯ˆāŽ¯ āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽŋāŽŸāŽ¤ā¯āŽ¤āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆāŽ•ā¯ āŽ•āŽžāŽŸā¯āŽŸ āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽŋāŽŸ āŽĒāŽŖāŽŋ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸ āŽĩā¯‡āŽŖā¯āŽŸā¯āŽŽā¯. āŽ‡āŽĒā¯āŽĒā¯‹āŽ¤ā¯ āŽ…āŽ¤ā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", + "map_location_service_disabled_title": "āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽŋāŽŸ āŽĒāŽŖāŽŋ āŽŽā¯āŽŸāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "map_marker_for_images": "{city}, {country}", "map_marker_with_image": "āŽĒāŽŸāŽ¤ā¯āŽ¤ā¯āŽŸāŽŠā¯ āŽĩāŽ°ā¯ˆāŽĒāŽŸ āŽŽāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽ°ā¯", + "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": "āŽ•āŽŸāŽ¨ā¯āŽ¤ {days} āŽ¨āŽžāŽŸā¯āŽ•āŽŗā¯", + "map_settings_date_range_option_year": "āŽ•āŽŸāŽ¨ā¯āŽ¤ āŽ†āŽŖā¯āŽŸā¯", + "map_settings_date_range_option_years": "āŽ•āŽŸāŽ¨ā¯āŽ¤ {years} āŽ†āŽŖā¯āŽŸā¯āŽ•āŽŗā¯", + "map_settings_dialog_title": "āŽĩāŽ°ā¯ˆāŽĒāŽŸ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", + "map_settings_include_show_archived": "āŽ•āŽžāŽĒā¯āŽĒāŽ•āŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŸāŽĩāŽ°ā¯", + "map_settings_include_show_partners": "āŽ•ā¯‚āŽŸā¯āŽŸāŽžāŽŗāŽ°ā¯āŽ•āŽŗā¯ˆāŽšā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "map_settings_only_show_favorites": "āŽĒāŽŋāŽŸāŽŋāŽ¤ā¯āŽ¤āŽ¤ā¯ˆ āŽŽāŽŸā¯āŽŸā¯āŽŽā¯ āŽ•āŽžāŽŸā¯āŽŸā¯", + "map_settings_theme_settings": "āŽĩāŽ°ā¯ˆāŽĒāŽŸ āŽ•āŽ°ā¯āŽĒā¯āŽĒā¯ŠāŽ°ā¯āŽŗā¯", + "map_zoom_to_see_photos": "āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆāŽ•ā¯ āŽ•āŽžāŽŖ āŽĒā¯†āŽ°āŽŋāŽ¤āŽžāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "mark_all_as_read": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ˆāŽ¯ā¯āŽŽā¯ āŽĒāŽŸāŽŋāŽ¤ā¯āŽ¤āŽĒāŽŸāŽŋ āŽ•ā¯āŽąāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "mark_as_read": "āŽĒāŽŸāŽŋāŽ¤ā¯āŽ¤āŽĒāŽŸāŽŋ āŽ•ā¯āŽąāŽŋ", + "marked_all_as_read": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ˆāŽ¯ā¯āŽŽā¯ āŽĩāŽžāŽšāŽŋāŽĒā¯āŽĒāŽ¤āŽžāŽ• āŽ•ā¯āŽąāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗāŽ¤ā¯", "matches": "āŽĒā¯‹āŽŸā¯āŽŸāŽŋāŽ•āŽŗā¯", + "matching_assets": "āŽĒā¯ŠāŽ°ā¯āŽ¨ā¯āŽ¤ā¯āŽŽā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯", "media_type": "āŽŠāŽŸāŽ• āŽĩāŽ•ā¯ˆ", "memories": "āŽ¨āŽŋāŽŠā¯ˆāŽĩā¯āŽ•āŽŗā¯", + "memories_all_caught_up": "āŽ…āŽŠā¯ˆāŽĩāŽ°ā¯āŽŽā¯ āŽĒāŽŋāŽŸāŽŋāŽĒāŽŸā¯āŽŸāŽŠāŽ°ā¯", + "memories_check_back_tomorrow": "āŽŽā¯‡āŽ˛ā¯āŽŽā¯ āŽ¨āŽŋāŽŠā¯ˆāŽĩā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽ¨āŽžāŽŗā¯ˆ āŽŽā¯€āŽŖā¯āŽŸā¯āŽŽā¯ āŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "memories_setting_description": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ¨āŽŋāŽŠā¯ˆāŽĩā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽĒāŽžāŽ°ā¯āŽĒā¯āŽĒāŽ¤ā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "memories_start_over": "āŽ¤ā¯ŠāŽŸāŽ•ā¯āŽ•", + "memories_swipe_to_close": "āŽŽā¯‚āŽŸā¯āŽĩāŽ¤āŽąā¯āŽ•ā¯ āŽšā¯āŽĩ❈āŽĒā¯ āŽšā¯†āŽ¯ā¯āŽ¯āŽĩā¯āŽŽā¯", "memory": "āŽ¨āŽŋāŽŠā¯ˆāŽĩāŽ•āŽŽā¯", "memory_lane_title": "āŽ¨āŽŋāŽŠā¯ˆāŽĩāŽ• āŽ˛ā¯‡āŽŠā¯ {title}", "menu": "āŽĒāŽŸā¯āŽŸāŽŋāŽ¯āŽ˛ā¯", @@ -851,19 +1343,40 @@ "merged_people_count": "āŽ’āŽŠā¯āŽąāŽŋāŽŖā¯ˆāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽ¨āŽĒāŽ°ā¯} āŽŽāŽąā¯āŽą {# āŽŽāŽ•ā¯āŽ•āŽŗā¯}}", "minimize": "āŽ•ā¯āŽąā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "minute": "āŽ¨āŽŋāŽŽāŽŋāŽŸāŽ™ā¯āŽ•āŽŗā¯", + "minutes": "āŽ¨āŽŋāŽŽāŽŋāŽŸāŽ™ā¯āŽ•āŽŗā¯", "missing": "āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ", "model": "āŽŽāŽžāŽ¤āŽŋāŽ°āŽŋāŽ¯ā¯āŽ°ā¯", "month": "āŽŽāŽžāŽ¤āŽŽā¯", + "monthly_title_text_date_format": "Mmmm āŽ’āŽ¯ā¯", "more": "āŽŽā¯‡āŽ˛ā¯āŽŽā¯", + "move": "āŽ¨āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", + "move_off_locked_folder": "āŽĒā¯‚āŽŸā¯āŽŸāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆāŽ¯āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽĩā¯†āŽŗāŽŋāŽ¯ā¯‡āŽąāŽĩā¯āŽŽā¯", + "move_to_lock_folder_action_prompt": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ the āŽĒā¯‚āŽŸā¯āŽŸāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗāŽ¤ā¯", + "move_to_locked_folder": "āŽĒā¯‚āŽŸā¯āŽŸāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽšā¯†āŽ˛ā¯āŽ˛ā¯āŽ™ā¯āŽ•āŽŗā¯", + "move_to_locked_folder_confirmation": "āŽ‡āŽ¨ā¯āŽ¤ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹ āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗāŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯āŽŽā¯ āŽ…āŽ•āŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŽā¯, āŽŽā¯‡āŽ˛ā¯āŽŽā¯ āŽĒā¯‚āŽŸā¯āŽŸāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆāŽ¯āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽŽāŽŸā¯āŽŸā¯āŽŽā¯‡ āŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯ā¯āŽŽā¯", + "moved_to_archive": "āŽ¨āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "moved_to_library": "āŽ¨āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "moved_to_trash": "āŽ•ā¯āŽĒā¯āŽĒā¯ˆāŽ•ā¯āŽ•ā¯ āŽ¨āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "multiselect_grid_edit_date_time_err_read_only": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ (āŽ•āŽŗā¯ˆ) āŽŽāŽŸā¯āŽŸā¯āŽŽā¯‡ āŽĒāŽŸāŽŋāŽ¤ā¯āŽ¤ āŽ¤ā¯‡āŽ¤āŽŋāŽ¯ā¯ˆāŽ¤ā¯ āŽ¤āŽŋāŽ°ā¯āŽ¤ā¯āŽ¤ āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯, āŽ¤āŽĩāŽŋāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "multiselect_grid_edit_gps_err_read_only": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ (āŽ•āŽŗā¯ˆ) āŽŽāŽŸā¯āŽŸā¯āŽŽā¯‡ āŽĒāŽŸāŽŋāŽ•ā¯āŽ•, āŽšā¯āŽ•āŽŋāŽĒā¯āŽĒāŽŋāŽ™ā¯ āŽ†āŽ•āŽŋāŽ¯āŽĩāŽąā¯āŽąā¯ˆāŽ¤ā¯ āŽ¤āŽŋāŽ°ā¯āŽ¤ā¯āŽ¤ āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", + "mute_memories": "āŽŽā¯āŽŸāŽ•ā¯āŽ•ā¯ āŽ¨āŽŋāŽŠā¯ˆāŽĩā¯āŽ•āŽŗā¯", "my_albums": "āŽŽāŽŠāŽ¤ā¯ āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯", "name": "āŽĒā¯†āŽ¯āŽ°ā¯", "name_or_nickname": "āŽĒā¯†āŽ¯āŽ°ā¯ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽĒā¯āŽŠā¯ˆāŽĒā¯āŽĒā¯†āŽ¯āŽ°ā¯", + "network_requirement_photos_upload": "āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽšā¯†āŽ˛ā¯āŽ˛ā¯āŽ˛āŽžāŽ°ā¯ āŽ¤āŽ°āŽĩ❈āŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", + "network_requirement_videos_upload": "āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽšā¯†āŽ˛ā¯āŽ˛ā¯āŽ˛āŽžāŽ°ā¯ āŽ¤āŽ°āŽĩ❈āŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", + "network_requirements": "āŽĒāŽŋāŽŖā¯ˆāŽ¯ āŽ¤ā¯‡āŽĩā¯ˆāŽ•āŽŗā¯", + "network_requirements_updated": "āŽĒāŽŋāŽŖā¯ˆāŽ¯āŽŽā¯ āŽ¤ā¯‡āŽĩā¯ˆāŽ•āŽŗā¯ āŽŽāŽžāŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸāŽŠ, āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋ āŽĩāŽ°āŽŋāŽšā¯ˆāŽ¯ā¯ˆ āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆāŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯", + "networking_settings": "āŽ¨ā¯†āŽŸā¯āŽĩā¯ŠāŽ°ā¯āŽ•ā¯āŽ•āŽŋāŽ™ā¯", + "networking_subtitle": "āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ• āŽ‡āŽąā¯āŽ¤āŽŋāŽĒā¯āŽĒā¯āŽŗā¯āŽŗāŽŋ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "never": "āŽ’āŽ°ā¯āŽĒā¯‹āŽ¤ā¯āŽŽā¯", "new_album": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ†āŽ˛ā¯āŽĒāŽŽā¯", "new_api_key": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽĒāŽ¨āŽŋāŽ‡ āŽĩāŽŋāŽšā¯ˆ", "new_password": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯", "new_person": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ¨āŽĒāŽ°ā¯", + "new_pin_code": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽŽā¯āŽŗā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯", + "new_pin_code_subtitle": "āŽĒā¯‚āŽŸā¯āŽŸāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆāŽ¯ā¯ˆ āŽ…āŽŖā¯āŽ• āŽ‡āŽ¤ā¯ āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽŽā¯āŽ¤āŽ˛ā¯ āŽŽā¯āŽąā¯ˆāŽ¯āŽžāŽ•ā¯āŽŽā¯. āŽ‡āŽ¨ā¯āŽ¤ āŽĒāŽ•ā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽĒāŽžāŽ¤ā¯āŽ•āŽžāŽĒā¯āŽĒāŽžāŽ• āŽ…āŽŖā¯āŽ• āŽ’āŽ°ā¯ āŽŽā¯āŽŗā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "new_timeline": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ•āŽžāŽ˛āŽĩāŽ°āŽŋāŽšā¯ˆ", "new_user_created": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽĒāŽ¯āŽŠāŽ°ā¯ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "new_version_available": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽĒāŽ¤āŽŋāŽĒā¯āŽĒ❁ āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯", "newest_first": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽŽā¯āŽ¤āŽ˛ā¯", @@ -875,42 +1388,68 @@ "no_albums_yet": "āŽ‰āŽ™ā¯āŽ•āŽŗāŽŋāŽŸāŽŽā¯ āŽ‡āŽ¤ā¯āŽĩāŽ°ā¯ˆ āŽŽāŽ¨ā¯āŽ¤ āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯āŽŽā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ āŽŽāŽŠā¯āŽąā¯ āŽ¤ā¯†āŽ°āŽŋāŽ•āŽŋāŽąāŽ¤ā¯.", "no_archived_assets_message": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ•ā¯ āŽ•āŽžāŽŸā¯āŽšāŽŋāŽ¯āŽŋāŽ˛ā¯ āŽ‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ…āŽĩāŽąā¯āŽąā¯ˆ āŽŽāŽąā¯ˆāŽ•ā¯āŽ• āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ˆ āŽ•āŽžāŽĒā¯āŽĒāŽ•āŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", "no_assets_message": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽŽā¯āŽ¤āŽ˛ā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽą āŽšā¯ŠāŽŸā¯āŽ•ā¯āŽ•ā¯ āŽšā¯†āŽ¯ā¯āŽ•", + "no_assets_to_show": "āŽ•āŽžāŽŸā¯āŽŸ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ", + "no_cast_devices_found": "āŽ¨āŽŸāŽŋāŽ•āŽ°ā¯āŽ•āŽŗā¯ āŽšāŽžāŽ¤āŽŠāŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽ¤ā¯āŽĩā¯āŽŽā¯ āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", + "no_checksum_local": "āŽšā¯†āŽ•ā¯āŽšāŽŽā¯ āŽŽāŽ¤ā¯āŽĩā¯āŽŽā¯ āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ - āŽ‰āŽŗā¯āŽŗāŽ• āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆāŽĒā¯ āŽĒā¯†āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", + "no_checksum_remote": "āŽšā¯†āŽ•ā¯āŽšāŽŽā¯ āŽŽāŽ¤ā¯āŽĩā¯āŽŽā¯ āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ - āŽ¤ā¯ŠāŽ˛ā¯ˆ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ āŽĒā¯†āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", "no_duplicates_found": "āŽ¨āŽ•āŽ˛ā¯āŽ•āŽŗā¯ āŽŽāŽ¤ā¯āŽĩā¯āŽŽā¯ āŽ•āŽžāŽŖāŽĒā¯āŽĒāŽŸāŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ.", "no_exif_info_available": "EXIF āŽšā¯†āŽ¯ā¯āŽ¤āŽŋ āŽŽāŽ¤ā¯āŽĩā¯āŽŽā¯ āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "no_explore_results_message": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ¤ā¯ŠāŽ•ā¯āŽĒā¯āŽĒ❈ āŽ†āŽ°āŽžāŽ¯ āŽ•ā¯‚āŽŸā¯āŽ¤āŽ˛ā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąāŽĩā¯āŽŽā¯.", "no_favorites_message": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽšāŽŋāŽąāŽ¨ā¯āŽ¤ āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ˆ āŽĩāŽŋāŽ°ā¯ˆāŽĩāŽžāŽ•āŽ•ā¯ āŽ•āŽŖā¯āŽŸā¯āŽĒāŽŋāŽŸāŽŋāŽ•ā¯āŽ• āŽĒāŽŋāŽŸāŽŋāŽ¤ā¯āŽ¤āŽĩā¯ˆāŽ•āŽŗā¯ˆāŽšā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "no_libraries_message": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ˆāŽ•ā¯ āŽ•āŽžāŽŖ āŽĩā¯†āŽŗāŽŋāŽĒā¯āŽĒā¯āŽą āŽ¨ā¯‚āŽ˛āŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "no_local_assets_found": "āŽ‡āŽ¨ā¯āŽ¤ āŽšā¯†āŽ•ā¯āŽšāŽŽā¯ āŽŽā¯‚āŽ˛āŽŽā¯ āŽ‰āŽŗā¯āŽŗāŽ• āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ āŽŽāŽ¤ā¯āŽĩā¯āŽŽā¯ āŽ•āŽžāŽŖāŽĒā¯āŽĒāŽŸāŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", + "no_locked_photos_message": "āŽĒā¯‚āŽŸā¯āŽŸāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽ‰āŽŗā¯āŽŗ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ āŽŽāŽąā¯ˆāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗāŽŠ, āŽŽā¯‡āŽ˛ā¯āŽŽā¯ āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ¨ā¯‚āŽ˛āŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽ‰āŽ˛āŽžāŽĩā¯āŽŽā¯āŽĒā¯‹āŽ¤ā¯ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽ¤ā¯‡āŽŸā¯āŽŽā¯āŽĒā¯‹āŽ¤ā¯ āŽ•āŽžāŽŖā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸāŽžāŽ¤ā¯.", "no_name": "āŽĒā¯†āŽ¯āŽ°ā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ", + "no_notifications": "āŽ…āŽąāŽŋāŽĩāŽŋāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ", + "no_people_found": "āŽĒā¯ŠāŽ°ā¯āŽ¨ā¯āŽ¤āŽ•ā¯āŽ•ā¯‚āŽŸāŽŋāŽ¯ āŽ¨āŽĒāŽ°ā¯āŽ•āŽŗā¯ āŽŽāŽ¤ā¯āŽĩā¯āŽŽā¯ āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "no_places": "āŽ‡āŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ", + "no_remote_assets_found": "āŽ‡āŽ¨ā¯āŽ¤ āŽšā¯†āŽ•ā¯āŽšāŽŽā¯ āŽŽā¯‚āŽ˛āŽŽā¯ āŽ¤ā¯ŠāŽ˛ā¯ˆāŽ¨āŽŋāŽ˛ā¯ˆ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ āŽŽāŽ¤ā¯āŽĩā¯āŽŽā¯ āŽ•āŽžāŽŖāŽĒā¯āŽĒāŽŸāŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "no_results": "āŽŽā¯āŽŸāŽŋāŽĩā¯āŽ•āŽŗā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ", "no_results_description": "āŽ’āŽ°ā¯ āŽ’āŽ¤ā¯āŽ¤ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽĒā¯ŠāŽ¤ā¯āŽĩāŽžāŽŠ āŽŽā¯āŽ•ā¯āŽ•āŽŋāŽ¯ āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽŽā¯āŽ¯āŽąā¯āŽšāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "no_shared_albums_message": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ¨ā¯†āŽŸā¯āŽĩā¯ŠāŽ°ā¯āŽ•ā¯āŽ•āŽŋāŽ˛ā¯ āŽ‰āŽŗā¯āŽŗāŽĩāŽ°ā¯āŽ•āŽŗā¯āŽŸāŽŠā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽĒāŽ•āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ•ā¯ŠāŽŗā¯āŽŗ āŽ’āŽ°ā¯ āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤ā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "no_uploads_in_progress": "āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąāŽ™ā¯āŽ•āŽŗā¯ āŽŽā¯āŽŠā¯āŽŠā¯‡āŽąā¯āŽąāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ", + "not_available": "āŽ‡āŽ¤āŽąā¯āŽ•āŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "not_in_any_album": "āŽŽāŽ¨ā¯āŽ¤ āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯āŽŽā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ", + "not_selected": "āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸāŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "note_apply_storage_label_to_previously_uploaded assets": "āŽ•ā¯āŽąāŽŋāŽĒā¯āŽĒ❁: āŽŽā¯āŽŠā¯āŽŠāŽ°ā¯ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽšā¯‡āŽŽāŽŋāŽĒā¯āŽĒāŽ• āŽ˛ā¯‡āŽĒāŽŋāŽŗā¯ˆ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤, āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "notes": "āŽ•ā¯āŽąāŽŋāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", + "nothing_here_yet": "āŽ‡āŽŠā¯āŽŠā¯āŽŽā¯ āŽ‡āŽ™ā¯āŽ•ā¯‡ āŽŽāŽ¤ā¯āŽĩā¯āŽŽā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ", + "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": "āŽ‰āŽ¤ā¯āŽ¤āŽŋāŽ¯ā¯‹āŽ•āŽĒā¯‚āŽ°ā¯āŽĩ āŽ‡āŽŽā¯āŽŽāŽž āŽĩāŽŗāŽ™ā¯āŽ•āŽŗā¯", "offline": "āŽ‡āŽŖā¯ˆāŽ¯āŽŽāŽŋāŽ˛ā¯āŽ˛āŽžāŽŽāŽ˛ā¯", + "offset": "āŽˆāŽŸā¯āŽšā¯†āŽ¯ā¯āŽ¯ā¯āŽŽā¯", "ok": "āŽšāŽ°āŽŋ", "oldest_first": "āŽŽā¯āŽ¤āŽ˛āŽŋāŽ˛ā¯ āŽĒāŽ´āŽŽā¯ˆāŽ¯āŽžāŽŠāŽ¤ā¯", + "on_this_device": "āŽ‡āŽ¨ā¯āŽ¤ āŽšāŽžāŽ¤āŽŠāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯", "onboarding": "āŽ†āŽŠā¯ āŽĒā¯‹āŽ°ā¯āŽŸāŽŋāŽ™ā¯", - "onboarding_privacy_description": "āŽĒāŽŋāŽŠā¯āŽĩāŽ°ā¯āŽŽā¯ (āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒāŽŋāŽŠāŽžāŽ˛ā¯) āŽ¨āŽąā¯āŽĒā¯ŠāŽ°ā¯āŽ¤ā¯āŽ¤āŽ™ā¯āŽ•āŽŗā¯ āŽĩā¯†āŽŗāŽŋāŽĒā¯āŽĒā¯āŽą āŽšā¯‡āŽĩā¯ˆāŽ•āŽŗā¯ˆ āŽ¨āŽŽā¯āŽĒāŽŋāŽ¯ā¯āŽŗā¯āŽŗāŽŠ, āŽŽā¯‡āŽ˛ā¯āŽŽā¯ āŽ¨āŽŋāŽ°ā¯āŽĩāŽžāŽ• āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽŽāŽ¨ā¯āŽ¤ āŽ¨ā¯‡āŽ°āŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯āŽŽā¯ āŽŽā¯āŽŸāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸāŽ˛āŽžāŽŽā¯.", + "onboarding_locale_description": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽŽāŽžāŽŠ āŽŽā¯ŠāŽ´āŽŋāŽ¯ā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯. āŽ‡āŽ¤ā¯ˆ āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽĒāŽŋāŽŠā¯āŽŠāŽ°ā¯ āŽŽāŽžāŽąā¯āŽąāŽ˛āŽžāŽŽā¯.", + "onboarding_privacy_description": "āŽĒāŽŋāŽŠā¯āŽĩāŽ°ā¯āŽŽā¯ (āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒāŽŋāŽŠāŽžāŽ˛ā¯) āŽ¨āŽąā¯āŽĒā¯ŠāŽ°ā¯āŽ¤ā¯āŽ¤āŽ™ā¯āŽ•āŽŗā¯ āŽĩā¯†āŽŗāŽŋāŽĒā¯āŽĒā¯āŽą āŽšā¯‡āŽĩā¯ˆāŽ•āŽŗā¯ˆ āŽ¨āŽŽā¯āŽĒāŽŋāŽ¯ā¯āŽŗā¯āŽŗāŽŠ, āŽŽā¯‡āŽ˛ā¯āŽŽā¯ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽŽāŽ¨ā¯āŽ¤ āŽ¨ā¯‡āŽ°āŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯āŽŽā¯ āŽŽā¯āŽŸāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸāŽ˛āŽžāŽŽā¯.", + "onboarding_server_welcome_description": "āŽšāŽŋāŽ˛ āŽĒā¯ŠāŽ¤ā¯āŽĩāŽžāŽŠ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯āŽŸāŽŠā¯ āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ¨āŽŋāŽ•āŽ´ā¯āŽĩ❈ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯‹āŽŽā¯.", "onboarding_theme_description": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ‰āŽ¤āŽžāŽ°āŽŖāŽ¤ā¯āŽ¤āŽŋāŽąā¯āŽ•ā¯ āŽĩāŽŖā¯āŽŖ āŽ•āŽ°ā¯āŽĒā¯āŽĒā¯ŠāŽ°ā¯āŽŗā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽĩā¯āŽšā¯†āŽ¯ā¯āŽ•. āŽ‡āŽ¤ā¯ˆ āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽĒāŽŋāŽŠā¯āŽŠāŽ°ā¯ āŽŽāŽžāŽąā¯āŽąāŽ˛āŽžāŽŽā¯.", + "onboarding_user_welcome_description": "āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽ¤ā¯ŠāŽŸāŽ™ā¯āŽ•ā¯āŽĩā¯‹āŽŽā¯!", "onboarding_welcome_user": "āŽĩāŽ°āŽĩā¯‡āŽąā¯āŽ•āŽŋāŽąā¯‹āŽŽā¯, {user}", "online": "āŽ†āŽŠā¯āŽ˛ā¯ˆāŽŠāŽŋāŽ˛ā¯", "only_favorites": "āŽĒāŽŋāŽŸāŽŋāŽ¤ā¯āŽ¤āŽĩ❈ āŽŽāŽŸā¯āŽŸā¯āŽŽā¯‡", + "open": "āŽ¤āŽŋāŽą", "open_in_map_view": "āŽĩāŽ°ā¯ˆāŽĒāŽŸāŽ•ā¯ āŽ•āŽžāŽŸā¯āŽšāŽŋāŽ¯āŽŋāŽ˛ā¯ āŽ¤āŽŋāŽąāŽ¨ā¯āŽ¤āŽŋāŽ°ā¯āŽ•ā¯āŽ•ā¯āŽŽā¯", "open_in_openstreetmap": "OpenStreetMap āŽ‡āŽ˛ā¯ āŽ¤āŽŋāŽąāŽ¨ā¯āŽ¤āŽŋāŽ°ā¯āŽ•ā¯āŽ•ā¯āŽŽā¯", "open_the_search_filters": "āŽ¤ā¯‡āŽŸāŽ˛ā¯ āŽĩāŽŸāŽŋāŽĒā¯āŽĒāŽžāŽŠā¯āŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤āŽŋāŽąāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "options": "āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯", "or": "āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯", + "organize_into_albums": "āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗāŽžāŽ• āŽ’āŽ´ā¯āŽ™ā¯āŽ•āŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "organize_into_albums_description": "āŽ¤āŽąā¯āŽĒā¯‹āŽ¤ā¯ˆāŽ¯ āŽ’āŽ¤ā¯āŽ¤āŽŋāŽšā¯ˆāŽĩ❁ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽŋ āŽāŽąā¯āŽ•āŽŠāŽĩ❇ āŽ‰āŽŗā¯āŽŗ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆ āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽĩā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "organize_your_library": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ¨ā¯‚āŽ˛āŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽ’āŽ´ā¯āŽ™ā¯āŽ•āŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "original": "āŽ…āŽšāŽ˛ā¯", "other": "āŽŽāŽąā¯āŽąā¯ŠāŽŠā¯āŽąā¯", "other_devices": "āŽĒāŽŋāŽą āŽšāŽžāŽ¤āŽŠāŽ™ā¯āŽ•āŽŗā¯", + "other_entities": "āŽĒāŽŋāŽą āŽ¨āŽŋāŽąā¯āŽĩāŽŠāŽ™ā¯āŽ•āŽŗā¯", "other_variables": "āŽĒāŽŋāŽą āŽŽāŽžāŽąāŽŋāŽ•āŽŗā¯", "owned": "āŽšā¯ŠāŽ¨ā¯āŽ¤āŽŽāŽžāŽŠāŽ¤ā¯", "owner": "āŽ‰āŽ°āŽŋāŽŽā¯ˆāŽ¯āŽžāŽŗāŽ°ā¯", @@ -918,6 +1457,14 @@ "partner_can_access": "{partner} āŽ…āŽŖā¯āŽ•āŽ˛āŽžāŽŽā¯", "partner_can_access_assets": "āŽ•āŽžāŽĒā¯āŽĒāŽ•āŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽ¨ā¯€āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽĩ❈ āŽ¤āŽĩāŽŋāŽ° āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯āŽŽā¯", "partner_can_access_location": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ‡āŽŸāŽŽā¯", + "partner_list_user_photos": "{āŽĒāŽ¯āŽŠāŽ°āŽŋāŽŠā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯", + "partner_list_view_all": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ˆāŽ¯ā¯āŽŽā¯ āŽ•āŽžāŽŖā¯āŽ•", + "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": "{āŽ•ā¯‚āŽŸā¯āŽŸāŽžāŽŗāŽ°ā¯ your āŽ‡āŽŠāŽŋ āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆ āŽ…āŽŖā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯.", "partner_sharing": "āŽ•ā¯‚āŽŸā¯āŽŸāŽžāŽŗāŽ°ā¯ āŽĒāŽ•āŽŋāŽ°ā¯āŽĩ❁", "partners": "āŽ•ā¯‚āŽŸā¯āŽŸāŽžāŽŗāŽ°ā¯āŽ•āŽŗā¯", "password": "āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯", @@ -943,10 +1490,24 @@ "permanent_deletion_warning_setting_description": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ¨ā¯€āŽ•ā¯āŽ•ā¯āŽŽā¯āŽĒā¯‹āŽ¤ā¯ āŽ’āŽ°ā¯ āŽŽāŽšā¯āŽšāŽ°āŽŋāŽ•ā¯āŽ•ā¯ˆāŽ¯ā¯ˆāŽ•ā¯ āŽ•āŽžāŽŸā¯āŽŸā¯āŽ™ā¯āŽ•āŽŗā¯", "permanently_delete": "āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ¨ā¯€āŽ•ā¯āŽ•ā¯", "permanently_delete_assets_count": "āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ¨ā¯€āŽ•ā¯āŽ•ā¯ {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {asset} āŽŽāŽąā¯āŽą {assets}}", - "permanently_delete_assets_prompt": "āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽ¨āŽŋāŽšā¯āŽšāŽ¯āŽŽāŽžāŽ• {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {āŽ‡āŽ¨ā¯āŽ¤ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯?} āŽŽāŽąā¯āŽą {āŽ‡āŽ¨ā¯āŽ¤ # āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯? } āŽ…āŽĩāŽ°ā¯āŽ•āŽŗāŽŋāŽŠā¯}} āŽ†āŽ˛ā¯āŽĒāŽŽā¯ (āŽ•āŽŗā¯) āŽ‡āŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯.", + "permanently_delete_assets_prompt": "{count, plural, one {this asset?} other {these # assets?}} āŽŽāŽŠā¯āŽĒāŽ¤ā¯ˆ āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ¨ā¯€āŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž? āŽ‡āŽ¤ā¯ {count, plural, one {it from its} other {them from their}} āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤ā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯āŽŽā¯.", "permanently_deleted_asset": "āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ¨ā¯€āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯", "permanently_deleted_assets_count": "āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ¨ā¯€āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯ {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} āŽĒāŽŋāŽą {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}}", + "permission": "āŽ‡āŽšā¯ˆāŽĩ❁", + "permission_empty": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ‡āŽšā¯ˆāŽĩ❁ āŽ•āŽžāŽ˛āŽŋāŽ¯āŽžāŽ• āŽ‡āŽ°ā¯āŽ•ā¯āŽ•āŽ•ā¯āŽ•ā¯‚āŽŸāŽžāŽ¤ā¯", + "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": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ˆāŽ•ā¯ āŽ•āŽžāŽŖ āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯āŽšā¯āŽ•ā¯āŽ•ā¯ āŽ‡āŽšā¯ˆāŽĩ❁ āŽ¤ā¯‡āŽĩ❈.", "person": "āŽ†āŽŗā¯", + "person_age_months": "{āŽŽāŽžāŽ¤āŽ™ā¯āŽ•āŽŗā¯, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽŽāŽžāŽ¤āŽŽā¯} āŽŽāŽąā¯āŽą {# āŽŽāŽžāŽ¤āŽ™ā¯āŽ•āŽŗā¯}} āŽĒāŽ´ā¯ˆāŽ¯āŽ¤ā¯", + "person_age_year_months": "1 āŽ†āŽŖā¯āŽŸā¯, {āŽŽāŽžāŽ¤āŽ™ā¯āŽ•āŽŗā¯, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽŽāŽžāŽ¤āŽŽā¯} āŽŽāŽąā¯āŽą {# āŽŽāŽžāŽ¤āŽ™ā¯āŽ•āŽŗā¯}} āŽĒāŽ´ā¯ˆāŽ¯āŽ¤ā¯", + "person_age_years": "{āŽ†āŽŖā¯āŽŸā¯āŽ•āŽŗā¯, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽĒāŽŋāŽą {# āŽ†āŽŖā¯āŽŸā¯āŽ•āŽŗā¯}} āŽĒāŽ´ā¯ˆāŽ¯āŽ¤ā¯", + "person_birthdate": "{date} āŽ‡āŽ˛ā¯ āŽĒāŽŋāŽąāŽ¨ā¯āŽ¤āŽžāŽ°ā¯", "person_hidden": "{name} {āŽŽāŽąā¯ˆāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ, āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯, āŽ‰āŽŖā¯āŽŽā¯ˆ {(āŽŽāŽąā¯ˆāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ)} āŽĒāŽŋāŽą {}}", "photo_shared_all_users": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆ āŽŽāŽ˛ā¯āŽ˛āŽž āŽĒāŽ¯āŽŠāŽ°ā¯āŽ•āŽŗā¯āŽŸāŽŠā¯āŽŽā¯ āŽĒāŽ•āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ•ā¯ŠāŽŖā¯āŽŸāŽ¤āŽžāŽ•āŽ¤ā¯ āŽ¤ā¯†āŽ°āŽŋāŽ•āŽŋāŽąāŽ¤ā¯ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽĒāŽ•āŽŋāŽ°ā¯āŽĩāŽ¤āŽąā¯āŽ•ā¯ āŽ‰āŽ™ā¯āŽ•āŽŗāŽŋāŽŸāŽŽā¯ āŽŽāŽ¨ā¯āŽ¤ āŽĒāŽ¯āŽŠāŽ°ā¯āŽŽā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ.", "photos": "āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯", @@ -954,20 +1515,41 @@ "photos_count": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽŽāŽŖā¯} āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽŽā¯} āŽĒāŽŋāŽą {{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽŽāŽŖā¯} āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯}}", "photos_from_previous_years": "āŽŽā¯āŽ¨ā¯āŽ¤ā¯ˆāŽ¯ āŽ†āŽŖā¯āŽŸā¯āŽ•āŽŗāŽŋāŽŠā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯", "pick_a_location": "āŽ’āŽ°ā¯ āŽ‡āŽŸāŽ¤ā¯āŽ¤ā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ™ā¯āŽ•āŽŗā¯", + "pin_code_changed_successfully": "āŽŽā¯āŽŗā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ˆ āŽĩā¯†āŽąā¯āŽąāŽŋāŽ•āŽ°āŽŽāŽžāŽ• āŽŽāŽžāŽąā¯āŽąāŽŋāŽ¯āŽ¤ā¯", + "pin_code_reset_successfully": "āŽŽā¯āŽŗā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ˆ āŽĩā¯†āŽąā¯āŽąāŽŋāŽ•āŽ°āŽŽāŽžāŽ• āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "pin_code_setup_successfully": "āŽŽā¯āŽŗā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ˆ āŽĩā¯†āŽąā¯āŽąāŽŋāŽ•āŽ°āŽŽāŽžāŽ• āŽ…āŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "pin_verification": "āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯ āŽšāŽ°āŽŋāŽĒāŽžāŽ°ā¯āŽĒā¯āŽĒ❁", "place": "āŽ‡āŽŸāŽŽā¯", "places": "āŽ‡āŽŸāŽ™ā¯āŽ•āŽŗā¯", + "places_count": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽŽāŽŖā¯} āŽ‡āŽŸāŽŽā¯} āŽĒāŽŋāŽą {{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽŽāŽŖā¯} āŽ‡āŽŸāŽ™ā¯āŽ•āŽŗā¯}}", "play": "āŽĩāŽŋāŽŗā¯ˆāŽ¯āŽžāŽŸā¯āŽ™ā¯āŽ•āŽŗā¯", "play_memories": "āŽĒāŽŋāŽŗā¯‡āŽŽā¯†āŽŽāŽ°āŽŋāŽ•āŽŗā¯", "play_motion_photo": "āŽ‡āŽ¯āŽ•ā¯āŽ• āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽĩāŽŋāŽŗā¯ˆāŽ¯āŽžāŽŸā¯āŽ™ā¯āŽ•āŽŗā¯", "play_or_pause_video": "āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽĩ❈ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽ‡āŽŸā¯ˆāŽ¨āŽŋāŽąā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", + "please_auth_to_access": "āŽ…āŽŖā¯āŽ•āŽ˛ā¯ˆ āŽ…āŽ™ā¯āŽ•ā¯€āŽ•āŽ°āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "port": "āŽ¤ā¯āŽąā¯ˆāŽŽā¯āŽ•āŽŽā¯", + "preferences_settings_subtitle": "āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯āŽŸāŽŋāŽŠā¯ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "preferences_settings_title": "āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ¤ā¯āŽ¤ā¯‡āŽ°ā¯āŽĩā¯āŽ•āŽŗā¯", + "preparing": "āŽ¤āŽ¯āŽžāŽ°āŽžāŽ•āŽŋāŽąāŽ¤ā¯", "preset": "āŽŽā¯āŽŠā¯āŽŠāŽŽā¯ˆāŽĩ❁", "preview": "āŽŽā¯āŽŠā¯āŽŠā¯‹āŽŸā¯āŽŸāŽŽā¯", "previous": "āŽŽā¯āŽ¨ā¯āŽ¤ā¯ˆāŽ¯", "previous_memory": "āŽŽā¯āŽ¨ā¯āŽ¤ā¯ˆāŽ¯ āŽ¨āŽŋāŽŠā¯ˆāŽĩāŽ•āŽŽā¯", - "previous_or_next_photo": "āŽŽā¯āŽ¨ā¯āŽ¤ā¯ˆāŽ¯ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽ…āŽŸā¯āŽ¤ā¯āŽ¤ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽŽā¯", + "previous_or_next_day": "āŽ¨āŽžāŽŗā¯ āŽŽā¯āŽŠā¯āŽŠā¯‹āŽ•ā¯āŽ•āŽŋ/āŽĒāŽŋāŽŠā¯āŽŠā¯‹āŽ•ā¯āŽ•āŽŋ", + "previous_or_next_month": "āŽŽāŽžāŽ¤āŽŽā¯ āŽŽā¯āŽŠā¯āŽŠā¯‹āŽ•ā¯āŽ•āŽŋ/āŽĒāŽŋāŽŠā¯āŽŠā¯‹āŽ•ā¯āŽ•āŽŋ", + "previous_or_next_photo": "āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽŽā¯ āŽŽā¯āŽŠā¯āŽŠā¯‹āŽ•ā¯āŽ•āŽŋ/āŽĒāŽŋāŽŠā¯āŽŠā¯‹āŽ•ā¯āŽ•āŽŋ", + "previous_or_next_year": "āŽ†āŽŖā¯āŽŸā¯ āŽŽā¯āŽŠā¯āŽŠā¯‹āŽ•ā¯āŽ•āŽŋ/āŽĒāŽŋāŽŠā¯āŽŠā¯‹āŽ•ā¯āŽ•āŽŋ", "primary": "āŽŽā¯āŽ¤āŽŠā¯āŽŽā¯ˆ", "privacy": "āŽ¤āŽŠāŽŋāŽ¯ā¯āŽ°āŽŋāŽŽā¯ˆ", + "profile": "āŽšā¯āŽ¯āŽĩāŽŋāŽĩāŽ°āŽŽā¯", + "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_github": "āŽ•āŽŋāŽŸā¯āŽšāŽĒā¯", + "profile_drawer_readonly_mode": "āŽĒāŽŸāŽŋāŽ•ā¯āŽ• āŽŽāŽŸā¯āŽŸā¯āŽŽā¯ āŽĒāŽ¯āŽŠā¯āŽŽā¯āŽąā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯. āŽĩā¯†āŽŗāŽŋāŽ¯ā¯‡āŽą āŽĒāŽ¯āŽŠāŽ°ā¯ āŽ…āŽĩāŽ¤āŽžāŽ°ā¯ āŽāŽ•āŽžāŽŠā¯ˆ āŽ¨ā¯€āŽŖā¯āŽŸ āŽ¨ā¯‡āŽ°āŽŽā¯ āŽ…āŽ´ā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯.", + "profile_drawer_server_out_of_date_major": "āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽŽā¯ āŽ•āŽžāŽ˛āŽžāŽĩāŽ¤āŽŋāŽ¯āŽžāŽŠāŽ¤ā¯. āŽ…āŽŖā¯āŽŽā¯ˆāŽ•ā¯ āŽ•āŽžāŽ˛ āŽŽā¯āŽ•ā¯āŽ•āŽŋāŽ¯ āŽĒāŽ¤āŽŋāŽĒā¯āŽĒāŽŋāŽąā¯āŽ•ā¯ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯.", + "profile_drawer_server_out_of_date_minor": "āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽŽā¯ āŽ•āŽžāŽ˛āŽžāŽĩāŽ¤āŽŋāŽ¯āŽžāŽŠāŽ¤ā¯. āŽ…āŽŖā¯āŽŽā¯ˆāŽ•ā¯ āŽ•āŽžāŽ˛ āŽšāŽŋāŽąāŽŋāŽ¯ āŽĒāŽ¤āŽŋāŽĒā¯āŽĒāŽŋāŽąā¯āŽ•ā¯ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯.", "profile_image_of_user": "{āŽĒāŽ¯āŽŠāŽ°āŽŋāŽŠā¯ āŽšā¯āŽ¯āŽĩāŽŋāŽĩāŽ°āŽĒā¯ āŽĒāŽŸāŽŽā¯", "profile_picture_set": "āŽšā¯āŽ¯āŽĩāŽŋāŽĩāŽ°āŽĒā¯ āŽĒāŽŸ āŽ¤ā¯ŠāŽ•ā¯āŽĒā¯āŽĒ❁.", "public_album": "āŽĒā¯ŠāŽ¤ā¯ āŽ†āŽ˛ā¯āŽĒāŽŽā¯", @@ -992,7 +1574,7 @@ "purchase_lifetime_description": "āŽĩāŽžāŽ´ā¯āŽ¨āŽžāŽŗā¯ āŽ•ā¯ŠāŽŗā¯āŽŽā¯āŽ¤āŽ˛ā¯", "purchase_option_title": "āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯ˆ āŽĩāŽžāŽ™ā¯āŽ•āŽĩā¯āŽŽā¯", "purchase_panel_info_1": "āŽ‡āŽŽā¯āŽŽāŽŋāŽ¯ā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•ā¯āŽĩāŽ¤āŽąā¯āŽ•ā¯ āŽ¨āŽŋāŽąā¯ˆāŽ¯ āŽ¨ā¯‡āŽ°āŽŽā¯āŽŽā¯ āŽŽā¯āŽ¯āŽąā¯āŽšāŽŋāŽ¯ā¯āŽŽā¯ āŽ¤ā¯‡āŽĩ❈āŽĒā¯āŽĒāŽŸā¯āŽ•āŽŋāŽąāŽ¤ā¯, āŽŽā¯‡āŽ˛ā¯āŽŽā¯ āŽŽā¯āŽ´ā¯āŽ¨ā¯‡āŽ° āŽĒā¯ŠāŽąāŽŋāŽ¯āŽŋāŽ¯āŽ˛āŽžāŽŗāŽ°ā¯āŽ•āŽŗā¯ āŽ…āŽ¤ā¯ˆ āŽŽāŽ™ā¯āŽ•āŽŗāŽžāŽ˛ā¯ āŽŽā¯āŽŸāŽŋāŽ¨ā¯āŽ¤āŽĩāŽ°ā¯ˆ āŽšāŽŋāŽąāŽĒā¯āŽĒāŽžāŽ•āŽšā¯ āŽšā¯†āŽ¯ā¯āŽ¯ āŽĩā¯‡āŽ˛ā¯ˆ āŽšā¯†āŽ¯ā¯āŽ•āŽŋāŽąāŽžāŽ°ā¯āŽ•āŽŗā¯. āŽŽāŽ™ā¯āŽ•āŽŗā¯ āŽ¨ā¯‹āŽ•ā¯āŽ•āŽŽā¯ āŽ¤āŽŋāŽąāŽ¨ā¯āŽ¤ āŽŽā¯‚āŽ˛ āŽŽā¯†āŽŠā¯āŽĒā¯ŠāŽ°ā¯āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽ¨ā¯†āŽąāŽŋāŽŽā¯āŽąā¯ˆ āŽĩāŽŖāŽŋāŽ• āŽ¨āŽŸā¯ˆāŽŽā¯āŽąā¯ˆāŽ•āŽŗā¯ āŽŸā¯†āŽĩāŽ˛āŽĒā¯āŽĒāŽ°ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•āŽžāŽŠ āŽ¨āŽŋāŽ˛ā¯ˆāŽ¯āŽžāŽŠ āŽĩāŽ°ā¯āŽŽāŽžāŽŠ āŽ†āŽ¤āŽžāŽ°āŽŽāŽžāŽ• āŽŽāŽžāŽąā¯āŽĩāŽ¤ā¯āŽŽā¯, āŽšā¯āŽ°āŽŖā¯āŽŸāŽ˛ā¯ āŽŽā¯āŽ•āŽŋāŽ˛ā¯ āŽšā¯‡āŽĩā¯ˆāŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽ‰āŽŖā¯āŽŽā¯ˆāŽ¯āŽžāŽŠ āŽŽāŽžāŽąā¯āŽąā¯āŽ•āŽŗā¯āŽŸāŽŠā¯ āŽ¤āŽŠāŽŋāŽ¯ā¯āŽ°āŽŋāŽŽā¯ˆ-āŽŽāŽ°āŽŋāŽ¯āŽžāŽ¤ā¯ˆāŽ•ā¯āŽ•ā¯āŽ°āŽŋāŽ¯ āŽšā¯āŽąā¯āŽąā¯āŽšā¯āŽšā¯‚āŽ´āŽ˛ā¯ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒ❈ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•ā¯āŽĩāŽ¤ā¯āŽŽā¯ āŽ†āŽ•ā¯āŽŽā¯.", - "purchase_panel_info_2": "āŽĒ❇āŽĩāŽžāŽ˛ā¯āŽ•āŽŗā¯ˆāŽšā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽžāŽŽāŽ˛ā¯ āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽ¤āŽŋāŽ˛ā¯ āŽ¨āŽžāŽ™ā¯āŽ•āŽŗā¯ āŽ•āŽŸāŽŽā¯ˆāŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗāŽ¤āŽžāŽ˛ā¯, āŽ‡āŽ¨ā¯āŽ¤ āŽ•ā¯ŠāŽŗā¯āŽŽā¯āŽ¤āŽ˛ā¯ āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯āŽšāŽŋāŽ˛ā¯ āŽ•ā¯‚āŽŸā¯āŽ¤āŽ˛ā¯ āŽ…āŽŽā¯āŽšāŽ™ā¯āŽ•āŽŗā¯ˆ āŽ‰āŽ™ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽĩāŽ´āŽ™ā¯āŽ•āŽžāŽ¤ā¯. āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯āŽšāŽŋāŽŠā¯ āŽ¤āŽąā¯āŽĒā¯‹āŽ¤ā¯ˆāŽ¯ āŽĩāŽŗāŽ°ā¯āŽšā¯āŽšāŽŋāŽ¯ā¯ˆ āŽ†āŽ¤āŽ°āŽŋāŽ•ā¯āŽ• āŽ‰āŽ™ā¯āŽ•āŽŗā¯ˆāŽĒā¯ āŽĒā¯‹āŽŠā¯āŽą āŽĒāŽ¯āŽŠāŽ°ā¯āŽ•āŽŗā¯ˆ āŽ¨āŽžāŽ™ā¯āŽ•āŽŗā¯ āŽ¨āŽŽā¯āŽĒāŽŋāŽ¯ā¯āŽŗā¯āŽŗā¯‹āŽŽā¯.", + "purchase_panel_info_2": "āŽĒ❇āŽĩāŽžāŽ˛ā¯āŽ•āŽŗā¯ˆāŽšā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽžāŽŽāŽ˛ā¯ āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽ¤āŽŋāŽ˛ā¯ āŽ¨āŽžāŽ™ā¯āŽ•āŽŗā¯ āŽ‰āŽąā¯āŽ¤āŽŋāŽ¯āŽžāŽ• āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽ¤āŽžāŽ˛ā¯, āŽ‡āŽ¨ā¯āŽ¤ āŽ•ā¯ŠāŽŗā¯āŽŽā¯āŽ¤āŽ˛ā¯ āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯āŽšāŽŋāŽ˛ā¯ āŽ•ā¯‚āŽŸā¯āŽ¤āŽ˛ā¯ āŽ…āŽŽā¯āŽšāŽ™ā¯āŽ•āŽŗā¯ˆ āŽ‰āŽ™ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽĩāŽ´āŽ™ā¯āŽ•āŽžāŽ¤ā¯. āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯āŽšāŽŋāŽŠā¯ āŽ¤āŽąā¯āŽĒā¯‹āŽ¤ā¯ˆāŽ¯ āŽĩāŽŗāŽ°ā¯āŽšā¯āŽšāŽŋāŽ¯ā¯ˆ āŽ†āŽ¤āŽ°āŽŋāŽ•ā¯āŽ• āŽ‰āŽ™ā¯āŽ•āŽŗā¯ˆāŽĒā¯ āŽĒā¯‹āŽŠā¯āŽą āŽĒāŽ¯āŽŠāŽ°ā¯āŽ•āŽŗā¯ˆ āŽ¨āŽžāŽ™ā¯āŽ•āŽŗā¯ āŽ¨āŽŽā¯āŽĒāŽŋāŽ¯ā¯āŽŗā¯āŽŗā¯‹āŽŽā¯.", "purchase_panel_title": "āŽ¤āŽŋāŽŸā¯āŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽ†āŽ¤āŽ°āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "purchase_per_server": "āŽ’āŽ°ā¯ āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽ¤ā¯āŽ¤āŽŋāŽąā¯āŽ•ā¯", "purchase_per_user": "āŽ’āŽ°ā¯ āŽĒāŽ¯āŽŠāŽ°ā¯āŽ•ā¯āŽ•ā¯", @@ -1004,19 +1586,28 @@ "purchase_server_description_2": "āŽ†āŽ¤āŽ°āŽĩāŽžāŽŗāŽ°ā¯ āŽ¨āŽŋāŽ˛ā¯ˆ", "purchase_server_title": "āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽŽā¯", "purchase_settings_server_activated": "āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ• āŽ¤āŽ¯āŽžāŽ°āŽŋāŽĒā¯āŽĒ❁ āŽĩāŽŋāŽšā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽžāŽ•āŽŋāŽ¯āŽžāŽ˛ā¯ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽ•āŽŋāŽąāŽ¤ā¯", + "query_asset_id": "āŽĩāŽŋāŽŠāŽĩāŽ˛ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ āŽ…āŽŸā¯ˆāŽ¯āŽžāŽŗāŽŽā¯", + "queue_status": "āŽĩāŽ°āŽŋāŽšā¯ˆ {count}/{total}", "rating": "āŽ¨āŽŸā¯āŽšāŽ¤ā¯āŽ¤āŽŋāŽ° āŽŽāŽ¤āŽŋāŽĒā¯āŽĒā¯€āŽŸā¯", "rating_clear": "āŽ¤ā¯†āŽŗāŽŋāŽĩāŽžāŽŠ āŽŽāŽ¤āŽŋāŽĒā¯āŽĒā¯€āŽŸā¯", "rating_count": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽ¨āŽŸā¯āŽšāŽ¤ā¯āŽ¤āŽŋāŽ°āŽŽā¯} āŽŽāŽąā¯āŽą {# āŽ¨āŽŸā¯āŽšāŽ¤ā¯āŽ¤āŽŋāŽ°āŽ™ā¯āŽ•āŽŗā¯}}", "rating_description": "āŽšā¯†āŽ¯ā¯āŽ¤āŽŋ āŽ•ā¯āŽ´ā¯āŽĩāŽŋāŽ˛ā¯ EXIF āŽŽāŽ¤āŽŋāŽĒā¯āŽĒā¯€āŽŸā¯āŽŸā¯ˆāŽ•ā¯ āŽ•āŽžāŽŖā¯āŽĒāŽŋ", "reaction_options": "āŽŽāŽ¤āŽŋāŽ°ā¯āŽĩāŽŋāŽŠā¯ˆ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯", "read_changelog": "āŽšā¯‡āŽžā¯āŽšā¯āŽ˛āŽžāŽ•ā¯ āŽĒāŽŸāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", - "reassign": "āŽŽā¯€āŽŖā¯āŽŸā¯āŽŽā¯ āŽ‡āŽŖā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "readonly_mode_disabled": "āŽĒāŽŸāŽŋāŽ•ā¯āŽ• āŽŽāŽŸā¯āŽŸā¯āŽŽā¯ āŽĒāŽ¯āŽŠā¯āŽŽā¯āŽąā¯ˆ āŽŽā¯āŽŸāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗāŽ¤ā¯", + "readonly_mode_enabled": "āŽĒāŽŸāŽŋāŽ•ā¯āŽ• āŽŽāŽŸā¯āŽŸā¯āŽŽā¯ āŽĒāŽ¯āŽŠā¯āŽŽā¯āŽąā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "ready_for_upload": "āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąāŽ¤ā¯ āŽ¤āŽ¯āŽžāŽ°ā¯", + "reassign": "āŽŽā¯€āŽŖā¯āŽŸā¯āŽŽā¯ āŽ’āŽ¤ā¯āŽ•ā¯āŽ•ā¯", "reassigned_assets_to_existing_person": "āŽŽā¯€āŽŖā¯āŽŸā¯āŽŽā¯ āŽ’āŽ¤ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} āŽĒāŽŋāŽą {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}} āŽĒā¯†āŽąā¯āŽ¨āŽ°ā¯ {āŽĒā¯†āŽ¯āŽ°ā¯āŽ•ā¯āŽ•ā¯, āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯, āŽšā¯āŽ´āŽŋāŽ¯ {an existing person} āŽĒāŽŋāŽą {{name}}}", "reassigned_assets_to_new_person": "āŽŽā¯€āŽŖā¯āŽŸā¯āŽŽā¯ āŽ’āŽ¤ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} āŽĒāŽŋāŽą {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}} āŽ’āŽ°ā¯ āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ¨āŽĒāŽ°ā¯āŽ•ā¯āŽ•ā¯", "reassing_hint": "āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽāŽąā¯āŽ•āŽŠāŽĩ❇ āŽ‡āŽ°ā¯āŽ•ā¯āŽ•ā¯āŽŽā¯ āŽ¨āŽĒāŽ°ā¯āŽ•ā¯āŽ•ā¯ āŽ’āŽ¤ā¯āŽ•ā¯āŽ•ā¯āŽ™ā¯āŽ•āŽŗā¯", "recent": "āŽ…āŽŖā¯āŽŽā¯ˆāŽ•ā¯ āŽ•āŽžāŽ˛", "recent-albums": "āŽ…āŽŖā¯āŽŽā¯ˆāŽ•ā¯ āŽ•āŽžāŽ˛ āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯", "recent_searches": "āŽ…āŽŖā¯āŽŽā¯ˆāŽ•ā¯ āŽ•āŽžāŽ˛ āŽ¤ā¯‡āŽŸāŽ˛ā¯āŽ•āŽŗā¯", + "recently_added": "āŽ…āŽŖā¯āŽŽā¯ˆāŽ•ā¯ āŽ•āŽžāŽ˛āŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "recently_added_page_title": "āŽ…āŽŖā¯āŽŽā¯ˆāŽ•ā¯ āŽ•āŽžāŽ˛āŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "recently_taken": "āŽ…āŽŖā¯āŽŽā¯ˆāŽ•ā¯ āŽ•āŽžāŽ˛āŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽŽāŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "recently_taken_page_title": "āŽ…āŽŖā¯āŽŽā¯ˆāŽ•ā¯ āŽ•āŽžāŽ˛āŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽŽāŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "refresh": "āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽĒā¯āŽĒ❁", "refresh_encoded_videos": "āŽ•ā¯āŽąāŽŋāŽ¯āŽŋāŽŸāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ˆ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "refresh_faces": "āŽŽā¯āŽ•āŽ™ā¯āŽ•āŽŗā¯ˆāŽĒā¯ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", @@ -1028,6 +1619,9 @@ "refreshing_faces": "āŽĒā¯āŽ¤ā¯āŽ¤ā¯āŽŖāŽ°ā¯āŽšā¯āŽšāŽŋāŽ¯ā¯‚āŽŸā¯āŽŸā¯āŽŽā¯ āŽŽā¯āŽ•āŽ™ā¯āŽ•āŽŗā¯", "refreshing_metadata": "āŽĒā¯āŽ¤ā¯āŽ¤ā¯āŽŖāŽ°ā¯āŽšā¯āŽšāŽŋāŽ¯ā¯‚āŽŸā¯āŽŸā¯āŽŽā¯ āŽŽā¯‡āŽŠāŽŋāŽ˛ā¯ˆ āŽ¤āŽ°āŽĩ❁", "regenerating_thumbnails": "āŽšāŽŋāŽąā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆ āŽŽā¯€āŽŖā¯āŽŸā¯āŽŽā¯ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯", + "remote": "āŽ¤ā¯ŠāŽ˛ā¯ˆāŽ¨āŽŋāŽ˛ā¯ˆ", + "remote_assets": "āŽ¤ā¯ŠāŽ˛ā¯ˆ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯", + "remote_media_summary": "āŽ¤ā¯ŠāŽ˛ā¯ˆ āŽŠāŽŸāŽ• āŽšā¯āŽ°ā¯āŽ•ā¯āŽ•āŽŽā¯", "remove": "āŽ…āŽ•āŽąā¯āŽąā¯", "remove_assets_album_confirmation": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} āŽĒāŽŋāŽą {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯} your āŽ āŽ…āŽ•āŽąā¯āŽą āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", "remove_assets_shared_link_confirmation": "āŽ‡āŽ¨ā¯āŽ¤ āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒāŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} āŽĒāŽŋāŽą {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯} your āŽ āŽ…āŽ•āŽąā¯āŽą āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", @@ -1035,14 +1629,23 @@ "remove_custom_date_range": "āŽ¤āŽŠāŽŋāŽĒā¯āŽĒāŽ¯āŽŠā¯ āŽ¤ā¯‡āŽ¤āŽŋ āŽĩāŽ°āŽŽā¯āŽĒ❈ āŽ…āŽ•āŽąā¯āŽąā¯", "remove_deleted_assets": "āŽ¨ā¯€āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽ…āŽ•āŽąā¯āŽąāŽĩā¯āŽŽā¯", "remove_from_album": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ…āŽ•āŽąā¯āŽąā¯", + "remove_from_album_action_prompt": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ the āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ…āŽ•āŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "remove_from_favorites": "āŽĒāŽŋāŽŸāŽŋāŽ¤ā¯āŽ¤āŽĩā¯ˆāŽ•āŽŗāŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ…āŽ•āŽąā¯āŽąā¯", + "remove_from_lock_folder_action_prompt": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ the āŽĒā¯‚āŽŸā¯āŽŸāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆāŽ¯āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ…āŽ•āŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "remove_from_locked_folder": "āŽĒā¯‚āŽŸā¯āŽŸāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆāŽ¯āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ…āŽ•āŽąā¯āŽąā¯", + "remove_from_locked_folder_confirmation": "āŽĒā¯‚āŽŸā¯āŽŸāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽąā¯ˆāŽ¯āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ‡āŽ¨ā¯āŽ¤ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¨āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤ āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž? āŽ…āŽĩ❈ āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ¨ā¯‚āŽ˛āŽ•āŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ¤ā¯†āŽ°āŽŋāŽ¯ā¯āŽŽā¯.", "remove_from_shared_link": "āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒāŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ…āŽ•āŽąā¯āŽąā¯", + "remove_memory": "āŽ¨āŽŋāŽŠā¯ˆāŽĩāŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽ…āŽ•āŽąā¯āŽąā¯", + "remove_photo_from_memory": "āŽ‡āŽ¨ā¯āŽ¤ āŽ¨āŽŋāŽŠā¯ˆāŽĩāŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽ…āŽ•āŽąā¯āŽąā¯", + "remove_tag": "āŽ•ā¯āŽąāŽŋāŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽ…āŽ•āŽąā¯āŽąā¯", "remove_url": "āŽŽā¯āŽ•āŽĩāŽ°āŽŋ āŽ āŽ…āŽ•āŽąā¯āŽąā¯", "remove_user": "āŽĒāŽ¯āŽŠāŽ°ā¯ˆ āŽ…āŽ•āŽąā¯āŽąā¯", "removed_api_key": "āŽ…āŽ•āŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽĒāŽ¨āŽŋāŽ‡ āŽĩāŽŋāŽšā¯ˆ: {name}", "removed_from_archive": "āŽ•āŽžāŽĒā¯āŽĒāŽ•āŽ¤ā¯āŽ¤āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ…āŽ•āŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "removed_from_favorites": "āŽĒāŽŋāŽŸāŽŋāŽ¤ā¯āŽ¤āŽĩā¯ˆāŽ•āŽŗāŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ…āŽ•āŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "removed_from_favorites_count": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽĒāŽŋāŽą {āŽĒāŽŋāŽŸāŽŋāŽ¤ā¯āŽ¤āŽĩā¯ˆāŽ•āŽŗāŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ #}} āŽ…āŽ•āŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "removed_memory": "āŽ…āŽ•āŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ¨āŽŋāŽŠā¯ˆāŽĩāŽ•āŽŽā¯", + "removed_photo_from_memory": "āŽ¨āŽŋāŽŠā¯ˆāŽĩāŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽ…āŽ•āŽąā¯āŽąāŽŋāŽ¯āŽ¤ā¯", "removed_tagged_assets": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} āŽĒāŽŋāŽą {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯} āŽ‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ‡āŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ…āŽ•āŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ•ā¯āŽąāŽŋāŽšā¯āŽšā¯ŠāŽ˛ā¯", "rename": "āŽŽāŽąā¯āŽĒā¯†āŽ¯āŽ°āŽŋāŽŸā¯āŽ™ā¯āŽ•āŽŗā¯", "repair": "āŽĒāŽ´ā¯āŽ¤ā¯", @@ -1051,27 +1654,41 @@ "repository": "āŽ•āŽŗāŽžā¯āŽšāŽŋāŽ¯āŽŽā¯", "require_password": "āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯ āŽ¤ā¯‡āŽĩ❈", "require_user_to_change_password_on_first_login": "āŽŽā¯āŽ¤āŽ˛ā¯ āŽ‰āŽŗā¯āŽ¨ā¯āŽ´ā¯ˆāŽĩāŽŋāŽ˛ā¯ āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽŽāŽžāŽąā¯āŽą āŽĒāŽ¯āŽŠāŽ°ā¯ āŽ¤ā¯‡āŽĩ❈", + "rescan": "āŽ°ā¯†āŽšā¯āŽ•āŽžāŽŠā¯", "reset": "āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆ", "reset_password": "āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "reset_people_visibility": "āŽŽāŽ•ā¯āŽ•āŽŗāŽŋāŽŠā¯ āŽ¤ā¯†āŽ°āŽŋāŽĩā¯āŽ¨āŽŋāŽ˛ā¯ˆāŽ¯ā¯ˆ āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "reset_pin_code": "āŽŽā¯āŽŗā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ˆ āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "reset_pin_code_description": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽŽā¯āŽŗā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ˆ āŽŽāŽąāŽ¨ā¯āŽ¤ā¯āŽĩāŽŋāŽŸā¯āŽŸāŽžāŽ˛ā¯, āŽ…āŽ¤ā¯ˆ āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆāŽ•ā¯āŽ• āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ• āŽ¨āŽŋāŽ°ā¯āŽĩāŽžāŽ•āŽŋāŽ¯ā¯ˆ āŽ¤ā¯ŠāŽŸāŽ°ā¯āŽĒ❁ āŽ•ā¯ŠāŽŗā¯āŽŗāŽ˛āŽžāŽŽā¯", + "reset_pin_code_success": "āŽŽā¯āŽŗā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ˆ āŽĩā¯†āŽąā¯āŽąāŽŋāŽ•āŽ°āŽŽāŽžāŽ• āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "reset_pin_code_with_password": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯ āŽŽā¯‚āŽ˛āŽŽā¯ āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽŽā¯āŽŗā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ˆ āŽŽāŽĒā¯āŽĒā¯‹āŽ¤ā¯āŽŽā¯ āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆāŽ•ā¯āŽ•āŽ˛āŽžāŽŽā¯", + "reset_sqlite": "SQLite āŽ¤āŽ°āŽĩā¯āŽ¤ā¯āŽ¤āŽŗāŽ¤ā¯āŽ¤ā¯ˆ āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "reset_sqlite_confirmation": "SQLITE āŽ¤āŽ°āŽĩā¯āŽ¤ā¯āŽ¤āŽŗāŽ¤ā¯āŽ¤ā¯ˆ āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆāŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž? āŽ¤āŽ°āŽĩ❈ āŽŽā¯€āŽŖā¯āŽŸā¯āŽŽā¯ āŽ’āŽ¤ā¯āŽ¤āŽŋāŽšā¯ˆāŽ•ā¯āŽ• āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽĩā¯†āŽŗāŽŋāŽ¯ā¯‡āŽąāŽŋ āŽŽā¯€āŽŖā¯āŽŸā¯āŽŽā¯ āŽ‰āŽŗā¯āŽ¨ā¯āŽ´ā¯ˆāŽ¯ āŽĩā¯‡āŽŖā¯āŽŸā¯āŽŽā¯", + "reset_sqlite_success": "SQLITE āŽ¤āŽ°āŽĩā¯āŽ¤ā¯āŽ¤āŽŗāŽ¤ā¯āŽ¤ā¯ˆ āŽĩā¯†āŽąā¯āŽąāŽŋāŽ•āŽ°āŽŽāŽžāŽ• āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "reset_to_default": "āŽ‡āŽ¯āŽ˛ā¯āŽĒā¯āŽ¨āŽŋāŽ˛ā¯ˆāŽ•ā¯āŽ•ā¯ āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "resolve_duplicates": "āŽ¨āŽ•āŽ˛ā¯āŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤ā¯€āŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "resolved_all_duplicates": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ āŽ¨āŽ•āŽ˛ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¤ā¯€āŽ°ā¯āŽ•ā¯āŽ•ā¯āŽŽā¯", "restore": "āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆ", "restore_all": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ˆāŽ¯ā¯āŽŽā¯ āŽŽā¯€āŽŸā¯āŽŸā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "restore_trash_action_prompt": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ the āŽ•ā¯āŽĒā¯āŽĒā¯ˆāŽ•āŽŗāŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽŽā¯€āŽŸā¯āŽŸā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "restore_user": "āŽĒāŽ¯āŽŠāŽ°ā¯ˆ āŽŽā¯€āŽŸā¯āŽŸāŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "restored_asset": "āŽŽā¯€āŽŸā¯āŽŸā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯", "resume": "āŽŽā¯€āŽŖā¯āŽŸā¯āŽŽā¯ āŽ¤ā¯ŠāŽŸāŽ™ā¯āŽ•ā¯āŽ™ā¯āŽ•āŽŗā¯", + "resume_paused_jobs": "āŽŽā¯€āŽŖā¯āŽŸā¯āŽŽā¯ āŽ¤ā¯ŠāŽŸāŽ™ā¯āŽ•ā¯āŽ™ā¯āŽ•āŽŗā¯ {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽ‡āŽŸā¯ˆāŽ¨āŽŋāŽąā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽĩā¯‡āŽ˛ā¯ˆ} āŽŽāŽąā¯āŽą {# āŽ‡āŽŸā¯ˆāŽ¨āŽŋāŽąā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽĩā¯‡āŽ˛ā¯ˆāŽ•āŽŗā¯}}", "retry_upload": "āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽą āŽŽā¯āŽ¯āŽąā¯āŽšāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "review_duplicates": "āŽ¨āŽ•āŽ˛ā¯āŽ•āŽŗā¯ˆ āŽŽāŽ¤āŽŋāŽĒā¯āŽĒāŽžāŽ¯ā¯āŽĩ❁ āŽšā¯†āŽ¯ā¯āŽ¯āŽĩā¯āŽŽā¯", + "review_large_files": "āŽĒā¯†āŽ°āŽŋāŽ¯ āŽ•ā¯‹āŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽŽāŽ¤āŽŋāŽĒā¯āŽĒāŽžāŽ¯ā¯āŽĩ❁ āŽšā¯†āŽ¯ā¯āŽ¯āŽĩā¯āŽŽā¯", "role": "āŽĒāŽ™ā¯āŽ•ā¯", "role_editor": "āŽ¤āŽŋāŽ°ā¯āŽ¤ā¯āŽ¤āŽŋ", "role_viewer": "āŽĒāŽžāŽ°ā¯āŽĩā¯ˆāŽ¯āŽžāŽŗāŽ°ā¯", + "running": "āŽ‡āŽ¯āŽ™ā¯āŽ•ā¯āŽŽā¯", "save": "āŽšā¯‡āŽŽāŽŋ", + "save_to_gallery": "āŽ•ā¯‡āŽ˛āŽ°āŽŋāŽ¯āŽŋāŽ˛ā¯ āŽšā¯‡āŽŽāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "saved_api_key": "āŽšā¯‡āŽŽāŽŋāŽ¤ā¯āŽ¤ āŽĒāŽ¨āŽŋāŽ‡ āŽĩāŽŋāŽšā¯ˆ", "saved_profile": "āŽšā¯‡āŽŽāŽŋāŽ¤ā¯āŽ¤ āŽšā¯āŽ¯āŽĩāŽŋāŽĩāŽ°āŽŽā¯", "saved_settings": "āŽšā¯‡āŽŽāŽŋāŽ¤ā¯āŽ¤ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", "say_something": "āŽāŽ¤āŽžāŽĩāŽ¤ā¯ āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯āŽ™ā¯āŽ•āŽŗā¯", + "scaffold_body_error_occurred": "āŽĒāŽŋāŽ´ā¯ˆ āŽāŽąā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "scan_all_libraries": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ āŽ¨ā¯‚āŽ˛āŽ•āŽ™ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽšā¯āŽ•ā¯‡āŽŠā¯ āŽšā¯†āŽ¯ā¯āŽ¯ā¯āŽ™ā¯āŽ•āŽŗā¯", "scan_library": "āŽšā¯āŽ•ā¯‡āŽŠā¯", "scan_settings": "āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽšā¯āŽ•ā¯‡āŽŠā¯ āŽšā¯†āŽ¯ā¯āŽ¯ā¯āŽ™ā¯āŽ•āŽŗā¯", @@ -1079,20 +1696,53 @@ "search": "āŽ¤ā¯‡āŽŸāŽ˛ā¯", "search_albums": "āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽŸā¯āŽ™ā¯āŽ•āŽŗā¯", "search_by_context": "āŽšā¯‚āŽ´āŽ˛āŽžāŽ˛ā¯ āŽ¤ā¯‡āŽŸā¯āŽ™ā¯āŽ•āŽŗā¯", + "search_by_description": "āŽĩāŽŋāŽŗāŽ•ā¯āŽ•āŽ¤ā¯āŽ¤āŽŋāŽŠā¯ āŽŽā¯‚āŽ˛āŽŽā¯ āŽ¤ā¯‡āŽŸā¯āŽ™ā¯āŽ•āŽŗā¯", + "search_by_description_example": "āŽšāŽĒā¯āŽĒāŽžāŽĩāŽŋāŽ˛ā¯ āŽ¨āŽŸā¯ˆāŽĒāŽ¯āŽŖāŽŽā¯", "search_by_filename": "āŽ•ā¯‹āŽĒā¯āŽĒ❁ āŽĒā¯†āŽ¯āŽ°ā¯ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽ¨ā¯€āŽŸā¯āŽŸāŽŋāŽĒā¯āŽĒ❁ āŽŽā¯‚āŽ˛āŽŽā¯ āŽ¤ā¯‡āŽŸā¯āŽ™ā¯āŽ•āŽŗā¯", "search_by_filename_example": "I.E. IMG_1234.JPG āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ PNG", "search_camera_make": "āŽ¤ā¯‡āŽŸāŽ˛ā¯ āŽ•ā¯‡āŽŽāŽ°āŽž āŽšā¯†āŽ¯ā¯āŽ¯ā¯āŽ™ā¯āŽ•āŽŗā¯ ...", "search_camera_model": "āŽ•ā¯‡āŽŽāŽ°āŽž āŽŽāŽžāŽ¤āŽŋāŽ°āŽŋāŽ¯ā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽŸā¯āŽ™ā¯āŽ•āŽŗā¯ ...", "search_city": "āŽ¤ā¯‡āŽŸāŽ˛ā¯ āŽ¨āŽ•āŽ°āŽŽā¯ ...", "search_country": "āŽ¤ā¯‡āŽŸāŽ˛ā¯ āŽ¨āŽžāŽŸā¯ ...", + "search_filter_apply": "āŽĩāŽŸāŽŋāŽ•āŽŸā¯āŽŸāŽŋāŽ¯ā¯ˆāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽ™ā¯āŽ•āŽŗā¯", + "search_filter_camera_title": "āŽ•ā¯‡āŽŽāŽ°āŽž āŽĩāŽ•ā¯ˆāŽ¯ā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "search_filter_date": "āŽ¤āŽŋāŽ•āŽ¤āŽŋ", + "search_filter_date_interval": "{start} āŽĒā¯†āŽąā¯āŽ¨āŽ°ā¯ {end}", + "search_filter_date_title": "āŽ¤ā¯‡āŽ¤āŽŋ āŽĩāŽ°āŽŽā¯āŽĒā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "search_filter_display_option_not_in_album": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ", + "search_filter_display_options": "āŽ•āŽžāŽŸā¯āŽšāŽŋ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯", + "search_filter_filename": "āŽ•ā¯‹āŽĒā¯āŽĒ❁ āŽĒā¯†āŽ¯āŽ°ā¯ āŽŽā¯‚āŽ˛āŽŽā¯ āŽ¤ā¯‡āŽŸā¯āŽ™ā¯āŽ•āŽŗā¯", + "search_filter_location": "āŽ‡āŽŸāŽŽā¯", + "search_filter_location_title": "āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽŋāŽŸāŽ¤ā¯āŽ¤ā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "search_filter_media_type": "āŽŠāŽŸāŽ• āŽĩāŽ•ā¯ˆ", + "search_filter_media_type_title": "āŽŽā¯€āŽŸāŽŋāŽ¯āŽž āŽĩāŽ•ā¯ˆāŽ¯ā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "search_filter_people_title": "āŽŽāŽ•ā¯āŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "search_for": "āŽ¤ā¯‡āŽŸā¯āŽ™ā¯āŽ•āŽŗā¯", "search_for_existing_person": "āŽ‡āŽ°ā¯āŽ•ā¯āŽ•ā¯āŽŽā¯ āŽ¨āŽĒāŽ°ā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽŸā¯āŽ™ā¯āŽ•āŽŗā¯", + "search_no_more_result": "āŽŽā¯‡āŽ˛ā¯āŽŽā¯ āŽŽā¯āŽŸāŽŋāŽĩā¯āŽ•āŽŗā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ", "search_no_people": "āŽŽāŽ•ā¯āŽ•āŽŗā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ", "search_no_people_named": "\"{name}\" āŽŽāŽŠā¯āŽąā¯ āŽĒā¯†āŽ¯āŽ°āŽŋāŽŸāŽĒā¯āŽĒāŽŸā¯āŽŸāŽĩāŽ°ā¯āŽ•āŽŗā¯ āŽ¯āŽžāŽ°ā¯āŽŽā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ", + "search_no_result": "āŽŽā¯āŽŸāŽŋāŽĩā¯āŽ•āŽŗā¯ āŽŽāŽ¤ā¯āŽĩā¯āŽŽā¯ āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ, āŽĩā¯‡āŽąā¯ āŽ¤ā¯‡āŽŸāŽ˛ā¯ āŽ•āŽžāŽ˛āŽ¤ā¯āŽ¤ā¯ˆ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽ•āŽ˛āŽĩā¯ˆāŽ¯ā¯ˆ āŽŽā¯āŽ¯āŽąā¯āŽšāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "search_options": "āŽ¤ā¯‡āŽŸāŽ˛ā¯ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯", + "search_page_categories": "āŽĩāŽ•ā¯ˆāŽ•āŽŗā¯", + "search_page_motion_photos": "āŽ‡āŽ¯āŽ•ā¯āŽ• āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯", + "search_page_no_objects": "āŽĒā¯ŠāŽ°ā¯āŽŗā¯ āŽšā¯†āŽ¯ā¯āŽ¤āŽŋ āŽŽāŽ¤ā¯āŽĩā¯āŽŽā¯ āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", + "search_page_no_places": "āŽ‡āŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽšā¯†āŽ¯ā¯āŽ¤āŽŋ āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", + "search_page_screenshots": "āŽ¤āŽŋāŽ°ā¯ˆāŽ•ā¯āŽ•āŽžāŽŸā¯āŽšāŽŋāŽ•āŽŗā¯", + "search_page_search_photos_videos": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽŸā¯āŽ™ā¯āŽ•āŽŗā¯", + "search_page_selfies": "āŽšā¯†āŽ˛ā¯āŽƒāŽĒāŽŋāŽ•āŽŗā¯", + "search_page_things": "āŽĩāŽŋāŽšāŽ¯āŽ™ā¯āŽ•āŽŗā¯", + "search_page_view_all_button": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ˆāŽ¯ā¯āŽŽā¯ āŽ•āŽžāŽŖā¯āŽ•", + "search_page_your_activity": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽšā¯†āŽ¯āŽ˛ā¯āŽĒāŽžāŽŸā¯", + "search_page_your_map": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽĩāŽ°ā¯ˆāŽĒāŽŸāŽŽā¯", "search_people": "āŽŽāŽ•ā¯āŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽŸā¯āŽ™ā¯āŽ•āŽŗā¯", "search_places": "āŽ‡āŽŸāŽ™ā¯āŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽŸā¯āŽ™ā¯āŽ•āŽŗā¯", + "search_rating": "āŽŽāŽ¤āŽŋāŽĒā¯āŽĒā¯€āŽŸā¯āŽŸāŽŋāŽŠā¯ āŽŽā¯‚āŽ˛āŽŽā¯ āŽ¤ā¯‡āŽŸā¯āŽ™ā¯āŽ•āŽŗā¯ ...", + "search_result_page_new_search_hint": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ¤ā¯‡āŽŸāŽ˛ā¯", "search_settings": "āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽŸā¯āŽ™ā¯āŽ•āŽŗā¯", "search_state": "āŽ¤ā¯‡āŽŸāŽ˛ā¯ āŽ¨āŽŋāŽ˛ā¯ˆ ...", + "search_suggestion_list_smart_search_hint_1": "āŽŽā¯†āŽŸā¯āŽŸāŽžāŽŸā¯‡āŽŸā¯āŽŸāŽžāŽĩā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽŸ, āŽ¨āŽŋāŽ•āŽ´ā¯āŽĩ❈āŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤, āŽ…āŽąāŽŋāŽĩā¯āŽŗā¯āŽŗ āŽ¤ā¯‡āŽŸāŽ˛ā¯ āŽ‡āŽ¯āŽ˛ā¯āŽĒā¯āŽ¨āŽŋāŽ˛ā¯ˆāŽ¯āŽžāŽ• āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯ ", + "search_suggestion_list_smart_search_hint_2": "āŽŽāŽŽā¯: āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ¤ā¯‡āŽŸāŽ˛ā¯-āŽ•āŽžāŽ˛āŽ¨āŽŋāŽ˛ā¯ˆ", "search_tags": "āŽ•ā¯āŽąāŽŋāŽšā¯āŽšā¯ŠāŽąā¯āŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽŸā¯āŽ™ā¯āŽ•āŽŗā¯ ...", "search_timezone": "āŽ¨ā¯‡āŽ° āŽŽāŽŖā¯āŽŸāŽ˛āŽ¤ā¯āŽ¤ā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽŸā¯āŽ™ā¯āŽ•āŽŗā¯ ...", "search_type": "āŽ¤ā¯‡āŽŸāŽ˛ā¯ āŽĩāŽ•ā¯ˆ", @@ -1100,9 +1750,11 @@ "searching_locales": "āŽ‡āŽŸāŽ™ā¯āŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽŸā¯āŽ•āŽŋāŽąāŽ¤ā¯ ...", "second": "āŽ‡āŽ°āŽŖā¯āŽŸāŽžāŽĩāŽ¤ā¯", "see_all_people": "āŽŽāŽ˛ā¯āŽ˛āŽž āŽŽāŽ•ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽĒāŽžāŽ°ā¯āŽ™ā¯āŽ•āŽŗā¯", + "select": "āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯", "select_album_cover": "āŽ†āŽ˛ā¯āŽĒāŽŽā¯ āŽ…āŽŸā¯āŽŸā¯ˆāŽ¯ā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "select_all": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¤ā¯†āŽ°āŽŋāŽĩā¯āŽšā¯†āŽ¯ā¯", "select_all_duplicates": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ āŽ¨āŽ•āŽ˛ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "select_all_in": "{āŽ•ā¯āŽ´ā¯āŽĩāŽŋāŽ˛ā¯ āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "select_avatar_color": "āŽ…āŽĩāŽ¤āŽžāŽ°ā¯ āŽ¨āŽŋāŽąāŽ¤ā¯āŽ¤ā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "select_face": "āŽŽā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "select_featured_photo": "āŽĒāŽŋāŽ°āŽ¤ā¯āŽ¯ā¯‡āŽ• āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ¤ā¯āŽ¤ā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", @@ -1110,14 +1762,21 @@ "select_keep_all": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ˆāŽ¯ā¯āŽŽā¯ āŽĩā¯ˆāŽ¤ā¯āŽ¤āŽŋāŽ°ā¯āŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽŠā¯āŽĒāŽ¤ā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "select_library_owner": "āŽ¨ā¯‚āŽ˛āŽ• āŽ‰āŽ°āŽŋāŽŽā¯ˆāŽ¯āŽžāŽŗāŽ°ā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "select_new_face": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽŽā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "select_person_to_tag": "āŽ•ā¯āŽąāŽŋāŽ•ā¯āŽ• āŽ’āŽ°ā¯ āŽ¨āŽĒāŽ°ā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "select_photos": "āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "select_trash_all": "āŽ•ā¯āŽĒā¯āŽĒā¯ˆāŽ¤ā¯ āŽ¤ā¯ŠāŽŸā¯āŽŸāŽŋāŽ¯ā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "select_user_for_sharing_page_err_album": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤ā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽ¤ā¯ āŽ¤āŽĩāŽąāŽŋāŽĩāŽŋāŽŸā¯āŽŸāŽ¤ā¯", "selected": "āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "selected_count": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽĒāŽŋāŽą {# āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ}}", + "selected_gps_coordinates": "āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽšāŽŋ.āŽĒāŽŋ.āŽŽāŽšā¯ āŽ†āŽ¯āŽ¤ā¯āŽ¤ā¯ŠāŽ˛ā¯ˆāŽĩā¯āŽ•āŽŗā¯", "send_message": "āŽšā¯†āŽ¯ā¯āŽ¤āŽŋ āŽ…āŽŠā¯āŽĒā¯āŽĒāŽĩā¯āŽŽā¯", "send_welcome_email": "āŽĩāŽ°āŽĩā¯‡āŽąā¯āŽĒ❁ āŽŽāŽŋāŽŠā¯āŽŠāŽžā¯āŽšāŽ˛ā¯ˆ āŽ…āŽŠā¯āŽĒā¯āŽĒāŽĩā¯āŽŽā¯", + "server_endpoint": "āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ• āŽ‡āŽąā¯āŽ¤āŽŋāŽĒā¯āŽĒā¯āŽŗā¯āŽŗāŽŋ", + "server_info_box_app_version": "āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯āŽŸā¯ āŽĒāŽ¤āŽŋāŽĒā¯āŽĒ❁", + "server_info_box_server_url": "āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ• āŽŽā¯āŽ•āŽĩāŽ°āŽŋ", "server_offline": "āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽŽā¯ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒāŽŋāŽ˛ā¯āŽ˛āŽžāŽ¤", "server_online": "āŽ†āŽŠā¯āŽ˛ā¯ˆāŽŠāŽŋāŽ˛ā¯ āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽŽā¯", + "server_privacy": "āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ• āŽ¤āŽŠāŽŋāŽ¯ā¯āŽ°āŽŋāŽŽā¯ˆ", "server_stats": "āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ• āŽĒā¯āŽŗā¯āŽŗāŽŋāŽĩāŽŋāŽĩāŽ°āŽ™ā¯āŽ•āŽŗā¯", "server_version": "āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ• āŽĒāŽ¤āŽŋāŽĒā¯āŽĒ❁", "set": "āŽ•āŽŖāŽŽā¯", @@ -1127,21 +1786,96 @@ "set_date_of_birth": "āŽĒāŽŋāŽąāŽ¨ā¯āŽ¤ āŽ¤ā¯‡āŽ¤āŽŋāŽ¯ā¯ˆ āŽ…āŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "set_profile_picture": "āŽšā¯āŽ¯āŽĩāŽŋāŽĩāŽ°āŽĒā¯ āŽĒāŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽ…āŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "set_slideshow_to_fullscreen": "āŽšā¯āŽ˛ā¯ˆāŽŸā¯āŽšā¯‹āŽĩ❈ āŽŽā¯āŽ´ā¯āŽŽā¯ˆāŽ•ā¯āŽ•ā¯ āŽ…āŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "set_stack_primary_asset": "āŽŽā¯āŽ¤āŽŠā¯āŽŽā¯ˆ āŽšā¯ŠāŽ¤ā¯āŽ¤āŽžāŽ• āŽ…āŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "setting_image_viewer_help": "āŽĩāŽŋāŽĩāŽ°āŽŽā¯ āŽĒāŽžāŽ°ā¯āŽĩā¯ˆāŽ¯āŽžāŽŗāŽ°ā¯ āŽŽā¯āŽ¤āŽ˛āŽŋāŽ˛ā¯ āŽšāŽŋāŽąāŽŋāŽ¯ āŽšāŽŋāŽąā¯ āŽ‰āŽ°ā¯āŽĩāŽ¤ā¯āŽ¤ā¯ˆ āŽāŽąā¯āŽąā¯āŽ•āŽŋāŽąāŽžāŽ°ā¯, āŽĒāŽŋāŽŠā¯āŽŠāŽ°ā¯ āŽ¨āŽŸā¯āŽ¤ā¯āŽ¤āŽ° āŽ…āŽŗāŽĩāŽŋāŽ˛āŽžāŽŠ āŽŽā¯āŽŠā¯āŽŠā¯‹āŽŸā¯āŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽāŽąā¯āŽąā¯āŽ•āŽŋāŽąāŽžāŽ°ā¯ (āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽžāŽ˛ā¯), āŽ‡āŽąā¯āŽ¤āŽŋāŽ¯āŽžāŽ• āŽ…āŽšāŽ˛ā¯ˆ āŽāŽąā¯āŽąā¯āŽ•āŽŋāŽąāŽ¤ā¯ (āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽžāŽ˛ā¯).", + "setting_image_viewer_original_subtitle": "āŽ…āŽšāŽ˛ā¯ āŽŽā¯āŽ´ā¯ āŽ¤ā¯†āŽŗāŽŋāŽĩā¯āŽ¤ā¯āŽ¤āŽŋāŽąāŽŠā¯ āŽĒāŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽāŽąā¯āŽąāŽĩā¯āŽŽā¯ (āŽĒā¯†āŽ°āŽŋāŽ¯āŽ¤ā¯!). āŽ¤āŽ°āŽĩ❁ āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯āŽŸā¯ˆāŽ•ā¯ āŽ•ā¯āŽąā¯ˆāŽ•ā¯āŽ• āŽŽā¯āŽŸāŽ•ā¯āŽ•ā¯ (āŽĒāŽŋāŽŖā¯ˆāŽ¯āŽŽā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽšāŽžāŽ¤āŽŠ āŽ¤āŽąā¯āŽ•āŽžāŽ˛āŽŋāŽ• āŽšā¯‡āŽŽāŽŋāŽĒā¯āŽĒ❁ āŽ‡āŽ°āŽŖā¯āŽŸā¯āŽŽā¯).", + "setting_image_viewer_original_title": "āŽ…āŽšāŽ˛ā¯ āŽĒāŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽāŽąā¯āŽąāŽĩā¯āŽŽā¯", + "setting_image_viewer_preview_subtitle": "āŽ¨āŽŸā¯āŽ¤ā¯āŽ¤āŽ°-āŽ¤ā¯†āŽŗāŽŋāŽĩā¯āŽ¤ā¯āŽ¤āŽŋāŽąāŽŠā¯ āŽĒāŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽāŽąā¯āŽąāŽĩā¯āŽŽā¯. āŽ…āŽšāŽ˛ā¯ˆ āŽ¨ā¯‡āŽ°āŽŸāŽŋāŽ¯āŽžāŽ• āŽāŽąā¯āŽą āŽŽā¯āŽŸāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽšāŽŋāŽąā¯āŽĒāŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽŽāŽŸā¯āŽŸā¯āŽŽā¯‡ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯.", + "setting_image_viewer_preview_title": "āŽŽā¯āŽŠā¯āŽŠā¯‹āŽŸā¯āŽŸāŽŽā¯ āŽĒāŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽāŽąā¯āŽąāŽĩā¯āŽŽā¯", + "setting_image_viewer_title": "āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯", + "setting_languages_apply": "āŽ‡āŽŸā¯", + "setting_languages_subtitle": "āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯āŽŸāŽŋāŽŠā¯ āŽŽā¯ŠāŽ´āŽŋāŽ¯ā¯ˆ āŽŽāŽžāŽąā¯āŽąāŽĩā¯āŽŽā¯", + "setting_notifications_notify_failures_grace_period": "āŽĒāŽŋāŽŠā¯āŽŠāŽŖāŽŋ āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋ āŽ¤ā¯‹āŽ˛ā¯āŽĩāŽŋāŽ•āŽŗā¯ˆ āŽ…āŽąāŽŋāŽĩāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯: {duration}", + "setting_notifications_notify_hours": "{count} āŽŽāŽŖāŽŋāŽ¨ā¯‡āŽ°āŽŽā¯", + "setting_notifications_notify_immediately": "āŽ‰āŽŸāŽŠāŽŸāŽŋāŽ¯āŽžāŽ•", + "setting_notifications_notify_minutes": "{count} āŽ¨āŽŋāŽŽāŽŋāŽŸāŽ™ā¯āŽ•āŽŗā¯", + "setting_notifications_notify_never": "āŽ’āŽ°ā¯āŽĒā¯‹āŽ¤ā¯āŽŽā¯", + "setting_notifications_notify_seconds": "{count} āŽĩāŽŋāŽ¨āŽžāŽŸāŽŋāŽ•āŽŗā¯", + "setting_notifications_single_progress_subtitle": "āŽĩāŽŋāŽ°āŽŋāŽĩāŽžāŽŠ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąā¯āŽŽā¯ āŽŽā¯āŽŠā¯āŽŠā¯‡āŽąā¯āŽą āŽšā¯†āŽ¯ā¯āŽ¤āŽŋ āŽ’āŽ°ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•ā¯", + "setting_notifications_single_progress_title": "āŽĒāŽŋāŽŠā¯āŽŠāŽŖāŽŋ āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯āŽĒāŽŋāŽ°āŽ¤āŽŋ āŽĩāŽŋāŽĩāŽ°āŽŽā¯ āŽŽā¯āŽŠā¯āŽŠā¯‡āŽąā¯āŽąāŽ¤ā¯āŽ¤ā¯ˆāŽ•ā¯ āŽ•āŽžāŽŸā¯āŽŸā¯", + "setting_notifications_subtitle": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ…āŽąāŽŋāŽĩāŽŋāŽĒā¯āŽĒ❁ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯ˆ āŽšāŽ°āŽŋāŽšā¯†āŽ¯ā¯āŽ¯āŽĩā¯āŽŽā¯", + "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_title": "āŽ…āŽšāŽ˛ā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽĩ❈ āŽ•āŽŸā¯āŽŸāŽžāŽ¯āŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽ™ā¯āŽ•āŽŗā¯", "settings": "āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", + "settings_require_restart": "āŽ‡āŽ¨ā¯āŽ¤ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒ❈āŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ āŽ‡āŽŽā¯āŽŽāŽŋāŽ¯ā¯ˆ āŽŽāŽąā¯āŽ¤ā¯ŠāŽŸāŽ•ā¯āŽ•āŽŽā¯ āŽšā¯†āŽ¯ā¯āŽ¯ā¯āŽ™ā¯āŽ•āŽŗā¯", "settings_saved": "āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ āŽšā¯‡āŽŽāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽŠ", + "setup_pin_code": "āŽŽā¯āŽŗā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ˆ āŽ…āŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "share": "āŽĒāŽ™ā¯āŽ•ā¯", + "share_action_prompt": "āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ {count} āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯", + "share_add_photos": "āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆāŽšā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "share_assets_selected": "{count} āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "share_dialog_preparing": "āŽ¤āŽ¯āŽžāŽ°āŽŋāŽ¤ā¯āŽ¤āŽ˛ā¯ ...", + "share_link": "āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❈āŽĒā¯ āŽĒāŽ•āŽŋāŽ°āŽĩā¯āŽŽā¯", "shared": "āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "shared_album_activities_input_disable": "āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤ā¯ āŽŽā¯āŽŸāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗāŽ¤ā¯", + "shared_album_activity_remove_content": "āŽ‡āŽ¨ā¯āŽ¤āŽšā¯ āŽšā¯†āŽ¯āŽ˛ā¯āŽĒāŽžāŽŸā¯āŽŸā¯ˆ āŽ¨ā¯€āŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", + "shared_album_activity_remove_title": "āŽšā¯†āŽ¯āŽ˛ā¯āŽĒāŽžāŽŸā¯āŽŸā¯ˆ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯", + "shared_album_section_people_action_error": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽĩā¯†āŽŗāŽŋāŽ¯ā¯‡āŽąā¯āŽ¤āŽ˛ā¯/āŽ¨ā¯€āŽ•ā¯āŽ•ā¯āŽ¤āŽ˛ā¯", + "shared_album_section_people_action_leave": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽĒāŽ¯āŽŠāŽ°ā¯ˆ āŽ…āŽ•āŽąā¯āŽąā¯", + "shared_album_section_people_action_remove_user": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽĒāŽ¯āŽŠāŽ°ā¯ˆ āŽ…āŽ•āŽąā¯āŽąā¯", + "shared_album_section_people_title": "āŽŽāŽ•ā¯āŽ•āŽŗā¯", "shared_by": "āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "shared_by_user": "{āŽĒāŽ¯āŽŠāŽ°āŽžāŽ˛ā¯ āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "shared_by_you": "āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽĒāŽ•āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ•ā¯ŠāŽŖā¯āŽŸāŽžāŽ°ā¯", "shared_from_partner": "{partner} āŽ‡āŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯", + "shared_intent_upload_button_progress_text": "{current} / {total} āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "shared_link_app_bar_title": "āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", + "shared_link_clipboard_copied_massage": "āŽ‡āŽŸā¯ˆāŽ¨āŽŋāŽ˛ā¯ˆāŽĒā¯āŽĒāŽ˛āŽ•ā¯ˆāŽ•ā¯āŽ•ā¯ āŽ¨āŽ•āŽ˛ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "shared_link_clipboard_text": "āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❁: {link} \nāŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯: {password}", + "shared_link_create_error": "āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❈ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•ā¯āŽŽā¯ āŽĒā¯‹āŽ¤ā¯ āŽĒāŽŋāŽ´ā¯ˆ", + "shared_link_custom_url_description": "āŽ¤āŽŠāŽŋāŽĒā¯āŽĒāŽ¯āŽŠā¯ āŽŽā¯āŽ•āŽĩāŽ°āŽŋ āŽ‰āŽŸāŽŠā¯ āŽ‡āŽ¨ā¯āŽ¤ āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❈ āŽ…āŽŖā¯āŽ•āŽĩā¯āŽŽā¯", + "shared_link_edit_description_hint": "āŽĒāŽ™ā¯āŽ•ā¯ āŽĩāŽŋāŽŗāŽ•ā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆ āŽ‰āŽŗā¯āŽŗāŽŋāŽŸāŽĩā¯āŽŽā¯", + "shared_link_edit_expire_after_option_day": "1 āŽ¨āŽžāŽŗā¯", + "shared_link_edit_expire_after_option_days": "{count} āŽ¨āŽžāŽŸā¯āŽ•āŽŗā¯", + "shared_link_edit_expire_after_option_hour": "1 āŽŽāŽŖāŽŋ āŽ¨ā¯‡āŽ°āŽŽā¯", + "shared_link_edit_expire_after_option_hours": "{count} āŽŽāŽŖāŽŋāŽ¨ā¯‡āŽ°āŽŽā¯", + "shared_link_edit_expire_after_option_minute": "1 āŽŽāŽŖāŽŋāŽ¤ā¯āŽ¤ā¯āŽŗāŽŋ", + "shared_link_edit_expire_after_option_minutes": "{count} āŽ¨āŽŋāŽŽāŽŋāŽŸāŽ™ā¯āŽ•āŽŗā¯", + "shared_link_edit_expire_after_option_months": "{count} āŽŽāŽžāŽ¤āŽ™ā¯āŽ•āŽŗā¯", + "shared_link_edit_expire_after_option_year": "{count} āŽ†āŽŖā¯āŽŸā¯", + "shared_link_edit_password_hint": "āŽĒāŽ•āŽŋāŽ°ā¯āŽĩ❁ āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽ‰āŽŗā¯āŽŗāŽŋāŽŸāŽĩā¯āŽŽā¯", + "shared_link_edit_submit_button": "āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❈āŽĒā¯ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "shared_link_error_server_url_fetch": "āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ• āŽŽā¯āŽ•āŽĩāŽ°āŽŋ āŽāŽĒā¯ āŽĒā¯†āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯", + "shared_link_expires_day": "{count} āŽ¨āŽžāŽŗā¯ āŽ•āŽžāŽ˛āŽžāŽĩāŽ¤āŽŋāŽ¯āŽžāŽ•āŽŋāŽąāŽ¤ā¯", + "shared_link_expires_days": "{count} āŽ¨āŽžāŽŸā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽ•āŽžāŽ˛āŽžāŽĩāŽ¤āŽŋāŽ¯āŽžāŽ•āŽŋāŽąāŽ¤ā¯", + "shared_link_expires_hour": "{count} āŽŽāŽŖāŽŋāŽ¨ā¯‡āŽ°āŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ•āŽžāŽ˛āŽžāŽĩāŽ¤āŽŋāŽ¯āŽžāŽ•āŽŋāŽąāŽ¤ā¯", + "shared_link_expires_hours": "{count} āŽŽāŽŖāŽŋāŽ¨ā¯‡āŽ°āŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ•āŽžāŽ˛āŽžāŽĩāŽ¤āŽŋāŽ¯āŽžāŽ•āŽŋāŽąāŽ¤ā¯", + "shared_link_expires_minute": "{count} āŽ¨āŽŋāŽŽāŽŋāŽŸāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ•āŽžāŽ˛āŽžāŽĩāŽ¤āŽŋāŽ¯āŽžāŽ•āŽŋāŽąāŽ¤ā¯", + "shared_link_expires_minutes": "{count} āŽ¨āŽŋāŽŽāŽŋāŽŸāŽ™ā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽ•āŽžāŽ˛āŽžāŽĩāŽ¤āŽŋāŽ¯āŽžāŽ•āŽŋāŽąāŽ¤ā¯", + "shared_link_expires_never": "āŽ•āŽžāŽ˛āŽžāŽĩāŽ¤āŽŋāŽ¯āŽžāŽ•āŽŋāŽąāŽ¤ā¯", + "shared_link_expires_second": "{count} āŽ‡āŽ°āŽŖā¯āŽŸāŽžāŽĩāŽ¤āŽžāŽ• āŽ•āŽžāŽ˛āŽžāŽĩāŽ¤āŽŋāŽ¯āŽžāŽ•āŽŋāŽąāŽ¤ā¯", + "shared_link_expires_seconds": "{count} āŽĩāŽŋāŽ¨āŽžāŽŸāŽŋāŽ•āŽŗāŽŋāŽ˛ā¯ āŽ•āŽžāŽ˛āŽžāŽĩāŽ¤āŽŋāŽ¯āŽžāŽ•āŽŋāŽąāŽ¤ā¯", + "shared_link_individual_shared": "āŽ¤āŽŠāŽŋāŽ¨āŽĒāŽ°ā¯ āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸāŽĩāŽ°ā¯", + "shared_link_info_chip_metadata": "Exif", + "shared_link_manage_links": "āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "shared_link_options": "āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❁ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯", + "shared_link_password_description": "āŽ‡āŽ¨ā¯āŽ¤ āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❈ āŽ…āŽŖā¯āŽ• āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯ āŽ¤ā¯‡āŽĩ❈", "shared_links": "āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯", + "shared_links_description": "āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ˆ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒā¯āŽŸāŽŠā¯ āŽĒāŽ•āŽŋāŽ°āŽĩā¯āŽŽā¯", "shared_photos_and_videos_count": "{ASSETCOUNT, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽĒāŽŋāŽą {# āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯.}}", + "shared_with_me": "āŽŽāŽŠā¯āŽŠā¯āŽŸāŽŠā¯ āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "shared_with_partner": "{āŽ•ā¯‚āŽŸā¯āŽŸāŽžāŽŗāŽ°ā¯ with āŽ‰āŽŸāŽŠā¯ āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "sharing": "āŽĒāŽ•āŽŋāŽ°ā¯āŽĩ❁", "sharing_enter_password": "āŽ‡āŽ¨ā¯āŽ¤ āŽĒāŽ•ā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆāŽ•ā¯ āŽ•āŽžāŽŖ āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽ‰āŽŗā¯āŽŗāŽŋāŽŸāŽĩā¯āŽŽā¯.", + "sharing_page_album": "āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯", + "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": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆ āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ¨ā¯€āŽ•ā¯āŽ• ⇧ āŽ āŽ…āŽ´ā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", "show_album_options": "āŽ†āŽ˛ā¯āŽĒāŽŽā¯ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯ˆāŽ•ā¯ āŽ•āŽžāŽŸā¯āŽŸā¯", "show_albums": "āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯ˆāŽ•ā¯ āŽ•āŽžāŽŸā¯āŽŸā¯", @@ -1159,9 +1893,11 @@ "show_person_options": "āŽ¨āŽĒāŽ°ā¯ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯ˆāŽ•ā¯ āŽ•āŽžāŽŸā¯āŽŸā¯", "show_progress_bar": "āŽŽā¯āŽŠā¯āŽŠā¯‡āŽąā¯āŽąāŽĒā¯ āŽĒāŽŸā¯āŽŸāŽŋāŽ¯ā¯ˆāŽ•ā¯ āŽ•āŽžāŽŸā¯āŽŸā¯", "show_search_options": "āŽ¤ā¯‡āŽŸāŽ˛ā¯ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯ˆāŽ•ā¯ āŽ•āŽžāŽŸā¯āŽŸā¯", + "show_shared_links": "āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆāŽ•ā¯ āŽ•āŽžāŽŸā¯āŽŸā¯", "show_slideshow_transition": "āŽšā¯āŽ˛ā¯ˆāŽŸā¯āŽšā¯‹ āŽŽāŽžāŽąā¯āŽąāŽ¤ā¯āŽ¤ā¯ˆāŽ•ā¯ āŽ•āŽžāŽŸā¯āŽŸā¯", "show_supporter_badge": "āŽ†āŽ¤āŽ°āŽĩāŽžāŽŗāŽ°ā¯ āŽ’āŽŸā¯āŽŸā¯", "show_supporter_badge_description": "āŽ’āŽ°ā¯ āŽ†āŽ¤āŽ°āŽĩāŽžāŽŗāŽ°ā¯ āŽĒā¯‡āŽŸā¯āŽšā¯ˆāŽ•ā¯ āŽ•āŽžāŽŸā¯āŽŸā¯", + "show_text_search_menu": "āŽ‰āŽ°ā¯ˆ āŽ¤ā¯‡āŽŸāŽ˛ā¯ āŽŽā¯†āŽŠā¯āŽĩā¯ˆāŽ•ā¯ āŽ•āŽžāŽŸā¯āŽŸā¯", "shuffle": "āŽ•āŽ˛āŽ•ā¯āŽ•ā¯", "sidebar": "āŽĒāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽŋ", "sidebar_display_description": "āŽĒāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽŋāŽ¯āŽŋāŽ˛ā¯ āŽĒāŽžāŽ°ā¯āŽĩā¯ˆāŽ•ā¯āŽ•ā¯ āŽ’āŽ°ā¯ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒā¯ˆāŽ•ā¯ āŽ•āŽžāŽŖā¯āŽĒāŽŋ", @@ -1177,12 +1913,14 @@ "sort_created": "āŽ¤ā¯‡āŽ¤āŽŋ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "sort_items": "āŽĒā¯ŠāŽ°ā¯āŽŸā¯āŽ•āŽŗāŽŋāŽŠā¯ āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ", "sort_modified": "āŽ¤ā¯‡āŽ¤āŽŋ āŽŽāŽžāŽąā¯āŽąāŽŋāŽ¯āŽŽā¯ˆāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "sort_newest": "āŽĒā¯āŽ¤āŽŋāŽ¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽŽā¯", "sort_oldest": "āŽĒāŽ´āŽŽā¯ˆāŽ¯āŽžāŽŠ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽŽā¯", "sort_people_by_similarity": "āŽ’āŽąā¯āŽąā¯āŽŽā¯ˆāŽ¯āŽžāŽ˛ā¯ āŽŽāŽ•ā¯āŽ•āŽŗā¯ˆ āŽĩāŽ°āŽŋāŽšā¯ˆāŽĒā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤ā¯āŽ™ā¯āŽ•āŽŗā¯", "sort_recent": "āŽŽāŽŋāŽ• āŽ…āŽŖā¯āŽŽā¯ˆāŽ•ā¯ āŽ•āŽžāŽ˛ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽŽā¯", "sort_title": "āŽ¤āŽ˛ā¯ˆāŽĒā¯āŽĒ❁", "source": "āŽŽā¯‚āŽ˛āŽŽā¯", "stack": "āŽ…āŽŸā¯āŽ•ā¯āŽ•ā¯", + "stack_action_prompt": "{count} āŽ…āŽŸā¯āŽ•ā¯āŽ•āŽŋ āŽĩā¯ˆāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸā¯āŽŗā¯āŽŗāŽ¤ā¯", "stack_duplicates": "āŽ…āŽŸā¯āŽ•ā¯āŽ•ā¯ āŽ¨āŽ•āŽ˛ā¯āŽ•āŽŗā¯", "stack_select_one_photo": "āŽ…āŽŸā¯āŽ•ā¯āŽ•ā¯āŽ•ā¯āŽ•ā¯ āŽ’āŽ°ā¯ āŽŽā¯āŽ•ā¯āŽ•āŽŋāŽ¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ¤ā¯āŽ¤ā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "stack_selected_photos": "āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆ āŽ…āŽŸā¯āŽ•ā¯āŽ•āŽŋ āŽĩā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", @@ -1190,16 +1928,20 @@ "stacktrace": "āŽšā¯āŽŸāŽžāŽ•ā¯ āŽŸā¯āŽ°ā¯‡āŽšā¯", "start": "āŽ¤ā¯ŠāŽŸāŽ™ā¯āŽ•ā¯", "start_date": "āŽ¤ā¯ŠāŽŸāŽ•ā¯āŽ• āŽ¤ā¯‡āŽ¤āŽŋ", + "start_date_before_end_date": "āŽ¤ā¯ŠāŽŸāŽ•ā¯āŽ• āŽ¤ā¯‡āŽ¤āŽŋ āŽ‡āŽąā¯āŽ¤āŽŋ āŽ¤ā¯‡āŽ¤āŽŋāŽ•ā¯āŽ•ā¯ āŽŽā¯āŽŠā¯ āŽ‡āŽ°ā¯āŽ•ā¯āŽ• āŽĩā¯‡āŽŖā¯āŽŸā¯āŽŽā¯", "state": "āŽŽāŽžāŽ¨āŽŋāŽ˛āŽŽā¯", "status": "āŽ¨āŽŋāŽ˛ā¯ˆ", + "stop_casting": "āŽĩāŽžāŽ°ā¯āŽĒā¯āŽĒāŽ¤ā¯ˆ āŽ¨āŽŋāŽąā¯āŽ¤ā¯āŽ¤ā¯āŽ™ā¯āŽ•āŽŗā¯", "stop_motion_photo": "āŽ‡āŽ¯āŽ•ā¯āŽ• āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ¤ā¯āŽ¤ā¯ˆ āŽ¨āŽŋāŽąā¯āŽ¤ā¯āŽ¤ā¯", "stop_photo_sharing": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆāŽĒā¯ āŽĒāŽ•āŽŋāŽ°ā¯āŽĩāŽ¤ā¯ˆ āŽ¨āŽŋāŽąā¯āŽ¤ā¯āŽ¤āŽĩāŽž?", "stop_photo_sharing_description": "{āŽ•ā¯‚āŽŸā¯āŽŸāŽžāŽŗāŽ°ā¯ your āŽ‡āŽŠāŽŋ āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆ āŽ…āŽŖā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽžāŽ¤ā¯.", "stop_sharing_photos_with_user": "āŽ‡āŽ¨ā¯āŽ¤ āŽĒāŽ¯āŽŠāŽ°ā¯āŽŸāŽŠā¯ āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆāŽĒā¯ āŽĒāŽ•āŽŋāŽ°ā¯āŽĩāŽ¤ā¯ˆ āŽ¨āŽŋāŽąā¯āŽ¤ā¯āŽ¤ā¯āŽ™ā¯āŽ•āŽŗā¯", "storage": "āŽšā¯‡āŽŽāŽŋāŽĒā¯āŽĒāŽ• āŽ‡āŽŸāŽŽā¯", "storage_label": "āŽšā¯‡āŽŽāŽŋāŽĒā¯āŽĒāŽ• āŽšāŽŋāŽŸā¯āŽŸā¯ˆ", + "storage_quota": "āŽšā¯‡āŽŽāŽŋāŽĒā¯āŽĒāŽ• āŽ’āŽ¤ā¯āŽ•ā¯āŽ•ā¯€āŽŸā¯", "storage_usage": "{used} āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽ•āŽŋāŽąāŽ¤ā¯", "submit": "āŽšāŽŽāŽ°ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "success": "āŽšā¯†āŽ¯ā¯", "suggestions": "āŽĒāŽ°āŽŋāŽ¨ā¯āŽ¤ā¯āŽ°ā¯ˆāŽ•āŽŗā¯", "sunrise_on_the_beach": "āŽ•āŽŸāŽąā¯āŽ•āŽ°ā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽšā¯‚āŽ°āŽŋāŽ¯ āŽ¤ā¯‹āŽŠā¯āŽąā¯āŽ•ā¯ˆ", "support": "āŽ‰āŽ¤āŽĩāŽŋ", @@ -1207,18 +1949,40 @@ "support_third_party_description": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯ āŽ¨āŽŋāŽąā¯āŽĩāŽ˛ā¯ āŽŽā¯‚āŽŠā¯āŽąāŽžāŽŽā¯ āŽ¤āŽ°āŽĒā¯āŽĒāŽŋāŽŠāŽ°āŽžāŽ˛ā¯ āŽ¤ā¯ŠāŽ•ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯. āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽ…āŽŠā¯āŽĒāŽĩāŽŋāŽ•ā¯āŽ•ā¯āŽŽā¯ āŽšāŽŋāŽ•ā¯āŽ•āŽ˛ā¯āŽ•āŽŗā¯ āŽ…āŽ¨ā¯āŽ¤ āŽ¤ā¯ŠāŽ•ā¯āŽĒā¯āŽĒāŽžāŽ˛ā¯ āŽāŽąā¯āŽĒāŽŸāŽ˛āŽžāŽŽā¯, āŽŽāŽŠāŽĩ❇ āŽ•ā¯€āŽ´ā¯‡āŽ¯ā¯āŽŗā¯āŽŗ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽŋ āŽŽā¯āŽ¤āŽ˛ā¯ āŽšāŽ¨ā¯āŽ¤āŽ°ā¯āŽĒā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽ…āŽĩāŽ°ā¯āŽ•āŽŗā¯āŽŸāŽŠā¯ āŽšāŽŋāŽ•ā¯āŽ•āŽ˛ā¯āŽ•āŽŗā¯ˆ āŽŽāŽ´ā¯āŽĒā¯āŽĒā¯āŽ™ā¯āŽ•āŽŗā¯.", "swap_merge_direction": "āŽ’āŽŠā¯āŽąāŽŋāŽŖā¯ˆāŽ•ā¯āŽ•ā¯āŽŽā¯ āŽ¤āŽŋāŽšā¯ˆāŽ¯ā¯ˆ āŽŽāŽžāŽąā¯āŽąāŽĩā¯āŽŽā¯", "sync": "āŽ’āŽ¤ā¯āŽ¤āŽŋāŽšā¯ˆāŽĩ❁", + "sync_albums": "āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯ˆ āŽ’āŽ¤ā¯āŽ¤āŽŋāŽšā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "sync_albums_manual_subtitle": "āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąāŽŋāŽ¯ āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ•āŽžāŽĒā¯āŽĒ❁ āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽ’āŽ¤ā¯āŽ¤āŽŋāŽšā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "sync_local": "āŽ‰āŽŗā¯āŽŗāŽ• āŽ’āŽ¤ā¯āŽ¤āŽŋāŽšā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "sync_remote": "āŽ¤ā¯ŠāŽ˛ā¯ˆāŽ¤ā¯‚āŽ°āŽ¤ā¯āŽ¤ā¯ˆ āŽ’āŽ¤ā¯āŽ¤āŽŋāŽšā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "sync_status": "āŽ¨āŽŋāŽ˛ā¯ˆāŽ¯ā¯ˆ āŽ’āŽ¤ā¯āŽ¤āŽŋāŽšā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "sync_status_subtitle": "āŽ’āŽ¤ā¯āŽ¤āŽŋāŽšā¯ˆāŽĩ❁ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒ❈ āŽĒāŽžāŽ°ā¯āŽĩā¯ˆāŽ¯āŽŋāŽŸāŽĩā¯āŽŽā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "sync_upload_album_setting_subtitle": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯āŽšāŽŋāŽ˛ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ†āŽ˛ā¯āŽĒāŽ™ā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽŋ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąāŽĩā¯āŽŽā¯", "tag": "āŽ•ā¯āŽąāŽŋāŽšā¯āŽšā¯ŠāŽ˛ā¯", "tag_assets": "āŽ•ā¯āŽąāŽŋāŽšā¯āŽšā¯ŠāŽ˛ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯", "tag_created": "āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ•ā¯āŽąāŽŋāŽšā¯āŽšā¯ŠāŽ˛ā¯: {tag}", "tag_feature_description": "āŽ¤āŽ°ā¯āŽ•ā¯āŽ•āŽ°ā¯€āŽ¤āŽŋāŽ¯āŽžāŽŠ āŽ•ā¯āŽąāŽŋāŽšā¯āŽšā¯ŠāŽ˛ā¯ āŽ¤āŽ˛ā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗāŽžāŽ˛ā¯ āŽ¤ā¯ŠāŽ•ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ˆ āŽ‰āŽ˛āŽžāŽĩā¯āŽ¤āŽ˛ā¯", - "tag_not_found_question": "āŽ•ā¯āŽąāŽŋāŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆāŽ•ā¯ āŽ•āŽŖā¯āŽŸā¯āŽĒāŽŋāŽŸāŽŋāŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆāŽ¯āŽž? <āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❁> āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ•ā¯āŽąāŽŋāŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯. ", + "tag_not_found_question": "āŽ•ā¯āŽąāŽŋāŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆāŽ•ā¯ āŽ•āŽŖā¯āŽŸā¯āŽĒāŽŋāŽŸāŽŋāŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆāŽ¯āŽž?āŽĒā¯āŽ¤āŽŋāŽ¯ āŽ•ā¯āŽąāŽŋāŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽ‰āŽ°ā¯āŽĩāŽžāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯.", + "tag_people": "āŽŽāŽ•ā¯āŽ•āŽŗā¯ˆ āŽ•ā¯āŽąāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "tag_updated": "āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ•ā¯āŽąāŽŋāŽšā¯āŽšā¯ŠāŽ˛ā¯: {tag}", "tagged_assets": "āŽ•ā¯āŽąāŽŋāŽ¤ā¯āŽ¤ā¯āŽŗā¯āŽŗāŽžāŽ°ā¯ {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} āŽŽāŽąā¯āŽą {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}}", "tags": "āŽ•ā¯āŽąāŽŋāŽšā¯āŽšā¯†āŽžāŽąā¯āŽ•āŽŗā¯", + "tap_to_run_job": "āŽĩā¯‡āŽ˛ā¯ˆāŽ¯ā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ• āŽ¤āŽŸā¯āŽŸāŽĩā¯āŽŽā¯", "template": "āŽĩāŽžāŽ°ā¯āŽĒā¯āŽĒā¯āŽ°ā¯", "theme": "āŽ•āŽ°ā¯āŽĒā¯āŽĒā¯ŠāŽ°ā¯āŽŗā¯", "theme_selection": "āŽ•āŽ°ā¯āŽĒā¯āŽĒā¯ŠāŽ°ā¯āŽŗā¯ āŽ¤ā¯‡āŽ°ā¯āŽĩ❁", "theme_selection_description": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ‰āŽ˛āŽžāŽĩāŽŋāŽ¯āŽŋāŽŠā¯ āŽ•āŽŖāŽŋāŽŠāŽŋ āŽĩāŽŋāŽ°ā¯āŽĒā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽŠā¯ āŽ…āŽŸāŽŋāŽĒā¯āŽĒāŽŸā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽ¤āŽžāŽŠāŽžāŽ•āŽĩ❇ āŽ•āŽ°ā¯āŽĒā¯āŽĒā¯ŠāŽ°ā¯āŽŗā¯ āŽ’āŽŗāŽŋ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽ‡āŽ°ā¯āŽŸā¯āŽŸāŽžāŽ• āŽ…āŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "theme_setting_asset_list_storage_indicator_title": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ āŽ“āŽŸā¯āŽ•āŽŗāŽŋāŽ˛ā¯ āŽšā¯‡āŽŽāŽŋāŽĒā¯āŽĒāŽ• āŽ•ā¯āŽąāŽŋāŽ•āŽžāŽŸā¯āŽŸāŽŋāŽ¯ā¯ˆāŽ•ā¯ āŽ•āŽžāŽŸā¯āŽŸā¯", + "theme_setting_asset_list_tiles_per_row_title": "āŽ’āŽ°ā¯ āŽĩāŽ°āŽŋāŽšā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗāŽŋāŽŠā¯ āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ ({count})", + "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_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_title": "āŽŽā¯‚āŽŠā¯āŽąā¯-āŽ¨āŽŋāŽ˛ā¯ˆ āŽāŽąā¯āŽąā¯āŽ¤āŽ˛ā¯ˆ āŽ‡āŽ¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "they_will_be_merged_together": "āŽ…āŽĩāŽ°ā¯āŽ•āŽŗā¯ āŽ’āŽŠā¯āŽąāŽžāŽ• āŽ‡āŽŖā¯ˆāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽĩāŽžāŽ°ā¯āŽ•āŽŗā¯", "third_party_resources": "āŽŽā¯‚āŽŠā¯āŽąāŽžāŽŽā¯ āŽ¤āŽ°āŽĒā¯āŽĒ❁ āŽĩāŽŗāŽ™ā¯āŽ•āŽŗā¯", "time_based_memories": "āŽ¨ā¯‡āŽ° āŽ…āŽŸāŽŋāŽĒā¯āŽĒāŽŸā¯ˆāŽ¯āŽŋāŽ˛āŽžāŽŠ āŽ¨āŽŋāŽŠā¯ˆāŽĩā¯āŽ•āŽŗā¯", @@ -1228,53 +1992,91 @@ "to_change_password": "āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯āŽ˛ā¯ˆ āŽŽāŽžāŽąā¯āŽąāŽĩā¯āŽŽā¯", "to_favorite": "āŽĒāŽŋāŽŸāŽŋāŽ¤ā¯āŽ¤", "to_login": "āŽĒā¯āŽ•ā¯āŽĒāŽ¤āŽŋāŽĩ❁", + "to_multi_select": "āŽĒāŽ˛-āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ", "to_parent": "āŽĒā¯†āŽąā¯āŽąā¯‹āŽ°āŽŋāŽŸāŽŽā¯ āŽšā¯†āŽ˛ā¯āŽ˛ā¯āŽ™ā¯āŽ•āŽŗā¯", + "to_select": "āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•", "to_trash": "āŽ•ā¯āŽĒā¯āŽĒ❈", "toggle_settings": "āŽ…āŽŽā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆ āŽŽāŽžāŽąā¯āŽąāŽĩā¯āŽŽā¯", "total": "āŽŽā¯ŠāŽ¤ā¯āŽ¤āŽŽā¯", "total_usage": "āŽŽā¯ŠāŽ¤ā¯āŽ¤ āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯", "trash": "āŽ•ā¯āŽĒā¯āŽĒ❈", + "trash_action_prompt": "{count} āŽ•ā¯āŽĒā¯āŽĒā¯ˆāŽ•ā¯āŽ•ā¯ āŽ¨āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "trash_all": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ˆāŽ¯ā¯āŽŽā¯ āŽ•ā¯āŽĒā¯āŽĒ❈", "trash_count": "āŽ•ā¯āŽĒā¯āŽĒ❈ {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽŽāŽŖā¯}", "trash_delete_asset": "āŽ•ā¯āŽĒā¯āŽĒ❈/āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯", + "trash_emptied": "āŽ•āŽžāŽ˛āŽŋāŽ¯āŽžāŽ• āŽ•ā¯āŽĒā¯āŽĒ❈", "trash_no_results_message": "āŽ•ā¯āŽĒā¯āŽĒā¯ˆāŽ¤ā¯ āŽ¤ā¯ŠāŽŸā¯āŽŸāŽŋāŽ•āŽŗā¯ āŽŽāŽąā¯āŽąā¯āŽŽā¯ āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽ•ā¯āŽ•āŽŗā¯ āŽ‡āŽ™ā¯āŽ•ā¯‡ āŽ•āŽžāŽŖā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŽā¯.", + "trash_page_delete_all": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯", + "trash_page_empty_trash_dialog_content": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ•ā¯āŽĒā¯āŽĒ❈ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆ āŽĩā¯†āŽąā¯āŽŽā¯ˆ āŽšā¯†āŽ¯ā¯āŽ¯ āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž? āŽ‡āŽ¨ā¯āŽ¤ āŽ‰āŽ°ā¯āŽĒā¯āŽĒāŽŸāŽŋāŽ•āŽŗā¯ āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯āŽšāŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ…āŽ•āŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŽā¯", + "trash_page_info": "āŽ•ā¯āŽĒā¯āŽĒā¯ˆāŽ¤ā¯ āŽ¤ā¯ŠāŽŸā¯āŽŸāŽŋāŽ•āŽŗā¯ {days} āŽ¨āŽžāŽŸā¯āŽ•āŽŗā¯āŽ•ā¯āŽ•ā¯āŽĒā¯ āŽĒāŽŋāŽąāŽ•ā¯ āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ¨ā¯€āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŽā¯", + "trash_page_no_assets": "āŽ•ā¯āŽĒā¯āŽĒ❈ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ", + "trash_page_restore_all": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ˆāŽ¯ā¯āŽŽā¯ āŽŽā¯€āŽŸā¯āŽŸā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "trash_page_select_assets_btn": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆāŽ¤ā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "trash_page_title": "({count})", "trashed_items_will_be_permanently_deleted_after": "{āŽ¨āŽžāŽŸā¯āŽ•āŽŗā¯, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽ¨āŽžāŽŗā¯} āŽĒāŽŋāŽą {# āŽ¨āŽžāŽŸā¯āŽ•āŽŗā¯}} āŽ•ā¯āŽ•ā¯āŽĒā¯ āŽĒāŽŋāŽąāŽ•ā¯ āŽ•ā¯āŽĒā¯āŽĒā¯ˆāŽ¤ā¯ āŽ¤ā¯ŠāŽŸā¯āŽŸāŽŋāŽ•āŽŗā¯ āŽ¨āŽŋāŽ°āŽ¨ā¯āŽ¤āŽ°āŽŽāŽžāŽ• āŽ¨ā¯€āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŽā¯.", + "troubleshoot": "āŽšāŽ°āŽŋāŽšā¯†āŽ¯ā¯āŽ¤āŽ˛ā¯", "type": "āŽĩāŽ•ā¯ˆ", + "unable_to_change_pin_code": "āŽŽā¯āŽŗā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ˆ āŽŽāŽžāŽąā¯āŽą āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", + "unable_to_setup_pin_code": "āŽŽā¯āŽŗā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ˆ āŽ…āŽŽā¯ˆāŽ•ā¯āŽ• āŽŽā¯āŽŸāŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", "unarchive": "āŽ…āŽŠā¯āŽ•āŽžāŽŠā¯", + "unarchive_action_prompt": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ the āŽ•āŽžāŽĒā¯āŽĒāŽ•āŽ¤ā¯āŽ¤āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ…āŽ•āŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "unarchived_count": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽĒāŽŋāŽą {āŽ…āŽ˛ā¯āŽ˛āŽžāŽ¤ #}}", + "undo": "āŽšā¯†āŽ¯āŽ˛ā¯āŽ¤āŽĩāŽŋāŽ°ā¯", "unfavorite": "āŽŽāŽžāŽąāŽžāŽ¤", + "unfavorite_action_prompt": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ the āŽĒāŽŋāŽŸāŽŋāŽ¤ā¯āŽ¤āŽĩā¯ˆāŽ•āŽŗāŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ…āŽ•āŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "unhide_person": "āŽ…āŽ°ā¯āŽĩāŽ°ā¯āŽĒā¯āŽĒāŽžāŽŠ āŽ¨āŽĒāŽ°ā¯", "unknown": "āŽ¤ā¯†āŽ°āŽŋāŽ¯āŽĩāŽŋāŽ˛ā¯āŽ˛ā¯ˆ", + "unknown_country": "āŽ¤ā¯†āŽ°āŽŋāŽ¯āŽžāŽ¤ āŽ¨āŽžāŽŸā¯", "unknown_year": "āŽ¤ā¯†āŽ°āŽŋāŽ¯āŽžāŽ¤ āŽ†āŽŖā¯āŽŸā¯", "unlimited": "āŽĩāŽ°āŽŽā¯āŽĒāŽąā¯āŽąāŽ¤ā¯", "unlink_motion_video": "āŽ‡āŽ¯āŽ•ā¯āŽ• āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹āŽĩ❈ āŽ‡āŽŖā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "unlink_oauth": "OAUTH āŽ āŽ‡āŽŖā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "unlinked_oauth_account": "āŽ‡āŽŖā¯ˆāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸāŽžāŽ¤ OAUTH āŽ•āŽŖāŽ•ā¯āŽ•ā¯", + "unmute_memories": "āŽŠāŽŸā¯āŽ°ā¯āŽĩāŽ˛ā¯ āŽ¨āŽŋāŽŠā¯ˆāŽĩā¯āŽ•āŽŗā¯", "unnamed_album": "āŽĒā¯†āŽ¯āŽ°āŽŋāŽŸāŽĒā¯āŽĒāŽŸāŽžāŽ¤ āŽ†āŽ˛ā¯āŽĒāŽŽā¯", "unnamed_album_delete_confirmation": "āŽ‡āŽ¨ā¯āŽ¤ āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤ā¯ˆ āŽ¨ā¯€āŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", "unnamed_share": "āŽĒā¯†āŽ¯āŽ°āŽŋāŽŸāŽĒā¯āŽĒāŽŸāŽžāŽ¤ āŽĒāŽ™ā¯āŽ•ā¯", "unsaved_change": "āŽšā¯‡āŽŽāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸāŽžāŽ¤ āŽŽāŽžāŽąā¯āŽąāŽŽā¯", "unselect_all": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¤ā¯‡āŽ°ā¯āŽĩ❁ āŽšā¯†āŽ¯ā¯āŽ¯ā¯āŽ™ā¯āŽ•āŽŗā¯", "unselect_all_duplicates": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ āŽ¨āŽ•āŽ˛ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "unselect_all_in": "{group}", "unstack": "āŽ…āŽŠā¯-āŽšā¯āŽŸāŽžāŽ•ā¯", + "unstack_action_prompt": "{count} āŽ¤āŽŸā¯ˆāŽ¯āŽŋāŽŠā¯āŽąāŽŋ", "unstacked_assets_count": "āŽ…āŽŠā¯-āŽšā¯āŽŸāŽžāŽ•ā¯ {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} āŽĒāŽŋāŽą {# āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}}", + "untagged": "āŽ…āŽĩāŽŋāŽ´ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸāŽžāŽ¤āŽ¤ā¯", "up_next": "āŽ…āŽŸā¯āŽ¤ā¯āŽ¤ā¯", + "update_location_action_prompt": "{count} āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗāŽŋāŽŠā¯ āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽŋāŽŸāŽ¤ā¯āŽ¤ā¯ˆāŽĒā¯ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯:", + "updated_at": "āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "updated_password": "āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ•āŽŸāŽĩā¯āŽšā¯āŽšā¯ŠāŽ˛ā¯", "upload": "āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąā¯āŽŽā¯", + "upload_action_prompt": "{count} āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąā¯āŽĩāŽ¤āŽąā¯āŽ•ā¯ āŽĩāŽ°āŽŋāŽšā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽ¨āŽŋāŽąā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "upload_concurrency": "āŽ’āŽ¤ā¯āŽ¤āŽŋāŽšā¯ˆāŽĩ❈āŽĒā¯ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąāŽĩā¯āŽŽā¯", + "upload_details": "āŽĩāŽŋāŽĩāŽ°āŽ™ā¯āŽ•āŽŗā¯ˆ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąāŽĩā¯āŽŽā¯", + "upload_dialog_info": "āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ (āŽ•āŽŗā¯ˆ) āŽšā¯‡āŽĩā¯ˆāŽ¯āŽ•āŽ¤ā¯āŽ¤āŽŋāŽąā¯āŽ•ā¯ āŽ•āŽžāŽĒā¯āŽĒ❁āŽĒā¯ āŽĒāŽŋāŽ°āŽ¤āŽŋ āŽŽāŽŸā¯āŽ•ā¯āŽ• āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒā¯āŽ•āŽŋāŽąā¯€āŽ°ā¯āŽ•āŽŗāŽž?", + "upload_dialog_title": "āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąāŽĩā¯āŽŽā¯", "upload_errors": "āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąāŽŽā¯ {āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽĒāŽŋāŽ´ā¯ˆ} āŽŽāŽąā¯āŽą {# āŽĒāŽŋāŽ´ā¯ˆāŽ•āŽŗā¯}} āŽ‰āŽŸāŽŠā¯ āŽŽā¯āŽŸāŽŋāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯, āŽĒā¯āŽ¤āŽŋāŽ¯ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽą āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆāŽ•ā¯ āŽ•āŽžāŽŖ āŽĒāŽ•ā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆāŽĒā¯ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯.", + "upload_finished": "āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąāŽŽā¯ āŽŽā¯āŽŸāŽŋāŽ¨ā¯āŽ¤āŽ¤ā¯", "upload_progress": "āŽŽā¯€āŽ¤āŽŽā¯āŽŗā¯āŽŗ {āŽŽā¯€āŽ¤āŽŽā¯āŽŗā¯āŽŗ, āŽŽāŽŖā¯} - āŽšā¯†āŽ¯āŽ˛āŽžāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸ {āŽšā¯†āŽ¯āŽ˛āŽžāŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯, āŽŽāŽŖā¯}/{āŽŽā¯ŠāŽ¤ā¯āŽ¤āŽŽā¯, āŽŽāŽŖā¯}", "upload_skipped_duplicates": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽ¨āŽ•āŽ˛ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯} āŽĒāŽŋāŽą {# āŽ¨āŽ•āŽ˛ā¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯}}", "upload_status_duplicates": "āŽ¨āŽ•āŽ˛ā¯āŽ•āŽŗā¯", "upload_status_errors": "āŽĒāŽŋāŽ´ā¯ˆāŽ•āŽŗā¯", "upload_status_uploaded": "āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "upload_success": "āŽĩā¯†āŽąā¯āŽąāŽŋāŽ¯ā¯ˆāŽĒā¯ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąāŽĩā¯āŽŽā¯, āŽĒā¯āŽ¤āŽŋāŽ¯ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽą āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆāŽ•ā¯ āŽ•āŽžāŽŖ āŽĒāŽ•ā¯āŽ•āŽ¤ā¯āŽ¤ā¯ˆāŽĒā¯ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯.", + "upload_to_immich": "āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯āŽšāŽŋāŽąā¯āŽ•ā¯ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąā¯ ({count})", + "uploading": "āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąā¯āŽ•āŽŋāŽąāŽ¤ā¯", + "uploading_media": "āŽŽā¯€āŽŸāŽŋāŽ¯āŽžāŽĩ❈āŽĒā¯ āŽĒāŽ¤āŽŋāŽĩā¯‡āŽąā¯āŽąā¯āŽ•āŽŋāŽąāŽ¤ā¯", "url": "āŽŽā¯āŽ•āŽĩāŽ°āŽŋ", "usage": "āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯", + "use_biometric": "āŽĒāŽ¯ā¯‹āŽŽā¯†āŽŸā¯āŽ°āŽŋāŽ•ā¯āŽ•ā¯ˆāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", + "use_current_connection": "āŽ¤āŽąā¯āŽĒā¯‹āŽ¤ā¯ˆāŽ¯ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❈āŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", "use_custom_date_range": "āŽ…āŽ¤āŽąā¯āŽ•ā¯ āŽĒāŽ¤āŽŋāŽ˛āŽžāŽ• āŽ¤āŽŠāŽŋāŽĒā¯āŽĒāŽ¯āŽŠā¯ āŽ¤ā¯‡āŽ¤āŽŋ āŽĩāŽ°āŽŽā¯āŽĒ❈āŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", "user": "āŽĒāŽ¯āŽŠāŽ°ā¯", + "user_has_been_deleted": "āŽ‡āŽ¨ā¯āŽ¤āŽĒā¯ āŽĒāŽ¯āŽŠāŽ°ā¯ āŽ¨ā¯€āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽžāŽ°ā¯.", "user_id": "āŽĒāŽ¯āŽŠāŽ°ā¯ āŽāŽŸāŽŋ", "user_liked": "{user} āŽĩāŽŋāŽ°ā¯āŽŽā¯āŽĒāŽŋāŽŠāŽžāŽ°ā¯ {āŽĩāŽ•ā¯ˆ, āŽ¤ā¯‡āŽ°ā¯āŽ¨ā¯āŽ¤ā¯†āŽŸā¯, āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽŽā¯ {this photo} āŽĩā¯€āŽŸāŽŋāŽ¯ā¯‹ {this video} āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ {this asset} āŽĒāŽŋāŽą {it}}", + "user_pin_code_settings": "āŽĒāŽŋāŽŠā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯", + "user_pin_code_settings_description": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽĒāŽŋāŽŠā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "user_privacy": "āŽĒāŽ¯āŽŠāŽ°ā¯ āŽ¤āŽŠāŽŋāŽ¯ā¯āŽ°āŽŋāŽŽā¯ˆ", "user_purchase_settings": "āŽĩāŽžāŽ™ā¯āŽ•", "user_purchase_settings_description": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽĩāŽžāŽ™ā¯āŽ•ā¯āŽ¤āŽ˛ā¯ˆ āŽ¨āŽŋāŽ°ā¯āŽĩāŽ•āŽŋāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", "user_role_set": "{user} {āŽĒāŽžāŽ¤ā¯āŽ¤āŽŋāŽ°āŽŽāŽžāŽ• āŽ…āŽŽā¯ˆāŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", @@ -1283,12 +2085,14 @@ "user_usage_stats_description": "āŽ•āŽŖāŽ•ā¯āŽ•ā¯ āŽ‰āŽĒāŽ¯ā¯‹āŽ•āŽĒā¯ āŽĒā¯āŽŗā¯āŽŗāŽŋāŽĩāŽŋāŽĩāŽ°āŽ™ā¯āŽ•āŽŗā¯ˆāŽĒā¯ āŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•", "username": "āŽĒāŽ¯āŽŠāŽ°ā¯āŽĒā¯†āŽ¯āŽ°ā¯", "users": "āŽĒāŽ¯āŽŠāŽ°ā¯āŽ•āŽŗā¯", + "users_added_to_album_count": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽĒāŽ¯āŽŠāŽ°ā¯} āŽŽāŽąā¯āŽą {# āŽĒāŽ¯āŽŠāŽ°ā¯āŽ•āŽŗā¯}} āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤āŽŋāŽ˛ā¯ āŽšā¯‡āŽ°ā¯āŽ•ā¯āŽ•āŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "utilities": "āŽĒāŽ¯āŽŠā¯āŽĒāŽžāŽŸā¯āŽ•āŽŗā¯", "validate": "āŽšāŽ°āŽŋāŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "validate_endpoint_error": "āŽ¤āŽ¯āŽĩā¯āŽšā¯†āŽ¯ā¯āŽ¤ā¯ āŽ’āŽ°ā¯ āŽšā¯†āŽ˛ā¯āŽ˛ā¯āŽĒāŽŸāŽŋāŽ¯āŽžāŽ•ā¯āŽŽā¯ URL āŽ āŽ‰āŽŗā¯āŽŗāŽŋāŽŸāŽĩā¯āŽŽā¯", "variables": "āŽŽāŽžāŽąāŽŋāŽ•āŽŗā¯", "version": "āŽĒāŽ¤āŽŋāŽĒā¯āŽĒ❁", "version_announcement_closing": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ¨āŽŖā¯āŽĒāŽ°ā¯, āŽ…āŽ˛ā¯†āŽ•ā¯āŽšā¯", - "version_announcement_message": "āŽ†āŽ¯ā¯! āŽ‡āŽŽā¯āŽŽāŽŋāŽ¯āŽŋāŽŠā¯ āŽĒā¯āŽ¤āŽŋāŽ¯ āŽĒāŽ¤āŽŋāŽĒā¯āŽĒ❁ āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯. āŽŽāŽ¨ā¯āŽ¤āŽĩā¯ŠāŽ°ā¯ āŽ¤āŽĩāŽąāŽžāŽŠ āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¤āŽŸā¯āŽ•ā¯āŽ• āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒ❁ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ¤ā¯āŽ¤ āŽ¨āŽŋāŽ˛ā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽ¤ā¯ˆ āŽ‰āŽąā¯āŽ¤āŽŋāŽšā¯†āŽ¯ā¯āŽ¯ <āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒ❁> āŽĩā¯†āŽŗāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯āŽ•ā¯ āŽ•ā¯āŽąāŽŋāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ āŽāŽĒā¯ āŽĒāŽŸāŽŋāŽ•ā¯āŽ• āŽšāŽŋāŽąāŽŋāŽ¤ā¯ āŽ¨ā¯‡āŽ°āŽŽā¯ āŽ’āŽ¤ā¯āŽ•ā¯āŽ•ā¯āŽ™ā¯āŽ•āŽŗā¯, āŽ•ā¯āŽąāŽŋāŽĒā¯āŽĒāŽžāŽ• āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽ•āŽžāŽĩāŽąā¯āŽ•ā¯‹āŽĒā¯āŽ°āŽ¤ā¯āŽ¤ā¯ˆāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽŋāŽŠāŽžāŽ˛ā¯ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯ āŽ¨āŽŋāŽ•āŽ´ā¯āŽĩ❈ āŽ¤āŽžāŽŠāŽžāŽ•āŽĩ❇ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽĒā¯āŽĒāŽ¤ā¯ˆāŽ•ā¯ āŽ•ā¯ˆāŽ¯āŽžāŽŗā¯āŽŽā¯ āŽŽāŽ¨ā¯āŽ¤āŽĩā¯ŠāŽ°ā¯ āŽĒā¯ŠāŽąāŽŋāŽŽā¯āŽąā¯ˆāŽ¯ā¯ˆāŽ¯ā¯āŽŽā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽŋāŽŠāŽžāŽ˛ā¯.", + "version_announcement_message": "āŽĩāŽŖāŽ•ā¯āŽ•āŽŽā¯! āŽ‡āŽŽā¯āŽŽāŽŋāŽ¯āŽŋāŽŠā¯ āŽĒā¯āŽ¤āŽŋāŽ¯ āŽĒāŽ¤āŽŋāŽĒā¯āŽĒ❁ āŽ•āŽŋāŽŸā¯ˆāŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯. āŽŽāŽ¨ā¯āŽ¤āŽĩā¯ŠāŽ°ā¯ āŽ¤āŽĩāŽąāŽžāŽŠ āŽ•āŽ°ā¯āŽ¤ā¯āŽ¤ā¯āŽ•ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽ¤āŽŸā¯āŽ•ā¯āŽ• āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ…āŽŽā¯ˆāŽĒā¯āŽĒ❁ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽ¤ā¯āŽ¤ āŽ¨āŽŋāŽ˛ā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽ‡āŽ°ā¯āŽĒā¯āŽĒāŽ¤ā¯ˆ āŽ‰āŽąā¯āŽ¤āŽŋāŽšā¯†āŽ¯ā¯āŽ¯ āŽĩā¯†āŽŗāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯āŽ•ā¯ āŽ•ā¯āŽąāŽŋāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ āŽāŽĒā¯ āŽĒāŽŸāŽŋāŽ•ā¯āŽ• āŽšāŽŋāŽąāŽŋāŽ¤ā¯ āŽ¨ā¯‡āŽ°āŽŽā¯ āŽ’āŽ¤ā¯āŽ•ā¯āŽ•ā¯āŽ™ā¯āŽ•āŽŗā¯, āŽ•ā¯āŽąāŽŋāŽĒā¯āŽĒāŽžāŽ• āŽ¨ā¯€āŽ™ā¯āŽ•āŽŗā¯ āŽ•āŽžāŽĩāŽąā¯āŽ•ā¯‹āŽĒā¯āŽ°āŽ¤ā¯āŽ¤ā¯ˆāŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽŋāŽŠāŽžāŽ˛ā¯ āŽ…āŽ˛ā¯āŽ˛āŽ¤ā¯ āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯ āŽ¨āŽŋāŽ•āŽ´ā¯āŽĩ❈ āŽ¤āŽžāŽŠāŽžāŽ•āŽĩ❇ āŽĒā¯āŽ¤ā¯āŽĒā¯āŽĒāŽŋāŽĒā¯āŽĒāŽ¤ā¯ˆāŽ•ā¯ āŽ•ā¯ˆāŽ¯āŽžāŽŗā¯āŽŽā¯ āŽŽāŽ¨ā¯āŽ¤āŽĩā¯ŠāŽ°ā¯ āŽĒā¯ŠāŽąāŽŋāŽŽā¯āŽąā¯ˆāŽ¯ā¯ˆāŽ¯ā¯āŽŽā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽŋāŽŠāŽžāŽ˛ā¯.", "version_history": "āŽĒāŽ¤āŽŋāŽĒā¯āŽĒ❁ āŽĩāŽ°āŽ˛āŽžāŽąā¯", "version_history_item": "{version} āŽ‡āŽ˛ā¯ {date} āŽ¨āŽŋāŽąā¯āŽĩāŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "video": "āŽ’āŽŗāŽŋāŽ¤ā¯‹āŽąā¯āŽąāŽŽā¯", @@ -1300,21 +2104,33 @@ "view_album": "āŽ†āŽ˛ā¯āŽĒāŽ¤ā¯āŽ¤ā¯ˆāŽ•ā¯ āŽ•āŽžāŽŖā¯āŽ•", "view_all": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ˆāŽ¯ā¯āŽŽā¯ āŽ•āŽžāŽŖā¯āŽ•", "view_all_users": "āŽ…āŽŠā¯ˆāŽ¤ā¯āŽ¤ā¯ āŽĒāŽ¯āŽŠāŽ°ā¯āŽ•āŽŗā¯ˆāŽ¯ā¯āŽŽā¯ āŽ•āŽžāŽŖā¯āŽ•", + "view_details": "āŽĩāŽŋāŽĩāŽ°āŽ™ā¯āŽ•āŽŗā¯ˆāŽĒā¯ āŽĒāŽžāŽ°ā¯", "view_in_timeline": "āŽ•āŽžāŽ˛āŽĩāŽ°āŽŋāŽšā¯ˆāŽ¯āŽŋāŽ˛ā¯ āŽ•āŽžāŽŖā¯āŽ•", + "view_link": "āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒā¯ˆāŽ•ā¯ āŽ•āŽžāŽŖā¯āŽ•", "view_links": "āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ˆāŽ•ā¯ āŽ•āŽžāŽŖā¯āŽ•", "view_name": "āŽĒāŽžāŽ°ā¯āŽĩ❈", "view_next_asset": "āŽ…āŽŸā¯āŽ¤ā¯āŽ¤ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆ āŽ•āŽžāŽŖā¯āŽ•", "view_previous_asset": "āŽŽā¯āŽ¨ā¯āŽ¤ā¯ˆāŽ¯ āŽšā¯ŠāŽ¤ā¯āŽ¤ā¯ˆāŽĒā¯ āŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "view_qr_code": "QR āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯āŽŸā¯ˆāŽ•ā¯ āŽ•āŽžāŽŸā¯āŽŸā¯", + "view_similar_photos": "āŽ‡āŽ¤ā¯‡ āŽĒā¯‹āŽŠā¯āŽą āŽĒā¯āŽ•ā¯ˆāŽĒā¯āŽĒāŽŸāŽ™ā¯āŽ•āŽŗā¯ˆāŽ•ā¯ āŽ•āŽžāŽŸā¯āŽŸā¯", "view_stack": "āŽ•āŽžāŽŖā¯āŽ• āŽ…āŽŸā¯āŽ•ā¯āŽ•ā¯", - "visibility_changed": "{āŽŽāŽŖā¯āŽŖāŽŋāŽ•ā¯āŽ•ā¯ˆ, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽ¨āŽĒāŽ°ā¯} āŽŽāŽąā¯āŽą {# āŽ¨āŽĒāŽ°ā¯āŽ•āŽŗā¯} āŽ•ā¯āŽ•ā¯ āŽ•ā¯āŽ•ā¯ āŽ¤ā¯†āŽ°āŽŋāŽĩā¯āŽ¨āŽŋāŽ˛ā¯ˆ āŽŽāŽžāŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", + "view_user": "āŽĒāŽ¯āŽŠāŽ°ā¯ˆāŽĒā¯ āŽĒāŽžāŽ°ā¯āŽ•ā¯āŽ•āŽĩā¯āŽŽā¯", + "viewer_remove_from_stack": "āŽ…āŽŸā¯āŽ•ā¯āŽ•āŽŋāŽ˛āŽŋāŽ°ā¯āŽ¨ā¯āŽ¤ā¯ āŽ…āŽ•āŽąā¯āŽąā¯", + "viewer_stack_use_as_main_asset": "āŽĒāŽŋāŽ°āŽ¤āŽžāŽŠ āŽšā¯ŠāŽ¤ā¯āŽ¤āŽžāŽ•āŽĒā¯ āŽĒāŽ¯āŽŠā¯āŽĒāŽŸā¯āŽ¤ā¯āŽ¤āŽĩā¯āŽŽā¯", + "viewer_unstack": "āŽ…āŽŸā¯āŽ•ā¯āŽ•ā¯ˆ āŽ¨ā¯€āŽ•ā¯āŽ•ā¯", + "visibility_changed": "{count, plural, one {# āŽ¨āŽĒāŽ°ā¯} other {# āŽ¨āŽĒāŽ°ā¯āŽ•āŽŗā¯}} āŽ•ā¯āŽ•āŽžāŽŠ āŽ¤ā¯†āŽ°āŽŋāŽĩā¯āŽ¨āŽŋāŽ˛ā¯ˆ āŽŽāŽžāŽąā¯āŽąāŽĒā¯āŽĒāŽŸā¯āŽŸāŽ¤ā¯", "waiting": "āŽ•āŽžāŽ¤ā¯āŽ¤āŽŋāŽ°ā¯āŽ•ā¯āŽ•āŽŋāŽąāŽ¤ā¯", "warning": "āŽŽāŽšā¯āŽšāŽ°āŽŋāŽ•ā¯āŽ•ā¯ˆ", "week": "āŽĩāŽžāŽ°āŽŽā¯", "welcome": "āŽĩāŽ°āŽĩā¯‡āŽąā¯āŽ•āŽŋāŽąā¯‹āŽŽā¯", "welcome_to_immich": "āŽ‡āŽŽā¯āŽŽāŽŋāŽšā¯āŽšāŽŋāŽąā¯āŽ•ā¯ āŽĩāŽ°ā¯āŽ•", + "wifi_name": "āŽĩā¯ˆāŽƒāŽĒ❈ āŽĒā¯†āŽ¯āŽ°ā¯", + "wrong_pin_code": "āŽ¤āŽĩāŽąāŽžāŽŠ āŽĒāŽŋāŽŠā¯ āŽ•ā¯āŽąāŽŋāŽ¯ā¯€āŽŸā¯", "year": "āŽ†āŽŖā¯āŽŸā¯", - "years_ago": "{āŽ†āŽŖā¯āŽŸā¯āŽ•āŽŗā¯, āŽĒāŽŠā¯āŽŽā¯ˆ, āŽ’āŽŠā¯āŽąā¯ {# āŽ†āŽŖā¯āŽŸā¯} āŽŽāŽąā¯āŽą {# āŽ†āŽŖā¯āŽŸā¯āŽ•āŽŗā¯}}} āŽŽā¯āŽŠā¯āŽĒ❁", + "years_ago": "{years, plural, one {# āŽ†āŽŖā¯āŽŸā¯} other {# āŽ†āŽŖā¯āŽŸā¯āŽ•āŽŗā¯}} āŽŽā¯āŽŠā¯āŽĒ❁", "yes": "āŽ†āŽŽā¯", "you_dont_have_any_shared_links": "āŽ‰āŽ™ā¯āŽ•āŽŗāŽŋāŽŸāŽŽā¯ āŽĒāŽ•āŽŋāŽ°āŽĒā¯āŽĒāŽŸā¯āŽŸ āŽ‡āŽŖā¯ˆāŽĒā¯āŽĒā¯āŽ•āŽŗā¯ āŽŽāŽ¤ā¯āŽĩā¯āŽŽā¯ āŽ‡āŽ˛ā¯āŽ˛ā¯ˆ", - "zoom_image": "āŽĒā¯†āŽ°āŽŋāŽ¤āŽžāŽ•ā¯āŽ• āŽĒāŽŸāŽŽā¯" + "your_wifi_name": "āŽ‰āŽ™ā¯āŽ•āŽŗā¯ āŽĩā¯ˆāŽƒāŽĒ❈ āŽĒā¯†āŽ¯āŽ°ā¯", + "zoom_image": "āŽĒā¯†āŽ°āŽŋāŽ¤āŽžāŽ•ā¯āŽ• āŽĒāŽŸāŽŽā¯", + "zoom_to_bounds": "āŽŽāŽ˛ā¯āŽ˛ā¯ˆāŽ•ā¯āŽ•ā¯ āŽĒā¯†āŽ°āŽŋāŽ¤āŽžāŽ•ā¯āŽ•ā¯" } diff --git a/i18n/tr.json b/i18n/tr.json index f9355564ad..0f80e60e85 100644 --- a/i18n/tr.json +++ b/i18n/tr.json @@ -11,16 +11,16 @@ "activity_changed": "Etkinlik {enabled, select, true {etkin} other {devre dÄąÅŸÄą}}", "add": "Ekle", "add_a_description": "AÃ§Äąklama ekle", - "add_a_location": "Lokasyon ekle", + "add_a_location": "Bir konum ekle", "add_a_name": "İsim ekle", "add_a_title": "BaşlÄąk ekle", "add_birthday": "Doğum gÃŧnÃŧ ekle", "add_endpoint": "Uç nokta ekle", "add_exclusion_pattern": "Hariç tutma deseni ekle", "add_import_path": "İçe aktarma yolu ekle", - "add_location": "Lokasyon ekle", + "add_location": "Konum ekle", "add_more_users": "Daha fazla kullanÄącÄą ekle", - "add_partner": "Partner ekle", + "add_partner": "Ortak ekle", "add_path": "Yol ekle", "add_photos": "Fotoğraf ekle", "add_tag": "Etiket ekle", @@ -28,23 +28,26 @@ "add_to_album": "AlbÃŧme ekle", "add_to_album_bottom_sheet_added": "{album} albÃŧmÃŧne eklendi", "add_to_album_bottom_sheet_already_exists": "Zaten {album} albÃŧmÃŧne ekli", + "add_to_album_bottom_sheet_some_local_assets": "BazÄą yerel Ãļğeler albÃŧme eklenemedi", + "add_to_album_toggle": "{album} için seçimi değiştir", "add_to_albums": "AlbÃŧmlere ekle", "add_to_albums_count": "{count} albÃŧmlerine ekle", "add_to_shared_album": "PaylaÅŸÄąlan albÃŧme ekle", + "add_upload_to_stack": "YÃŧklemeyi yığına ekle", "add_url": "URL ekle", "added_to_archive": "Arşive eklendi", "added_to_favorites": "Favorilere eklendi", "added_to_favorites_count": "{count, number} fotoğraf favorilere eklendi", "admin": { "add_exclusion_pattern_description": "Hariç tutma desenleri ekleyin. *, ** ve ? kullanÄąlarak Globbing (temsili yer doldurucu karakter) desteklenir. Farzedelim \"Raw\" adlÄą bir dizininiz var, içinde ki tÃŧm dosyalarÄą yoksaymak için \"**/Raw/**\" şeklinde yazabilirsiniz. \".tif\" ile biten tÃŧm dosyalarÄą yoksaymak için \"**/*.tif\" yazabilirsiniz. Mutlak yolu yoksaymak için \"/yoksayÄąlacak/olan/yol/**\" şeklinde yazabilirsiniz.", - "admin_user": "YÃļnetici kullanÄącÄąsÄą", - "asset_offline_description": "Bu harici kÃŧtÃŧphane varlığı artÄąk diskte bulunmuyor ve çÃļp kutusuna taÅŸÄąndÄą. Dosya kÃŧtÃŧphane içinde taÅŸÄąndÄąysa, yeni karÅŸÄąlÄąk gelen varlÄąk için zaman çizelgenizi kontrol edin. Bu varlığı geri yÃŧklemek için lÃŧtfen aşağıdaki dosya yolunun Immich tarafÄąndan erişilebilir olduğundan emin olun ve kÃŧtÃŧphaneyi tarayÄąn.", + "admin_user": "YÃļnetici KullanÄącÄą", + "asset_offline_description": "Bu harici kÃŧtÃŧphane Ãļğesi artÄąk diskte bulunmuyor ve çÃļp kutusuna taÅŸÄąndÄą. Dosya kÃŧtÃŧphane içinde taÅŸÄąndÄąysa, yeni karÅŸÄąlÄąk gelen Ãļğe için zaman çizelgenizi kontrol edin. Bu Ãļğeyi geri yÃŧklemek için lÃŧtfen aşağıdaki dosya yolunun Immich tarafÄąndan erişilebilir olduğundan emin olun ve kÃŧtÃŧphaneyi tarayÄąn.", "authentication_settings": "Yetkilendirme AyarlarÄą", "authentication_settings_description": "Şifre, OAuth, ve diğer yetkilendirme ayarlarÄąnÄą yÃļnet", "authentication_settings_disable_all": "TÃŧm giriş yÃļntemlerini devre dÄąÅŸÄą bÄąrakmak istediğinize emin misiniz? Giriş yapma fonksiyonu tamamen devre dÄąÅŸÄą bÄąrakÄąlacak.", "authentication_settings_reenable": "Yeniden aktif etmek için Sunucu Komutu'nu kullanÄąn.", "background_task_job": "Arka Plan GÃļrevleri", - "backup_database": "VeritabanÄą yığınÄą oluştur", + "backup_database": "VeritabanÄą YığınÄą Oluştur", "backup_database_enable_description": "VeritabanÄą yığınlarÄąnÄą etkinleştir", "backup_keep_last_amount": "TutulmasÄą gereken geçmiş yığınÄą miktarÄą", "backup_onboarding_1_description": "bulutta veya başka bir fiziksel konumda bulunan yedek kopya.", @@ -54,20 +57,20 @@ "backup_onboarding_footer": "Immich'i yedekleme hakkÄąnda daha fazla bilgi için lÃŧtfen belgelere bakÄąn.", "backup_onboarding_parts_title": "3-2-1 yedekleme şunlarÄą içerir:", "backup_onboarding_title": "Yedeklemeler", - "backup_settings": "VeritabanÄą yığınÄą ayarlarÄą", + "backup_settings": "VeritabanÄą YığınÄą AyarlarÄą", "backup_settings_description": "VeritabanÄą dÃļkÃŧm ayarlarÄąnÄą yÃļnet.", "cleared_jobs": "{job} için işler temizlendi", "config_set_by_file": "Ayarlar şuanda config dosyasÄą tarafÄąndan ayarlanmÄąÅŸtÄąr", "confirm_delete_library": "{library} kÃŧtÃŧphanesini silmek istediğinize emin misiniz?", - "confirm_delete_library_assets": "Bu kÃŧtÃŧphaneyi silmek istediğinize emin misiniz? Bu işlem {count, plural, one {# tane varlığı} other {all # tane varlığı}} Immich'den silecek ve bu işlem geri alÄąnamaz. Silinen dosyalar diskten silinmeyecek.", - "confirm_email_below": "Onaylamak için aşağıya {email} yazÄąn", + "confirm_delete_library_assets": "Bu kÃŧtÃŧphaneyi silmek istediğinize emin misiniz? Bu işlem {count, plural, one {# tane Ãļğeyi} other {all # tane Ãļğeyi}} Immich'den silecek ve bu işlem geri alÄąnamaz. Dosyalar diskte kalacaktÄąr.", + "confirm_email_below": "Onaylamak için aşağıya \"{email}\" yazÄąn", "confirm_reprocess_all_faces": "TÃŧm yÃŧzleri tekrardan işlemek istediğinize emin misiniz? Bu işlem isimlendirilmiş insanlarÄą da silecek.", "confirm_user_password_reset": "{user} adlÄą kullanÄącÄąnÄąn şifresini sÄąfÄąrlamak istediğinize emin misiniz?", "confirm_user_pin_code_reset": "{user} adlÄą kullanÄącÄąnÄąn PIN kodunu sÄąfÄąrlamak istediğinize emin misiniz?", "create_job": "GÃļrev oluştur", - "cron_expression": "Cron İfadesi", + "cron_expression": "Cron ifadesi", "cron_expression_description": "Cron formatÄąnÄą kullanarak tarama aralığınÄą belirle. Daha fazla bilgi için Ãļrneğin Crontab Guru’ya bakÄąn", - "cron_expression_presets": "Cron İfadesi ÖnayarlarÄą", + "cron_expression_presets": "Cron ifadesi Ãļn ayarlarÄą", "disable_login": "Girişi devre dÄąÅŸÄą bÄąrak", "duplicate_detection_job_description": "Benzer fotoğraflarÄą bulmak için makine Ãļğrenmesini çalÄąÅŸtÄąr. Bu işlem AkÄąllÄą Arama'ya bağlÄądÄąr", "exclusion_pattern_description": "KÃŧtÃŧphaneyi tararken dosya ve klasÃļrleri gÃļrmezden gelmek için dÄąÅŸlama desenlerini kullanabilirsiniz. RAW dosyalarÄą gibi bazÄą dosya ve klasÃļrleri içe aktarmak istemediğinizde bu seçeneği kullanabilirsiniz.", @@ -76,25 +79,25 @@ "face_detection_description": "Makine Ãļğrenimi kullanarak varlÄąklardaki yÃŧzleri tespit et. Videolar için sadece kÃŧçÃŧk resim (thumbnail) dikkate alÄąnÄąr. 'Yenile' tÃŧm varlÄąklarÄą yeniden işler. 'SÄąfÄąrla', mevcut tÃŧm yÃŧz verilerini temizleyerek işlemi yeniden başlatÄąr. 'Eksik' henÃŧz işlenmemiş varlÄąklarÄą sÄąraya alÄąr. Tespit edilen yÃŧzler, YÃŧz TanÄąma işlemi tamamlandÄąktan sonra mevcut ya da yeni kişilere gruplanmak Ãŧzere YÃŧz TanÄąma için sÄąraya alÄąnacaktÄąr.", "facial_recognition_job_description": "AlgÄąlanan yÃŧzleri kişilere grupla. Bu adÄąm, YÃŧz Tespit işlemi tamamlandÄąktan sonra çalÄąÅŸÄąr. \"SÄąfÄąrla\", tÃŧm yÃŧzleri yeniden gruplandÄąrÄąr. \"Eksik\" ise henÃŧz bir kişiye atanmamÄąÅŸ yÃŧzleri sÄąraya alÄąr.", "failed_job_command": "{job} gÃļrevi için {command} komutu başarÄąsÄąz", - "force_delete_user_warning": "UYARI: Bu işlem kullanÄącÄąyÄą ve tÃŧm varlÄąklarÄą anÄąnda kaldÄąracaktÄąr. Bu geri alÄąnamaz ve dosyalar geri getirilemez.", + "force_delete_user_warning": "UYARI: Bu işlem kullanÄącÄąyÄą ve tÃŧm Ãļğeleri anÄąnda kaldÄąracaktÄąr. Bu geri alÄąnamaz ve dosyalar geri getirilemez.", "image_format": "Biçim", "image_format_description": "WebP, JPEG'e gÃļre daha kÃŧçÃŧk dosya boyutu sunar fakat işlemesi daha uzun sÃŧrer.", "image_fullsize_description": "YakÄąnlaştÄąrÄąldığında kullanÄąlan, meta verileri kaldÄąrÄąlmÄąÅŸ tam boyutlu gÃļrÃŧntÃŧ", "image_fullsize_enabled": "Tam boyutlu gÃļrÃŧntÃŧ Ãŧretimini etkinleştir", "image_fullsize_enabled_description": "Yerleşik Ãļnizlemeyi tercih et” seçeneği etkinleştirildiğinde, yerleşik Ãļnizlemeler dÃļnÃŧştÃŧrme yapÄąlmadan doğrudan kullanÄąlÄąr. JPEG gibi web dostu formatlar bu ayardan etkilenmez.", "image_fullsize_quality_description": "1-100 arasÄąnda tam boyutlu gÃļrÃŧntÃŧ kalitesi. Daha yÃŧksek kalitelidir, ancak daha bÃŧyÃŧk dosyalar Ãŧretir.", - "image_fullsize_title": "Tam boyutlu gÃļrÃŧntÃŧ ayarlarÄą", - "image_prefer_embedded_preview": "GÃļmÃŧlÃŧ Ãļnizlemeyi tercih et", - "image_prefer_embedded_preview_setting_description": "RAtoğraflarÄą için mÃŧmkÃŧn olduğunda gÃļmÃŧlÃŧ Ãļnizlemeyi kullan. Bu, bazÄą fotoğraflarda daha gerçekçi renkler n kameraya bağlÄądÄąr ve fotoğrafta normalden daha fazla gÃļrÃŧntÃŧ bozukluklarÄąna sebep olabilir.", + "image_fullsize_title": "Tam Boyutlu GÃļrÃŧntÃŧ AyarlarÄą", + "image_prefer_embedded_preview": "GÃļmÃŧlÃŧ Ãļn izlemeyi tercih et", + "image_prefer_embedded_preview_setting_description": "RAW fotoğraflarÄą için mÃŧmkÃŧn olduğunda gÃļmÃŧlÃŧ Ãļn izlemeyi kullan. Bu, bazÄą fotoğraflarda daha gerçekçi renkler n kameraya bağlÄądÄąr ve fotoğrafta normalden daha fazla gÃļrÃŧntÃŧ bozukluklarÄąna sebep olabilir.", "image_prefer_wide_gamut": "Geniş renk aralığınÄą tercih et", "image_prefer_wide_gamut_setting_description": "Önizleme gÃļrseli için P3 renk paletini tercih et. Bu, geniş renk paletli fotoğraflarda renk canlÄąlığınÄą daha iyi korur, fakat fotoğraflar eski tarayÄącÄąlarda ve eski cihazlarda daha farklÄą gÃļrÃŧnebilir. sRGB fotoğraflar renk paletini korumak için sRGB olarak tutulur.", - "image_preview_description": "Orta boyutlu gÃļrÃŧntÃŧ, meta verisi Ã§ÄąkarÄąlmÄąÅŸ, tekil bir varlÄąk gÃļrÃŧntÃŧlenirken ve makine Ãļğrenimi için kullanÄąlÄąr", + "image_preview_description": "Orta boyutlu gÃļrÃŧntÃŧ, meta verisi Ã§ÄąkarÄąlmÄąÅŸ, tekil bir Ãļğe gÃļrÃŧntÃŧlenirken ve makine Ãļğrenimi için kullanÄąlÄąr", "image_preview_quality_description": "Ön izleme kalitesi 1-100 arasÄądÄąr. YÃŧksek değerler daha iyi kalite sağlar, ancak daha bÃŧyÃŧk dosyalar Ãŧretir ve uygulama yanÄąt verme hÄązÄąnÄą dÃŧşÃŧrebilir. DÃŧşÃŧk bir değer belirlemek, makine Ãļğrenimi kalitesini etkileyebilir.", - "image_preview_title": "Ön izleme AyarlarÄą", + "image_preview_title": "Ön İzleme AyarlarÄą", "image_quality": "Kalite", "image_resolution": "ÇÃļzÃŧnÃŧrlÃŧk", "image_resolution_description": "Daha yÃŧksek çÃļzÃŧnÃŧrlÃŧkle, daha fazla detayÄą koruyabilir ancak kodlanmasÄą daha uzun sÃŧrer, daha bÃŧyÃŧk dosya boyutlarÄąna sahip olur ve uygulamanÄąn yanÄąt verme hÄązÄąnÄą azaltabilir.", - "image_settings": "Fotoğraf ayarlarÄą", + "image_settings": "Fotoğraf AyarlarÄą", "image_settings_description": "Oluşturulan fotoğraflarÄąn kalite ve çÃļzÃŧnÃŧrlÃŧklerini yÃļnet", "image_thumbnail_description": "Meta verisi Ã§ÄąkarÄąlmÄąÅŸ kÃŧçÃŧk boyutlu kÃŧçÃŧk resim, ana zaman çizelgesi gibi fotoğraf gruplarÄąnÄą gÃļrÃŧntÃŧlerken kullanÄąlÄąr", "image_thumbnail_quality_description": "KÃŧçÃŧk resim kalitesi 1-100 arasÄąnda. Daha yÃŧksek değerler daha iyidir, ancak daha bÃŧyÃŧk dosyalar Ãŧretir ve uygulamanÄąn yanÄąt hÄązÄąnÄą azaltabilir.", @@ -104,37 +107,44 @@ "job_not_concurrency_safe": "Bu işlem eşzamanlama için uygun değil.", "job_settings": "GÃļrev AyarlarÄą", "job_settings_description": "AynÄą anda çalÄąÅŸacak gÃļrevleri yÃļnet", - "job_status": "GÃļrev StatÃŧleri", + "job_status": "GÃļrev Durumu", "jobs_delayed": "{jobCount, plural, other {# gecikmeli}}", "jobs_failed": "{jobCount, plural, other {# BaşarÄąsÄąz}}", - "library_created": "{library} kÃŧtÃŧphanesi oluşturuldu", + "library_created": "Oluşturulan kÃŧtÃŧphane : {library}", "library_deleted": "KÃŧtÃŧphane silindi", "library_import_path_description": "Belirtilecek klasÃļrÃŧ içe aktarÄąn. Bu klasÃļr, alt klasÃļrler dahil olmak Ãŧzere, gÃļrÃŧntÃŧler ve videolar için taranacaktÄąr.", "library_scanning": "Periyodik Tarama", "library_scanning_description": "Periyodik kÃŧtÃŧphane taramasÄąnÄą yÃļnet", "library_scanning_enable_description": "Periyodik kÃŧtÃŧphane taramasÄąnÄą etkinleştir", - "library_settings": "Harici kÃŧtÃŧphane", + "library_settings": "Harici KÃŧtÃŧphane", "library_settings_description": "Harici kÃŧtÃŧphane ayarlarÄąnÄą yÃļnet", - "library_tasks_description": "Yeni yada değiştirilmiş varlÄąklar için dÄąÅŸ kÃŧtÃŧphaneleri tara", + "library_tasks_description": "Yeni yada değiştirilmiş Ãļğeler için dÄąÅŸ kÃŧtÃŧphaneleri tara", "library_watching_enable_description": "Harici kÃŧtÃŧphanelerdeki dosya değişikliklerini izle", "library_watching_settings": "KÃŧtÃŧphane izleme (DENEYSEL)", "library_watching_settings_description": "Değişen dosyalar için otomatik olarak izle", - "logging_enable_description": "GÃŧnlÃŧğÃŧ aktifleştir", + "logging_enable_description": "GÃŧnlÃŧğÃŧ etkinleştir", "logging_level_description": "Etkinleştirildiğinde hangi gÃŧnlÃŧk seviyesi kullanÄąlÄąr.", - "logging_settings": "GÃŧnlÃŧk tutma", + "logging_settings": "GÃŧnlÃŧk Tutma", + "machine_learning_availability_checks": "KullanÄąlabilirlik kontrolleri", + "machine_learning_availability_checks_description": "KullanÄąlabilir makine Ãļğrenimi sunucularÄąnÄą otomatik olarak algÄąlayÄąn ve tercih edin", + "machine_learning_availability_checks_enabled": "KullanÄąlabilirlik kontrollerini etkinleştir", + "machine_learning_availability_checks_interval": "Kontrol aralığı", + "machine_learning_availability_checks_interval_description": "KullanÄąlabilirlik kontrolleri arasÄąndaki milisaniye cinsinden aralÄąk", + "machine_learning_availability_checks_timeout": "İstek zaman aÅŸÄąmÄą", + "machine_learning_availability_checks_timeout_description": "KullanÄąlabilirlik kontrolleri için milisaniye cinsinden zaman aÅŸÄąmÄą", "machine_learning_clip_model": "CLIP modeli", "machine_learning_clip_model_description": "Link burada listelenen CLIP modelinin adÄą. Bu Ãļzelliği değiştirdikten sonra \"AkÄąllÄą Arama\" işini tÃŧm fotoğraflar için tekrardan çalÄąÅŸtÄąrmalÄąsÄąnÄąz.", - "machine_learning_duplicate_detection": "Kopya fotoğraf tespiti", + "machine_learning_duplicate_detection": "Kopya Fotoğraf Tespiti", "machine_learning_duplicate_detection_enabled": "Kopya fotoğraf tespitini etkinleştir", - "machine_learning_duplicate_detection_enabled_description": "Devre dÄąÅŸÄą bÄąrakÄąlÄąrsa aynÄą Ãļgeler yine de temizlenecek.", + "machine_learning_duplicate_detection_enabled_description": "Devre dÄąÅŸÄą bÄąrakÄąlÄąrsa aynÄą Ãļğeler yine de temizlenecek.", "machine_learning_duplicate_detection_setting_description": "Birbirinin kopyasÄą olan varlÄąklarÄą bulmak için CLIP kullan", "machine_learning_enabled": "Makine Ãļğrenmesini etkinleştir", "machine_learning_enabled_description": "Eğer devre dÄąÅŸÄą bÄąrakÄąlÄąrsa bÃŧtÃŧn Makine Öğrenmesi Ãļzellikleri devre dÄąÅŸÄą bÄąrakÄąlacak.", "machine_learning_facial_recognition": "YÃŧz TanÄąma", "machine_learning_facial_recognition_description": "Fotoğraflardaki yÃŧzleri tara, tanÄą ve gruplandÄąr", - "machine_learning_facial_recognition_model": "YÃŧz TanÄąma Modeli", + "machine_learning_facial_recognition_model": "YÃŧz tanÄąma modeli", "machine_learning_facial_recognition_model_description": "Modeller, azalan boyut sÄąrasÄąna gÃļre listelenmiştir. Daha bÃŧyÃŧk modeller daha yavaştÄąr ve daha fazla bellek kullanÄąr, ancak daha iyi sonuçlar Ãŧretir. Bir modeli değiştirdikten sonra tÃŧm gÃļrÃŧntÃŧler için yÃŧz algÄąlama işini yeniden çalÄąÅŸtÄąrmanÄąz gerektiğini unutmayÄąn.", - "machine_learning_facial_recognition_setting": "YÃŧz TanÄąmayÄą etkinleştir", + "machine_learning_facial_recognition_setting": "YÃŧz tanÄąmayÄą etkinleştir", "machine_learning_facial_recognition_setting_description": "Devre dÄąÅŸÄą bÄąrakÄąldığında fotoğraflar yÃŧz tanÄąma için işlenmeyecek ve Keşfet sayfasÄąndaki Kişiler sekmesini doldurmayacak.", "machine_learning_max_detection_distance": "Maksimum tespit uzaklığı", "machine_learning_max_detection_distance_description": "Resimleri birbirinin çifti saymak için hesap edilecek azami benzerlik ÃļlçÃŧsÃŧ, 0.001-0.1 aralığında. Daha yÃŧksek değer daha hassas olup daha fazla çift tespit eder ancak çift olmayan resimleri birbirinin çifti sayabilir.", @@ -169,37 +179,37 @@ "memory_cleanup_job": "AnÄą temizliği", "memory_generate_job": "AnÄą oluşturma", "metadata_extraction_job": "Meta verilerinden AyÄąkla", - "metadata_extraction_job_description": "GPS ve çÃļzÃŧnÃŧrlÃŧk gibi ger bir varlığın meta veri bilgilerini ayÄąklayÄąn", + "metadata_extraction_job_description": "GPS, yÃŧzler ve çÃļzÃŧnÃŧrlÃŧk gibi her bir Ãļğeden meta veri bilgilerini Ã§ÄąkarÄąn", "metadata_faces_import_setting": "YÃŧz içe aktarmayÄą etkinleştir", "metadata_faces_import_setting_description": "YÃŧzleri, EXIF verileri ve sidecar dosyalardan getir", "metadata_settings": "Metaveri AyarlarÄą", "metadata_settings_description": "Metaveri ayarlarÄąnÄą yÃļnet", "migration_job": "Birleştirme", - "migration_job_description": "VarlÄąklar ve yÃŧzler için resim çerçeve Ãļnizlemelerini en yeni klasÃļr yapÄąsÄąna aktar", + "migration_job_description": "Öğeler ve yÃŧzler için kÃŧçÃŧk resimleri en son klasÃļr yapÄąsÄąna taÅŸÄąyÄąn", "nightly_tasks_cluster_faces_setting_description": "Yeni algÄąlanan yÃŧzlerde yÃŧz tanÄąma işlemini çalÄąÅŸtÄąrÄąn", "nightly_tasks_cluster_new_faces_setting": "Yeni yÃŧzleri bir araya getirin", "nightly_tasks_database_cleanup_setting": "VeritabanÄą temizleme gÃļrevleri", "nightly_tasks_database_cleanup_setting_description": "VeritabanÄąndan eski, sÃŧresi dolmuş verileri temizleyin", "nightly_tasks_generate_memories_setting": "AnÄąlar oluşturun", - "nightly_tasks_generate_memories_setting_description": "VarlÄąklardan yeni anÄąlar yaratÄąn", + "nightly_tasks_generate_memories_setting_description": "Öğelerden yeni anÄąlar yaratÄąn", "nightly_tasks_missing_thumbnails_setting": "Eksik kÃŧçÃŧk resimleri oluştur", - "nightly_tasks_missing_thumbnails_setting_description": "KÃŧçÃŧk resim oluşturmak için kÃŧçÃŧk resim içermeyen varlÄąklarÄą sÄąraya alÄąn", + "nightly_tasks_missing_thumbnails_setting_description": "KÃŧçÃŧk resim oluşturmak için kÃŧçÃŧk resim içermeyen Ãļğeleri sÄąraya alÄąn", "nightly_tasks_settings": "Gece GÃļrevleri AyarlarÄą", "nightly_tasks_settings_description": "Gece gÃļrevlerini yÃļnet", "nightly_tasks_start_time_setting": "BaşlangÄąÃ§ saati", "nightly_tasks_start_time_setting_description": "Sunucunun gece gÃļrevlerini çalÄąÅŸtÄąrmaya başladığı saat", - "nightly_tasks_sync_quota_usage_setting": "Kota kullanÄąmÄąnÄą senkronize et", + "nightly_tasks_sync_quota_usage_setting": "Kota kullanÄąmÄąnÄą eşzamanla", "nightly_tasks_sync_quota_usage_setting_description": "Mevcut kullanÄąma gÃļre kullanÄącÄą depolama kotasÄąnÄą gÃŧncelle", "no_paths_added": "Yol eklenmedi", "no_pattern_added": "Desen eklenmedi", - "note_apply_storage_label_previous_assets": "Not: Daha Ãļnce yÃŧklenen varlÄąklara Depolama Etiketi uygulamak için şu komutu çalÄąÅŸtÄąrÄąn", + "note_apply_storage_label_previous_assets": "Not: Daha Ãļnce yÃŧklenen Ãļğelere Depolama Etiketi uygulamak için şu komutu çalÄąÅŸtÄąrÄąn", "note_cannot_be_changed_later": "NOT: Bu daha sonra değiştirilemez!", "notification_email_from_address": "Şu adresten", "notification_email_from_address_description": "GÃļnderen e-posta adresi, Ãļrneğin: \"Immich GÃļrsel Sunucusu \". E-posta gÃļnderilmesine izin verdiğiniz bir adres kullandığınÄązdan emin olun.", "notification_email_host_description": "E-posta sunucusunun ana bilgisayarÄą (Ãļrneğin, smtp.immich.app)", "notification_email_ignore_certificate_errors": "Sertifika hatalarÄąnÄą gÃļrmezden gel", "notification_email_ignore_certificate_errors_description": "TLS sertifika doğrulama ayarlarÄąnÄą gÃļrmezden gel (Önerilmez)", - "notification_email_password_description": "Email sunucusuyla doğrulama için kullanÄąlacak olan şifre", + "notification_email_password_description": "E-posta sunucusunda kimlik doğrulama yaparken kullanÄąlacak şifre", "notification_email_port_description": "Email sunucusunun port numarasÄą (25, 465, 587 gibi)", "notification_email_sent_test_email_button": "Test emaili yolla ve kaydet", "notification_email_setting_description": "Email yollama bildirim ayarlarÄą", @@ -208,7 +218,7 @@ "notification_email_test_email_sent": "Test emaili {email} adresine yollandÄą. LÃŧtfen gelen kutunuzu kontrol edin.", "notification_email_username_description": "Email sunucu doğrulamasÄąnda kullanÄąlacak olan kullanÄącÄą adÄą", "notification_enable_email_notifications": "Email bildirimlerini etkinleştir", - "notification_settings": "Bildirim ayarlarÄą", + "notification_settings": "Bildirim AyarlarÄą", "notification_settings_description": "Email ve bildirim ayarlarÄąnÄą yÃļnet", "oauth_auto_launch": "Otomatik başlat", "oauth_auto_launch_description": "Giriş sayfasÄąna girildiğinde OAuth akÄąÅŸÄąnÄą otomatik olarak başlat", @@ -231,16 +241,16 @@ "oauth_storage_quota_claim_description": "KullanÄącÄąya depolama kotasÄą koymak için kullanÄąlacak değer (en: OAuth claim).", "oauth_storage_quota_default": "VarsayÄąlan depolama kotasÄą (GiB)", "oauth_storage_quota_default_description": "Değer (en: OAuth claim) mevcut değilse GiB cinsinden konulacak kota.", - "oauth_timeout": "İstek zaman aÅŸÄąmÄą", + "oauth_timeout": "İstek Zaman AÅŸÄąmÄą", "oauth_timeout_description": "Milisaniye cinsinden istek zaman aÅŸÄąmÄą", - "password_enable_description": "Email ve şifre ile giriş yap", - "password_settings": "Şifre giriş", + "password_enable_description": "E-posta ve şifre ile giriş yapÄąn", + "password_settings": "Şifre ile Giriş", "password_settings_description": "Şifre giriş ayarlarÄąnÄą yÃļnet", "paths_validated_successfully": "TÃŧm yollar başarÄąyla doğrulandÄą", "person_cleanup_job": "Kişi temizleme", - "quota_size_gib": "Kota boyutu (GiB)", + "quota_size_gib": "Kota Boyutu (GiB)", "refreshing_all_libraries": "TÃŧm kÃŧtÃŧphaneler yenileniyor", - "registration": "YÃļnetici kaydÄą", + "registration": "YÃļnetici KaydÄą", "registration_description": "Sistemdeki ilk kullanÄącÄą olduğunuz için hesabÄąnÄąz YÃļnetici olarak ayarlandÄą. Yeni oluşturulan Ãŧyeliklerin, ve yÃļnetici gÃļrevlerinin sorumlusu olarak atandÄąnÄąz.", "require_password_change_on_login": "KullanÄącÄąnÄąn ilk girişinde şifre değiştirmesini zorunlu kÄąl", "reset_settings_to_default": "AyarlarÄą varsayÄąlana sÄąfÄąrla", @@ -252,28 +262,28 @@ "server_external_domain_settings_description": "PaylaÅŸÄąlan fotoğraflar için domain, http(s):// dahil", "server_public_users": "Harici KullanÄącÄąlar", "server_public_users_description": "PaylaÅŸÄąlan albÃŧmlere bir kullanÄącÄą eklenirken tÃŧm kullanÄącÄąlar (ad ve e-posta) listelenir. Devre dÄąÅŸÄą bÄąrakÄąldığında, kullanÄącÄą listesi yalnÄązca yÃļnetici kullanÄącÄąlar tarafÄąndan kullanÄąlabilir.", - "server_settings": "Sunucu ayarlarÄą", + "server_settings": "Sunucu AyarlarÄą", "server_settings_description": "Sunucu ayarlarÄąnÄą yÃļnet", "server_welcome_message": "Hoş geldin mesajÄą", "server_welcome_message_description": "Giriş sayfasÄąnda gÃļsterilen mesaj.", "sidecar_job": "Ek dosya ile taÅŸÄąnan metadata", - "sidecar_job_description": "Ek dosyalardaki metadatalarÄą bul ve gÃŧncelle", + "sidecar_job_description": "Dosya sisteminden yan araç meta verilerini keşfedin veya eşzamanlayÄąn", "slideshow_duration_description": "Her fotoğrafÄąn kaç saniye gÃļrÃŧntÃŧleneceği", - "smart_search_job_description": "AkÄąllÄą aramayÄą desteklemek için tÃŧm varlÄąklarda makine Ãļğrenmesini çalÄąÅŸtÄąrÄąn", - "storage_template_date_time_description": "DosyanÄąn yaratÄąlma tarihini, varlığın yaratÄąlma tarihi olarak kullanÄąlacak", + "smart_search_job_description": "AkÄąllÄą aramayÄą desteklemek için tÃŧm Ãļğelerde makine Ãļğrenmesini çalÄąÅŸtÄąrÄąn", + "storage_template_date_time_description": "Öğenin oluşturulma zaman damgasÄą, tarih ve saat bilgisi için kullanÄąlÄąr", "storage_template_date_time_sample": "Örnek tarih {date}", "storage_template_enable_description": "Depolama şablon motorunu etkinleştir", "storage_template_hash_verification_enabled": "Hash doğrulama etkinleştirildi", "storage_template_hash_verification_enabled_description": "Hash doğrulamayÄą etkinleştirir, eğer ne işe yaradığınÄą bilmiyorsanÄąz bunu devre dÄąÅŸÄą bÄąrakmayÄąn", "storage_template_migration": "Depolama şablonu birleştirme", - "storage_template_migration_description": "Geçerli {template} ayarlarÄąnÄą daha Ãļnce yÃŧklenmiş olan varlÄąklara uygula", - "storage_template_migration_info": "Depolama şablonu tÃŧm dosya uzantÄąlarÄąnÄą kÃŧçÃŧk harfe dÃļnÃŧştÃŧrecektir. Şablon ayarlarÄąndaki değişiklikler sadece yeni varlÄąklara uygulanacak. Şablon ayarlarÄąnÄą daha Ãļnce yÃŧklenmiş olan varlÄąklara uygulamak için {job} çalÄąÅŸtÄąrÄąn.", + "storage_template_migration_description": "Geçerli {template} ayarlarÄąnÄą daha Ãļnce yÃŧklenmiş olan Ãļğelere uygula", + "storage_template_migration_info": "Depolama şablonu tÃŧm dosya uzantÄąlarÄąnÄą kÃŧçÃŧk harfe dÃļnÃŧştÃŧrecektir. Şablon ayarlarÄąndaki değişiklikler sadece yeni Ãļğelere uygulanacak. Şablon ayarlarÄąnÄą daha Ãļnce yÃŧklenmiş olan Ãļğelere uygulamak için {job} çalÄąÅŸtÄąrÄąn.", "storage_template_migration_job": "Depolama Adreslerini Değiştirme GÃļrevi", "storage_template_more_details": "Bu Ãļzellik hakkÄąnda daha fazla bilgi için, Depolama Şablonu ve onun etkileri kÄąsmÄąna bakÄąn", "storage_template_onboarding_description_v2": "Etkinleştirildiğinde, bu Ãļzellik dosyalarÄą kullanÄącÄą tanÄąmlÄą bir şablona gÃļre otomatik olarak organize eder. Daha fazla bilgi için lÃŧtfen belgelere bakÄąn.", "storage_template_path_length": "Tahmini dosya adresi uzunluğu: {length, number}/{limit, number}", "storage_template_settings": "Depolama Şablonu", - "storage_template_settings_description": "YÃŧklenen dosyanÄąn ismini ve klasÃļr yapÄąsÄąnÄą dÃŧzenle", + "storage_template_settings_description": "YÃŧklenen Ãļğenin ismini ve klasÃļr yapÄąsÄąnÄą dÃŧzenle", "storage_template_user_label": "{label} kullanÄącÄąnÄą dosyalarÄą için kullanÄąlan alt klasÃļrdÃŧr", "system_settings": "Sistem AyarlarÄą", "tag_cleanup_job": "Etiket temizleme", @@ -288,14 +298,14 @@ "template_settings_description": "Bildirim şablonlarÄąnÄą yÃļnet", "theme_custom_css_settings": "Özel CSS", "theme_custom_css_settings_description": "CSS (Cascading Style Sheets) kullanÄąlarak Immich'in tasarÄąmÄą değiştirilebilir.", - "theme_settings": "Tema ayarlarÄą", + "theme_settings": "Tema AyarlarÄą", "theme_settings_description": "Immich web arayÃŧzÃŧnÃŧn Ãļzelleştirilmesi ayarlarÄąnÄą yÃļnet", "thumbnail_generation_job": "Önizlemeleri oluştur", - "thumbnail_generation_job_description": "Her kişi ve obje için bÃŧyÃŧk, kÃŧçÃŧk ve bulanÄąk thumbnail (kÃŧçÃŧk resim) oluştur", + "thumbnail_generation_job_description": "Her bir Ãļğe için bÃŧyÃŧk, kÃŧçÃŧk ve bulanÄąk kÃŧçÃŧk resimler ile her kişi için kÃŧçÃŧk resimler oluşturun", "transcoding_acceleration_api": "HÄązlandÄąrma API", "transcoding_acceleration_api_description": "Video formatÄą çevriminde kullanÄąlacak API. Bu ayara 'mÃŧmkÃŧn olduğunca' uyulmaktadÄąr; seçilen API'da sorun Ã§Äąkarsa yazÄąlÄąm tabanlÄą çevirime dÃļnÃŧlÃŧr. VP9 donanÄąmÄąnÄąza bağlÄą olarak çalÄąÅŸmayabilir.", "transcoding_acceleration_nvenc": "NVENC (NVIDIA GPU gerektirir)", - "transcoding_acceleration_qsv": "Quick Sync (7. nesil veya daha yeni bir Intel CPU gerektirir)", + "transcoding_acceleration_qsv": "HÄązlÄą Eşzamanlama (7. nesil veya daha yeni bir Intel CPU gerektirir)", "transcoding_acceleration_rkmpp": "RKMPP (Sadece Rockchip SOC'ler)", "transcoding_acceleration_vaapi": "VAAPI", "transcoding_accepted_audio_codecs": "Kabul edilen ses kodekleri", @@ -354,18 +364,18 @@ "transcoding_video_codec_description": "VP9 yÃŧksek verimliliğe ve web uyumluluğuna sahiptir, ancak kod dÃļnÃŧştÃŧrme işlemi daha uzun sÃŧrer. HEVC benzer performans gÃļsterir ancak web uyumluluğu daha dÃŧşÃŧktÃŧr. H.264 geniş çapta uyumludur ve kod dÃļnÃŧştÃŧrmesi hÄązlÄądÄąr, ancak çok daha bÃŧyÃŧk dosyalar Ãŧretir. AV1 en verimli codec'tir ancak eski cihazlarda desteği yoktur.", "trash_enabled_description": "ÇÃļp Ãļzelliklerini etkinleştir", "trash_number_of_days": "GÃŧn sayÄąsÄą", - "trash_number_of_days_description": "VarlÄąklarÄąn kalÄącÄą olarak silinmeden Ãļnce çÃļpte kaç gÃŧn tutulacağı", - "trash_settings": "ÇÃļp ayarlarÄą", - "trash_settings_description": "ÇÃļp ayarlarÄąnÄą yÃļnet", + "trash_number_of_days_description": "Öğeleri kalÄącÄą olarak silmeden Ãļnce çÃļp kutusunda tutma sÃŧresi (gÃŧn)", + "trash_settings": "ÇÃļp Kutusu AyarlarÄą", + "trash_settings_description": "ÇÃļp kutusu ayarlarÄąnÄą yÃļnet", "unlink_all_oauth_accounts": "TÃŧm OAuth hesaplarÄąnÄąn bağlantÄąsÄąnÄą kaldÄąr", "unlink_all_oauth_accounts_description": "Yeni bir sağlayÄącÄąya geçmeden Ãļnce tÃŧm OAuth hesaplarÄąnÄą kaldÄąrÄąlmayÄą unutmayÄąn.", "unlink_all_oauth_accounts_prompt": "TÃŧm OAuth hesaplarÄąnÄą kaldÄąrmak istediğinizden emin misiniz? Bu, her kullanÄącÄą için OAuth kimliğini sÄąfÄąrlar ve geri alÄąnamaz.", "user_cleanup_job": "KullanÄącÄą temizleme", - "user_delete_delay": "{user} hesabÄą ve varlÄąklarÄą {delay, plural, one {# day} other {# days}} gÃŧn içinde kalÄącÄą olarak silinmek için planlandÄą.", + "user_delete_delay": "{user} hesabÄą ve Ãļğeleri {delay, plural, one {# day} other {# days}} gÃŧn içinde kalÄącÄą olarak silinecektir.", "user_delete_delay_settings": "Silme gecikmesi", - "user_delete_delay_settings_description": "Bir kullanÄącÄąnÄąn hesabÄąnÄą ve varlÄąklarÄąnÄą kalÄącÄą olarak silmek için kaldÄąrÄąldÄąktan sonra gereken gÃŧn sayÄąsÄą. KullanÄącÄą silme işi, silinmeye hazÄąr kullanÄącÄąlarÄą kontrol etmek için gece yarÄąsÄą çalÄąÅŸÄąr. Bu ayardaki değişiklikler bir sonraki yÃŧrÃŧtmede değerlendirilecektir.", - "user_delete_immediately": "{user}'in hesabÄą ve varlÄąklarÄą hemen kalÄącÄą olarak silinmek Ãŧzere sÄąraya alÄąnacak.", - "user_delete_immediately_checkbox": "KullanÄącÄą ve varlÄąklarÄą hemen silinmek Ãŧzere sÄąraya al", + "user_delete_delay_settings_description": "Bir kullanÄącÄąnÄąn hesabÄąnÄą ve Ãļğelerini kalÄącÄą olarak silmek için kaldÄąrÄąldÄąktan sonra gereken gÃŧn sayÄąsÄą. KullanÄącÄą silme işi, silinmeye hazÄąr kullanÄącÄąlarÄą kontrol etmek için gece yarÄąsÄą çalÄąÅŸÄąr. Bu ayardaki değişiklikler bir sonraki yÃŧrÃŧtmede değerlendirilecektir.", + "user_delete_immediately": "{user}'in hesabÄą ve Ãļğeleri hemen kalÄącÄą olarak silinmek Ãŧzere sÄąraya alÄąnacak.", + "user_delete_immediately_checkbox": "KullanÄącÄą ve Ãļğeleri hemen silmek için sÄąraya alÄąn", "user_details": "KullanÄącÄą AyrÄąntÄąlarÄą", "user_management": "KullanÄącÄą YÃļnetimi", "user_password_has_been_reset": "KullanÄącÄąnÄąn şifresi sÄąfÄąrlandÄą:", @@ -373,32 +383,32 @@ "user_restore_description": "{user} kullanÄącÄąsÄą geri yÃŧklenecek.", "user_restore_scheduled_removal": "KullanÄącÄąyÄą geri yÃŧkle - {date, date, long} tarihinde planlanan kaldÄąrma", "user_settings": "KullanÄącÄą AyarlarÄą", - "user_settings_description": "KullanÄącÄą AyarlarÄąnÄą YÃļnet", + "user_settings_description": "KullanÄącÄą ayarlarÄąnÄą yÃļnet", "user_successfully_removed": "KullanÄącÄą {email} başarÄąyla kaldÄąrÄąldÄą.", "version_check_enabled_description": "SÃŧrÃŧm kontrolÃŧ etkin", "version_check_implications": "SÃŧrÃŧm kontrol Ãļzelliği, github.com ile periyodik iletişime dayanÄąr", - "version_check_settings": "Versiyon kontrolÃŧ", + "version_check_settings": "SÃŧrÃŧm KontrolÃŧ", "version_check_settings_description": "Yeni sÃŧrÃŧm bildirimini etkinleştir/devre dÄąÅŸÄą bÄąrak", "video_conversion_job": "VideolarÄą dÃļnÃŧştÃŧr", "video_conversion_job_description": "TarayÄącÄąlar ve cihazlarla daha geniş uyumluluk için videolarÄą dÃļnÃŧştÃŧr" }, - "admin_email": "YÃļnetici Emaili", + "admin_email": "YÃļnetici E-postasÄą", "admin_password": "YÃļnetici Şifresi", "administration": "YÃļnetim", "advanced": "Gelişmiş", - "advanced_settings_beta_timeline_subtitle": "Yeni uygulama deneyimini deneyin", - "advanced_settings_beta_timeline_title": "Beta Zaman Çizelgesi", - "advanced_settings_enable_alternate_media_filter_subtitle": "Eşleme sÄąrasÄąnda medyayÄą alternatif ÃļlçÃŧtlere gÃļre sÃŧzgeçten geçirmek için bu seçeneği kullanÄąn. UygulamanÄąn tÃŧm albÃŧmleri algÄąlamasÄąnda sorun yaÅŸÄąyorsanÄąz yalnÄązca bu durumda deneyin.", - "advanced_settings_enable_alternate_media_filter_title": "[DENEYSEL] Alternatif cihaz albÃŧm eşleme sÃŧzgeci kullanÄąn", + "advanced_settings_enable_alternate_media_filter_subtitle": "Eşzamanlama sÄąrasÄąnda medyayÄą alternatif ÃļlçÃŧtlere gÃļre sÃŧzgeçten geçirmek için bu seçeneği kullanÄąn. UygulamanÄąn tÃŧm albÃŧmleri algÄąlamasÄąnda sorun yaÅŸÄąyorsanÄąz yalnÄązca bu durumda deneyin.", + "advanced_settings_enable_alternate_media_filter_title": "[DENEYSEL] Alternatif cihaz albÃŧm eşzamanlama sÃŧzgeci kullanÄąn", "advanced_settings_log_level_title": "GÃŧnlÃŧk dÃŧzeyi: {level}", - "advanced_settings_prefer_remote_subtitle": "BazÄą cihazlar yerel varlÄąklardan kÃŧçÃŧk resimleri yÃŧklerken çok yavaş çalÄąÅŸÄąr. Bu ayarÄą etkinleştirerek uzak gÃļrÃŧntÃŧleri yÃŧkleyin.", + "advanced_settings_prefer_remote_subtitle": "BazÄą cihazlar yerel Ãļğelerden kÃŧçÃŧk resimleri yÃŧklerken çok yavaş çalÄąÅŸÄąr. Bunun yerine uzak gÃļrÃŧntÃŧleri yÃŧklemek için bu ayarÄą etkinleştirin.", "advanced_settings_prefer_remote_title": "Uzak gÃļrÃŧntÃŧleri tercih et", "advanced_settings_proxy_headers_subtitle": "Immich'in her ağ isteğiyle birlikte gÃļndermesi gereken proxy header'larÄą tanÄąmlayÄąn", - "advanced_settings_proxy_headers_title": "Proxy Header'lar", + "advanced_settings_proxy_headers_title": "Proxy BaşlÄąklarÄą", + "advanced_settings_readonly_mode_subtitle": "FotoğraflarÄąn yalnÄązca gÃļrÃŧntÃŧlenebildiği salt okunur modu etkinleştirir; birden fazla gÃļrÃŧntÃŧ seçme, paylaşma, aktarma, silme gibi işlemler devre dÄąÅŸÄą bÄąrakÄąlÄąr. Ana ekrandan kullanÄącÄą avatarÄą aracÄąlığıyla salt okunur modu Etkinleştirin/Devre dÄąÅŸÄą bÄąrakÄąn", + "advanced_settings_readonly_mode_title": "Salt okunur Mod", "advanced_settings_self_signed_ssl_subtitle": "Sunucu uç noktasÄą için SSL sertifika doğrulamasÄąnÄą atlar. Kendinden imzalÄą sertifikalar için gereklidir.", "advanced_settings_self_signed_ssl_title": "Kendi kendine imzalanmÄąÅŸ SSL sertifikalarÄąna izin ver", - "advanced_settings_sync_remote_deletions_subtitle": "Web Ãŧzerinde işlem yapÄąldığında, bu aygÄąttaki varlığı otomatik olarak sil veya geri yÃŧkle", - "advanced_settings_sync_remote_deletions_title": "Uzaktan silinmeleri eşle [DENEYSEL]", + "advanced_settings_sync_remote_deletions_subtitle": "Web Ãŧzerinde işlem yapÄąldığında, bu aygÄąttaki Ãļğeyi otomatik olarak sil veya geri yÃŧkle", + "advanced_settings_sync_remote_deletions_title": "Uzaktan silmeleri eşzamanla [DENEYSEL]", "advanced_settings_tile_subtitle": "Gelişmiş kullanÄącÄą ayarlarÄą", "advanced_settings_troubleshooting_subtitle": "Sorun giderme için ek Ãļzellikleri etkinleştirin", "advanced_settings_troubleshooting_title": "Sorun Giderme", @@ -406,15 +416,15 @@ "age_year_months": "1 yaş, {months, plural, one {# ay} other {# ay}}", "age_years": "{years, plural, other {Yaş #}}", "album_added": "AlbÃŧm eklendi", - "album_added_notification_setting_description": "PaylaÅŸÄąlan bir albÃŧme eklendiğinizde email bildirimi alÄąn", - "album_cover_updated": "AlbÃŧm Kapağı gÃŧncellendi", + "album_added_notification_setting_description": "PaylaÅŸÄąlan bir albÃŧme eklendiğinizde e-posta bildirimi alÄąn", + "album_cover_updated": "AlbÃŧm kapağı gÃŧncellendi", "album_delete_confirmation": "{album} albÃŧmÃŧnÃŧ silmek istediğinize emin misiniz?", "album_delete_confirmation_description": "AlbÃŧm paylaÅŸÄąlÄąyorsa, diğer kullanÄącÄąlar artÄąk bu albÃŧme erişemeyecektir.", "album_deleted": "AlbÃŧm silindi", "album_info_card_backup_album_excluded": "HARİÇ", "album_info_card_backup_album_included": "DAHİL", "album_info_updated": "AlbÃŧm bilgisi gÃŧncellendi", - "album_leave": "AlbÃŧmden AyrÄąl?", + "album_leave": "AlbÃŧmden ayrÄąl?", "album_leave_confirmation": "{album} albÃŧmÃŧnden ayrÄąlmak istediğinize emin misiniz?", "album_name": "AlbÃŧm AdÄą", "album_options": "AlbÃŧm seçenekleri", @@ -422,14 +432,15 @@ "album_remove_user_confirmation": "{user} kullanÄącÄąsÄąnÄą kaldÄąrmak istediğinize emin misiniz?", "album_search_not_found": "AramanÄązla eşleşen albÃŧm bulunamadÄą", "album_share_no_users": "GÃļrÃŧnÃŧşe gÃļre bu albÃŧmÃŧ tÃŧm kullanÄącÄąlarla paylaştÄąnÄąz veya paylaşacak herhangi bir başka kullanÄącÄąnÄąz yok.", + "album_summary": "AlbÃŧm Ãļzeti", "album_updated": "AlbÃŧm gÃŧncellendi", - "album_updated_setting_description": "PaylaÅŸÄąlan bir albÃŧme yeni bir varlÄąk eklendiğinde email bildirimi alÄąn", + "album_updated_setting_description": "PaylaÅŸÄąlan bir albÃŧme yeni bir Ãļğe eklendiğinde e-posta bildirimi alÄąn", "album_user_left": "{album}den ayrÄąldÄąnÄąz", "album_user_removed": "{user} kaldÄąrÄąldÄą", "album_viewer_appbar_delete_confirm": "Bu albÃŧmÃŧ hesabÄąnÄązdan silmek istediğinizden emin misiniz?", "album_viewer_appbar_share_err_delete": "AlbÃŧm silinemedi", "album_viewer_appbar_share_err_leave": "AlbÃŧmden Ã§ÄąkÄąlamadÄą", - "album_viewer_appbar_share_err_remove": "AlbÃŧmden Ãļğeleri kaldÄąrmada sorunlar var", + "album_viewer_appbar_share_err_remove": "AlbÃŧmden Ãļğeler kaldÄąrÄąrken sorunlar yaşanÄąyor", "album_viewer_appbar_share_err_title": "AlbÃŧm başlığı değiştirilemedi", "album_viewer_appbar_share_leave": "AlbÃŧmden Ã§Äąk", "album_viewer_appbar_share_to": "Paylaşma", @@ -438,8 +449,8 @@ "albums": "AlbÃŧmler", "albums_count": "{count, plural, one {{count, number} AlbÃŧm} other {{count, number} AlbÃŧm}}", "albums_default_sort_order": "VarsayÄąlan albÃŧm sÄąralama dÃŧzeni", - "albums_default_sort_order_description": "Yeni albÃŧm oluştururken kullanÄąlacak başlangÄąÃ§ varlÄąk sÄąralama dÃŧzeni.", - "albums_feature_description": "Diğer kullanÄącÄąlarla paylaÅŸÄąlabilen varlÄąk koleksiyonlarÄą.", + "albums_default_sort_order_description": "Yeni albÃŧm oluştururken kullanÄąlacak başlangÄąÃ§ Ãļğe sÄąralama dÃŧzeni.", + "albums_feature_description": "Diğer kullanÄącÄąlarla paylaÅŸÄąlabilen Ãļğe koleksiyonlarÄą.", "albums_on_device_count": "Cihazdaki albÃŧmler ({count})", "all": "TÃŧmÃŧ", "all_albums": "TÃŧm AlbÃŧmler", @@ -460,6 +471,7 @@ "app_bar_signout_dialog_title": "Ã‡ÄąkÄąÅŸ", "app_settings": "Uygulama AyarlarÄą", "appears_in": "Şurada gÃļrÃŧnÃŧr", + "apply_count": "Uygula ({count, number})", "archive": "Arşiv", "archive_action_prompt": "{count} arşive eklendi", "archive_or_unarchive_photo": "FotoğrafÄą arşivle/arşivden Ã§Äąkar", @@ -475,9 +487,9 @@ "asset_action_share_err_offline": "ÇevrimdÄąÅŸÄą Ãļğeler alÄąnamÄąyor, atlanÄąyor", "asset_added_to_album": "AlbÃŧme eklendi", "asset_adding_to_album": "AlbÃŧme ekleniyorâ€Ļ", - "asset_description_updated": "VarlÄąk aÃ§ÄąklamasÄą gÃŧncellendi", - "asset_filename_is_offline": "VarlÄąk {filename} çevrimdÄąÅŸÄą", - "asset_has_unassigned_faces": "VarlÄąk, atanmamÄąÅŸ yÃŧzler içeriyor", + "asset_description_updated": "Öğe aÃ§ÄąklamasÄą gÃŧncellendi", + "asset_filename_is_offline": "Öğe {filename} çevrimdÄąÅŸÄą", + "asset_has_unassigned_faces": "Öğe, atanmamÄąÅŸ yÃŧzler içeriyor", "asset_hashing": "Karma (hashleme) oluşturuluyorâ€Ļ", "asset_list_group_by_sub_title": "Grupla", "asset_list_layout_settings_dynamic_layout_title": "Dinamik dÃŧzen", @@ -487,50 +499,58 @@ "asset_list_layout_sub_title": "DÃŧzen", "asset_list_settings_subtitle": "Fotoğraf Äązgara dÃŧzeni ayarlarÄą", "asset_list_settings_title": "Fotoğraf IzgarasÄą", - "asset_offline": "VarlÄąk Çevrim DÄąÅŸÄą", - "asset_offline_description": "Bu harici varlÄąk artÄąk diskte bulunmuyor. YardÄąm için lÃŧtfen Immich yÃļneticinizle iletişime geçin.", + "asset_offline": "Öğe Çevrim DÄąÅŸÄą", + "asset_offline_description": "Bu harici Ãļğe artÄąk diskte bulunmuyor. YardÄąm için lÃŧtfen Immich yÃļneticinizle iletişime geçin.", "asset_restored_successfully": "Öğe başarÄąyla geri yÃŧklendi", "asset_skipped": "AtlandÄą", "asset_skipped_in_trash": "ÇÃļpte", + "asset_trashed": "Öğe çÃļpe atÄąldÄą", + "asset_troubleshoot": "Öğe Sorun Giderme", "asset_uploaded": "YÃŧklendi", "asset_uploading": "YÃŧkleniyorâ€Ļ", "asset_viewer_settings_subtitle": "Galeri gÃļrÃŧntÃŧleyici ayarlarÄąnÄą dÃŧzenle", "asset_viewer_settings_title": "İçerik GÃļrÃŧntÃŧleyici", - "assets": "VarlÄąklar", - "assets_added_count": "{count, plural, one {# varlÄąk eklendi} other {# varlÄąk eklendi}}", - "assets_added_to_album_count": "{count, plural, one {# varlÄąk} other {# varlÄąk}} albÃŧme eklendi", - "assets_cannot_be_added_to_album_count": "{count, plural, one {VarlÄąk} other {VarlÄąklar}} albÃŧme eklenemiyor", - "assets_count": "{count, plural, one {# varlÄąk} other {# varlÄąklar}}", + "assets": "Öğeler", + "assets_added_count": "Eklendi {count, plural, one {# asset} other {# assets}}", + "assets_added_to_album_count": "AlbÃŧme {count, plural, one {# asset} other {# assets}} eklendi", + "assets_added_to_albums_count": "Eklendi {assetTotal, plural, one {# asset} other {# assets}} buraya {albumTotal, plural, one {# album} other {# albums}}", + "assets_cannot_be_added_to_album_count": "{count, plural, one {Asset} other {Assets}} albÃŧme eklenemiyor", + "assets_cannot_be_added_to_albums": "{count, plural, one {Asset} other {Assets}} hiçbir albÃŧme eklenemez", + "assets_count": "{count, plural, one {# Ãļğe} other {# Ãļğeler}}", "assets_deleted_permanently": "{count} Ãļğe kalÄącÄą olarak silindi", "assets_deleted_permanently_from_server": "{count} Ãļğe kalÄącÄą olarak Immich sunucusundan silindi", - "assets_downloaded_failed": "{count, plural, one {# dosya indirildi – {error} dosya indirilemedi} other {# dosya indirildi – {error} dosya indirilemedi}}", + "assets_downloaded_failed": "{count, plural, one {İndirilen # dosya - {error} dosya başarÄąsÄąz} other {İndirilen # dosyalar - {error} dosyalar başarÄąsÄąz oldu}}", "assets_downloaded_successfully": "{count, plural, one {# dosya başarÄąyla indirildi} other {# dosya başarÄąyla indirildi}}", - "assets_moved_to_trash_count": "{count, plural, one {# varlÄąk} other {# varlÄąk}} çÃļpe taÅŸÄąndÄą", - "assets_permanently_deleted_count": "KalÄącÄą olarak silindi {count, plural, one {# varlÄąk} other {# varlÄąklar}}", - "assets_removed_count": "KaldÄąrÄąldÄą {count, plural, one {# varlÄąk} other {# varlÄąklar}}", + "assets_moved_to_trash_count": "{count, plural, one {# Ãļğe} other {# Ãļğeler}} çÃļpe taÅŸÄąndÄą", + "assets_permanently_deleted_count": "KalÄącÄą olarak silindi {count, plural, one {# Ãļğe} other {# Ãļğeler}}", + "assets_removed_count": "KaldÄąrÄąldÄą {count, plural, one {# Ãļğe} other {# Ãļğeler}}", "assets_removed_permanently_from_device": "{count} Ãļğe cihazÄąnÄązdan kalÄącÄą olarak silindi", - "assets_restore_confirmation": "TÃŧm çÃļp kutusundaki varlÄąklarÄąnÄązÄą geri yÃŧklemek istediğinizden emin misiniz? Bu işlemi geri alamazsÄąnÄąz! AyrÄąca, çevrim dÄąÅŸÄą olan varlÄąklarÄąn bu şekilde geri yÃŧklenemeyeceğini unutmayÄąn.", - "assets_restored_count": "{count, plural, one {# varlÄąk} other {# varlÄąklar}} geri yÃŧklendi", - "assets_restored_successfully": "{count} Ãļğe geri yÃŧklendi", + "assets_restore_confirmation": "TÃŧm çÃļp kutusundaki Ãļğeleri geri yÃŧklemek istediğinizden emin misiniz? Bu işlemi geri alamazsÄąnÄąz! AyrÄąca, çevrim dÄąÅŸÄą olan Ãļğelerin bu şekilde geri yÃŧklenemeyeceğini unutmayÄąn.", + "assets_restored_count": "{count, plural, one {# Ãļğe} other {# Ãļğeler}} geri yÃŧklendi", + "assets_restored_successfully": "{count} Ãļğe başarÄąyla geri yÃŧklendi", "assets_trashed": "{count} Ãļğe çÃļpe atÄąldÄą", - "assets_trashed_count": "{count, plural, one {# varlÄąk} other {# varlÄąklar}} çÃļp kutusuna taÅŸÄąndÄą", - "assets_trashed_from_server": "{count} Ãļğe Immich sunucusunda çÃļpe atÄąldÄą", - "assets_were_part_of_album_count": "{count, plural, one {VarlÄąk zaten} other {VarlÄąklar zaten}} albÃŧmÃŧn parçasÄąydÄą", + "assets_trashed_count": "{count, plural, one {# Ãļğe} other {# Ãļğeler}} çÃļp kutusuna taÅŸÄąndÄą", + "assets_trashed_from_server": "{count} Ãļğe Immich sunucusundan çÃļpe atÄąldÄą", + "assets_were_part_of_album_count": "{count, plural, one {Öğe zaten} other {Öğeler zaten}} albÃŧmÃŧn parçasÄąydÄą", + "assets_were_part_of_albums_count": "{count, plural, one {Öğe zaten} other {Öğeler zaten}} albÃŧmlerin bir parçasÄąydÄą", "authorized_devices": "Yetki Verilmiş Cihazlar", "automatic_endpoint_switching_subtitle": "Belirlenmiş Wi-Fi ağına bağlÄąyken yerel olarak bağlanÄąp başka yerlerde alternatif bağlantÄąyÄą kullan", "automatic_endpoint_switching_title": "Otomatik URL değiştirme", "autoplay_slideshow": "Otomatik slayt gÃļsterisi", "back": "Geri", "back_close_deselect": "Geri, kapat veya seçimi kaldÄąr", + "background_backup_running_error": "Arka plan yedekleme şu anda çalÄąÅŸÄąyor, manuel yedekleme başlatÄąlamÄąyor", "background_location_permission": "Arka plan konum izni", "background_location_permission_content": "Arka planda çalÄąÅŸÄąrken ağ değiştirmek için Immich'in *her zaman* tam konum erişimine sahip olmasÄą gerekir, bÃļylece uygulama Wi-Fi ağınÄąn adÄąnÄą okuyabilir", + "background_options": "Arka Plan Seçenekleri", "backup": "Yedekle", "backup_album_selection_page_albums_device": "Cihazdaki albÃŧmler ({count})", "backup_album_selection_page_albums_tap": "Seçmek için dokunun, hariç tutmak için çift dokunun", - "backup_album_selection_page_assets_scatter": "VarlÄąklar birden fazla albÃŧme dağılabilir. Bu nedenle, yedekleme işlemi sÄąrasÄąnda albÃŧmler dahil edilebilir veya hariç tutulabilir.", + "backup_album_selection_page_assets_scatter": "Öğeler birden fazla albÃŧme dağılabilir. Bu nedenle, yedekleme işlemi sÄąrasÄąnda albÃŧmler dahil edilebilir veya hariç tutulabilir.", "backup_album_selection_page_select_albums": "AlbÃŧm seç", "backup_album_selection_page_selection_info": "Seçim Bilgileri", "backup_album_selection_page_total_assets": "Toplam eşsiz Ãļğeler", + "backup_albums_sync": "Yedekleme albÃŧmlerinin senkronizasyonu", "backup_all": "TÃŧmÃŧ", "backup_background_service_backup_failed_message": "Yedekleme başarÄąsÄąz. Tekrar deneniyorâ€Ļ", "backup_background_service_connection_failed_message": "Sunucuya bağlanÄąlamadÄą. Tekrar deneniyorâ€Ļ", @@ -556,16 +576,16 @@ "backup_controller_page_background_turn_off": "Arka plan hizmetini kapat", "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": "Yedek", "backup_controller_page_backup_selected": "Seçilen: ", - "backup_controller_page_backup_sub": "Yedeklenen Ãļğeler", + "backup_controller_page_backup_sub": "Yedeklenen fotoğraflar ve videolar", "backup_controller_page_created": "Oluşturma tarihi: {date}", "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_failed": "BaşarÄąsÄąz ({count})", "backup_controller_page_filename": "Dosya adÄą: {filename} [{size}]", "backup_controller_page_id": "KNu: {id}", - "backup_controller_page_info": "Yedekleme bilgileri", + "backup_controller_page_info": "Yedekleme Bilgileri", "backup_controller_page_none_selected": "Hiçbiri seçilmedi", "backup_controller_page_remainder": "Kalan", "backup_controller_page_remainder_sub": "Seçili albÃŧmlerden yedeklenecek kalan Ãļğeler", @@ -580,6 +600,7 @@ "backup_controller_page_turn_on": "Ön planda yedeklemeyi aç", "backup_controller_page_uploading_file_info": "Dosya bilgisi yÃŧkleniyor", "backup_err_only_album": "Tek albÃŧm kaldÄąrÄąlamaz", + "backup_error_sync_failed": "Senkronizasyon başarÄąsÄąz. Yedekleme işlemi gerçekleştirilemiyor.", "backup_info_card_assets": "Ãļğeler", "backup_manual_cancelled": "İptal Edildi", "backup_manual_in_progress": "YÃŧkleme halihazÄąrda devam ediyor. Bir sÃŧre sonra deneyin", @@ -590,15 +611,13 @@ "backup_setting_subtitle": "Arka planda ve Ãļn planda yÃŧkleme ayarlarÄąnÄą dÃŧzenle", "backup_settings_subtitle": "YÃŧkleme ayarlarÄąnÄą yÃļnet", "backward": "Geriye doğru", - "beta_sync": "Beta Senkronizasyon Durumu", - "beta_sync_subtitle": "Yeni senkronizasyon sistemini yÃļnetin", "biometric_auth_enabled": "Biyometrik kimlik doğrulama etkin", "biometric_locked_out": "Biyometrik kimlik doğrulamasÄą kilitli", "biometric_no_options": "Biyometrik seçenek yok", "biometric_not_available": "Bu cihazda biyometrik kimlik doğrulama mevcut değil", "birthdate_saved": "Doğum gÃŧnÃŧ başarÄąlÄą bir şekilde kaydedildi", "birthdate_set_description": "Doğum gÃŧnÃŧ, fotoğraftaki insanÄąn fotoğraf çekildiği zamandaki yaÅŸÄąnÄąn hesaplanmasÄą için kullanÄąlÄąr.", - "blurred_background": "BulanÄąk arkaplan", + "blurred_background": "BulanÄąk arka plan", "bugs_and_feature_requests": "Hatalar ve Özellik Talepleri", "build": "YapÄą", "build_image": "GÃļrÃŧntÃŧ Oluştur", @@ -640,32 +659,34 @@ "change_name": "İsim değiştir", "change_name_successfully": "AdÄą başarÄąyla değiştirildi", "change_password": "Şifre Değiştir", - "change_password_description": "Bu ya sistemdeki ilk oturum aÃ§ÄąÅŸÄąnÄąz ya da şifre değişikliği için bir talepte bulunuldu. LÃŧtfen yeni şifreyi aşağıya yazÄąnÄąz.", - "change_password_form_confirm_password": "Parola OnayÄą", - "change_password_form_description": "Merhaba {name},\n\nBu sisteme ilk kez giriş yaptÄąnÄąz veya parolanÄązÄą değiştirmeniz için bir talepte bulunuldu. LÃŧtfen aşağıya yeni parolanÄązÄą girin.", - "change_password_form_new_password": "Yeni Parola", - "change_password_form_password_mismatch": "Parolalar eşleşmiyor", - "change_password_form_reenter_new_password": "Tekrar Yeni Parola", + "change_password_description": "Bu sisteme ilk kez giriş yapÄąyorsunuz veya şifrenizi değiştirmek için bir istekte bulunuldu. LÃŧtfen aşağıya yeni şifrenizi girin.", + "change_password_form_confirm_password": "Şifreyi Onayla", + "change_password_form_description": "Merhaba {name},\n\nBu sisteme ilk kez giriş yapÄąyorsunuz veya şifrenizi değiştirmek için bir istekte bulunuldu. LÃŧtfen aşağıya yeni şifrenizi girin.", + "change_password_form_new_password": "Yeni Şifre", + "change_password_form_password_mismatch": "Şifreler eşleşmiyor", + "change_password_form_reenter_new_password": "Yeni Şifreyi Tekrar Giriniz", "change_pin_code": "PIN kodunu değiştirin", "change_your_password": "Şifreni değiştir", "changed_visibility_successfully": "GÃļrÃŧnÃŧrlÃŧk başarÄąyla değiştirildi", - "check_corrupt_asset_backup": "Bozuk yedek dosyalarÄąnÄą kontrol et", + "charging": "Şarj oluyor", + "charging_requirement_mobile_backup": "Arka plan yedekleme için cihazÄąn şarjda olmasÄą gerekir", + "check_corrupt_asset_backup": "Bozuk Ãļğe yedeklemelerini kontrol et", "check_corrupt_asset_backup_button": "Kontrol et", - "check_corrupt_asset_backup_description": "Bu kontrolÃŧ yalnÄązca Wi-Fi Ãŧzerinden ve tÃŧm dosyalar yedeklendikten sonra çalÄąÅŸtÄąrÄąn. İşlem birkaç dakika sÃŧrebilir.", + "check_corrupt_asset_backup_description": "Bu kontrolÃŧ yalnÄązca Wi-Fi Ãŧzerinden ve tÃŧm Ãļğeler yedeklendikten sonra çalÄąÅŸtÄąrÄąn. İşlem birkaç dakika sÃŧrebilir.", "check_logs": "GÃŧnlÃŧkleri Kontrol Et", "choose_matching_people_to_merge": "Birleştirmek için eşleşen kişileri seçiniz", "city": "Şehir", - "clear": "Temiz", + "clear": "Temizle", "clear_all": "Hepsini temizle", "clear_all_recent_searches": "Son aramalarÄąn hepsini temizle", - "clear_file_cache": "Dosya Önbelleği Temizle", - "clear_message": "MesajÄą Temizle", - "clear_value": "Değeri Temizle", + "clear_file_cache": "Dosya Önbelleğini Temizle", + "clear_message": "MesajÄą temizle", + "clear_value": "Değeri temizle", "client_cert_dialog_msg_confirm": "Tamam", - "client_cert_enter_password": "Parola Gir", + "client_cert_enter_password": "Şifreyi Girin", "client_cert_import": "İçe Aktar", "client_cert_import_success_msg": "İstemci sertifikasÄą içe aktarÄąldÄą", - "client_cert_invalid_msg": "Geçersiz sertifika dosyasÄą veya yanlÄąÅŸ parola", + "client_cert_invalid_msg": "Geçersiz sertifika dosyasÄą veya yanlÄąÅŸ şifre", "client_cert_remove_msg": "İstemci sertifikasÄą kaldÄąrÄąldÄą", "client_cert_subtitle": "YalnÄązca PKCS12 (.p12, .pfx) biçimini destekler. Sertifika İçe Aktarma/KaldÄąrma yalnÄązca oturum açmadan Ãļnce kullanÄąlabilir", "client_cert_title": "SSL İstemci SertifikasÄą", @@ -684,16 +705,16 @@ "completed": "TamamlandÄą", "confirm": "Onayla", "confirm_admin_password": "YÃļnetici Şifresini Onayla", - "confirm_delete_face": "VarlÄąktan {name} yÃŧzÃŧnÃŧ silmek istediğinizden emin misiniz?", + "confirm_delete_face": "Öğeden {name} yÃŧzÃŧnÃŧ silmek istediğinizden emin misiniz?", "confirm_delete_shared_link": "Bu paylaÅŸÄąlan bağlantÄąyÄą silmek istediğinizden emin misiniz?", - "confirm_keep_this_delete_others": "Yığındaki diğer tÃŧm Ãļğeler bu varlÄąk haricinde silinecektir. Devam etmek istediğinizden emin misiniz?", + "confirm_keep_this_delete_others": "Bu Ãļğe hariç, yığındaki diğer tÃŧm Ãļğeler silinecektir. Devam etmek istediğinizden emin misiniz?", "confirm_new_pin_code": "Yeni PIN kodunu onaylayÄąn", "confirm_password": "Şifreyi onayla", "confirm_tag_face": "Bu yÃŧzÃŧ {name} olarak etiketlemek ister misiniz?", "confirm_tag_face_unnamed": "Bu yÃŧzÃŧ etiketlemek ister misin?", "connected_device": "Cihaz bağlandÄą", "connected_to": "BağlÄą", - "contain": "İçermek", + "contain": "SığdÄąr", "context": "Bağlam", "continue": "Devam et", "control_bottom_app_bar_create_new_album": "Yeni albÃŧm", @@ -711,11 +732,11 @@ "copy_image": "Resmi Kopyala", "copy_link": "BağlantÄąyÄą kopyala", "copy_link_to_clipboard": "BağlantÄąyÄą panoya kopyala", - "copy_password": "ParolayÄą kopyala", + "copy_password": "Şifreyi kopyala", "copy_to_clipboard": "Panoya Kopyala", "country": "Ülke", "cover": "Kapla", - "covers": "Kaplar", + "covers": "Kapak", "create": "Oluştur", "create_album": "AlbÃŧm oluştur", "create_album_page_untitled": "BaşlÄąksÄąz", @@ -725,9 +746,9 @@ "create_link_to_share_description": "BağlantÄąya sahip olan herkesin seçilen fotoğraflarÄą gÃļrmesine izin ver", "create_new": "YENİ OLUŞTUR", "create_new_person": "Yeni kişi oluştur", - "create_new_person_hint": "Seçili varlÄąklarÄą yeni bir kişiye atayÄąn", + "create_new_person_hint": "Seçili Ãļğeleri yeni bir kişiye atayÄąn", "create_new_user": "Yeni kullanÄącÄą oluştur", - "create_shared_album_page_share_add_assets": "İÇERİK EKLE", + "create_shared_album_page_share_add_assets": "ÖĞELER EKLE", "create_shared_album_page_share_select_photos": "FotoğraflarÄą Seç", "create_shared_link": "PaylaÅŸÄąlan bağlantÄą oluştur", "create_tag": "Etiket oluştur", @@ -735,6 +756,7 @@ "create_user": "KullanÄącÄą oluştur", "created": "Oluşturuldu", "created_at": "Oluşturuldu", + "creating_linked_albums": "BağlantÄąlÄą albÃŧmler oluşturuluyor...", "crop": "Kes", "curated_object_page_title": "Nesneler", "current_device": "Mevcut cihaz", @@ -759,11 +781,11 @@ "deduplication_criteria_1": "Resim boyutu (bayt olarak)", "deduplication_criteria_2": "EXIF veri sayÄąsÄą", "deduplication_info": "Tekilleştirme Bilgileri", - "deduplication_info_description": "VarlÄąklarÄą otomatik olarak Ãļnceden seçmek ve yinelenenleri toplu olarak kaldÄąrmak için şunlara bakÄąyoruz:", + "deduplication_info_description": "Öğeleri otomatik olarak Ãļnceden seçmek ve yinelenenleri toplu olarak kaldÄąrmak için şunlara bakÄąyoruz:", "default_locale": "VarsayÄąlan Yerel Ayar", "default_locale_description": "Tarihleri ve sayÄąlarÄą tarayÄącÄąnÄązÄąn yerel ayarÄąna gÃļre biçimlendirin", "delete": "Sil", - "delete_action_confirmation_message": "Bu varlığı silmek istediğinizden emin misiniz? Bu işlem, varlığı sunucunun çÃļp kutusuna taÅŸÄąyacak ve yerel olarak silmek isteyip istemediğinizi soracaktÄąr", + "delete_action_confirmation_message": "Bu Ãļğeyi silmek istediğinizden emin misiniz? Bu işlem, Ãļğeyi sunucunun çÃļp kutusuna taÅŸÄąyacak ve yerel olarak silmek isteyip istemediğinizi soracaktÄąr", "delete_action_prompt": "{count} silindi", "delete_album": "AlbÃŧmÃŧ sil", "delete_api_key_prompt": "Bu API anahtarÄąnÄą silmek istediğinizden emin misiniz?", @@ -784,13 +806,13 @@ "delete_others": "Diğerlerini sil", "delete_permanently": "KalÄącÄą olarak sil", "delete_permanently_action_prompt": "{count} kalÄącÄą olarak silindi", - "delete_shared_link": "PaylaÅŸÄąlmÄąÅŸ linki sil", - "delete_shared_link_dialog_title": "PaylaÅŸÄąlan BağlantÄą Sil", + "delete_shared_link": "PaylaÅŸÄąlan bağlantÄąyÄą sil", + "delete_shared_link_dialog_title": "PaylaÅŸÄąlan BağlantÄąyÄą Sil", "delete_tag": "Etiketi sil", "delete_tag_confirmation_prompt": "{tagName} etiketini silmek istediğinizden emin misiniz?", "delete_user": "KullanÄącÄąyÄą sil", "deleted_shared_link": "PaylaÅŸÄąlan bağlantÄą silindi", - "deletes_missing_assets": "Diskte eksik olan varlÄąklarÄą siler", + "deletes_missing_assets": "Diskte eksik olan Ãļğeleri siler", "description": "AÃ§Äąklama", "description_input_hint_text": "AÃ§Äąklama ekle...", "description_input_submit_error": "AÃ§Äąklama gÃŧncellenirken hata oluştu, daha fazla ayrÄąntÄą için gÃŧnlÃŧğÃŧ kontrol edin", @@ -807,12 +829,12 @@ "display_options": "GÃļrÃŧntÃŧleme seçenekleri", "display_order": "GÃļsterim sÄąralamasÄą", "display_original_photos": "Orijinal fotoğraflarÄą gÃļster", - "display_original_photos_setting_description": "Orijinal varlÄąk web uyumlu olduğunda, bir varlığı gÃļrÃŧntÃŧlerken kÃŧçÃŧk resimler yerine orijinal fotoğrafÄą gÃļrÃŧntÃŧlemeyi tercih edin. Bu, fotoğraf gÃļrÃŧntÃŧleme hÄązlarÄąnÄąn yavaşlamasÄąna neden olabilir.", + "display_original_photos_setting_description": "Orijinal Ãļğe web uyumlu olduğunda, bir Ãļğeyi gÃļrÃŧntÃŧlerken kÃŧçÃŧk resimler yerine orijinal fotoğrafÄą gÃļrÃŧntÃŧlemeyi tercih edin. Bu, fotoğraf gÃļrÃŧntÃŧleme hÄązlarÄąnÄąn yavaşlamasÄąna neden olabilir.", "do_not_show_again": "Bu mesajÄą bir daha gÃļsterme", "documentation": "DokÃŧmantasyon", "done": "Bitti", "download": "İndir", - "download_action_prompt": "{count} varlÄąk indiriliyor", + "download_action_prompt": "{count} Ãļğe indiriliyor", "download_canceled": "İndirme iptal edildi", "download_complete": "İndirme tamamlandÄą", "download_enqueue": "İndirme sÄąraya alÄąndÄą", @@ -824,13 +846,13 @@ "download_notfound": "İndirme bulunamadÄą", "download_paused": "İndirme duraklatÄąldÄą", "download_settings": "İndir", - "download_settings_description": "VarlÄąk indirme ile ilgili ayarlarÄą yÃļnetin", + "download_settings_description": "Öğe indirme ile ilgili ayarlarÄą yÃļnetin", "download_started": "İndirme başladÄą", "download_sucess": "İndirme başarÄąlÄą", "download_sucess_android": "Medya DCIM/Immich klasÃļrÃŧne indirildi", "download_waiting_to_retry": "Yeniden denemek için bekleniyor", "downloading": "İndiriliyor", - "downloading_asset_filename": "VarlÄąk indiriliyor {filename}", + "downloading_asset_filename": "Öğe indiriliyor {filename}", "downloading_media": "Medya indiriliyor", "drop_files_to_upload": "DosyalarÄą yÃŧklemek için herhangi bir yere bÄąrakÄąn", "duplicates": "Kopyalar", @@ -843,6 +865,7 @@ "edit_date": "Tarihi DÃŧzenle", "edit_date_and_time": "Tarih ve zamanÄą dÃŧzenleyin", "edit_date_and_time_action_prompt": "{count} tarih ve zaman dÃŧzenlendi", + "edit_date_and_time_by_offset": "Tarihi ofset ile değiştir", "edit_date_and_time_by_offset_interval": "Yeni tarih aralığı: {from}'dan {to}'a kadar", "edit_description": "AÃ§ÄąklamayÄą dÃŧzenle", "edit_description_prompt": "LÃŧtfen yeni bir aÃ§Äąklama seçin:", @@ -870,7 +893,7 @@ "email_notifications": "E-posta bildirimleri", "empty_folder": "Bu klasÃļr boş", "empty_trash": "ÇÃļpÃŧ boşalt", - "empty_trash_confirmation": "ÇÃļp kutusunu boşaltmak istediğinizden emin misiniz? Bu işlem, Immich'teki çÃļp kutusundaki tÃŧm varlÄąklarÄą kalÄącÄą olarak silecektir.\nBu işlemi geri alamazsÄąnÄąz!", + "empty_trash_confirmation": "ÇÃļp kutusunu boşaltmak istediğinizden emin misiniz? Bu işlem, çÃļp kutusundaki tÃŧm varlÄąklarÄą Immich'ten kalÄącÄą olarak silecektir.\nBu işlemi geri alamazsÄąnÄąz!", "enable": "Etkinleştir", "enable_backup": "Yedeklemeyi Etkinleştir", "enable_biometric_auth_description": "Biyometrik kimlik doğrulamasÄąnÄą etkinleştirmek için PIN kodu girin", @@ -878,47 +901,49 @@ "end_date": "Bitiş tarihi", "enqueued": "Kuyruğa alÄąndÄą", "enter_wifi_name": "Wi-Fi adÄąnÄą girin", - "enter_your_pin_code": "Pin kodu girin", + "enter_your_pin_code": "PIN kodunuzu girin", "enter_your_pin_code_subtitle": "Kilitli klasÃļre erişmek için PIN kodunuzu girin", "error": "Hata", "error_change_sort_album": "AlbÃŧm sÄąralama dÃŧzeni değiştirilemedi", - "error_delete_face": "YÃŧzÃŧ varlÄąktan silme hatasÄą", + "error_delete_face": "Öğeden yÃŧz silme hatasÄą", + "error_getting_places": "Konum bilgisi alÄąnÄąrken hata oluştu", "error_loading_image": "Resim yÃŧklenirken hata oluştu", + "error_loading_partners": "OrtaklarÄą yÃŧkleme hatasÄą: {error}", "error_saving_image": "Hata: {error}", "error_tag_face_bounding_box": "YÃŧz etiketleme hatasÄą – sÄąnÄąrlayÄącÄą kutu koordinatlarÄą alÄąnamadÄą", "error_title": "Bir Hata Oluştu - Bir şeyler ters gitti", "errors": { - "cannot_navigate_next_asset": "Sonraki varlığa geçiş yapÄąlamÄąyor", - "cannot_navigate_previous_asset": "Önceki varlığa geçiş yapÄąlamÄąyor", + "cannot_navigate_next_asset": "Sonraki Ãļğeye geçiş yapÄąlamÄąyor", + "cannot_navigate_previous_asset": "Önceki Ãļğeye geçiş yapÄąlamÄąyor", "cant_apply_changes": "Değişiklikler uygulanamÄąyor", "cant_change_activity": "Etkinliği {enabled, select, true {devre dÄąÅŸÄą bÄąrakamÄąyor} other {etkinleştiremiyor}}", - "cant_change_asset_favorite": "Varlığın favori durumunu değiştiremiyor", - "cant_change_metadata_assets_count": "{count, plural, one {# varlığın} other {# varlÄąklarÄąn}} meta verisi değiştirilemiyor", + "cant_change_asset_favorite": "Öğenin favori durumu değiştirilemiyor", + "cant_change_metadata_assets_count": "{count, plural, one {# Ãļğenin} other {# Ãļğelerin}} meta verisi değiştirilemiyor", "cant_get_faces": "YÃŧzler alÄąnamadÄą", "cant_get_number_of_comments": "YorumlarÄąn sayÄąsÄą alÄąnamadÄą", "cant_search_people": "Kişiler aranamÄąyor", "cant_search_places": "Mekanlar aranamÄąyor", - "error_adding_assets_to_album": "AlbÃŧme varlÄąk ekleme hatasÄą", + "error_adding_assets_to_album": "AlbÃŧme Ãļğe ekleme hatasÄą", "error_adding_users_to_album": "AlbÃŧme kullanÄącÄą ekleme hatasÄą", "error_deleting_shared_user": "PaylaÅŸÄąlan kullanÄącÄą silme hatasÄą", "error_downloading": "{filename} indirme hatasÄą", "error_hiding_buy_button": "SatÄąn alma butonu gizleme hatasÄą", - "error_removing_assets_from_album": "Varlığı albÃŧmden silme hatasÄą, daha fazla detay için konsolu kontrol et", - "error_selecting_all_assets": "BÃŧtÃŧn varlÄąklarÄą seçme hatasÄą", + "error_removing_assets_from_album": "Öğeyi albÃŧmden silme hatasÄą, daha fazla detay için konsolu kontrol et", + "error_selecting_all_assets": "TÃŧm Ãļğeleri seçerken hata oluştu", "exclusion_pattern_already_exists": "Bu dÄąÅŸlama modeli halihazÄąrda mevcut.", "failed_to_create_album": "AlbÃŧm oluşturulamadÄą", "failed_to_create_shared_link": "PaylaÅŸÄąlan bağlantÄą oluşturulamadÄą", "failed_to_edit_shared_link": "PaylaÅŸÄąlan bağlantÄą dÃŧzenlenemedi", "failed_to_get_people": "Kişiler alÄąnamadÄą", "failed_to_keep_this_delete_others": "Bu Ãļğenin tutulmasÄą ve diğer Ãļğenin silinmesi başarÄąsÄąz oldu", - "failed_to_load_asset": "VarlÄąk yÃŧklenemedi", - "failed_to_load_assets": "VarlÄąklar yÃŧklenemedi", + "failed_to_load_asset": "Öğe yÃŧklenemedi", + "failed_to_load_assets": "Öğeler yÃŧklenemedi", "failed_to_load_notifications": "Bildirim yÃŧklenemedi", "failed_to_load_people": "Kişiler yÃŧklenemedi", "failed_to_remove_product_key": "ÜrÃŧn anahtarÄą kaldÄąrÄąlamadÄą", - "failed_to_reset_pin_code": "Pin kodu sÄąfÄąrlanamadÄą", - "failed_to_stack_assets": "VarlÄąklar yığınlanamadÄą", - "failed_to_unstack_assets": "VarlÄąklarÄąn yığınÄą kaldÄąrÄąlamadÄą", + "failed_to_reset_pin_code": "PIN kodu sÄąfÄąrlanamadÄą", + "failed_to_stack_assets": "Öğeler yığınlanamadÄą", + "failed_to_unstack_assets": "Öğelerin yığınÄą kaldÄąrÄąlamadÄą", "failed_to_update_notification_status": "Bildirim durumu gÃŧncellenemedi", "import_path_already_exists": "Bu içe aktarma yolu halihazÄąrda mevcut.", "incorrect_email_or_password": "YanlÄąÅŸ e-posta veya şifre", @@ -927,7 +952,7 @@ "quota_higher_than_disk_size": "Disk boyutundan daha yÃŧksek bir kota belirlediniz", "something_went_wrong": "Bir şeyler ters gitti", "unable_to_add_album_users": "KullanÄącÄąlar albÃŧme eklenemiyor", - "unable_to_add_assets_to_shared_link": "VarlÄąklar paylaÅŸÄąlan bağlantÄąya eklenemiyor", + "unable_to_add_assets_to_shared_link": "Öğeler paylaÅŸÄąlan bağlantÄąya eklenemiyor", "unable_to_add_comment": "Yorum eklenemiyor", "unable_to_add_exclusion_pattern": "Hariç tutma modeli eklenemiyor", "unable_to_add_import_path": "İçe aktarma yolu eklenemiyor", @@ -950,8 +975,8 @@ "unable_to_create_library": "KÃŧtÃŧphane oluşturulamÄąyor", "unable_to_create_user": "KullanÄącÄą oluşturulamÄąyor", "unable_to_delete_album": "AlbÃŧm silinemiyor", - "unable_to_delete_asset": "VarlÄąk silinemiyor", - "unable_to_delete_assets": "VarlÄąklar silinemiyor", + "unable_to_delete_asset": "Öğe silinemiyor", + "unable_to_delete_assets": "Öğeler silinemiyor", "unable_to_delete_exclusion_pattern": "Hariç tutma deseni silinemiyor", "unable_to_delete_import_path": "İçe aktarma yolu silinemiyor", "unable_to_delete_shared_link": "PaylaÅŸÄąlan bağlantÄą silinemiyor", @@ -971,19 +996,19 @@ "unable_to_log_out_device": "Cihazdan Ã§ÄąkÄąÅŸ yapÄąlamÄąyor", "unable_to_login_with_oauth": "OAuth ile giriş yapÄąlamÄąyor", "unable_to_play_video": "Video oynatÄąlamÄąyor", - "unable_to_reassign_assets_existing_person": "VarlÄąklar {name, select, null {mevcut bir kişiye} other {{name}}} yeniden atanamÄąyor", - "unable_to_reassign_assets_new_person": "VarlÄąklar yeni bir kişiye yeniden atanamÄąyor", + "unable_to_reassign_assets_existing_person": "Öğeler {name, select, null {mevcut bir kişiye} other {{name}}} yeniden atanamÄąyor", + "unable_to_reassign_assets_new_person": "Öğeler yeni bir kişiye yeniden atanamÄąyor", "unable_to_refresh_user": "KullanÄącÄą yenilenemiyor", "unable_to_remove_album_users": "AlbÃŧm kullanÄącÄąlarÄą kaldÄąrÄąlamÄąyor", "unable_to_remove_api_key": "API anahtarÄą kaldÄąrÄąlamÄąyor", - "unable_to_remove_assets_from_shared_link": "VarlÄąklar paylaÅŸÄąlan bağlantÄądan kaldÄąrÄąlamÄąyor", + "unable_to_remove_assets_from_shared_link": "Öğeler paylaÅŸÄąlan bağlantÄądan kaldÄąrÄąlamÄąyor", "unable_to_remove_library": "KÃŧtÃŧphane kaldÄąrÄąlamadÄą", "unable_to_remove_partner": "Ortak kaldÄąrÄąlamÄąyor", "unable_to_remove_reaction": "Reaksiyon kaldÄąrÄąlamÄąyor", "unable_to_reset_password": "Şifre sÄąfÄąrlanamÄąyor", - "unable_to_reset_pin_code": "Pin kodunu sÄąfÄąrlanamÄąyor", + "unable_to_reset_pin_code": "PIN kodu sÄąfÄąrlanamÄąyor", "unable_to_resolve_duplicate": "Çiftler çÃļzÃŧmlenemiyor", - "unable_to_restore_assets": "VarlÄąklar geri yÃŧklenemiyor", + "unable_to_restore_assets": "Öğeler geri yÃŧklenemiyor", "unable_to_restore_trash": "ÇÃļp geri yÃŧklenemiyor", "unable_to_restore_user": "KullanÄącÄą geri yÃŧklenemiyor", "unable_to_save_album": "AlbÃŧm kaydedilemiyor", @@ -997,7 +1022,7 @@ "unable_to_set_feature_photo": "Özellikli fotoğraf ayarlanamÄąyor", "unable_to_set_profile_picture": "Profil resmi ayarlanamÄąyor", "unable_to_submit_job": "GÃļrev gÃļnderilemiyor", - "unable_to_trash_asset": "VarlÄąk çÃļp kutusuna taÅŸÄąnamÄąyor", + "unable_to_trash_asset": "Öğe çÃļp kutusuna taÅŸÄąnamÄąyor", "unable_to_unlink_account": "Hesap bağlantÄąsÄą kaldÄąrÄąlamÄąyor", "unable_to_unlink_motion_video": "Hareket videosunun bağlantÄąsÄą kaldÄąrÄąlamÄąyor", "unable_to_update_album_cover": "AlbÃŧm resmi gÃŧncellenemiyor", @@ -1039,15 +1064,16 @@ "face_unassigned": "YÃŧz atanmadÄą", "failed": "BaşarÄąsÄąz", "failed_to_authenticate": "Kimlik doğrulamasÄą yapÄąlamadÄą", - "failed_to_load_assets": "VarlÄąklar yÃŧklenemedi", + "failed_to_load_assets": "Öğeler yÃŧklenemedi", "failed_to_load_folder": "KlasÃļr yÃŧklenemedi", - "favorite": "GÃļzde", - "favorite_action_prompt": "{count} gÃļzdelere eklendi", - "favorite_or_unfavorite_photo": "GÃļzdeye ekle veya Ã§Äąkar", - "favorites": "GÃļzdeler", - "favorites_page_no_favorites": "GÃļzde Ãļge bulunamadÄą", - "feature_photo_updated": "Özellikli fotoğraf gÃŧncellendi", + "favorite": "Favori", + "favorite_action_prompt": "{count} Favorilere eklendi", + "favorite_or_unfavorite_photo": "Favorilere ekle veya Ã§Äąkar", + "favorites": "Favoriler", + "favorites_page_no_favorites": "Favori Ãļğe bulunamadÄą", + "feature_photo_updated": "Öne Ã§Äąkan fotoğraf gÃŧncellendi", "features": "Özellikler", + "features_in_development": "Geliştirme AşamasÄąndaki Özellikler", "features_setting_description": "UygulamanÄąn Ãļzelliklerini yÃļnet", "file_name": "Dosya adÄą", "file_name_or_extension": "Dosya adÄą veya uzantÄą", @@ -1063,17 +1089,20 @@ "folder_not_found": "KlasÃļr bulunamadÄą", "folders": "KlasÃļrler", "folders_feature_description": "Dosya sistemindeki fotoğraf ve videolarÄą klasÃļr gÃļrÃŧnÃŧmÃŧyle keşfedin", - "forgot_pin_code_question": "PIN'inizi mi unuttunuz?", + "forgot_pin_code_question": "PIN kodunuzu mu unuttunuz?", "forward": "İleri", "gcast_enabled": "Google Cast", "gcast_enabled_description": "Bu Ãļzellik, çalÄąÅŸabilmek için Google'dan harici kaynaklar yÃŧkler.", "general": "Genel", + "geolocation_instruction_location": "GPS koordinatlarÄą olan bir Ãļğeyi tÄąklayarak konumunu kullanÄąn veya haritadan doğrudan bir konum seçin", "get_help": "YardÄąm Al", "get_wifiname_error": "Wi-Fi adÄą alÄąnamadÄą. Gerekli izinleri verdiğinizden ve bir Wi-Fi ağına bağlÄą olduğunuzdan emin olun", "getting_started": "Başlarken", "go_back": "Geri git", "go_to_folder": "KlasÃļre git", "go_to_search": "Aramaya git", + "gps": "GPS", + "gps_missing": "GPS yok", "grant_permission": "İzin ver", "group_albums_by": "AlbÃŧmleri gruplandÄąr...", "group_country": "Ülkeye gÃļre grupla", @@ -1084,14 +1113,14 @@ "haptic_feedback_switch": "Dokunsal geri bildirimi aç", "haptic_feedback_title": "Dokunsal Geri Bildirim (Haptic Feedback)", "has_quota": "Kota var", - "hash_asset": "Hash varlığı", - "hashed_assets": "Hashlenmiş varlÄąklar", + "hash_asset": "Karma Ãļğe", + "hashed_assets": "Karma Ãļğeler", "hashing": "Hashleme", "header_settings_add_header_tip": "Header Ekle", "header_settings_field_validator_msg": "Değer boş olamaz", "header_settings_header_name_input": "Header adÄą", "header_settings_header_value_input": "Header değeri", - "headers_settings_tile_subtitle": "UygulamanÄąn her ağ isteğiyle birlikte gÃļndermesi gereken proxy header'larÄą tanÄąmlayÄąn", + "headers_settings_tile_subtitle": "UygulamanÄąn her ağ isteğinde gÃļndermesi gereken proxy başlÄąklarÄąnÄą tanÄąmlayÄąn", "headers_settings_tile_title": "Özel proxy headers", "hi_user": "Merhaba {name} {email}", "hide_all_people": "TÃŧm kişileri gizle", @@ -1100,20 +1129,20 @@ "hide_password": "Şifreyi gizle", "hide_person": "Kişiyi gizle", "hide_unnamed_people": "İsimsiz kişileri gizle", - "home_page_add_to_album_conflicts": "{album} albÃŧmÃŧne {added} Ãļğe eklendi. {failed} varlÄąk zaten albÃŧmdeydi.", + "home_page_add_to_album_conflicts": "{album} albÃŧmÃŧne {added} Ãļğe eklendi. {failed} Ãļğe zaten albÃŧmdeydi.", "home_page_add_to_album_err_local": "Yerel Ãļğeler henÃŧz albÃŧmlere eklenemiyor, atlanÄąyor", "home_page_add_to_album_success": "{album} albÃŧmÃŧne {added} Ãļğe eklendi.", - "home_page_album_err_partner": "Partner Ãļğeleri henÃŧz bir albÃŧme eklenemiyor, atlanÄąyor", + "home_page_album_err_partner": "Ortak Ãļğeler henÃŧz bir albÃŧme eklenemiyor, atlanÄąyor", "home_page_archive_err_local": "Yerel Ãļğeler henÃŧz arşivlenemiyor, atlanÄąyor", - "home_page_archive_err_partner": "Partner Ãļğeleri henÃŧz arşivlenemiyor, atlanÄąyor", + "home_page_archive_err_partner": "Ortak Ãļğeler henÃŧz arşivlenemiyor, atlanÄąyor", "home_page_building_timeline": "Zaman çizelgesi oluşturuluyor", - "home_page_delete_err_partner": "Partner Ãļğeleri silinemez, atlanÄąyor", + "home_page_delete_err_partner": "Ortak Ãļğeler silinemez, atlanÄąyor", "home_page_delete_remote_err_local": "Uzaktan silme seçimindeki yerel Ãļğeler atlanÄąyor", - "home_page_favorite_err_local": "Yerel Ãļgeler henÃŧz gÃļzdelere eklenemiyor, atlanÄąyor", - "home_page_favorite_err_partner": "Ortak Ãļgeleri henÃŧz gÃļzdelere eklenemiyor, atlanÄąyor", - "home_page_first_time_notice": "UygulamayÄą ilk kez kullanÄąyorsanÄąz, zaman çizelgesinin albÃŧmlerdeki fotoğraf ve videolar ile oluşturulabilmesi için lÃŧtfen yedekleme için albÃŧm(ler) seçtiğinizden emin olun.", - "home_page_locked_error_local": "Yerel varlÄąklar kilitli klasÃļre taÅŸÄąnamÄąyor, atlanÄąyor", - "home_page_locked_error_partner": "Ortak varlÄąklar kilitli klasÃļre taÅŸÄąnamÄąyor, atlanÄąyor", + "home_page_favorite_err_local": "Yerel Ãļğeler henÃŧz favorilere eklenemiyor, atlanÄąyor", + "home_page_favorite_err_partner": "Ortak Ãļğeler henÃŧz favorilere eklenemiyor, atlanÄąyor", + "home_page_first_time_notice": "UygulamayÄą ilk kez kullanÄąyorsanÄąz, zaman çizelgesinin albÃŧmlerdeki fotoğraf ve videolar ile oluşturulabilmesi için lÃŧtfen yedekleme için albÃŧm seçtiğinizden emin olun", + "home_page_locked_error_local": "Yerel Ãļğeler kilitli klasÃļre taÅŸÄąnamÄąyor, atlanÄąyor", + "home_page_locked_error_partner": "Ortak Ãļğeler kilitli klasÃļre taÅŸÄąnamÄąyor, atlanÄąyor", "home_page_share_err_local": "Yerel Ãļğeler bağlantÄą ile paylaÅŸÄąlamaz, atlanÄąyor", "home_page_upload_err_limit": "AynÄą anda en fazla 30 Ãļğe yÃŧklenebilir, atlanabilir", "host": "Ana bilgisayar", @@ -1146,7 +1175,7 @@ "in_archive": "Arşivde", "include_archived": "Arşivlenenleri dahil et", "include_shared_albums": "PaylaÅŸÄąlmÄąÅŸ albÃŧmleri dahil et", - "include_shared_partner_assets": "PaylaÅŸÄąlan ortak varlÄąklarÄą dahil et", + "include_shared_partner_assets": "PaylaÅŸÄąlan ortak Ãļğeleri dahil et", "individual_share": "Bireysel paylaÅŸÄąm", "individual_shares": "Kişisel paylaÅŸÄąmlar", "info": "Bilgi", @@ -1161,9 +1190,9 @@ "invite_people": "Kişileri Davet Et", "invite_to_album": "AlbÃŧme davet et", "ios_debug_info_fetch_ran_at": "Veri çekme {dateTime} tarihinde çalÄąÅŸtÄąrÄąldÄą", - "ios_debug_info_last_sync_at": "Son eşleme: {dateTime}", + "ios_debug_info_last_sync_at": "Son eşzamanlama {dateTime}", "ios_debug_info_no_processes_queued": "Hiçbir arka plan işlemi kuyruğa alÄąnmadÄą", - "ios_debug_info_no_sync_yet": "HenÃŧz hiçbir arka plan eşleme gÃļrevi çalÄąÅŸtÄąrÄąlmadÄą", + "ios_debug_info_no_sync_yet": "HenÃŧz arka plan eşzamanlama gÃļrevi çalÄąÅŸtÄąrÄąlmadÄą", "ios_debug_info_processes_queued": "{count, plural, one {{count} arka plan işlemi kuyruğa alÄąndÄą} other {{count} arka plan işlemi kuyruğa alÄąndÄą}}", "ios_debug_info_processing_ran_at": "İşleme {dateTime} tarihinde çalÄąÅŸtÄąrÄąldÄą", "items_count": "{count, plural, one {# Öğe} other {# Öğe}}", @@ -1171,7 +1200,7 @@ "keep": "Koru", "keep_all": "Hepsini koru", "keep_this_delete_others": "Bunu sakla, diğerlerini sil", - "kept_this_deleted_others": "Bu varlÄąk tutuldu ve {count, plural, one {# varlÄąk} other {# varlÄąk}} silindi", + "kept_this_deleted_others": "Bu Ãļğe tutuldu ve {count, plural, one {# varlÄąk} other {# varlÄąk}} silindi", "keyboard_shortcuts": "Klavye kÄąsayollarÄą", "language": "Dil", "language_no_results_subtitle": "Arama teriminizi değiştirmeyi deneyin", @@ -1181,7 +1210,7 @@ "large_files": "BÃŧyÃŧk Dosyalar", "last": "Son", "last_seen": "Son gÃļrÃŧlme", - "latest_version": "En son versiyon", + "latest_version": "En Son SÃŧrÃŧm", "latitude": "Enlem", "leave": "AyrÄąl", "leave_album": "AlbÃŧmden Ã§Äąk", @@ -1207,9 +1236,10 @@ "loading": "YÃŧkleniyor", "loading_search_results_failed": "Arama sonuçlarÄą yÃŧklenemedi", "local": "Yerel", - "local_asset_cast_failed": "Sunucuya yÃŧklenmemiş bir varlÄąk yansÄątÄąlamaz", - "local_assets": "Yerel VarlÄąklar", - "local_network": "Yerel Wi-Fi", + "local_asset_cast_failed": "Sunucuya yÃŧklenmemiş bir Ãļğe yansÄątÄąlamaz", + "local_assets": "Yerel Öğeler", + "local_media_summary": "Yerel Medya Özeti", + "local_network": "Yerel ağ", "local_network_sheet_info": "Uygulama belirlenmiş Wi-Fi ağınÄą kullanÄąrken bu URL Ãŧzerinden sunucuya bağlanacaktÄąr", "location_permission": "Konum izni", "location_permission_content": "Otomatik geçiş Ãļzelliğinin çalÄąÅŸabilmesi için Immich'in mevcut Wi-Fi ağınÄąn adÄąnÄą bilmesi, bunu sağlamak için de tam konum iznine ihtiyacÄą vardÄąr", @@ -1220,6 +1250,7 @@ "location_picker_longitude_hint": "Buraya boylam yazÄąn", "lock": "Kilitle", "locked_folder": "Kilitli KlasÃļr", + "log_detail_title": "GÃŧnlÃŧk AyrÄąntÄąlarÄą", "log_out": "Oturumu kapat", "log_out_all_devices": "TÃŧm Cihazlarda Oturumu Kapat", "logged_in_as": "{user} olarak oturum aÃ§ÄąldÄą", @@ -1239,17 +1270,18 @@ "login_form_err_trailing_whitespace": "Sondaki boşluk", "login_form_failed_get_oauth_server_config": "OAuth kullanÄąrken bir hata oluştu, sunucu URL'sini kontrol edin", "login_form_failed_get_oauth_server_disable": "OAuth Ãļzelliği bu sunucuda mevcut değil", - "login_form_failed_login": "Giriş yaparken hata oluştu, sunucu URL'sini, e-postayÄą ve parolayÄą kontrol edin", + "login_form_failed_login": "Giriş yaparken hata oluştu, sunucu URL'sini, e-postayÄą ve şifreyi kontrol edin", "login_form_handshake_exception": "Sunucuda bir El SÄąkÄąÅŸma İstisnasÄą vardÄą. Kendi kendine imzalanmÄąÅŸ bir sertifika kullanÄąyorsanÄąz, ayarlar menÃŧsÃŧnden kendi kendine imzalanmÄąÅŸ sertifikalara izin verin.", - "login_form_password_hint": "parola", + "login_form_password_hint": "şifre", "login_form_save_login": "Oturum aÃ§Äąk kalsÄąn", - "login_form_server_empty": "Sunucu URL'si girin", + "login_form_server_empty": "Sunucu URL'si girin.", "login_form_server_error": "Sunucuya bağlanÄąlamadÄą.", "login_has_been_disabled": "Giriş devre dÄąÅŸÄą bÄąrakÄąldÄą.", - "login_password_changed_error": "ParolanÄąz gÃŧncellenirken bir hata oluştu.", - "login_password_changed_success": "Parola gÃŧncellendi", + "login_password_changed_error": "Şifreniz gÃŧncellenirken bir hata oluştu", + "login_password_changed_success": "Şifre başarÄąyla gÃŧncellendi", "logout_all_device_confirmation": "TÃŧm cihazlarda oturum kapatmak istediğinizden emin misiniz?", "logout_this_device_confirmation": "Bu cihazda oturum kapatmak istediğinizden emin misiniz?", + "logs": "KayÄątlar", "longitude": "Boylam", "look": "GÃļrÃŧnÃŧm", "loop_videos": "VideolarÄą dÃļngÃŧye al", @@ -1257,6 +1289,7 @@ "main_branch_warning": "Geliştirme sÃŧrÃŧmÃŧ kullanÄąyorsunuz. YayÄąnlanan bir sÃŧrÃŧm kullanmanÄązÄą Ãļnemle tavsiye ederiz!", "main_menu": "Ana menÃŧ", "make": "Marka", + "manage_geolocation": "Konumu yÃļnet", "manage_shared_links": "PaylaÅŸÄąlan bağlantÄąlarÄą yÃļnet", "manage_sharing_with_partners": "Ortaklarla paylaÅŸÄąmÄą yÃļnet", "manage_the_app_settings": "Uygulama ayarlarÄąnÄą yÃļnet", @@ -1265,7 +1298,7 @@ "manage_your_devices": "CihazlarÄąnÄązÄą yÃļnetin", "manage_your_oauth_connection": "OAuth bağlantÄąnÄązÄą yÃļnetin", "map": "Harita", - "map_assets_in_bounds": "{count} fotoğraf", + "map_assets_in_bounds": "{count, plural, =0 {Bu alanda fotoğraf yok} one {# photo} other {# photos}}", "map_cannot_get_user_location": "KullanÄącÄąnÄąn konumu alÄąnamÄąyor", "map_location_dialog_yes": "Evet", "map_location_picker_page_use_location": "Bu konumu kullan", @@ -1283,14 +1316,15 @@ "map_settings_date_range_option_years": "Son {years} yÄąl", "map_settings_dialog_title": "Harita AyarlarÄą", "map_settings_include_show_archived": "Arşivdekileri dahil et", - "map_settings_include_show_partners": "Partnerleri Dahil Et", - "map_settings_only_show_favorites": "Sadece GÃļzdeleri GÃļster", + "map_settings_include_show_partners": "OrtaklarÄą Dahil Et", + "map_settings_only_show_favorites": "Sadece Favorileri GÃļster", "map_settings_theme_settings": "Harita TemasÄą", "map_zoom_to_see_photos": "FotoğraflarÄą gÃļrmek için uzaklaştÄąrÄąn", "mark_all_as_read": "TÃŧmÃŧnÃŧ okundu olarak işaretle", "mark_as_read": "Okundu olarak işaretle", "marked_all_as_read": "TÃŧmÃŧ okundu olarak işaretlendi", "matches": "Eşleşenler", + "matching_assets": "Eşleşen Öğeler", "media_type": "Medya tÃŧrÃŧ", "memories": "AnÄąlar", "memories_all_caught_up": "TÃŧmÃŧ gÃļrÃŧldÃŧ", @@ -1309,7 +1343,7 @@ "merged_people_count": "{count, plural, one {# kişi} other {# kişi}} birleştirildi", "minimize": "KÃŧçÃŧlt", "minute": "Dakika", - "minutes": "Dakikalar", + "minutes": "Dakika", "missing": "Eksik", "model": "Model", "month": "Ay", @@ -1320,8 +1354,8 @@ "move_to_lock_folder_action_prompt": "{count} kilitli klasÃļre eklendi", "move_to_locked_folder": "Kilitli klasÃļre taÅŸÄą", "move_to_locked_folder_confirmation": "Bu fotoğraflar ve videolar tÃŧm albÃŧmlerden kaldÄąrÄąlacak ve yalnÄązca kilitli klasÃļrden gÃļrÃŧntÃŧlenebilecektir", - "moved_to_archive": "{count, plural, one {# Ãļğe arşive taÅŸÄąndÄą} other {# Ãļğe arşive taÅŸÄąndÄą}}", - "moved_to_library": "{count, plural, one {# Ãļğe kitaplığa taÅŸÄąndÄą} other {# Ãļğe kitaplığa taÅŸÄąndÄą}}", + "moved_to_archive": "{count, plural, one {# Ãļğe} other {# Ãļğeler}} arşive taÅŸÄąndÄą", + "moved_to_library": "{count, plural, one {# Ãļğe} other {# Ãļğeler}} kitaplığa taÅŸÄąndÄą", "moved_to_trash": "ÇÃļp kutusuna taÅŸÄąndÄą", "multiselect_grid_edit_date_time_err_read_only": "Salt okunur Ãļğelerin tarihi dÃŧzenlenemedi, atlanÄąyor", "multiselect_grid_edit_gps_err_read_only": "Salt okunur Ãļğelerin konumu dÃŧzenlenemedi, atlanÄąyor", @@ -1331,6 +1365,7 @@ "name_or_nickname": "İsim veya takma isim", "network_requirement_photos_upload": "FotoğraflarÄą yedeklemek için mobil veriyi kullan", "network_requirement_videos_upload": "VideolarÄą yedeklemek için mobil veriyi kullan", + "network_requirements": "Ağ Gereksinimleri", "network_requirements_updated": "Ağ durumu değişti, yedekleme kuyruğu sÄąfÄąrlandÄą", "networking_settings": "Ağ AyarlarÄą", "networking_subtitle": "Sunucu uç nokta ayarlarÄąnÄą dÃŧzenle", @@ -1341,8 +1376,9 @@ "new_person": "Yeni kişi", "new_pin_code": "Yeni PIN kodu", "new_pin_code_subtitle": "Kilitli klasÃļre ilk kez erişiyorsunuz. Bu sayfaya gÃŧvenli erişim için bir PIN kodu oluşturun", + "new_timeline": "Yeni Zaman Çizelgesi", "new_user_created": "Yeni kullanÄącÄą oluşturuldu", - "new_version_available": "YENİ VERSİYON MEVCUT", + "new_version_available": "YENİ SÜRÜM MEVCUT", "newest_first": "Önce en yeniler", "next": "Sonraki", "next_memory": "Sonraki anÄą", @@ -1354,23 +1390,28 @@ "no_assets_message": "İLK FOTOĞRAFINIZI YÜKLEMEK İÇİN TIKLAYIN", "no_assets_to_show": "GÃļsterilecek Ãļğe yok", "no_cast_devices_found": "YansÄątÄąlacak cihaz bulunamadÄą", - "no_duplicates_found": "Çift bulunamadÄą.", + "no_checksum_local": "Sağlama toplamÄą mevcut değil - yerel varlÄąklarÄą alamÄąyor", + "no_checksum_remote": "Sağlama toplamÄą mevcut değil - uzak varlÄąk alÄąnamÄąyor", + "no_duplicates_found": "Hiçbir kopya bulunamadÄą.", "no_exif_info_available": "EXIF bilgisi mevcut değil", "no_explore_results_message": "Koleksiyonunuzu keşfetmek için daha fazla fotoğraf yÃŧkleyin.", - "no_favorites_message": "En sevdiğiniz fotoğraf ve videolarÄą hÄązlÄąca bulmak için gÃļzdelere ekleyin", + "no_favorites_message": "En sevdiğiniz fotoğraf ve videolarÄą hÄązlÄąca bulmak için favorilere ekleyin", "no_libraries_message": "Fotoğraf ve videolarÄąnÄązÄą gÃļrmek için bir harici kÃŧtÃŧphane oluşturun", + "no_local_assets_found": "Bu sağlama toplamÄą ile yerel varlÄąk bulunamadÄą", "no_locked_photos_message": "Kilitli klasÃļrdeki fotoğraf ve videolar gizlidir; kitaplığınÄązda gezinirken veya arama yaparken gÃļrÃŧnmezler.", - "no_name": "İsim yok", + "no_name": "İsim Yok", "no_notifications": "Bildirim yok", "no_people_found": "Eşleşen kişi bulunamadÄą", "no_places": "Yer yok", + "no_remote_assets_found": "Bu sağlama toplamÄą ile uzaktaki varlÄąk bulunamadÄą", "no_results": "Sonuç bulunamadÄą", "no_results_description": "Eş anlamlÄą ya da daha genel anlamlÄą bir kelime deneyin", "no_shared_albums_message": "FotoğraflarÄą ve videolarÄą ağınÄązdaki kişilerle paylaşmak için bir albÃŧm oluşturun", "no_uploads_in_progress": "YÃŧkleme işlemi yok", + "not_available": "YOK", "not_in_any_album": "Hiçbir albÃŧmde değil", "not_selected": "Seçilmedi", - "note_apply_storage_label_to_previously_uploaded assets": "Not: Daha Ãļnce yÃŧklenen varlÄąklar için bir depolama yolu etiketi uygulamak Ãŧzere şunu başlatÄąn", + "note_apply_storage_label_to_previously_uploaded assets": "Not: Daha Ãļnce yÃŧklenen Ãļğeler için bir depolama yolu etiketi uygulamak Ãŧzere şunu başlatÄąn", "notes": "Notlar", "nothing_here_yet": "Burada henÃŧz bir şey yok", "notification_permission_dialog_content": "Bildirimleri etkinleştirmek için cihaz ayarlarÄąna gidin ve izin verin.", @@ -1383,6 +1424,7 @@ "oauth": "OAuth", "official_immich_resources": "Resmi Immich KaynaklarÄą", "offline": "Çevrim dÄąÅŸÄą", + "offset": "Ofset", "ok": "Tamam", "oldest_first": "Eski olan Ãļnce", "on_this_device": "Bu cihazda", @@ -1394,13 +1436,15 @@ "onboarding_user_welcome_description": "Haydi başlayalÄąm!", "onboarding_welcome_user": "Hoş geldin, {user}", "online": "Çevrimiçi", - "only_favorites": "Sadece gÃļzdeler", + "only_favorites": "Sadece favoriler", "open": "Aç", "open_in_map_view": "Harita gÃļrÃŧnÃŧmÃŧnde aç", "open_in_openstreetmap": "OpenStreetMap'te Aç", "open_the_search_filters": "Arama filtrelerini aç", "options": "Seçenekler", "or": "veya", + "organize_into_albums": "AlbÃŧmler halinde dÃŧzenle", + "organize_into_albums_description": "Mevcut eşzamanlama ayarlarÄąnÄą kullanarak mevcut fotoğraflarÄą albÃŧmlere ekleyin", "organize_your_library": "KÃŧtÃŧphanenizi dÃŧzenleyin", "original": "orijinal", "other": "Diğer", @@ -1415,17 +1459,17 @@ "partner_can_access_location": "Fotoğraf ve videolarÄąnÄązÄąn çekildiği konum", "partner_list_user_photos": "{user} fotoğraflarÄą", "partner_list_view_all": "TÃŧmÃŧnÃŧ gÃļr", - "partner_page_empty_message": "FotoğraflarÄąnÄąz henÃŧz hiçbir partnerle paylaÅŸÄąlmadÄą.", + "partner_page_empty_message": "FotoğraflarÄąnÄąz henÃŧz hiçbir ortakla paylaÅŸÄąlmadÄą.", "partner_page_no_more_users": "Eklenecek başka kullanÄącÄą yok", - "partner_page_partner_add_failed": "Partner eklenemedi", - "partner_page_select_partner": "Partner seç", + "partner_page_partner_add_failed": "Ortak eklenemedi", + "partner_page_select_partner": "Ortak seç", "partner_page_shared_to_title": "PaylaÅŸÄąldÄą", "partner_page_stop_sharing_content": "{partner} artÄąk fotoğraflarÄąnÄąza erişemeyecek.", - "partner_sharing": "Ortak paylaÅŸÄąmÄą", + "partner_sharing": "Ortak PaylaÅŸÄąmÄą", "partners": "Ortaklar", "password": "Şifre", - "password_does_not_match": "Şifreler eşleşmiyor", - "password_required": "Şifre gereklidir", + "password_does_not_match": "Şifre eşleşmiyor", + "password_required": "Şifre Gerekiyor", "password_reset_success": "Şifre başarÄąyla sÄąfÄąrlandÄą", "past_durations": { "days": "{days, plural, one {DÃŧn} other {Son # gÃŧn}}", @@ -1445,10 +1489,10 @@ "permanent_deletion_warning": "KalÄącÄą silme uyarÄąsÄą", "permanent_deletion_warning_setting_description": "Nesneleri kalÄącÄą olarak silerken uyarÄą gÃļster", "permanently_delete": "KalÄącÄą olarak sil", - "permanently_delete_assets_count": "{count, plural, one {Dosya} other {Dosyalar}} kalÄącÄą olarak silindi", - "permanently_delete_assets_prompt": "Bu {count, plural, one {dosyayÄą} other {# dosyalarÄą}} kalÄącÄą olarak silmek istediğinizden emin misiniz? Bu işlem {count, plural, one {bu dosyayÄą} other {bu dosyalarÄą}} albÃŧmlerinizden de kaldÄąrÄąr.", - "permanently_deleted_asset": "KalÄącÄą olarak silinmiş Ãļgeler", - "permanently_deleted_assets_count": "{count, plural, one {# dosya} other {# dosya}} kalÄącÄą olarak silindi", + "permanently_delete_assets_count": "{count, plural, one {Ãļğe} other {Ãļğe}} kalÄącÄą olarak silindi", + "permanently_delete_assets_prompt": "Bu {count, plural, one {Ãļğeyi} other {# Ãļğeleri}} kalÄącÄą olarak silmek istediğinizden emin misiniz? Bu işlem {count, plural, one {bu Ãļğeyi} other {bu Ãļğeleri}} albÃŧmlerinizden de kaldÄąrÄąr.", + "permanently_deleted_asset": "KalÄącÄą olarak silinmiş Ãļğeler", + "permanently_deleted_assets_count": "{count, plural, one {# Ãļğe} other {# Ãļğe}} kalÄącÄą olarak silindi", "permission": "İzin", "permission_empty": "İzniniz boş olmamalÄą", "permission_onboarding_back": "Geri", @@ -1460,7 +1504,9 @@ "permission_onboarding_permission_limited": "SÄąnÄąrlÄą izin. Immich'in tÃŧm fotoğrav ve videolarÄąnÄązÄą yedeklemesine ve yÃļnetmesine izin vermek için Ayarlar'da fotoğraf ve video izinlerini verin.", "permission_onboarding_request": "Immich'in fotoğraflarÄąnÄązÄą ve videolarÄąnÄązÄą gÃļrÃŧntÃŧleyebilmesi için izne ihtiyacÄą var.", "person": "Kişi", - "person_age_years": "{years, plural, other {# sene}} Ãļnce", + "person_age_months": "{months, plural, one {# aylÄąk} other {# aylÄąk}}", + "person_age_year_months": "1 yÄąl, {months, plural, one {# aylÄąk} other {# aylÄąk}}", + "person_age_years": "{years, plural, other {# yaÅŸÄąnda}}", "person_birthdate": "{date} tarihinde doğdu", "person_hidden": "{name}{hidden, select, true { (gizli)} other {}}", "photo_shared_all_users": "FotoğraflarÄąnÄązÄą tÃŧm kullanÄącÄąlarla paylaştÄąnÄąz gibi gÃļrÃŧnÃŧyor veya paylaşacak kullanÄącÄą bulunmuyor.", @@ -1478,12 +1524,13 @@ "places_count": "{count, plural, one {{count, number} yer} other {{count, number} yer}}", "play": "Oynat", "play_memories": "AnÄąlarÄą oynat", - "play_motion_photo": "Hareketli fotoğrafÄą oynat", + "play_motion_photo": "Hareketli FotoğrafÄą Oynat", "play_or_pause_video": "Videoyu oynat ya da durdur", "please_auth_to_access": "Erişim için lÃŧtfen kimliğinizi doğrulayÄąn", "port": "Port", "preferences_settings_subtitle": "Uygulama tercihlerini dÃŧzenle", "preferences_settings_title": "Tercihler", + "preparing": "HazÄąrlanÄąyor", "preset": "Ön ayar", "preview": "Önizleme", "previous": "Önceki", @@ -1500,6 +1547,7 @@ "profile_drawer_client_out_of_date_minor": "Mobil uygulama gÃŧncel değil. LÃŧtfen en son sÃŧrÃŧme gÃŧncelleyin.", "profile_drawer_client_server_up_to_date": "Uygulama ve sunucu gÃŧncel", "profile_drawer_github": "GitHub", + "profile_drawer_readonly_mode": "Salt okunur mod etkinleştirildi. Ã‡Äąkmak için kullanÄącÄą avatar simgesine uzun basÄąn.", "profile_drawer_server_out_of_date_major": "Sunucu gÃŧncel değil. LÃŧtfen en son ana sÃŧrÃŧme gÃŧncelleyin.", "profile_drawer_server_out_of_date_minor": "Sunucu gÃŧncel değil. LÃŧtfen en son sÃŧrÃŧme gÃŧncelleyin.", "profile_image_of_user": "{user} kullanÄącÄąsÄąnÄąn profil resmi", @@ -1538,6 +1586,7 @@ "purchase_server_description_2": "Destekçi statÃŧsÃŧ", "purchase_server_title": "Sunucu", "purchase_settings_server_activated": "Sunucu ÃŧrÃŧn anahtarÄą, yÃļnetici tarafÄąndan yÃļnetilir", + "query_asset_id": "Öğe Kimliği Sorgulama", "queue_status": "SÄąrada {count}/{total}", "rating": "Derecelendirme", "rating_clear": "Derecelendirmeyi temizle", @@ -1545,10 +1594,13 @@ "rating_description": "EXIF derecelendirmesini bilgi panelinde gÃļster", "reaction_options": "Tepki seçenekleri", "read_changelog": "Değişiklik gÃŧnlÃŧğÃŧnÃŧ oku", + "readonly_mode_disabled": "Salt okunur mod devre dÄąÅŸÄą", + "readonly_mode_enabled": "Salt okunur mod etkin", + "ready_for_upload": "YÃŧklemeye hazÄąr", "reassign": "Yeniden ata", - "reassigned_assets_to_existing_person": "{count, plural, one {# dosya} other {# dosya}} {name, select, null {mevcut bir kişiye} other {{name}}} atandÄą", - "reassigned_assets_to_new_person": "{count, plural, one {# dosya} other {# dosya}} yeni bir kişiye atandÄą", - "reassing_hint": "Seçili dosyalarÄą mevcut bir kişiye atayÄąn", + "reassigned_assets_to_existing_person": "{count, plural, one {# Ãļğe} other {# Ãļğeler}} {name, select, null {mevcut bir kişiye} other {{name}}} atandÄą", + "reassigned_assets_to_new_person": "{count, plural, one {# Ãļğe} other {# Ãļğeler}} yeni bir kişiye atandÄą", + "reassing_hint": "Seçili Ãļğeleri mevcut bir kişiye atayÄąn", "recent": "Son", "recent-albums": "Son kaydedilen albÃŧmler", "recent_searches": "Son aramalar", @@ -1568,16 +1620,17 @@ "refreshing_metadata": "Meta veriler yenileniyor", "regenerating_thumbnails": "KÃŧçÃŧk resimler yeniden oluşturuluyor", "remote": "Uzaktan", - "remote_assets": "Uzak VarlÄąklar", + "remote_assets": "Uzak Öğeler", + "remote_media_summary": "Uzaktan Medya Özeti", "remove": "KaldÄąr", - "remove_assets_album_confirmation": "{count, plural, one {# dosyayÄą} other {# dosyayÄą}} albÃŧmden Ã§Äąkarmak istediğinizden emin misiniz?", - "remove_assets_shared_link_confirmation": "{count, plural, one {# dosyayÄą} other {# dosyayÄą}} bu paylaÅŸÄąlan bağlantÄądan Ã§Äąkarmak istediğinizden emin misiniz?", - "remove_assets_title": "DosyalarÄą Ã§Äąkar?", + "remove_assets_album_confirmation": "{count, plural, one {# Ãļğeyi} other {# Ãļğeleri}} albÃŧmden Ã§Äąkarmak istediğinizden emin misiniz?", + "remove_assets_shared_link_confirmation": "{count, plural, one {# Ãļğeyi} other {# Ãļğeleri}} bu paylaÅŸÄąlan bağlantÄądan Ã§Äąkarmak istediğinizden emin misiniz?", + "remove_assets_title": "Öğeleri Ã§Äąkar?", "remove_custom_date_range": "Özel tarih aralığınÄą kaldÄąr", - "remove_deleted_assets": "ÇevrimdÄąÅŸÄą dosyalarÄą kaldÄąr", + "remove_deleted_assets": "Silinen Öğeleri KaldÄąr", "remove_from_album": "AlbÃŧmden Ã§Äąkar", "remove_from_album_action_prompt": "{count} albÃŧmden kaldÄąrÄąldÄą", - "remove_from_favorites": "GÃļzdelerden Ã§Äąkar", + "remove_from_favorites": "Favorilerden Ã§Äąkar", "remove_from_lock_folder_action_prompt": "{count} kilitli klasÃļrden kaldÄąrÄąldÄą", "remove_from_locked_folder": "Kilitli klasÃļrden kaldÄąr", "remove_from_locked_folder_confirmation": "Bu fotoğraf ve videolarÄą kilitli klasÃļrden Ã§Äąkarmak istediğinizden emin misiniz? Ã‡ÄąkarÄąldÄąklarÄąnda kitaplığınÄązda gÃļrÃŧnÃŧr olacaklar.", @@ -1589,28 +1642,28 @@ "remove_user": "KullanÄącÄąyÄą Ã§Äąkar", "removed_api_key": "API anahtarÄą {name} kaldÄąrÄąldÄą", "removed_from_archive": "Arşivden Ã§ÄąkarÄąldÄą", - "removed_from_favorites": "GÃļzdelerden kaldÄąrÄąldÄą", - "removed_from_favorites_count": "{count, plural, other {#}} gÃļzdelerden Ã§ÄąkarÄąldÄą", + "removed_from_favorites": "Favorilerden kaldÄąrÄąldÄą", + "removed_from_favorites_count": "{count, plural, other {#}} favorilerden Ã§ÄąkarÄąldÄą", "removed_memory": "AnÄą kaldÄąrÄąldÄą", "removed_photo_from_memory": "Fotoğraf anÄądan kaldÄąrÄąldÄą", - "removed_tagged_assets": "{count, plural, one {# dosya} other {# dosya}} etiketleri kaldÄąrÄąldÄą", + "removed_tagged_assets": "{count, plural, one {# Ãļğenin} other {# Ãļğelerin}} etiketleri kaldÄąrÄąldÄą", "rename": "Yeniden adlandÄąr", "repair": "Onar", "repair_no_results_message": "Bulunamayan ve eksik dosyalar burada listelenecektir", "replace_with_upload": "YÃŧkleme ile değiştir", "repository": "Depo", - "require_password": "Şifre gerekli", + "require_password": "Şifre gerekiyor", "require_user_to_change_password_on_first_login": "KullanÄącÄą ilk girişte şifreyi değiştirmeli", "rescan": "Yeniden tara", "reset": "SÄąfÄąrla", "reset_password": "Şifreyi sÄąfÄąrla", "reset_people_visibility": "Kişilerin gÃļrÃŧnÃŧrlÃŧğÃŧnÃŧ sÄąfÄąrla", "reset_pin_code": "PIN kodunu sÄąfÄąrlayÄąn", - "reset_pin_code_description": "Pin kodunuzu unuttuysanÄąz, sÄąfÄąrlamak için sunucu yÃļneticisiyle iletişime geçebilirsiniz", - "reset_pin_code_success": "Pin kodu başarÄąyla sÄąfÄąrlandÄą", - "reset_pin_code_with_password": "Pin kodunuzu her zaman şifrenizle sÄąfÄąrlayabilirsiniz", + "reset_pin_code_description": "PIN kodunuzu unuttuysanÄąz, sÄąfÄąrlamak için sunucu yÃļneticisiyle iletişime geçebilirsiniz", + "reset_pin_code_success": "PIN kodu başarÄąyla sÄąfÄąrlandÄą", + "reset_pin_code_with_password": "PIN kodunuzu her zaman şifrenizle sÄąfÄąrlayabilirsiniz", "reset_sqlite": "SQLite VeritabanÄąnÄą SÄąfÄąrla", - "reset_sqlite_confirmation": "SQLite veritabanÄąnÄą sÄąfÄąrlamak istediğinizden emin misiniz? Verileri yeniden senkronize etmek için oturumu kapatÄąp tekrar oturum açmanÄąz gerekecektir", + "reset_sqlite_confirmation": "SQLite veritabanÄąnÄą sÄąfÄąrlamak istediğinizden emin misiniz? Verileri yeniden eşzamanlamak için oturumu kapatÄąp tekrar oturum açmanÄąz gerekecektir", "reset_sqlite_success": "SQLite veritabanÄąnÄą başarÄąyla sÄąfÄąrladÄąnÄąz", "reset_to_default": "VarsayÄąlana sÄąfÄąrla", "resolve_duplicates": "Çiftleri çÃļz", @@ -1619,11 +1672,12 @@ "restore_all": "TÃŧmÃŧnÃŧ geri yÃŧkle", "restore_trash_action_prompt": "{count} çÃļp kutusundan geri yÃŧklendi", "restore_user": "KullanÄącÄąyÄą geri yÃŧkle", - "restored_asset": "Dosya geri yÃŧklendi", + "restored_asset": "Öğe geri yÃŧklendi", "resume": "Devam et", + "resume_paused_jobs": "SÃŧrdÃŧr {count, plural, one {# duraklatÄąlmÄąÅŸ iş} other {# duraklatÄąlmÄąÅŸ işler}}", "retry_upload": "Yeniden yÃŧklemeyi dene", - "review_duplicates": "Çiftleri gÃļzden geçir", - "review_large_files": "BÃŧyÃŧk dosyalarÄą inceleyin", + "review_duplicates": "KopyalarÄą gÃļzden geçir", + "review_large_files": "BÃŧyÃŧk dosyalarÄą incele", "role": "Rol", "role_editor": "DÃŧzenleyici", "role_viewer": "GÃļrÃŧntÃŧleyici", @@ -1687,7 +1741,7 @@ "search_result_page_new_search_hint": "Yeni Arama", "search_settings": "AyarlarÄą ara", "search_state": "Eyalet/İl ara...", - "search_suggestion_list_smart_search_hint_1": "AkÄąllÄą arama varsayÄąlan olarak etkindir, meta verileri aramak için syntax kullanÄąn", + "search_suggestion_list_smart_search_hint_1": "AkÄąllÄą arama varsayÄąlan olarak etkindir, meta verileri aramak için şu sÃļzdizimini kullanÄąn ", "search_suggestion_list_smart_search_hint_2": "m:meta-veri-aramasÄą", "search_tags": "Etiketleri ara...", "search_timezone": "Saat dilimi ara...", @@ -1714,6 +1768,7 @@ "select_user_for_sharing_page_err_album": "AlbÃŧm oluşturulamadÄą", "selected": "Seçildi", "selected_count": "{count, plural, other {# seçildi}}", + "selected_gps_coordinates": "Seçilen GPS KoordinatlarÄą", "send_message": "Mesaj gÃļnder", "send_welcome_email": "Hoş geldin e-postasÄą gÃļnder", "server_endpoint": "Sunucu Uç NoktasÄą", @@ -1723,7 +1778,7 @@ "server_online": "Sunucu çevrimiçi", "server_privacy": "Sunucu Gizliliği", "server_stats": "Sunucu istatistikleri", - "server_version": "Sunucu versiyonu", + "server_version": "Sunucu SÃŧrÃŧmÃŧ", "set": "Ayarla", "set_as_album_cover": "AlbÃŧm resmi olarak ayarla", "set_as_featured_photo": "Öne Ã§Äąkan fotoğraf olarak ayarla", @@ -1731,9 +1786,9 @@ "set_date_of_birth": "Doğum tarihini ayarla", "set_profile_picture": "Profil resmini ayarla", "set_slideshow_to_fullscreen": "Slayt gÃļsterisini tam ekran yap", - "set_stack_primary_asset": "Birincil varlÄąk olarak ayarla", + "set_stack_primary_asset": "Birincil Ãļğe olarak ayarla", "setting_image_viewer_help": "GÃļrÃŧntÃŧleyici Ãļnce kÃŧçÃŧk resmi gÃļsterir, ardÄąndan orta boy Ãļnizlemeyi (etkinleştirilmişse) ve son olarak orijinali (etkinleştirilmişse) gÃļsterir.", - "setting_image_viewer_original_subtitle": "Orijinal tam çÃļzÃŧnÃŧrlÃŧklÃŧ gÃļrÃŧntÃŧyÃŧ gÃļstermek için etkinleştirin. Veri kullanÄąmÄąnÄą azaltmak için devre dÄąÅŸÄą bÄąrakÄąn (hem ağ hem de cihaz Ãļnbelleği).", + "setting_image_viewer_original_subtitle": "Orijinal tam çÃļzÃŧnÃŧrlÃŧklÃŧ gÃļrÃŧntÃŧyÃŧ (bÃŧyÃŧk!) yÃŧklemek için etkinleştirin. Veri kullanÄąmÄąnÄą azaltmak için devre dÄąÅŸÄą bÄąrakÄąn (hem ağ hem de cihaz Ãļnbelleği).", "setting_image_viewer_original_title": "Orijinal gÃļrÃŧntÃŧyÃŧ gÃļster", "setting_image_viewer_preview_subtitle": "Orta çÃļzÃŧnÃŧrlÃŧklÃŧ bir gÃļrÃŧntÃŧ gÃļstermek için etkinleştirin. Orijinali doğrudan gÃļstermek veya yalnÄązca kÃŧçÃŧk resmi kullanmak için devre dÄąÅŸÄą bÄąrakÄąn.", "setting_image_viewer_preview_title": "Önizleme gÃļrÃŧntÃŧsÃŧ gÃļster", @@ -1759,7 +1814,7 @@ "settings_saved": "Ayarlar kaydedildi", "setup_pin_code": "PIN kodunu ayarlayÄąn", "share": "Paylaş", - "share_action_prompt": "PaylaÅŸÄąlan {count} varlÄąk", + "share_action_prompt": "PaylaÅŸÄąlan {count} Ãļğe", "share_add_photos": "Fotoğraf ekle", "share_assets_selected": "{count} seçili", "share_dialog_preparing": "HazÄąrlanÄąyor...", @@ -1779,7 +1834,7 @@ "shared_intent_upload_button_progress_text": "{current} / {total} YÃŧklendi", "shared_link_app_bar_title": "PaylaÅŸÄąlan BağlantÄąlar", "shared_link_clipboard_copied_massage": "Panoya kopyalandÄą", - "shared_link_clipboard_text": "BağlantÄą: {link}\nParola: {password}", + "shared_link_clipboard_text": "BağlantÄą: {link}\nŞifre: {password}", "shared_link_create_error": "PaylaÅŸÄąm bağlantÄąsÄą oluşturulurken hata oluştu", "shared_link_custom_url_description": "Özel bir URL ile bu paylaÅŸÄąlan bağlantÄąya erişin", "shared_link_edit_description_hint": "AÃ§Äąklama yazÄąn", @@ -1791,7 +1846,7 @@ "shared_link_edit_expire_after_option_minutes": "{count} dakika", "shared_link_edit_expire_after_option_months": "{count} ay", "shared_link_edit_expire_after_option_year": "{count} yÄąl", - "shared_link_edit_password_hint": "PaylaÅŸÄąm parolasÄąnÄą girin", + "shared_link_edit_password_hint": "PaylaÅŸÄąm şifresini girin", "shared_link_edit_submit_button": "BağlantÄąyÄą gÃŧncelle", "shared_link_error_server_url_fetch": "Sunucu URL'si alÄąnamadÄą", "shared_link_expires_day": "SÃŧresi {count} gÃŧn içinde doluyor", @@ -1807,21 +1862,21 @@ "shared_link_info_chip_metadata": "EXIF", "shared_link_manage_links": "PaylaÅŸÄąlan BağlantÄąlarÄą YÃļnet", "shared_link_options": "PaylaÅŸÄąlan bağlantÄą seçenekleri", - "shared_link_password_description": "Bu paylaÅŸÄąlan bağlantÄąya erişmek için şifre gerektirir", + "shared_link_password_description": "Bu paylaÅŸÄąlan bağlantÄąya erişmek için şifre gereklidir", "shared_links": "PaylaÅŸÄąlan bağlantÄąlar", "shared_links_description": "Fotoğraf ve videolarÄą bir bağlantÄą ile paylaş", - "shared_photos_and_videos_count": "{assetCount, plural, one {# paylaÅŸÄąlan fotoğraf veya video.} other {# paylaÅŸÄąlan fotoğraf & video.}}", + "shared_photos_and_videos_count": "{assetCount, plural, other {# paylaÅŸÄąlan fotoğraflar & videolar.}}", "shared_with_me": "Benimle paylaÅŸÄąlanlar", "shared_with_partner": "{partner} ile paylaÅŸÄąldÄą", - "sharing": "PaylaÅŸÄąlÄąyor", + "sharing": "PaylaÅŸÄąm", "sharing_enter_password": "Bu sayfayÄą gÃļrebilmek için lÃŧtfen şifreyi giriniz.", "sharing_page_album": "PaylaÅŸÄąlan albÃŧmler", "sharing_page_description": "AğınÄązdaki kişilerle fotoğraf ve video paylaşmak için paylaÅŸÄąmlÄą albÃŧmler oluşturun.", "sharing_page_empty_list": "LİSTEYİ BOŞALT", "sharing_sidebar_description": "Yan panelde paylaÅŸÄąlanlara kÄąsa yol gÃļster", "sharing_silver_appbar_create_shared_album": "Yeni paylaÅŸÄąlan albÃŧm", - "sharing_silver_appbar_share_partner": "Partnerle paylaş", - "shift_to_permanent_delete": "DosyayÄą kalÄącÄą olarak silmek için ⇧ tuşuna basÄąn", + "sharing_silver_appbar_share_partner": "Ortakla paylaş", + "shift_to_permanent_delete": "Öğeyi kalÄącÄą olarak silmek için ⇧ tuşuna basÄąn", "show_album_options": "AlbÃŧm ayarlarÄąnÄą gÃļster", "show_albums": "AlbÃŧmleri gÃļster", "show_all_people": "TÃŧm kişileri gÃļster", @@ -1842,6 +1897,7 @@ "show_slideshow_transition": "Slayt geçişini gÃļster", "show_supporter_badge": "Destekçi rozeti", "show_supporter_badge_description": "Destekçi rozetini gÃļster", + "show_text_search_menu": "Metin arama menÃŧsÃŧnÃŧ gÃļster", "shuffle": "KarÄąÅŸtÄąr", "sidebar": "Yan panel", "sidebar_display_description": "Yan panelde gÃļrÃŧnÃŧme kÄąsa yol gÃļster", @@ -1868,10 +1924,11 @@ "stack_duplicates": "Çiftleri yığınla", "stack_select_one_photo": "Yığın için ana fotoğrafÄą seç", "stack_selected_photos": "Seçili fotoğraflarÄą yığınla", - "stacked_assets_count": "{count, plural, one {# dosya} other {# dosya}} yığınlandÄą", + "stacked_assets_count": "{count, plural, one {# Ãļğe} other {# Ãļğeler}} yığınlandÄą", "stacktrace": "Yığın izi", "start": "Başlat", "start_date": "BaşlangÄąÃ§ tarihi", + "start_date_before_end_date": "BaşlangÄąÃ§ tarihi bitiş tarihinden Ãļnce olmalÄądÄąr", "state": "Eyalet/İl", "status": "Durum", "stop_casting": "YansÄątmayÄą durdur", @@ -1891,27 +1948,29 @@ "support_and_feedback": "Destek & Geri Bildirim", "support_third_party_description": "Immich kurulumu ÃŧçÃŧncÃŧ bir tarafça yapÄąldÄą. YaşadığınÄąz sorunlar bu paketle ilgili olabilir. LÃŧtfen Ãļncelikli olarak aşağıdaki bağlantÄąlarÄą kullanarak bu sağlayÄącÄąyla iletişime geçin.", "swap_merge_direction": "Birleştirme yÃļnÃŧnÃŧ değiştir", - "sync": "Senkronize et", + "sync": "Eşzamanla", "sync_albums": "AlbÃŧmleri eşzamanla", "sync_albums_manual_subtitle": "YÃŧklenmiş fotoğraf ve videolarÄą yedekleme için seçili albÃŧmler ile eşzamanlayÄąn", - "sync_local": "Yerel Senkronizasyon", - "sync_remote": "Uzaktan Senkronizasyon", - "sync_upload_album_setting_subtitle": "Seçili albÃŧmleri Immich'te oluşturun ve içindekileri Immich'e yÃŧkleyin.", + "sync_local": "Yerel Eşzamanlama", + "sync_remote": "Uzaktan Eşzamanlama", + "sync_status": "Eşzamanlama Durumu", + "sync_status_subtitle": "Eşzamanlama sistemini gÃļrÃŧntÃŧleyin ve yÃļnetin", + "sync_upload_album_setting_subtitle": "FotoğraflarÄąnÄązÄą ve videolarÄąnÄązÄą oluşturun ve Immich'te seçtiğiniz albÃŧmlere yÃŧkleyin", "tag": "Etiket", - "tag_assets": "DosyalarÄą etiketle", + "tag_assets": "Öğeleri etiketle", "tag_created": "Etiket oluşturuldu: {tag}", "tag_feature_description": "Etiket temalarÄąna gÃļre gruplandÄąrÄąlmÄąÅŸ fotoğraf ve videolarÄą keşfedin", "tag_not_found_question": "Etiket bulunamadÄą mÄą? Yeni bir etiket oluşturun.", "tag_people": "İnsanlarÄą etiketle", "tag_updated": "Etiket gÃŧncellendi: {tag}", - "tagged_assets": "{count, plural, one {# dosya} other {# dosya}} etiketlendi", + "tagged_assets": "{count, plural, one {# Ãļğe} other {# Ãļğeler}} etiketlendi", "tags": "Etiketler", "tap_to_run_job": "Başlatmak için dokunun", "template": "Şablon", "theme": "Tema", "theme_selection": "Tema seçimi", "theme_selection_description": "TemayÄą otomatik olarak tarayÄącÄąnÄązÄąn sistem tercihine gÃļre aÃ§Äąk veya koyu ayarlayÄąn", - "theme_setting_asset_list_storage_indicator_title": "Öğelerin kÃŧçÃŧk resimlerinde depolama gÃļstergesini gÃļster", + "theme_setting_asset_list_storage_indicator_title": "Öğe kutucuklarÄąnda depolama gÃļstergesini gÃļster", "theme_setting_asset_list_tiles_per_row_title": "SatÄąr baÅŸÄąna Ãļğe sayÄąsÄą ({count})", "theme_setting_colorful_interface_subtitle": "Birincil rengi arka plan yÃŧzeylerine uygulayÄąn.", "theme_setting_colorful_interface_title": "Renkli arayÃŧz", @@ -1922,7 +1981,7 @@ "theme_setting_system_primary_color_title": "Sistem rengini kullan", "theme_setting_system_theme_switch": "Otomatik (sistem ayarÄąna gÃļre)", "theme_setting_theme_subtitle": "Uygulama temasÄą seç", - "theme_setting_three_stage_loading_subtitle": "Üç aşamalÄą yÃŧkleme, yÃŧkleme performansÄąnÄą artÄąrabilir ancak Ãļnemli ÃļlçÃŧde daha yÃŧksek ağ yÃŧkÃŧne sebep olur.", + "theme_setting_three_stage_loading_subtitle": "Üç aşamalÄą yÃŧkleme, yÃŧkleme performansÄąnÄą artÄąrabilir ancak ağ yÃŧkÃŧnÃŧ Ãļnemli ÃļlçÃŧde artÄąrÄąr", "theme_setting_three_stage_loading_title": "Üç aşamalÄą yÃŧklemeyi etkinleştir", "they_will_be_merged_together": "Birlikte birleştirilecekler", "third_party_resources": "ÜçÃŧncÃŧ taraf kaynaklar", @@ -1931,7 +1990,7 @@ "timezone": "Zaman dilimi", "to_archive": "Arşivle", "to_change_password": "Şifreyi değiştir", - "to_favorite": "GÃļzdelere ekle", + "to_favorite": "Favorilere ekle", "to_login": "Oturum aç", "to_multi_select": "çoklu seçim için", "to_parent": "Üst Ãļğeye git", @@ -1944,17 +2003,18 @@ "trash_action_prompt": "{count} çÃļp kutusuna taÅŸÄąndÄą", "trash_all": "Hepsini sil", "trash_count": "ÇÃļp kutusu {count, number}", - "trash_delete_asset": "Ögeyi Sil/ÇÃļpe gÃļnder", + "trash_delete_asset": "Öğeyi Sil/ÇÃļpe GÃļnder", "trash_emptied": "ÇÃļp kutusu temizlendi", "trash_no_results_message": "Silinen fotoğraf ve videolar burada listelenecektir.", "trash_page_delete_all": "TÃŧmÃŧnÃŧ Sil", "trash_page_empty_trash_dialog_content": "ÇÃļp kutusuna atÄąlmÄąÅŸ Ãļğeleri silmek istediğinize emin misiniz? Bu Ãļğeler Immich'ten kalÄącÄą olarak silinecek", "trash_page_info": "ÇÃļp kutusuna atÄąlan Ãļğeler {days} gÃŧn sonra kalÄącÄą olarak silinecektir", - "trash_page_no_assets": "ÇÃļp kutusu boş", - "trash_page_restore_all": "TÃŧmÃŧnÃŧ geri yÃŧkle", - "trash_page_select_assets_btn": "İçerik seç", + "trash_page_no_assets": "ÇÃļp kutusuna atÄąlmÄąÅŸ Ãļğe yok", + "trash_page_restore_all": "TÃŧmÃŧnÃŧ Geri YÃŧkle", + "trash_page_select_assets_btn": "Öğeleri seç", "trash_page_title": "ÇÃļp Kutusu ({count})", "trashed_items_will_be_permanently_deleted_after": "Silinen Ãļğeler {days, plural, one {# gÃŧn} other {# gÃŧn}} sonra kalÄącÄą olarak silinecek.", + "troubleshoot": "Sorun giderme", "type": "TÃŧr", "unable_to_change_pin_code": "PIN kodu değiştirilemedi", "unable_to_setup_pin_code": "PIN kodu ayarlanamadÄą", @@ -1962,45 +2022,46 @@ "unarchive_action_prompt": "{count} Arşivden kaldÄąrÄąldÄą", "unarchived_count": "{count, plural, other {# arşivden Ã§ÄąkarÄąldÄą}}", "undo": "Geri al", - "unfavorite": "GÃļzdelerden kaldÄąr", - "unfavorite_action_prompt": "{count} SÄąk KullanÄąlanlar'dan kaldÄąrÄąldÄą", + "unfavorite": "Favorilerden kaldÄąr", + "unfavorite_action_prompt": "{count} Favorilerden kaldÄąrÄąldÄą", "unhide_person": "Kişiyi gÃļster", "unknown": "Bilinmeyen", - "unknown_country": "Bilinmeyen Ãŧlke", - "unknown_year": "Bilinmeyen YIl", + "unknown_country": "Bilinmeyen Ülke", + "unknown_year": "Bilinmeyen YÄąl", "unlimited": "SÄąnÄąrsÄąz", "unlink_motion_video": "Hareketli video bağlantÄąsÄąnÄą kaldÄąr", "unlink_oauth": "OAuth bağlantÄąsÄąnÄą kaldÄąr", "unlinked_oauth_account": "BağlantÄąsÄą kaldÄąrÄąlmÄąÅŸ OAuth hesabÄą", - "unmute_memories": "AnÄąlarÄąn sesini aç", + "unmute_memories": "AnÄąlarÄąn Sesini Aç", "unnamed_album": "İsimsiz AlbÃŧm", "unnamed_album_delete_confirmation": "Bu albÃŧmÃŧ silmek istediğinizden emin misiniz?", - "unnamed_share": "İsimsiz paylaÅŸÄąm", + "unnamed_share": "İsimsiz PaylaÅŸÄąm", "unsaved_change": "Kaydedilmemiş değişiklik", "unselect_all": "TÃŧmÃŧnÃŧ seçimini kaldÄąr", "unselect_all_duplicates": "TÃŧm çiftlerin seçimini kaldÄąr", "unselect_all_in": "{group} içindeki tÃŧm seçimleri kaldÄąr", "unstack": "YığınÄą kaldÄąr", "unstack_action_prompt": "{count} istiflenmemiş", - "unstacked_assets_count": "{count, plural, one {# dosya} other {# dosya}} yığınÄą kaldÄąrÄąldÄą", + "unstacked_assets_count": "{count, plural, one {# Ãļğenin} other {# Ãļğelerin}} yığınÄą kaldÄąrÄąldÄą", "untagged": "Etiketlenmemiş", "up_next": "SÄąradaki", + "update_location_action_prompt": "Seçilen {count} Ãļğenin konumunu şu şekilde gÃŧncelleyin:", "updated_at": "GÃŧncellenme", - "updated_password": "Şifreyi gÃŧncelle", + "updated_password": "GÃŧncellenen şifre", "upload": "YÃŧkle", "upload_action_prompt": "{count} yÃŧkleme için sÄąraya alÄąndÄą", "upload_concurrency": "YÃŧkleme eşzamanlÄąlığı", "upload_details": "YÃŧkleme AyrÄąntÄąlarÄą", "upload_dialog_info": "Seçili Ãļğeleri sunucuya yedeklemek istiyor musunuz?", "upload_dialog_title": "Öğe YÃŧkle", - "upload_errors": "{count, plural, one {# hata} other {# hatayla}} yÃŧkleme tamamlandÄą, yeni yÃŧklenen dosyalarÄą gÃļrmek için sayfayÄą gÃŧncelleyin.", + "upload_errors": "{count, plural, one {# hata} other {# hatayla}} yÃŧkleme tamamlandÄą, yeni yÃŧklenen Ãļğeleri gÃļrmek için sayfayÄą gÃŧncelleyin.", "upload_finished": "YÃŧkleme tamamlandÄą", "upload_progress": "{remaining, number} kalan - {processed, number}/{total, number} işlendi", - "upload_skipped_duplicates": "{count, plural, one {# çift dosya} other {# çift dosya}} atlandÄą", + "upload_skipped_duplicates": "{count, plural, one {# yinelenen Ãļğe} other {# yinelenen Ãļğeler}} atlandÄą", "upload_status_duplicates": "Çiftler", "upload_status_errors": "Hatalar", "upload_status_uploaded": "YÃŧklendi", - "upload_success": "YÃŧkleme başarÄąlÄą, yÃŧklenen yeni Ãļgeleri gÃļrebilmek için sayfayÄą yenileyin.", + "upload_success": "YÃŧkleme başarÄąlÄą, yÃŧklenen yeni Ãļğeleri gÃļrebilmek için sayfayÄą yenileyin.", "upload_to_immich": "Immich'e YÃŧkle ({count})", "uploading": "YÃŧkleniyor", "uploading_media": "Medya yÃŧkleme", @@ -2012,7 +2073,7 @@ "user": "KullanÄącÄą", "user_has_been_deleted": "Bu kullanÄącÄą silindi.", "user_id": "KullanÄącÄą ID", - "user_liked": "{type, select, photo {Bu fotoğraf} video {Bu video} asset {Bu dosya} other {Bu}} {user} tarafÄąndan beğenildi", + "user_liked": "{type, select, photo {Bu fotoğraf} video {Bu video} asset {Bu Ãļğe} other {Bu}} {user} tarafÄąndan beğenildi", "user_pin_code_settings": "PIN Kodu", "user_pin_code_settings_description": "PIN kodunuzu yÃļnetin", "user_privacy": "KullanÄącÄą Gizliliği", @@ -2021,21 +2082,21 @@ "user_role_set": "{user}, {role} olarak ayarlandÄą", "user_usage_detail": "KullanÄącÄą kullanÄąm detayÄą", "user_usage_stats": "Hesap kullanÄąm istatistikleri", - "user_usage_stats_description": "hesap kullanÄąm istatistiklerini gÃļster", + "user_usage_stats_description": "Hesap kullanÄąm istatistiklerini gÃļster", "username": "KullanÄącÄą adÄą", "users": "KullanÄącÄąlar", "users_added_to_album_count": "AlbÃŧme {count, plural, one {# user} other {# users}} eklendi", - "utilities": "YardÄąmcÄąlar", + "utilities": "YardÄąmcÄą Programlar", "validate": "Doğrula", "validate_endpoint_error": "LÃŧtfen geçerli bir URL girin", "variables": "Değişkenler", - "version": "Versiyon", + "version": "SÃŧrÃŧm", "version_announcement_closing": "ArkadaÅŸÄąnÄąz, Alex", "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_history": "Versiyon geçmişi", + "version_history": "SÃŧrÃŧm Geçmişi", "version_history_item": "{version}, {date} tarihinde kuruldu", "video": "Video", - "video_hover_setting": "Üzerinde durulduğunda video Ãļnizlemesi oynat", + "video_hover_setting": "Üzerinde durulduğunda video Ãļn izlemesi oynat", "video_hover_setting_description": "Öğe Ãŧzerinde fareyle durulduğunda video kÃŧçÃŧk resmini oynatÄąr. Bu Ãļzellik devre dÄąÅŸÄąyken, oynatma simgesine fareyle gidilerek oynatma başlatÄąlabilir.", "videos": "Videolar", "videos_count": "{count, plural, one {# video} other {# video}}", @@ -2048,9 +2109,10 @@ "view_link": "BağlantÄąyÄą gÃļster", "view_links": "BağlantÄąlarÄą gÃļster", "view_name": "GÃļster", - "view_next_asset": "Sonraki dosyayÄą gÃļrÃŧntÃŧle", - "view_previous_asset": "Önceki dosyayÄą gÃļrÃŧntÃŧle", + "view_next_asset": "Sonraki Ãļğeyi gÃļrÃŧntÃŧle", + "view_previous_asset": "Önceki Ãļğeyi gÃļrÃŧntÃŧle", "view_qr_code": "QR kodu gÃļrÃŧntÃŧle", + "view_similar_photos": "Benzer fotoğraflarÄą gÃļrÃŧntÃŧle", "view_stack": "YığınÄą gÃļrÃŧntÃŧle", "view_user": "KullanÄącÄąyÄą GÃļrÃŧntÃŧle", "viewer_remove_from_stack": "Yığından KaldÄąr", @@ -2069,5 +2131,6 @@ "yes": "Evet", "you_dont_have_any_shared_links": "Herhangi bir paylaÅŸÄąlan bağlantÄąnÄąz yok", "your_wifi_name": "Wi-Fi AdÄąnÄąz", - "zoom_image": "GÃļrÃŧntÃŧyÃŧ yakÄąnlaştÄąr" + "zoom_image": "GÃļrÃŧntÃŧyÃŧ yakÄąnlaştÄąr", + "zoom_to_bounds": "SÄąnÄąrlara yakÄąnlaştÄąr" } diff --git a/i18n/uk.json b/i18n/uk.json index 9721728d68..0640982fe6 100644 --- a/i18n/uk.json +++ b/i18n/uk.json @@ -28,10 +28,12 @@ "add_to_album": "Đ”ĐžĐ´Đ°Ņ‚Đ¸ ҃ аĐģŅŒĐąĐžĐŧ", "add_to_album_bottom_sheet_added": "ДодаĐŊĐž Đ´Đž {album}", "add_to_album_bottom_sheet_already_exists": "ВĐļĐĩ Ņ” в {album}", + "add_to_album_bottom_sheet_some_local_assets": "ДĐĩŅĐēŅ– ĐģĐžĐēаĐģҌĐŊŅ– Ņ€ĐĩŅŅƒŅ€ŅĐ¸ ĐŊĐĩ вдаĐģĐžŅŅ Đ´ĐžĐ´Đ°Ņ‚Đ¸ Đ´Đž аĐģŅŒĐąĐžĐŧ҃", "add_to_album_toggle": "ПĐĩŅ€ĐĩĐŧиĐēаĐŊĐŊŅ Đ˛Đ¸ĐąĐžŅ€Ņƒ Đ´ĐģŅ {album}", "add_to_albums": "Đ”ĐžĐ´Đ°Ņ‚Đ¸ Đ´Đž аĐģŅŒĐąĐžĐŧŅ–Đ˛", "add_to_albums_count": "Đ”ĐžĐ´Đ°Ņ‚Đ¸ Đ´Đž аĐģŅŒĐąĐžĐŧŅ–Đ˛ ({count})", "add_to_shared_album": "Đ”ĐžĐ´Đ°Ņ‚Đ¸ ҃ ҁĐŋŅ–ĐģҌĐŊиК аĐģŅŒĐąĐžĐŧ", + "add_upload_to_stack": "Đ”ĐžĐ´Đ°Ņ‚Đ¸ СаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ Đ´Đž ҁ҂ĐĩĐē҃", "add_url": "Đ”ĐžĐ´Đ°Ņ‚Đ¸ URL", "added_to_archive": "ДодаĐŊĐž Đ´Đž Đ°Ņ€Ņ…Ņ–Đ˛Ņƒ", "added_to_favorites": "ДодаĐŊĐž Đ´Đž ĐžĐąŅ€Đ°ĐŊĐžĐŗĐž", @@ -39,7 +41,7 @@ "admin": { "add_exclusion_pattern_description": "Đ”ĐžĐ´Đ°ĐšŅ‚Đĩ ŅˆĐ°ĐąĐģĐžĐŊи виĐēĐģŅŽŅ‡ĐĩĐŊҌ. ĐŸŅ–Đ´ŅŅ‚Đ°ĐŊОвĐēа С виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅĐŧ *, ** Ņ‚Đ° ? ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚ŅŒŅŅ. ДĐģŅ Ņ–ĐŗĐŊĐžŅ€ŅƒĐ˛Đ°ĐŊĐŊŅ Đ˛ŅŅ–Ņ… Ņ„Đ°ĐšĐģŅ–Đ˛ ҃ ĐąŅƒĐ´ŅŒ-ŅĐēĐžĐŧ҃ ĐēĐ°Ņ‚Đ°ĐģĐžĐˇŅ– С Ņ–Đŧ'ŅĐŧ ÂĢRawÂģ, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ \"**/Raw/**\". ДĐģŅ Ņ–ĐŗĐŊĐžŅ€ŅƒĐ˛Đ°ĐŊĐŊŅ Đ˛ŅŅ–Ņ… Ņ„Đ°ĐšĐģŅ–Đ˛, Ņ‰Đž СаĐēŅ–ĐŊŅ‡ŅƒŅŽŅ‚ŅŒŅŅ ĐŊа \".tif\", виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ \"**/*.tif\". ДĐģŅ Ņ–ĐŗĐŊĐžŅ€ŅƒĐ˛Đ°ĐŊĐŊŅ Đ°ĐąŅĐžĐģŅŽŅ‚ĐŊĐžĐŗĐž ҈ĐģŅŅ…Ņƒ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ \"/path/to/ignore/**\".", "admin_user": "АдĐŧŅ–ĐŊŅ–ŅŅ‚Ņ€Đ°Ņ‚ĐžŅ€", - "asset_offline_description": "ĐĻĐĩĐš Ņ„Đ°ĐšĐģ СОвĐŊŅ–ŅˆĐŊŅŒĐžŅ— ĐąŅ–ĐąĐģŅ–ĐžŅ‚ĐĩĐēи ĐŊĐĩ СĐŊаКдĐĩĐŊĐž ĐŊа Đ´Đ¸ŅĐē҃ Ņ– ĐąŅƒĐ˛ ĐŋĐĩŅ€ĐĩĐŧҖ҉ĐĩĐŊиК Đ´Đž ҁĐŧŅ–Ņ‚ĐŊиĐēа. Đ¯ĐēŅ‰Đž Ņ„Đ°ĐšĐģ ĐąŅƒĐ˛ ĐŋĐĩŅ€ĐĩĐŧҖ҉ĐĩĐŊиК ҃ ĐŧĐĩĐļĐ°Ņ… ĐąŅ–ĐąĐģŅ–ĐžŅ‚ĐĩĐēи, ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Ņ‚Đĩ ŅĐ˛ĐžŅŽ ҁ҂ҀҖ҇Đē҃ ĐŊа ĐŊĐ°ŅĐ˛ĐŊŅ–ŅŅ‚ŅŒ ĐŊĐžĐ˛ĐžĐŗĐž Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐŊĐžĐŗĐž Ņ„Đ°ĐšĐģ҃. ЊОй Đ˛Ņ–Đ´ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ ҆ĐĩĐš Ņ„Đ°ĐšĐģ, ĐŋĐĩŅ€ĐĩĐēĐžĐŊĐ°ĐšŅ‚ĐĩŅŅ, Ņ‰Đž ҈ĐģŅŅ… Đ´Đž Ņ„Đ°ĐšĐģ҃ Đ´ĐžŅŅ‚ŅƒĐŋĐŊиК Đ´ĐģŅ Immich, Ņ– ĐŋŅ€ĐžŅĐēаĐŊŅƒĐšŅ‚Đĩ ĐąŅ–ĐąĐģŅ–ĐžŅ‚ĐĩĐē҃.", + "asset_offline_description": "ĐĻĐĩĐš Ņ„Đ°ĐšĐģ СОвĐŊŅ–ŅˆĐŊŅŒĐžŅ— ĐąŅ–ĐąĐģŅ–ĐžŅ‚ĐĩĐēи ĐŊĐĩ СĐŊаКдĐĩĐŊĐž ĐŊа Đ´Đ¸ŅĐē҃ Ņ– ĐąŅƒĐ˛ ĐŋĐĩŅ€ĐĩĐŧҖ҉ĐĩĐŊиК Đ´Đž ĐēĐžŅˆĐ¸Đēа. Đ¯ĐēŅ‰Đž Ņ„Đ°ĐšĐģ ĐąŅƒĐ˛ ĐŋĐĩŅ€ĐĩĐŧҖ҉ĐĩĐŊиК ҃ ĐŧĐĩĐļĐ°Ņ… ĐąŅ–ĐąĐģŅ–ĐžŅ‚ĐĩĐēи, ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Ņ‚Đĩ ŅĐ˛ĐžŅŽ ҁ҂ҀҖ҇Đē҃ ĐŊа ĐŊĐ°ŅĐ˛ĐŊŅ–ŅŅ‚ŅŒ ĐŊĐžĐ˛ĐžĐŗĐž Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐŊĐžĐŗĐž Ņ„Đ°ĐšĐģ҃. ЊОй Đ˛Ņ–Đ´ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ ҆ĐĩĐš Ņ„Đ°ĐšĐģ, ĐŋĐĩŅ€ĐĩĐēĐžĐŊĐ°ĐšŅ‚ĐĩŅŅ, Ņ‰Đž ҈ĐģŅŅ… Đ´Đž Ņ„Đ°ĐšĐģ҃ Đ´ĐžŅŅ‚ŅƒĐŋĐŊиК Đ´ĐģŅ Immich, Ņ– ĐŋŅ€ĐžŅĐēаĐŊŅƒĐšŅ‚Đĩ ĐąŅ–ĐąĐģŅ–ĐžŅ‚ĐĩĐē҃.", "authentication_settings": "НаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ Đ°ŅƒŅ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ—", "authentication_settings_description": "ĐŖĐŋŅ€Đ°Đ˛ĐģŅ–ĐŊĐŊŅ ĐŋĐ°Ņ€ĐžĐģŅĐŧи, OAuth Ņ‚Đ° Ņ–ĐŊŅˆĐ¸Đŧи ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅĐŧи Đ°ŅƒŅ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ—", "authentication_settings_disable_all": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ виĐŧĐēĐŊŅƒŅ‚Đ¸ Đ˛ŅŅ– ĐŧĐĩŅ‚ĐžĐ´Đ¸ Đ˛Ņ…ĐžĐ´Ņƒ? Đ’Ņ…Ņ–Đ´ ĐąŅƒĐ´Đĩ ĐŋОвĐŊŅ–ŅŅ‚ŅŽ виĐŧĐēĐŊĐĩĐŊиК.", @@ -70,14 +72,14 @@ "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_management": "КĐĩŅ€ŅƒĐ˛Đ°ĐŊĐŊŅ СОвĐŊŅ–ŅˆĐŊŅ–Đŧи ĐąŅ–ĐąĐģŅ–ĐžŅ‚ĐĩĐēаĐŧи", "face_detection": "Đ’Đ¸ŅĐ˛ĐģĐĩĐŊĐŊŅ ОйĐģĐ¸Ņ‡Ņ‡Ņ", "face_detection_description": "Đ’Đ¸ŅĐ˛ĐģĐĩĐŊĐŊŅ ОйĐģĐ¸Ņ‡ ĐŊа ĐŧĐĩĐ´Ņ–Đ°Ņ„Đ°ĐšĐģĐ°Ņ… Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ ĐŧĐ°ŅˆĐ¸ĐŊĐŊĐžĐŗĐž ĐŊĐ°Đ˛Ņ‡Đ°ĐŊĐŊŅ. ДĐģŅ Đ˛Ņ–Đ´ĐĩĐž ĐžĐąŅ€ĐžĐąĐģŅŅ”Ņ‚ŅŒŅŅ ĐģĐ¸ŅˆĐĩ ĐĩҁĐēŅ–Đˇ. \"ОĐŊĐžĐ˛Đ¸Ņ‚Đ¸\" ĐŋĐžĐ˛Ņ‚ĐžŅ€ĐŊĐž ĐžĐąŅ€ĐžĐąĐģŅŅ” Đ˛ŅŅ– Ņ„Đ°ĐšĐģи. \"ĐĄĐēиĐŊŅƒŅ‚Đ¸\" Đ´ĐžĐ´Đ°Ņ‚ĐēОвО ĐžŅ‡Đ¸Ņ‰Đ°Ņ” Đ˛ŅŅ– ĐŋĐžŅ‚ĐžŅ‡ĐŊŅ– даĐŊŅ– ĐŋŅ€Đž ОйĐģĐ¸Ņ‡Ņ‡Ņ. \"Đ’Ņ–Đ´ŅŅƒŅ‚ĐŊŅ–\" ŅŅ‚Đ°Đ˛Đ¸Ņ‚ŅŒ ҃ ҇ĐĩŅ€ĐŗŅƒ Ņ„Đ°ĐšĐģи, ŅĐēŅ– ҉Đĩ ĐŊĐĩ ĐąŅƒĐģи ĐžĐąŅ€ĐžĐąĐģĐĩĐŊŅ–. Đ’Đ¸ŅĐ˛ĐģĐĩĐŊŅ– ОйĐģĐ¸Ņ‡Ņ‡Ņ ĐąŅƒĐ´ŅƒŅ‚ŅŒ ĐŋĐžŅŅ‚Đ°Đ˛ĐģĐĩĐŊŅ– в ҇ĐĩŅ€ĐŗŅƒ Đ´ĐģŅ Ņ€ĐžĐˇĐŋŅ–ĐˇĐŊаваĐŊĐŊŅ ĐŋҖҁĐģŅ СавĐĩŅ€ŅˆĐĩĐŊĐŊŅ Đ˛Đ¸ŅĐ˛ĐģĐĩĐŊĐŊŅ, ĐŗŅ€ŅƒĐŋŅƒŅŽŅ‡Đ¸ Ņ—Ņ… ҃ вĐļĐĩ ҖҁĐŊŅƒŅŽŅ‡Đ¸Ņ… айО ĐŊĐžĐ˛Đ¸Ņ… ĐģŅŽĐ´ĐĩĐš.", "facial_recognition_job_description": "Đ“Ņ€ŅƒĐŋŅƒĐ˛Đ°ĐŊĐŊŅ Đ˛Đ¸ŅĐ˛ĐģĐĩĐŊĐ¸Ņ… ОйĐģĐ¸Ņ‡ ҃ ĐģŅŽĐ´ĐĩĐš. ĐĻĐĩĐš ĐēŅ€ĐžĐē виĐēĐžĐŊŅƒŅ”Ņ‚ŅŒŅŅ ĐŋҖҁĐģŅ СавĐĩŅ€ŅˆĐĩĐŊĐŊŅ Đ˛Đ¸ŅĐ˛ĐģĐĩĐŊĐŊŅ ОйĐģĐ¸Ņ‡. \"ĐĄĐēиĐŊŅƒŅ‚Đ¸\" ĐŋĐžĐ˛Ņ‚ĐžŅ€ĐŊĐž ĐēĐģĐ°ŅŅ‚ĐĩŅ€Đ¸ĐˇŅƒŅ” Đ˛ŅŅ– ОйĐģĐ¸Ņ‡Ņ‡Ņ. \"Đ’Ņ–Đ´ŅŅƒŅ‚ĐŊŅ–\" ŅŅ‚Đ°Đ˛Đ¸Ņ‚ŅŒ ҃ ҇ĐĩŅ€ĐŗŅƒ ОйĐģĐ¸Ņ‡Ņ‡Ņ, ŅĐēиĐŧ ҉Đĩ ĐŊĐĩ ĐŋŅ€Đ¸ĐˇĐŊĐ°Ņ‡ĐĩĐŊĐž ĐģŅŽĐ´Đ¸ĐŊ҃.", "failed_job_command": "КоĐŧаĐŊда {command} ĐŊĐĩ виĐēĐžĐŊаĐģĐ°ŅŅ Đ´ĐģŅ СавдаĐŊĐŊŅ: {job}", - "force_delete_user_warning": "ĐŸĐžĐŸĐ•Đ Đ•Đ”Đ–Đ•ĐĐĐ¯: ĐĻĐĩ ĐŊĐĩĐŗĐ°ĐšĐŊĐž ĐŋŅ€Đ¸ĐˇĐ˛ĐĩĐ´Đĩ Đ´Đž видаĐģĐĩĐŊĐŊŅ ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ° Ņ– Đ˛ŅŅ–Ņ… аĐēŅ‚Đ¸Đ˛Ņ–Đ˛. ĐĻŅŽ Đ´Ņ–ŅŽ ĐŊĐĩ ĐŧĐžĐļĐŊа ҁĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸, Ņ– Ņ„Đ°ĐšĐģи ĐŊĐĩ ĐŧĐžĐļĐŊа ĐąŅƒĐ´Đĩ Đ˛Ņ–Đ´ĐŊĐžĐ˛Đ¸Ņ‚Đ¸.", + "force_delete_user_warning": "ĐŸĐžĐŸĐ•Đ Đ•Đ”Đ–Đ•ĐĐĐ¯: ĐĻĐĩ ĐŊĐĩĐŗĐ°ĐšĐŊĐž ĐŋŅ€Đ¸ĐˇĐ˛ĐĩĐ´Đĩ Đ´Đž видаĐģĐĩĐŊĐŊŅ ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ° Ņ– Đ˛ŅŅ–Ņ… Ņ€ĐĩŅŅƒŅ€ŅŅ–Đ˛. ĐĻŅŽ Đ´Ņ–ŅŽ ĐŊĐĩ ĐŧĐžĐļĐŊа ҁĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸, Ņ– Ņ„Đ°ĐšĐģи ĐŊĐĩ ĐŧĐžĐļĐŊа ĐąŅƒĐ´Đĩ Đ˛Ņ–Đ´ĐŊĐžĐ˛Đ¸Ņ‚Đ¸.", "image_format": "Đ¤ĐžŅ€ĐŧĐ°Ņ‚", "image_format_description": "Đ¤ĐžŅ€ĐŧĐ°Ņ‚ WebP Đ˛Đ¸Ņ€ĐžĐąĐģŅŅ” ĐŧĐĩĐŊŅŒŅˆŅ– Ņ„Đ°ĐšĐģŅ–Đ˛, ĐŊŅ–Đļ JPEG, аĐģĐĩ ĐšĐžĐŗĐž ĐēĐžĐ´ŅƒĐ˛Đ°ĐŊĐŊŅ виĐŧĐ°ĐŗĐ°Ņ” ĐąŅ–ĐģҌ҈Đĩ Ņ‡Đ°ŅŅƒ.", "image_fullsize_description": "ПовĐŊĐžŅ€ĐžĐˇĐŧŅ–Ņ€ĐŊĐĩ ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ С видаĐģĐĩĐŊиĐŧи ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊиĐŧи, ŅĐēŅ– виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‚ŅŒŅŅ ĐŋŅ–Đ´ Ņ‡Đ°Ņ ĐˇĐąŅ–ĐģҌ҈ĐĩĐŊĐŊŅ", @@ -123,6 +125,13 @@ "logging_enable_description": "ĐŖĐ˛Ņ–ĐŧĐēĐŊŅƒŅ‚Đ¸ вĐĩĐ´ĐĩĐŊĐŊŅ ĐļŅƒŅ€ĐŊаĐģ҃", "logging_level_description": "КоĐģи ŅƒĐ˛Ņ–ĐŧĐēĐŊĐĩĐŊĐž, ŅĐēиК Ņ€Ņ–Đ˛ĐĩĐŊҌ ĐļŅƒŅ€ĐŊаĐģŅŽĐ˛Đ°ĐŊĐŊŅ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸.", "logging_settings": "Đ–ŅƒŅ€ĐŊаĐģŅŽĐ˛Đ°ĐŊĐŊŅ", + "machine_learning_availability_checks": "ПĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đēи Đ´ĐžŅŅ‚ŅƒĐŋĐŊĐžŅŅ‚Ņ–", + "machine_learning_availability_checks_description": "ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž Đ˛Đ¸ŅĐ˛ĐģŅŅ‚Đ¸ Ņ‚Đ° ĐŊĐ°Đ´Đ°Đ˛Đ°Ņ‚Đ¸ ĐŋĐĩŅ€ĐĩĐ˛Đ°ĐŗŅƒ Đ´ĐžŅŅ‚ŅƒĐŋĐŊиĐŧ ҁĐĩŅ€Đ˛ĐĩŅ€Đ°Đŧ ĐŧĐ°ŅˆĐ¸ĐŊĐŊĐžĐŗĐž ĐŊĐ°Đ˛Ņ‡Đ°ĐŊĐŊŅ", + "machine_learning_availability_checks_enabled": "ĐŖĐ˛Ņ–ĐŧĐēĐŊŅƒŅ‚Đ¸ ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đēи Đ´ĐžŅŅ‚ŅƒĐŋĐŊĐžŅŅ‚Ņ–", + "machine_learning_availability_checks_interval": "ІĐŊŅ‚ĐĩŅ€Đ˛Đ°Đģ ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đēи", + "machine_learning_availability_checks_interval_description": "ІĐŊŅ‚ĐĩŅ€Đ˛Đ°Đģ ҃ ĐŧŅ–ĐģҖҁĐĩĐē҃ĐŊĐ´Đ°Ņ… ĐŧŅ–Đļ ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€ĐēаĐŧи Đ´ĐžŅŅ‚ŅƒĐŋĐŊĐžŅŅ‚Ņ–", + "machine_learning_availability_checks_timeout": "ĐĸаКĐŧ-Đ°ŅƒŅ‚ СаĐŋĐ¸Ņ‚Ņƒ", + "machine_learning_availability_checks_timeout_description": "ĐĸаКĐŧ-Đ°ŅƒŅ‚ ҃ ĐŧŅ–ĐģҖҁĐĩĐē҃ĐŊĐ´Đ°Ņ… Đ´ĐģŅ ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đēи Đ´ĐžŅŅ‚ŅƒĐŋĐŊĐžŅŅ‚Ņ–", "machine_learning_clip_model": "МодĐĩĐģҌ CLIP", "machine_learning_clip_model_description": "ІĐŧ'Ņ ОдĐŊҖҔҗ С ĐŧОдĐĩĐģĐĩĐš CLIP, ŅĐēа ĐŋĐĩŅ€ĐĩŅ€Đ°Ņ…ĐžĐ˛Đ°ĐŊа Ņ‚ŅƒŅ‚. Đ—Đ°ŅƒĐ˛Đ°ĐļŅ‚Đĩ, Ņ‰Đž ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž СĐŊĐžĐ˛Ņƒ СаĐŋŅƒŅŅ‚Đ¸Ņ‚Đ¸ СавдаĐŊĐŊŅ ÂĢĐ ĐžĐˇŅƒĐŧĐŊиК ĐŋĐžŅˆŅƒĐēÂģ Đ´ĐģŅ Đ˛ŅŅ–Ņ… ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊҌ ĐŋҖҁĐģŅ СĐŧŅ–ĐŊи ĐŧОдĐĩĐģŅ–.", "machine_learning_duplicate_detection": "Đ’Đ¸ŅĐ˛ĐģĐĩĐŊĐŊŅ Đ´ŅƒĐąĐģŅ–ĐēĐ°Ņ‚Ņ–Đ˛", @@ -258,10 +267,10 @@ "server_welcome_message": "Đ’Ņ–Ņ‚Đ°ĐģҌĐŊĐĩ ĐŋĐžĐ˛Ņ–Đ´ĐžĐŧĐģĐĩĐŊĐŊŅ", "server_welcome_message_description": "ĐŸĐžĐ˛Ņ–Đ´ĐžĐŧĐģĐĩĐŊĐŊŅ, ŅĐēĐĩ Đ˛Ņ–Đ´ĐžĐąŅ€Đ°ĐļĐ°Ņ”Ņ‚ŅŒŅŅ ĐŊа ŅŅ‚ĐžŅ€Ņ–ĐŊ҆Җ Đ˛Ņ…ĐžĐ´Ņƒ.", "sidecar_job": "МĐĩŅ‚Đ°Đ´Đ°ĐŊŅ– С sidecar-Ņ„Đ°ĐšĐģŅ–Đ˛", - "sidecar_job_description": "Đ’Đ¸ŅĐ˛ĐģĐĩĐŊĐŊŅ айО ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊŅ–ĐˇĐ°Ņ†Ņ–Ņ ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐ¸Ņ… Đ´ĐžĐ´Đ°Ņ‚ĐēŅ–Đ˛ С Ņ„Đ°ĐšĐģĐžĐ˛ĐžŅ— ŅĐ¸ŅŅ‚ĐĩĐŧи", + "sidecar_job_description": "ĐŸĐžŅˆŅƒĐē айО ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊŅ–ĐˇĐ°Ņ†Ņ–Ņ ŅĐ°ĐšĐ´ĐēĐ°Ņ€-ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐ¸Ņ… С Ņ„Đ°ĐšĐģĐžĐ˛ĐžŅ— ŅĐ¸ŅŅ‚ĐĩĐŧи", "slideshow_duration_description": "ĐšŅ–ĐģҌĐēŅ–ŅŅ‚ŅŒ ҁĐĩĐē҃ĐŊĐ´ Đ´ĐģŅ Đ˛Ņ–Đ´ĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ ĐēĐžĐļĐŊĐžĐŗĐž ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ", "smart_search_job_description": "ЗаĐŋ҃ҁĐē ĐŧĐ°ŅˆĐ¸ĐŊĐŊĐžĐŗĐž ĐŊĐ°Đ˛Ņ‡Đ°ĐŊĐŊŅ Đ´ĐģŅ Ņ€ĐĩŅŅƒŅ€ŅŅ–Đ˛ Đ´ĐģŅ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēи Ņ€ĐžĐˇŅƒĐŧĐŊĐžĐŗĐž ĐŋĐžŅˆŅƒĐē҃", - "storage_template_date_time_description": "ПозĐŊĐ°Ņ‡Đēа Ņ‡Đ°ŅŅƒ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ аĐēŅ‚Đ¸Đ˛Ņƒ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ Đ´ĐģŅ Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ— ĐŋŅ€Đž Đ´Đ°Ņ‚Ņƒ Đš Ņ‡Đ°Ņ", + "storage_template_date_time_description": "ПозĐŊĐ°Ņ‡Đēа Ņ‡Đ°ŅŅƒ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ Ņ€ĐĩŅŅƒŅ€ŅŅƒ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ Đ´ĐģŅ Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ— ĐŋŅ€Đž Đ´Đ°Ņ‚Ņƒ Đš Ņ‡Đ°Ņ", "storage_template_date_time_sample": "Đ§Đ°Ņ Đ˛Đ¸ĐąŅ–Ņ€Đēи {date}", "storage_template_enable_description": "Đ’Đ˛Ņ–ĐŧĐēĐŊŅƒŅ‚Đ¸ ĐŧĐĩŅ…Đ°ĐŊŅ–ĐˇĐŧ ŅˆĐ°ĐąĐģĐžĐŊŅ–Đ˛ ŅŅ…ĐžĐ˛Đ¸Ņ‰Đ°", "storage_template_hash_verification_enabled": "ĐŖĐ˛Ņ–ĐŧĐēĐŊĐĩĐŊĐž ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đē҃ Ņ…Đĩ҈҃", @@ -340,7 +349,7 @@ "transcoding_settings": "НаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ Ņ‚Ņ€Đ°ĐŊҁĐēĐžĐ´ŅƒĐ˛Đ°ĐŊĐŊŅ Đ˛Ņ–Đ´ĐĩĐž", "transcoding_settings_description": "КĐĩŅ€ŅƒĐ˛Đ°ĐŊĐŊŅ ŅĐēŅ– Đ˛Ņ–Đ´ĐĩĐž Ņ‚Ņ€Đ°ĐŊҁĐēĐžĐ´ŅƒĐ˛Đ°Ņ‚Đ¸ Ņ– ŅĐē Ņ—Ņ… ĐžĐąŅ€ĐžĐąĐģŅŅ‚Đ¸", "transcoding_target_resolution": "Đ ĐžĐˇĐ´Ņ–ĐģҌĐŊа ĐˇĐ´Đ°Ņ‚ĐŊŅ–ŅŅ‚ŅŒ", - "transcoding_target_resolution_description": "Đ’Đ¸Ņ‰Ņ– Ņ€ĐžĐˇĐ´Ņ–ĐģҌĐŊŅ– ĐˇĐ´Đ°Ņ‚ĐŊĐžŅŅ‚Ņ– ĐŧĐžĐļŅƒŅ‚ŅŒ СйĐĩŅ€Ņ–ĐŗĐ°Ņ‚Đ¸ ĐąŅ–ĐģҌ҈Đĩ Đ´ĐĩŅ‚Đ°ĐģĐĩĐš, аĐģĐĩ СаКĐŧĐ°ŅŽŅ‚ŅŒ ĐąŅ–ĐģҌ҈Đĩ Ņ‡Đ°ŅŅƒ ĐŊа ĐēĐžĐ´ŅƒĐ˛Đ°ĐŊĐŊŅ, ĐŧĐ°ŅŽŅ‚ŅŒ ĐąŅ–ĐģŅŒŅˆŅ– Ņ€ĐžĐˇĐŧŅ–Ņ€Đ¸ Ņ„Đ°ĐšĐģŅ–Đ˛ Ņ– ĐŧĐžĐļŅƒŅ‚ŅŒ СĐŧĐĩĐŊŅˆĐ¸Ņ‚Đ¸ ŅˆĐ˛Đ¸Đ´ĐēŅ–ŅŅ‚ŅŒ Ņ€ĐžĐąĐžŅ‚Đ¸ Đ´ĐžĐ´Đ°Ņ‚Đē҃.", + "transcoding_target_resolution_description": "Đ’Đ¸Ņ‰Ņ– Ņ€ĐžĐˇĐ´Ņ–ĐģҌĐŊŅ– ĐˇĐ´Đ°Ņ‚ĐŊĐžŅŅ‚Ņ– ĐŧĐžĐļŅƒŅ‚ŅŒ СйĐĩŅ€Ņ–ĐŗĐ°Ņ‚Đ¸ ĐąŅ–ĐģҌ҈Đĩ Đ´ĐĩŅ‚Đ°ĐģĐĩĐš, аĐģĐĩ СаКĐŧĐ°ŅŽŅ‚ŅŒ ĐąŅ–ĐģҌ҈Đĩ Ņ‡Đ°ŅŅƒ ĐŊа ĐēĐžĐ´ŅƒĐ˛Đ°ĐŊĐŊŅ, ĐŧĐ°ŅŽŅ‚ŅŒ ĐąŅ–ĐģŅŒŅˆŅ– Ņ€ĐžĐˇĐŧŅ–Ņ€Đ¸ Ņ„Đ°ĐšĐģŅ–Đ˛ Ņ– ĐŧĐžĐļŅƒŅ‚ŅŒ СĐŧĐĩĐŊŅˆĐ¸Ņ‚Đ¸ ŅˆĐ˛Đ¸Đ´ĐēŅ–ŅŅ‚ŅŒ Ņ€ĐžĐąĐžŅ‚Đ¸ ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐē҃.", "transcoding_temporal_aq": "ĐĸиĐŧŅ‡Đ°ŅĐžĐ˛Đĩ AQ", "transcoding_temporal_aq_description": "ĐĻĐĩ ĐˇĐ°ŅŅ‚ĐžŅĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ ĐģĐ¸ŅˆĐĩ Đ´Đž NVENC. ĐŸŅ–Đ´Đ˛Đ¸Ņ‰ŅƒŅ” ŅĐēŅ–ŅŅ‚ŅŒ ҁ҆ĐĩĐŊ С вĐĩĐģиĐēĐžŅŽ Đ´ĐĩŅ‚Đ°ĐģŅ–ĐˇĐ°Ņ†Ņ–Ņ”ŅŽ Ņ‚Đ° ĐŊĐ¸ĐˇŅŒĐēиĐŧ Ņ€ŅƒŅ…ĐžĐŧ. МоĐļĐĩ ĐąŅƒŅ‚Đ¸ ĐŊĐĩҁ҃ĐŧҖҁĐŊиĐŧ ĐˇŅ– ŅŅ‚Đ°Ņ€Đ¸Đŧи ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅĐŧи.", "transcoding_threads": "ĐŸĐžŅ‚ĐžĐēи", @@ -353,11 +362,11 @@ "transcoding_two_pass_encoding_setting_description": "ĐĸŅ€Đ°ĐŊҁĐēĐžĐ´ŅƒĐ˛Đ°ĐŊĐŊŅ Са двОĐŧа ĐŋŅ€ĐžŅ…ĐžĐ´Đ°Đŧи Đ´ĐģŅ ĐžŅ‚Ņ€Đ¸ĐŧаĐŊĐŊŅ ĐēŅ€Đ°Ņ‰Đ¸Ņ… СаĐēОдОваĐŊĐ¸Ņ… Đ˛Ņ–Đ´ĐĩĐž. КоĐģи Đ˛Đ˛Ņ–ĐŧĐēĐŊĐĩĐŊĐž ĐŧаĐēŅĐ¸ĐŧаĐģҌĐŊиК ĐąŅ–Ņ‚Ņ€ĐĩĐšŅ‚ (ĐŊĐĩĐžĐąŅ…Ņ–Đ´ĐŊиК Đ´ĐģŅ Ņ€ĐžĐąĐžŅ‚Đ¸ С H.264 Ņ‚Đ° HEVC), ҆ĐĩĐš Ņ€ĐĩĐļиĐŧ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ” Đ´Ņ–Đ°ĐŋаСОĐŊ ĐąŅ–Ņ‚Ņ€ĐĩĐšŅ‚Ņƒ, ĐˇĐ°ŅĐŊОваĐŊиК ĐŊа ĐŧаĐēŅĐ¸ĐŧаĐģҌĐŊĐžĐŧ҃ ĐąŅ–Ņ‚Ņ€ĐĩĐšŅ‚Ņ–, Ņ– Ņ–ĐŗĐŊĐžŅ€ŅƒŅ” CRF. ДĐģŅ VP9 ĐŧĐžĐļĐŊа виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ CRF, ŅĐēŅ‰Đž виĐŧĐēĐŊĐĩĐŊĐž ĐŧаĐēŅĐ¸ĐŧаĐģҌĐŊиК ĐąŅ–Ņ‚Ņ€ĐĩĐšŅ‚.", "transcoding_video_codec": "Đ’Ņ–Đ´ĐĩĐžĐēОдĐĩĐē", "transcoding_video_codec_description": "VP9 ĐŧĐ°Ņ” Đ˛Đ¸ŅĐžĐē҃ ĐĩŅ„ĐĩĐēŅ‚Đ¸Đ˛ĐŊŅ–ŅŅ‚ŅŒ Ņ– ҁ҃ĐŧҖҁĐŊŅ–ŅŅ‚ŅŒ С вĐĩйОĐŧ, аĐģĐĩ ĐŋĐžŅ‚Ņ€ĐĩĐąŅƒŅ” ĐąŅ–ĐģҌ҈Đĩ Ņ‡Đ°ŅŅƒ ĐŊа Ņ‚Ņ€Đ°ĐŊҁĐēĐžĐ´ŅƒĐ˛Đ°ĐŊĐŊŅ. HEVC ĐŋŅ€Đ°Ņ†ŅŽŅ” ŅŅ…ĐžĐļĐĩ, аĐģĐĩ ĐŧĐ°Ņ” ĐŧĐĩĐŊ҈҃ ҁ҃ĐŧҖҁĐŊŅ–ŅŅ‚ŅŒ С вĐĩйОĐŧ. H.264 ĐŧĐ°Ņ” ŅˆĐ¸Ņ€ĐžĐē҃ ҁ҃ĐŧҖҁĐŊŅ–ŅŅ‚ŅŒ Ņ– ŅˆĐ˛Đ¸Đ´ĐēĐž Ņ‚Ņ€Đ°ĐŊҁĐēĐžĐ´ŅƒŅ”Ņ‚ŅŒŅŅ, аĐģĐĩ ŅŅ‚Đ˛ĐžŅ€ŅŽŅ” СĐŊĐ°Ņ‡ĐŊĐž ĐąŅ–ĐģŅŒŅˆŅ– Ņ„Đ°ĐšĐģи. AV1 - ĐŊаКĐĩŅ„ĐĩĐēŅ‚Đ¸Đ˛ĐŊŅ–ŅˆĐ¸Đš ĐēОдĐĩĐē, аĐģĐĩ ĐŊĐĩ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚ŅŒŅŅ ĐŊа ŅŅ‚Đ°Ņ€Ņ–ŅˆĐ¸Ņ… ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅŅ….", - "trash_enabled_description": "ĐŖĐ˛Ņ–ĐŧĐēĐŊĐĩĐŊĐŊŅ ҁĐŧŅ–Ņ‚ĐŊиĐēа", + "trash_enabled_description": "ĐŖĐ˛Ņ–ĐŧĐēĐŊĐĩĐŊĐŊŅ ĐēĐžŅˆĐ¸Đēа", "trash_number_of_days": "ĐšŅ–ĐģҌĐēŅ–ŅŅ‚ŅŒ Đ´ĐŊŅ–Đ˛", - "trash_number_of_days_description": "ĐšŅ–ĐģҌĐēŅ–ŅŅ‚ŅŒ Đ´ĐŊŅ–Đ˛, Ņ‰ĐžĐą СаĐģĐ¸ŅˆĐ¸Ņ‚Đ¸ Ņ€ĐĩŅŅƒŅ€ŅĐ¸ в ҁĐŧŅ–Ņ‚ĐŊиĐē҃ ĐŋĐĩŅ€ĐĩĐ´ ĐžŅŅ‚Đ°Ņ‚ĐžŅ‡ĐŊиĐŧ Ņ—Ņ… видаĐģĐĩĐŊĐŊŅĐŧ", - "trash_settings": "НаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ ҁĐŧŅ–Ņ‚ĐŊиĐēа", - "trash_settings_description": "КĐĩŅ€ŅƒĐ˛Đ°ĐŊĐŊŅ ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅĐŧи ҁĐŧŅ–Ņ‚ĐŊиĐēа", + "trash_number_of_days_description": "ĐšŅ–ĐģҌĐēŅ–ŅŅ‚ŅŒ Đ´ĐŊŅ–Đ˛, ĐŋŅ€ĐžŅ‚ŅĐŗĐžĐŧ ŅĐēĐžŅ— СаĐģĐ¸ŅˆĐ°Ņ‚Đ¸ Ņ€ĐĩŅŅƒŅ€ŅĐ¸ в ĐēĐžŅˆĐ¸Đē҃ ĐŋĐĩŅ€ĐĩĐ´ Ņ—Ņ… ĐžŅŅ‚Đ°Ņ‚ĐžŅ‡ĐŊиĐŧ видаĐģĐĩĐŊĐŊŅĐŧ", + "trash_settings": "НаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ ĐēĐžŅˆĐ¸Đēа", + "trash_settings_description": "КĐĩŅ€ŅƒĐ˛Đ°ĐŊĐŊŅ ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅĐŧи ĐēĐžŅˆĐ¸Đēа", "unlink_all_oauth_accounts": "Đ’Ņ–Đ´â€™Ņ”Đ´ĐŊĐ°Ņ‚Đ¸ Đ˛ŅŅ– ОйĐģŅ–ĐēĐžĐ˛Ņ– СаĐŋĐ¸ŅĐ¸ OAuth", "unlink_all_oauth_accounts_description": "НĐĩ ĐˇĐ°ĐąŅƒĐ´ŅŒŅ‚Đĩ Đ˛Ņ–Đ´â€™Ņ”Đ´ĐŊĐ°Ņ‚Đ¸ Đ˛ŅŅ– ОйĐģŅ–ĐēĐžĐ˛Ņ– СаĐŋĐ¸ŅĐ¸ OAuth ĐŋĐĩŅ€ĐĩĐ´ ĐŋĐĩŅ€ĐĩŅ…ĐžĐ´ĐžĐŧ Đ´Đž ĐŊĐžĐ˛ĐžĐŗĐž ĐŋĐžŅŅ‚Đ°Ņ‡Đ°ĐģҌĐŊиĐēа.", "unlink_all_oauth_accounts_prompt": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ Đ˛Ņ–Đ´â€™Ņ”Đ´ĐŊĐ°Ņ‚Đ¸ Đ˛ŅŅ– ОйĐģŅ–ĐēĐžĐ˛Ņ– СаĐŋĐ¸ŅĐ¸ OAuth? ĐĻĐĩ ҁĐēиĐŊĐĩ Ņ–Đ´ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ‚ĐžŅ€ OAuth Đ´ĐģŅ ĐēĐžĐļĐŊĐžĐŗĐž ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ°, Ņ– Ņ†ŅŽ Đ´Ņ–ŅŽ ĐŊĐĩ ĐŧĐžĐļĐŊа ĐąŅƒĐ´Đĩ ҁĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸.", @@ -387,9 +396,7 @@ "admin_password": "ĐŸĐ°Ņ€ĐžĐģҌ адĐŧŅ–ĐŊŅ–ŅŅ‚Ņ€Đ°Ņ‚ĐžŅ€Đ°", "administration": "АдĐŧŅ–ĐŊŅ–ŅŅ‚Ņ€ŅƒĐ˛Đ°ĐŊĐŊŅ", "advanced": "Đ ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊŅ–", - "advanced_settings_beta_timeline_subtitle": "ВиĐŋŅ€ĐžĐąŅƒĐšŅ‚Đĩ ĐŊОвиК Ņ–ĐŊŅ‚ĐĩҀ҄ĐĩĐšŅ ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐē҃", - "advanced_settings_beta_timeline_title": "БĐĩŅ‚Đ°-вĐĩŅ€ŅŅ–Ņ ҁ҂ҀҖ҇Đēи", - "advanced_settings_enable_alternate_media_filter_subtitle": "ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ ҆ĐĩĐš Đ˛Đ°Ņ€Ņ–Đ°ĐŊŅ‚ Đ´ĐģŅ ҄ҖĐģŅŒŅ‚Ņ€Đ°Ņ†Ņ–Ņ— ĐŧĐĩĐ´Ņ–Đ°Ņ„Đ°ĐšĐģŅ–Đ˛ ĐŋŅ–Đ´ Ņ‡Đ°Ņ ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊŅ–ĐˇĐ°Ņ†Ņ–Ņ— Са аĐģŅŒŅ‚ĐĩŅ€ĐŊĐ°Ņ‚Đ¸Đ˛ĐŊиĐŧи ĐēŅ€Đ¸Ņ‚ĐĩŅ€Ņ–ŅĐŧи. ĐĄĐŋŅ€ĐžĐąŅƒĐšŅ‚Đĩ ҆Đĩ, ŅĐēŅ‰Đž ҃ Đ˛Đ°Ņ виĐŊиĐēĐ°ŅŽŅ‚ŅŒ ĐŋŅ€ĐžĐąĐģĐĩĐŧи С Ņ‚Đ¸Đŧ, Ņ‰Đž Đ´ĐžĐ´Đ°Ņ‚ĐžĐē ĐŊĐĩ Đ˛Đ¸ŅĐ˛ĐģŅŅ” Đ˛ŅŅ– аĐģŅŒĐąĐžĐŧи.", + "advanced_settings_enable_alternate_media_filter_subtitle": "ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ ҆ĐĩĐš Đ˛Đ°Ņ€Ņ–Đ°ĐŊŅ‚ Đ´ĐģŅ ҄ҖĐģŅŒŅ‚Ņ€Đ°Ņ†Ņ–Ņ— ĐŧĐĩĐ´Ņ–Đ°Ņ„Đ°ĐšĐģŅ–Đ˛ ĐŋŅ–Đ´ Ņ‡Đ°Ņ ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊŅ–ĐˇĐ°Ņ†Ņ–Ņ— Са аĐģŅŒŅ‚ĐĩŅ€ĐŊĐ°Ņ‚Đ¸Đ˛ĐŊиĐŧи ĐēŅ€Đ¸Ņ‚ĐĩŅ€Ņ–ŅĐŧи. ĐĄĐŋŅ€ĐžĐąŅƒĐšŅ‚Đĩ ҆Đĩ, ŅĐēŅ‰Đž ҃ Đ˛Đ°Ņ виĐŊиĐēĐ°ŅŽŅ‚ŅŒ ĐŋŅ€ĐžĐąĐģĐĩĐŧи С Ņ‚Đ¸Đŧ, Ņ‰Đž ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐžĐē ĐŊĐĩ Đ˛Đ¸ŅĐ˛ĐģŅŅ” Đ˛ŅŅ– аĐģŅŒĐąĐžĐŧи.", "advanced_settings_enable_alternate_media_filter_title": "[ЕКСПЕРИМЕНĐĸАЛĐŦНИЙ] ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ аĐģŅŒŅ‚ĐĩŅ€ĐŊĐ°Ņ‚Đ¸Đ˛ĐŊиК ҄ҖĐģŅŒŅ‚Ņ€ ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊŅ–ĐˇĐ°Ņ†Ņ–Ņ— аĐģŅŒĐąĐžĐŧŅ–Đ˛ ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅŽ", "advanced_settings_log_level_title": "Đ Ņ–Đ˛ĐĩĐŊҌ ĐģĐžĐŗŅƒĐ˛Đ°ĐŊĐŊŅ: {level}", "advanced_settings_prefer_remote_subtitle": "ДĐĩŅĐēŅ– ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅ— вĐĩĐģҌĐŧи ĐŋĐžĐ˛Ņ–ĐģҌĐŊĐž СаваĐŊŅ‚Đ°ĐļŅƒŅŽŅ‚ŅŒ ĐŧŅ–ĐŊŅ–Đ°Ņ‚ŅŽŅ€Đ¸ Ņ–Đˇ ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛ ĐŊа ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅ—. АĐēŅ‚Đ¸Đ˛ŅƒĐšŅ‚Đĩ ҆ĐĩĐš ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ, Ņ‰ĐžĐą СаваĐŊŅ‚Đ°ĐļŅƒĐ˛Đ°Ņ‚Đ¸ ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ С ҁĐĩŅ€Đ˛ĐĩŅ€Ņƒ.", @@ -425,6 +432,7 @@ "album_remove_user_confirmation": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ {user}?", "album_search_not_found": "АĐģŅŒĐąĐžĐŧŅ–Đ˛, Ņ‰Đž Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Đ°ŅŽŅ‚ŅŒ Đ˛Đ°ŅˆĐžĐŧ҃ СаĐŋĐ¸Ņ‚Ņƒ, ĐŊĐĩ СĐŊаКдĐĩĐŊĐž", "album_share_no_users": "ĐĄŅ…ĐžĐļĐĩ, ви ĐŋĐžĐ´Ņ–ĐģиĐģĐ¸ŅŅ Ņ†Đ¸Đŧ аĐģŅŒĐąĐžĐŧĐžĐŧ С ŅƒŅŅ–Đŧа ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ°Đŧи айО ҃ Đ˛Đ°Ņ ĐŊĐĩĐŧĐ°Ņ” ĐļОдĐŊĐžĐŗĐž ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ°, С ŅĐēиĐŧ ĐŧĐžĐļĐŊа ĐąŅƒĐģĐž Đą ĐŋĐžĐ´Ņ–ĐģĐ¸Ņ‚Đ¸ŅŅ.", + "album_summary": "ĐšĐžŅ€ĐžŅ‚ĐēиК ĐžĐŋĐ¸Ņ аĐģŅŒĐąĐžĐŧ҃", "album_updated": "АĐģŅŒĐąĐžĐŧ ĐžĐŊОвĐģĐĩĐŊĐž", "album_updated_setting_description": "ĐžŅ‚Ņ€Đ¸ĐŧŅƒĐšŅ‚Đĩ ҁĐŋĐžĐ˛Ņ–Ņ‰ĐĩĐŊĐŊŅ ĐŊа ĐĩĐģĐĩĐēŅ‚Ņ€ĐžĐŊĐŊ҃ ĐŋĐžŅˆŅ‚Ņƒ, ĐēĐžĐģи ҃ ҁĐŋŅ–ĐģҌĐŊĐžĐŧ҃ аĐģŅŒĐąĐžĐŧŅ– С'ŅĐ˛ĐģŅŅŽŅ‚ŅŒŅŅ ĐŊĐžĐ˛Ņ– Ņ€ĐĩŅŅƒŅ€ŅĐ¸", "album_user_left": "Ви ĐŋĐžĐēиĐŊ҃Đģи {album}", @@ -491,11 +499,13 @@ "asset_list_layout_sub_title": "РОСĐŧŅ–Ņ‚Đēа", "asset_list_settings_subtitle": "НаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ Đ˛Đ¸ĐŗĐģŅĐ´Ņƒ ҁҖ҂Đēи Ņ„ĐžŅ‚Đž", "asset_list_settings_title": "Đ¤ĐžŅ‚Đž-ҁҖ҂Đēа", - "asset_offline": "АĐēŅ‚Đ¸Đ˛ виĐŧĐēĐŊĐĩĐŊĐž", - "asset_offline_description": "ĐĻĐĩĐš СОвĐŊŅ–ŅˆĐŊŅ–Đš аĐēŅ‚Đ¸Đ˛ ĐąŅ–ĐģҌ҈Đĩ ĐŊĐĩ СĐŊаКдĐĩĐŊĐž ĐŊа Đ´Đ¸ŅĐē҃. Đ‘ŅƒĐ´ŅŒ ĐģĐ°ŅĐēа, СвĐĩŅ€ĐŊŅ–Ņ‚ŅŒŅŅ Đ´Đž адĐŧŅ–ĐŊŅ–ŅŅ‚Ņ€Đ°Ņ‚ĐžŅ€Đ° Immich Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ.", + "asset_offline": "Đ ĐĩŅŅƒŅ€Ņ ĐžŅ„ĐģаКĐŊ", + "asset_offline_description": "ĐĻĐĩĐš СОвĐŊŅ–ŅˆĐŊŅ–Đš Ņ€ĐĩŅŅƒŅ€Ņ ĐąŅ–ĐģҌ҈Đĩ ĐŊĐĩ СĐŊаКдĐĩĐŊĐž ĐŊа Đ´Đ¸ŅĐē҃. Đ‘ŅƒĐ´ŅŒ ĐģĐ°ŅĐēа, СвĐĩŅ€ĐŊŅ–Ņ‚ŅŒŅŅ Đ´Đž адĐŧŅ–ĐŊŅ–ŅŅ‚Ņ€Đ°Ņ‚ĐžŅ€Đ° Immich Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ.", "asset_restored_successfully": "ЕĐģĐĩĐŧĐĩĐŊŅ‚ ҃ҁĐŋŅ–ŅˆĐŊĐž Đ˛Ņ–Đ´ĐŊОвĐģĐĩĐŊĐž", "asset_skipped": "ĐŸŅ€ĐžĐŋŅƒŅ‰ĐĩĐŊĐž", - "asset_skipped_in_trash": "ĐŖ ҁĐŧŅ–Ņ‚ĐŊиĐē҃", + "asset_skipped_in_trash": "ĐŖ ĐēĐžŅˆĐ¸Đē҃", + "asset_trashed": "Об'Ņ”ĐēŅ‚ видаĐģĐĩĐŊĐž С ĐēĐžŅˆĐ¸Đēа", + "asset_troubleshoot": "Đ’Đ¸Ņ€Ņ–ŅˆĐĩĐŊĐŊŅ ĐŋŅ€ĐžĐąĐģĐĩĐŧ С аĐēŅ‚Đ¸Đ˛Đ°Đŧи", "asset_uploaded": "ЗаваĐŊŅ‚Đ°ĐļĐĩĐŊĐž", "asset_uploading": "ЗаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅâ€Ļ", "asset_viewer_settings_subtitle": "КĐĩŅ€ŅƒĐšŅ‚Đĩ ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅĐŧи ĐŋĐĩŅ€ĐĩĐŗĐģŅĐ´Đ°Ņ‡Đ° ĐŗĐ°ĐģĐĩŅ€ĐĩŅ—", @@ -503,34 +513,36 @@ "assets": "ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸", "assets_added_count": "ДодаĐŊĐž {count, plural, one {# Ņ€ĐĩŅŅƒŅ€Ņ} few {# Ņ€ĐĩŅŅƒŅ€ŅĐ¸} other {# Ņ€ĐĩŅŅƒŅ€ŅŅ–Đ˛}}", "assets_added_to_album_count": "ДодаĐŊĐž {count, plural, one {# Ņ€ĐĩŅŅƒŅ€Ņ} few {# Ņ€ĐĩŅŅƒŅ€ŅĐ¸} other {# Ņ€ĐĩŅŅƒŅ€ŅŅ–Đ˛}} Đ´Đž аĐģŅŒĐąĐžĐŧ҃", - "assets_added_to_albums_count": "ДодаĐŊĐž {assetTotal, plural, one {# аĐēŅ‚Đ¸Đ˛} other {# аĐēŅ‚Đ¸Đ˛Đ¸}} Đ´Đž {albumTotal, plural, one {# аĐģŅŒĐąĐžĐŧ} other {# аĐģŅŒĐąĐžĐŧ}}", + "assets_added_to_albums_count": "ДодаĐŊĐž {assetTotal, plural, one {# Ņ€ĐĩŅŅƒŅ€Ņ} other {# Ņ€ĐĩŅŅƒŅ€ŅĐ¸}} Đ´Đž {albumTotal, plural, one {# аĐģŅŒĐąĐžĐŧ} other {# аĐģŅŒĐąĐžĐŧ}}", "assets_cannot_be_added_to_album_count": "{count, plural, one {Đ ĐĩŅŅƒŅ€Ņ} other {Đ ĐĩŅŅƒŅ€ŅĐ¸}} ĐŊĐĩ ĐŧĐžĐļĐŊа Đ´ĐžĐ´Đ°Ņ‚Đ¸ Đ´Đž аĐģŅŒĐąĐžĐŧ҃", - "assets_cannot_be_added_to_albums": "{count, plural, one {АĐēŅ‚Đ¸Đ˛} other {АĐēŅ‚Đ¸Đ˛Đ¸}} ĐŊĐĩ ĐŧĐžĐļĐŊа Đ´ĐžĐ´Đ°Ņ‚Đ¸ Đ´Đž ĐļОдĐŊĐžĐŗĐž С аĐģŅŒĐąĐžĐŧŅ–Đ˛", + "assets_cannot_be_added_to_albums": "{count, plural, one {ЕĐģĐĩĐŧĐĩĐŊŅ‚} other {ЕĐģĐĩĐŧĐĩĐŊŅ‚Đ¸}} ĐŊĐĩ ĐŧĐžĐļĐŊа Đ´ĐžĐ´Đ°Ņ‚Đ¸ Đ´Đž ĐļОдĐŊĐžĐŗĐž С аĐģŅŒĐąĐžĐŧŅ–Đ˛", "assets_count": "{count, plural, one {# Ņ€ĐĩŅŅƒŅ€Ņ} few {# Ņ€ĐĩŅŅƒŅ€ŅĐ¸} other {# Ņ€ĐĩŅŅƒŅ€ŅŅ–Đ˛}}", "assets_deleted_permanently": "{count} ĐĩĐģĐĩĐŧĐĩĐŊŅ‚(и) ĐžŅŅ‚Đ°Ņ‚ĐžŅ‡ĐŊĐž видаĐģĐĩĐŊĐž", "assets_deleted_permanently_from_server": "{count} ĐĩĐģĐĩĐŧĐĩĐŊŅ‚(и) видаĐģĐĩĐŊĐž ĐŊаСавĐļди С ҁĐĩŅ€Đ˛ĐĩŅ€Đ° Immich", "assets_downloaded_failed": "{count, plural, one {ЗаваĐŊŅ‚Đ°ĐļĐĩĐŊĐž # Ņ„Đ°ĐšĐģ — {error} Ņ„Đ°ĐšĐģ ĐŊĐĩ вдаĐģĐžŅŅ} other {ЗаваĐŊŅ‚Đ°ĐļĐĩĐŊĐž # Ņ„Đ°ĐšĐģŅ–Đ˛ — {error} Ņ„Đ°ĐšĐģŅ–Đ˛ ĐŊĐĩ вдаĐģĐžŅŅ}}", "assets_downloaded_successfully": "{count, plural, one {ĐŖŅĐŋŅ–ŅˆĐŊĐž СаваĐŊŅ‚Đ°ĐļĐĩĐŊĐž # Ņ„Đ°ĐšĐģ} other {ĐŖŅĐŋŅ–ŅˆĐŊĐž СаваĐŊŅ‚Đ°ĐļĐĩĐŊĐž # Ņ„Đ°ĐšĐģŅ–Đ˛}}", - "assets_moved_to_trash_count": "ПĐĩŅ€ĐĩĐŧҖ҉ĐĩĐŊĐž {count, plural, one {# Ņ€ĐĩŅŅƒŅ€Ņ} few {# Ņ€ĐĩŅŅƒŅ€ŅĐ¸} other {# Ņ€ĐĩŅŅƒŅ€ŅŅ–Đ˛}} ҃ ҁĐŧŅ–Ņ‚ĐŊиĐē", + "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": "{count} ĐĩĐģĐĩĐŧĐĩĐŊŅ‚(и) видаĐģĐĩĐŊŅ– ĐŊаСавĐļди С Đ˛Đ°ŅˆĐžĐŗĐž ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅŽ", - "assets_restore_confirmation": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ Đ˛Ņ–Đ´ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ Đ˛ŅŅ– ŅĐ˛ĐžŅ— аĐēŅ‚Đ¸Đ˛Đ¸ С ҁĐŧŅ–Ņ‚ĐŊиĐēа? ĐĻŅŽ Đ´Ņ–ŅŽ ĐŊĐĩ ĐŧĐžĐļĐŊа ҁĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸! ЗвĐĩŅ€ĐŊŅ–Ņ‚ŅŒ ŅƒĐ˛Đ°ĐŗŅƒ, Ņ‰Đž ĐąŅƒĐ´ŅŒ-ŅĐēŅ– ĐžŅ„ĐģаКĐŊ-аĐēŅ‚Đ¸Đ˛Đ¸ ĐŊĐĩ ĐŧĐžĐļŅƒŅ‚ŅŒ ĐąŅƒŅ‚Đ¸ Đ˛Ņ–Đ´ĐŊОвĐģĐĩĐŊŅ– Ņ‚Đ°ĐēиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ.", + "assets_restore_confirmation": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ Đ˛Ņ–Đ´ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ Đ˛ŅŅ– ŅĐ˛ĐžŅ— ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ С ĐēĐžŅˆĐ¸Đēа? ĐĻŅŽ Đ´Ņ–ŅŽ ĐŊĐĩ ĐŧĐžĐļĐŊа ҁĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸! ЗвĐĩŅ€ĐŊŅ–Ņ‚ŅŒ ŅƒĐ˛Đ°ĐŗŅƒ, Ņ‰Đž ĐļОдĐŊŅ– ĐžŅ„ĐģаКĐŊ Ņ€ĐĩŅŅƒŅ€ŅĐ¸ ĐŊĐĩ ĐŧĐžĐļŅƒŅ‚ŅŒ ĐąŅƒŅ‚Đ¸ Đ˛Ņ–Đ´ĐŊОвĐģĐĩĐŊŅ– Ņ‚Đ°ĐēиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ.", "assets_restored_count": "Đ’Ņ–Đ´ĐŊОвĐģĐĩĐŊĐž {count, plural, one {# Ņ€ĐĩŅŅƒŅ€Ņ} few {# Ņ€ĐĩŅŅƒŅ€ŅĐ¸} other {# Ņ€ĐĩŅŅƒŅ€ŅŅ–Đ˛}}", "assets_restored_successfully": "{count} ĐĩĐģĐĩĐŧĐĩĐŊŅ‚(и) ҃ҁĐŋŅ–ŅˆĐŊĐž Đ˛Ņ–Đ´ĐŊОвĐģĐĩĐŊĐž", "assets_trashed": "{count} ĐĩĐģĐĩĐŧĐĩĐŊŅ‚(и) ĐŋĐžĐŧҖ҉ĐĩĐŊĐž Đ´Đž ĐēĐžŅˆĐ¸Đēа", - "assets_trashed_count": "ПоĐŧҖ҉ĐĩĐŊĐž в ҁĐŧŅ–Ņ‚ĐŊиĐē {count, plural, one {# Ņ€ĐĩŅŅƒŅ€Ņ} few {# Ņ€ĐĩŅŅƒŅ€ŅĐ¸} other {# Ņ€ĐĩŅŅƒŅ€ŅŅ–Đ˛}}", + "assets_trashed_count": "ПоĐŧҖ҉ĐĩĐŊĐž в ĐēĐžŅˆĐ¸Đē {count, plural, one {# Ņ€ĐĩŅŅƒŅ€Ņ} few {# Ņ€ĐĩŅŅƒŅ€ŅĐ¸} other {# Ņ€ĐĩŅŅƒŅ€ŅŅ–Đ˛}}", "assets_trashed_from_server": "{count} ĐĩĐģĐĩĐŧĐĩĐŊŅ‚(и) ĐŋĐžĐŧҖ҉ĐĩĐŊĐž Đ´Đž ĐēĐžŅˆĐ¸Đēа ĐŊа ҁĐĩŅ€Đ˛ĐĩҀҖ Immich", "assets_were_part_of_album_count": "{count, plural, one {Đ ĐĩŅŅƒŅ€Ņ ĐąŅƒĐ˛} few {Đ ĐĩŅŅƒŅ€ŅĐ¸ ĐąŅƒĐģи} other {Đ ĐĩŅŅƒŅ€ŅĐ¸ ĐąŅƒĐģи}} вĐļĐĩ Ņ‡Đ°ŅŅ‚Đ¸ĐŊĐžŅŽ аĐģŅŒĐąĐžĐŧ҃", - "assets_were_part_of_albums_count": "{count, plural, one {АĐēŅ‚Đ¸Đ˛ ĐąŅƒĐ˛} other {АĐēŅ‚Đ¸Đ˛Đ¸ ĐąŅƒĐģи}} вĐļĐĩ Ņ” Ņ‡Đ°ŅŅ‚Đ¸ĐŊĐžŅŽ аĐģŅŒĐąĐžĐŧŅ–Đ˛", + "assets_were_part_of_albums_count": "{count, plural, one {ЕĐģĐĩĐŧĐĩĐŊŅ‚ вĐļĐĩ ĐąŅƒĐ˛} other {ЕĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ вĐļĐĩ ĐąŅƒĐģи}} Ņ‡Đ°ŅŅ‚Đ¸ĐŊĐžŅŽ аĐģŅŒĐąĐžĐŧŅ–Đ˛", "authorized_devices": "ĐĐ˛Ņ‚ĐžŅ€Đ¸ĐˇĐžĐ˛Đ°ĐŊŅ– ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅ—", "automatic_endpoint_switching_subtitle": "ĐŸŅ–Đ´ĐēĐģŅŽŅ‡Đ°Ņ‚Đ¸ŅŅ ĐģĐžĐēаĐģҌĐŊĐž ҇ĐĩŅ€ĐĩС СаСĐŊĐ°Ņ‡ĐĩĐŊ҃ Wi-Fi ĐŧĐĩŅ€ĐĩĐļ҃, ĐēĐžĐģи ҆Đĩ ĐŧĐžĐļĐģивО, Ņ– виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ аĐģŅŒŅ‚ĐĩŅ€ĐŊĐ°Ņ‚Đ¸Đ˛ĐŊŅ– С'Ņ”Đ´ĐŊаĐŊĐŊŅ в Ņ–ĐŊŅˆĐ¸Ņ… виĐŋадĐēĐ°Ņ…", "automatic_endpoint_switching_title": "ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐĩ ĐŋĐĩŅ€ĐĩĐŧиĐēаĐŊĐŊŅ URL", "autoplay_slideshow": "ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐĩ Đ˛Ņ–Đ´Ņ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ ҁĐģĐ°ĐšĐ´ŅˆĐžŅƒ", "back": "Назад", "back_close_deselect": "ПовĐĩŅ€ĐŊŅƒŅ‚Đ¸ŅŅ, СаĐēŅ€Đ¸Ņ‚Đ¸ айО ҁĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸ Đ˛Đ¸ĐąŅ–Ņ€", + "background_backup_running_error": "ĐĐ°Ņ€Đ°ĐˇŅ– виĐēĐžĐŊŅƒŅ”Ņ‚ŅŒŅŅ Ņ„ĐžĐŊОвĐĩ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐĩ ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ, ĐŊĐĩĐŧĐžĐļĐģивО Ņ€ĐžĐˇĐŋĐžŅ‡Đ°Ņ‚Đ¸ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐĩ ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ Đ˛Ņ€ŅƒŅ‡ĐŊ҃", "background_location_permission": "Đ”ĐžĐˇĐ˛Ņ–Đģ Đ´Đž ĐŧҖҁ҆ĐĩСĐŊĐ°Ņ…ĐžĐ´ĐļĐĩĐŊĐŊŅ ҃ Ņ„ĐžĐŊŅ–", "background_location_permission_content": "ЊОй ĐŋĐĩŅ€ĐĩĐŧиĐēĐ°Ņ‚Đ¸ ĐŧĐĩŅ€ĐĩĐļŅ– ҃ Ņ„ĐžĐŊОвОĐŧ҃ Ņ€ĐĩĐļиĐŧŅ–, Immich ĐŧĐ°Ņ” *СавĐļди* ĐŧĐ°Ņ‚Đ¸ Đ´ĐžŅŅ‚ŅƒĐŋ Đ´Đž Ņ‚ĐžŅ‡ĐŊĐžŅ— ĐŗĐĩĐžĐģĐžĐēĐ°Ņ†Ņ–Ņ—, Ņ‰ĐžĐą ĐˇŅ‡Đ¸Ņ‚ŅƒĐ˛Đ°Ņ‚Đ¸ ĐŊĐ°ĐˇĐ˛Ņƒ Wi-Fi ĐŧĐĩŅ€ĐĩĐļŅ–", + "background_options": "ĐŸĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ Ņ„ĐžĐŊ҃", "backup": "Đ ĐĩСĐĩŅ€Đ˛ĐŊĐĩ ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ", "backup_album_selection_page_albums_device": "АĐģŅŒĐąĐžĐŧи ĐŊа ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅ— ({count})", "backup_album_selection_page_albums_tap": "ĐĸĐžŅ€ĐēĐŊŅ–Ņ‚ŅŒŅŅ, Ņ‰ĐžĐą вĐēĐģŅŽŅ‡Đ¸Ņ‚Đ¸, Đ´Đ˛Ņ–Ņ‡Ņ–, Ņ‰ĐžĐą виĐēĐģŅŽŅ‡Đ¸Ņ‚Đ¸", @@ -538,6 +550,7 @@ "backup_album_selection_page_select_albums": "ОбĐĩŅ€Ņ–Ņ‚ŅŒ аĐģŅŒĐąĐžĐŧи", "backup_album_selection_page_selection_info": "ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ ĐŋŅ€Đž ĐžĐąŅ€Đ°ĐŊĐĩ", "backup_album_selection_page_total_assets": "Đ—Đ°ĐŗĐ°ĐģҌĐŊа ĐēŅ–ĐģҌĐēŅ–ŅŅ‚ŅŒ ҃ĐŊŅ–ĐēаĐģҌĐŊĐ¸Ņ… ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛", + "backup_albums_sync": "ХиĐŊŅ…Ņ€ĐžĐŊŅ–ĐˇĐ°Ņ†Ņ–Ņ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐ¸Ņ… ĐēĐžĐŋŅ–Đš аĐģŅŒĐąĐžĐŧŅ–Đ˛", "backup_all": "ĐŖŅŅ–", "backup_background_service_backup_failed_message": "НĐĩ вдаĐģĐžŅŅ ĐˇŅ€ĐžĐąĐ¸Ņ‚Đ¸ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊ҃ ĐēĐžĐŋŅ–ŅŽ ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛. ĐŸĐžĐ˛Ņ‚ĐžŅ€ŅŽŅŽâ€Ļ", "backup_background_service_connection_failed_message": "НĐĩ вдаĐģĐžŅŅ Св'ŅĐˇĐ°Ņ‚Đ¸ŅŅ Ņ–Đˇ ҁĐĩŅ€Đ˛ĐĩŅ€ĐžĐŧ. ĐŸĐžĐ˛Ņ‚ĐžŅ€ŅŽŅŽâ€Ļ", @@ -587,6 +600,7 @@ "backup_controller_page_turn_on": "ĐŖĐ˛Ņ–ĐŧĐēĐŊŅƒŅ‚Đ¸ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐĩ ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ в аĐēŅ‚Đ¸Đ˛ĐŊĐžĐŧ҃ Ņ€ĐĩĐļиĐŧŅ–", "backup_controller_page_uploading_file_info": "ЗаваĐŊŅ‚Đ°ĐļŅƒŅŽ Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–ŅŽ ĐŋŅ€Đž Ņ„Đ°ĐšĐģ", "backup_err_only_album": "НĐĩ ĐŧĐžĐļ҃ видаĐģĐ¸Ņ‚Đ¸ Ņ”Đ´Đ¸ĐŊиК аĐģŅŒĐąĐžĐŧ", + "backup_error_sync_failed": "ПоĐŧиĐģĐēа ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊŅ–ĐˇĐ°Ņ†Ņ–Ņ—. НĐĩ Đ˛Đ´Đ°Ņ”Ņ‚ŅŒŅŅ ĐžĐąŅ€ĐžĐąĐ¸Ņ‚Đ¸ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊ҃ ĐēĐžĐŋŅ–ŅŽ.", "backup_info_card_assets": "ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸", "backup_manual_cancelled": "ĐĄĐēĐ°ŅĐžĐ˛Đ°ĐŊĐž", "backup_manual_in_progress": "ЗаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ вĐļĐĩ Đ˛Ņ–Đ´ĐąŅƒĐ˛Đ°Ņ”Ņ‚ŅŒŅŅ. ĐĄĐŋŅ€ĐžĐąŅƒĐšŅ‚Đĩ ĐˇĐŗĐžĐ´ĐžĐŧ", @@ -597,8 +611,6 @@ "backup_setting_subtitle": "ĐŖĐŋŅ€Đ°Đ˛ĐģŅ–ĐŊĐŊŅ ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅĐŧи СаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ ҃ Ņ„ĐžĐŊОвОĐŧ҃ Ņ‚Đ° аĐēŅ‚Đ¸Đ˛ĐŊĐžĐŧ҃ Ņ€ĐĩĐļиĐŧŅ–", "backup_settings_subtitle": "КĐĩŅ€ŅƒĐ˛Đ°ĐŊĐŊŅ ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅĐŧи СаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ", "backward": "Đ—Đ˛ĐžŅ€ĐžŅ‚ĐŊŅ–Đš", - "beta_sync": "ĐĄŅ‚Đ°ĐŊ ĐąĐĩŅ‚Đ°-ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊŅ–ĐˇĐ°Ņ†Ņ–Ņ—", - "beta_sync_subtitle": "НаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ ĐŊĐžĐ˛ĐžŅ— ŅĐ¸ŅŅ‚ĐĩĐŧи ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊŅ–ĐˇĐ°Ņ†Ņ–Ņ—", "biometric_auth_enabled": "Đ‘Ņ–ĐžĐŧĐĩŅ‚Ņ€Đ¸Ņ‡ĐŊа Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ ŅƒĐ˛Ņ–ĐŧĐēĐŊĐĩĐŊа", "biometric_locked_out": "ВаĐŧ СаĐēŅ€Đ¸Ņ‚Đž Đ´ĐžŅŅ‚ŅƒĐŋ Đ´Đž ĐąŅ–ĐžĐŧĐĩŅ‚Ņ€Đ¸Ņ‡ĐŊĐžŅ— Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ—", "biometric_no_options": "Đ‘Ņ–ĐžĐŧĐĩŅ‚Ņ€Đ¸Ņ‡ĐŊŅ– ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ ĐŊĐĩĐ´ĐžŅŅ‚ŅƒĐŋĐŊŅ–", @@ -611,12 +623,12 @@ "build_image": "ВĐĩŅ€ŅŅ–Ņ ĐˇĐąŅ–Ņ€Đēи", "bulk_delete_duplicates_confirmation": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐŧĐ°ŅĐžĐ˛Đž видаĐģĐ¸Ņ‚Đ¸ {count, plural, one {# Đ´ŅƒĐąĐģŅŒĐžĐ˛Đ°ĐŊиК Ņ€ĐĩŅŅƒŅ€Ņ} few {# Đ´ŅƒĐąĐģŅŒĐžĐ˛Đ°ĐŊŅ– Ņ€ĐĩŅŅƒŅ€ŅĐ¸} other {# Đ´ŅƒĐąĐģŅŒĐžĐ˛Đ°ĐŊĐ¸Ņ… Ņ€ĐĩŅŅƒŅ€ŅŅ–Đ˛}}? ĐĻĐĩ Đ´Ņ–Ņ СаĐģĐ¸ŅˆĐ¸Ņ‚ŅŒ ĐŊĐ°ĐšĐąŅ–ĐģŅŒŅˆĐ¸Đš Ņ€ĐĩŅŅƒŅ€Ņ ҃ ĐēĐžĐļĐŊŅ–Đš ĐŗŅ€ŅƒĐŋŅ– Ņ– ĐžŅŅ‚Đ°Ņ‚ĐžŅ‡ĐŊĐž видаĐģĐ¸Ņ‚ŅŒ Đ˛ŅŅ– Ņ–ĐŊŅˆŅ– Đ´ŅƒĐąĐģŅ–ĐēĐ°Ņ‚Đ¸. ĐĻŅŽ Đ´Ņ–ŅŽ ĐŊĐĩĐŧĐžĐļĐģивО ҁĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸!", "bulk_keep_duplicates_confirmation": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ СаĐģĐ¸ŅˆĐ¸Ņ‚Đ¸ {count, plural, one {# Đ´ŅƒĐąĐģŅŒĐžĐ˛Đ°ĐŊиК Ņ€ĐĩŅŅƒŅ€Ņ} few {# Đ´ŅƒĐąĐģŅŒĐžĐ˛Đ°ĐŊŅ– Ņ€ĐĩŅŅƒŅ€ŅĐ¸} other {# Đ´ŅƒĐąĐģŅŒĐžĐ˛Đ°ĐŊĐ¸Ņ… Ņ€ĐĩŅŅƒŅ€ŅŅ–Đ˛}}? ĐĻĐĩ дОСвОĐģĐ¸Ņ‚ŅŒ Đ˛Đ¸Ņ€Ņ–ŅˆĐ¸Ņ‚Đ¸ Đ˛ŅŅ– ĐŗŅ€ŅƒĐŋи Đ´ŅƒĐąĐģŅ–ĐēĐ°Ņ‚Ņ–Đ˛ ĐąĐĩС видаĐģĐĩĐŊĐŊŅ Ņ‡ĐžĐŗĐž-ĐŊĐĩĐąŅƒĐ´ŅŒ.", - "bulk_trash_duplicates_confirmation": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ виĐēиĐŊŅƒŅ‚Đ¸ в ҁĐŧŅ–Ņ‚ĐŊиĐē {count, plural, one {# Đ´ŅƒĐąĐģŅŒĐžĐ˛Đ°ĐŊиК Ņ€ĐĩŅŅƒŅ€Ņ} few {# Đ´ŅƒĐąĐģŅŒĐžĐ˛Đ°ĐŊŅ– Ņ€ĐĩŅŅƒŅ€ŅĐ¸} other {# Đ´ŅƒĐąĐģŅŒĐžĐ˛Đ°ĐŊĐ¸Ņ… Ņ€ĐĩŅŅƒŅ€ŅŅ–Đ˛}} ĐŧĐ°ŅĐžĐ˛Đž? ĐĻĐĩ СаĐģĐ¸ŅˆĐ¸Ņ‚ŅŒ ĐŊĐ°ĐšĐąŅ–ĐģŅŒŅˆĐ¸Đš Ņ€ĐĩŅŅƒŅ€Ņ ҃ ĐēĐžĐļĐŊŅ–Đš ĐŗŅ€ŅƒĐŋŅ– Ņ– виĐēиĐŊĐĩ в ҁĐŧŅ–Ņ‚ĐŊиĐē Đ˛ŅŅ– Ņ–ĐŊŅˆŅ– Đ´ŅƒĐąĐģŅ–ĐēĐ°Ņ‚Đ¸.", + "bulk_trash_duplicates_confirmation": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ виĐēиĐŊŅƒŅ‚Đ¸ в ĐēĐžŅˆĐ¸Đē {count, plural, one {# Đ´ŅƒĐąĐģŅŒĐžĐ˛Đ°ĐŊиК Ņ€ĐĩŅŅƒŅ€Ņ} few {# Đ´ŅƒĐąĐģŅŒĐžĐ˛Đ°ĐŊŅ– Ņ€ĐĩŅŅƒŅ€ŅĐ¸} other {# Đ´ŅƒĐąĐģŅŒĐžĐ˛Đ°ĐŊĐ¸Ņ… Ņ€ĐĩŅŅƒŅ€ŅŅ–Đ˛}} ĐŧĐ°ŅĐžĐ˛Đž? ĐĻĐĩ СаĐģĐ¸ŅˆĐ¸Ņ‚ŅŒ ĐŊĐ°ĐšĐąŅ–ĐģŅŒŅˆĐ¸Đš Ņ€ĐĩŅŅƒŅ€Ņ ҃ ĐēĐžĐļĐŊŅ–Đš ĐŗŅ€ŅƒĐŋŅ– Ņ– виĐēиĐŊĐĩ в ĐēĐžŅˆĐ¸Đē Đ˛ŅŅ– Ņ–ĐŊŅˆŅ– Đ´ŅƒĐąĐģŅ–ĐēĐ°Ņ‚Đ¸.", "buy": "ĐŸŅ€Đ¸Đ´ĐąĐ°ĐšŅ‚Đĩ Immich", "cache_settings_clear_cache_button": "ĐžŅ‡Đ¸ŅŅ‚Đ¸Ņ‚Đ¸ ĐēĐĩ҈", "cache_settings_clear_cache_button_title": "ĐžŅ‡Đ¸Ņ‰Đ°Ņ” ĐēĐĩ҈ ĐŋŅ€ĐžĐŗŅ€Đ°Đŧи. ĐĻĐĩ ŅŅƒŅ‚Ņ‚Ņ”Đ˛Đž СĐŊĐ¸ĐˇĐ¸Ņ‚ŅŒ ĐŋŅ€ĐžĐ´ŅƒĐēŅ‚Đ¸Đ˛ĐŊŅ–ŅŅ‚ŅŒ ĐŋŅ€ĐžĐŗŅ€Đ°Đŧи, Đ´ĐžĐēи ĐēĐĩ҈ ĐŊĐĩ ĐąŅƒĐ´Đĩ ĐŋĐĩŅ€ĐĩĐąŅƒĐ´ĐžĐ˛Đ°ĐŊĐž.", "cache_settings_duplicated_assets_clear_button": "ОЧИСĐĸИĐĸИ", - "cache_settings_duplicated_assets_subtitle": "Đ¤ĐžŅ‚Đž Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž, ŅĐēŅ– Đ´ĐžĐ´Đ°Ņ‚ĐžĐē Ņ–ĐŗĐŊĐžŅ€ŅƒŅ”", + "cache_settings_duplicated_assets_subtitle": "Đ¤ĐžŅ‚Đž Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž, ŅĐēŅ– Ņ–ĐŗĐŊĐžŅ€ŅƒŅŽŅ‚ŅŒŅŅ ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐēĐžĐŧ", "cache_settings_duplicated_assets_title": "Đ”ŅƒĐąĐģŅŒĐžĐ˛Đ°ĐŊŅ– ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ ({count})", "cache_settings_statistics_album": "Đ‘Ņ–ĐąĐģŅ–ĐžŅ‚Đĩ҇ĐŊŅ– ĐŧŅ–ĐŊŅ–Đ°Ņ‚ŅŽŅ€Đ¸", "cache_settings_statistics_full": "ПовĐŊĐžŅ€ĐˇĐžĐŧŅ–Ņ€ĐŊŅ– ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ", @@ -656,9 +668,11 @@ "change_pin_code": "ЗĐŧŅ–ĐŊĐ¸Ņ‚Đ¸ PIN-ĐēОд", "change_your_password": "ЗĐŧŅ–ĐŊŅ–Ņ‚ŅŒ ŅĐ˛Ņ–Đš ĐŋĐ°Ņ€ĐžĐģҌ", "changed_visibility_successfully": "ВидиĐŧŅ–ŅŅ‚ŅŒ ҃ҁĐŋŅ–ŅˆĐŊĐž СĐŧŅ–ĐŊĐĩĐŊĐž", - "check_corrupt_asset_backup": "ПĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đ¸Ņ‚Đ¸ ĐŊа ĐŋĐžŅˆĐēОдĐļĐĩĐŊŅ– Ņ€ĐĩСĐĩŅ€Đ˛ĐŊŅ– ĐēĐžĐŋŅ–Ņ— аĐēŅ‚Đ¸Đ˛Ņ–Đ˛", + "charging": "Đ—Đ°Ņ€ŅĐ´Đēа", + "charging_requirement_mobile_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": "ĐœŅ–ŅŅ‚Đž", @@ -691,7 +705,7 @@ "completed": "ЗавĐĩŅ€ŅˆĐĩĐŊĐž", "confirm": "ĐŸŅ–Đ´Ņ‚Đ˛ĐĩŅ€Đ´Ņ–Ņ‚ŅŒ", "confirm_admin_password": "ĐŸŅ–Đ´Ņ‚Đ˛ĐĩŅ€Đ´Đ¸Ņ‚Đ¸ ĐŋĐ°Ņ€ĐžĐģҌ адĐŧŅ–ĐŊŅ–ŅŅ‚Ņ€Đ°Ņ‚ĐžŅ€Đ°", - "confirm_delete_face": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ ОйĐģĐ¸Ņ‡Ņ‡Ņ {name} С аĐēŅ‚Đ¸Đ˛Ņƒ?", + "confirm_delete_face": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ ОйĐģĐ¸Ņ‡Ņ‡Ņ {name} С ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņƒ?", "confirm_delete_shared_link": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ ҆Đĩ ҁĐŋŅ–ĐģҌĐŊĐĩ ĐŋĐžŅĐ¸ĐģаĐŊĐŊŅ?", "confirm_keep_this_delete_others": "ĐŖŅŅ– Ņ–ĐŊŅˆŅ– Ņ€ĐĩŅŅƒŅ€ŅĐ¸ в ҁ҂ĐĩĐē҃ ĐąŅƒĐ´Đĩ видаĐģĐĩĐŊĐž, ĐžĐēҀҖĐŧ Ņ†ŅŒĐžĐŗĐž Ņ€ĐĩŅŅƒŅ€ŅŅƒ. Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐŋŅ€ĐžĐ´ĐžĐ˛ĐļĐ¸Ņ‚Đ¸?", "confirm_new_pin_code": "ĐŸŅ–Đ´Ņ‚Đ˛ĐĩŅ€Đ´ŅŒŅ‚Đĩ ĐŊОвиК PIN-ĐēОд", @@ -732,7 +746,7 @@ "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_select_photos": "Đ’Đ¸ĐąŅ€Đ°Ņ‚Đ¸ Ņ„ĐžŅ‚Đž", @@ -742,6 +756,7 @@ "create_user": "ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ°", "created": "ĐĄŅ‚Đ˛ĐžŅ€ĐĩĐŊĐž", "created_at": "ĐĄŅ‚Đ˛ĐžŅ€ĐĩĐŊĐž", + "creating_linked_albums": "ĐĄŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ ĐŋĐžĐ˛â€™ŅĐˇĐ°ĐŊĐ¸Ņ… аĐģŅŒĐąĐžĐŧŅ–Đ˛...", "crop": "ĐšĐ°Đ´Ņ€ŅƒĐ˛Đ°Ņ‚Đ¸", "curated_object_page_title": "Đ Đĩ҇Җ", "current_device": "ĐŸĐžŅ‚ĐžŅ‡ĐŊиК ĐŋŅ€Đ¸ŅŅ‚Ņ€Ņ–Đš", @@ -797,7 +812,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": "ПоĐŧиĐģĐēа ĐžĐŊОвĐģĐĩĐŊĐŊŅ ĐžĐŋĐ¸ŅŅƒ, ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Ņ‚Đĩ ĐģĐžĐŗĐ¸ Đ´ĐģŅ ĐŋĐžĐ´Ņ€ĐžĐąĐ¸Ņ†ŅŒ", @@ -877,8 +892,8 @@ "email": "ЕĐģĐĩĐēŅ‚Ņ€ĐžĐŊĐŊа ĐŋĐžŅˆŅ‚Đ°", "email_notifications": "ĐĄĐŋĐžĐ˛Ņ–Ņ‰ĐĩĐŊĐŊŅ ĐĩĐģ. ĐŋĐžŅˆŅ‚ĐžŅŽ", "empty_folder": "ĐĻŅ ĐŋаĐŋĐēа ĐŋĐžŅ€ĐžĐļĐŊŅ", - "empty_trash": "ĐžŅ‡Đ¸ŅŅ‚Đ¸Ņ‚Đ¸ ҁĐŧŅ–Ņ‚ĐŊиĐē", - "empty_trash_confirmation": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐžŅ‡Đ¸ŅŅ‚Đ¸Ņ‚Đ¸ ҁĐŧŅ–Ņ‚ĐŊиĐē? ĐĻĐĩ ĐžŅŅ‚Đ°Ņ‚ĐžŅ‡ĐŊĐž видаĐģĐ¸Ņ‚ŅŒ Đ˛ŅŅ– Ņ€ĐĩŅŅƒŅ€ŅĐ¸ в ҁĐŧŅ–Ņ‚ĐŊиĐē҃ С Immich.\nĐĻŅŽ Đ´Ņ–ŅŽ ĐŊĐĩ ĐŧĐžĐļĐŊа ҁĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸!", + "empty_trash": "ĐžŅ‡Đ¸ŅŅ‚Đ¸Ņ‚Đ¸ ĐēĐžŅˆĐ¸Đē", + "empty_trash_confirmation": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐžŅ‡Đ¸ŅŅ‚Đ¸Ņ‚Đ¸ ĐēĐžŅˆĐ¸Đē? ĐĻĐĩ ĐžŅŅ‚Đ°Ņ‚ĐžŅ‡ĐŊĐž видаĐģĐ¸Ņ‚ŅŒ Đ˛ŅŅ– Ņ€ĐĩŅŅƒŅ€ŅĐ¸ в ĐēĐžŅˆĐ¸Đē҃ С Immich.\nĐĻŅŽ Đ´Ņ–ŅŽ ĐŊĐĩ ĐŧĐžĐļĐŊа ҁĐēĐ°ŅŅƒĐ˛Đ°Ņ‚Đ¸!", "enable": "ĐŖĐ˛Ņ–ĐŧĐēĐŊŅƒŅ‚Đ¸", "enable_backup": "ĐŖĐ˛Ņ–ĐŧĐēĐŊŅƒŅ‚Đ¸ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐĩ ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ", "enable_biometric_auth_description": "ВвĐĩĐ´Ņ–Ņ‚ŅŒ ŅĐ˛Ņ–Đš PIN-ĐēОд, Ņ‰ĐžĐą ŅƒĐ˛Ņ–ĐŧĐēĐŊŅƒŅ‚Đ¸ ĐąŅ–ĐžĐŧĐĩŅ‚Ņ€Đ¸Ņ‡ĐŊ҃ Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–ŅŽ", @@ -890,8 +905,10 @@ "enter_your_pin_code_subtitle": "ВвĐĩĐ´Ņ–Ņ‚ŅŒ ŅĐ˛Ņ–Đš PIN-ĐēОд, Ņ‰ĐžĐą ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ Đ´ĐžŅŅ‚ŅƒĐŋ Đ´Đž ĐžŅĐžĐąĐ¸ŅŅ‚ĐžŅ— ĐŋаĐŋĐēи", "error": "ПоĐŧиĐģĐēа", "error_change_sort_album": "НĐĩ вдаĐģĐžŅŅ СĐŧŅ–ĐŊĐ¸Ņ‚Đ¸ ĐŋĐžŅ€ŅĐ´ĐžĐē ŅĐžŅ€Ņ‚ŅƒĐ˛Đ°ĐŊĐŊŅ аĐģŅŒĐąĐžĐŧ҃", - "error_delete_face": "ПоĐŧиĐģĐēа ĐŋŅ€Đ¸ видаĐģĐĩĐŊĐŊŅ– ОйĐģĐ¸Ņ‡Ņ‡Ņ С аĐēŅ‚Đ¸Đ˛Ņƒ", + "error_delete_face": "ПоĐŧиĐģĐēа ĐŋŅ€Đ¸ видаĐģĐĩĐŊĐŊŅ– ОйĐģĐ¸Ņ‡Ņ‡Ņ С ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņƒ", + "error_getting_places": "ПоĐŧиĐģĐēа ĐžŅ‚Ņ€Đ¸ĐŧаĐŊĐŊŅ ĐŧŅ–ŅŅ†ŅŒ", "error_loading_image": "ПоĐŧиĐģĐēа СаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ", + "error_loading_partners": "ПоĐŧиĐģĐēа СаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ ĐŋĐ°Ņ€Ņ‚ĐŊĐĩŅ€Ņ–Đ˛: {error}", "error_saving_image": "ПоĐŧиĐģĐēа: {error}", "error_tag_face_bounding_box": "ПоĐŧиĐģĐēа ĐŋŅ–Đ´ Ņ‡Đ°Ņ ĐŋОСĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ОйĐģĐ¸Ņ‡Ņ‡Ņ – ĐŊĐĩ вдаĐģĐžŅŅ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ ĐēĐžĐžŅ€Đ´Đ¸ĐŊĐ°Ņ‚Đ¸ Ņ€Đ°ĐŧĐēи", "error_title": "ПоĐŧиĐģĐēа: Ņ‰ĐžŅŅŒ ĐŋŅ–ŅˆĐģĐž ĐŊĐĩ Ņ‚Đ°Đē", @@ -967,7 +984,7 @@ "unable_to_download_files": "НĐĩĐŧĐžĐļĐģивО СаваĐŊŅ‚Đ°ĐļĐ¸Ņ‚Đ¸ Ņ„Đ°ĐšĐģи", "unable_to_edit_exclusion_pattern": "НĐĩ вдаĐģĐžŅŅ Ņ€ĐĩĐ´Đ°ĐŗŅƒĐ˛Đ°Ņ‚Đ¸ ŅˆĐ°ĐąĐģĐžĐŊ виĐēĐģŅŽŅ‡ĐĩĐŊĐŊŅ", "unable_to_edit_import_path": "НĐĩĐŧĐžĐļĐģивО Đ˛Ņ–Đ´Ņ€ĐĩĐ´Đ°ĐŗŅƒĐ˛Đ°Ņ‚Đ¸ ҈ĐģŅŅ… Ņ–ĐŧĐŋĐžŅ€Ņ‚Ņƒ", - "unable_to_empty_trash": "НĐĩĐŧĐžĐļĐģивО ĐžŅ‡Đ¸ŅŅ‚Đ¸Ņ‚Đ¸ ҁĐŧŅ–Ņ‚ĐŊиĐē", + "unable_to_empty_trash": "НĐĩĐŧĐžĐļĐģивО ĐžŅ‡Đ¸ŅŅ‚Đ¸Ņ‚Đ¸ ĐēĐžŅˆĐ¸Đē", "unable_to_enter_fullscreen": "НĐĩĐŧĐžĐļĐģивО ŅƒĐ˛Ņ–ĐšŅ‚Đ¸ в ĐŋОвĐŊĐžĐĩĐēŅ€Đ°ĐŊĐŊиК Ņ€ĐĩĐļиĐŧ", "unable_to_exit_fullscreen": "НĐĩĐŧĐžĐļĐģивО Đ˛Đ¸ĐšŅ‚Đ¸ С ĐŋОвĐŊĐžĐĩĐēŅ€Đ°ĐŊĐŊĐžĐŗĐž Ņ€ĐĩĐļиĐŧ҃", "unable_to_get_comments_number": "НĐĩ вдаĐģĐžŅŅ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ ĐēŅ–ĐģҌĐēŅ–ŅŅ‚ŅŒ ĐēĐžĐŧĐĩĐŊŅ‚Đ°Ņ€Ņ–Đ˛", @@ -991,7 +1008,7 @@ "unable_to_reset_password": "НĐĩ Đ˛Đ´Đ°Ņ”Ņ‚ŅŒŅŅ ҁĐēиĐŊŅƒŅ‚Đ¸ ĐŋĐ°Ņ€ĐžĐģҌ", "unable_to_reset_pin_code": "НĐĩĐŧĐžĐļĐģивО ҁĐēиĐŊŅƒŅ‚Đ¸ PIN-ĐēОд", "unable_to_resolve_duplicate": "НĐĩ Đ˛Đ´Đ°Ņ”Ņ‚ŅŒŅŅ Đ˛Đ¸Ņ€Ņ–ŅˆĐ¸Ņ‚Đ¸ Đ´ŅƒĐąĐģŅ–ĐēĐ°Ņ‚", - "unable_to_restore_assets": "НĐĩĐŧĐžĐļĐģивО Đ˛Ņ–Đ´ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ аĐēŅ‚Đ¸Đ˛Đ¸", + "unable_to_restore_assets": "НĐĩĐŧĐžĐļĐģивО Đ˛Ņ–Đ´ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸", "unable_to_restore_trash": "НĐĩ вдаĐģĐžŅŅ Đ˛Ņ–Đ´ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ вĐŧҖҁ҂", "unable_to_restore_user": "НĐĩ Đ˛Đ´Đ°Ņ”Ņ‚ŅŒŅŅ Đ˛Ņ–Đ´ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ°", "unable_to_save_album": "НĐĩ Đ˛Đ´Đ°Ņ”Ņ‚ŅŒŅŅ СйĐĩŅ€ĐĩĐŗŅ‚Đ¸ аĐģŅŒĐąĐžĐŧ", @@ -1005,7 +1022,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": "НĐĩĐŧĐžĐļĐģивО ĐžĐŊĐžĐ˛Đ¸Ņ‚Đ¸ ОйĐēĐģадиĐŊĐē҃ аĐģŅŒĐąĐžĐŧ҃", @@ -1022,6 +1039,7 @@ "exif_bottom_sheet_description_error": "ПоĐŧиĐģĐēа ĐŋŅ–Đ´ Ņ‡Đ°Ņ ĐžĐŊОвĐģĐĩĐŊĐŊŅ ĐžĐŋĐ¸ŅŅƒ", "exif_bottom_sheet_details": "ПОДРОБИĐĻІ", "exif_bottom_sheet_location": "МІСĐĻЕ", + "exif_bottom_sheet_no_description": "БĐĩС ĐžĐŋĐ¸ŅŅƒ", "exif_bottom_sheet_people": "ЛЮДИ", "exif_bottom_sheet_person_add_person": "Đ”ĐžĐ´Đ°Ņ‚Đ¸ Ņ–Đŧ'Ņ", "exit_slideshow": "Đ’Đ¸ĐšŅ‚Đ¸ ĐˇŅ– ҁĐģаКд-ŅˆĐžŅƒ", @@ -1043,7 +1061,7 @@ "external": "ЗовĐŊŅ–ŅˆĐŊŅ–", "external_libraries": "ЗовĐŊŅ–ŅˆĐŊŅ– ĐąŅ–ĐąĐģŅ–ĐžŅ‚ĐĩĐēи", "external_network": "ЗовĐŊŅ–ŅˆĐŊŅ ĐŧĐĩŅ€ĐĩĐļа", - "external_network_sheet_info": "КоĐģи ви ĐŊĐĩ ĐŋŅ–Đ´ĐēĐģŅŽŅ‡ĐĩĐŊŅ– Đ´Đž ĐŋĐĩŅ€ĐĩваĐļĐŊĐžŅ— ĐŧĐĩŅ€ĐĩĐļŅ– Wi-Fi, Đ´ĐžĐ´Đ°Ņ‚ĐžĐē ĐŋŅ–Đ´ĐēĐģŅŽŅ‡Đ°Ņ‚Đ¸ĐŧĐĩŅ‚ŅŒŅŅ Đ´Đž ҁĐĩŅ€Đ˛ĐĩŅ€Đ° ҇ĐĩŅ€ĐĩС ĐŋĐĩŅ€ŅˆŅƒ С ĐŊавĐĩĐ´ĐĩĐŊĐ¸Ņ… ĐŊиĐļ҇Đĩ URL-Đ°Đ´Ņ€Đĩҁ, ŅĐē҃ Đ˛Ņ–ĐŊ СĐŧĐžĐļĐĩ Đ´ĐžŅŅĐŗŅ‚Đ¸, ĐŋĐžŅ‡Đ¸ĐŊĐ°ŅŽŅ‡Đ¸ СвĐĩŅ€Ņ…Ņƒ вĐŊиС", + "external_network_sheet_info": "КоĐģи ви ĐŊĐĩ ĐŋŅ–Đ´ĐēĐģŅŽŅ‡ĐĩĐŊŅ– Đ´Đž ĐžĐąŅ€Đ°ĐŊĐžŅ— ĐŧĐĩŅ€ĐĩĐļŅ– Wi-Fi, ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐžĐē ĐŋŅ–Đ´ĐēĐģŅŽŅ‡Đ°Ņ‚Đ¸ĐŧĐĩŅ‚ŅŒŅŅ Đ´Đž ҁĐĩŅ€Đ˛ĐĩŅ€Đ° ҇ĐĩŅ€ĐĩС ĐŋĐĩŅ€ŅˆŅƒ С ĐŊавĐĩĐ´ĐĩĐŊĐ¸Ņ… ĐŊиĐļ҇Đĩ URL-Đ°Đ´Ņ€Đĩҁ, ŅĐē҃ Đ˛Ņ–ĐŊ СĐŧĐžĐļĐĩ Đ´ĐžŅŅĐŗŅ‚Đ¸, ĐŋĐžŅ‡Đ¸ĐŊĐ°ŅŽŅ‡Đ¸ СвĐĩŅ€Ņ…Ņƒ вĐŊиС", "face_unassigned": "НĐĩ ĐŋŅ€Đ¸ĐˇĐŊĐ°Ņ‡ĐĩĐŊĐž", "failed": "НĐĩ вдаĐģĐžŅŅ", "failed_to_authenticate": "ПоĐŧиĐģĐēа Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ—", @@ -1056,7 +1074,8 @@ "favorites_page_no_favorites": "НĐĩĐŧĐ°Ņ” ҃ĐģŅŽĐąĐģĐĩĐŊĐ¸Ņ… ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛", "feature_photo_updated": "Đ’Đ¸ĐąŅ€Đ°ĐŊĐĩ Ņ„ĐžŅ‚Đž ĐžĐŊОвĐģĐĩĐŊĐž", "features": "Đ”ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– ĐŧĐžĐļĐģĐ¸Đ˛ĐžŅŅ‚Ņ–", - "features_setting_description": "КĐĩŅ€ŅƒĐ˛Đ°ĐŊĐŊŅ Đ´ĐžĐ´Đ°Ņ‚ĐēОвиĐŧи ĐŧĐžĐļĐģĐ¸Đ˛ĐžŅŅ‚ŅĐŧи Đ´ĐžĐ´Đ°Ņ‚Đēа", + "features_in_development": "Đ¤ŅƒĐŊĐē҆Җҗ в Ņ€ĐžĐˇŅ€ĐžĐąŅ†Ņ–", + "features_setting_description": "КĐĩŅ€ŅƒĐ˛Đ°ĐŊĐŊŅ Đ´ĐžĐ´Đ°Ņ‚ĐēОвиĐŧи ĐŧĐžĐļĐģĐ¸Đ˛ĐžŅŅ‚ŅĐŧи ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐē҃", "file_name": "ІĐŧ'Ņ Ņ„Đ°ĐšĐģ҃", "file_name_or_extension": "ІĐŧ'Ņ Ņ„Đ°ĐšĐģ҃ айО Ņ€ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊĐŊŅ", "filename": "ІĐŧ'Ņ Ņ„Đ°ĐšĐģ҃", @@ -1076,10 +1095,7 @@ "gcast_enabled": "Google Cast'", "gcast_enabled_description": "ĐĻŅ Ņ„ŅƒĐŊĐēŅ†Ņ–Ņ СаваĐŊŅ‚Đ°ĐļŅƒŅ” СОвĐŊŅ–ŅˆĐŊŅ– Ņ€ĐĩŅŅƒŅ€ŅĐ¸ С Google Đ´ĐģŅ ŅĐ˛ĐžŅ”Ņ— Ņ€ĐžĐąĐžŅ‚Đ¸.", "general": "Đ—Đ°ĐŗĐ°ĐģҌĐŊŅ–", - "geolocation_instruction_all_have_location": "ĐŖŅŅ– ĐžĐąâ€™Ņ”ĐēŅ‚Đ¸ Đ´ĐģŅ ҆ҖҔҗ Đ´Đ°Ņ‚Đ¸ вĐļĐĩ ĐŧĐ°ŅŽŅ‚ŅŒ даĐŊŅ– ĐŋŅ€Đž ĐŧҖҁ҆ĐĩСĐŊĐ°Ņ…ĐžĐ´ĐļĐĩĐŊĐŊŅ. ĐĄĐŋŅ€ĐžĐąŅƒĐšŅ‚Đĩ ĐŋĐžĐēĐ°ĐˇĐ°Ņ‚Đ¸ Đ˛ŅŅ– ĐžĐąâ€™Ņ”ĐēŅ‚Đ¸ айО вийĐĩŅ€Ņ–Ņ‚ŅŒ Ņ–ĐŊ҈҃ Đ´Đ°Ņ‚Ņƒ", "geolocation_instruction_location": "ĐĐ°Ņ‚Đ¸ŅĐŊŅ–Ņ‚ŅŒ ĐŊа Ой'Ņ”ĐēŅ‚ Ņ–Đˇ GPS-ĐēĐžĐžŅ€Đ´Đ¸ĐŊĐ°Ņ‚Đ°Đŧи, Ņ‰ĐžĐą виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ ĐšĐžĐŗĐž ĐŧҖҁ҆ĐĩСĐŊĐ°Ņ…ĐžĐ´ĐļĐĩĐŊĐŊŅ, айО вийĐĩŅ€Ņ–Ņ‚ŅŒ ĐŧҖҁ҆ĐĩСĐŊĐ°Ņ…ĐžĐ´ĐļĐĩĐŊĐŊŅ ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž ĐŊа ĐēĐ°Ņ€Ņ‚Ņ–", - "geolocation_instruction_no_date": "ВибĐĩŅ€Ņ–Ņ‚ŅŒ Đ´Đ°Ņ‚Ņƒ Đ´ĐģŅ ĐēĐĩŅ€ŅƒĐ˛Đ°ĐŊĐŊŅ даĐŊиĐŧи ĐŋŅ€Đž ĐŧҖҁ҆ĐĩСĐŊĐ°Ņ…ĐžĐ´ĐļĐĩĐŊĐŊŅ Đ´ĐģŅ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Ņ–Đš Ņ– Đ˛Ņ–Đ´ĐĩĐž Са ҆ĐĩĐš Đ´ĐĩĐŊҌ", - "geolocation_instruction_no_photos": "ДĐģŅ ҆ҖҔҗ Đ´Đ°Ņ‚Đ¸ ĐŊĐĩ СĐŊаКдĐĩĐŊĐž Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Ņ–Đš Ņ‡Đ¸ Đ˛Ņ–Đ´ĐĩĐž. ВибĐĩŅ€Ņ–Ņ‚ŅŒ Ņ–ĐŊ҈҃ Đ´Đ°Ņ‚Ņƒ, Ņ‰ĐžĐą ĐŋĐžĐēĐ°ĐˇĐ°Ņ‚Đ¸ Ņ—Ņ…", "get_help": "ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ Đ´ĐžĐŋĐžĐŧĐžĐŗŅƒ", "get_wifiname_error": "НĐĩ вдаĐģĐžŅŅ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ ĐŊĐ°ĐˇĐ˛Ņƒ Wi-Fi. ПĐĩŅ€ĐĩĐēĐžĐŊĐ°ĐšŅ‚ĐĩŅŅ, Ņ‰Đž ви ĐŊадаĐģи ĐŊĐĩĐžĐąŅ…Ņ–Đ´ĐŊŅ– дОСвОĐģи Ņ‚Đ° ĐŋŅ–Đ´ĐēĐģŅŽŅ‡ĐĩĐŊŅ– Đ´Đž Wi-Fi ĐŧĐĩŅ€ĐĩĐļŅ–", "getting_started": "ĐŸĐžŅ‡Đ°Ņ‚ĐžĐē", @@ -1099,7 +1115,7 @@ "haptic_feedback_title": "ĐĸаĐēŅ‚Đ¸ĐģҌĐŊа Đ˛Ņ–Đ´Đ´Đ°Ņ‡Đ°", "has_quota": "ĐšĐ˛ĐžŅ‚Đ°", "hash_asset": "ГĐĩŅˆŅƒĐ˛Đ°Ņ‚Đ¸ Ņ„Đ°ĐšĐģ", - "hashed_assets": "ГĐĩŅˆĐžĐ˛Đ°ĐŊŅ– Ņ„ĐžŅ‚Đž Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž", + "hashed_assets": "ĐĨĐĩŅˆĐ¸", "hashing": "ĐĨĐĩŅˆŅƒĐ˛Đ°ĐŊĐŊŅ", "header_settings_add_header_tip": "Đ”ĐžĐ´Đ°Ņ‚Đ¸ ĐˇĐ°ĐŗĐžĐģОвОĐē", "header_settings_field_validator_msg": "ЗĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐŊĐĩ ĐŧĐžĐļĐĩ ĐąŅƒŅ‚Đ¸ ĐŋĐžŅ€ĐžĐļĐŊŅ–Đŧ", @@ -1125,7 +1141,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_locked_error_local": "НĐĩ Đ˛Đ´Đ°Ņ”Ņ‚ŅŒŅŅ ĐŋĐĩŅ€ĐĩĐŧŅ–ŅŅ‚Đ¸Ņ‚Đ¸ ĐģĐžĐēаĐģҌĐŊŅ– Ņ„Đ°ĐšĐģи Đ´Đž ĐžŅĐžĐąĐ¸ŅŅ‚ĐžŅ— ĐŋаĐŋĐēи, ĐŋŅ€ĐžĐŋ҃ҁĐēĐ°Ņ”Ņ‚ŅŒŅŅ", "home_page_locked_error_partner": "НĐĩ Đ˛Đ´Đ°Ņ”Ņ‚ŅŒŅŅ ĐŋĐĩŅ€ĐĩĐŧŅ–ŅŅ‚Đ¸Ņ‚Đ¸ ĐŋĐ°Ņ€Ņ‚ĐŊĐĩŅ€ŅŅŒĐēŅ– Ņ„Đ°ĐšĐģи Đ´Đž ĐžŅĐžĐąĐ¸ŅŅ‚ĐžŅ— ĐŋаĐŋĐēи, ĐŋŅ€ĐžĐŋ҃ҁĐēĐ°Ņ”Ņ‚ŅŒŅŅ", "home_page_share_err_local": "НĐĩĐŧĐžĐļĐģивО ĐŋĐžĐ´Ņ–ĐģĐ¸Ņ‚Đ¸ŅŅ ĐģĐžĐēаĐģҌĐŊиĐŧи ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ°Đŧи ҇ĐĩŅ€ĐĩС ĐŋĐžŅĐ¸ĐģаĐŊĐŊŅ, ĐŋŅ€ĐžĐŋŅƒŅ‰ĐĩĐŊĐž", @@ -1160,7 +1176,7 @@ "in_archive": "В Đ°Ņ€Ņ…Ņ–Đ˛Ņ–", "include_archived": "Đ’Ņ–Đ´ĐžĐąŅ€Đ°ĐļĐ°Ņ‚Đ¸ Đ°Ņ€Ņ…Ņ–Đ˛", "include_shared_albums": "ВĐēĐģŅŽŅ‡Đ¸Ņ‚Đ¸ ҁĐŋŅ–ĐģҌĐŊŅ– аĐģŅŒĐąĐžĐŧи", - "include_shared_partner_assets": "ВĐēĐģŅŽŅ‡Đ°ĐšŅ‚Đĩ ҁĐŋŅ–ĐģҌĐŊŅ– ĐŋĐ°Ņ€Ņ‚ĐŊĐĩŅ€ŅŅŒĐēŅ– аĐēŅ‚Đ¸Đ˛Đ¸", + "include_shared_partner_assets": "ВĐēĐģŅŽŅ‡Đ°ĐšŅ‚Đĩ ҁĐŋŅ–ĐģҌĐŊŅ– ĐŋĐ°Ņ€Ņ‚ĐŊĐĩŅ€ŅŅŒĐēŅ– Ņ€ĐĩŅŅƒŅ€ŅĐ¸", "individual_share": "ІĐŊĐ´Đ¸Đ˛Ņ–Đ´ŅƒĐ°ĐģҌĐŊиК Đ´ĐžŅŅ‚ŅƒĐŋ", "individual_shares": "ОĐēŅ€ĐĩĐŧŅ– ҁĐŋŅ–ĐģҌĐŊŅ– Đ´ĐžŅŅ‚ŅƒĐŋи", "info": "ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ", @@ -1223,8 +1239,9 @@ "local": "На ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅ—", "local_asset_cast_failed": "НĐĩĐŧĐžĐļĐģивО Ņ‚Ņ€Đ°ĐŊҁĐģŅŽĐ˛Đ°Ņ‚Đ¸ Ņ€ĐĩŅŅƒŅ€Ņ, ŅĐēиК ĐŊĐĩ СаваĐŊŅ‚Đ°ĐļĐĩĐŊĐž ĐŊа ҁĐĩŅ€Đ˛ĐĩŅ€", "local_assets": "ЛоĐēаĐģҌĐŊŅ– Ņ„ĐžŅ‚Đž Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž", + "local_media_summary": "ЗвĐĩĐ´ĐĩĐŊĐŊŅ ĐŧҖҁ҆ĐĩĐ˛Đ¸Ņ… ЗМІ", "local_network": "ЛоĐēаĐģҌĐŊа ĐŧĐĩŅ€ĐĩĐļа", - "local_network_sheet_info": "Đ”ĐžĐ´Đ°Ņ‚ĐžĐē ĐŋŅ–Đ´ĐēĐģŅŽŅ‡Đ°Ņ‚Đ¸ĐŧĐĩŅ‚ŅŒŅŅ Đ´Đž ҁĐĩŅ€Đ˛ĐĩŅ€Đ° ҇ĐĩŅ€ĐĩС ҆ĐĩĐš URL, ĐēĐžĐģи виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ вĐēаСаĐŊа Wi-Fi ĐŧĐĩŅ€ĐĩĐļа", + "local_network_sheet_info": "Đ—Đ°ŅŅ‚ĐžŅŅƒĐŊĐžĐē ĐŋŅ–Đ´ĐēĐģŅŽŅ‡Đ°Ņ‚Đ¸ĐŧĐĩŅ‚ŅŒŅŅ Đ´Đž ҁĐĩŅ€Đ˛ĐĩŅ€Đ° ҇ĐĩŅ€ĐĩС ҆ĐĩĐš URL, ĐēĐžĐģи виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ вĐēаСаĐŊа Wi-Fi ĐŧĐĩŅ€ĐĩĐļа", "location_permission": "Đ”ĐžĐˇĐ˛Ņ–Đģ Đ´Đž ĐŧҖҁ҆ĐĩСĐŊĐ°Ņ…ĐžĐ´ĐļĐĩĐŊĐŊŅ", "location_permission_content": "ЊОй ĐŋĐĩŅ€ĐĩĐŧиĐēĐ°Ņ‚Đ¸ ĐŧĐĩŅ€ĐĩĐļŅ– ҃ Ņ„ĐžĐŊОвОĐŧ҃ Ņ€ĐĩĐļиĐŧŅ–, Immich ĐŧĐ°Ņ” СавĐļди ĐŧĐ°Ņ‚Đ¸ Đ´ĐžŅŅ‚ŅƒĐŋ Đ´Đž Ņ‚ĐžŅ‡ĐŊĐžŅ— ĐŗĐĩĐžĐģĐžĐēĐ°Ņ†Ņ–Ņ—, Ņ‰ĐžĐą ĐˇŅ‡Đ¸Ņ‚ŅƒĐ˛Đ°Ņ‚Đ¸ ĐŊĐ°ĐˇĐ˛Ņƒ Wi-Fi ĐŧĐĩŅ€ĐĩĐļŅ–", "location_picker_choose_on_map": "ĐžĐąŅ€Đ°Ņ‚Đ¸ ĐŊа ĐŧаĐŋŅ–", @@ -1234,6 +1251,7 @@ "location_picker_longitude_hint": "ВĐēаĐļŅ–Ņ‚ŅŒ Đ´ĐžĐ˛ĐŗĐžŅ‚Ņƒ", "lock": "ЗабĐģĐžĐēŅƒĐ˛Đ°Ņ‚Đ¸", "locked_folder": "ĐžŅĐžĐąĐ¸ŅŅ‚Đ° ĐŋаĐŋĐēа", + "log_detail_title": "ДĐĩŅ‚Đ°ĐģŅ– ĐļŅƒŅ€ĐŊаĐģ҃", "log_out": "Đ’Đ¸ĐšŅ‚Đ¸", "log_out_all_devices": "Đ’Đ¸ĐšŅ‚Đ¸ С ŅƒŅŅ–Ņ… ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅ—Đ˛", "logged_in_as": "Đ’Ņ…Ņ–Đ´ виĐēĐžĐŊаĐŊĐž ŅĐē {user}", @@ -1264,6 +1282,7 @@ "login_password_changed_success": "ĐŸĐ°Ņ€ĐžĐģҌ ĐžĐŊОвĐģĐĩĐŊĐž ҃ҁĐŋŅ–ŅˆĐŊĐž", "logout_all_device_confirmation": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ Đ˛Đ¸ĐšŅ‚Đ¸ С ŅƒŅŅ–Ņ… ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅ—Đ˛?", "logout_this_device_confirmation": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ Đ˛Đ¸ĐšŅ‚Đ¸ С Ņ†ŅŒĐžĐŗĐž ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅŽ?", + "logs": "Đ–ŅƒŅ€ĐŊаĐģи", "longitude": "Đ”ĐžĐ˛ĐŗĐžŅ‚Đ°", "look": "Đ”Đ¸Đ˛Đ¸Ņ‚Đ¸ŅŅ", "loop_videos": "ĐĻиĐēĐģҖ҇ĐŊŅ– Đ˛Ņ–Đ´ĐĩĐž", @@ -1306,6 +1325,7 @@ "mark_as_read": "ПозĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ ŅĐē ĐŋŅ€ĐžŅ‡Đ¸Ņ‚Đ°ĐŊĐĩ", "marked_all_as_read": "ПозĐŊĐ°Ņ‡ĐĩĐŊĐž Đ˛ŅŅ– ŅĐē ĐŋŅ€ĐžŅ‡Đ¸Ņ‚Đ°ĐŊŅ–", "matches": "Đ—ĐąŅ–ĐŗĐ¸", + "matching_assets": "Đ’Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐŊŅ– аĐēŅ‚Đ¸Đ˛Đ¸", "media_type": "ĐĸиĐŋ ĐŧĐĩĐ´Ņ–Đ°", "memories": "ĐĄĐŋĐžĐŗĐ°Đ´Đ¸", "memories_all_caught_up": "ĐĻĐĩ Đ˛ŅĐĩ ĐŊа ŅŅŒĐžĐŗĐžĐ´ĐŊŅ–", @@ -1335,9 +1355,9 @@ "move_to_lock_folder_action_prompt": "{count} дОдаĐŊĐž Đ´Đž ĐˇĐ°Ņ…Đ¸Ņ‰ĐĩĐŊĐžŅ— Ņ‚ĐĩĐēи", "move_to_locked_folder": "ПĐĩŅ€ĐĩĐŧŅ–ŅŅ‚Đ¸Ņ‚Đ¸ Đ´Đž ĐžŅĐžĐąĐ¸ŅŅ‚ĐžŅ— ĐŋаĐŋĐēи", "move_to_locked_folder_confirmation": "ĐĻŅ– Ņ„ĐžŅ‚Đž Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž ĐąŅƒĐ´Đĩ видаĐģĐĩĐŊĐž ĐˇŅ– Đ˛ŅŅ–Ņ… аĐģŅŒĐąĐžĐŧŅ–Đ˛ Ņ– Ņ—Ņ… ĐŧĐžĐļĐŊа ĐąŅƒĐ´Đĩ ĐŋĐĩŅ€ĐĩĐŗĐģŅĐ´Đ°Ņ‚Đ¸ ĐģĐ¸ŅˆĐĩ в ĐžŅĐžĐąĐ¸ŅŅ‚Ņ–Đš ĐŋаĐŋ҆Җ", - "moved_to_archive": "ПĐĩŅ€ĐĩĐŧҖ҉ĐĩĐŊĐž {count, plural, one {# аĐēŅ‚Đ¸Đ˛} other {# аĐēŅ‚Đ¸Đ˛Ņ–Đ˛}} в Đ°Ņ€Ņ…Ņ–Đ˛", - "moved_to_library": "ПĐĩŅ€ĐĩĐŧҖ҉ĐĩĐŊĐž {count, plural, one {# аĐēŅ‚Đ¸Đ˛} other {# аĐēŅ‚Đ¸Đ˛Ņ–Đ˛}} в ĐąŅ–ĐąĐģŅ–ĐžŅ‚ĐĩĐē҃", - "moved_to_trash": "ПĐĩŅ€ĐĩĐŊĐĩҁĐĩĐŊĐž Đ´Đž ҁĐŧŅ–Ņ‚ĐŊиĐēа", + "moved_to_archive": "ПĐĩŅ€ĐĩĐŧҖ҉ĐĩĐŊĐž {count, plural, one {# ĐĩĐģĐĩĐŧĐĩĐŊŅ‚} other {# ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛}} в Đ°Ņ€Ņ…Ņ–Đ˛", + "moved_to_library": "ПĐĩŅ€ĐĩĐŧҖ҉ĐĩĐŊĐž {count, plural, one {# ĐĩĐģĐĩĐŧĐĩĐŊŅ‚} other {# ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛}} в ĐąŅ–ĐąĐģŅ–ĐžŅ‚ĐĩĐē҃", + "moved_to_trash": "ПĐĩŅ€ĐĩĐŊĐĩҁĐĩĐŊĐž Đ´Đž ĐēĐžŅˆĐ¸Đēа", "multiselect_grid_edit_date_time_err_read_only": "НĐĩĐŧĐžĐļĐģивО Ņ€ĐĩĐ´Đ°ĐŗŅƒĐ˛Đ°Ņ‚Đ¸ Đ´Đ°Ņ‚Ņƒ ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛ ĐģĐ¸ŅˆĐĩ Đ´ĐģŅ Ņ‡Đ¸Ņ‚Đ°ĐŊĐŊŅ, ĐŋŅ€ĐžĐŋŅƒŅ‰ĐĩĐŊĐž", "multiselect_grid_edit_gps_err_read_only": "НĐĩĐŧĐžĐļĐģивО Ņ€ĐĩĐ´Đ°ĐŗŅƒĐ˛Đ°Ņ‚Đ¸ ĐŧҖҁ҆ĐĩСĐŊĐ°Ņ…ĐžĐ´ĐļĐĩĐŊĐŊŅ ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛ ĐģĐ¸ŅˆĐĩ Đ´ĐģŅ Ņ‡Đ¸Ņ‚Đ°ĐŊĐŊŅ, ĐŋŅ€ĐžĐŋŅƒŅ‰ĐĩĐŊĐž", "mute_memories": "ĐŸŅ€Đ¸ĐŗĐģŅƒŅˆĐ¸Ņ‚Đ¸ ҁĐŋĐžĐŗĐ°Đ´Đ¸", @@ -1346,6 +1366,7 @@ "name_or_nickname": "ІĐŧ'Ņ айО ĐŋҁĐĩвдОĐŊŅ–Đŧ", "network_requirement_photos_upload": "ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ҁ҂ҖĐģҌĐŊиĐēĐžĐ˛Ņ– даĐŊŅ– Đ´ĐģŅ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ Ņ„ĐžŅ‚Đž", "network_requirement_videos_upload": "ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ҁ҂ҖĐģҌĐŊиĐēĐžĐ˛Ņ– даĐŊŅ– Đ´ĐģŅ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ Đ˛Ņ–Đ´ĐĩĐž", + "network_requirements": "ВиĐŧĐžĐŗĐ¸ Đ´Đž ĐŧĐĩŅ€ĐĩĐļŅ–", "network_requirements_updated": "ВиĐŧĐžĐŗĐ¸ Đ´Đž ĐŧĐĩŅ€ĐĩĐļŅ– СĐŧŅ–ĐŊиĐģĐ¸ŅŅ, ҇ĐĩŅ€ĐŗĐ° Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ ĐžŅ‡Đ¸Ņ‰ĐĩĐŊа", "networking_settings": "МĐĩŅ€ĐĩĐļĐĩĐ˛Ņ– ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ", "networking_subtitle": "КĐĩŅ€ŅƒĐ˛Đ°ĐŊĐŊŅ ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅĐŧи ĐēŅ–ĐŊ҆ĐĩĐ˛ĐžŅ— Ņ‚ĐžŅ‡Đēи ҁĐĩŅ€Đ˛ĐĩŅ€Đ°", @@ -1356,6 +1377,7 @@ "new_person": "Нова ĐģŅŽĐ´Đ¸ĐŊа", "new_pin_code": "Новий PIN-ĐēОд", "new_pin_code_subtitle": "Ви вĐŋĐĩŅ€ŅˆĐĩ ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚Đĩ Đ´ĐžŅŅ‚ŅƒĐŋ Đ´Đž ĐžŅĐžĐąĐ¸ŅŅ‚ĐžŅ— ĐŋаĐŋĐēи. ĐĄŅ‚Đ˛ĐžŅ€Ņ–Ņ‚ŅŒ PIN-ĐēОд Đ´ĐģŅ ĐąĐĩСĐŋĐĩ҇ĐŊĐžĐŗĐž Đ´ĐžŅŅ‚ŅƒĐŋ҃ Đ´Đž ҆ҖҔҗ ŅŅ‚ĐžŅ€Ņ–ĐŊĐēи", + "new_timeline": "Нова Ņ…Ņ€ĐžĐŊĐžĐģĐžĐŗŅ–Ņ", "new_user_created": "ĐĄŅ‚Đ˛ĐžŅ€ĐĩĐŊĐž ĐŊĐžĐ˛ĐžĐŗĐž ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ°", "new_version_available": "ДОСĐĸĐŖĐŸĐĐ НОВА Đ’Đ•Đ ĐĄĐ†Đ¯", "newest_first": "ĐĄĐŋĐžŅ‡Đ°Ņ‚Đē҃ ĐŊĐžĐ˛Ņ–", @@ -1369,20 +1391,25 @@ "no_assets_message": "НАĐĸИСНІĐĸĐŦ, ЩОБ ЗАВАНĐĸАЖИĐĸИ ВАШЕ ПЕРШЕ ФОĐĸО", "no_assets_to_show": "ЕĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ Đ˛Ņ–Đ´ŅŅƒŅ‚ĐŊŅ–", "no_cast_devices_found": "ĐŸŅ€Đ¸ŅŅ‚Ņ€ĐžŅ— Đ´ĐģŅ Ņ‚Ņ€Đ°ĐŊҁĐģŅŅ†Ņ–Ņ— ĐŊĐĩ СĐŊаКдĐĩĐŊĐž", + "no_checksum_local": "КоĐŊŅ‚Ņ€ĐžĐģҌĐŊа ҁ҃Đŧа ĐŊĐĩĐ´ĐžŅŅ‚ŅƒĐŋĐŊа – ĐŊĐĩĐŧĐžĐļĐģивО ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ ĐģĐžĐēаĐģҌĐŊŅ– Ņ€ĐĩŅŅƒŅ€ŅĐ¸", + "no_checksum_remote": "КоĐŊŅ‚Ņ€ĐžĐģҌĐŊа ҁ҃Đŧа ĐŊĐĩĐ´ĐžŅŅ‚ŅƒĐŋĐŊа – ĐŊĐĩĐŧĐžĐļĐģивО ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ Đ˛Ņ–Đ´Đ´Đ°ĐģĐĩĐŊиК Ņ€ĐĩŅŅƒŅ€Ņ", "no_duplicates_found": "Đ”ŅƒĐąĐģŅ–ĐēĐ°Ņ‚Ņ–Đ˛ ĐŊĐĩ Đ˛Đ¸ŅĐ˛ĐģĐĩĐŊĐž.", "no_exif_info_available": "Đ’Ņ–Đ´ŅŅƒŅ‚ĐŊŅ Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ ĐŋŅ€Đž exif", "no_explore_results_message": "ЗаваĐŊŅ‚Đ°ĐļŅƒĐšŅ‚Đĩ ĐąŅ–ĐģҌ҈Đĩ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Ņ–Đš, Ņ‰ĐžĐą ĐŊĐ°ŅĐžĐģОдĐļŅƒĐ˛Đ°Ņ‚Đ¸ŅŅ Đ˛Đ°ŅˆĐžŅŽ ĐēĐžĐģĐĩĐēŅ†Ņ–Ņ”ŅŽ.", "no_favorites_message": "Đ”ĐžĐ´Đ°Đ˛Đ°ĐšŅ‚Đĩ ҃ĐģŅŽĐąĐģĐĩĐŊŅ– Ņ„Đ°ĐšĐģи, Ņ‰ĐžĐą ŅˆĐ˛Đ¸Đ´ĐēĐž СĐŊĐ°Ņ…ĐžĐ´Đ¸Ņ‚Đ¸ Đ˛Đ°ŅˆŅ– ĐŊаКĐēŅ€Đ°Ņ‰Ņ– ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž", "no_libraries_message": "ĐĄŅ‚Đ˛ĐžŅ€Ņ–Ņ‚ŅŒ СОвĐŊŅ–ŅˆĐŊŅŽ ĐąŅ–ĐąĐģŅ–ĐžŅ‚ĐĩĐē҃ Đ´ĐģŅ ĐŋĐĩŅ€ĐĩĐŗĐģŅĐ´Ņƒ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Ņ–Đš Ņ– Đ˛Ņ–Đ´ĐĩĐž", + "no_local_assets_found": "З Ņ†Ņ–Ņ”ŅŽ ĐēĐžĐŊŅ‚Ņ€ĐžĐģҌĐŊĐžŅŽ ҁ҃ĐŧĐžŅŽ ĐŊĐĩ СĐŊаКдĐĩĐŊĐž ĐģĐžĐēаĐģҌĐŊĐ¸Ņ… Ņ€ĐĩŅŅƒŅ€ŅŅ–Đ˛", "no_locked_photos_message": "Đ¤ĐžŅ‚Đž Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž в ĐžŅĐžĐąĐ¸ŅŅ‚Ņ–Đš ĐŋаĐŋ҆Җ ĐŋŅ€Đ¸Ņ…ĐžĐ˛Đ°ĐŊŅ– Ņ– ĐŊĐĩ Đ˛Ņ–Đ´ĐžĐąŅ€Đ°ĐļĐ°ŅŽŅ‚ŅŒŅŅ ĐŋŅ–Đ´ Ņ‡Đ°Ņ ĐŋĐĩŅ€ĐĩĐŗĐģŅĐ´Ņƒ Ņ‡Đ¸ ĐŋĐžŅˆŅƒĐē҃ ҃ Đ˛Đ°ŅˆŅ–Đš ĐąŅ–ĐąĐģŅ–ĐžŅ‚Đĩ҆Җ.", "no_name": "БĐĩС Ņ–ĐŧĐĩĐŊŅ–", "no_notifications": "НĐĩĐŧĐ°Ņ” ҁĐŋĐžĐ˛Ņ–Ņ‰ĐĩĐŊҌ", "no_people_found": "Đ›ŅŽĐ´ĐĩĐš, Ņ‰Đž Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Đ°ŅŽŅ‚ŅŒ СаĐŋĐ¸Ņ‚Ņƒ, ĐŊĐĩ СĐŊаКдĐĩĐŊĐž", "no_places": "ĐœŅ–ŅŅ†ŅŒ ĐŊĐĩĐŧĐ°Ņ”", + "no_remote_assets_found": "З Ņ†Ņ–Ņ”ŅŽ ĐēĐžĐŊŅ‚Ņ€ĐžĐģҌĐŊĐžŅŽ ҁ҃ĐŧĐžŅŽ ĐŊĐĩ СĐŊаКдĐĩĐŊĐž Đ˛Ņ–Đ´Đ´Đ°ĐģĐĩĐŊĐ¸Ņ… Ņ€ĐĩŅŅƒŅ€ŅŅ–Đ˛", "no_results": "НĐĩĐŧĐ°Ņ” Ņ€ĐĩĐˇŅƒĐģŅŒŅ‚Đ°Ņ‚Ņ–Đ˛", "no_results_description": "ĐĄĐŋŅ€ĐžĐąŅƒĐšŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ŅĐ¸ĐŊĐžĐŊŅ–Đŧ айО ĐąŅ–ĐģҌ҈ ĐˇĐ°ĐŗĐ°ĐģҌĐŊĐĩ ĐēĐģŅŽŅ‡ĐžĐ˛Đĩ ҁĐģОвО", "no_shared_albums_message": "ĐĄŅ‚Đ˛ĐžŅ€Ņ–Ņ‚ŅŒ аĐģŅŒĐąĐžĐŧ, Ņ‰ĐžĐą Đ´Ņ–ĐģĐ¸Ņ‚Đ¸ŅŅ Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Ņ–ŅĐŧи Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž С ĐģŅŽĐ´ŅŒĐŧи ҃ Đ˛Đ°ŅˆŅ–Đš ĐŧĐĩŅ€ĐĩĐļŅ–", "no_uploads_in_progress": "НĐĩĐŧĐ°Ņ” аĐēŅ‚Đ¸Đ˛ĐŊĐ¸Ņ… СаваĐŊŅ‚Đ°ĐļĐĩĐŊҌ", + "not_available": "НĐĩĐŧĐ°Ņ” даĐŊĐ¸Ņ…", "not_in_any_album": "ĐŖ ĐļОдĐŊĐžĐŧ҃ аĐģŅŒĐąĐžĐŧŅ–", "not_selected": "НĐĩ Đ˛Đ¸ĐąŅ€Đ°ĐŊĐž", "note_apply_storage_label_to_previously_uploaded assets": "ĐŸŅ€Đ¸ĐŧŅ–Ņ‚Đēа: ЊОй ĐˇĐ°ŅŅ‚ĐžŅŅƒĐ˛Đ°Ņ‚Đ¸ ĐŧŅ–Ņ‚Đē҃ ŅŅ…ĐžĐ˛Đ¸Ņ‰Đ° Đ´Đž Ņ€Đ°ĐŊŅ–ŅˆĐĩ СаваĐŊŅ‚Đ°ĐļĐĩĐŊĐ¸Ņ… Ņ€ĐĩŅŅƒŅ€ŅŅ–Đ˛, виĐēĐžĐŊĐ°ĐšŅ‚Đĩ ĐēĐžĐŧаĐŊĐ´Ņƒ", @@ -1476,7 +1503,7 @@ "permission_onboarding_permission_denied": "Đ”ĐžŅŅ‚ŅƒĐŋ ĐˇĐ°ĐąĐžŅ€ĐžĐŊĐĩĐŊĐž. ДĐģŅ виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ Immich ĐŊĐ°Đ´Đ°ĐšŅ‚Đĩ дОСвОĐģи Đ´Đž \"Đ¤ĐžŅ‚Đž Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž\" в ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅŅ….", "permission_onboarding_permission_granted": "Đ”ĐžŅŅ‚ŅƒĐŋ ĐŊадаĐŊĐž! Đ’ŅĐĩ ĐŗĐžŅ‚ĐžĐ˛Đž.", "permission_onboarding_permission_limited": "Đ”ĐžŅŅ‚ŅƒĐŋ ОйĐŧĐĩĐļĐĩĐŊĐž. ЊОйи дОСвОĐģĐ¸Ņ‚Đ¸ Immich ŅŅ‚Đ˛ĐžŅ€ŅŽĐ˛Đ°Ņ‚Đ¸ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊŅ– ĐēĐžĐŋŅ–Ņ— Ņ‚Đ° ĐēĐĩŅ€ŅƒĐ˛Đ°Ņ‚Đ¸ Đ˛ŅŅ–Ņ”ŅŽ ĐŗĐ°ĐģĐĩŅ€ĐĩŅ”ŅŽ, ĐŊĐ°Đ´Đ°ĐšŅ‚Đĩ дОСвОĐģи ĐŊа Ņ„ĐžŅ‚Đž Đš Đ˛Ņ–Đ´ĐĩĐž в ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅŅ….", - "permission_onboarding_request": "Đ”ĐžĐ´Đ°Ņ‚Đē҃ Immich ĐŋĐžŅ‚Ņ€Ņ–ĐąĐĩĐŊ Đ´ĐžĐˇĐ˛Ņ–Đģ Đ´ĐģŅ ĐŋĐĩŅ€ĐĩĐŗĐģŅĐ´Ņƒ Đ˛Đ°ŅˆĐ¸Ņ… Ņ„ĐžŅ‚Đž Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž.", + "permission_onboarding_request": "Đ—Đ°ŅŅ‚ĐžŅŅƒĐŊĐē҃ Immich ĐŋĐžŅ‚Ņ€Ņ–ĐąĐĩĐŊ Đ´ĐžĐˇĐ˛Ņ–Đģ Đ´ĐģŅ ĐŋĐĩŅ€ĐĩĐŗĐģŅĐ´Ņƒ Đ˛Đ°ŅˆĐ¸Ņ… Ņ„ĐžŅ‚Đž Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž.", "person": "Đ›ŅŽĐ´Đ¸ĐŊа", "person_age_months": "{months, plural, one {# ĐŧŅ–ŅŅŅ†ŅŒ} other {# ĐŧŅ–ŅŅŅ†Ņ–}}", "person_age_year_months": "1 year , {months, plural, one {# ĐŧŅ–ŅŅŅ†ŅŒ} other {# ĐŧŅ–ŅŅŅ†Ņ–}}", @@ -1502,8 +1529,9 @@ "play_or_pause_video": "Đ’Ņ–Đ´Ņ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ айО ĐŋŅ€Đ¸ĐˇŅƒĐŋиĐŊĐĩĐŊĐŊŅ Đ˛Ņ–Đ´ĐĩĐž", "please_auth_to_access": "Đ‘ŅƒĐ´ŅŒ ĐģĐ°ŅĐēа, ĐŋŅ€ĐžĐšĐ´Ņ–Ņ‚ŅŒ Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–ŅŽ", "port": "ĐŸĐžŅ€Ņ‚", - "preferences_settings_subtitle": "КĐĩŅ€ŅƒĐ˛Đ°ĐŊĐŊŅ ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅĐŧи Đ´ĐžĐ´Đ°Ņ‚Đē҃", + "preferences_settings_subtitle": "КĐĩŅ€ŅƒĐ˛Đ°ĐŊĐŊŅ ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅĐŧи ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐē҃", "preferences_settings_title": "ĐŸĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸", + "preparing": "ĐŸŅ–Đ´ĐŗĐžŅ‚ĐžĐ˛Đēа", "preset": "ПĐĩŅ€ĐĩĐ´Đ˛ŅŅ‚Đ°ĐŊОвĐģĐĩĐŊĐŊŅ", "preview": "ĐŸŅ€Đĩв'ŅŽ", "previous": "ПоĐŋĐĩŅ€ĐĩĐ´ĐŊŅ”", @@ -1516,11 +1544,11 @@ "privacy": "КоĐŊŅ„Ņ–Đ´ĐĩĐŊŅ†Ņ–ĐšĐŊŅ–ŅŅ‚ŅŒ", "profile": "ĐŸŅ€ĐžŅ„Ņ–ĐģҌ", "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_readonly_mode": "Đ ĐĩĐļиĐŧ ĐģĐ¸ŅˆĐĩ Đ´ĐģŅ Ņ‡Đ¸Ņ‚Đ°ĐŊĐŊŅ Đ˛Đ˛Ņ–ĐŧĐēĐŊĐĩĐŊĐž. Đ”Đ˛Ņ–Ņ‡Ņ– Ņ‚ĐžŅ€ĐēĐŊŅ–Ņ‚ŅŒŅŅ СĐŊĐ°Ņ‡Đēа Đ°Đ˛Đ°Ņ‚Đ°Ņ€Đ° ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ°, Ņ‰ĐžĐą Đ˛Đ¸ĐšŅ‚Đ¸.", + "profile_drawer_readonly_mode": "Đ ĐĩĐļиĐŧ ĐģĐ¸ŅˆĐĩ Đ´ĐģŅ Ņ‡Đ¸Ņ‚Đ°ĐŊĐŊŅ Đ˛Đ˛Ņ–ĐŧĐēĐŊĐĩĐŊĐž. ЊОй Đ˛Đ¸ĐšŅ‚Đ¸, Đ´ĐžĐ˛ĐŗĐž ĐŊĐ°Ņ‚Đ¸ŅĐŊŅ–Ņ‚ŅŒ СĐŊĐ°Ņ‡ĐžĐē Đ°Đ˛Đ°Ņ‚Đ°Ņ€Đ° ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ°.", "profile_drawer_server_out_of_date_major": "ĐĄĐĩŅ€Đ˛ĐĩŅ€ ĐˇĐ°ŅŅ‚Đ°Ņ€Ņ–Đ˛. Đ‘ŅƒĐ´ŅŒ ĐģĐ°ŅĐēа, ĐžĐŊĐžĐ˛Ņ–Ņ‚ŅŒ Đ´Đž ĐžŅŅ‚Đ°ĐŊĐŊŅŒĐžŅ— ĐŧаĐļĐžŅ€ĐŊĐžŅ— вĐĩҀҁҖҗ.", "profile_drawer_server_out_of_date_minor": "ĐĄĐĩŅ€Đ˛ĐĩŅ€ ĐˇĐ°ŅŅ‚Đ°Ņ€Ņ–Đ˛. Đ‘ŅƒĐ´ŅŒ ĐģĐ°ŅĐēа, ĐžĐŊĐžĐ˛Ņ–Ņ‚ŅŒ Đ´Đž ĐžŅŅ‚Đ°ĐŊĐŊŅŒĐžŅ— ĐŧŅ–ĐŊĐžŅ€ĐŊĐžŅ— вĐĩҀҁҖҗ.", "profile_image_of_user": "Đ—ĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ ĐŋŅ€ĐžŅ„Ņ–ĐģŅŽ {user}", @@ -1569,6 +1597,7 @@ "read_changelog": "ĐŸŅ€ĐžŅ‡Đ¸Ņ‚Đ°Ņ‚Đ¸ СĐŧŅ–ĐŊи в ĐžĐŊОвĐģĐĩĐŊĐŊŅ–", "readonly_mode_disabled": "Đ ĐĩĐļиĐŧ ĐģĐ¸ŅˆĐĩ Đ´ĐģŅ Ņ‡Đ¸Ņ‚Đ°ĐŊĐŊŅ виĐŧĐēĐŊĐĩĐŊĐž", "readonly_mode_enabled": "Đ ĐĩĐļиĐŧ ĐģĐ¸ŅˆĐĩ Đ´ĐģŅ Ņ‡Đ¸Ņ‚Đ°ĐŊĐŊŅ Đ˛Đ˛Ņ–ĐŧĐēĐŊĐĩĐŊĐž", + "ready_for_upload": "Đ“ĐžŅ‚ĐžĐ˛Đž Đ´Đž СаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ", "reassign": "ПĐĩŅ€ĐĩĐŋŅ€Đ¸ĐˇĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸", "reassigned_assets_to_existing_person": "ПĐĩŅ€ĐĩĐŋŅ€Đ¸ĐˇĐŊĐ°Ņ‡ĐĩĐŊĐž {count, plural, one {# Ņ€ĐĩŅŅƒŅ€Ņ} few {# Ņ€ĐĩŅŅƒŅ€ŅĐ¸} many {# Ņ€ĐĩŅŅƒŅ€ŅŅ–Đ˛} other {# Ņ€ĐĩŅŅƒŅ€ŅŅ–Đ˛}} {name, select, null {ҖҁĐŊŅƒŅŽŅ‡Ņ–Đš ĐžŅĐžĐąŅ–} other {{name}}}", "reassigned_assets_to_new_person": "ПĐĩŅ€ĐĩĐŋŅ€Đ¸ĐˇĐŊĐ°Ņ‡ĐĩĐŊĐž {count, plural, one {# Ņ€ĐĩŅŅƒŅ€Ņ} other {# Ņ€ĐĩŅŅƒŅ€ŅĐ¸}} ĐŊĐžĐ˛Ņ–Đš ĐžŅĐžĐąŅ–", @@ -1593,6 +1622,7 @@ "regenerating_thumbnails": "Đ’Ņ–Đ´ĐŊОвĐģĐĩĐŊĐŊŅ ĐŧŅ–ĐŊŅ–Đ°Ņ‚ŅŽŅ€", "remote": "На ҁĐĩŅ€Đ˛ĐĩҀҖ", "remote_assets": "Đ’Ņ–Đ´Đ´Đ°ĐģĐĩĐŊŅ– Ņ„ĐžŅ‚Đž Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž", + "remote_media_summary": "ЗвĐĩĐ´ĐĩĐŊĐŊŅ Đ˛Ņ–Đ´Đ´Đ°ĐģĐĩĐŊĐ¸Ņ… ĐŧĐĩĐ´Ņ–Đ°Ņ„Đ°ĐšĐģŅ–Đ˛", "remove": "ВиĐģŅƒŅ‡Đ¸Ņ‚Đ¸", "remove_assets_album_confirmation": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ {count, plural, one {# Ņ€ĐĩŅŅƒŅ€Ņ} few {# Ņ€ĐĩŅŅƒŅ€ŅĐ¸} many {# Ņ€ĐĩŅŅƒŅ€ŅŅ–Đ˛} other {# Ņ€ĐĩŅŅƒŅ€ŅŅ–Đ˛}} С аĐģŅŒĐąĐžĐŧ҃?", "remove_assets_shared_link_confirmation": "Ви вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ {count, plural, one {# Ņ€ĐĩŅŅƒŅ€Ņ} few {# Ņ€ĐĩŅŅƒŅ€ŅĐ¸} many {# Ņ€ĐĩŅŅƒŅ€ŅŅ–Đ˛} other {# Ņ€ĐĩŅŅƒŅ€ŅŅ–Đ˛}} С Ņ†ŅŒĐžĐŗĐž ҁĐŋŅ–ĐģҌĐŊĐžĐŗĐž ĐŋĐžŅĐ¸ĐģаĐŊĐŊŅ?", @@ -1617,7 +1647,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": "НĐĩĐ˛Ņ–Đ´ŅŅ‚ĐĩĐļŅƒĐ˛Đ°ĐŊŅ– Ņ‚Đ° Đ˛Ņ–Đ´ŅŅƒŅ‚ĐŊŅ– Ņ„Đ°ĐšĐģи ĐąŅƒĐ´ŅƒŅ‚ŅŒ Đ˛Ņ–Đ´ĐžĐąŅ€Đ°ĐļĐĩĐŊŅ– Ņ‚ŅƒŅ‚", @@ -1641,10 +1671,11 @@ "resolved_all_duplicates": "ĐŖŅŅ– Đ´ŅƒĐąĐģŅ–ĐēĐ°Ņ‚Đ¸ ҃ҁ҃ĐŊŅƒŅ‚Đž", "restore": "Đ’Ņ–Đ´ĐŊĐžĐ˛Đ¸Ņ‚Đ¸", "restore_all": "Đ’Ņ–Đ´ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ Đ˛ŅĐĩ", - "restore_trash_action_prompt": "{count} Đ˛Ņ–Đ´ĐŊОвĐģĐĩĐŊĐž ĐˇŅ– ҁĐŧŅ–Ņ‚ĐŊиĐēа", + "restore_trash_action_prompt": "{count} Đ˛Ņ–Đ´ĐŊОвĐģĐĩĐŊĐž С ĐēĐžŅˆĐ¸Đēа", "restore_user": "Đ’Ņ–Đ´ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ°", - "restored_asset": "Đ’Ņ–Đ´ĐŊОвĐģĐĩĐŊиК аĐēŅ‚Đ¸Đ˛", + "restored_asset": "Đ’Ņ–Đ´ĐŊОвĐģĐĩĐŊиК Ņ€ĐĩŅŅƒŅ€Ņ", "resume": "ĐŸŅ€ĐžĐ´ĐžĐ˛ĐļĐ¸Ņ‚Đ¸", + "resume_paused_jobs": "Đ’Ņ–Đ´ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ {count, plural, one {# ĐŋŅ€Đ¸ĐˇŅƒĐŋиĐŊĐĩĐŊĐĩ СавдаĐŊĐŊŅ} other {# ĐŋŅ€Đ¸ĐˇŅƒĐŋиĐŊĐĩĐŊŅ– СавдаĐŊĐŊŅ}}", "retry_upload": "ĐŸĐžĐ˛Ņ‚ĐžŅ€Đ¸Ņ‚Đ¸ СаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ", "review_duplicates": "ПĐĩŅ€ĐĩĐŗĐģŅĐŊŅƒŅ‚Đ¸ Đ´ŅƒĐąĐģŅ–ĐēĐ°Ņ‚Đ¸", "review_large_files": "ПĐĩŅ€ĐĩĐŗĐģŅĐ´ вĐĩĐģиĐēĐ¸Ņ… Ņ„Đ°ĐšĐģŅ–Đ˛", @@ -1742,7 +1773,7 @@ "send_message": "ĐĐ°Đ´Ņ–ŅĐģĐ°Ņ‚Đ¸ ĐŋĐžĐ˛Ņ–Đ´ĐžĐŧĐģĐĩĐŊĐŊŅ", "send_welcome_email": "ĐĐ°Đ´Ņ–ŅˆĐģŅ–Ņ‚ŅŒ Đ˛Ņ–Ņ‚Đ°ĐģҌĐŊиК ĐģĐ¸ŅŅ‚", "server_endpoint": "ĐšŅ–ĐŊ҆Đĩва Ņ‚ĐžŅ‡Đēа ҁĐĩŅ€Đ˛ĐĩŅ€Đ°", - "server_info_box_app_version": "ВĐĩŅ€ŅŅ–Ņ Đ´ĐžĐ´Đ°Ņ‚Đēа", + "server_info_box_app_version": "ВĐĩŅ€ŅŅ–Ņ ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐē҃", "server_info_box_server_url": "URL ҁĐĩŅ€Đ˛ĐĩŅ€Đ°", "server_offline": "ĐĄĐĩŅ€Đ˛ĐĩŅ€ ĐžŅ„ĐģаКĐŊ", "server_online": "ĐĄĐĩŅ€Đ˛ĐĩŅ€ ĐžĐŊĐģаКĐŊ", @@ -1764,7 +1795,7 @@ "setting_image_viewer_preview_title": "ЗаваĐŊŅ‚Đ°ĐļŅƒĐ˛Đ°Ņ‚Đ¸ ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ ĐŋĐžĐŋĐĩŅ€ĐĩĐ´ĐŊŅŒĐžĐŗĐž ĐŋĐĩŅ€ĐĩĐŗĐģŅĐ´Ņƒ", "setting_image_viewer_title": "Đ—ĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ", "setting_languages_apply": "Đ—Đ°ŅŅ‚ĐžŅŅƒĐ˛Đ°Ņ‚Đ¸", - "setting_languages_subtitle": "ЗĐŧŅ–ĐŊĐ¸Ņ‚Đ¸ ĐŧĐžĐ˛Ņƒ Đ´ĐžĐ´Đ°Ņ‚Đē҃", + "setting_languages_subtitle": "ЗĐŧŅ–ĐŊĐ¸Ņ‚Đ¸ ĐŧĐžĐ˛Ņƒ ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐē҃", "setting_notifications_notify_failures_grace_period": "ĐŸĐžĐ˛Ņ–Đ´ĐžĐŧĐ¸Ņ‚Đ¸ ĐŋŅ€Đž ĐŋĐžĐŧиĐģĐēи Ņ„ĐžĐŊĐžĐ˛ĐžĐŗĐž Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ: {duration}", "setting_notifications_notify_hours": "{count} ĐŗĐžĐ´Đ¸ĐŊ", "setting_notifications_notify_immediately": "ĐŊĐĩĐŗĐ°ĐšĐŊĐž", @@ -1849,10 +1880,8 @@ "shift_to_permanent_delete": "ĐŊĐ°Ņ‚Đ¸ŅĐŊŅ–Ņ‚ŅŒ ⇧ Ņ‰ĐžĐą видаĐģĐ¸Ņ‚Đ¸ Ой'Ņ”ĐēŅ‚ ĐŊаСавĐļди", "show_album_options": "ПоĐēĐ°ĐˇĐ°Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ аĐģŅŒĐąĐžĐŧ҃", "show_albums": "ПоĐēĐ°ĐˇŅƒĐ˛Đ°Ņ‚Đ¸ аĐģŅŒĐąĐžĐŧи", - "show_all_assets": "ПоĐēĐ°ĐˇĐ°Ņ‚Đ¸ Đ˛ŅŅ– Ņ€ĐĩŅŅƒŅ€ŅĐ¸", "show_all_people": "ПоĐēĐ°ĐˇĐ°Ņ‚Đ¸ Đ˛ŅŅ–Ņ… ĐģŅŽĐ´ĐĩĐš", "show_and_hide_people": "ПоĐēĐ°ĐˇĐ°Ņ‚Đ¸ Ņ‚Đ° ĐŋŅ€Đ¸Ņ…ĐžĐ˛Đ°Ņ‚Đ¸ ĐģŅŽĐ´ĐĩĐš", - "show_assets_without_location": "ПоĐēĐ°ĐˇĐ°Ņ‚Đ¸ аĐēŅ‚Đ¸Đ˛Đ¸ ĐąĐĩС ĐŧҖҁ҆ĐĩСĐŊĐ°Ņ…ĐžĐ´ĐļĐĩĐŊĐŊŅ", "show_file_location": "ПоĐēĐ°ĐˇĐ°Ņ‚Đ¸ Ņ€ĐžĐˇŅ‚Đ°ŅˆŅƒĐ˛Đ°ĐŊĐŊŅ Ņ„Đ°ĐšĐģ҃", "show_gallery": "ПоĐēĐ°ĐˇĐ°Ņ‚Đ¸ ĐŗĐ°ĐģĐĩŅ€ĐĩŅŽ", "show_hidden_people": "ПоĐēĐ°ĐˇĐ°Ņ‚Đ¸ ĐŋŅ€Đ¸Ņ…ĐžĐ˛Đ°ĐŊĐ¸Ņ… ĐģŅŽĐ´ĐĩĐš", @@ -1869,6 +1898,7 @@ "show_slideshow_transition": "ПоĐēĐ°ĐˇĐ°Ņ‚Đ¸ ĐŋĐĩŅ€ĐĩŅ…Ņ–Đ´ ҁĐģаКд-ŅˆĐžŅƒ", "show_supporter_badge": "ЗĐŊĐ°Ņ‡ĐžĐē ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēи", "show_supporter_badge_description": "ПоĐēĐ°ĐˇĐ°Ņ‚Đ¸ СĐŊĐ°Ņ‡ĐžĐē ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēи", + "show_text_search_menu": "ПоĐēĐ°ĐˇĐ°Ņ‚Đ¸ ĐŧĐĩĐŊŅŽ Ņ‚ĐĩĐēŅŅ‚ĐžĐ˛ĐžĐŗĐž ĐŋĐžŅˆŅƒĐē҃", "shuffle": "ПĐĩŅ€ĐĩĐŧŅ–ŅˆĐ°Ņ‚Đ¸", "sidebar": "Đ‘Ņ–Ņ‡ĐŊа ĐŋаĐŊĐĩĐģҌ", "sidebar_display_description": "Đ’Ņ–Đ´ĐžĐąŅ€Đ°ĐˇĐ¸Ņ‚Đ¸ ĐŋĐžŅĐ¸ĐģаĐŊĐŊŅ ĐŊа ĐŋĐĩŅ€ĐĩĐŗĐģŅĐ´ ҃ ĐąŅ–Ņ‡ĐŊŅ–Đš ĐŋаĐŊĐĩĐģŅ–", @@ -1899,6 +1929,7 @@ "stacktrace": "ĐĄŅ‚ĐĩĐē виĐēĐģиĐēŅ–Đ˛", "start": "ĐĄŅ‚Đ°Ņ€Ņ‚", "start_date": "Đ”Đ°Ņ‚Đ° ĐŋĐžŅ‡Đ°Ņ‚Đē҃", + "start_date_before_end_date": "Đ”Đ°Ņ‚Đ° ĐŋĐžŅ‡Đ°Ņ‚Đē҃ ĐŧĐ°Ņ” ĐąŅƒŅ‚Đ¸ Ņ€Đ°ĐŊŅ–ŅˆĐĩ Đ´Đ°Ņ‚Đ¸ СавĐĩŅ€ŅˆĐĩĐŊĐŊŅ", "state": "Đ ĐĩĐŗŅ–ĐžĐŊ", "status": "ĐĄŅ‚Đ°ĐŊ", "stop_casting": "Đ—ŅƒĐŋиĐŊĐ¸Ņ‚Đ¸ Ņ‚Ņ€Đ°ĐŊҁĐģŅŅ†Ņ–ŅŽ", @@ -1923,6 +1954,8 @@ "sync_albums_manual_subtitle": "ХиĐŊŅ…Ņ€ĐžĐŊŅ–ĐˇŅƒĐ˛Đ°Ņ‚Đ¸ Đ˛ŅŅ– СаваĐŊŅ‚Đ°ĐļĐĩĐŊŅ– Ņ„ĐžŅ‚Đž Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž ҃ Đ˛Đ¸ĐąŅ€Đ°ĐŊŅ– аĐģŅŒĐąĐžĐŧи Đ´ĐģŅ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ", "sync_local": "ХиĐŊŅ…Ņ€ĐžĐŊŅ–ĐˇŅƒĐ˛Đ°Ņ‚Đ¸ ĐŊа ĐŋŅ€Đ¸ŅŅ‚Ņ€ĐžŅ—", "sync_remote": "ХиĐŊŅ…Ņ€ĐžĐŊŅ–ĐˇŅƒĐ˛Đ°Ņ‚Đ¸ С ҁĐĩŅ€Đ˛ĐĩŅ€ĐžĐŧ", + "sync_status": "ĐĄŅ‚Đ°ĐŊ ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊŅ–ĐˇĐ°Ņ†Ņ–Ņ—", + "sync_status_subtitle": "ПĐĩŅ€ĐĩĐŗĐģŅĐ´ Ņ‚Đ° ĐēĐĩŅ€ŅƒĐ˛Đ°ĐŊĐŊŅ ŅĐ¸ŅŅ‚ĐĩĐŧĐžŅŽ ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊŅ–ĐˇĐ°Ņ†Ņ–Ņ—", "sync_upload_album_setting_subtitle": "ĐĄŅ‚Đ˛ĐžŅ€ŅŽĐšŅ‚Đĩ Ņ‚Đ° СаваĐŊŅ‚Đ°ĐļŅƒĐšŅ‚Đĩ ŅĐ˛ĐžŅ— Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Ņ–Ņ— Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž Đ´Đž Đ˛Đ¸ĐąŅ€Đ°ĐŊĐ¸Ņ… аĐģŅŒĐąĐžĐŧŅ–Đ˛ ĐŊа ҁĐĩŅ€Đ˛ĐĩŅ€ Immich", "tag": "ĐĸĐĩĐŗ", "tag_assets": "Đ”ĐžĐ´Đ°Ņ‚Đ¸ Ņ‚ĐĩĐŗĐ¸", @@ -1931,7 +1964,7 @@ "tag_not_found_question": "НĐĩ Đ˛Đ´Đ°Ņ”Ņ‚ŅŒŅŅ СĐŊĐ°ĐšŅ‚Đ¸ Ņ‚ĐĩĐŗ? ĐĄŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐŊОвиК Ņ‚ĐĩĐŗ.", "tag_people": "ĐĸĐĩĐŗ ĐģŅŽĐ´ĐĩĐš", "tag_updated": "ОĐŊОвĐģĐĩĐŊĐž Ņ‚ĐĩĐŗ: {tag}", - "tagged_assets": "ПозĐŊĐ°Ņ‡ĐĩĐŊĐž Ņ‚ĐĩĐŗĐžĐŧ {count, plural, one {# аĐēŅ‚Đ¸Đ˛} other {# аĐēŅ‚Đ¸Đ˛Đ¸}}", + "tagged_assets": "ПозĐŊĐ°Ņ‡ĐĩĐŊĐž Ņ‚ĐĩĐŗĐžĐŧ {count, plural, one {# Ņ€ĐĩŅŅƒŅ€Ņ} other {# Ņ€ĐĩŅŅƒŅ€ŅĐ¸}}", "tags": "ĐĸĐĩĐŗĐ¸", "tap_to_run_job": "ĐĸĐžŅ€ĐēĐŊŅ–Ņ‚ŅŒŅŅ, Ņ‰ĐžĐą СаĐŋŅƒŅŅ‚Đ¸Ņ‚Đ¸ СавдаĐŊĐŊŅ", "template": "ШайĐģĐžĐŊ", @@ -1948,7 +1981,7 @@ "theme_setting_primary_color_title": "ĐžŅĐŊОвĐŊиК ĐēĐžĐģŅ–Ņ€", "theme_setting_system_primary_color_title": "ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐēĐžĐģŅ–Ņ€ ŅĐ¸ŅŅ‚ĐĩĐŧи", "theme_setting_system_theme_switch": "ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž (ŅĐē ҃ ŅĐ¸ŅŅ‚ĐĩĐŧŅ–)", - "theme_setting_theme_subtitle": "НаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ Ņ‚ĐĩĐŧи Đ´ĐžĐ´Đ°Ņ‚Đēа", + "theme_setting_theme_subtitle": "НаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ Ņ‚ĐĩĐŧи ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐē҃", "theme_setting_three_stage_loading_subtitle": "ĐĸŅ€Đ¸ĐĩŅ‚Đ°ĐŋĐŊĐĩ СаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ ĐŧĐžĐļĐĩ ĐŋŅ–Đ´Đ˛Đ¸Ņ‰Đ¸Ņ‚Đ¸ ĐŋŅ€ĐžĐ´ŅƒĐēŅ‚Đ¸Đ˛ĐŊŅ–ŅŅ‚ŅŒ СаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ, аĐģĐĩ ҁĐŋŅ€Đ¸Ņ‡Đ¸ĐŊĐ¸Ņ‚ŅŒ СĐŊĐ°Ņ‡ĐŊĐž ĐąŅ–ĐģҌ҈Đĩ ĐŊаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ ĐŊа ĐŧĐĩŅ€ĐĩĐļ҃", "theme_setting_three_stage_loading_title": "ĐŖĐ˛Ņ–ĐŧĐēĐŊŅƒŅ‚Đ¸ Ņ‚Ņ€Đ¸ĐĩŅ‚Đ°ĐŋĐŊĐĩ СаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ", "they_will_be_merged_together": "ВоĐŊи ĐąŅƒĐ´ŅƒŅ‚ŅŒ Ой'Ņ”Đ´ĐŊаĐŊŅ– Ņ€Đ°ĐˇĐžĐŧ", @@ -1963,25 +1996,26 @@ "to_multi_select": "Đ´ĐģŅ ĐąĐ°ĐŗĐ°Ņ‚ĐžŅ€Đ°ĐˇĐžĐ˛ĐžĐŗĐž Đ˛Đ¸ĐąĐžŅ€Ņƒ", "to_parent": "ПовĐĩŅ€ĐŊŅƒŅ‚Đ¸ŅŅŒ ĐŊаСад", "to_select": "Đ˛Đ¸ĐąŅ€Đ°Ņ‚Đ¸", - "to_trash": "ĐĄĐŧŅ–Ņ‚ĐŊиĐē", + "to_trash": "ĐšĐžŅˆĐ¸Đē", "toggle_settings": "ПĐĩŅ€ĐĩĐŧиĐēаĐŊĐŊŅ ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊҌ", "total": "ĐŖŅŅŒĐžĐŗĐž", "total_usage": "Đ—Đ°ĐŗĐ°ĐģҌĐŊĐĩ виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ", - "trash": "ĐĄĐŧŅ–Ņ‚ĐŊиĐē", - "trash_action_prompt": "{count} ĐŋĐĩŅ€ĐĩĐŧҖ҉ĐĩĐŊĐž Đ´Đž ҁĐŧŅ–Ņ‚ĐŊиĐēа", + "trash": "ĐšĐžŅˆĐ¸Đē", + "trash_action_prompt": "{count} ĐŋĐĩŅ€ĐĩĐŧҖ҉ĐĩĐŊĐž Đ´Đž ĐēĐžŅˆĐ¸Đēа", "trash_all": "ВидаĐģĐ¸Ņ‚Đ¸ Đ˛ŅĐĩ", "trash_count": "ВидаĐģĐ¸Ņ‚Đ¸ {count, number}", - "trash_delete_asset": "ĐĄĐŧŅ–Ņ‚ĐŊиĐē/ВидаĐģĐ¸Ņ‚Đ¸ Ņ€ĐĩŅŅƒŅ€Ņ", - "trash_emptied": "ĐšĐžŅˆĐ¸Đē ĐžŅ‡Đ¸Ņ‰ĐĩĐŊиК", + "trash_delete_asset": "ĐŖ ĐēĐžŅˆĐ¸Đē/ВидаĐģĐ¸Ņ‚Đ¸ Ņ€ĐĩŅŅƒŅ€Ņ", + "trash_emptied": "ĐšĐžŅˆĐ¸Đē ĐžŅ‡Đ¸Ņ‰ĐĩĐŊĐž", "trash_no_results_message": "ĐĸŅƒŅ‚ С'ŅĐ˛ĐģŅŅ‚Đ¸ĐŧŅƒŅ‚ŅŒŅŅ видаĐģĐĩĐŊŅ– Ņ„ĐžŅ‚Đž Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž.", - "trash_page_delete_all": "ВидаĐģĐ¸Ņ‚Đ¸ ŅƒŅŅ–", + "trash_page_delete_all": "ВидаĐģĐ¸Ņ‚Đ¸ ҃ҁĐĩ", "trash_page_empty_trash_dialog_content": "Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐžŅ‡Đ¸ŅŅ‚Đ¸Ņ‚Đ¸ ĐēĐžŅˆĐ¸Đē? ĐĻŅ– ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ ĐąŅƒĐ´ŅƒŅ‚ŅŒ ĐžŅŅ‚Đ°Ņ‚ĐžŅ‡ĐŊĐž видаĐģĐĩĐŊŅ– С Immich", "trash_page_info": "ПоĐŧҖ҉ĐĩĐŊŅ– ҃ ĐēĐžŅˆĐ¸Đē ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ ĐąŅƒĐ´Đĩ ĐžŅŅ‚Đ°Ņ‚ĐžŅ‡ĐŊĐž видаĐģĐĩĐŊĐž ҇ĐĩŅ€ĐĩС {days} Đ´ĐŊŅ–Đ˛", - "trash_page_no_assets": "Đ’Ņ–Đ´Đ´Đ°ĐģĐĩĐŊŅ– ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ Đ˛Ņ–Đ´ŅŅƒŅ‚ĐŊŅ–", - "trash_page_restore_all": "Đ’Ņ–Đ´ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ ŅƒŅŅ–", - "trash_page_select_assets_btn": "Đ’Đ¸ĐąŅ€Đ°ĐŊŅ– ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸", + "trash_page_no_assets": "ВидаĐģĐĩĐŊŅ– ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ Đ˛Ņ–Đ´ŅŅƒŅ‚ĐŊŅ–", + "trash_page_restore_all": "Đ’Ņ–Đ´ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ ҃ҁĐĩ", + "trash_page_select_assets_btn": "Đ’Đ¸ĐąŅ€Đ°Ņ‚Đ¸ ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸", "trash_page_title": "ĐšĐžŅˆĐ¸Đē ({count})", "trashed_items_will_be_permanently_deleted_after": "ВидаĐģĐĩĐŊŅ– ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ ĐąŅƒĐ´ŅƒŅ‚ŅŒ ĐžŅŅ‚Đ°Ņ‚ĐžŅ‡ĐŊĐž видаĐģĐĩĐŊŅ– ҇ĐĩŅ€ĐĩС {days, plural, one {# Đ´ĐĩĐŊҌ} few {# Đ´ĐŊŅ–} many {# Đ´ĐŊŅ–Đ˛} other {# Đ´ĐŊŅ–Đ˛}}.", + "troubleshoot": "ВиĐŋŅ€Đ°Đ˛ĐģĐĩĐŊĐŊŅ ĐŊĐĩĐŋĐžĐģадОĐē", "type": "ĐĸиĐŋ", "unable_to_change_pin_code": "НĐĩĐŧĐžĐļĐģивО СĐŧŅ–ĐŊĐ¸Ņ‚Đ¸ PIN-ĐēОд", "unable_to_setup_pin_code": "НĐĩĐŧĐžĐļĐģивО ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ PIN-ĐēОд", @@ -2037,7 +2071,6 @@ "use_biometric": "ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐąŅ–ĐžĐŧĐĩŅ‚Ņ€Ņ–ŅŽ", "use_current_connection": "виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐŋĐžŅ‚ĐžŅ‡ĐŊĐĩ ĐŋŅ–Đ´ĐēĐģŅŽŅ‡ĐĩĐŊĐŊŅ", "use_custom_date_range": "ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ†ŅŒĐēиК Đ´Ņ–Đ°ĐŋаСОĐŊ Đ´Đ°Ņ‚", - "use_this_location": "ĐĐ°Ņ‚Đ¸ŅĐŊŅ–Ņ‚ŅŒ, Ņ‰ĐžĐą виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐŧҖҁ҆ĐĩСĐŊĐ°Ņ…ĐžĐ´ĐļĐĩĐŊĐŊŅ", "user": "ĐšĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡", "user_has_been_deleted": "ĐšĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ° видаĐģĐĩĐŊĐž.", "user_id": "ID ĐšĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ°", @@ -2099,5 +2132,6 @@ "yes": "ĐĸаĐē", "you_dont_have_any_shared_links": "ĐŖ Đ˛Đ°Ņ ĐŊĐĩĐŧĐ°Ņ” ҁĐŋŅ–ĐģҌĐŊĐ¸Ņ… ĐŋĐžŅĐ¸ĐģаĐŊҌ", "your_wifi_name": "Назва Đ˛Đ°ŅˆĐžŅ— Wi-Fi ĐŧĐĩŅ€ĐĩĐļŅ–", - "zoom_image": "Đ—ĐąŅ–ĐģŅŒŅˆĐ¸Ņ‚Đ¸ ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ" + "zoom_image": "Đ—ĐąŅ–ĐģŅŒŅˆĐ¸Ņ‚Đ¸ ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ", + "zoom_to_bounds": "Đ—ĐąŅ–ĐģŅŒŅˆĐ¸Ņ‚Đ¸ ĐŧĐ°ŅŅˆŅ‚Đ°Đą Đ´Đž ĐŧĐĩĐļ" } diff --git a/i18n/vi.json b/i18n/vi.json index 49a73f022c..b9ee8cfcc9 100644 --- a/i18n/vi.json +++ b/i18n/vi.json @@ -360,8 +360,6 @@ "admin_password": "Máē­t kháēŠu QuáēŖn tráģ‹ viÃĒn", "administration": "QuáēŖn tráģ‹", "advanced": "NÃĸng cao", - "advanced_settings_beta_timeline_subtitle": "TráēŖi nghiáģ‡m giao diáģ‡n app máģ›i", - "advanced_settings_beta_timeline_title": "Timeline Beta", "advanced_settings_enable_alternate_media_filter_subtitle": "DÚng tÚy cháģn này đáģƒ láģc phÆ°ÆĄng tiáģ‡n khi đáģ“ng báģ™ theo tiÃĒu chí khÃĄc. Cháģ‰ tháģ­ khi áģŠng dáģĨng không nháē­n diáģ‡n đưáģŖc táēĨt cáēŖ cÃĄc album.", "advanced_settings_enable_alternate_media_filter_title": "[THáģŦ NGHIáģ†M] DÚng báģ™ láģc đáģ“ng báģ™ album thay tháēŋ", "advanced_settings_log_level_title": "PhÃĸn loáēĄi nháē­t kÃŊ: {level}", @@ -558,8 +556,6 @@ "backup_setting_subtitle": "QuáēŖn lÃŊ cài đáēˇt táēŖi lÃĒn áģŸ cháēŋ đáģ™ náģn và khi đang máģŸ", "backup_settings_subtitle": "Cài đáēˇt viáģ‡c táēŖi lÃĒn", "backward": "LÚi láēĄi", - "beta_sync": "TráēĄng thÃĄi đáģ“ng báģ™ Beta", - "beta_sync_subtitle": "Háģ‡ tháģ‘ng đáģ“ng máģ›i", "biometric_auth_enabled": "ÄÃŖ báē­t xÃĄc tháģąc sinh tráē¯c háģc", "biometric_locked_out": "BáēĄn Ä‘ÃŖ báģ‹ khÃŗa xÃĄc tháģąc báēąng sinh tráē¯c háģc", "biometric_no_options": "Không cÃŗ tÚy cháģn báēąng sinh tráē¯c háģc", diff --git a/i18n/zh_Hant.json b/i18n/zh_Hant.json index 6130716ce6..267eb767c3 100644 --- a/i18n/zh_Hant.json +++ b/i18n/zh_Hant.json @@ -28,18 +28,19 @@ "add_to_album": "加å…Ĩåˆ°į›¸į°ŋ", "add_to_album_bottom_sheet_added": "新åĸžåˆ° {album}", "add_to_album_bottom_sheet_already_exists": "厞圍 {album} 中", + "add_to_album_bottom_sheet_some_local_assets": "į„Ąæŗ•å°‡æŸä盿œŦæŠŸčŗ‡į”ĸ新åĸžåˆ°į›¸į°ŋ", "add_to_album_toggle": "é¸æ“‡į›¸į°ŋ{album}", "add_to_albums": "加å…Ĩᛏį°ŋ", - "add_to_albums_count": "將({count})å€‹é …į›ŽåŠ å…Ĩᛏį°ŋ", + "add_to_albums_count": "將 ({count}) å€‹é …į›ŽåŠ å…Ĩᛏį°ŋ", "add_to_shared_album": "åŠ åˆ°å…ąäēĢᛏį°ŋ", - "add_url": "åģēį̋逪įĩ", + "add_url": "新åĸž URL", "added_to_archive": "į§ģč‡ŗå°å­˜", "added_to_favorites": "加å…Ĩæ”ļ藏", "added_to_favorites_count": "將 {count, number} å€‹é …į›ŽåŠ å…Ĩæ”ļ藏", "admin": { "add_exclusion_pattern_description": "新åĸžæŽ’除æĸäģļ。支援äŊŋį”¨ã€Œ*」、「 **」、「?」䞆扞尋įŦĻ合čĻå‰‡įš„å­—ä¸˛ã€‚åĻ‚æžœčρ圍äģģäŊ•名į‚ē「Rawã€įš„į›ŽéŒ„å…§æŽ’é™¤æ‰€æœ‰įŦĻ合æĸäģļįš„æĒ”æĄˆīŧŒčĢ‹äŊŋį”¨ã€Œ**/Raw/**」。åĻ‚æžœčĻæŽ’é™¤æ‰€æœ‰ã€Œ.tif」įĩå°žįš„æĒ”æĄˆīŧŒčĢ‹äŊŋį”¨ã€Œ**/*.tif」。åĻ‚æžœčĻæŽ’é™¤æŸå€‹įĩ•å°čˇ¯åž‘īŧŒčĢ‹äŊŋį”¨ã€Œ/path/to/ignore/**」。", "admin_user": "įŽĄį†å“Ą", - "asset_offline_description": "此外部åĒ’éĢ”åēĢé …į›Žåˇ˛į„Ąæŗ•åœ¨įŖįĸŸä¸Šæ‰žåˆ°īŧŒä¸Ļ厞į§ģč‡ŗåžƒåœžæĄļ。č‹Ĩ芲æĒ”æĄˆæ˜¯åœ¨åĒ’éĢ”åēĢ內į§ģ動īŧŒčĢ‹åœ¨æ™‚é–“čģ¸ä¸­æŸĨįœ‹æ–°įš„å°æ‡‰é …į›Žã€‚č‹ĨčĻé‚„åŽŸæ­¤é …į›ŽīŧŒčĢ‹įĸēäŋä¸‹æ–šįš„æĒ”æĄˆčˇ¯åž‘å¯äž› Immich 存取īŧŒä¸Ļ重新掃描åĒ’éĢ”åēĢ。", + "asset_offline_description": "此外部åĒ’éĢ”åēĢé …į›Žåˇ˛į„Ąæŗ•åœ¨įŖįĸŸä¸Šæ‰žåˆ°īŧŒä¸Ļ厞į§ģč‡ŗåžƒåœžæĄļ。č‹Ĩ芲æĒ”æĄˆæ˜¯åœ¨åĒ’éĢ”åēĢ內į§ģ動īŧŒčĢ‹åœ¨æ™‚é–“čģ¸ä¸­æĒĸčĻ–æ–°įš„å°æ‡‰é …į›Žã€‚č‹ĨčĻé‚„åŽŸæ­¤é …į›ŽīŧŒčĢ‹įĸēäŋä¸‹æ–šįš„æĒ”æĄˆčˇ¯åž‘å¯äž› Immich 存取īŧŒä¸Ļ重新掃描åĒ’éĢ”åēĢ。", "authentication_settings": "éŠ—č­‰č¨­åŽš", "authentication_settings_description": "įŽĄį†å¯†įĸŧ、OAuth 與å…ļäģ–éŠ—č­‰č¨­åŽš", "authentication_settings_disable_all": "įĸē厚čĻåœį”¨æ‰€æœ‰į™ģå…Ĩæ–šåŧå—ŽīŧŸé€™æ¨ŖæœƒåŽŒå…¨į„Ąæŗ•į™ģå…Ĩ。", @@ -49,8 +50,8 @@ "backup_database_enable_description": "å•Ÿį”¨čŗ‡æ–™åēĢ備äģŊ", "backup_keep_last_amount": "äŋį•™å…ˆå‰å‚™äģŊįš„æ•¸é‡", "backup_onboarding_1_description": "åœ¨é›˛įĢ¯æˆ–å…ļäģ–å¯ĻéĢ”äŊįŊŽįš„į•°åœ°å‚™äģŊ副æœŦ。", - "backup_onboarding_2_description": "å„˛å­˜åœ¨ä¸åŒčŖįŊŽä¸Šįš„æœŦ地副æœŦ。這包æ‹Ŧä¸ģčρæĒ”æĄˆåŠå…ļæœŦ地備äģŊ。", - "backup_onboarding_3_description": "æ‚¨čŗ‡æ–™įš„į¸Ŋ備äģŊäģŊ數īŧŒåŒ…æ‹Ŧ原始æĒ”æĄˆåœ¨å…§ã€‚é€™åŒ…æ‹Ŧ 1 äģŊį•°åœ°å‚™äģŊ與 2 äģŊæœŦ地副æœŦ。", + "backup_onboarding_2_description": "å„˛å­˜åœ¨ä¸åŒčŖįŊŽä¸Šįš„æœŦ抟副æœŦ。這包æ‹Ŧä¸ģčρæĒ”æĄˆåŠå…ļæœŦ抟備äģŊ。", + "backup_onboarding_3_description": "æ‚¨čŗ‡æ–™įš„į¸Ŋ備äģŊäģŊ數īŧŒåŒ…æ‹Ŧ原始æĒ”æĄˆåœ¨å…§ã€‚é€™åŒ…æ‹Ŧ 1 äģŊį•°åœ°å‚™äģŊ與 2 äģŊæœŦ抟副æœŦ。", "backup_onboarding_description": "åģēč­°æŽĄį”¨ 3-2-1 備äģŊį­–į•Ĩ 來äŋč­ˇæ‚¨įš„čŗ‡æ–™ã€‚æ‚¨æ‡‰äŋį•™åˇ˛ä¸Šå‚ŗįš„ᅧቇ/åŊąį‰‡å‰¯æœŦīŧŒäģĨ及 Immich čŗ‡æ–™åēĢīŧŒäģĨåģēįĢ‹åŽŒæ•´įš„å‚™äģŊæ–šæĄˆã€‚", "backup_onboarding_footer": "更多備äģŊ Immich čŗ‡č¨ŠīŧŒčĢ‹åƒč€ƒčĒĒæ˜Žæ–‡äģļ。", "backup_onboarding_parts_title": "éĩåžžå‚™äģŊ原則 3-2-1īŧš", @@ -81,7 +82,7 @@ "image_format": "æ ŧåŧ", "image_format_description": "WebP čƒŊį”ĸį”Ÿį›¸å°æ–ŧ JPEG æ›´å°įš„æĒ”æĄˆīŧŒäŊ†įˇ¨įĸŧ速åēĻčŧƒæ…ĸ。", "image_fullsize_description": "į§ģ除中įšŧčŗ‡æ–™įš„å¤§å°ē寸åŊąåƒīŧŒåœ¨æ”žå¤§åœ–į‰‡æ™‚äŊŋᔍ", - "image_fullsize_enabled": "å•Ÿį”¨å¤§å°ē寸åŊąåƒį”Ÿæˆ", + "image_fullsize_enabled": "å•Ÿį”¨å¤§å°ē寸åŊąåƒį”ĸį”Ÿ", "image_fullsize_enabled_description": "į”ĸį”Ÿéžįļ˛é å‹å–„æ ŧåŧįš„大å°ē寸åŊąåƒã€‚å•Ÿį”¨ã€ŒååĨŊåĩŒå…Ĩįš„é čĻŊ」時īŧŒæœƒį›´æŽĨäŊŋᔍ內åĩŒé čĻŊ而不進行čŊ‰æ›ã€‚不會åŊąéŸŋ JPEG į­‰įļ˛é å‹å–„æ ŧåŧã€‚", "image_fullsize_quality_description": "大å°ē寸åŊąåƒå“čŗĒīŧŒį¯„圍į‚ē 1 到 100。數å€ŧčļŠéĢ˜å“čŗĒčļŠåĨŊīŧŒäŊ†æĒ”æĄˆä🿜ƒčļŠå¤§ã€‚", "image_fullsize_title": "大å°ē寸åŊąåƒč¨­åޚ", @@ -123,6 +124,13 @@ "logging_enable_description": "å•Ÿį”¨æ—ĨčĒŒč¨˜éŒ„", "logging_level_description": "å•Ÿį”¨æ™‚įš„æ—ĨčĒŒåą¤į´šã€‚", "logging_settings": "æ—Ĩčnj", + "machine_learning_availability_checks": "å¯į”¨æ€§æĒĸæŸĨ", + "machine_learning_availability_checks_description": "č‡Ē動åĩæ¸Ŧä¸Ļå„Ēå…ˆé¸æ“‡å¯į”¨įš„æŠŸå™¨å­¸įŋ’äŧ翜å™¨", + "machine_learning_availability_checks_enabled": "å•Ÿį”¨å¯į”¨æ€§æĒĸæŸĨ", + "machine_learning_availability_checks_interval": "æĒĸæŸĨ間隔", + "machine_learning_availability_checks_interval_description": "å¯į”¨æ€§æĒĸæŸĨäš‹é–“įš„é–“éš”īŧˆæ¯Ģį§’īŧ‰", + "machine_learning_availability_checks_timeout": "čĢ‹æą‚čļ…æ™‚", + "machine_learning_availability_checks_timeout_description": "å¯į”¨æ€§æĒĸæŸĨčļ…æ™‚īŧˆæ¯Ģį§’īŧ‰", "machine_learning_clip_model": "CLIP æ¨Ąåž‹", "machine_learning_clip_model_description": "é€™čŖĄæœ‰äģŊ CLIP æ¨Ąåž‹åå–Žã€‚æŗ¨æ„īŧšæ›´æ›æ¨Ąåž‹åžŒé ˆå°æ‰€æœ‰åœ–į‰‡é‡æ–°åŸˇčĄŒã€Œæ™ē慧搜尋」äģģ務。", "machine_learning_duplicate_detection": "é‡č¤‡é …į›Žåĩæ¸Ŧ", @@ -151,14 +159,14 @@ "machine_learning_smart_search_description": "äŊŋᔍ CLIP åĩŒå…Ĩ向量äģĨčĒžæ„æ–šåŧæœå°‹åŊąåƒ", "machine_learning_smart_search_enabled": "å•Ÿį”¨æ™ē慧搜尋", "machine_learning_smart_search_enabled_description": "åĻ‚æžœåœį”¨īŧŒåŊąåƒå°‡ä¸æœƒčĸĢᎍįĸŧäģĨ進行æ™ē慧搜尋。", - "machine_learning_url_description": "抟器學įŋ’äŧ翜å™¨įš„ URL。č‹Ĩ提䞛多個 URLīŧŒįŗģįĩ࿜ƒäžåēé€ä¸€å˜—čŠĻīŧŒį›´åˆ°å…ļ中一台成功回應į‚ēæ­ĸīŧˆį”ąå‰åˆ°åžŒīŧ‰ã€‚æœĒå›žæ‡‰įš„äŧ翜å™¨å°‡čĸĢæšĢ時åŋŊį•ĨīŧŒį›´åˆ°å…ļé‡æ–°ä¸Šįˇšã€‚", + "machine_learning_url_description": "抟器學įŋ’äŧ翜å™¨įš„ URL。č‹Ĩ提䞛多個 URLīŧŒįŗģįĩ࿜ƒäžåēé€ä¸€å˜—čŠĻīŧŒį›´åˆ°å…ļ中一č‡ē成功回應į‚ēæ­ĸīŧˆį”ąå‰åˆ°åžŒīŧ‰ã€‚æœĒå›žæ‡‰įš„äŧ翜å™¨å°‡čĸĢæšĢ時åŋŊį•ĨīŧŒį›´åˆ°å…ļé‡æ–°ä¸Šįˇšã€‚", "manage_concurrency": "įŽĄį†äŊĩį™ŧ", "manage_log_settings": "įŽĄį†æ—ĨčĒŒč¨­åŽš", "map_dark_style": "æˇąč‰˛æ¨Ŗåŧ", "map_enable_description": "å•Ÿį”¨åœ°åœ–åŠŸčƒŊ", "map_gps_settings": "åœ°åœ–čˆ‡ GPS č¨­åŽš", "map_gps_settings_description": "įŽĄį†åœ°åœ–čˆ‡ GPSīŧˆåå‘åœ°į†įˇ¨įĸŧīŧ‰č¨­åޚ", - "map_implications": "地圖功čƒŊäžčŗ´å¤–éƒ¨åœ–įŖšæœå‹™īŧˆtiles.immich.cloudīŧ‰", + "map_implications": "地圖功čƒŊäģ°čŗ´å¤–éƒ¨åœ–įŖšæœå‹™īŧˆtiles.immich.cloudīŧ‰", "map_light_style": "æˇēč‰˛æ¨Ŗåŧ", "map_manage_reverse_geocoding_settings": "įŽĄį†é€†å‘åœ°į†įˇ¨įĸŧč¨­åŽš", "map_reverse_geocoding": "åå‘åœ°į†įˇ¨įĸŧ", @@ -191,7 +199,7 @@ "nightly_tasks_start_time_setting_description": "äŧ翜å™¨é–‹å§‹åŸˇčĄŒå¤œé–“äģģå‹™įš„æ™‚é–“", "nightly_tasks_sync_quota_usage_setting": "同æ­Ĩ配額äŊŋį”¨æƒ…æŗ", "nightly_tasks_sync_quota_usage_setting_description": "æ šæ“šį›Žå‰įš„äŊŋį”¨é‡æ›´æ–°äŊŋį”¨č€…įš„å„˛å­˜é…éĄ", - "no_paths_added": "æ˛’æœ‰åˇ˛æˇģåŠ įš„čˇ¯åž‘", + "no_paths_added": "æ˛’æœ‰åˇ˛æ–°åĸžįš„čˇ¯åž‘", "no_pattern_added": "尚æœĒ新åĸžæŽ’除čĻå‰‡", "note_apply_storage_label_previous_assets": "提į¤ēīŧšč‹ĨčĻå°‡å„˛å­˜æ¨™įą¤åĨ—į”¨åˆ°å…ˆå‰ä¸Šå‚ŗįš„åĒ’éĢ”æĒ”æĄˆīŧŒčĢ‹åŸˇčĄŒ", "note_cannot_be_changed_later": "æŗ¨æ„īŧ𿭤荭åޚæ—ĨåžŒį„Ąæŗ•čŽŠæ›´īŧ", @@ -205,12 +213,12 @@ "notification_email_sent_test_email_button": "傺送æ¸ŦčŠĻé›ģ子éƒĩäģļä¸Ļå„˛å­˜", "notification_email_setting_description": "寄送é›ģ子éƒĩäģļ通įŸĨįš„č¨­åŽš", "notification_email_test_email": "傺送æ¸ŦčŠĻé›ģ子éƒĩäģļ", - "notification_email_test_email_failed": "į„Ąæŗ•į™ŧ送æ¸ŦčŠĻé›ģ子éƒĩäģļīŧŒčĢ‹æĒĸæŸĨæ‚¨įš„č¨­åŽščŗ‡č¨Š", - "notification_email_test_email_sent": "æ¸ŦčŠĻé›ģ子éƒĩäģļ厞į™ŧ送臺 {email}。čĢ‹æĒĸæŸĨæ‚¨įš„æ”ļäģļåŒŖã€‚", + "notification_email_test_email_failed": "į„Ąæŗ•å‚ŗé€æ¸ŦčŠĻé›ģ子éƒĩäģļīŧŒčĢ‹æĒĸæŸĨæ‚¨įš„č¨­åŽščŗ‡č¨Š", + "notification_email_test_email_sent": "æ¸ŦčŠĻé›ģ子éƒĩäģļ厞傺送臺 {email}。čĢ‹æĒĸæŸĨæ‚¨įš„æ”ļäģļåŒŖã€‚", "notification_email_username_description": "ᔍæ–ŧ與é›ģ子éƒĩäģļäŧ翜å™¨éŠ—č­‰įš„äŊŋį”¨č€…åį¨ą", "notification_enable_email_notifications": "å•Ÿį”¨é›ģ子éƒĩäģļ通įŸĨ", "notification_settings": "通įŸĨč¨­åŽš", - "notification_settings_description": "įŽĄį†é€šįŸĨ設įŊŽīŧŒåŒ…æ‹Ŧé›ģ子éƒĩäģļ", + "notification_settings_description": "įŽĄį†é€šįŸĨč¨­åŽšīŧŒåŒ…æ‹Ŧé›ģ子éƒĩäģļ", "oauth_auto_launch": "č‡Ē動啟動", "oauth_auto_launch_description": "進å…Ĩį™ģå…Ĩ頁éĸ時īŧŒč‡Ē動啟動 OAuth į™ģå…Ĩæĩį¨‹", "oauth_auto_register": "č‡Ē動č¨ģ冊", @@ -252,7 +260,7 @@ "server_external_domain_settings": "外部įļ˛åŸŸ", "server_external_domain_settings_description": "å…Ŧ開分äēĢ逪įĩįš„įļ˛åŸŸīŧŒåŒ…åĢ http(s)://", "server_public_users": "å…Ŧ開äŊŋᔍ者", - "server_public_users_description": "在將äŊŋį”¨č€…æ–°åĸžåˆ°å…ąäēĢᛏį°ŋ時īŧŒæœƒåˆ—å‡ē所有äŊŋį”¨č€…įš„å§“åčˆ‡é›ģ子éƒĩäģļã€‚åœį”¨æ­¤åŠŸčƒŊ垌īŧŒäŊŋį”¨č€…æ¸…å–Žå°‡åƒ…äž›įŗģįĩąįŽĄį†å“ĄæŸĨįœ‹ã€‚", + "server_public_users_description": "在將äŊŋį”¨č€…æ–°åĸžåˆ°å…ąäēĢᛏį°ŋ時īŧŒæœƒåˆ—å‡ē所有äŊŋį”¨č€…įš„å§“åčˆ‡é›ģ子éƒĩäģļã€‚åœį”¨æ­¤åŠŸčƒŊ垌īŧŒäŊŋį”¨č€…æ¸…å–Žå°‡åƒ…äž›įŗģįĩąįŽĄį†å“ĄæĒĸčĻ–ã€‚", "server_settings": "äŧ翜å™¨č¨­åޚ", "server_settings_description": "įŽĄį†äŧ翜å™¨č¨­åޚ", "server_welcome_message": "æ­ĄčŋŽč¨Šæ¯", @@ -262,10 +270,10 @@ "slideshow_duration_description": "每åŧĩåœ–į‰‡æ”žæ˜ įš„į§’æ•¸", "smart_search_job_description": "åŸˇčĄŒæŠŸå™¨å­¸įŋ’有劊æ–ŧæ™ē慧搜尋", "storage_template_date_time_description": "æĒ”æĄˆįš„åģēįĢ‹æ™‚é–“æˆŗæœƒį”¨æ–ŧæ—ĨæœŸčˆ‡æ™‚é–“čŗ‡č¨Š", - "storage_template_date_time_sample": "æŽĄæ¨Ŗæ™‚é–“ {date}", + "storage_template_date_time_sample": "å–æ¨Ŗæ™‚é–“ {date}", "storage_template_enable_description": "å•Ÿį”¨å„˛å­˜į¯„æœŦåŧ•擎", - "storage_template_hash_verification_enabled": "雜暊å‡Ŋæ•°éŠ—č­‰åˇ˛å•Ÿį”¨", - "storage_template_hash_verification_enabled_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}。", @@ -286,15 +294,15 @@ "template_email_update_album": "ᛏį°ŋæ›´æ–°į¯„æœŦ", "template_email_welcome": "æ­ĄčŋŽéƒĩäģļᝄæœŦ", "template_settings": "通įŸĨᝄæœŦ", - "template_settings_description": "įŽĄį†é€šįŸĨįš„č‡ĒåŽšįžŠį¯„æœŦ", - "theme_custom_css_settings": "č‡ĒåŽšįžŠ CSS", + "template_settings_description": "įŽĄį†é€šįŸĨįš„č‡Ē荂ᝄæœŦ", + "theme_custom_css_settings": "č‡Ē訂 CSS", "theme_custom_css_settings_description": "可äģĨį”¨åą¤į–Šæ¨ŖåŧčĄ¨īŧˆCSSīŧ‰äž†č‡Ē訂 Immich įš„č¨­č¨ˆã€‚", "theme_settings": "ä¸ģéĄŒč¨­åŽš", - "theme_settings_description": "č‡Ē訂 Immich įš„įļ˛é į•Œéĸ", + "theme_settings_description": "č‡Ē訂 Immich įš„įļ˛é äģ‹éĸ", "thumbnail_generation_job": "į”ĸį”Ÿį¸Žåœ–", "thumbnail_generation_job_description": "į‚ē每個æĒ”æĄˆį”ĸį”Ÿå¤§ã€å°åŠæ¨ĄįŗŠį¸Žåœ–īŧŒäšŸį‚ē每äŊäēēį‰Šį”ĸį”Ÿį¸Žåœ–", "transcoding_acceleration_api": "加速 API", - "transcoding_acceleration_api_description": "æ­¤ API 會äŊŋį”¨æ‚¨įš„įĄŦéĢ”äģĨ加速čŊ‰įĸŧæĩį¨‹ã€‚æ­¤č¨­åŽšæŽĄã€Œį›ĄåŠ›č€Œį‚ēã€æ¨Ąåŧâ€”—č‹ĨčŊ‰įĸŧå¤ąæ•—īŧŒå°‡æœƒå›žé€€č‡ŗčģŸéĢ”čŊ‰įĸŧ。VP9 是åĻčƒŊ運äŊœīŧŒå–æąēæ–ŧæ‚¨įš„įĄŦéĢ”é…įŊŽã€‚", + "transcoding_acceleration_api_description": "æ­¤ API 會äŊŋį”¨æ‚¨įš„įĄŦéĢ”äģĨ加速čŊ‰įĸŧæĩį¨‹ã€‚æ­¤č¨­åŽšæŽĄã€Œį›ĄåŠ›č€Œį‚ēã€æ¨Ąåŧâ€”—č‹ĨčŊ‰įĸŧå¤ąæ•—īŧŒå°‡æœƒå›žé€€č‡ŗčģŸéĢ”čŊ‰įĸŧ。VP9 是åĻčƒŊ運äŊœīŧŒå–æąēæ–ŧæ‚¨įš„įĄŦéĢ”č¨­åŽšã€‚", "transcoding_acceleration_nvenc": "NVENCīŧˆéœ€čρ NVIDIA GPUīŧ‰", "transcoding_acceleration_qsv": "Quick Syncīŧˆéœ€čρįŦŦ 7 äģŖæˆ–æ›´æ–°įš„ Intel 處ᐆ噍īŧ‰", "transcoding_acceleration_rkmpp": "RKMPPīŧˆåƒ…éŠį”¨æ–ŧ Rockchip SOCsīŧ‰", @@ -314,7 +322,7 @@ "transcoding_constant_quality_mode_description": "ICQ įš„æ•ˆæžœå„Ēæ–ŧ CQPīŧŒäŊ†éƒ¨åˆ†įĄŦéĢ”åŠ é€ŸčŖįŊŽä¸æ”¯æ´æ­¤æ¨Ąåŧã€‚č¨­åŽšæ­¤é¸é …æ™‚īŧŒåœ¨äŊŋᔍäģĨ品čŗĒį‚ēåŸēæē–įš„įˇ¨įĸŧ時會å„Ēå…ˆæŽĄį”¨æ‰€æŒ‡åŽšįš„æ¨Ąåŧã€‚NVENC 不支援 ICQīŧŒå› æ­¤æ­¤č¨­åޚ圍 NVENC 下會čĸĢåŋŊį•Ĩ。", "transcoding_constant_rate_factor": "æ†åŽšé€ŸįŽ‡å› å­īŧˆ-crfīŧ‰", "transcoding_constant_rate_factor_description": "čĻ–č¨Šå“čŗĒį­‰į´šã€‚å…¸åž‹å€ŧį‚ē H.264 įš„ 23、HEVC įš„ 28、VP9 įš„ 31 和 AV1 įš„ 35。數å€ŧčļŠäŊŽīŧŒå“čŗĒčļŠåĨŊīŧŒäŊ†æœƒį”ĸį”Ÿčŧƒå¤§įš„æĒ”æĄˆã€‚", - "transcoding_disabled_description": "不對äģģäŊ•åŊąį‰‡é€˛čĄŒčŊ‰įĸŧīŧŒå¯čƒŊæœƒå°Žč‡´éƒ¨åˆ†åŽĸæˆļįĢ¯į„Ąæŗ•æ­Ŗå¸¸æ’­æ”ž", + "transcoding_disabled_description": "不對äģģäŊ•åŊąį‰‡é€˛čĄŒčŊ‰įĸŧīŧŒå¯čƒŊæœƒå°Žč‡´éƒ¨åˆ†į”¨æˆļįĢ¯į„Ąæŗ•æ­Ŗå¸¸æ’­æ”ž", "transcoding_encoding_options": "ᎍįĸŧ選項", "transcoding_encoding_options_description": "č¨­åŽšįˇ¨įĸŧåŊąį‰‡įš„ᎍ觪įĸŧå™¨ã€č§ŖæžåēĻ、品čŗĒ和å…ļäģ–選項", "transcoding_hardware_acceleration": "įĄŦéĢ”åŠ é€Ÿ", @@ -326,11 +334,11 @@ "transcoding_max_bitrate": "最大äŊå…ƒé€Ÿįއ", "transcoding_max_bitrate_description": "č¨­åŽšæœ€å¤§äŊå…ƒįŽ‡å¯äģĨ在čŧ•åžŽįŠ§į‰˛å“čŗĒįš„æƒ…æŗä¸‹īŧŒčŽ“æĒ”æĄˆå¤§å°æ›´åŽšæ˜“é æ¸Ŧ。在 720p č§ŖæžåēĻ下īŧŒVP9 或 HEVC įš„å…¸åž‹å€ŧį‚ē 2600 kbit/sīŧŒH.264 則į‚ē 4500 kbit/sã€‚č¨­į‚ē 0 å‰‡åœį”¨æ­¤åŠŸčƒŊ。", "transcoding_max_keyframe_interval": "最大關éĩ嚀間隔", - "transcoding_max_keyframe_interval_description": "設įŊŽé—œéĩåš€äš‹é–“įš„æœ€å¤§åš€čˇã€‚čŧƒäŊŽįš„å€ŧ會降äŊŽåŖ“į¸Žæ•ˆįŽ‡īŧŒäŊ†å¯äģĨ攚善搜尋時間īŧŒä¸Ļ有可čƒŊ會攚善åŋĢé€ŸčŽŠå‹•å ´æ™¯įš„å“čŗĒ。0 會č‡Ē動荭įŊŽæ­¤å€ŧ。", + "transcoding_max_keyframe_interval_description": "č¨­åŽšé—œéĩåš€äš‹é–“įš„æœ€å¤§åš€čˇã€‚čŧƒäŊŽįš„å€ŧ會降äŊŽåŖ“į¸Žæ•ˆįŽ‡īŧŒäŊ†å¯äģĨ攚善搜尋時間īŧŒä¸Ļ有可čƒŊ會攚善åŋĢé€ŸčŽŠå‹•å ´æ™¯įš„å“čŗĒ。0 會č‡Ēå‹•č¨­åŽšæ­¤å€ŧ。", "transcoding_optimal_description": "é̘æ–ŧį›Žæ¨™č§ŖæžåēĻæˆ–æ ŧåŧä¸åœ¨å¯æŽĨå—į¯„åœįš„åŊąį‰‡", "transcoding_policy": "čŊ‰įĸŧį­–į•Ĩ", "transcoding_policy_description": "č¨­åŽšåŊąį‰‡é€˛čĄŒčŊ‰įĸŧįš„æĸäģļ", - "transcoding_preferred_hardware_device": "éϖ遏įĄŦé̔荭備", + "transcoding_preferred_hardware_device": "éϖ遏įĄŦéĢ”čŖįŊŽ", "transcoding_preferred_hardware_device_description": "åƒ…éŠį”¨æ–ŧ VAAPI 和 QSVã€‚č¨­åŽšį”¨æ–ŧįĄŦéĢ”čŊ‰įĸŧįš„ dri ᝀéģžã€‚", "transcoding_preset_preset": "預設å€ŧīŧˆ-presetīŧ‰", "transcoding_preset_preset_description": "åŖ“į¸Žé€ŸåēĻ。čŧƒæ…ĸįš„é č¨­å€ŧ會į”ĸį”Ÿčŧƒå°įš„æĒ”æĄˆīŧŒä¸Ļ在鎖厚äŊå…ƒįŽ‡æ™‚æå‡å“čŗĒ。VP9 在速åēĻé̘æ–ŧ「faster」時將åŋŊį•Ĩč¨­åŽšã€‚", @@ -342,10 +350,10 @@ "transcoding_target_resolution": "į›Žæ¨™č§ŖæžåēĻ", "transcoding_target_resolution_description": "čŧƒéĢ˜įš„č§ŖæžåēĻ可äģĨäŋį•™æ›´å¤šį´°į¯€īŧŒäŊ†įˇ¨įĸŧ時間čŧƒé•ˇīŧŒæĒ”æĄˆäšŸčŧƒå¤§īŧŒä¸”可čƒŊ降äŊŽæ‡‰į”¨į¨‹åŧįš„回應速åēĻ。", "transcoding_temporal_aq": "時間č‡Ē遊應量化īŧˆTemporal AQīŧ‰", - "transcoding_temporal_aq_description": "åƒ…éŠį”¨æ–ŧ NVENCīŧŒå¯æå‡éĢ˜į´°į¯€ã€äŊŽå‹•æ…‹å ´æ™¯įš„į•ĢčŗĒ。可čƒŊ與čŧƒčˆŠįš„č¨­å‚™ä¸į›¸åŽšã€‚", + "transcoding_temporal_aq_description": "åƒ…éŠį”¨æ–ŧ NVENCīŧŒå¯æå‡éĢ˜į´°į¯€ã€äŊŽå‹•æ…‹å ´æ™¯įš„į•ĢčŗĒ。可čƒŊ與čŧƒčˆŠįš„čŖįŊŽä¸į›¸åŽšã€‚", "transcoding_threads": "åŸˇčĄŒįˇ’æ•¸é‡", - "transcoding_threads_description": "čŧƒéĢ˜įš„å€ŧ會加åŋĢᎍįĸŧ速åēĻīŧŒäŊ†æœƒæ¸›å°‘äŧ翜å™¨åœ¨é‹čĄŒéŽį¨‹ä¸­č™•ᐆå…ļäģ–äģģå‹™įš„įŠē間。此å€ŧ不應čļ…過 CPU æ ¸åŋƒæ•¸ã€‚設åޚį‚ē 0 可äģĨæœ€å¤§åŒ–åˆŠį”¨įŽ‡ã€‚", - "transcoding_tone_mapping": "色čĒŋ映射", + "transcoding_threads_description": "čŧƒéĢ˜įš„å€ŧ會加åŋĢᎍįĸŧ速åēĻīŧŒäŊ†æœƒæ¸›å°‘äŧ翜å™¨åœ¨åŸˇčĄŒéŽį¨‹ä¸­č™•ᐆå…ļäģ–äģģå‹™įš„įŠē間。此å€ŧ不應čļ…過 CPU æ ¸åŋƒæ•¸ã€‚設åޚį‚ē 0 可äģĨæœ€å¤§åŒ–åˆŠį”¨įŽ‡ã€‚", + "transcoding_tone_mapping": "色čĒŋ對映", "transcoding_tone_mapping_description": "在將 HDR åŊąį‰‡čŊ‰æ›į‚ē SDR 時īŧŒį›Ąé‡įļ­æŒåŽŸå§‹č§€æ„Ÿã€‚æ¯į¨Žæŧ”įŽ—æŗ•åœ¨č‰˛åŊŠã€į´°į¯€å’ŒäēŽåēĻæ–šéĸéƒŊæœ‰ä¸åŒįš„æŦŠčĄĄã€‚Hable äŋį•™į´°į¯€īŧŒMobius äŋį•™č‰˛åŊŠīŧŒReinhard äŋį•™äēŽåēĻ。", "transcoding_transcode_policy": "čŊ‰įĸŧį­–į•Ĩ", "transcoding_transcode_policy_description": "åŊąį‰‡äŊ•æ™‚æ‡‰é€˛čĄŒčŊ‰įĸŧįš„į­–į•Ĩ。HDR åŊąį‰‡ä¸€åŽšæœƒčŊ‰įĸŧīŧˆé™¤éžåœį”¨čŊ‰įĸŧīŧ‰ã€‚", @@ -360,7 +368,7 @@ "trash_settings_description": "įŽĄį†åžƒåœžæĄļč¨­åŽš", "unlink_all_oauth_accounts": "č§Ŗé™¤æ‰€æœ‰ OAuth å¸ŗč™Ÿįš„é€Ŗįĩ", "unlink_all_oauth_accounts_description": "圍過į§ģč‡ŗæ–°įš„æœå‹™æäž›č€…å‰īŧŒčĢ‹ä¸čρåŋ˜č¨˜čĻå…ˆč§Ŗé™¤æ‰€æœ‰čˆ‡ OAuth 叺æˆļįš„é€Ŗįĩã€‚", - "unlink_all_oauth_accounts_prompt": "您是åĻįĸēčĒčĻč§Ŗé™¤æ‰€æœ‰čˆ‡ OAuth 叺æˆļįš„é€Ŗįĩ? æ‰€æœ‰į›¸é—œįš„äŊŋᔍ者čēĢäģŊ會čĸĢ重設īŧŒä¸Ļ且不čƒŊčĸĢ還原。", + "unlink_all_oauth_accounts_prompt": "您是åĻįĸēčĒčĻč§Ŗé™¤æ‰€æœ‰čˆ‡ OAuth 叺æˆļįš„é€ŖįĩīŧŸæ‰€æœ‰į›¸é—œįš„äŊŋᔍ者čēĢäģŊ會čĸĢ重設īŧŒä¸Ļ且不čƒŊčĸĢ還原。", "user_cleanup_job": "æ¸…į†äŊŋᔍ者", "user_delete_delay": "{user} įš„å¸ŗč™Ÿå’Œé …į›Žæœƒåœ¨ {delay, plural, one {# 夊} other {# 夊}} 垌永䚅åˆĒ除。", "user_delete_delay_settings": "åģļ垌åˆĒ除", @@ -387,14 +395,12 @@ "admin_password": "įŽĄį†å“Ąå¯†įĸŧ", "administration": "įŽĄį†", "advanced": "進階", - "advanced_settings_beta_timeline_subtitle": "čŠĻį”¨å…¨æ–°įš„æ‡‰į”¨į¨‹åŧéĢ”éŠ—", - "advanced_settings_beta_timeline_title": "æ¸ŦčŠĻį‰ˆæ™‚é–“čģ¸", "advanced_settings_enable_alternate_media_filter_subtitle": "äŊŋį”¨æ­¤é¸é …å¯åœ¨åŒæ­Ĩ時䞝å…ļäģ–æĸäģļį¯Šé¸åĒ’éĢ”ã€‚åƒ…åœ¨æ‡‰į”¨į¨‹åŧį„Ąæŗ•åĩæ¸Ŧåˆ°æ‰€æœ‰į›¸į°ŋ時再嘗čŠĻäŊŋį”¨ã€‚", "advanced_settings_enable_alternate_media_filter_title": "[å¯Ļ銗性] äŊŋᔍæ›ŋäģŖįš„čŖįŊŽį›¸į°ŋ同æ­Ĩį¯Šé¸å™¨", "advanced_settings_log_level_title": "æ—ĨčĒŒį­‰į´šīŧš{level}", - "advanced_settings_prefer_remote_subtitle": "éƒ¨åˆ†čŖįŊŽåžžæœŦ抟ˊéĢ”åēĢčŧ‰å…Ĩį¸Žåœ–įš„é€ŸåēĻ非常æ…ĸã€‚å•Ÿį”¨æ­¤č¨­åŽšå¯æ”šį‚ēčŧ‰å…Ĩ遠įĢ¯åœ–į‰‡ã€‚", + "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_readonly_mode_subtitle": "é–‹å•Ÿå”¯čŽ€æ¨ĄåŧåžŒīŧŒį…§į‰‡åĒčƒŊį€čĻŊīŧŒåƒæ˜¯å¤šé¸åŊąåƒã€åˆ†äēĢ、投攞、åˆĒé™¤į­‰åŠŸčƒŊéƒŊ會關閉。可在ä¸ģį•Ģéĸ透過äŊŋį”¨č€…é ­åƒäž†é–‹å•Ÿ/é—œé–‰å”¯čŽ€æ¨Ąåŧ", "advanced_settings_readonly_mode_title": "å”¯čŽ€æ¨Ąåŧ", @@ -402,7 +408,7 @@ "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_tile_subtitle": "進階äŊŋį”¨č€…č¨­åŽš", "advanced_settings_troubleshooting_subtitle": "å•Ÿį”¨éĄå¤–åŠŸčƒŊäģĨé€˛čĄŒį–‘é›ŖæŽ’č§Ŗ", "advanced_settings_troubleshooting_title": "į–‘é›ŖæŽ’č§Ŗ", "age_months": "{months, plural, one {# 個月} other {# 個月}}", @@ -425,6 +431,7 @@ "album_remove_user_confirmation": "įĸē厚čρį§ģ除 {user} 嗎īŧŸ", "album_search_not_found": "扞不到įŦĻ合搜尋æĸäģļįš„į›¸į°ŋ", "album_share_no_users": "įœ‹äž†æ‚¨čˆ‡æ‰€æœ‰äŊŋį”¨č€…å…ąäēĢäē†é€™æœŦᛏį°ŋīŧŒæˆ–æ˛’æœ‰å…ļäģ–äŊŋį”¨č€…å¯äž›åˆ†äēĢ。", + "album_summary": "ᛏį°ŋ摘čρ", "album_updated": "æ›´æ–°į›¸į°ŋ時", "album_updated_setting_description": "į•ļå…ąäēĢᛏį°ŋæœ‰æ–°é …į›Žæ™‚į”¨é›ģ子éƒĩäģļ通įŸĨ我", "album_user_left": "é›ĸ開 {album}", @@ -437,12 +444,12 @@ "album_viewer_appbar_share_leave": "é›ĸ開ᛏį°ŋ", "album_viewer_appbar_share_to": "分äēĢįĩĻ", "album_viewer_page_share_add_users": "邀čĢ‹å…ļäģ–äēē", - "album_with_link_access": "äģģäŊ•æ“æœ‰é€Ŗįĩįš„äēēéƒŊčƒŊæŸĨįœ‹æ­¤į›¸į°ŋä¸­įš„į…§į‰‡čˆ‡äŊŋį”¨č€…ã€‚", + "album_with_link_access": "äģģäŊ•æ“æœ‰é€Ŗįĩįš„äēēéƒŊčƒŊæĒĸčĻ–æ­¤į›¸į°ŋä¸­įš„į…§į‰‡čˆ‡äēēį‰Šã€‚", "albums": "ᛏį°ŋ", "albums_count": "{count, plural, one {{count, number} 個ᛏį°ŋ} other {{count, number} 個ᛏį°ŋ}}", "albums_default_sort_order": "預荭ᛏį°ŋ排åē", "albums_default_sort_order_description": "åģēįĢ‹æ–°į›¸į°ŋ時čĻåˆå§‹åŒ–é …į›ŽæŽ’åēæ–šåŧã€‚", - "albums_feature_description": "一įŗģ列可äģĨ分äēĢįĩĻå…ļäģ–ᔍæˆļįš„é …į›Žã€‚", + "albums_feature_description": "一įŗģ列可äģĨ分äēĢįĩĻå…ļäģ–äŊŋį”¨č€…įš„é …į›Žã€‚", "albums_on_device_count": "æ­¤čŖįŊŽæœ‰ ({count}) 個ᛏį°ŋ", "all": "全部", "all_albums": "æ‰€æœ‰į›¸į°ŋ", @@ -463,13 +470,14 @@ "app_bar_signout_dialog_title": "į™ģå‡ē", "app_settings": "æ‡‰į”¨į¨‹åŧč¨­åޚ", "appears_in": "å‡ēįžæ–ŧ", + "apply_count": "æ‡‰į”¨ ({count, number})", "archive": "封存", "archive_action_prompt": "厞將 ({count}) 個加å…Ĩé€˛å°å­˜", "archive_or_unarchive_photo": "封存或取æļˆå°å­˜į…§į‰‡", "archive_page_no_archived_assets": "æœĒ扞到封存åĒ’éĢ”", "archive_page_title": "封存 ({count})", "archive_size": "封存大小", - "archive_size_description": "č¨­åŽščρ䏋čŧ‰įš„封存æĒ”æĄˆå¤§å° (å–ŽäŊīŧš GiB)", + "archive_size_description": "č¨­åŽščρ䏋čŧ‰įš„封存æĒ”æĄˆå¤§å° (å–ŽäŊīŧšGiB)", "archived": "厞封存", "archived_count": "{count, plural, other {厞封存 # å€‹é …į›Ž}}", "are_these_the_same_person": "同一äŊäēēį‰ŠīŧŸ", @@ -483,18 +491,20 @@ "asset_has_unassigned_faces": "åĒ’éĢ”æœ‰æœĒåˆ†é…įš„č‡‰å­”", "asset_hashing": "æ­Ŗåœ¨č¨ˆįŽ—é›œæšŠâ€Ļ", "asset_list_group_by_sub_title": "åˆ†éĄžæ–šåŧ", - "asset_list_layout_settings_dynamic_layout_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_month_day": "月äģŊ和æ—Ĩ期", - "asset_list_layout_sub_title": "å¸ƒåą€", - "asset_list_settings_subtitle": "ᛏቇæ ŧį‹€å¸ƒåą€č¨­åŽš", + "asset_list_layout_sub_title": "į‰ˆéĸ", + "asset_list_settings_subtitle": "ᛏቇæ ŧį‹€į‰ˆéĸč¨­åŽš", "asset_list_settings_title": "ᛏቇæ ŧį‹€æĒĸčĻ–", "asset_offline": "åĒ’éĢ”é›ĸ᎚", "asset_offline_description": "此外部åĒ’éĢ”åˇ˛į„Ąæŗ•åœ¨įŖįĸŸä¸­æ‰žåˆ°ã€‚č̋聝įĩĄæ‚¨įš„ Immich įŽĄį†å“ĄäģĨ取垗協劊。", "asset_restored_successfully": "åĒ’éĢ”åžŠåŽŸæˆåŠŸ", "asset_skipped": "åˇ˛čˇŗéŽ", "asset_skipped_in_trash": "åˇ˛åœ¨åžƒåœžæĄļ", + "asset_trashed": "čŗ‡į”ĸčĸĢä¸ŸæŖ„", + "asset_troubleshoot": "čŗ‡į”ĸ故障排除", "asset_uploaded": "åˇ˛ä¸Šå‚ŗ", "asset_uploading": "ä¸Šå‚ŗä¸­â€Ļ", "asset_viewer_settings_subtitle": "įŽĄį†æ‚¨įš„åĒ’éĢ”åēĢæĒĸčĻ–å™¨č¨­åŽš", @@ -523,13 +533,15 @@ "assets_were_part_of_album_count": "{count, plural, one {芲åĒ’é̔厞} other {這äē›åĒ’é̔厞}}åœ¨į›¸į°ŋ中", "assets_were_part_of_albums_count": "{count, plural, one {個} other {個}}é …į›Žåˇ˛čĸĢå„˛å­˜åœ¨į›¸į°ŋ中", "authorized_devices": "åˇ˛æŽˆæŦŠčŖįŊŽ", - "automatic_endpoint_switching_subtitle": "į•ļå¯į”¨æ™‚īŧŒé€éŽæŒ‡åŽšįš„ Wi-Fi 在æœŦåœ°é€ŖįˇšīŧŒå…ļäģ–æƒ…æŗå‰‡äŊŋᔍæ›ŋäģŖé€Ŗįˇš", + "automatic_endpoint_switching_subtitle": "į•ļå¯į”¨æ™‚īŧŒé€éŽæŒ‡åŽšįš„ Wi-Fi 在æœŦæŠŸé€ŖįˇšīŧŒå…ļäģ–æƒ…æŗå‰‡äŊŋᔍæ›ŋäģŖé€Ŗįˇš", "automatic_endpoint_switching_title": "č‡Ē動 URL 切換", "autoplay_slideshow": "č‡Ē動播攞åšģį‡ˆį‰‡", - "back": "čŋ”回", - "back_close_deselect": "čŋ”回、關閉及取æļˆé¸å–", + "back": "上一頁", + "back_close_deselect": "回上一頁、關閉ä¸Ļ取æļˆé¸å–", + "background_backup_running_error": "垌č‡ē備äģŊį›Žå‰æ­Ŗåœ¨åŸˇčĄŒīŧŒį„Ąæŗ•啟動手動備äģŊ", "background_location_permission": "čƒŒæ™¯å­˜å–äŊįŊŽæŦŠé™", "background_location_permission_content": "į‚ēäē†åœ¨čƒŒæ™¯åŸˇčĄŒæ™‚切換įļ˛čˇ¯īŧŒImmich åŋ…須始įĩ‚å…ˇæœ‰į˛žįĸēäŊįŊŽå­˜å–æŦŠé™īŧŒæ‰čƒŊčŽ€å– Wi-Fi įļ˛čˇ¯åį¨ą", + "background_options": "čƒŒæ™¯é¸é …", "backup": "備äģŊ", "backup_album_selection_page_albums_device": "čŖįŊŽä¸Šįš„ᛏį°ŋīŧˆ{count}īŧ‰", "backup_album_selection_page_albums_tap": "éģžä¸€ä¸‹äģĨ選取īŧŒéģžå…Šä¸‹äģĨ排除", @@ -537,9 +549,10 @@ "backup_album_selection_page_select_albums": "é¸å–į›¸į°ŋ", "backup_album_selection_page_selection_info": "é¸å–čŗ‡č¨Š", "backup_album_selection_page_total_assets": "į¸Ŋ不重複åĒ’éĢ”æ•¸", + "backup_albums_sync": "備äģŊᛏį°ŋ同æ­Ĩ", "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": "æ­Ŗåœ¨ä¸Šå‚ŗ {filename}", "backup_background_service_default_notification": "æ­Ŗåœ¨æĒĸæŸĨ新åĒ’éĢ”â€Ļ", "backup_background_service_error_title": "備äģŊ錯čǤ", @@ -556,7 +569,7 @@ "backup_controller_page_background_charging": "僅在充é›ģ時", "backup_controller_page_background_configure_error": "čƒŒæ™¯æœå‹™č¨­åŽšå¤ąæ•—", "backup_controller_page_background_delay": "新åĒ’é̔備äģŊåģļ遲īŧš{duration}", - "backup_controller_page_background_description": "é–‹å•ŸčƒŒæ™¯æœå‹™īŧŒåŗå¯åœ¨ä¸éœ€æ‰“é–‹ App įš„æƒ…æŗä¸‹īŧŒč‡Ē動備äģŊ所有新åĒ’éĢ”", + "backup_controller_page_background_description": "é–‹å•ŸčƒŒæ™¯æœå‹™īŧŒåŗå¯åœ¨ä¸éœ€é–‹å•Ÿ App įš„æƒ…æŗä¸‹īŧŒč‡Ē動備äģŊ所有新åĒ’éĢ”", "backup_controller_page_background_is_off": "čƒŒæ™¯č‡Ē動備äģŊåˇ˛é—œé–‰", "backup_controller_page_background_is_on": "čƒŒæ™¯č‡Ē動備äģŊåˇ˛é–‹å•Ÿ", "backup_controller_page_background_turn_off": "é—œé–‰čƒŒæ™¯æœå‹™", @@ -566,7 +579,7 @@ "backup_controller_page_backup_selected": "厞遏䏭īŧš ", "backup_controller_page_backup_sub": "厞備äģŊįš„į…§į‰‡å’ŒåŊąį‰‡", "backup_controller_page_created": "åģēįĢ‹æ™‚é–“īŧš{date}", - "backup_controller_page_desc_backup": "開啟前台備äģŊīŧŒåœ¨æ‰“é–‹ App 時č‡Ē動將新åĒ’éĢ”ä¸Šå‚ŗč‡ŗäŧ翜å™¨ã€‚", + "backup_controller_page_desc_backup": "開啟前č‡ē備äģŊīŧŒåœ¨é–‹å•Ÿ App 時č‡Ē動將新åĒ’éĢ”ä¸Šå‚ŗč‡ŗäŧ翜å™¨ã€‚", "backup_controller_page_excluded": "åˇ˛æŽ’é™¤īŧš ", "backup_controller_page_failed": "å¤ąæ•—īŧˆ{count}īŧ‰", "backup_controller_page_filename": "æĒ”æĄˆåį¨ąīŧš{filename} [{size}]", @@ -577,15 +590,16 @@ "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_storage_format": "{used} ä¸­įš„ {total} 厞äŊŋᔍ", + "backup_controller_page_status_off": "前č‡ēč‡Ē動備äģŊåˇ˛é—œé–‰", + "backup_controller_page_status_on": "前č‡ēč‡Ē動備äģŊåˇ˛é–‹å•Ÿ", + "backup_controller_page_storage_format": "{used} / {total} 厞äŊŋᔍ", "backup_controller_page_to_backup": "čρ備äģŊįš„į›¸į°ŋ", "backup_controller_page_total_sub": "åˇ˛é¸å–į›¸į°ŋä¸­įš„æ‰€æœ‰ä¸é‡č¤‡įš„į…§į‰‡čˆ‡åŊąį‰‡", - "backup_controller_page_turn_off": "關閉前台備äģŊ", - "backup_controller_page_turn_on": "開啟前台備äģŊ", + "backup_controller_page_turn_off": "關閉前č‡ē備äģŊ", + "backup_controller_page_turn_on": "開啟前č‡ē備äģŊ", "backup_controller_page_uploading_file_info": "ä¸Šå‚ŗä¸­įš„æĒ”æĄˆčŗ‡č¨Š", "backup_err_only_album": "不čƒŊį§ģé™¤å”¯ä¸€įš„į›¸į°ŋ", + "backup_error_sync_failed": "同æ­Ĩå¤ąæ•—īŧŒį„Ąæŗ•處ᐆ備äģŊ。", "backup_info_card_assets": "個åĒ’éĢ”", "backup_manual_cancelled": "åˇ˛å–æļˆ", "backup_manual_in_progress": "ä¸Šå‚ŗæ­Ŗåœ¨é€˛čĄŒä¸­īŧŒčĢ‹į¨åžŒå†čŠĻ", @@ -593,22 +607,20 @@ "backup_manual_title": "ä¸Šå‚ŗį‹€æ…‹", "backup_options": "備äģŊ選項", "backup_options_page_title": "備äģŊ選項", - "backup_setting_subtitle": "įŽĄį†čƒŒæ™¯čˆ‡å‰å°ä¸Šå‚ŗč¨­åŽš", + "backup_setting_subtitle": "įŽĄį†čƒŒæ™¯čˆ‡å‰č‡ēä¸Šå‚ŗč¨­åŽš", "backup_settings_subtitle": "įŽĄį†ä¸Šå‚ŗč¨­åŽš", "backward": "į”ąčˆŠč‡ŗæ–°", - "beta_sync": "æ¸ŦčŠĻį‰ˆåŒæ­Ĩį‹€æ…‹", - "beta_sync_subtitle": "įŽĄį†æ–°įš„åŒæ­Ĩįŗģįĩą", "biometric_auth_enabled": "į”Ÿį‰Ščž¨č­˜éŠ—č­‰åˇ˛å•Ÿį”¨", "biometric_locked_out": "æ‚¨åˇ˛čĸĢéŽ–åŽšį„Ąæŗ•äŊŋį”¨į”Ÿį‰Ščž¨č­˜éŠ—č­‰", "biometric_no_options": "æ˛’æœ‰į”Ÿį‰Ščž¨č­˜é¸é …å¯į”¨", - "biometric_not_available": "æ­¤č¨­å‚™ä¸Šį„Ąæŗ•äŊŋį”¨į”Ÿį‰Ščž¨č­˜éŠ—č­‰", + "biometric_not_available": "æ­¤čŖįŊŽä¸Šį„Ąæŗ•äŊŋį”¨į”Ÿį‰Ščž¨č­˜éŠ—č­‰", "birthdate_saved": "å‡ēį”Ÿæ—ĨæœŸå„˛å­˜æˆåŠŸ", "birthdate_set_description": "å‡ēį”Ÿæ—ĨæœŸį”¨æ–ŧč¨ˆįŽ—æ­¤äēēåœ¨į…§į‰‡æ‹æ”æ™‚įš„åš´éŊĄã€‚", "blurred_background": "čƒŒæ™¯æ¨ĄįŗŠ", "bugs_and_feature_requests": "錯čĒ¤åŠåŠŸčƒŊčĢ‹æą‚", "build": "åģēįŊŽįˇ¨č™Ÿ", "build_image": "åģēįŊŽæ˜ åƒ", - "bulk_delete_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", @@ -625,7 +637,7 @@ "cache_settings_subtitle": "控åˆļ Immich čĄŒå‹•æ‡‰į”¨į¨‹åŧįš„åŋĢå–čĄŒį‚ē", "cache_settings_tile_subtitle": "č¨­åŽšæœŦæŠŸå„˛å­˜čĄŒį‚ē", "cache_settings_tile_title": "æœŦæŠŸå„˛å­˜įŠē間", - "cache_settings_title": "įˇŠå­˜č¨­åŽš", + "cache_settings_title": "åŋĢå–č¨­åŽš", "camera": "į›¸æŠŸ", "camera_brand": "į›¸æŠŸå“į‰Œ", "camera_model": "į›¸æŠŸåž‹č™Ÿ", @@ -636,7 +648,7 @@ "cannot_merge_people": "į„Ąæŗ•åˆäŊĩäēēį‰Š", "cannot_undo_this_action": "此操äŊœį„Ąæŗ•垊原īŧ", "cannot_update_the_description": "į„Ąæŗ•æ›´æ–°æčŋ°", - "cast": "投åŊą", + "cast": "投攞", "cast_description": "č¨­åŽšå¯į”¨įš„æŠ•æ”žčŖįŊŽ", "change_date": "čŽŠæ›´æ—Ĩ期", "change_description": "čŽŠæ›´æčŋ°", @@ -655,26 +667,28 @@ "change_pin_code": "čŽŠæ›´ PIN įĸŧ", "change_your_password": "čŽŠæ›´æ‚¨įš„å¯†įĸŧ", "changed_visibility_successfully": "åˇ˛æˆåŠŸčŽŠæ›´å¯čĻ‹æ€§", + "charging": "充é›ģ", + "charging_requirement_mobile_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": "æĒĸæŸĨæ—Ĩčnj", "choose_matching_people_to_merge": "選擇čρ合äŊĩįš„į›¸įŦĻäēēį‰Š", "city": "城市", "clear": "清įŠē", "clear_all": "全部清除", "clear_all_recent_searches": "清除所有最čŋ‘įš„æœå°‹", - "clear_file_cache": "清除文äģļåŋĢ取", + "clear_file_cache": "清除æĒ”æĄˆåŋĢ取", "clear_message": "æ¸…é™¤č¨Šæ¯", "clear_value": "清除å€ŧ", "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_title": "SSL åŽĸæˆļįĢ¯č­‰æ›¸", + "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": "關閉", "collapse": "æŠ˜į–Š", @@ -697,10 +711,10 @@ "confirm_password": "įĸēčĒå¯†įĸŧ", "confirm_tag_face": "æ‚¨æƒŗčĻå°‡æ­¤č‡‰å­”æ¨™įą¤į‚ē {name} 嗎īŧŸ", "confirm_tag_face_unnamed": "æ‚¨æƒŗæ¨™įą¤é€™åŧĩč‡‰å—ŽīŧŸ", - "connected_device": "厞逪įĩčŖįŊŽ", - "connected_to": "厞逪æŽĨ到", - "contain": "į­‰æ¯”įŊŽå…Ĩ", - "context": "內厚上下文", + "connected_device": "åˇ˛é€ŖįˇščŖįŊŽ", + "connected_to": "åˇ˛é€Ŗįˇšč‡ŗ", + "contain": "į­‰æ¯”å…§į¸Ž", + "context": "脈įĩĄ", "continue": "įšŧįēŒ", "control_bottom_app_bar_create_new_album": "åģēįĢ‹æ–°į›¸į°ŋ", "control_bottom_app_bar_delete_from_immich": "åžž Immich äŧ翜å™¨ä¸­åˆĒ除", @@ -728,7 +742,7 @@ "create_library": "åģēįĢ‹åĒ’éĢ”åēĢ", "create_link": "åģēį̋逪įĩ", "create_link_to_share": "åģēįĢ‹å…ąäēĢ逪įĩ", - "create_link_to_share_description": "äģģäŊ•æŒæœ‰é€Ŗįĩįš„äēēéƒŊå…č¨ąæŸĨįœ‹æ‰€é¸į›¸į‰‡", + "create_link_to_share_description": "äģģäŊ•æŒæœ‰é€Ŗįĩįš„äēēéƒŊå…č¨ąæĒĸčĻ–æ‰€é¸į›¸į‰‡", "create_new": "新åĸž", "create_new_person": "åģēįĢ‹æ–°äēēį‰Š", "create_new_person_hint": "å°‡é¸åŽšįš„åĒ’éĢ”åˆ†é…įĩĻæ–°äēēį‰Š", @@ -741,6 +755,7 @@ "create_user": "åģēįĢ‹äŊŋᔍ者", "created": "åģēįĢ‹æ–ŧ", "created_at": "åģēįĢ‹æ–ŧ", + "creating_linked_albums": "åģēį̋逪įĩį›¸į°ŋ ...", "crop": "誁å‰Ē", "curated_object_page_title": "äē‹į‰Š", "current_device": "į›Žå‰čŖįŊŽ", @@ -748,7 +763,7 @@ "current_server_address": "į›Žå‰įš„äŧ翜å™¨äŊå€", "custom_locale": "č‡Ēč¨‚åœ°å€č¨­åŽš", "custom_locale_description": "栚據čĒžč¨€čˆ‡åœ°å€æ ŧåŧåŒ–æ—ĨæœŸčˆ‡æ•¸å­—", - "custom_url": "č‡ĒåŽšįžŠ URL", + "custom_url": "č‡Ē訂 URL", "daily_title_text_date": "E, MMM dd", "daily_title_text_date_year": "YYYY åš´ M 月 D æ—Ĩ (E)", "dark": "æˇąč‰˛", @@ -769,7 +784,7 @@ "default_locale": "é č¨­åœ°å€", "default_locale_description": "äžį…§æ‚¨įš„į€čĻŊå™¨åœ°å€č¨­åŽšæ ŧåŧåŒ–æ—ĨæœŸčˆ‡æ•¸å­—", "delete": "åˆĒ除", - "delete_action_confirmation_message": "您įĸē厚čρåˆĒ除此åĒ’éĢ”å—ŽīŧŸæ­¤æ“äŊœæœƒå°‡čОåĒ’éĢ”į§ģ臺äŧ翜å™¨įš„垃圞æĄļīŧŒä¸Ļ會提į¤ē您是åĻčρ圍æœŦ地同時åˆĒ除", + "delete_action_confirmation_message": "您įĸē厚čρåˆĒ除此åĒ’éĢ”å—ŽīŧŸæ­¤æ“äŊœæœƒå°‡čОåĒ’éĢ”į§ģ臺äŧ翜å™¨įš„垃圞æĄļīŧŒä¸Ļ會提į¤ē您是åĻčρ圍æœŦ抟同時åˆĒ除", "delete_action_prompt": "{count} 個厞åˆĒ除", "delete_album": "åˆĒ除ᛏį°ŋ", "delete_api_key_prompt": "您įĸē厚čρåˆĒ除這個 API 金鑰嗎īŧŸ", @@ -782,9 +797,9 @@ "delete_duplicates_confirmation": "您įĸē厚čĻæ°¸äš…åˆĒ除這äē›é‡č¤‡é …į›Žå—ŽīŧŸ", "delete_face": "åˆĒ除臉孔", "delete_key": "åˆĒ除金鑰", - "delete_library": "åˆĒ除圖åēĢ", + "delete_library": "åˆĒ除ᛏį°ŋ", "delete_link": "åˆĒ除逪įĩ", - "delete_local_action_prompt": "厞圍æœŦ地åˆĒ除 {count} å€‹é …į›Ž", + "delete_local_action_prompt": "厞圍æœŦ抟åˆĒ除 {count} å€‹é …į›Ž", "delete_local_dialog_ok_backed_up_only": "僅åˆĒ除厞備äģŊįš„é …į›Ž", "delete_local_dialog_ok_force": "įĸēčĒåˆĒ除", "delete_others": "åˆĒ除å…ļäģ–", @@ -807,7 +822,7 @@ "disallow_edits": "ä¸å…č¨ąįˇ¨čŧ¯", "discord": "Discord", "discover": "æŽĸį´ĸ", - "discovered_devices": "厞æŽĸį´ĸįš„č¨­å‚™", + "discovered_devices": "厞æŽĸį´ĸįš„čŖįŊŽ", "dismiss_all_errors": "åŋŊį•Ĩ所有錯čǤ", "dismiss_error": "åŋŊį•Ĩ錯čǤ", "display_options": "éĄ¯į¤ē選項", @@ -838,7 +853,7 @@ "downloading": "下čŧ‰ä¸­", "downloading_asset_filename": "æ­Ŗåœ¨ä¸‹čŧ‰åĒ’éĢ” {filename}", "downloading_media": "æ­Ŗåœ¨ä¸‹čŧ‰åĒ’éĢ”", - "drop_files_to_upload": "將文äģļæ‹–攞到äģģäŊ•äŊįŊŽäģĨä¸Šå‚ŗ", + "drop_files_to_upload": "將æĒ”æĄˆæ‹–æ”žåˆ°äģģäŊ•äŊįŊŽäģĨä¸Šå‚ŗ", "duplicates": "é‡č¤‡é …į›Ž", "duplicates_description": "逐一æĒĸæŸĨæ¯å€‹įž¤įĩ„īŧŒä¸Ļ標į¤ēå…ļ中是åĻæœ‰é‡č¤‡åĒ’éĢ”", "duration": "éĄ¯į¤ēæ™‚é•ˇ", @@ -890,7 +905,9 @@ "error": "錯čǤ", "error_change_sort_album": "čŽŠæ›´į›¸į°ŋ排åēå¤ąæ•—", "error_delete_face": "åžžåĒ’éĢ”åˆĒé™¤č‡‰å­”æ™‚å¤ąæ•—", + "error_getting_places": "取垗äŊįŊŽæ™‚å‡ē錯", "error_loading_image": "åœ–į‰‡čŧ‰å…Ĩ錯čǤ", + "error_loading_partners": "čŧ‰å…Ĩ合äŊœå¤Ĩäŧ´æ™‚å‡ē錯īŧš{error}", "error_saving_image": "錯čǤīŧš{error}", "error_tag_face_bounding_box": "æ¨™č¨˜č‡‰éƒ¨éŒ¯čǤ - į„Ąæŗ•å–åž—é‚Šį•ŒæĄ†åæ¨™", "error_title": "錯čǤ - į™ŧį”ŸéŒ¯čǤ", @@ -910,7 +927,7 @@ "error_deleting_shared_user": "åˆĒé™¤å…ąäēĢäŊŋį”¨č€…æ™‚į™ŧį”ŸéŒ¯čǤ", "error_downloading": "下čŧ‰ {filename} 時į™ŧį”ŸéŒ¯čǤ", "error_hiding_buy_button": "隱藏čŗŧč˛ˇæŒ‰éˆ•æ™‚į™ŧį”ŸéŒ¯čǤ", - "error_removing_assets_from_album": "åžžį›¸į°ŋį§ģ除åĒ’éĢ”æ™‚į™ŧį”ŸéŒ¯čǤīŧŒčĢ‹æĒĸæŸĨä¸ģ控台äģĨå–åž—æ›´å¤ščŠŗį´°čŗ‡č¨Š", + "error_removing_assets_from_album": "åžžį›¸į°ŋį§ģ除åĒ’éĢ”æ™‚į™ŧį”ŸéŒ¯čǤīŧŒčĢ‹æĒĸæŸĨä¸ģ控č‡ēäģĨå–åž—æ›´å¤ščŠŗį´°čŗ‡č¨Š", "error_selecting_all_assets": "選取所有æĒ”æĄˆæ™‚į™ŧį”ŸéŒ¯čǤ", "exclusion_pattern_already_exists": "æ­¤æŽ’é™¤æ¨Ąåŧåˇ˛å­˜åœ¨ã€‚", "failed_to_create_album": "ᛏį°ŋåģēįĢ‹å¤ąæ•—", @@ -923,22 +940,22 @@ "failed_to_load_notifications": "čŧ‰å…Ĩ通įŸĨå¤ąæ•—", "failed_to_load_people": "čŧ‰å…Ĩäēēį‰Šå¤ąæ•—", "failed_to_remove_product_key": "į§ģ除į”ĸå“é‡‘é‘°å¤ąæ•—", - "failed_to_reset_pin_code": "重įŊŽ PIN įĸŧå¤ąæ•—", + "failed_to_reset_pin_code": "重設 PIN įĸŧå¤ąæ•—", "failed_to_stack_assets": "į„Ąæŗ•åĒ’éĢ”å †į–Š", "failed_to_unstack_assets": "觪除åĒ’éĢ”å †į–Šå¤ąæ•—", "failed_to_update_notification_status": "į„Ąæŗ•æ›´æ–°é€šįŸĨį‹€æ…‹", "import_path_already_exists": "此匯å…Ĩčˇ¯åž‘åˇ˛å­˜åœ¨ã€‚", "incorrect_email_or_password": "é›ģ子éƒĩäģ￈–密įĸŧ錯čǤ", "paths_validation_failed": "{paths, plural, one {# å€‹čˇ¯åž‘} other {# å€‹čˇ¯åž‘}} éŠ—č­‰å¤ąæ•—", - "profile_picture_transparent_pixels": "個äēēčŗ‡æ–™åœ–į‰‡ä¸čƒŊæœ‰é€æ˜Žåƒį´ ã€‚čĢ‹æ”žå¤§ä¸Ļ/或į§ģ動åŊąåƒã€‚", + "profile_picture_transparent_pixels": "個äēēčŗ‡æ–™åœ–į‰‡ä¸čƒŊ有透明į•Ģį´ ã€‚čĢ‹æ”žå¤§ä¸Ļ/或į§ģ動åŊąåƒã€‚", "quota_higher_than_disk_size": "æ‚¨æ‰€č¨­åŽšįš„é…éĄå¤§æ–ŧ᪁įĸŸå¤§å°", "something_went_wrong": "į™ŧį”ŸéŒ¯čǤ", "unable_to_add_album_users": "į„Ąæŗ•å°‡äŊŋį”¨č€…åŠ å…Ĩᛏį°ŋ", "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_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_archive_unarchive": "į„Ąæŗ•{archived, select, true {封存} other {取æļˆå°å­˜}}", @@ -950,7 +967,7 @@ "unable_to_change_password": "į„Ąæŗ•čŽŠæ›´å¯†įĸŧ", "unable_to_change_visibility": "į„Ąæŗ•čŽŠæ›´ {count, plural, one {# äŊäēēį‰Š} other {# äŊäēēį‰Š}} įš„å¯čĻ‹æ€§", "unable_to_complete_oauth_login": "į„Ąæŗ•åŽŒæˆ OAuth į™ģå…Ĩ", - "unable_to_connect": "į„Ąæŗ•é€ŖæŽĨ", + "unable_to_connect": "į„Ąæŗ•é€Ŗįˇš", "unable_to_copy_to_clipboard": "į„Ąæŗ•č¤‡čŖŊ到å‰Ēč˛ŧį°ŋīŧŒčĢ‹įĸēäŋæ‚¨æ˜¯äģĨ https 存取æœŦ頁éĸ", "unable_to_create_admin_account": "į„Ąæŗ•åģēįĢ‹įŽĄį†å“Ąå¸ŗč™Ÿ", "unable_to_create_api_key": "į„Ąæŗ•åģēįĢ‹æ–°įš„ API 金鑰", @@ -968,12 +985,12 @@ "unable_to_edit_import_path": "į„Ąæŗ•įˇ¨čŧ¯åŒ¯å…Ĩčˇ¯åž‘", "unable_to_empty_trash": "į„Ąæŗ•æ¸…įŠē垃圞æĄļ", "unable_to_enter_fullscreen": "į„Ąæŗ•é€˛å…Ĩ全čžĸåš•", - "unable_to_exit_fullscreen": "į„Ąæŗ•é€€å‡ē全čžĸåš•", + "unable_to_exit_fullscreen": "į„Ąæŗ•įĩæŸå…¨čžĸåš•", "unable_to_get_comments_number": "į„Ąæŗ•å–åž—į•™č¨€æ•¸é‡", "unable_to_get_shared_link": "å–åž—å…ąäēĢ逪įĩå¤ąæ•—", "unable_to_hide_person": "į„Ąæŗ•éšąč—äēēį‰Š", "unable_to_link_motion_video": "į„Ąæŗ•é€Ŗįĩå‹•æ…‹åŊąį‰‡", - "unable_to_link_oauth_account": "į„Ąæŗ•é€ŖæŽĨ OAuth å¸ŗč™Ÿ", + "unable_to_link_oauth_account": "į„Ąæŗ•é€Ŗįĩ OAuth å¸ŗč™Ÿ", "unable_to_log_out_all_devices": "į„Ąæŗ•į™ģå‡ēæ‰€æœ‰čŖįŊŽ", "unable_to_log_out_device": "į„Ąæŗ•į™ģå‡ēčŖįŊŽ", "unable_to_login_with_oauth": "į„Ąæŗ•äŊŋᔍ OAuth į™ģå…Ĩ", @@ -988,7 +1005,7 @@ "unable_to_remove_partner": "į„Ąæŗ•į§ģ除čĻĒæœ‹åĨŊ友", "unable_to_remove_reaction": "į„Ąæŗ•į§ģ除反應", "unable_to_reset_password": "į„Ąæŗ•é‡č¨­å¯†įĸŧ", - "unable_to_reset_pin_code": "į„Ąæŗ•é‡įŊŽ PIN įĸŧ", + "unable_to_reset_pin_code": "į„Ąæŗ•é‡č¨­ PIN įĸŧ", "unable_to_resolve_duplicate": "į„Ąæŗ•č§Ŗæąēé‡č¤‡é …į›Ž", "unable_to_restore_assets": "į„Ąæŗ•é‚„åŽŸåĒ’éĢ”", "unable_to_restore_trash": "į„Ąæŗ•é‚„åŽŸåžƒåœžæĄļ", @@ -1005,8 +1022,8 @@ "unable_to_set_profile_picture": "į„Ąæŗ•č¨­åŽšå€‹äēēčŗ‡æ–™åœ–į‰‡", "unable_to_submit_job": "į„Ąæŗ•æäē¤äģģ務", "unable_to_trash_asset": "į„Ąæŗ•å°‡åĒ’éĢ”ä¸Ÿé€˛åžƒåœžæĄļ", - "unable_to_unlink_account": "į„Ąæŗ•å–æļˆå¸ŗč™Ÿįš„逪æŽĨ", - "unable_to_unlink_motion_video": "į„Ąæŗ•å–æļˆé€ŖæŽĨ動態åŊąį‰‡", + "unable_to_unlink_account": "į„Ąæŗ•č§Ŗé™¤å¸ŗč™Ÿé€Ŗįĩ", + "unable_to_unlink_motion_video": "į„Ąæŗ•č§Ŗé™¤é€Ŗįĩå‹•æ…‹åŊąį‰‡", "unable_to_update_album_cover": "į„Ąæŗ•æ›´æ–°į›¸į°ŋ封éĸ", "unable_to_update_album_info": "į„Ąæŗ•æ›´æ–°į›¸į°ŋčŗ‡č¨Š", "unable_to_update_library": "į„Ąæŗ•æ›´æ–°åĒ’éĢ”åēĢ", @@ -1016,17 +1033,17 @@ "unable_to_update_user": "į„Ąæŗ•æ›´æ–°äŊŋᔍ者", "unable_to_upload_file": "į„Ąæŗ•ä¸Šå‚ŗæĒ”æĄˆ" }, - "exif": "EXIF 可ä礿›åœ–像文äģļæ ŧåŧ", + "exif": "EXIF 可ä礿›åŊąåƒæĒ”æ ŧåŧ", "exif_bottom_sheet_description": "新åĸžæčŋ°...", "exif_bottom_sheet_description_error": "更新描čŋ°æ™‚į™ŧį”ŸéŒ¯čǤ", "exif_bottom_sheet_details": "čŠŗį´°čŗ‡æ–™", "exif_bottom_sheet_location": "äŊįŊŽ", "exif_bottom_sheet_people": "äēēį‰Š", "exif_bottom_sheet_person_add_person": "新åĸžå§“名", - "exit_slideshow": "退å‡ēåšģį‡ˆį‰‡", + "exit_slideshow": "įĩæŸåšģį‡ˆį‰‡", "expand_all": "åą•é–‹å…¨éƒ¨", "experimental_settings_new_asset_list_subtitle": "æ­Ŗåœ¨č™•į†", - "experimental_settings_new_asset_list_title": "å•Ÿį”¨å¯ĻéŠ—æ€§į›¸į‰‡æ ŧį‹€å¸ƒåą€", + "experimental_settings_new_asset_list_title": "å•Ÿį”¨å¯ĻéŠ—æ€§į›¸į‰‡æ ŧį‹€į‰ˆéĸ", "experimental_settings_subtitle": "äŊŋᔍéĸ¨éšĒč‡Ē負īŧ", "experimental_settings_title": "å¯Ļ銗性功čƒŊ", "expire_after": "å¤ąæ•ˆæ™‚é–“", @@ -1042,7 +1059,7 @@ "external": "外部", "external_libraries": "外部åĒ’éĢ”åēĢ", "external_network": "外部įļ˛čˇ¯", - "external_network_sheet_info": "č‹ĨæœĒ逪æŽĨ偏åĨŊįš„ Wi-FiīŧŒå°‡äžåˆ—čĄ¨åžžä¸Šåˆ°ä¸‹é¸æ“‡å¯é€Ŗįˇšįš„äŧ翜å™¨įļ˛å€", + "external_network_sheet_info": "č‹ĨæœĒé€Ŗįˇšč‡ŗååĨŊįš„ Wi-FiīŧŒå°‡äžåˆ—čĄ¨åžžä¸Šåˆ°ä¸‹é¸æ“‡å¯é€Ŗįˇšįš„äŧ翜å™¨įļ˛å€", "face_unassigned": "æœĒ指厚", "failed": "å¤ąæ•—", "failed_to_authenticate": "čēĢäģŊéŠ—č­‰å¤ąæ•—", @@ -1055,6 +1072,7 @@ "favorites_page_no_favorites": "æœĒ扞到æ”ļč—é …į›Ž", "feature_photo_updated": "į‰šč‰˛į…§į‰‡åˇ˛æ›´æ–°", "features": "功čƒŊ", + "features_in_development": "į™ŧåą•ä¸­įš„į‰šéģž", "features_setting_description": "įŽĄį†æ‡‰į”¨į¨‹åŧåŠŸčƒŊ", "file_name": "æĒ”æĄˆåį¨ą", "file_name_or_extension": "æĒ”æĄˆåį¨ąæˆ–å‰¯æĒ”名", @@ -1075,16 +1093,15 @@ "gcast_enabled": "Google Cast", "gcast_enabled_description": "此功čƒŊ需čĻåžž Google čŧ‰å…Ĩå¤–éƒ¨čŗ‡æēæ‰čƒŊæ­Ŗå¸¸é‹äŊœã€‚", "general": "一čˆŦ", - "geolocation_instruction_all_have_location": "æ­¤æ—ĨæœŸįš„æ‰€æœ‰é …į›Žåˇ˛å…ˇæœ‰äŊįŊŽčŗ‡æ–™ã€‚čĢ‹å˜—čŠĻéĄ¯į¤ēæ‰€æœ‰é …į›Žæˆ–é¸æ“‡å…ļäģ–æ—Ĩ期", - "geolocation_instruction_location": "éģžæ“Šå…ˇæœ‰ GPS åē§æ¨™įš„é …į›ŽäģĨäŊŋᔍå…ļäŊįŊŽīŧŒæˆ–į›´æŽĨ垞地圖中選擇地éģž", - "geolocation_instruction_no_date": "選擇æ—Ĩ期äģĨįŽĄį†čŠ˛å¤Šįš„į…§į‰‡å’ŒåŊąį‰‡äŊįŊŽčŗ‡æ–™", - "geolocation_instruction_no_photos": "æ­¤æ—ĨæœŸæ˛’æœ‰æ‰žåˆ°į…§į‰‡æˆ–åŊąį‰‡ã€‚čĢ‹é¸æ“‡å…ļäģ–æ—Ĩ期äģĨéĄ¯į¤ē", - "get_help": "įˇšä¸Šæą‚åŠŠ", - "get_wifiname_error": "į„Ąæŗ•å–åž— Wi-Fi åį¨ąã€‚čĢ‹įĸēčĒæ‚¨åˇ˛æŽˆäēˆåŋ…čĻįš„æŦŠé™īŧŒä¸Ļ厞逪æŽĨ臺 Wi-Fi įļ˛čˇ¯", + "geolocation_instruction_location": "éģžé¸å…ˇæœ‰ GPS åē§æ¨™įš„é …į›ŽäģĨäŊŋᔍå…ļäŊįŊŽīŧŒæˆ–į›´æŽĨ垞地圖中選擇地éģž", + "get_help": "取垗協劊", + "get_wifiname_error": "į„Ąæŗ•å–åž— Wi-Fi åį¨ąã€‚čĢ‹įĸēčĒæ‚¨åˇ˛æŽˆäēˆåŋ…čĻįš„æŦŠé™īŧŒä¸Ļåˇ˛é€Ŗįˇšč‡ŗ Wi-Fi įļ˛čˇ¯", "getting_started": "開始äŊŋᔍ", - "go_back": "čŋ”回", + "go_back": "上一頁", "go_to_folder": "å‰åž€čŗ‡æ–™å¤ž", "go_to_search": "前垀搜尋", + "gps": "GPS", + "gps_missing": "į„Ą GPS", "grant_permission": "授ä爿ŦŠé™", "group_albums_by": "åˆ†éĄžįž¤įĩ„įš„æ–šåŧ...", "group_country": "æŒ‰į…§åœ‹åŽļåˆ†éĄž", @@ -1103,7 +1120,7 @@ "header_settings_header_name_input": "æ¨™é ­åį¨ą", "header_settings_header_value_input": "標頭å€ŧ", "headers_settings_tile_subtitle": "åŽšįžŠæ‡‰į”¨į¨‹åŧåœ¨æ¯æŦĄįļ˛čˇ¯čĢ‹æą‚æ™‚æ‡‰é™„å¸ļįš„äģŖį†æ¨™é ­", - "headers_settings_tile_title": "č‡ĒåŽšįžŠäģŖį†æ¨™é ­", + "headers_settings_tile_title": "č‡Ē訂äģŖį†æ¨™é ­", "hi_user": "嗨īŧ{name}īŧˆ{email}īŧ‰", "hide_all_people": "éšąč—æ‰€æœ‰äēēį‰Š", "hide_gallery": "隱藏åĒ’éĢ”åēĢ", @@ -1112,21 +1129,21 @@ "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_err_local": "æšĢ時不čƒŊ將æœŦ抟åĒ’éĢ”æ–°åĸžåˆ°į›¸į°ŋīŧŒåˇ˛į•Ĩ過", "home_page_add_to_album_success": "厞圍 {album} ᛏį°ŋ中新åĸž {added} 個åĒ’éĢ”ã€‚", "home_page_album_err_partner": "æšĢ時不čƒŊį„Ąæŗ•å°‡čĻĒæœ‹åĨŊå‹įš„åĒ’éĢ”æ–°åĸžåˆ°į›¸į°ŋīŧŒåˇ˛į•Ĩ過", - "home_page_archive_err_local": "æšĢ時不čƒŊ封存æœŦ地åĒ’éĢ”īŧŒåˇ˛į•Ĩ過", + "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_local": "æšĢ不čƒŊæ”ļ藏æœŦæŠŸé …į›ŽīŧŒį•Ĩ過", "home_page_favorite_err_partner": "æšĢį„Ąæŗ•æ”ļ藏čĻĒæœ‹åĨŊå‹įš„é …į›ŽīŧŒį•Ĩ過", "home_page_first_time_notice": "åĻ‚æžœé€™æ˜¯æ‚¨įŦŦ一æŦĄäŊŋᔍæœŦፋåŧīŧŒčĢ‹įĸēäŋé¸æ“‡ä¸€å€‹čρ備äģŊįš„į›¸į°ŋīŧŒäģĨå°‡į…§į‰‡čˆ‡åŊąį‰‡åŠ å…Ĩ時間čģ¸", "home_page_locked_error_local": "į„Ąæŗ•į§ģ動æœŦ抟æĒ”æĄˆč‡ŗéŽ–åŽšįš„čŗ‡æ–™å¤žīŧŒåˇ˛į•Ĩ過", "home_page_locked_error_partner": "į„Ąæŗ•į§ģ動čĻĒæœ‹åĨŊ友分äēĢįš„åĒ’éĢ”č‡ŗéŽ–åŽšįš„čŗ‡æ–™å¤žīŧŒåˇ˛į•Ĩ過", - "home_page_share_err_local": "į„Ąæŗ•é€šéŽé€Ŗįĩå…ąäēĢæœŦ地åĒ’éĢ”īŧŒåˇ˛į•Ĩ過", - "home_page_upload_err_limit": "一æŦĄæœ€å¤šåĒčƒŊä¸Šå‚ŗ 30 個åĒ’éĢ”īŧŒåˇ˛į•Ĩ過", + "home_page_share_err_local": "į„Ąæŗ•é€éŽé€Ŗįĩå…ąäēĢæœŦ抟åĒ’éĢ”īŧŒåˇ˛į•Ĩ過", + "home_page_upload_err_limit": "一æŦĄæœ€å¤šéšģčƒŊä¸Šå‚ŗ 30 個åĒ’éĢ”īŧŒåˇ˛į•Ĩ過", "host": "ä¸ģ抟", "hour": "小時", "hours": "小時", @@ -1149,7 +1166,7 @@ "image_viewer_page_state_provider_download_started": "下čŧ‰åˇ˛å•Ÿå‹•", "image_viewer_page_state_provider_download_success": "下čŧ‰æˆåŠŸ", "image_viewer_page_state_provider_share_error": "分äēĢæ™‚į™ŧį”ŸéŒ¯čǤ", - "immich_logo": "Immich 標čnj", + "immich_logo": "Immich Logo", "immich_web_interface": "Immich įļ˛é äģ‹éĸ", "import_from_json": "åžž JSON 匯å…Ĩ", "import_path": "匯å…Ĩčˇ¯åž‘", @@ -1173,9 +1190,9 @@ "invite_to_album": "邀č̋臺ᛏį°ŋ", "ios_debug_info_fetch_ran_at": "æŠ“å–åˇ˛æ–ŧ {dateTime} åŸˇčĄŒ", "ios_debug_info_last_sync_at": "上æŦĄåŒæ­Ĩæ–ŧ {dateTime}", - "ios_debug_info_no_processes_queued": "į„ĄæŽ’į¨‹ä¸­įš„čƒŒæ™¯į¨‹åē", + "ios_debug_info_no_processes_queued": "į„ĄæŽ’į¨‹ä¸­įš„čƒŒæ™¯į¨‹åŧ", "ios_debug_info_no_sync_yet": "尚æœĒåŸˇčĄŒäģģäŊ•čƒŒæ™¯åŒæ­Ĩäģģ務", - "ios_debug_info_processes_queued": "{count, plural, one {{count} å€‹čƒŒæ™¯į¨‹åēåˇ˛æŽ’ፋ} other {{count} å€‹čƒŒæ™¯į¨‹åēåˇ˛æŽ’ፋ}}", + "ios_debug_info_processes_queued": "{count, plural, one {{count} å€‹čƒŒæ™¯į¨‹åŧåˇ˛æŽ’ፋ} other {{count} å€‹čƒŒæ™¯į¨‹åŧåˇ˛æŽ’ፋ}}", "ios_debug_info_processing_ran_at": "æ–ŧ {dateTime} åŸˇčĄŒč™•į†", "items_count": "{count, plural, one {# å€‹é …į›Ž} other {# å€‹é …į›Ž}}", "jobs": "äģģ務", @@ -1199,7 +1216,7 @@ "lens_model": "éĄé ­åž‹č™Ÿ", "let_others_respond": "å…č¨ąäģ–äēē回čφ", "level": "į­‰į´š", - "library": "圖åēĢ", + "library": "ᛏį°ŋ", "library_options": "čŗ‡æ–™åēĢ選項", "library_page_device_albums": "čŖįŊŽä¸Šįš„ᛏį°ŋ", "library_page_new_album": "新åĸžį›¸į°ŋ", @@ -1210,20 +1227,21 @@ "licenses": "授æŦŠ", "light": "æˇē色", "like": "å–œæ­Ą", - "like_deleted": "厞åˆĒé™¤įš„æ”ļ藏", - "link_motion_video": "鏈įĩå‹•æ…‹åŊąį‰‡", - "link_to_oauth": "逪æŽĨ OAuth", - "linked_oauth_account": "厞逪æŽĨ OAuth å¸ŗč™Ÿ", + "like_deleted": "åˇ˛å–æļˆå–œæ­Ą", + "link_motion_video": "逪įĩå‹•æ…‹åŊąį‰‡", + "link_to_oauth": "逪įĩ OAuth", + "linked_oauth_account": "厞逪įĩ OAuth å¸ŗč™Ÿ", "list": "åˆ—čĄ¨", "loading": "čŧ‰å…Ĩ中", "loading_search_results_failed": "čŧ‰å…Ĩ搜尋įĩæžœå¤ąæ•—", - "local": "æœŦ地", - "local_asset_cast_failed": "į„Ąæŗ•čŊ‰æ›æœĒä¸Šå‚ŗč‡ŗäŧ翜å™¨įš„é …į›Ž", - "local_assets": "æœŦåœ°é …į›Ž", - "local_network": "æœŦ地įļ˛čˇ¯", + "local": "æœŦ抟", + "local_asset_cast_failed": "į„Ąæŗ•æŠ•æ”žæœĒä¸Šå‚ŗč‡ŗäŧ翜å™¨įš„é …į›Ž", + "local_assets": "æœŦæŠŸé …į›Ž", + "local_media_summary": "æœŦ抟åĒ’éĢ”æ‘˜čρ", + "local_network": "æœŦ抟įļ˛čˇ¯", "local_network_sheet_info": "į•ļäŊŋį”¨æŒ‡åŽšįš„ Wi-Fi įļ˛čˇ¯æ™‚īŧŒæ‡‰į”¨į¨‹åŧå°‡é€éŽæ­¤įļ˛å€é€Ŗįˇšč‡ŗäŧ翜å™¨", "location_permission": "äŊįŊŽæŦŠé™", - "location_permission_content": "äŊŋᔍč‡Ē動切換功čƒŊīŧŒImmich 需čĻį˛žįĸēäŊįŊŽæŦŠé™īŧŒäģĨå–åž—é€ŖæŽĨįš„ Wi-Fi įļ˛čˇ¯åį¨ą", + "location_permission_content": "äŊŋᔍč‡Ē動切換功čƒŊīŧŒImmich 需čĻį˛žįĸēäŊįŊŽæŦŠé™īŧŒäģĨå–åž—åˇ˛é€Ŗįˇšįš„ Wi-Fi įļ˛čˇ¯åį¨ą", "location_picker_choose_on_map": "在地圖上選擇", "location_picker_latitude_error": "čŧ¸å…Ĩæœ‰æ•ˆįš„įˇ¯åēĻå€ŧ", "location_picker_latitude_hint": "čĢ‹åœ¨æ­¤č™•čŧ¸å…Ĩæ‚¨įš„įˇ¯åēĻå€ŧ", @@ -1231,42 +1249,44 @@ "location_picker_longitude_hint": "čĢ‹åœ¨æ­¤č™•čŧ¸å…Ĩæ‚¨įš„įļ“åēĻå€ŧ", "lock": "鎖厚", "locked_folder": "éŽ–åŽšįš„čŗ‡æ–™å¤ž", + "log_detail_title": "æ—ĨčĒŒčŠŗį´°čŗ‡č¨Š", "log_out": "į™ģå‡ē", "log_out_all_devices": "į™ģå‡ēæ‰€æœ‰čŖįŊŽ", "logged_in_as": "äģĨ{user}čēĢ分į™ģå…Ĩ", "logged_out_all_devices": "厞į™ģå‡ēæ‰€æœ‰čŖįŊŽ", "logged_out_device": "厞į™ģå‡ēčŖįŊŽ", "login": "į™ģå…Ĩ", - "login_disabled": "厞įρᔍį™ģå…Ĩ", - "login_form_api_exception": "API ᕰ叏īŧŒčĢ‹æĒĸæŸĨäŧ翜å™¨åœ°å€ä¸Ļ重čŠĻ。", - "login_form_back_button_text": "垌退", + "login_disabled": "åˇ˛åœį”¨į™ģå…Ĩ", + "login_form_api_exception": "API į™ŧį”Ÿäž‹å¤–īŧŒčĢ‹æĒĸæŸĨäŧ翜å™¨äŊå€åžŒå†čŠĻ。", + "login_form_back_button_text": "上一頁", "login_form_email_hint": "é›ģ子éƒĩäģļ地址", - "login_form_endpoint_hint": "http://æ‚¨įš„äŧ翜å™¨åœ°å€:įĢ¯åŖ", - "login_form_endpoint_url": "äŧ翜å™¨éˆæŽĨ地址", - "login_form_err_http": "čĢ‹æŗ¨æ˜Ž http:// 或 https://", - "login_form_err_invalid_email": "é›ģéƒĩį„Ąæ•ˆ", - "login_form_err_invalid_url": "į„Ąæ•ˆįš„åœ°å€", + "login_form_endpoint_hint": "http://æ‚¨įš„äŧ翜å™¨äŊå€:逪æŽĨ埠", + "login_form_endpoint_url": "äŧ翜å™¨į̝éģž URL", + "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 į™ģå…Ĩ時錯čǤīŧŒčĢ‹æĒĸæŸĨäŧ翜å™¨åœ°å€", - "login_form_failed_get_oauth_server_disable": "OAuth 功čƒŊ在此äŧ翜å™¨ä¸Šä¸å¯į”¨", - "login_form_failed_login": "į™ģå…Ĩå¤ąæ•—īŧŒčĢ‹æĒĸæŸĨäŧ翜å™¨åœ°å€ã€é›ģéƒĩ和密įĸŧ", - "login_form_handshake_exception": "與äŧ翜å™¨é€šäŋĄæ™‚å‡ēįžæĄæ‰‹į•°å¸¸ã€‚åĻ‚æžœæ‚¨äŊŋį”¨įš„æ˜¯č‡Ēį°Ŋåč­‰æ›¸īŧŒčĢ‹åœ¨č¨­åŽšä¸­å•“į”¨č‡Ēį°Ŋåč­‰æ›¸æ”¯æŒã€‚", + "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_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": "密įĸŧ更新成功", "logout_all_device_confirmation": "您įĸē厚čρį™ģå‡ēæ‰€æœ‰čŖįŊŽå—ŽīŧŸ", "logout_this_device_confirmation": "čρį™ģå‡ē這č‡ēčŖįŊŽå—ŽīŧŸ", + "logs": "æ—Ĩčnj", "longitude": "įļ“åēĻ", "look": "æ¨Ŗč˛Œ", "loop_videos": "重播åŊąį‰‡", "loop_videos_description": "å•Ÿį”¨åžŒīŧŒåŊąį‰‡įĩæŸæœƒč‡Ē動重播。", "main_branch_warning": "æ‚¨įžåœ¨äŊŋį”¨įš„æ˜¯é–‹į™ŧį‰ˆæœŦīŧ›æˆ‘們åŧˇįƒˆæ‚¨åģēč­°äŊŋį”¨æ­Ŗåŧį™ŧčĄŒį‰ˆīŧ", - "main_menu": "ä¸ģ頁éĸ", + "main_menu": "ä¸ģ選喎", "make": "čŖŊ造商", "manage_geolocation": "įŽĄį†äŊįŊŽ", "manage_shared_links": "įŽĄį†å…ąäēĢ逪įĩ", @@ -1275,34 +1295,35 @@ "manage_your_account": "įŽĄį†æ‚¨įš„å¸ŗč™Ÿ", "manage_your_api_keys": "įŽĄį†æ‚¨įš„ API 金鑰", "manage_your_devices": "įŽĄį†åˇ˛į™ģå…Ĩįš„čŖįŊŽ", - "manage_your_oauth_connection": "įŽĄį†æ‚¨įš„ OAuth 逪æŽĨ", + "manage_your_oauth_connection": "įŽĄį†æ‚¨įš„ OAuth 逪įĩ", "map": "地圖", "map_assets_in_bounds": "{count, plural, one {# åŧĩᅧቇ} other {# åŧĩᅧቇ}}", "map_cannot_get_user_location": "į„Ąæŗ•å–åž—äŊŋᔍ者äŊįŊŽ", "map_location_dialog_yes": "įĸē厚", "map_location_picker_page_use_location": "äŊŋį”¨æ­¤äŊįŊŽ", - "map_location_service_disabled_content": "需čĻå•“į”¨åŽšäŊæœå‹™æ‰čƒŊéĄ¯į¤ēį•ļ前äŊįŊŽį›¸é—œįš„é …į›Žã€‚čĻįžåœ¨å•“į”¨å—ŽīŧŸ", - "map_location_service_disabled_title": "厚äŊæœå‹™åˇ˛įρᔍ", - "map_marker_for_images": "在 {city}、{country} æ‹æ”åœ–åƒįš„åœ°åœ–æ¨™č¨˜", - "map_marker_with_image": "å¸ļæœ‰åœ–åƒįš„åœ°åœ–æ¨™č¨˜", - "map_no_location_permission_content": "需čρäŊįŊŽæŦŠé™æ‰čƒŊéĄ¯į¤ē與į•ļ前äŊįŊŽã€‚čĻįžåœ¨å°ąæŽˆäēˆäŊįŊŽæŦŠé™å—ŽīŧŸ", + "map_location_service_disabled_content": "需čĻå•Ÿį”¨åŽšäŊæœå‹™æ‰čƒŊéĄ¯į¤ēį›Žå‰äŊįŊŽį›¸é—œįš„é …į›Žã€‚čĻįžåœ¨å•Ÿį”¨å—ŽīŧŸ", + "map_location_service_disabled_title": "厚äŊæœå‹™åˇ˛åœį”¨", + "map_marker_for_images": "在 {city}、{country} 拍攝åŊąåƒįš„地圖į¤ē記", + "map_marker_with_image": "å¸ļ有åŊąåƒįš„地圖į¤ē記", + "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_day": "過åŽģ 24 小時", "map_settings_date_range_option_days": "{days} 夊前", - "map_settings_date_range_option_year": "1嚴前", + "map_settings_date_range_option_year": "1 嚴前", "map_settings_date_range_option_years": "{years} 嚴前", "map_settings_dialog_title": "åœ°åœ–č¨­åŽš", "map_settings_include_show_archived": "包æ‹Ŧåˇ˛å°å­˜é …į›Ž", "map_settings_include_show_partners": "包åĢčĻĒæœ‹åĨŊ友", "map_settings_only_show_favorites": "åƒ…éĄ¯į¤ēæ”ļč—įš„é …į›Ž", "map_settings_theme_settings": "地圖ä¸ģ題", - "map_zoom_to_see_photos": "į¸Žå°äģĨæŸĨįœ‹é …į›Ž", + "map_zoom_to_see_photos": "į¸Žå°äģĨæĒĸčĻ–é …į›Ž", "mark_all_as_read": "å…¨éƒ¨æ¨™č¨˜į‚ēåˇ˛čŽ€", "mark_as_read": "æ¨™č¨˜į‚ēåˇ˛čŽ€", "marked_all_as_read": "åˇ˛å…¨éƒ¨æ¨™č¨˜į‚ēåˇ˛čŽ€", "matches": "ᛏįŦĻ", + "matching_assets": "åŒšé…čŗ‡į”ĸ", "media_type": "åĒ’éĢ”éĄžåž‹", "memories": "回æ†ļ", "memories_all_caught_up": "åˇ˛å…¨éƒ¨įœ‹åŽŒ", @@ -1315,7 +1336,7 @@ "menu": "選喎", "merge": "合äŊĩ", "merge_people": "合äŊĩäēēį‰Š", - "merge_people_limit": "一æŦĄæœ€å¤šåĒčƒŊ合äŊĩ 5 åŧĩ臉孔", + "merge_people_limit": "一æŦĄæœ€å¤šéšģčƒŊ合äŊĩ 5 åŧĩ臉孔", "merge_people_prompt": "您čρ合äŊĩ這äē›äēēį‰Šå—ŽīŧŸæ­¤æ“äŊœį„Ąæŗ•æ’¤éŠˇã€‚", "merge_people_successfully": "成功合äŊĩäēēį‰Š", "merged_people_count": "合äŊĩäē† {count, plural, one {# äŊäēēåŖĢ} other {# äŊäēēåŖĢ}}", @@ -1343,7 +1364,8 @@ "name_or_nickname": "åį¨ąæˆ–æšąį¨ą", "network_requirement_photos_upload": "äŊŋį”¨čĄŒå‹•įļ˛čˇ¯æĩé‡å‚™äģŊᅧቇ", "network_requirement_videos_upload": "äŊŋį”¨čĄŒå‹•įļ˛čˇ¯æĩé‡å‚™äģŊåŊąį‰‡", - "network_requirements_updated": "įļ˛įĩĄéœ€æą‚åˇ˛čŽŠæ›´īŧŒįžé‡įŊŽå‚™äģŊäŊ‡åˆ—", + "network_requirements": "įļ˛čˇ¯čĻæą‚", + "network_requirements_updated": "įļ˛čˇ¯éœ€æą‚åˇ˛čŽŠæ›´īŧŒįžé‡č¨­å‚™äģŊäŊ‡åˆ—", "networking_settings": "įļ˛čˇ¯", "networking_subtitle": "įŽĄį†äŧ翜å™¨į̝éģžč¨­åޚ", "never": "æ°¸ä¸å¤ąæ•ˆ", @@ -1353,6 +1375,7 @@ "new_person": "æ–°įš„äēēį‰Š", "new_pin_code": "新 PIN įĸŧ", "new_pin_code_subtitle": "這是您įŦŦ一æŦĄå­˜å–éŽ–åŽšįš„čŗ‡æ–™å¤žã€‚åģēįĢ‹ PIN įĸŧäģĨ厉全存取此頁éĸ", + "new_timeline": "新時間čģ¸", "new_user_created": "厞åģēįĢ‹æ–°äŊŋᔍ者", "new_version_available": "æ–°į‰ˆæœŦ厞į™ŧ布", "newest_first": "最新å„Ē先", @@ -1365,21 +1388,26 @@ "no_archived_assets_message": "å°‡į…§į‰‡å’ŒåŊąį‰‡å°å­˜īŧŒå°ąä¸æœƒéĄ¯į¤ēåœ¨ã€Œį…§į‰‡ã€ä¸­", "no_assets_message": "æŒ‰é€™čŖĄä¸Šå‚ŗæ‚¨įš„įŦŦ一åŧĩᅧቇ", "no_assets_to_show": "į„Ąé …į›Žåą•į¤ē", - "no_cast_devices_found": "æ˛’æœ‰æ‰žåˆ° Google Cast čŖįŊŽ", + "no_cast_devices_found": "扞不到 Google Cast čŖįŊŽ", + "no_checksum_local": "æ˛’æœ‰å¯į”¨įš„æ ĄéŠ—å’Œ - į„Ąæŗ•å–åž—æœŦæŠŸčŗ‡į”ĸ", + "no_checksum_remote": "æ˛’æœ‰å¯į”¨įš„æ ĄéŠ—å’Œ - į„Ąæŗ•å–åž—é į̝躇į”ĸ", "no_duplicates_found": "æ˛’į™ŧįžé‡č¤‡é …į›Žã€‚", "no_exif_info_available": "æ˛’æœ‰å¯į”¨įš„ Exif čŗ‡č¨Š", "no_explore_results_message": "ä¸Šå‚ŗæ›´å¤šį…§į‰‡äģĨ刊æŽĸį´ĸ。", "no_favorites_message": "加å…Ĩæ”ļ藏īŧŒåŠ é€Ÿå°‹æ‰žåŊąåƒ", - "no_libraries_message": "åģēįĢ‹å¤–éƒ¨åĒ’éĢ”åēĢäģĨæŸĨįœ‹æ‚¨įš„į…§į‰‡å’ŒåŊąį‰‡", - "no_locked_photos_message": "éŽ–åŽšįš„čŗ‡æ–™å¤žä¸­įš„į…§į‰‡å’ŒåŊąį‰‡æœƒčĸĢ隱藏īŧŒį•ļæ‚¨į€čĻŊ或搜尋圖åēĢæ™‚ä¸æœƒéĄ¯į¤ē。", + "no_libraries_message": "åģēįĢ‹å¤–éƒ¨åĒ’éĢ”åēĢäģĨæĒĸčĻ–æ‚¨įš„į…§į‰‡å’ŒåŊąį‰‡", + "no_local_assets_found": "æœĒæ‰žåˆ°å…ˇæœ‰æ­¤æ ĄéŠ—å’Œįš„æœŦæŠŸčŗ‡į”ĸ", + "no_locked_photos_message": "éŽ–åŽšįš„čŗ‡æ–™å¤žä¸­įš„į…§į‰‡å’ŒåŊąį‰‡æœƒčĸĢ隱藏īŧŒį•ļæ‚¨į€čĻŊæˆ–æœå°‹į›¸į°ŋæ™‚ä¸æœƒéĄ¯į¤ē。", "no_name": "į„Ąå", "no_notifications": "æ˛’æœ‰é€šįŸĨ", "no_people_found": "扞不到įŦĻåˆįš„äēēį‰Š", "no_places": "æ˛’æœ‰åœ°éģž", + "no_remote_assets_found": "æœĒæ‰žåˆ°å…ˇæœ‰æ­¤æ ĄéŠ—å’Œįš„é į̝躇į”ĸ", "no_results": "æ˛’æœ‰įĩæžœ", "no_results_description": "čŠĻčŠĻåŒįžŠčŠžæˆ–æ›´é€šį”¨įš„é—œéĩ字吧", "no_shared_albums_message": "åģēį̋ᛏį°ŋ分äēĢį…§į‰‡å’ŒåŊąį‰‡", "no_uploads_in_progress": "æ˛’æœ‰æ­Ŗåœ¨ä¸Šå‚ŗįš„é …į›Ž", + "not_available": "ä¸éŠį”¨", "not_in_any_album": "不在äģģäŊ•ᛏį°ŋ中", "not_selected": "æœĒ選擇", "note_apply_storage_label_to_previously_uploaded assets": "*č¨ģīŧšåŸˇčĄŒåĨ—į”¨å„˛å­˜æ¨™įą¤å‰å…ˆä¸Šå‚ŗé …į›Ž", @@ -1401,12 +1429,12 @@ "on_this_device": "åœ¨æ­¤čŖįŊŽ", "onboarding": "å…Ĩ門指南", "onboarding_locale_description": "é¸æ“‡æ‚¨æƒŗčĻéĄ¯į¤ēįš„čĒžč¨€ã€‚č¨­åŽšåŽŒæˆäš‹åžŒį”Ÿæ•ˆã€‚", - "onboarding_privacy_description": "äģĨ下īŧˆå¯é¸īŧ‰åŠŸčƒŊäžčŗ´å¤–éƒ¨æœå‹™īŧŒå¯éš¨æ™‚åœ¨č¨­åŽšä¸­åœį”¨ã€‚", + "onboarding_privacy_description": "äģĨ下īŧˆå¯é¸īŧ‰åŠŸčƒŊäģ°čŗ´å¤–部服務īŧŒå¯éš¨æ™‚åœ¨č¨­åŽšä¸­åœį”¨ã€‚", "onboarding_server_welcome_description": "čŽ“æˆ‘å€‘į‚ēæ‚¨įš„įŗģįĩąé€˛čĄŒä¸€äē›åŸēæœŦč¨­åŽšã€‚", - "onboarding_theme_description": "åšĢå¯Ļ例選色åŊŠä¸ģéĄŒã€‚äš‹åžŒäšŸå¯äģĨåœ¨č¨­åŽšä¸­čŽŠæ›´ã€‚", - "onboarding_user_welcome_description": "čŽ“æˆ‘å€‘é–‹å§‹å§!", + "onboarding_theme_description": "åšĢåŸˇčĄŒå€‹é̔遏艞åŊŠä¸ģéĄŒã€‚äš‹åžŒäšŸå¯äģĨåœ¨č¨­åŽšä¸­čŽŠæ›´ã€‚", + "onboarding_user_welcome_description": "čŽ“æˆ‘å€‘é–‹å§‹å§īŧ", "onboarding_welcome_user": "æ­ĄčŋŽīŧŒ{user}", - "online": "圍᎚", + "online": "᎚䏊", "only_favorites": "åƒ…éĄ¯į¤ēåˇąæ”ļ藏", "open": "開啟", "open_in_map_view": "開啟地圖æĒĸčĻ–", @@ -1414,7 +1442,9 @@ "open_the_search_filters": "é–‹å•Ÿæœå°‹į¯Šé¸å™¨", "options": "選項", "or": "或", - "organize_your_library": "æ•´į†æ‚¨įš„åœ–åēĢ", + "organize_into_albums": "æ•´į†æˆį›¸į°ŋ", + "organize_into_albums_description": "äŊŋį”¨į›Žå‰åŒæ­Ĩč¨­åŽšå°‡įžæœ‰į…§į‰‡æ”žå…Ĩᛏį°ŋ", + "organize_your_library": "æ•´į†æ‚¨įš„į›¸į°ŋ", "original": "原圖", "other": "å…ļäģ–", "other_devices": "å…ļåŽƒčŖįŊŽ", @@ -1429,7 +1459,7 @@ "partner_list_user_photos": "{user} įš„į…§į‰‡", "partner_list_view_all": "åą•į¤ē全部", "partner_page_empty_message": "æ‚¨įš„į…§į‰‡å°šæœĒ與äģģäŊ•čĻĒæœ‹åĨŊå‹å…ąäēĢ。", - "partner_page_no_more_users": "į„Ąéœ€æ–°åĸžæ›´å¤šį”¨æˆļ", + "partner_page_no_more_users": "į„Ąéœ€æ–°åĸžæ›´å¤šäŊŋᔍ者", "partner_page_partner_add_failed": "新åĸžčĻĒæœ‹åĨŊå‹å¤ąæ•—", "partner_page_select_partner": "選擇čĻĒæœ‹åĨŊ友", "partner_page_shared_to_title": "å…ąäēĢįĩĻ", @@ -1464,18 +1494,18 @@ "permanently_deleted_assets_count": "永䚅åˆĒé™¤įš„ {count, plural, one {# 個æĒ”æĄˆ} other {# 個æĒ”æĄˆ}}", "permission": "æŦŠé™", "permission_empty": "æŦŠé™ä¸čƒŊį‚ēįŠē", - "permission_onboarding_back": "čŋ”回", + "permission_onboarding_back": "上一頁", "permission_onboarding_continue_anyway": "įĸēčĒįšŧįēŒ", "permission_onboarding_get_started": "開始äŊŋᔍ", "permission_onboarding_go_to_settings": "å‰åž€č¨­åŽš", "permission_onboarding_permission_denied": "åĻ‚čρįšŧįēŒīŧŒčĢ‹å…č¨ą Immich å­˜å–į›¸į‰‡å’ŒåŊąį‰‡æŦŠé™ã€‚", "permission_onboarding_permission_granted": "åˇ˛å…č¨ąīŧä¸€åˆ‡å°ąįˇ’。", "permission_onboarding_permission_limited": "åĻ‚čρįšŧįēŒīŧŒčĢ‹å…č¨ą Immich 備äģŊå’ŒįŽĄį†æ‚¨įš„į›¸į°ŋæ”ļ藏īŧŒåœ¨č¨­åŽšä¸­æŽˆäēˆį›¸į‰‡å’ŒåŊąį‰‡æŦŠé™ã€‚", - "permission_onboarding_request": "Immich 需čρæŦŠé™æ‰čƒŊæŸĨįœ‹æ‚¨įš„į›¸į‰‡å’ŒįŸ­į‰‡ã€‚", + "permission_onboarding_request": "Immich 需čρæŦŠé™æ‰čƒŊæĒĸčĻ–æ‚¨įš„į›¸į‰‡å’ŒįŸ­į‰‡ã€‚", "person": "äēēį‰Š", "person_age_months": "{months, plural, one {# 個月} other {# 個月}}前", "person_age_year_months": "1 åš´ {months, plural, one {# 個月} other {# 個月}}前", - "person_age_years": "{years, plural, other {# åš´}}前", + "person_age_years": "{years, plural, other {# æ­˛}}", "person_birthdate": "į”Ÿæ–ŧ {date}", "person_hidden": "{name}{hidden, select, true {īŧˆéšąč—īŧ‰} other {}}", "photo_shared_all_users": "įœ‹äž†æ‚¨čˆ‡æ‰€æœ‰äŊŋį”¨č€…åˆ†äēĢäē†į…§į‰‡īŧŒæˆ–æ˛’æœ‰å…ļäģ–äŊŋį”¨č€…å¯äž›åˆ†äēĢ。", @@ -1485,9 +1515,9 @@ "photos_from_previous_years": "åž€åš´įš„į…§į‰‡", "pick_a_location": "選擇äŊįŊŽ", "pin_code_changed_successfully": "čŽŠæ›´ PIN įĸŧ成功", - "pin_code_reset_successfully": "重įŊŽ PIN įĸŧ成功", + "pin_code_reset_successfully": "重設 PIN įĸŧ成功", "pin_code_setup_successfully": "č¨­åŽš PIN įĸŧ成功", - "pin_verification": "PINįĸŧ驗證", + "pin_verification": "PIN įĸŧ驗證", "place": "地éģž", "places": "地éģž", "places_count": "{count, plural, one {{count, number} 個地éģž} other {{count, number} 個地éģž}}", @@ -1499,6 +1529,7 @@ "port": "åŸ åŖ", "preferences_settings_subtitle": "įŽĄį†æ‡‰į”¨į¨‹åŧååĨŊč¨­åŽš", "preferences_settings_title": "偏åĨŊč¨­åŽš", + "preparing": "æē–å‚™", "preset": "預設", "preview": "預čĻŊ", "previous": "上一åŧĩ", @@ -1511,13 +1542,13 @@ "privacy": "éšąį§", "profile": "叺æˆļč¨­åŽš", "profile_drawer_app_logs": "æ—Ĩčnj", - "profile_drawer_client_out_of_date_major": "åŽĸæˆļįĢ¯æœ‰å¤§į‰ˆæœŦå‡į´šīŧŒčĢ‹į›ĄåŋĢå‡į´šč‡ŗæœ€æ–°į‰ˆã€‚", - "profile_drawer_client_out_of_date_minor": "åŽĸæˆļįĢ¯æœ‰å°į‰ˆæœŦå‡į´šīŧŒčĢ‹į›ĄåŋĢå‡į´šč‡ŗæœ€æ–°į‰ˆã€‚", - "profile_drawer_client_server_up_to_date": "åŽĸæˆļįĢ¯å’Œæœå‹™į̝éƒŊæ˜¯æœ€æ–°įš„", + "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_readonly_mode": "å”¯čŽ€æ¨Ąåŧåˇ˛é–‹å•Ÿã€‚č̋逪éģžå…Šä¸‹äŊŋį”¨č€…é ­åƒåœ–į¤ēäģĨ退å‡ē。", - "profile_drawer_server_out_of_date_major": "服務įĢ¯æœ‰å¤§į‰ˆæœŦå‡į´šīŧŒčĢ‹į›ĄåŋĢå‡į´šč‡ŗæœ€æ–°į‰ˆã€‚", - "profile_drawer_server_out_of_date_minor": "服務įĢ¯æœ‰å°į‰ˆæœŦå‡į´šīŧŒčĢ‹į›ĄåŋĢå‡į´šč‡ŗæœ€æ–°į‰ˆã€‚", + "profile_drawer_readonly_mode": "å”¯čŽ€æ¨Ąåŧåˇ˛é–‹å•Ÿã€‚čĢ‹é•ˇæŒ‰äŊŋį”¨č€…é ­åƒåœ–į¤ēäģĨįĩæŸã€‚", + "profile_drawer_server_out_of_date_major": "äŧ翜å™¨įĢ¯æœ‰å¤§į‰ˆæœŦå‡į´šīŧŒčĢ‹į›ĄåŋĢå‡į´šč‡ŗæœ€æ–°į‰ˆã€‚", + "profile_drawer_server_out_of_date_minor": "äŧ翜å™¨įĢ¯æœ‰å°į‰ˆæœŦå‡į´šīŧŒčĢ‹į›ĄåŋĢå‡į´šč‡ŗæœ€æ–°į‰ˆã€‚", "profile_image_of_user": "{user} įš„å€‹äēēčŗ‡æ–™åœ–į‰‡", "profile_picture_set": "åˇ˛č¨­åŽšå€‹äēēčŗ‡æ–™åœ–į‰‡ã€‚", "public_album": "å…Ŧ開ᛏį°ŋ", @@ -1542,7 +1573,7 @@ "purchase_lifetime_description": "įĩ‚čēĢčŗŧįŊŽ", "purchase_option_title": "čŗŧįŊŽé¸é …", "purchase_panel_info_1": "開į™ŧ Immich 可不是äģļåŽšæ˜“įš„äē‹īŧŒčŠąä熿ˆ‘們不少功å¤Ģ。åĨŊåœ¨æœ‰ä¸€įž¤å…¨čˇåˇĨፋå¸Ģåœ¨čƒŒåžŒéģ˜éģ˜åŠĒ力īŧŒį‚ēįš„å°ąæ˜¯æŠŠåŽƒåšåˆ°æœ€åĨŊã€‚æˆ‘å€‘įš„į›Žæ¨™åžˆį°Ąå–ŽīŧščŽ“é–‹æ”žåŽŸå§‹įĸŧčģŸéĢ”å’Œæ­Ŗį•ļįš„å•†æĨ­æ¨ĄåŧčƒŊ成į‚ē開į™ŧč€…įš„é•ˇæœŸéŖ¯įĸ—īŧŒåŒæ™‚打造å‡ē重čĻ–éšąį§įš„į”Ÿæ…‹įŗģįĩąīŧŒčޓ大åŽļ有個不čĸĢ限åˆļįš„é›˛įĢ¯æœå‹™æ–°é¸æ“‡ã€‚", - "purchase_panel_info_2": "我們æ‰ŋčĢžä¸č¨­äģ˜č˛ģቆīŧŒæ‰€äģĨčŗŧįŊŽ Immich ä¸Ļä¸æœƒčŽ“æ‚¨į˛åž—éĄå¤–įš„åŠŸčƒŊã€‚æˆ‘å€‘æ˜¯äžčŗ´äŊŋį”¨č€…å€‘įš„æ”¯æ´äž†é–‹į™ŧ Immich įš„ã€‚", + "purchase_panel_info_2": "我們æ‰ŋčĢžä¸č¨­äģ˜č˛ģቆīŧŒæ‰€äģĨčŗŧįŊŽ Immich ä¸Ļä¸æœƒčŽ“æ‚¨į˛åž—éĄå¤–įš„åŠŸčƒŊ。我們äģ°čŗ´äŊŋį”¨č€…å€‘įš„æ”¯æ´äž†é–‹į™ŧ Immich。", "purchase_panel_title": "æ”¯æ´é€™é …å°ˆæĄˆ", "purchase_per_server": "每č‡ēäŧ翜å™¨", "purchase_per_user": "每äŊäŊŋᔍ者", @@ -1554,6 +1585,7 @@ "purchase_server_description_2": "æ“č­ˇč€…į‹€æ…‹", "purchase_server_title": "äŧ翜å™¨", "purchase_settings_server_activated": "äŧ翜å™¨į”ĸå“é‡‘é‘°æ˜¯į”ąįŽĄį†č€…įŽĄį†įš„", + "query_asset_id": "æŸģčŠĸčŗ‡į”ĸ ID", "queue_status": "處ᐆ䏭 {count}/{total}", "rating": "čŠ•æ˜Ÿ", "rating_clear": "æ¸…é™¤čŠ•į­‰", @@ -1563,6 +1595,7 @@ "read_changelog": "閱čĻŊčŽŠæ›´æ—Ĩčnj", "readonly_mode_disabled": "å”¯čŽ€æ¨Ąåŧåˇ˛é—œé–‰", "readonly_mode_enabled": "å”¯čŽ€æ¨Ąåŧåˇ˛é–‹å•Ÿ", + "ready_for_upload": "厞æē–å‚™åĨŊä¸Šå‚ŗ", "reassign": "重新指厚", "reassigned_assets_to_existing_person": "厞將 {count, plural, other {# 個æĒ”æĄˆ}}重新指厚įĩĻ{name, select, null {įžæœ‰įš„äēē} other {{name}}}", "reassigned_assets_to_new_person": "厞將 {count, plural, other {# 個æĒ”æĄˆ}}重新指厚įĩĻ一äŊæ–°äēēį‰Š", @@ -1587,6 +1620,7 @@ "regenerating_thumbnails": "重新į”ĸį”Ÿį¸Žåœ–ä¸­", "remote": "遠į̝", "remote_assets": "遠įĢ¯é …į›Ž", + "remote_media_summary": "遠į̝åĒ’éĢ”æ‘˜čρ", "remove": "į§ģ除", "remove_assets_album_confirmation": "įĸē厚čĻåžžį›¸į°ŋ中į§ģ除 {count, plural, other {# 個æĒ”æĄˆ}}嗎īŧŸ", "remove_assets_shared_link_confirmation": "įĸē厚åˆĒé™¤å…ąäēĢ逪įĩä¸­{count, plural, other {# å€‹é …į›Ž}}嗎īŧŸ", @@ -1598,13 +1632,13 @@ "remove_from_favorites": "åžžæ”ļ藏中į§ģ除", "remove_from_lock_folder_action_prompt": "åˇ˛åžžéŽ–åŽšįš„čŗ‡æ–™å¤žä¸­į§ģ除äē† {count} å€‹é …į›Ž", "remove_from_locked_folder": "åžžéŽ–åŽšįš„čŗ‡æ–™å¤žä¸­į§ģ除", - "remove_from_locked_folder_confirmation": "您įĸē厚čρ將這äē›į…§į‰‡å’ŒåŊąį‰‡į§ģå‡ēéŽ–åŽšįš„čŗ‡æ–™å¤žå—ŽīŧŸé€™äē›å…§åŽšå°‡æœƒéĄ¯į¤ēåœ¨æ‚¨įš„åœ–åēĢ中。", + "remove_from_locked_folder_confirmation": "您įĸē厚čρ將這äē›į…§į‰‡å’ŒåŊąį‰‡į§ģå‡ēéŽ–åŽšįš„čŗ‡æ–™å¤žå—ŽīŧŸé€™äē›å…§åŽšå°‡æœƒéĄ¯į¤ēåœ¨æ‚¨įš„į›¸į°ŋ中。", "remove_from_shared_link": "åžžå…ąäēĢ逪įĩä¸­į§ģ除", "remove_memory": "į§ģ除記æ†ļ", "remove_photo_from_memory": "å°‡åœ–į‰‡åžžæ­¤č¨˜æ†ļ中į§ģ除", "remove_tag": "į§ģé™¤æ¨™įą¤", "remove_url": "į§ģ除 URL", - "remove_user": "į§ģ除ᔍæˆļ", + "remove_user": "į§ģ除äŊŋᔍ者", "removed_api_key": "厞į§ģ除 API 金鑰īŧš{name}", "removed_from_archive": "垞封存中į§ģ除", "removed_from_favorites": "åˇ˛åžžæ”ļ藏中į§ģ除", @@ -1623,9 +1657,9 @@ "reset": "重設", "reset_password": "é‡č¨­å¯†įĸŧ", "reset_people_visibility": "重設äēēį‰Šå¯čĻ‹æ€§", - "reset_pin_code": "重įŊŽ PIN įĸŧ", - "reset_pin_code_description": "č‹Ĩåŋ˜č¨˜äē†PIN įĸŧīŧŒé–Ŗä¸‹å¯čĻæą‚įŗģįĩąäŧ翜å™¨įŽĄį†å“Ąį‚ē您重įŊŽ", - "reset_pin_code_success": "é–Ŗä¸‹åˇ˛æˆåŠŸé‡č¨­PINįĸŧ", + "reset_pin_code": "重設 PIN įĸŧ", + "reset_pin_code_description": "č‹Ĩåŋ˜č¨˜äē† PIN įĸŧīŧŒé–Ŗä¸‹å¯čĻæą‚įŗģįĩąäŧ翜å™¨įŽĄį†å“Ąį‚ēæ‚¨é‡č¨­", + "reset_pin_code_success": "é–Ŗä¸‹åˇ˛æˆåŠŸé‡č¨­ PIN įĸŧ", "reset_pin_code_with_password": "您可隨時äŊŋį”¨æ‚¨įš„å¯†įĸŧ來重設 PIN įĸŧ", "reset_sqlite": "重設 SQLite čŗ‡æ–™åēĢ", "reset_sqlite_confirmation": "įĸē厚čĻé‡č¨­ SQLite čŗ‡æ–™åēĢ嗎īŧŸé–Ŗä¸‹éœ€į™ģå‡ēä¸Ļ重新į™ģå…Ĩ才čƒŊ重新同æ­Ĩčŗ‡æ–™", @@ -1639,21 +1673,22 @@ "restore_user": "還原äŊŋᔍ者", "restored_asset": "åˇ˛é‚„åŽŸæĒ”æĄˆ", "resume": "įšŧįēŒ", + "resume_paused_jobs": "æĸ垊 {count, plural, one {# æšĢåœįš„äģģ務} other {# æšĢåœįš„äģģ務}}", "retry_upload": "é‡æ–°ä¸Šå‚ŗ", "review_duplicates": "æĒĸčĻ–é‡č¤‡é …į›Ž", - "review_large_files": "æĒĸčĻ–å¤§åž‹æ–‡äģļ", + "review_large_files": "æĒĸčĻ–å¤§åž‹æĒ”æĄˆ", "role": "角色", "role_editor": "ᎍčŧ¯č€…", "role_viewer": "æĒĸčϖ者", - "running": "運行中", + "running": "åŸˇčĄŒä¸­", "save": "å„˛å­˜", - "save_to_gallery": "å„˛å­˜åˆ°åœ–åēĢ", + "save_to_gallery": "å„˛å­˜åˆ°į›¸į°ŋ", "saved_api_key": "åˇ˛å„˛å­˜ API 金鑰", "saved_profile": "åˇ˛å„˛å­˜å€‹äēēčŗ‡æ–™", "saved_settings": "åˇ˛å„˛å­˜č¨­åŽš", "say_something": "čĒĒčĒĒæ‚¨įš„æƒŗæŗ•吧", "scaffold_body_error_occurred": "į™ŧį”ŸéŒ¯čǤ", - "scan_all_libraries": "掃描所有圖åēĢ", + "scan_all_libraries": "æŽƒææ‰€æœ‰į›¸į°ŋ", "scan_library": "掃描", "scan_settings": "æŽƒæč¨­åŽš", "scanning_for_album": "æŽƒæį›¸į°ŋ中â€Ļâ€Ļ", @@ -1692,11 +1727,11 @@ "search_page_motion_photos": "å‹•æ…‹į…§į‰‡", "search_page_no_objects": "æ‰žä¸åˆ°į‰Šäģļčŗ‡č¨Š", "search_page_no_places": "扞不到地éģžčŗ‡č¨Š", - "search_page_screenshots": "åąåš•æˆĒ圖", + "search_page_screenshots": "čžĸåš•æˆĒ圖", "search_page_search_photos_videos": "æœå°‹æ‚¨įš„į…§į‰‡čˆ‡åŊąį‰‡", "search_page_selfies": "č‡Ē拍", "search_page_things": "äē‹į‰Š", - "search_page_view_all_button": "æŸĨįœ‹å…¨éƒ¨", + "search_page_view_all_button": "æĒĸčĻ–å…¨éƒ¨", "search_page_your_activity": "æ‚¨įš„æ´ģ動", "search_page_your_map": "æ‚¨įš„čļŗčˇĄ", "search_people": "搜尋äēēį‰Š", @@ -1713,7 +1748,7 @@ "search_your_photos": "æœå°‹į…§į‰‡", "searching_locales": "搜尋區域â€Ļ", "second": "į§’", - "see_all_people": "æŸĨįœ‹æ‰€æœ‰äēēį‰Š", + "see_all_people": "æĒĸčĻ–æ‰€æœ‰äēēį‰Š", "select": "選擇", "select_album_cover": "é¸æ“‡į›¸į°ŋ封éĸ", "select_all": "選擇全部", @@ -1724,7 +1759,7 @@ "select_featured_photo": "é¸æ“‡į‰šč‰˛į…§į‰‡", "select_from_computer": "åžžé›ģč…Ļ中選取", "select_keep_all": "全部äŋį•™", - "select_library_owner": "選擇圖åēĢæ“æœ‰č€…", + "select_library_owner": "é¸æ“‡į›¸į°ŋæ“æœ‰č€…", "select_new_face": "é¸æ“‡æ–°č‡‰å­”", "select_person_to_tag": "選擇čĻæ¨™č¨˜įš„äēēį‰Š", "select_photos": "遏ᅧቇ", @@ -1732,12 +1767,12 @@ "select_user_for_sharing_page_err_album": "新åĸžį›¸į°ŋå¤ąæ•—", "selected": "åˇ˛é¸æ“‡", "selected_count": "{count, plural, other {選äē† # 項}}", - "selected_gps_coordinates": "åˇ˛é¸æ“‡įš„ GPS åē§æ¨™", + "selected_gps_coordinates": "é¸åŽšįš„ GPS åē§æ¨™", "send_message": "å‚ŗč¨Šæ¯", "send_welcome_email": "å‚ŗé€æ­ĄčŋŽé›ģ子éƒĩäģļ", "server_endpoint": "äŧ翜å™¨į̝éģž", "server_info_box_app_version": "App į‰ˆæœŦ", - "server_info_box_server_url": "äŧ翜å™¨åœ°å€", + "server_info_box_server_url": "äŧ翜å™¨įļ˛å€", "server_offline": "äŧ翜å™¨åˇ˛é›ĸ᎚", "server_online": "äŧ翜å™¨åˇ˛ä¸Šįˇš", "server_privacy": "äŧ翜å™¨éšąį§", @@ -1748,13 +1783,13 @@ "set_as_featured_photo": "設į‚ēį‰šč‰˛į…§į‰‡", "set_as_profile_picture": "設į‚ē個äēēčŗ‡æ–™åœ–į‰‡", "set_date_of_birth": "č¨­åŽšå‡ēį”Ÿæ—Ĩ期", - "set_profile_picture": "設įŊŽå€‹äēēčŗ‡æ–™åœ–į‰‡", + "set_profile_picture": "č¨­åŽšå€‹äēēčŗ‡æ–™åœ–į‰‡", "set_slideshow_to_fullscreen": "äģĨ全čžĸ嚕攞映åšģį‡ˆį‰‡", - "set_stack_primary_asset": "設įŊŽå †į–Šįš„éĻ–čĻé …į›Ž", - "setting_image_viewer_help": "čŠŗį´°čŗ‡č¨ŠæŸĨįœ‹å™¨éĻ–å…ˆčŧ‰å…Ĩå°į¸Žåœ–īŧŒį„ļ垌čŧ‰å…Ĩä¸­į­‰å¤§å°įš„é čĻŊ圖īŧˆč‹Ĩ啓ᔍīŧ‰īŧŒæœ€åžŒčŧ‰å…ĨåŽŸå§‹åœ–į‰‡ã€‚", - "setting_image_viewer_original_subtitle": "啓ᔍäģĨčŧ‰å…Ĩ原圖īŧŒįρᔍäģĨ減少數據äŊŋį”¨é‡īŧˆåŒ…æ‹Ŧįļ˛įĩĄå’ŒčŖįŊŽįˇŠå­˜īŧ‰ã€‚", + "set_stack_primary_asset": "č¨­åŽšå †į–Šįš„éĻ–čĻé …į›Ž", + "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": "åĨ—ᔍ", @@ -1768,13 +1803,13 @@ "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_looping_title": "čŋ´åœˆæ’­æ”ž", "setting_video_viewer_original_video_subtitle": "åžžäŧ翜å™¨ä¸˛æĩåŊąį‰‡æ™‚īŧŒå„Ē先播攞原始į•ĢčŗĒīŧˆåŗäŊŋ有čŊ‰æĒ”įš„į‰ˆæœŦå¯į”¨īŧ‰ã€‚這可čƒŊæœƒå°Žč‡´æ’­æ”žæ™‚å‡ēįžįˇŠčĄæƒ…æŗã€‚č‹ĨåŊąį‰‡åˇ˛å„˛å­˜åœ¨æœŦ抟īŧŒå‰‡ä¸€åž‹äģĨ原始į•ĢčŗĒ播攞īŧŒčˆ‡æ­¤č¨­åŽšį„Ąé—œã€‚", "setting_video_viewer_original_video_title": "一型播攞原始åŊąį‰‡", "settings": "č¨­åŽš", - "settings_require_restart": "čĢ‹é‡å•“ Immich äģĨäŊŋč¨­åŽšį”Ÿæ•ˆ", + "settings_require_restart": "čĢ‹é‡å•Ÿ Immich äģĨäŊŋč¨­åŽšį”Ÿæ•ˆ", "settings_saved": "č¨­åŽšåˇ˛å„˛å­˜", "setup_pin_code": "č¨­åŽš PIN įĸŧ", "share": "分äēĢ", @@ -1784,35 +1819,35 @@ "share_dialog_preparing": "æ­Ŗåœ¨æē–å‚™...", "share_link": "分äēĢ逪įĩ", "shared": "å…ąäēĢ", - "shared_album_activities_input_disable": "厞įĻį”¨čŠ•čĢ–", + "shared_album_activities_input_disable": "åˇ˛åœį”¨čŠ•čĢ–", "shared_album_activity_remove_content": "您įĸē厚čρåˆĒ除此æ´ģ動嗎īŧŸ", "shared_album_activity_remove_title": "åˆĒ除æ´ģ動", - "shared_album_section_people_action_error": "退å‡ē/åˆĒ除ᛏį°ŋå¤ąæ•—", - "shared_album_section_people_action_leave": "åžžį›¸į°ŋ中åˆĒ除ᔍæˆļ", - "shared_album_section_people_action_remove_user": "åžžį›¸į°ŋ中åˆĒ除ᔍæˆļ", + "shared_album_section_people_action_error": "įĩæŸ/åˆĒ除ᛏį°ŋå¤ąæ•—", + "shared_album_section_people_action_leave": "åžžį›¸į°ŋ中åˆĒ除äŊŋᔍ者", + "shared_album_section_people_action_remove_user": "åžžį›¸į°ŋ中åˆĒ除äŊŋᔍ者", "shared_album_section_people_title": "äēēį‰Š", "shared_by": "å…ąäēĢč‡Ē", "shared_by_user": "į”ą {user} 分äēĢ", "shared_by_you": "į”ąæ‚¨åˆ†äēĢ", "shared_from_partner": "來č‡Ē {partner} įš„į…§į‰‡", "shared_intent_upload_button_progress_text": "{current} / {total} åˇ˛ä¸Šå‚ŗ", - "shared_link_app_bar_title": "å…ąäēĢ鏈æŽĨ", - "shared_link_clipboard_copied_massage": "複čŖŊ到å‰Ēč˛ŧæŋ", + "shared_link_app_bar_title": "å…ąäēĢ逪įĩ", + "shared_link_clipboard_copied_massage": "複čŖŊ到å‰Ēč˛ŧį°ŋ", "shared_link_clipboard_text": "逪įĩīŧš {link}\n密įĸŧīŧš {password}", "shared_link_create_error": "新åĸžå…ąäēĢ逪įĩæ™‚į™ŧį”ŸéŒ¯čǤ", - "shared_link_custom_url_description": "äŊŋᔍč‡ĒåŽšįžŠįš„ URL 逪įĩ", + "shared_link_custom_url_description": "äŊŋᔍč‡Ē訂 URL", "shared_link_edit_description_hint": "ᎍčŧ¯å…ąäēĢæčŋ°", - "shared_link_edit_expire_after_option_day": "1夊", + "shared_link_edit_expire_after_option_day": "1 夊", "shared_link_edit_expire_after_option_days": "{count} 夊", - "shared_link_edit_expire_after_option_hour": "1小時", + "shared_link_edit_expire_after_option_hour": "1 小時", "shared_link_edit_expire_after_option_hours": "{count} 小時", - "shared_link_edit_expire_after_option_minute": "1分鐘", + "shared_link_edit_expire_after_option_minute": "1 分鐘", "shared_link_edit_expire_after_option_minutes": "{count} 分鐘", "shared_link_edit_expire_after_option_months": "{count} 個月", "shared_link_edit_expire_after_option_year": "{count} åš´", "shared_link_edit_password_hint": "čŧ¸å…Ĩå…ąäēĢ密įĸŧ", "shared_link_edit_submit_button": "æ›´æ–°é€Ŗįĩ", - "shared_link_error_server_url_fetch": "į„Ąæŗ•å–åž—äŧ翜å™¨åœ°å€", + "shared_link_error_server_url_fetch": "į„Ąæŗ•å–åž—äŧ翜å™¨įļ˛å€", "shared_link_expires_day": "{count} 夊垌過期", "shared_link_expires_days": "{count} 夊垌過期", "shared_link_expires_hour": "{count} 小時垌過期", @@ -1824,18 +1859,18 @@ "shared_link_expires_seconds": "將在 {count} į§’åžŒéŽæœŸ", "shared_link_individual_shared": "個äēēå…ąäēĢ", "shared_link_info_chip_metadata": "EXIF", - "shared_link_manage_links": "įŽĄį†å…ąäēĢ鏈æŽĨ", + "shared_link_manage_links": "įŽĄį†å…ąäēĢ逪įĩ", "shared_link_options": "å…ąäēĢ逪įĩé¸é …", - "shared_link_password_description": "čĻæą‚åœ¨č¨Ēå•æ­¤é€Ŗįĩæ™‚提䞛密įĸŧ", + "shared_link_password_description": "čĻæą‚åœ¨å­˜å–æ­¤é€Ŗįĩæ™‚提䞛密įĸŧ", "shared_links": "å…ąäēĢ逪įĩ", "shared_links_description": "äģĨ逪įĩåˆ†äēĢį…§į‰‡å’ŒåŊąį‰‡", "shared_photos_and_videos_count": "{assetCount, plural, other {åˇ˛åˆ†äēĢ # åŧĩį…§į‰‡åŠåŊąį‰‡ã€‚}}", "shared_with_me": "čˆ‡æˆ‘å…ąäēĢ", "shared_with_partner": "與 {partner} å…ąäēĢ", "sharing": "å…ąäēĢ", - "sharing_enter_password": "čρæŸĨįœ‹æ­¤é éĸčĢ‹čŧ¸å…Ĩ密įĸŧ。", + "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": "新åĸžå…ąäēĢᛏį°ŋ", @@ -1843,11 +1878,9 @@ "shift_to_permanent_delete": "按 ⇧ 永䚅åˆĒ除æĒ”æĄˆ", "show_album_options": "éĄ¯į¤ēᛏį°ŋ選項", "show_albums": "éĄ¯į¤ēᛏį°ŋ", - "show_all_assets": "éĄ¯į¤ēæ‰€æœ‰é …į›Ž", "show_all_people": "éĄ¯į¤ē所有äēēį‰Š", "show_and_hide_people": "éĄ¯į¤ē與隱藏äēēį‰Š", - "show_assets_without_location": "éĄ¯į¤ēæ˛’æœ‰åœ°éģžįš„é …į›Ž", - "show_file_location": "éĄ¯į¤ē文äģļäŊįŊŽ", + "show_file_location": "éĄ¯į¤ēæĒ”æĄˆäŊįŊŽ", "show_gallery": "éĄ¯į¤ēį•ĢåģŠ", "show_hidden_people": "éĄ¯į¤ēéšąč—įš„äēēį‰Š", "show_in_timeline": "在時間čģ¸ä¸­éĄ¯į¤ē", @@ -1863,9 +1896,10 @@ "show_slideshow_transition": "éĄ¯į¤ēåšģį‡ˆį‰‡čŊ‰å ´", "show_supporter_badge": "æ“č­ˇč€…åžŊįĢ ", "show_supporter_badge_description": "éĄ¯į¤ēæ“č­ˇč€…åžŊįĢ ", + "show_text_search_menu": "éĄ¯į¤ēæ–‡å­—č’į´ĸ選喎", "shuffle": "隨抟排åē", "sidebar": "側邊æŦ„", - "sidebar_display_description": "在側邊æŦ„ä¸­éĄ¯į¤ē鏈įĩ", + "sidebar_display_description": "在側邊æŦ„ä¸­éĄ¯į¤ē逪įĩ", "sign_out": "į™ģå‡ē", "sign_up": "č¨ģ冊", "size": "į”¨é‡", @@ -1884,7 +1918,7 @@ "sort_recent": "æœ€æ–°įš„į…§į‰‡", "sort_title": "æ¨™éĄŒ", "source": "來æē", - "stack": "堆叠", + "stack": "å †į–Š", "stack_action_prompt": "åˇ˛å †į–Šäē†{count} å€‹é …į›Ž", "stack_duplicates": "å †į–Šé‡č¤‡é …į›Ž", "stack_select_one_photo": "į‚ēå †į–Šé¸ä¸€åŧĩä¸ģčρᅧቇ", @@ -1893,13 +1927,14 @@ "stacktrace": "å †į–ŠčŋŊ蚤", "start": "開始", "start_date": "開始æ—Ĩ期", + "start_date_before_end_date": "開始æ—Ĩ期åŋ…須旊æ–ŧįĩæŸæ—Ĩ期", "state": "地區", "status": "į‹€æ…‹", - "stop_casting": "停æ­ĸcasting", + "stop_casting": "停æ­ĸ投攞", "stop_motion_photo": "停æ­ĸå‹•æ…‹į…§į‰‡", "stop_photo_sharing": "čρ停æ­ĸ分äēĢæ‚¨įš„į…§į‰‡å—ŽīŧŸ", - "stop_photo_sharing_description": "{partner} å°‡į„Ąæŗ•å†č¨Ēå•æ‚¨įš„į…§į‰‡ã€‚", - "stop_sharing_photos_with_user": "停æ­ĸčˆ‡æ­¤į”¨æˆļå…ąäēĢæ‚¨įš„ᅧቇ", + "stop_photo_sharing_description": "{partner} å°‡į„Ąæŗ•å†å­˜å–æ‚¨įš„į…§į‰‡ã€‚", + "stop_sharing_photos_with_user": "停æ­ĸčˆ‡æ­¤äŊŋį”¨č€…å…ąäēĢæ‚¨įš„ᅧቇ", "storage": "å„˛å­˜įŠē間", "storage_label": "å„˛å­˜æ¨™įą¤", "storage_quota": "å„˛å­˜įŠē間", @@ -1909,14 +1944,16 @@ "suggestions": "åģēč­°", "sunrise_on_the_beach": "æ—Ĩå‡ēįš„æĩˇį˜", "support": "支援", - "support_and_feedback": "æ”¯æŒčˆ‡å›žéĨ‹", - "support_third_party_description": "æ‚¨åŽ‰čŖįš„ immich æ˜¯į”ąįŦŦä¸‰æ–šæ‰“åŒ…įš„ã€‚æ‚¨é‡åˆ°įš„å•éĄŒå¯čƒŊæ˜¯čŠ˛čģŸéĢ”åŒ…é€ æˆįš„īŧŒæ‰€äģĨčĢ‹å…ˆäŊŋᔍ䏋éĸįš„éˆįĩå‘äģ–們提å‡ēå•éĄŒã€‚", + "support_and_feedback": "æ”¯æ´čˆ‡å›žéĨ‹", + "support_third_party_description": "æ‚¨åŽ‰čŖįš„ Immich æ˜¯į”ąįŦŦä¸‰æ–šæ‰“åŒ…įš„ã€‚æ‚¨é‡åˆ°įš„å•éĄŒå¯čƒŊæ˜¯čŠ˛åĨ—äģļé€ æˆįš„īŧŒæ‰€äģĨčĢ‹å…ˆäŊŋᔍ䏋éĸįš„é€Ŗįĩå‘äģ–們提å‡ēå•éĄŒã€‚", "swap_merge_direction": "ä礿›åˆäŊĩ斚向", "sync": "同æ­Ĩ", "sync_albums": "同æ­Ĩᛏį°ŋ", "sync_albums_manual_subtitle": "å°‡æ‰€æœ‰ä¸Šå‚ŗįš„įŸ­į‰‡å’Œį…§į‰‡åŒæ­Ĩåˆ°é¸åŽšįš„å‚™äģŊᛏį°ŋ", "sync_local": "同æ­ĨæœŦ抟", "sync_remote": "同æ­Ĩ遠į̝", + "sync_status": "同æ­Ĩį‹€æ…‹", + "sync_status_subtitle": "æĒĸčĻ–å’ŒįŽĄį†åŒæ­Ĩįŗģįĩą", "sync_upload_album_setting_subtitle": "新åĸžį…§į‰‡å’ŒįŸ­į‰‡ä¸Ļä¸Šå‚ŗåˆ° Immich ä¸Šįš„é¸åŽšį›¸į°ŋ中", "tag": "æ¨™įą¤", "tag_assets": "æ¨™č¨˜æĒ”æĄˆ", @@ -1927,7 +1964,7 @@ "tag_updated": "åˇ˛æ›´æ–°æ¨™įą¤īŧš{tag}", "tagged_assets": "åˇ˛æ¨™įą¤ {count, plural, one {# 個æĒ”æĄˆ} other {# 個æĒ”æĄˆ}}", "tags": "æ¨™įą¤", - "tap_to_run_job": "éģžæ“ŠäģĨ進行äŊœæĨ­", + "tap_to_run_job": "éģžé¸äģĨ進行äŊœæĨ­", "template": "æ¨Ąæŋ", "theme": "ä¸ģ題", "theme_selection": "ä¸ģ題選項", @@ -1935,16 +1972,16 @@ "theme_setting_asset_list_storage_indicator_title": "åœ¨é …į›Žæ¨™éĄŒä¸ŠéĄ¯į¤ēäŊŋį”¨äš‹å„˛å­˜įŠē間", "theme_setting_asset_list_tiles_per_row_title": "æ¯čĄŒåą•į¤ē {count} 項", "theme_setting_colorful_interface_subtitle": "åĨ—ᔍä¸ģ色čĒŋåˆ°čƒŒæ™¯ã€‚", - "theme_setting_colorful_interface_title": "åŊŠč‰˛į•Œéĸ", - "theme_setting_image_viewer_quality_subtitle": "čĒŋ整æŸĨįœ‹å¤§åœ–æ™‚įš„åœ–į‰‡čŗĒ量", - "theme_setting_image_viewer_quality_title": "åœ–į‰‡čŗĒ量", + "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_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_title": "啓ᔍ䏉æŽĩåŧčŧ‰å…Ĩ", + "theme_setting_three_stage_loading_title": "å•Ÿį”¨ä¸‰æŽĩåŧčŧ‰å…Ĩ", "they_will_be_merged_together": "厃們將會čĸĢ合äŊĩ在一čĩˇ", "third_party_resources": "įŦŦä¸‰æ–ščŗ‡æē", "time_based_memories": "䞝時間回æ†ļ", @@ -1954,7 +1991,9 @@ "to_change_password": "čŽŠæ›´å¯†įĸŧ", "to_favorite": "æ”ļ藏", "to_login": "į™ģå…Ĩ", + "to_multi_select": "é€˛čĄŒå¤šé¸", "to_parent": "åˆ°ä¸Šä¸€į´š", + "to_select": "選擇", "to_trash": "垃圞æĄļ", "toggle_settings": "åˆ‡æ›č¨­åŽš", "total": "įĩąč¨ˆ", @@ -1967,13 +2006,14 @@ "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": "回æ”ļæĄļä¸­é …į›Žå°‡åœ¨ {days} 夊垌永䚅åˆĒ除", "trash_page_no_assets": "æšĢį„Ąåˇ˛åˆĒé™¤é …į›Ž", "trash_page_restore_all": "æĸ垊全部", "trash_page_select_assets_btn": "é¸æ“‡é …į›Ž", "trash_page_title": "垃圞æĄļ ({count})", "trashed_items_will_be_permanently_deleted_after": "垃圞æĄļä¸­įš„é …į›Žæœƒåœ¨ {days, plural, other {# 夊}}垌永䚅åˆĒ除。", + "troubleshoot": "ᖑ雪觪᭔", "type": "éĄžåž‹", "unable_to_change_pin_code": "į„Ąæŗ•čŽŠæ›´ PIN įĸŧ", "unable_to_setup_pin_code": "į„Ąæŗ•č¨­åŽš PIN įĸŧ", @@ -1986,11 +2026,11 @@ "unhide_person": "取æļˆéšąč—äēēį‰Š", "unknown": "æœĒįŸĨ", "unknown_country": "æœĒįŸĨ國åŽļ", - "unknown_year": "不įŸĨåš´äģŊ", + "unknown_year": "æœĒįŸĨåš´äģŊ", "unlimited": "不限åˆļ", - "unlink_motion_video": "取æļˆéˆįĩå‹•æ…‹åŊąį‰‡", - "unlink_oauth": "取æļˆé€ŖæŽĨ OAuth", - "unlinked_oauth_account": "厞觪除逪æŽĨ OAuth å¸ŗč™Ÿ", + "unlink_motion_video": "觪除逪įĩå‹•æ…‹åŊąį‰‡", + "unlink_oauth": "觪除逪įĩ OAuth", + "unlinked_oauth_account": "厞觪除逪įĩ OAuth å¸ŗč™Ÿ", "unmute_memories": "取æļˆéœéŸŗå›žæ†ļ", "unnamed_album": "æœĒå‘Ŋåį›¸į°ŋ", "unnamed_album_delete_confirmation": "įĸē厚čρåˆĒ除這æœŦᛏį°ŋ嗎īŧŸ", @@ -1999,11 +2039,12 @@ "unselect_all": "取æļˆå…¨é¸", "unselect_all_duplicates": "取æļˆé¸å–æ‰€æœ‰įš„é‡č¤‡é …į›Ž", "unselect_all_in": "{group} 全不選", - "unstack": "取æļˆå †å ", + "unstack": "取æļˆå †į–Š", "unstack_action_prompt": "{count} 個取æļˆå †į–Š", "unstacked_assets_count": "åˇ˛č§Ŗé™¤å †į–Š {count, plural, other {# 個æĒ”æĄˆ}}", "untagged": "į„Ąæ¨™įą¤", "up_next": "下一個", + "update_location_action_prompt": "äŊŋᔍäģĨ下å‘Ŋä줿›´æ–°{count}å€‹æ‰€é¸čŗ‡į”ĸįš„äŊįŊŽīŧš", "updated_at": "更新æ–ŧ", "updated_password": "åˇ˛æ›´æ–°å¯†įĸŧ", "upload": "ä¸Šå‚ŗ", @@ -2012,14 +2053,14 @@ "upload_details": "ä¸Šå‚ŗčŠŗį´°čŗ‡č¨Š", "upload_dialog_info": "是åĻčĻå°‡æ‰€é¸é …į›Žå‚™äģŊ到äŧ翜å™¨īŧŸ", "upload_dialog_title": "ä¸Šå‚ŗé …į›Ž", - "upload_errors": "ä¸Šå‚ŗåŽŒæˆīŧŒäŊ†æœ‰ {count, plural, other {# č™•æ™‚į™ŧį”ŸéŒ¯čǤ}}īŧŒčρæŸĨįœ‹æ–°ä¸Šå‚ŗįš„æĒ”æĄˆčĢ‹é‡æ–°æ•´į†é éĸ。", + "upload_errors": "ä¸Šå‚ŗåŽŒæˆīŧŒäŊ†æœ‰ {count, plural, other {# č™•æ™‚į™ŧį”ŸéŒ¯čǤ}}īŧŒčρæĒĸčĻ–æ–°ä¸Šå‚ŗįš„æĒ”æĄˆčĢ‹é‡æ–°æ•´į†é éĸ。", "upload_finished": "ä¸Šå‚ŗåŽŒæˆ", "upload_progress": "削餘 {remaining, number} - 厞處ᐆ {processed, number}/{total, number}", "upload_skipped_duplicates": "厞į•Ĩ過 {count, plural, other {# å€‹é‡č¤‡įš„æĒ”æĄˆ}}", "upload_status_duplicates": "é‡č¤‡é …į›Ž", "upload_status_errors": "錯čǤ", "upload_status_uploaded": "åˇ˛ä¸Šå‚ŗ", - "upload_success": "ä¸Šå‚ŗæˆåŠŸīŧŒčρæŸĨįœ‹æ–°ä¸Šå‚ŗįš„æĒ”æĄˆčĢ‹é‡æ–°æ•´į†é éĸ。", + "upload_success": "ä¸Šå‚ŗæˆåŠŸīŧŒčρæĒĸčĻ–æ–°ä¸Šå‚ŗįš„æĒ”æĄˆčĢ‹é‡æ–°æ•´į†é éĸ。", "upload_to_immich": "ä¸Šå‚ŗč‡ŗ Immich ({count})", "uploading": "ä¸Šå‚ŗä¸­", "uploading_media": "åĒ’éĢ”ä¸Šå‚ŗä¸­", @@ -2028,9 +2069,8 @@ "use_biometric": "äŊŋį”¨į”Ÿį‰Ščž¨č­˜", "use_current_connection": "äŊŋį”¨į›Žå‰įš„é€Ŗįˇš", "use_custom_date_range": "æ”šį”¨č‡Ē訂æ—ĨæœŸį¯„åœ", - "use_this_location": "éģžæ“ŠäģĨäŊŋᔍäŊįŊŽ", "user": "äŊŋᔍ者", - "user_has_been_deleted": "æ­¤į”¨æˆļ厞čĸĢåˆĒ除。", + "user_has_been_deleted": "æ­¤äŊŋᔍ者厞čĸĢåˆĒ除。", "user_id": "äŊŋᔍ者 ID", "user_liked": "{user} å–œæ­Ąäē† {type, select, photo {這åŧĩᅧቇ} video {這æŽĩåŊąį‰‡} asset {這個æĒ”æĄˆ} other {厃}}", "user_pin_code_settings": "PIN įĸŧ", @@ -2041,13 +2081,13 @@ "user_role_set": "設 {user} į‚ē{role}", "user_usage_detail": "äŊŋį”¨č€…į”¨é‡čŠŗį´°čŗ‡č¨Š", "user_usage_stats": "å¸ŗč™ŸäŊŋį”¨é‡įĩąč¨ˆ", - "user_usage_stats_description": "æŸĨįœ‹å¸ŗč™ŸäŊŋį”¨é‡", + "user_usage_stats_description": "æĒĸčĻ–å¸ŗč™ŸäŊŋį”¨é‡", "username": "äŊŋį”¨č€…åį¨ą", "users": "admin", "users_added_to_album_count": "åˇ˛åœ¨æ­¤į›¸į°ŋ中新åĸžäē† {count, plural, one {# 個} other {# 個}} äŊŋᔍ者", "utilities": "åˇĨå…ˇ", "validate": "驗證", - "validate_endpoint_error": "čĢ‹čŧ¸å…Ĩæœ‰æ•ˆįš„é€Ŗįĩ", + "validate_endpoint_error": "čĢ‹čŧ¸å…Ĩæœ‰æ•ˆįš„ URL", "variables": "čŽŠæ•¸", "version": "į‰ˆæœŦ", "version_announcement_closing": "æ•ŦįĨé †åŋƒīŧŒAlex", @@ -2055,23 +2095,24 @@ "version_history": "į‰ˆæœŦį´€éŒ„", "version_history_item": "{date} åŽ‰čŖäē† {version}", "video": "åŊąį‰‡", - "video_hover_setting": "æ¸¸æ¨™åœį•™æ™‚æ’­æ”žåŊąį‰‡į¸Žåœ–", + "video_hover_setting": "éŠæ¨™åœį•™æ™‚æ’­æ”žåŊąį‰‡į¸Žåœ–", "video_hover_setting_description": "į•ļæģ‘éŧ åœåœ¨é …į›Žä¸Šæ™‚æ’­æ”žåŊąį‰‡į¸Žåœ–ã€‚åŗäŊŋåœį”¨īŧŒå°‡æģ‘éŧ åœåœ¨æ’­æ”žåœ–į¤ē上䚟可äģĨ播攞。", "videos": "åŊąį‰‡", "videos_count": "{count, plural, other {# 部åŊąį‰‡}}", - "view": "æŸĨįœ‹", - "view_album": "æŸĨįœ‹į›¸į°ŋ", + "view": "æĒĸčĻ–", + "view_album": "æĒĸčϖᛏį°ŋ", "view_all": "į€čĻŊ全部", - "view_all_users": "æŸĨįœ‹æ‰€æœ‰äŊŋᔍ者", + "view_all_users": "æĒĸčĻ–æ‰€æœ‰äŊŋᔍ者", "view_details": "æĒĸčĻ–čŠŗį´°čŗ‡č¨Š", - "view_in_timeline": "在時間čģ¸ä¸­æŸĨįœ‹", - "view_link": "æŸĨįœ‹é€Ŗįĩ", - "view_links": "æĒĸčĻ–éˆįĩ", + "view_in_timeline": "在時間čģ¸ä¸­æĒĸčĻ–", + "view_link": "æĒĸčϖ逪įĩ", + "view_links": "æĒĸčϖ逪įĩ", "view_name": "æĒĸčĻ–åˆ†éĄž", - "view_next_asset": "æŸĨįœ‹ä¸‹ä¸€é …", - "view_previous_asset": "æŸĨįœ‹ä¸Šä¸€é …", - "view_qr_code": "æŸĨįœ‹ QR code", - "view_stack": "æŸĨįœ‹å †į–Š", + "view_next_asset": "æĒĸčϖ䏋䏀項", + "view_previous_asset": "æĒĸčĻ–ä¸Šä¸€é …", + "view_qr_code": "æĒĸčĻ– QR code", + "view_similar_photos": "æĒĸčϖᛏäŧŧᅧቇ", + "view_stack": "æĒĸčĻ–å †į–Š", "view_user": "éĄ¯į¤ēäŊŋᔍ者", "viewer_remove_from_stack": "åžžå †į–Šä¸­į§ģ除", "viewer_stack_use_as_main_asset": "äŊœį‚ēä¸ģé …į›ŽäŊŋᔍ", @@ -2089,5 +2130,6 @@ "yes": "是", "you_dont_have_any_shared_links": "æ‚¨æ˛’æœ‰äģģäŊ•å…ąäēĢ逪įĩ", "your_wifi_name": "æ‚¨įš„ Wi-Fi åį¨ą", - "zoom_image": "į¸Žæ”žåœ–į‰‡" + "zoom_image": "į¸Žæ”žåœ–į‰‡", + "zoom_to_bounds": "į¸Žæ”žåˆ°é‚Šį•Œ" } diff --git a/i18n/zh_SIMPLIFIED.json b/i18n/zh_SIMPLIFIED.json index 79cc0ee227..fc575d44e5 100644 --- a/i18n/zh_SIMPLIFIED.json +++ b/i18n/zh_SIMPLIFIED.json @@ -26,12 +26,14 @@ "add_tag": "æˇģåŠ æ ‡į­ž", "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_added": "æˇģåŠ åˆ°į›¸å†Œ “{album}”", + "add_to_album_bottom_sheet_already_exists": "åˇ˛åœ¨į›¸å†Œâ€œ {album} ” 中", + "add_to_album_bottom_sheet_some_local_assets": "某ä盿œŦ地čĩ„äē§æ— æŗ•æˇģåŠ åˆ°į›¸å†Œ", "add_to_album_toggle": "é€‰æ‹Šį›¸å†Œ {album}", "add_to_albums": "æˇģåŠ åˆ°į›¸å†Œ", "add_to_albums_count": "æˇģåŠ åˆ°į›¸å†Œīŧˆ{count}ä¸Ēīŧ‰", "add_to_shared_album": "æˇģåŠ åˆ°å…ąäēĢį›¸å†Œ", + "add_upload_to_stack": "上äŧ éĄšį›Žč‡ŗå †å ", "add_url": "æˇģ加 URL", "added_to_archive": "æˇģ加到åŊ’æĄŖ", "added_to_favorites": "æˇģ加到æ”ļ藏", @@ -100,7 +102,7 @@ "image_thumbnail_description": "å‰ĨįĻģå…ƒæ•°æŽįš„å°įŧŠį•Ĩ回īŧŒį”¨äēŽæĩč§ˆä¸ģæ—ļ间įēŋᭉᅧቇįģ„", "image_thumbnail_quality_description": "įŧŠį•Ĩå›žč´¨é‡äģŽ 1 到 100。čļŠé̘čļŠåĨŊīŧŒäŊ†äŧšäē§į”Ÿæ›´å¤§įš„æ–‡äģļīŧŒåšļ且äŧšé™äŊŽįŗģįģŸįš„响åē”čƒŊ力。", "image_thumbnail_title": "įŧŠį•Ĩå›žčŽžįŊŽ", - "job_concurrency": "{job}åšļ发", + "job_concurrency": "{job}äģģåŠĄåšļ发", "job_created": "äģģåŠĄåˇ˛åˆ›åģē", "job_not_concurrency_safe": "æ­¤äģģåŠĄåšļ发åšļ不厉全。", "job_settings": "äģģåŠĄčŽžįŊŽ", @@ -121,13 +123,20 @@ "library_watching_settings": "į›‘æŽ§å›žåē“īŧˆåŽžéĒŒæ€§īŧ‰", "library_watching_settings_description": "č‡ĒåŠ¨į›‘æŽ§æ–‡äģļ变化", "logging_enable_description": "吝ᔍæ—Ĩåŋ—čްåŊ•", - "logging_level_description": "å¯į”¨įš„æ—Ĩåŋ—įē§åˆĢ。", + "logging_level_description": "吝ᔍæ—ļīŧŒčρäŊŋį”¨įš„æ—Ĩåŋ—įē§åˆĢ。", "logging_settings": "æ—Ĩåŋ—", + "machine_learning_availability_checks": "å¯į”¨æ€§æŖ€æŸĨ", + "machine_learning_availability_checks_description": "č‡ĒåŠ¨æŖ€æĩ‹åšļäŧ˜å…ˆé€‰æ‹Šå¯į”¨įš„æœē器å­Ļäš æœåŠĄå™¨", + "machine_learning_availability_checks_enabled": "å¯į”¨å¯į”¨æ€§æŖ€æŸĨ", + "machine_learning_availability_checks_interval": "æŖ€æŸĨ间隔", + "machine_learning_availability_checks_interval_description": "两æŦĄå¯į”¨æ€§æŖ€æŸĨäš‹é—´įš„é—´éš”īŧˆæ¯Ģį§’īŧ‰", + "machine_learning_availability_checks_timeout": "č¯ˇæą‚čļ…æ—ļ", + "machine_learning_availability_checks_timeout_description": "ᔍäēŽå¯į”¨æ€§æŖ€æŸĨįš„čļ…æ—ļæ—ļ间īŧˆæ¯Ģį§’īŧ‰", "machine_learning_clip_model": "CLIP æ¨Ąåž‹", "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": "åĻ‚æžœįρᔍīŧŒæ— čŽēäģĨ下åĻ‚äŊ•莞įŊŽīŧŒæ‰€æœ‰æœē器å­Ļ䚠功čƒŊ将čĸĢįĻį”¨ã€‚", @@ -158,7 +167,7 @@ "map_enable_description": "å¯į”¨åœ°å›žåŠŸčƒŊ", "map_gps_settings": "地回与 GPS 莞įŊŽ", "map_gps_settings_description": "įŽĄį†åœ°å›žä¸Ž GPSīŧˆåå‘åœ°į†įŧ–᠁īŧ‰čŽžįŊŽ", - "map_implications": "地回功čƒŊ䞝čĩ–äēŽå¤–部地åŊĸč´´å›žæœåŠĄīŧˆtiles.immich.cloudīŧ‰", + "map_implications": "地回功čƒŊ䞝čĩ–äēŽå¤–部地回į“Ļį‰‡æœåŠĄīŧˆtiles.immich.cloudīŧ‰", "map_light_style": "æĩ…č‰˛æ¨Ąåŧ", "map_manage_reverse_geocoding_settings": "įŽĄį†åå‘åœ°į†įŧ–į čŽžįŊŽ", "map_reverse_geocoding": "åå‘åœ°į†įŧ–᠁", @@ -220,7 +229,7 @@ "oauth_enable_description": "äŊŋᔍ OAuth į™ģåŊ•", "oauth_mobile_redirect_uri": "į§ģ动įĢ¯é‡åŽšå‘ URI", "oauth_mobile_redirect_uri_override": "į§ģ动įĢ¯é‡åŽšå‘ URI čφᛖ", - "oauth_mobile_redirect_uri_override_description": "åŊ“ OAuth æäž›å•†ä¸å…čŽ¸äŊŋᔍį§ģ动 URI æ—ļ吝ᔍīŧŒåĻ‚â€œ''{callback}''”", + "oauth_mobile_redirect_uri_override_description": "åŊ“ OAuth æäž›å•†ä¸å…čŽ¸äŊŋᔍį§ģ动 URI æ—ļ吝ᔍīŧŒåĻ‚â€œ{callback}”", "oauth_role_claim": "č§’č‰˛åŖ°æ˜Ž", "oauth_role_claim_description": "æ šæŽæ­¤åŖ°æ˜Žįš„å­˜åœ¨č‡Ē动授äēˆįŽĄį†å‘˜čŽŋé—Žæƒé™ã€‚åŖ°æ˜Žå¯äģĨ是“user”īŧˆį”¨æˆˇīŧ‰æˆ–“admin”īŧˆįŽĄį†å‘˜īŧ‰ã€‚", "oauth_settings": "OAuth", @@ -364,7 +373,7 @@ "user_cleanup_job": "æ¸…į†į”¨æˆˇ", "user_delete_delay": "{user}įš„č´ĻæˆˇåŠéĄšį›Žå°†åœ¨{delay, plural, one {#夊} other {#夊}}后č‡Ē动永䚅删除。", "user_delete_delay_settings": "åģᅵŸåˆ é™¤", - "user_delete_delay_settings_description": "永䚅删除č´ĻæˆˇåŠå…￉€æœ‰éĄšį›Žäš‹å‰æ‰€äŋį•™įš„å¤Šæ•°ã€‚į”¨æˆˇåˆ é™¤äŊœä¸šäŧšåœ¨åˆå¤œæŖ€æŸĨ是åĻæœ‰į”¨æˆˇå¯äģĨ删除。寚č¯Ĩ莞įŊŽįš„æ›´æ”šå°†åœ¨ä¸‹æŦĄæ‰§čĄŒæ—ļį”Ÿæ•ˆã€‚", + "user_delete_delay_settings_description": "åˆ é™¤åŽæ°¸äš…åˆ é™¤į”¨æˆˇå¸æˆˇå’Œčĩ„äē§įš„å¤Šæ•°ã€‚į”¨æˆˇåˆ é™¤äŊœä¸šäŧšåœ¨åˆå¤œæŖ€æŸĨ是åĻæœ‰į”¨æˆˇå¯äģĨ删除。寚č¯Ĩ莞įŊŽįš„æ›´æ”šå°†åœ¨ä¸‹æŦĄæ‰§čĄŒæ—ļį”Ÿæ•ˆã€‚", "user_delete_immediately": "{user}įš„č´ĻæˆˇåŠéĄšį›Žå°†įĢ‹åŗæ°¸äš…åˆ é™¤ã€‚", "user_delete_immediately_checkbox": "įĢ‹åŗåˆ é™¤æŖ€į´ĸåˆ°įš„į”¨æˆˇåŠéĄšį›Ž", "user_details": "į”¨æˆˇč¯Ļ情", @@ -387,8 +396,6 @@ "admin_password": "įŽĄį†å‘˜å¯†į ", "administration": "įŗģįģŸįŽĄį†", "advanced": "é̘įē§", - "advanced_settings_beta_timeline_subtitle": "äŊ“éĒŒå…¨æ–°įš„åē”ᔍፋåē", - "advanced_settings_beta_timeline_title": "æĩ‹č¯•į‰ˆæ—ļ间įēŋ", "advanced_settings_enable_alternate_media_filter_subtitle": "äŊŋį”¨æ­¤é€‰éĄšå¯åœ¨åŒæ­Ĩčŋ‡į¨‹ä¸­æ šæŽå¤‡į”¨æĄäģļį­›é€‰éĄšį›Žã€‚äģ…åŊ“您在åē”ᔍፋåēæŖ€æĩ‹æ‰€æœ‰į›¸å†Œå‡é‡åˆ°é—Žéĸ˜æ—￉å°č¯•此功čƒŊ。", "advanced_settings_enable_alternate_media_filter_title": "[厞énj] äŊŋį”¨å¤‡į”¨įš„čŽžå¤‡į›¸å†ŒåŒæ­Ĩį­›é€‰æĄäģļ", "advanced_settings_log_level_title": "æ—Ĩåŋ—į­‰įē§: {level}", @@ -425,6 +432,7 @@ "album_remove_user_confirmation": "įĄŽåŽščρį§ģ除“{user}”吗īŧŸ", "album_search_not_found": "æœĒ扞到įŦĻ合搜į´ĸæĄäģļįš„į›¸å†Œ", "album_share_no_users": "įœ‹čĩˇæĨæ‚¨åˇ˛ä¸Žæ‰€æœ‰į”¨æˆˇå…ąäēĢä熿­¤į›¸å†ŒīŧŒæˆ–č€…æ‚¨æ šæœŦæ˛Ąæœ‰äģģäŊ•į”¨æˆˇå¯å…ąäēĢ。", + "album_summary": "į›¸å†Œæ‘˜čρ", "album_updated": "į›¸å†Œæœ‰æ›´æ–°", "album_updated_setting_description": "åŊ“å…ąäēĢį›¸å†Œæœ‰æ–°éĄšį›Žæ—ļæŽĨæ”ļ邮äģļ通įŸĨ", "album_user_left": "įĻģåŧ€â€œ{album}”", @@ -458,7 +466,7 @@ "api_key_description": "č¯Ĩåē”ᔍ坆é’ĨåĒäŧšæ˜žį¤ē一æŦĄã€‚č¯ˇįĄŽäŋåœ¨å…ŗé—­įĒ—åŖå‰å¤åˆļ下æĨ。", "api_key_empty": "API 密é’Ĩåį§°ä¸å¯ä¸ēįŠē", "api_keys": "API 密é’Ĩ", - "app_bar_signout_dialog_content": "įĄŽåŽšé€€å‡ēį™ģåŊ•īŧŸ", + "app_bar_signout_dialog_content": "æ‚¨įĄŽåŽščρ退å‡ē吗īŧŸ", "app_bar_signout_dialog_ok": "是", "app_bar_signout_dialog_title": "退å‡ēį™ģåŊ•", "app_settings": "åē”į”¨čŽžįŊŽ", @@ -496,6 +504,8 @@ "asset_restored_successfully": "åˇ˛æˆåŠŸæĸå¤æ‰€æœ‰éĄšį›Ž", "asset_skipped": "厞莺čŋ‡", "asset_skipped_in_trash": "åˇ˛å›žæ”ļ", + "asset_trashed": "čĩ„äē§åˇ˛čĸĢ删除", + "asset_troubleshoot": "čĩ„äē§æ•…障排除", "asset_uploaded": "厞䏊äŧ ", "asset_uploading": "上äŧ ä¸­â€Ļ", "asset_viewer_settings_subtitle": "įŽĄį†å›žå瓿ĩč§ˆå™¨čŽžįŊŽ", @@ -529,8 +539,10 @@ "autoplay_slideshow": "č‡Ē动播攞åšģၝቇ", "back": "čŋ”回", "back_close_deselect": "čŋ”å›žã€å…ŗé—­æˆ–åé€‰", + "background_backup_running_error": "后台备äģŊæ­Ŗåœ¨čŋčĄŒīŧŒæ— æŗ•启动手动备äģŊ", "background_location_permission": "后台厚äŊæƒé™", "background_location_permission_content": "ä¸ēįĄŽäŋåŽå°čŋčĄŒæ—ļč‡Ē动切æĸįŊ‘įģœīŧŒéœ€æŽˆäēˆ Immich *始įģˆå…čŽ¸į˛žįĄŽåŽšäŊ* 权限īŧŒäģĨ蝆åˆĢ Wi-Fi įŊ‘įģœåį§°", + "background_options": "čƒŒæ™¯é€‰éĄš", "backup": "备äģŊ", "backup_album_selection_page_albums_device": "čŽžå¤‡ä¸Šįš„į›¸å†Œīŧˆ{count}īŧ‰", "backup_album_selection_page_albums_tap": "单å‡ģ选中īŧŒåŒå‡ģ取æļˆ", @@ -538,6 +550,7 @@ "backup_album_selection_page_select_albums": "é€‰æ‹Šį›¸å†Œ", "backup_album_selection_page_selection_info": "选拊äŋĄæ¯", "backup_album_selection_page_total_assets": "æ€ģ莥", + "backup_albums_sync": "备äģŊį›¸å†ŒåŒæ­Ĩ", "backup_all": "全部", "backup_background_service_backup_failed_message": "备äģŊå¤ąč´ĨīŧŒæ­Ŗåœ¨é‡č¯•â€Ļ", "backup_background_service_connection_failed_message": "čŋžæŽĨæœåŠĄå™¨å¤ąč´ĨīŧŒæ­Ŗåœ¨é‡č¯•â€Ļ", @@ -587,6 +600,7 @@ "backup_controller_page_turn_on": "åŧ€å¯å‰å°å¤‡äģŊ", "backup_controller_page_uploading_file_info": "æ­Ŗåœ¨ä¸Šäŧ ä¸­įš„æ–‡äģļäŋĄæ¯", "backup_err_only_album": "不čƒŊį§ģé™¤å”¯ä¸€įš„ä¸€ä¸Ēį›¸å†Œ", + "backup_error_sync_failed": "同æ­Ĩå¤ąč´Ĩã€‚æ— æŗ•å¤„į†å¤‡äģŊ。", "backup_info_card_assets": "饚", "backup_manual_cancelled": "åˇ˛å–æļˆ", "backup_manual_in_progress": "上äŧ æ­Ŗåœ¨čŋ›čĄŒä¸­īŧŒč¯ˇį¨åŽå†č¯•", @@ -597,8 +611,6 @@ "backup_setting_subtitle": "įŽĄį†åŽå°å’Œå‰å°ä¸Šäŧ čŽžįŊŽ", "backup_settings_subtitle": "įŽĄį†ä¸Šäŧ čŽžįŊŽ", "backward": "后退", - "beta_sync": "æĩ‹č¯•į‰ˆåŒæ­ĨįŠļ态", - "beta_sync_subtitle": "įŽĄį†æ–°įš„åŒæ­ĨįŗģįģŸ", "biometric_auth_enabled": "į”Ÿį‰Šč¯†åˆĢčēĢäģŊéĒŒč¯åˇ˛å¯į”¨", "biometric_locked_out": "您čĸĢé”åŽšåœ¨į”Ÿį‰Šč¯†åˆĢčēĢäģŊéĒŒč¯äš‹å¤–", "biometric_no_options": "æ˛Ąæœ‰å¯į”¨įš„į”Ÿį‰Šč¯†åˆĢ选项", @@ -656,6 +668,8 @@ "change_pin_code": "äŋŽæ”šPIN᠁", "change_your_password": "äŋŽæ”šæ‚¨įš„å¯†į ", "changed_visibility_successfully": "æ›´æ”šå¯č§æ€§æˆåŠŸ", + "charging": "充į”ĩ", + "charging_requirement_mobile_backup": "后台备äģŊ需čĻčŽžå¤‡å¤„äēŽå……į”ĩįŠļ态", "check_corrupt_asset_backup": "æŖ€æŸĨ备äģŊ是åĻ损坏", "check_corrupt_asset_backup_button": "æ‰§čĄŒæŖ€æŸĨ", "check_corrupt_asset_backup_description": "äģ…在čŋžæŽĨ到 Wi-Fi åšļåŽŒæˆæ‰€æœ‰éĄšį›Žå¤‡äģŊåŽæ‰§čĄŒæ­¤æŖ€æŸĨ。č¯Ĩčŋ‡į¨‹å¯čƒŊ需čĻå‡ åˆ†é’Ÿã€‚", @@ -742,6 +756,7 @@ "create_user": "创åģēį”¨æˆˇ", "created": "åˇ˛åˆ›åģē", "created_at": "åˇ˛åˆ›åģē", + "creating_linked_albums": "æ­Ŗåœ¨åˆ›åģēį›¸å†Œé“žæŽĨâ€Ļ", "crop": "誁å‰Ē", "curated_object_page_title": "äē‹į‰Š", "current_device": "åŊ“å‰čŽžå¤‡", @@ -891,7 +906,9 @@ "error": "错蝝", "error_change_sort_album": "æ›´æ”šį›¸å†ŒæŽ’åēå¤ąč´Ĩ", "error_delete_face": "删除äēēč„¸å¤ąč´Ĩ", + "error_getting_places": "čŽˇå–äŊįŊŽæ—ļå‡ē错", "error_loading_image": "加čŊŊå›žį‰‡æ—ļå‡ē错", + "error_loading_partners": "加čŊŊ同äŧ´æ—ļå‡ē错īŧš{error}", "error_saving_image": "错蝝īŧš{error}", "error_tag_face_bounding_box": "æ ‡čŽ°äēē脸å‡ē错 - æ— æŗ•čŽˇå–äēēč„¸æĄ†åæ ‡", "error_title": "错蝝 - åĨŊ像å‡ēäē†é—Žéĸ˜", @@ -1056,6 +1073,7 @@ "favorites_page_no_favorites": "æœĒ扞到æ”ļč—éĄšį›Ž", "feature_photo_updated": "äēēį‰Šå¤´åƒåˇ˛æ›´æ–°", "features": "功čƒŊ", + "features_in_development": "åŧ€å‘ä¸­įš„åŠŸčƒŊ", "features_setting_description": "įŽĄį† App 功čƒŊ", "file_name": "文äģļ名", "file_name_or_extension": "文äģļ名", @@ -1076,10 +1094,7 @@ "gcast_enabled": "Google Cast æŠ•åą", "gcast_enabled_description": "č¯Ĩ功čƒŊ需čρ加čŊŊæĨč‡Ē Google įš„å¤–éƒ¨čĩ„æēã€‚", "general": "é€šį”¨", - "geolocation_instruction_all_have_location": "æ­¤æ—ĨæœŸįš„æ‰€æœ‰čĩ„äē§éƒŊåˇ˛å…ˇæœ‰äŊįŊŽæ•°æŽã€‚å°č¯•æ˜žį¤ē所有čĩ„äē§æˆ–选拊å…ļäģ–æ—Ĩ期", "geolocation_instruction_location": "į‚šå‡ģå¸Ļ有GPSåæ ‡įš„čĩ„äē§äģĨäŊŋᔍå…ļäŊįŊŽīŧŒæˆ–į›´æŽĨäģŽåœ°å›žä¸Šé€‰æ‹ŠäŊįŊŽ", - "geolocation_instruction_no_date": "选拊一ä¸Ēæ—Ĩ期æĨįŽĄį†åŊ“å¤Šį…§į‰‡å’Œč§†éĸ‘įš„äŊįŊŽæ•°æŽ", - "geolocation_instruction_no_photos": "æ˛Ąæœ‰æ‰žåˆ°æ­¤æ—ĨæœŸįš„į…§į‰‡æˆ–č§†éĸ‘。选拊å…ļäģ–æ—Ĩ期昞į¤ē厃äģŦ", "get_help": "čŽˇå–å¸ŽåŠŠ", "get_wifiname_error": "æ— æŗ•čŽˇå– Wi-Fi åį§°ã€‚įĄŽäŋåˇ˛æŽˆäēˆåŋ…čĻįš„æƒé™īŧŒåšļ厞čŋžæŽĨ到 Wi-Fi įŊ‘įģœ", "getting_started": "å…Ĩ门", @@ -1223,6 +1238,7 @@ "local": "æœŦ地", "local_asset_cast_failed": "æ— æŗ•æŠ•æ”žæœĒ上äŧ č‡ŗæœåŠĄå™¨įš„éĄšį›Ž", "local_assets": "æœŦåœ°éĄšį›Ž", + "local_media_summary": "æœŦ地åĒ’äŊ“摘čρ", "local_network": "æœŦ地įŊ‘įģœ", "local_network_sheet_info": "åŊ“äŊŋį”¨æŒ‡åŽšįš„ Wi-Fi įŊ‘į윿—ļīŧŒåē”ᔍፋåēå°†é€ščŋ‡æ­¤ URL čŽŋé—ŽæœåŠĄå™¨", "location_permission": "厚äŊæƒé™", @@ -1234,6 +1250,7 @@ "location_picker_longitude_hint": "č¯ˇåœ¨æ­¤å¤„čž“å…ĨįģåēĻ", "lock": "锁厚", "locked_folder": "锁厚文äģļ多", + "log_detail_title": "æ—Ĩåŋ—č¯Ļįģ†äŋĄæ¯", "log_out": "æŗ¨é”€", "log_out_all_devices": "æŗ¨é”€æ‰€æœ‰čŽžå¤‡", "logged_in_as": "äģĨ {user} čēĢäģŊį™ģåŊ•", @@ -1264,6 +1281,7 @@ "login_password_changed_success": "å¯†į æ›´æ–°æˆåŠŸ", "logout_all_device_confirmation": "įĄŽåŽščρäģŽæ‰€æœ‰čŽžå¤‡æŗ¨é”€īŧŸ", "logout_this_device_confirmation": "įĄŽåŽščρäģŽæœŦčŽžå¤‡æŗ¨é”€īŧŸ", + "logs": "æ—Ĩåŋ—", "longitude": "įģåēĻ", "look": "æ ˇåŧ", "loop_videos": "åžĒįŽ¯č§†éĸ‘", @@ -1298,7 +1316,7 @@ "map_settings_date_range_option_years": "{years} 嚴前", "map_settings_dialog_title": "åœ°å›žčŽžįŊŽ", "map_settings_include_show_archived": "包æ‹Ŧ厞åŊ’æĄŖéĄšį›Ž", - "map_settings_include_show_partners": "包åĢäŧ™äŧ´", + "map_settings_include_show_partners": "包åĢ同äŧ´", "map_settings_only_show_favorites": "äģ…æ˜žį¤ēæ”ļč—įš„éĄšį›Ž", "map_settings_theme_settings": "地回ä¸ģéĸ˜", "map_zoom_to_see_photos": "įŧŠå°äģĨæŸĨįœ‹éĄšį›Ž", @@ -1306,6 +1324,7 @@ "mark_as_read": "æ ‡čŽ°ä¸ē厞č¯ģ", "marked_all_as_read": "åˇ˛å…¨éƒ¨æ ‡čŽ°ä¸ē厞č¯ģ", "matches": "匚配", + "matching_assets": "匚配čĩ„äē§", "media_type": "åĒ’äŊ“įąģ型", "memories": "回åŋ†", "memories_all_caught_up": "åˇ˛å…¨éƒ¨įœ‹åŽŒ", @@ -1346,6 +1365,7 @@ "name_or_nickname": "åį§°æˆ–æ˜ĩį§°", "network_requirement_photos_upload": "äŊŋį”¨čœ‚įĒæ•°æŽå¤‡äģŊᅧቇ", "network_requirement_videos_upload": "äŊŋį”¨čœ‚įĒæ•°æŽå¤‡äģŊ视éĸ‘", + "network_requirements": "įŊ‘įģœčĻæą‚", "network_requirements_updated": "įŊ‘įģœčĻæą‚å‘į”Ÿå˜åŒ–īŧŒæ­Ŗåœ¨é‡įŊŽå¤‡äģŊ队列", "networking_settings": "įŊ‘įģœ", "networking_subtitle": "įŽĄį†æœåŠĄå™¨æŽĨåŖčŽžįŊŽ", @@ -1356,6 +1376,7 @@ "new_person": "新äēēį‰Š", "new_pin_code": "æ–°įš„PIN᠁", "new_pin_code_subtitle": "čŋ™æ˜¯æ‚¨įŦŦ一æŦĄčŽŋ闎此锁厚文äģļ多。创åģē一ä¸ĒPIN᠁äģĨ厉全čŽŋé—Žæ­¤éĄĩéĸ", + "new_timeline": "切æĸåˆ°æ–°į‰ˆæ—ļ间įēŋ", "new_user_created": "åˇ˛åˆ›åģēæ–°į”¨æˆˇ", "new_version_available": "æœ‰æ–°į‰ˆæœŦ发布å•Ļ", "newest_first": "最新äŧ˜å…ˆ", @@ -1369,20 +1390,25 @@ "no_assets_message": "į‚šå‡ģ上äŧ æ‚¨įš„įŦŦ一åŧ į…§į‰‡", "no_assets_to_show": "æ˛Ąæœ‰čĻæ˜žį¤ēįš„čĩ„äē§", "no_cast_devices_found": "æœĒæ‰žåˆ°æŠ•æ”žčŽžå¤‡", + "no_checksum_local": "æ˛Ąæœ‰å¯į”¨įš„æ ĄéĒŒå’Œ-æ— æŗ•čŽˇå–æœŦ地čĩ„äē§", + "no_checksum_remote": "æ˛Ąæœ‰å¯į”¨įš„æ ĄéĒŒå’Œ-æ— æŗ•čŽˇå–čŋœį¨‹čĩ„äē§", "no_duplicates_found": "æœĒå‘įŽ°é‡å¤éĄšã€‚", "no_exif_info_available": "æ˛Ąæœ‰å¯į”¨įš„ EXIF äŋĄæ¯", "no_explore_results_message": "上äŧ æ›´å¤šį…§į‰‡æĨæŽĸį´ĸ。", "no_favorites_message": "æˇģ加到æ”ļč—å¤šīŧŒåŋĢ速æŸĨ扞最äŊŗå›žį‰‡å’Œč§†éĸ‘", "no_libraries_message": "创åģē外部回å瓿ĨæŸĨįœ‹æ‚¨įš„į…§į‰‡å’Œč§†éĸ‘", + "no_local_assets_found": "æœĒæ‰žåˆ°å…ˇæœ‰æ­¤æ ĄéĒŒå’Œįš„æœŦ地čĩ„äē§", "no_locked_photos_message": "锁厚文äģļå¤šä¸­įš„į…§į‰‡å’Œč§†éĸ‘å°†čĸĢ隐藏īŧŒä¸äŧšåœ¨æ‚¨æĩč§ˆã€æœį´ĸ回å瓿—ļå‡ēįŽ°ã€‚", "no_name": "æœĒå‘Ŋ名", "no_notifications": "æ˛Ąæœ‰é€šįŸĨ", "no_people_found": "æœĒæ‰žåˆ°åŒšé…įš„äēēį‰Š", "no_places": "无äŊįŊŽ", + "no_remote_assets_found": "æœĒæ‰žåˆ°å…ˇæœ‰æ­¤æ ĄéĒŒå’Œįš„čŋœį¨‹čĩ„äē§", "no_results": "无į쓿žœ", "no_results_description": "å°č¯•äŊŋį”¨åŒäš‰č¯æˆ–æ›´é€šį”¨įš„å…ŗé”Žč¯", "no_shared_albums_message": "创åģēį›¸å†ŒäģĨå…ąäēĢį…§į‰‡å’Œč§†éĸ‘", "no_uploads_in_progress": "æ˛Ąæœ‰æ­Ŗåœ¨čŋ›čĄŒįš„上äŧ ", + "not_available": "ä¸é€‚į”¨", "not_in_any_album": "不在äģģäŊ•į›¸å†Œä¸­", "not_selected": "æœĒ选拊", "note_apply_storage_label_to_previously_uploaded assets": "提į¤ēīŧščĻå°†å­˜å‚¨æ ‡į­žåē”ᔍäēŽäš‹å‰ä¸Šäŧ įš„éĄšį›ŽīŧŒéœ€čρčŋčĄŒ", @@ -1504,6 +1530,7 @@ "port": "įĢ¯åŖ", "preferences_settings_subtitle": "įŽĄį†åē”į”¨įš„ååĨŊ莞įŊŽ", "preferences_settings_title": "偏åĨŊ莞įŊŽ", + "preparing": "准备中", "preset": "éĸ„莞", "preview": "éĸ„č§ˆ", "previous": "上一ä¸Ē", @@ -1520,7 +1547,7 @@ "profile_drawer_client_out_of_date_minor": "åŽĸæˆˇįĢ¯æœ‰å°į‰ˆæœŦ升įē§īŧŒč¯ˇå°ŊåŋĢ升įē§č‡ŗæœ€æ–°į‰ˆã€‚", "profile_drawer_client_server_up_to_date": "åŽĸæˆˇįĢ¯å’ŒæœåŠĄį̝éƒŊæ˜¯æœ€æ–°įš„", "profile_drawer_github": "GitHub", - "profile_drawer_readonly_mode": "åĒč¯ģæ¨Ąåŧåˇ˛å¯į”¨ã€‚双å‡ģį”¨æˆˇå¤´åƒå›žæ ‡é€€å‡ē。", + "profile_drawer_readonly_mode": "åĒč¯ģæ¨Ąåŧåˇ˛å¯į”¨ã€‚é•ŋæŒ‰į”¨æˆˇå¤´åƒå›žæ ‡é€€å‡ē。", "profile_drawer_server_out_of_date_major": "æœåŠĄįĢ¯æœ‰å¤§į‰ˆæœŦ升įē§īŧŒč¯ˇå°ŊåŋĢ升įē§č‡ŗæœ€æ–°į‰ˆã€‚", "profile_drawer_server_out_of_date_minor": "æœåŠĄįĢ¯æœ‰å°į‰ˆæœŦ升įē§īŧŒč¯ˇå°ŊåŋĢ升įē§č‡ŗæœ€æ–°į‰ˆã€‚", "profile_image_of_user": "{user}įš„ä¸Ēäēēčĩ„æ–™å›žį‰‡", @@ -1569,6 +1596,7 @@ "read_changelog": "阅č¯ģ更新æ—Ĩåŋ—", "readonly_mode_disabled": "åĒč¯ģæ¨Ąåŧåˇ˛įρᔍ", "readonly_mode_enabled": "åĒč¯ģæ¨Ąåŧåˇ˛å¯į”¨", + "ready_for_upload": "准备上äŧ ", "reassign": "重新指洞", "reassigned_assets_to_existing_person": "重新指洞{count, plural, one {#ä¸ĒéĄšį›Ž} other {#ä¸ĒéĄšį›Ž}}到{name, select, null {åˇ˛å­˜åœ¨įš„äēēį‰Š} other {{name}}}", "reassigned_assets_to_new_person": "重新指洞{count, plural, one {#ä¸ĒéĄšį›Ž} other {#ä¸ĒéĄšį›Ž}}åˆ°æ–°įš„äēēį‰Š", @@ -1593,6 +1621,7 @@ "regenerating_thumbnails": "æ­Ŗåœ¨é‡æ–°į”ŸæˆįŧŠį•Ĩ回", "remote": "čŋœį¨‹", "remote_assets": "čŋœį¨‹éĄšį›Ž", + "remote_media_summary": "čŋœį¨‹åĒ’äŊ“摘čρ", "remove": "į§ģ除", "remove_assets_album_confirmation": "įĄŽåŽščρäģŽå›žåē“中į§ģ除{count, plural, one {#ä¸ĒéĄšį›Ž} other {#ä¸ĒéĄšį›Ž}}īŧŸ", "remove_assets_shared_link_confirmation": "įĄŽåŽščρäģŽå…ąäēĢ链æŽĨ中į§ģ除{count, plural, one {#ä¸ĒéĄšį›Ž} other {#ä¸ĒéĄšį›Ž}}īŧŸ", @@ -1645,6 +1674,7 @@ "restore_user": "æĸå¤į”¨æˆˇ", "restored_asset": "厞æĸå¤éĄšį›Ž", "resume": "įģ§įģ­", + "resume_paused_jobs": "įģ§įģ­ {count, plural, one {# åˇ˛æš‚åœįš„äģģåŠĄ} other {# åˇ˛æš‚åœįš„äģģåŠĄ}}", "retry_upload": "重新上äŧ ", "review_duplicates": "æŖ€æŸĨé‡å¤éĄš", "review_large_files": "æŸĨįœ‹å¤§æ–‡äģļ", @@ -1849,10 +1879,8 @@ "shift_to_permanent_delete": "按äŊ ⇧ Shift é”Žæ°¸äš…åˆ é™¤éĄšį›Ž", "show_album_options": "昞į¤ēį›¸å†Œé€‰éĄš", "show_albums": "昞į¤ēį›¸å†Œ", - "show_all_assets": "昞į¤ē所有čĩ„äē§", "show_all_people": "昞į¤ē所有äēēį‰Š", "show_and_hide_people": "昞į¤ēå’Œéšč—äēēį‰Š", - "show_assets_without_location": "昞į¤ē不å¸ĻGPS厚äŊįš„čĩ„äē§", "show_file_location": "昞į¤ē文äģļäŊįŊŽ", "show_gallery": "昞į¤ē回åē“", "show_hidden_people": "昞į¤ē隐藏äēēį‰Š", @@ -1869,10 +1897,11 @@ "show_slideshow_transition": "昞į¤ēåšģၝቇčŋ‡æ¸Ąæ•ˆæžœ", "show_supporter_badge": "æ”¯æŒč€…åžŊįĢ ", "show_supporter_badge_description": "åą•į¤ēæ”¯æŒč€…åžŊįĢ ", + "show_text_search_menu": "昞į¤ē文æœŦ搜į´ĸčœå•", "shuffle": "随æœē", "sidebar": "äž§čžšæ ", "sidebar_display_description": "åœ¨äž§čžšæ ä¸­æ˜žį¤ē链æŽĨ", - "sign_out": "æŗ¨é”€", + "sign_out": "退å‡ēį™ģåŊ•", "sign_up": "æŗ¨å†Œ", "size": "大小", "skip_to_content": "莺čŊŦ到内厚", @@ -1899,6 +1928,7 @@ "stacktrace": "å †æ ˆčˇŸč¸Ē", "start": "åŧ€å§‹", "start_date": "åŧ€å§‹æ—Ĩ期", + "start_date_before_end_date": "åŧ€å§‹æ—Ĩ期åŋ…éĄģ在į쓿Ÿæ—Ĩ期䚋前", "state": "ᜁäģŊ", "status": "įŠļ态", "stop_casting": "停æ­ĸ投攞", @@ -1923,6 +1953,8 @@ "sync_albums_manual_subtitle": "将所有上äŧ įš„视éĸ‘å’Œį…§į‰‡åŒæ­Ĩåˆ°é€‰åŽšįš„å¤‡äģŊį›¸å†Œ", "sync_local": "同æ­ĨæœŦ地", "sync_remote": "同æ­Ĩčŋœį¨‹", + "sync_status": "同æ­ĨįŠļ态", + "sync_status_subtitle": "æŸĨįœ‹å’ŒįŽĄį†åŒæ­ĨįŗģįģŸ", "sync_upload_album_setting_subtitle": "创åģēį…§į‰‡å’Œč§†éĸ‘åšļ上äŧ åˆ° Immich ä¸Šįš„é€‰åŽšį›¸å†Œä¸­", "tag": "æ ‡į­ž", "tag_assets": "æ ‡čŽ°éĄšį›Ž", @@ -1933,7 +1965,7 @@ "tag_updated": "åˇ˛æ›´æ–°æ ‡į­žīŧš{tag}", "tagged_assets": "{count, plural, one {# ä¸ĒéĄšį›Ž} other {# ä¸ĒéĄšį›Ž}}čĸĢåŠ ä¸Šæ ‡į­ž", "tags": "æ ‡į­ž", - "tap_to_run_job": "į‚šå‡ģčŋčĄŒäŊœä¸š", + "tap_to_run_job": "į‚šå‡ģčŋčĄŒäģģåŠĄ", "template": "æ¨Ąį‰ˆ", "theme": "ä¸ģéĸ˜", "theme_selection": "ä¸ģéĸ˜é€‰éĄš", @@ -1982,6 +2014,7 @@ "trash_page_select_assets_btn": "é€‰æ‹ŠéĄšį›Ž", "trash_page_title": "回æ”ļįĢ™ ({count})", "trashed_items_will_be_permanently_deleted_after": "回æ”ļįĢ™ä¸­įš„éĄšį›Žå°†åœ¨{days, plural, one {#夊} other {#夊}}后čĸĢæ°¸äš…删除。", + "troubleshoot": "故障排除", "type": "įąģ型", "unable_to_change_pin_code": "æ— æŗ•äŋŽæ”šPIN᠁", "unable_to_setup_pin_code": "æ— æŗ•čŽžįŊŽPIN᠁", @@ -2037,7 +2070,6 @@ "use_biometric": "äŊŋį”¨į”Ÿį‰Šč¯†åˆĢ", "use_current_connection": "äŊŋᔍåŊ“前čŋžæŽĨ", "use_custom_date_range": "č‡Ē厚䚉æ—ĨæœŸčŒƒå›´", - "use_this_location": "单å‡ģäģĨäŊŋį”¨æ­¤äŊįŊŽ", "user": "į”¨æˆˇ", "user_has_been_deleted": "æ­¤į”¨æˆˇåˇ˛čĸĢ删除。", "user_id": "į”¨æˆˇ ID", @@ -2099,5 +2131,6 @@ "yes": "是", "you_dont_have_any_shared_links": "æ‚¨æ˛Ąæœ‰äģģäŊ•å…ąäēĢ链æŽĨ", "your_wifi_name": "æ‚¨įš„ Wi-Fi åį§°", - "zoom_image": "įŧŠæ”žå›žåƒ" + "zoom_image": "įŧŠæ”žå›žåƒ", + "zoom_to_bounds": "įŧŠæ”žåˆ°čžšį•Œ" } diff --git a/machine-learning/Dockerfile b/machine-learning/Dockerfile index d1d7f1037e..f913fd3c78 100644 --- a/machine-learning/Dockerfile +++ b/machine-learning/Dockerfile @@ -1,6 +1,6 @@ ARG DEVICE=cpu -FROM python:3.11-bookworm@sha256:c642d5dfaf9115a12086785f23008558ae2e13bcd0c4794536340bcb777a4381 AS builder-cpu +FROM python:3.11-bookworm@sha256:fc1f2e357c307c4044133952b203e66a47e7726821a664f603a180a0c5823844 AS builder-cpu FROM builder-cpu AS builder-openvino @@ -22,7 +22,7 @@ FROM builder-cpu AS builder-rknn # Warning: 25GiB+ disk space required to pull this image # TODO: find a way to reduce the image size -FROM rocm/dev-ubuntu-22.04:6.3.4-complete@sha256:1f7e92ca7e3a3785680473329ed1091fc99db3e90fcb3a1688f2933e870ed76b AS builder-rocm +FROM rocm/dev-ubuntu-22.04:6.4.3-complete@sha256:1f7e92ca7e3a3785680473329ed1091fc99db3e90fcb3a1688f2933e870ed76b AS builder-rocm # renovate: datasource=github-releases depName=Microsoft/onnxruntime ARG ONNXRUNTIME_VERSION="v1.20.1" @@ -68,11 +68,12 @@ RUN if [ "$DEVICE" = "rocm" ]; then \ uv pip install /opt/onnxruntime_rocm-*.whl; \ fi -FROM python:3.11-slim-bookworm@sha256:838ff46ae6c481e85e369706fa3dea5166953824124735639f3c9f52af85f319 AS prod-cpu +FROM python:3.11-slim-bookworm@sha256:873f91540d53b36327ed4fb018c9669107a4e2a676719720edb4209c4b15d029 AS prod-cpu -ENV LD_PRELOAD=/usr/lib/libmimalloc.so.2 +ENV LD_PRELOAD=/usr/lib/libmimalloc.so.2 \ + MACHINE_LEARNING_MODEL_ARENA=false -FROM python:3.11-slim-bookworm@sha256:838ff46ae6c481e85e369706fa3dea5166953824124735639f3c9f52af85f319 AS prod-openvino +FROM python:3.11-slim-bookworm@sha256:873f91540d53b36327ed4fb018c9669107a4e2a676719720edb4209c4b15d029 AS prod-openvino RUN apt-get update && \ apt-get install --no-install-recommends -yqq ocl-icd-libopencl1 wget && \ @@ -88,7 +89,8 @@ RUN apt-get update && \ FROM nvidia/cuda:12.2.2-runtime-ubuntu22.04@sha256:94c1577b2cd9dd6c0312dc04dff9cb2fdce2b268018abc3d7c2dbcacf1155000 AS prod-cuda -ENV LD_PRELOAD=/usr/lib/libmimalloc.so.2 +ENV LD_PRELOAD=/usr/lib/libmimalloc.so.2 \ + MACHINE_LEARNING_MODEL_ARENA=false RUN apt-get update && \ apt-get install --no-install-recommends -yqq libcudnn9-cuda-12 && \ @@ -99,12 +101,13 @@ COPY --from=builder-cuda /usr/local/bin/python3 /usr/local/bin/python3 COPY --from=builder-cuda /usr/local/lib/python3.11 /usr/local/lib/python3.11 COPY --from=builder-cuda /usr/local/lib/libpython3.11.so /usr/local/lib/libpython3.11.so -FROM rocm/dev-ubuntu-22.04:6.3.4-complete@sha256:1f7e92ca7e3a3785680473329ed1091fc99db3e90fcb3a1688f2933e870ed76b AS prod-rocm +FROM rocm/dev-ubuntu-22.04:6.4.3-complete@sha256:1f7e92ca7e3a3785680473329ed1091fc99db3e90fcb3a1688f2933e870ed76b AS prod-rocm FROM prod-cpu AS prod-armnn ENV LD_LIBRARY_PATH=/opt/armnn \ - LD_PRELOAD=/usr/lib/libmimalloc.so.2 + LD_PRELOAD=/usr/lib/libmimalloc.so.2 \ + MACHINE_LEARNING_MODEL_ARENA=false RUN apt-get update && apt-get install -y --no-install-recommends ocl-icd-libopencl1 mesa-opencl-icd libgomp1 && \ rm -rf /var/lib/apt/lists/* && \ @@ -127,7 +130,8 @@ FROM prod-cpu AS prod-rknn # renovate: datasource=github-tags depName=airockchip/rknn-toolkit2 ARG RKNN_TOOLKIT_VERSION="v2.3.0" -ENV LD_PRELOAD=/usr/lib/libmimalloc.so.2 +ENV LD_PRELOAD=/usr/lib/libmimalloc.so.2 \ + MACHINE_LEARNING_MODEL_ARENA=false ADD --checksum=sha256:73993ed4b440460825f21611731564503cc1d5a0c123746477da6cd574f34885 "https://github.com/airockchip/rknn-toolkit2/raw/refs/tags/${RKNN_TOOLKIT_VERSION}/rknpu2/runtime/Linux/librknn_api/aarch64/librknnrt.so" /usr/lib/ diff --git a/machine-learning/immich_ml/__main__.py b/machine-learning/immich_ml/__main__.py index d15b0fb321..8d575a58d5 100644 --- a/machine-learning/immich_ml/__main__.py +++ b/machine-learning/immich_ml/__main__.py @@ -1,6 +1,7 @@ import os import signal import subprocess +from ipaddress import ip_address from pathlib import Path from .config import log, non_prefixed_settings, settings @@ -12,6 +13,19 @@ else: module_dir = Path(__file__).parent + +def is_ipv6(host: str) -> bool: + try: + return ip_address(host).version == 6 + except ValueError: + return False + + +bind_host = non_prefixed_settings.immich_host +if is_ipv6(bind_host): + bind_host = f"[{bind_host}]" +bind_address = f"{bind_host}:{non_prefixed_settings.immich_port}" + try: with subprocess.Popen( [ @@ -24,7 +38,7 @@ try: "-c", module_dir / "gunicorn_conf.py", "-b", - f"{non_prefixed_settings.immich_host}:{non_prefixed_settings.immich_port}", + bind_address, "-w", str(settings.workers), "-t", diff --git a/machine-learning/immich_ml/config.py b/machine-learning/immich_ml/config.py index 939afbc98b..d9edd88a8c 100644 --- a/machine-learning/immich_ml/config.py +++ b/machine-learning/immich_ml/config.py @@ -61,6 +61,7 @@ class Settings(BaseSettings): request_threads: int = os.cpu_count() or 4 model_inter_op_threads: int = 0 model_intra_op_threads: int = 0 + model_arena: bool = True ann: bool = True ann_fp16_turbo: bool = False ann_tuning_level: int = 2 diff --git a/machine-learning/immich_ml/models/constants.py b/machine-learning/immich_ml/models/constants.py index 41b0990f71..b15b75b7d1 100644 --- a/machine-learning/immich_ml/models/constants.py +++ b/machine-learning/immich_ml/models/constants.py @@ -79,6 +79,7 @@ SUPPORTED_PROVIDERS = [ "CUDAExecutionProvider", "ROCMExecutionProvider", "OpenVINOExecutionProvider", + "CoreMLExecutionProvider", "CPUExecutionProvider", ] diff --git a/machine-learning/immich_ml/sessions/ort.py b/machine-learning/immich_ml/sessions/ort.py index e7d8635876..d18aae751a 100644 --- a/machine-learning/immich_ml/sessions/ort.py +++ b/machine-learning/immich_ml/sessions/ort.py @@ -96,6 +96,14 @@ class OrtSession: "precision": "FP32", "cache_dir": (self.model_path.parent / "openvino").as_posix(), } + case "CoreMLExecutionProvider": + options = { + "ModelFormat": "MLProgram", + "MLComputeUnits": "ALL", + "SpecializationStrategy": "FastPrediction", + "AllowLowPrecisionAccumulationOnGPU": "1", + "ModelCacheDirectory": (self.model_path.parent / "coreml").as_posix(), + } case _: options = {} provider_options.append(options) @@ -115,7 +123,7 @@ class OrtSession: @property def _sess_options_default(self) -> ort.SessionOptions: sess_options = ort.SessionOptions() - sess_options.enable_cpu_mem_arena = False + sess_options.enable_cpu_mem_arena = settings.model_arena # avoid thread contention between models if settings.model_inter_op_threads > 0: diff --git a/machine-learning/pyproject.toml b/machine-learning/pyproject.toml index f0f08b20b6..683d8578a3 100644 --- a/machine-learning/pyproject.toml +++ b/machine-learning/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "immich-ml" -version = "1.129.0" +version = "2.1.0" description = "" authors = [{ name = "Hau Tran", email = "alex.tran1502@gmail.com" }] requires-python = ">=3.10,<4.0" diff --git a/machine-learning/scripts/healthcheck.py b/machine-learning/scripts/healthcheck.py index 82c6cad790..38c0a522f1 100644 --- a/machine-learning/scripts/healthcheck.py +++ b/machine-learning/scripts/healthcheck.py @@ -1,12 +1,22 @@ import os import sys +from ipaddress import ip_address import requests port = os.getenv("IMMICH_PORT", 3003) host = os.getenv("IMMICH_HOST", "0.0.0.0") + +def is_ipv6(host: str) -> bool: + try: + return ip_address(host).version == 6 + except ValueError: + return False + + host = "localhost" if host == "0.0.0.0" else host +host = f"[{host}]" if is_ipv6(host) else host try: response = requests.get(f"http://{host}:{port}/ping", timeout=2) diff --git a/machine-learning/test_main.py b/machine-learning/test_main.py index eeafd01062..582a05a950 100644 --- a/machine-learning/test_main.py +++ b/machine-learning/test_main.py @@ -180,6 +180,7 @@ class TestOrtSession: CUDA_EP_OUT_OF_ORDER = ["CPUExecutionProvider", "CUDAExecutionProvider"] TRT_EP = ["TensorrtExecutionProvider", "CUDAExecutionProvider", "CPUExecutionProvider"] ROCM_EP = ["ROCMExecutionProvider", "CPUExecutionProvider"] + COREML_EP = ["CoreMLExecutionProvider", "CPUExecutionProvider"] @pytest.mark.providers(CPU_EP) def test_sets_cpu_provider(self, providers: list[str]) -> None: @@ -225,6 +226,12 @@ class TestOrtSession: assert session.providers == self.ROCM_EP + @pytest.mark.providers(COREML_EP) + def test_uses_coreml(self, providers: list[str]) -> None: + session = OrtSession("ViT-B-32__openai") + + assert session.providers == self.COREML_EP + def test_sets_provider_kwarg(self) -> None: providers = ["CUDAExecutionProvider"] session = OrtSession("ViT-B-32__openai", providers=providers) @@ -284,7 +291,6 @@ class TestOrtSession: assert session.sess_options.execution_mode == ort.ExecutionMode.ORT_SEQUENTIAL assert session.sess_options.inter_op_num_threads == 1 assert session.sess_options.intra_op_num_threads == 2 - assert session.sess_options.enable_cpu_mem_arena is False def test_sets_default_sess_options_does_not_set_threads_if_non_cpu_and_default_threads(self) -> None: session = OrtSession("ViT-B-32__openai", providers=["CUDAExecutionProvider", "CPUExecutionProvider"]) @@ -302,6 +308,26 @@ class TestOrtSession: assert session.sess_options.inter_op_num_threads == 2 assert session.sess_options.intra_op_num_threads == 4 + def test_uses_arena_if_enabled(self, mocker: MockerFixture) -> None: + mock_settings = mocker.patch("immich_ml.sessions.ort.settings", autospec=True) + mock_settings.model_inter_op_threads = 0 + mock_settings.model_intra_op_threads = 0 + mock_settings.model_arena = True + + session = OrtSession("ViT-B-32__openai", providers=["CPUExecutionProvider"]) + + assert session.sess_options.enable_cpu_mem_arena + + def test_does_not_use_arena_if_disabled(self, mocker: MockerFixture) -> None: + mock_settings = mocker.patch("immich_ml.sessions.ort.settings", autospec=True) + mock_settings.model_inter_op_threads = 0 + mock_settings.model_intra_op_threads = 0 + mock_settings.model_arena = False + + session = OrtSession("ViT-B-32__openai", providers=["CPUExecutionProvider"]) + + assert not session.sess_options.enable_cpu_mem_arena + def test_sets_sess_options_kwarg(self) -> None: sess_options = ort.SessionOptions() session = OrtSession( diff --git a/machine-learning/uv.lock b/machine-learning/uv.lock index fa54a13e8c..c30120a40b 100644 --- a/machine-learning/uv.lock +++ b/machine-learning/uv.lock @@ -507,61 +507,87 @@ wheels = [ [[package]] name = "coverage" -version = "7.6.4" +version = "7.10.6" 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, upload-time = "2024-10-20T22:57:39.682Z" } +sdist = { url = "https://files.pythonhosted.org/packages/14/70/025b179c993f019105b79575ac6edb5e084fb0f0e63f15cdebef4e454fb5/coverage-7.10.6.tar.gz", hash = "sha256:f644a3ae5933a552a29dbb9aa2f90c677a875f80ebea028e5a52a4f429044b90", size = 823736, upload-time = "2025-08-29T15:35:16.668Z" } 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, 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" }, + { url = "https://files.pythonhosted.org/packages/a8/1d/2e64b43d978b5bd184e0756a41415597dfef30fcbd90b747474bd749d45f/coverage-7.10.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:70e7bfbd57126b5554aa482691145f798d7df77489a177a6bef80de78860a356", size = 217025, upload-time = "2025-08-29T15:32:57.169Z" }, + { url = "https://files.pythonhosted.org/packages/23/62/b1e0f513417c02cc10ef735c3ee5186df55f190f70498b3702d516aad06f/coverage-7.10.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e41be6f0f19da64af13403e52f2dec38bbc2937af54df8ecef10850ff8d35301", size = 217419, upload-time = "2025-08-29T15:32:59.908Z" }, + { url = "https://files.pythonhosted.org/packages/e7/16/b800640b7a43e7c538429e4d7223e0a94fd72453a1a048f70bf766f12e96/coverage-7.10.6-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c61fc91ab80b23f5fddbee342d19662f3d3328173229caded831aa0bd7595460", size = 244180, upload-time = "2025-08-29T15:33:01.608Z" }, + { url = "https://files.pythonhosted.org/packages/fb/6f/5e03631c3305cad187eaf76af0b559fff88af9a0b0c180d006fb02413d7a/coverage-7.10.6-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:10356fdd33a7cc06e8051413140bbdc6f972137508a3572e3f59f805cd2832fd", size = 245992, upload-time = "2025-08-29T15:33:03.239Z" }, + { url = "https://files.pythonhosted.org/packages/eb/a1/f30ea0fb400b080730125b490771ec62b3375789f90af0bb68bfb8a921d7/coverage-7.10.6-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:80b1695cf7c5ebe7b44bf2521221b9bb8cdf69b1f24231149a7e3eb1ae5fa2fb", size = 247851, upload-time = "2025-08-29T15:33:04.603Z" }, + { url = "https://files.pythonhosted.org/packages/02/8e/cfa8fee8e8ef9a6bb76c7bef039f3302f44e615d2194161a21d3d83ac2e9/coverage-7.10.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2e4c33e6378b9d52d3454bd08847a8651f4ed23ddbb4a0520227bd346382bbc6", size = 245891, upload-time = "2025-08-29T15:33:06.176Z" }, + { url = "https://files.pythonhosted.org/packages/93/a9/51be09b75c55c4f6c16d8d73a6a1d46ad764acca0eab48fa2ffaef5958fe/coverage-7.10.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c8a3ec16e34ef980a46f60dc6ad86ec60f763c3f2fa0db6d261e6e754f72e945", size = 243909, upload-time = "2025-08-29T15:33:07.74Z" }, + { url = "https://files.pythonhosted.org/packages/e9/a6/ba188b376529ce36483b2d585ca7bdac64aacbe5aa10da5978029a9c94db/coverage-7.10.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7d79dabc0a56f5af990cc6da9ad1e40766e82773c075f09cc571e2076fef882e", size = 244786, upload-time = "2025-08-29T15:33:08.965Z" }, + { url = "https://files.pythonhosted.org/packages/d0/4c/37ed872374a21813e0d3215256180c9a382c3f5ced6f2e5da0102fc2fd3e/coverage-7.10.6-cp310-cp310-win32.whl", hash = "sha256:86b9b59f2b16e981906e9d6383eb6446d5b46c278460ae2c36487667717eccf1", size = 219521, upload-time = "2025-08-29T15:33:10.599Z" }, + { url = "https://files.pythonhosted.org/packages/8e/36/9311352fdc551dec5b973b61f4e453227ce482985a9368305880af4f85dd/coverage-7.10.6-cp310-cp310-win_amd64.whl", hash = "sha256:e132b9152749bd33534e5bd8565c7576f135f157b4029b975e15ee184325f528", size = 220417, upload-time = "2025-08-29T15:33:11.907Z" }, + { url = "https://files.pythonhosted.org/packages/d4/16/2bea27e212c4980753d6d563a0803c150edeaaddb0771a50d2afc410a261/coverage-7.10.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c706db3cabb7ceef779de68270150665e710b46d56372455cd741184f3868d8f", size = 217129, upload-time = "2025-08-29T15:33:13.575Z" }, + { url = "https://files.pythonhosted.org/packages/2a/51/e7159e068831ab37e31aac0969d47b8c5ee25b7d307b51e310ec34869315/coverage-7.10.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8e0c38dc289e0508ef68ec95834cb5d2e96fdbe792eaccaa1bccac3966bbadcc", size = 217532, upload-time = "2025-08-29T15:33:14.872Z" }, + { url = "https://files.pythonhosted.org/packages/e7/c0/246ccbea53d6099325d25cd208df94ea435cd55f0db38099dd721efc7a1f/coverage-7.10.6-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:752a3005a1ded28f2f3a6e8787e24f28d6abe176ca64677bcd8d53d6fe2ec08a", size = 247931, upload-time = "2025-08-29T15:33:16.142Z" }, + { url = "https://files.pythonhosted.org/packages/7d/fb/7435ef8ab9b2594a6e3f58505cc30e98ae8b33265d844007737946c59389/coverage-7.10.6-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:689920ecfd60f992cafca4f5477d55720466ad2c7fa29bb56ac8d44a1ac2b47a", size = 249864, upload-time = "2025-08-29T15:33:17.434Z" }, + { url = "https://files.pythonhosted.org/packages/51/f8/d9d64e8da7bcddb094d511154824038833c81e3a039020a9d6539bf303e9/coverage-7.10.6-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec98435796d2624d6905820a42f82149ee9fc4f2d45c2c5bc5a44481cc50db62", size = 251969, upload-time = "2025-08-29T15:33:18.822Z" }, + { url = "https://files.pythonhosted.org/packages/43/28/c43ba0ef19f446d6463c751315140d8f2a521e04c3e79e5c5fe211bfa430/coverage-7.10.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b37201ce4a458c7a758ecc4efa92fa8ed783c66e0fa3c42ae19fc454a0792153", size = 249659, upload-time = "2025-08-29T15:33:20.407Z" }, + { url = "https://files.pythonhosted.org/packages/79/3e/53635bd0b72beaacf265784508a0b386defc9ab7fad99ff95f79ce9db555/coverage-7.10.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:2904271c80898663c810a6b067920a61dd8d38341244a3605bd31ab55250dad5", size = 247714, upload-time = "2025-08-29T15:33:21.751Z" }, + { url = "https://files.pythonhosted.org/packages/4c/55/0964aa87126624e8c159e32b0bc4e84edef78c89a1a4b924d28dd8265625/coverage-7.10.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5aea98383463d6e1fa4e95416d8de66f2d0cb588774ee20ae1b28df826bcb619", size = 248351, upload-time = "2025-08-29T15:33:23.105Z" }, + { url = "https://files.pythonhosted.org/packages/eb/ab/6cfa9dc518c6c8e14a691c54e53a9433ba67336c760607e299bfcf520cb1/coverage-7.10.6-cp311-cp311-win32.whl", hash = "sha256:e3fb1fa01d3598002777dd259c0c2e6d9d5e10e7222976fc8e03992f972a2cba", size = 219562, upload-time = "2025-08-29T15:33:24.717Z" }, + { url = "https://files.pythonhosted.org/packages/5b/18/99b25346690cbc55922e7cfef06d755d4abee803ef335baff0014268eff4/coverage-7.10.6-cp311-cp311-win_amd64.whl", hash = "sha256:f35ed9d945bece26553d5b4c8630453169672bea0050a564456eb88bdffd927e", size = 220453, upload-time = "2025-08-29T15:33:26.482Z" }, + { url = "https://files.pythonhosted.org/packages/d8/ed/81d86648a07ccb124a5cf1f1a7788712b8d7216b593562683cd5c9b0d2c1/coverage-7.10.6-cp311-cp311-win_arm64.whl", hash = "sha256:99e1a305c7765631d74b98bf7dbf54eeea931f975e80f115437d23848ee8c27c", size = 219127, upload-time = "2025-08-29T15:33:27.777Z" }, + { url = "https://files.pythonhosted.org/packages/26/06/263f3305c97ad78aab066d116b52250dd316e74fcc20c197b61e07eb391a/coverage-7.10.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5b2dd6059938063a2c9fee1af729d4f2af28fd1a545e9b7652861f0d752ebcea", size = 217324, upload-time = "2025-08-29T15:33:29.06Z" }, + { url = "https://files.pythonhosted.org/packages/e9/60/1e1ded9a4fe80d843d7d53b3e395c1db3ff32d6c301e501f393b2e6c1c1f/coverage-7.10.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:388d80e56191bf846c485c14ae2bc8898aa3124d9d35903fef7d907780477634", size = 217560, upload-time = "2025-08-29T15:33:30.748Z" }, + { url = "https://files.pythonhosted.org/packages/b8/25/52136173c14e26dfed8b106ed725811bb53c30b896d04d28d74cb64318b3/coverage-7.10.6-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:90cb5b1a4670662719591aa92d0095bb41714970c0b065b02a2610172dbf0af6", size = 249053, upload-time = "2025-08-29T15:33:32.041Z" }, + { url = "https://files.pythonhosted.org/packages/cb/1d/ae25a7dc58fcce8b172d42ffe5313fc267afe61c97fa872b80ee72d9515a/coverage-7.10.6-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:961834e2f2b863a0e14260a9a273aff07ff7818ab6e66d2addf5628590c628f9", size = 251802, upload-time = "2025-08-29T15:33:33.625Z" }, + { url = "https://files.pythonhosted.org/packages/f5/7a/1f561d47743710fe996957ed7c124b421320f150f1d38523d8d9102d3e2a/coverage-7.10.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf9a19f5012dab774628491659646335b1928cfc931bf8d97b0d5918dd58033c", size = 252935, upload-time = "2025-08-29T15:33:34.909Z" }, + { url = "https://files.pythonhosted.org/packages/6c/ad/8b97cd5d28aecdfde792dcbf646bac141167a5cacae2cd775998b45fabb5/coverage-7.10.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:99c4283e2a0e147b9c9cc6bc9c96124de9419d6044837e9799763a0e29a7321a", size = 250855, upload-time = "2025-08-29T15:33:36.922Z" }, + { url = "https://files.pythonhosted.org/packages/33/6a/95c32b558d9a61858ff9d79580d3877df3eb5bc9eed0941b1f187c89e143/coverage-7.10.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:282b1b20f45df57cc508c1e033403f02283adfb67d4c9c35a90281d81e5c52c5", size = 248974, upload-time = "2025-08-29T15:33:38.175Z" }, + { url = "https://files.pythonhosted.org/packages/0d/9c/8ce95dee640a38e760d5b747c10913e7a06554704d60b41e73fdea6a1ffd/coverage-7.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cdbe264f11afd69841bd8c0d83ca10b5b32853263ee62e6ac6a0ab63895f972", size = 250409, upload-time = "2025-08-29T15:33:39.447Z" }, + { url = "https://files.pythonhosted.org/packages/04/12/7a55b0bdde78a98e2eb2356771fd2dcddb96579e8342bb52aa5bc52e96f0/coverage-7.10.6-cp312-cp312-win32.whl", hash = "sha256:a517feaf3a0a3eca1ee985d8373135cfdedfbba3882a5eab4362bda7c7cf518d", size = 219724, upload-time = "2025-08-29T15:33:41.172Z" }, + { url = "https://files.pythonhosted.org/packages/36/4a/32b185b8b8e327802c9efce3d3108d2fe2d9d31f153a0f7ecfd59c773705/coverage-7.10.6-cp312-cp312-win_amd64.whl", hash = "sha256:856986eadf41f52b214176d894a7de05331117f6035a28ac0016c0f63d887629", size = 220536, upload-time = "2025-08-29T15:33:42.524Z" }, + { url = "https://files.pythonhosted.org/packages/08/3a/d5d8dc703e4998038c3099eaf77adddb00536a3cec08c8dcd556a36a3eb4/coverage-7.10.6-cp312-cp312-win_arm64.whl", hash = "sha256:acf36b8268785aad739443fa2780c16260ee3fa09d12b3a70f772ef100939d80", size = 219171, upload-time = "2025-08-29T15:33:43.974Z" }, + { url = "https://files.pythonhosted.org/packages/bd/e7/917e5953ea29a28c1057729c1d5af9084ab6d9c66217523fd0e10f14d8f6/coverage-7.10.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ffea0575345e9ee0144dfe5701aa17f3ba546f8c3bb48db62ae101afb740e7d6", size = 217351, upload-time = "2025-08-29T15:33:45.438Z" }, + { url = "https://files.pythonhosted.org/packages/eb/86/2e161b93a4f11d0ea93f9bebb6a53f113d5d6e416d7561ca41bb0a29996b/coverage-7.10.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:95d91d7317cde40a1c249d6b7382750b7e6d86fad9d8eaf4fa3f8f44cf171e80", size = 217600, upload-time = "2025-08-29T15:33:47.269Z" }, + { url = "https://files.pythonhosted.org/packages/0e/66/d03348fdd8df262b3a7fb4ee5727e6e4936e39e2f3a842e803196946f200/coverage-7.10.6-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3e23dd5408fe71a356b41baa82892772a4cefcf758f2ca3383d2aa39e1b7a003", size = 248600, upload-time = "2025-08-29T15:33:48.953Z" }, + { url = "https://files.pythonhosted.org/packages/73/dd/508420fb47d09d904d962f123221bc249f64b5e56aa93d5f5f7603be475f/coverage-7.10.6-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0f3f56e4cb573755e96a16501a98bf211f100463d70275759e73f3cbc00d4f27", size = 251206, upload-time = "2025-08-29T15:33:50.697Z" }, + { url = "https://files.pythonhosted.org/packages/e9/1f/9020135734184f439da85c70ea78194c2730e56c2d18aee6e8ff1719d50d/coverage-7.10.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:db4a1d897bbbe7339946ffa2fe60c10cc81c43fab8b062d3fcb84188688174a4", size = 252478, upload-time = "2025-08-29T15:33:52.303Z" }, + { url = "https://files.pythonhosted.org/packages/a4/a4/3d228f3942bb5a2051fde28c136eea23a761177dc4ff4ef54533164ce255/coverage-7.10.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d8fd7879082953c156d5b13c74aa6cca37f6a6f4747b39538504c3f9c63d043d", size = 250637, upload-time = "2025-08-29T15:33:53.67Z" }, + { url = "https://files.pythonhosted.org/packages/36/e3/293dce8cdb9a83de971637afc59b7190faad60603b40e32635cbd15fbf61/coverage-7.10.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:28395ca3f71cd103b8c116333fa9db867f3a3e1ad6a084aa3725ae002b6583bc", size = 248529, upload-time = "2025-08-29T15:33:55.022Z" }, + { url = "https://files.pythonhosted.org/packages/90/26/64eecfa214e80dd1d101e420cab2901827de0e49631d666543d0e53cf597/coverage-7.10.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:61c950fc33d29c91b9e18540e1aed7d9f6787cc870a3e4032493bbbe641d12fc", size = 250143, upload-time = "2025-08-29T15:33:56.386Z" }, + { url = "https://files.pythonhosted.org/packages/3e/70/bd80588338f65ea5b0d97e424b820fb4068b9cfb9597fbd91963086e004b/coverage-7.10.6-cp313-cp313-win32.whl", hash = "sha256:160c00a5e6b6bdf4e5984b0ef21fc860bc94416c41b7df4d63f536d17c38902e", size = 219770, upload-time = "2025-08-29T15:33:58.063Z" }, + { url = "https://files.pythonhosted.org/packages/a7/14/0b831122305abcc1060c008f6c97bbdc0a913ab47d65070a01dc50293c2b/coverage-7.10.6-cp313-cp313-win_amd64.whl", hash = "sha256:628055297f3e2aa181464c3808402887643405573eb3d9de060d81531fa79d32", size = 220566, upload-time = "2025-08-29T15:33:59.766Z" }, + { url = "https://files.pythonhosted.org/packages/83/c6/81a83778c1f83f1a4a168ed6673eeedc205afb562d8500175292ca64b94e/coverage-7.10.6-cp313-cp313-win_arm64.whl", hash = "sha256:df4ec1f8540b0bcbe26ca7dd0f541847cc8a108b35596f9f91f59f0c060bfdd2", size = 219195, upload-time = "2025-08-29T15:34:01.191Z" }, + { url = "https://files.pythonhosted.org/packages/d7/1c/ccccf4bf116f9517275fa85047495515add43e41dfe8e0bef6e333c6b344/coverage-7.10.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:c9a8b7a34a4de3ed987f636f71881cd3b8339f61118b1aa311fbda12741bff0b", size = 218059, upload-time = "2025-08-29T15:34:02.91Z" }, + { url = "https://files.pythonhosted.org/packages/92/97/8a3ceff833d27c7492af4f39d5da6761e9ff624831db9e9f25b3886ddbca/coverage-7.10.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8dd5af36092430c2b075cee966719898f2ae87b636cefb85a653f1d0ba5d5393", size = 218287, upload-time = "2025-08-29T15:34:05.106Z" }, + { url = "https://files.pythonhosted.org/packages/92/d8/50b4a32580cf41ff0423777a2791aaf3269ab60c840b62009aec12d3970d/coverage-7.10.6-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:b0353b0f0850d49ada66fdd7d0c7cdb0f86b900bb9e367024fd14a60cecc1e27", size = 259625, upload-time = "2025-08-29T15:34:06.575Z" }, + { url = "https://files.pythonhosted.org/packages/7e/7e/6a7df5a6fb440a0179d94a348eb6616ed4745e7df26bf2a02bc4db72c421/coverage-7.10.6-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d6b9ae13d5d3e8aeca9ca94198aa7b3ebbc5acfada557d724f2a1f03d2c0b0df", size = 261801, upload-time = "2025-08-29T15:34:08.006Z" }, + { url = "https://files.pythonhosted.org/packages/3a/4c/a270a414f4ed5d196b9d3d67922968e768cd971d1b251e1b4f75e9362f75/coverage-7.10.6-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:675824a363cc05781b1527b39dc2587b8984965834a748177ee3c37b64ffeafb", size = 264027, upload-time = "2025-08-29T15:34:09.806Z" }, + { url = "https://files.pythonhosted.org/packages/9c/8b/3210d663d594926c12f373c5370bf1e7c5c3a427519a8afa65b561b9a55c/coverage-7.10.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:692d70ea725f471a547c305f0d0fc6a73480c62fb0da726370c088ab21aed282", size = 261576, upload-time = "2025-08-29T15:34:11.585Z" }, + { url = "https://files.pythonhosted.org/packages/72/d0/e1961eff67e9e1dba3fc5eb7a4caf726b35a5b03776892da8d79ec895775/coverage-7.10.6-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:851430a9a361c7a8484a36126d1d0ff8d529d97385eacc8dfdc9bfc8c2d2cbe4", size = 259341, upload-time = "2025-08-29T15:34:13.159Z" }, + { url = "https://files.pythonhosted.org/packages/3a/06/d6478d152cd189b33eac691cba27a40704990ba95de49771285f34a5861e/coverage-7.10.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d9369a23186d189b2fc95cc08b8160ba242057e887d766864f7adf3c46b2df21", size = 260468, upload-time = "2025-08-29T15:34:14.571Z" }, + { url = "https://files.pythonhosted.org/packages/ed/73/737440247c914a332f0b47f7598535b29965bf305e19bbc22d4c39615d2b/coverage-7.10.6-cp313-cp313t-win32.whl", hash = "sha256:92be86fcb125e9bda0da7806afd29a3fd33fdf58fba5d60318399adf40bf37d0", size = 220429, upload-time = "2025-08-29T15:34:16.394Z" }, + { url = "https://files.pythonhosted.org/packages/bd/76/b92d3214740f2357ef4a27c75a526eb6c28f79c402e9f20a922c295c05e2/coverage-7.10.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6b3039e2ca459a70c79523d39347d83b73f2f06af5624905eba7ec34d64d80b5", size = 221493, upload-time = "2025-08-29T15:34:17.835Z" }, + { url = "https://files.pythonhosted.org/packages/fc/8e/6dcb29c599c8a1f654ec6cb68d76644fe635513af16e932d2d4ad1e5ac6e/coverage-7.10.6-cp313-cp313t-win_arm64.whl", hash = "sha256:3fb99d0786fe17b228eab663d16bee2288e8724d26a199c29325aac4b0319b9b", size = 219757, upload-time = "2025-08-29T15:34:19.248Z" }, + { url = "https://files.pythonhosted.org/packages/d3/aa/76cf0b5ec00619ef208da4689281d48b57f2c7fde883d14bf9441b74d59f/coverage-7.10.6-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6008a021907be8c4c02f37cdc3ffb258493bdebfeaf9a839f9e71dfdc47b018e", size = 217331, upload-time = "2025-08-29T15:34:20.846Z" }, + { url = "https://files.pythonhosted.org/packages/65/91/8e41b8c7c505d398d7730206f3cbb4a875a35ca1041efc518051bfce0f6b/coverage-7.10.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5e75e37f23eb144e78940b40395b42f2321951206a4f50e23cfd6e8a198d3ceb", size = 217607, upload-time = "2025-08-29T15:34:22.433Z" }, + { url = "https://files.pythonhosted.org/packages/87/7f/f718e732a423d442e6616580a951b8d1ec3575ea48bcd0e2228386805e79/coverage-7.10.6-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0f7cb359a448e043c576f0da00aa8bfd796a01b06aa610ca453d4dde09cc1034", size = 248663, upload-time = "2025-08-29T15:34:24.425Z" }, + { url = "https://files.pythonhosted.org/packages/e6/52/c1106120e6d801ac03e12b5285e971e758e925b6f82ee9b86db3aa10045d/coverage-7.10.6-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c68018e4fc4e14b5668f1353b41ccf4bc83ba355f0e1b3836861c6f042d89ac1", size = 251197, upload-time = "2025-08-29T15:34:25.906Z" }, + { url = "https://files.pythonhosted.org/packages/3d/ec/3a8645b1bb40e36acde9c0609f08942852a4af91a937fe2c129a38f2d3f5/coverage-7.10.6-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cd4b2b0707fc55afa160cd5fc33b27ccbf75ca11d81f4ec9863d5793fc6df56a", size = 252551, upload-time = "2025-08-29T15:34:27.337Z" }, + { url = "https://files.pythonhosted.org/packages/a1/70/09ecb68eeb1155b28a1d16525fd3a9b65fbe75337311a99830df935d62b6/coverage-7.10.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4cec13817a651f8804a86e4f79d815b3b28472c910e099e4d5a0e8a3b6a1d4cb", size = 250553, upload-time = "2025-08-29T15:34:29.065Z" }, + { url = "https://files.pythonhosted.org/packages/c6/80/47df374b893fa812e953b5bc93dcb1427a7b3d7a1a7d2db33043d17f74b9/coverage-7.10.6-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f2a6a8e06bbda06f78739f40bfb56c45d14eb8249d0f0ea6d4b3d48e1f7c695d", size = 248486, upload-time = "2025-08-29T15:34:30.897Z" }, + { url = "https://files.pythonhosted.org/packages/4a/65/9f98640979ecee1b0d1a7164b589de720ddf8100d1747d9bbdb84be0c0fb/coverage-7.10.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:081b98395ced0d9bcf60ada7661a0b75f36b78b9d7e39ea0790bb4ed8da14747", size = 249981, upload-time = "2025-08-29T15:34:32.365Z" }, + { url = "https://files.pythonhosted.org/packages/1f/55/eeb6603371e6629037f47bd25bef300387257ed53a3c5fdb159b7ac8c651/coverage-7.10.6-cp314-cp314-win32.whl", hash = "sha256:6937347c5d7d069ee776b2bf4e1212f912a9f1f141a429c475e6089462fcecc5", size = 220054, upload-time = "2025-08-29T15:34:34.124Z" }, + { url = "https://files.pythonhosted.org/packages/15/d1/a0912b7611bc35412e919a2cd59ae98e7ea3b475e562668040a43fb27897/coverage-7.10.6-cp314-cp314-win_amd64.whl", hash = "sha256:adec1d980fa07e60b6ef865f9e5410ba760e4e1d26f60f7e5772c73b9a5b0713", size = 220851, upload-time = "2025-08-29T15:34:35.651Z" }, + { url = "https://files.pythonhosted.org/packages/ef/2d/11880bb8ef80a45338e0b3e0725e4c2d73ffbb4822c29d987078224fd6a5/coverage-7.10.6-cp314-cp314-win_arm64.whl", hash = "sha256:a80f7aef9535442bdcf562e5a0d5a5538ce8abe6bb209cfbf170c462ac2c2a32", size = 219429, upload-time = "2025-08-29T15:34:37.16Z" }, + { url = "https://files.pythonhosted.org/packages/83/c0/1f00caad775c03a700146f55536ecd097a881ff08d310a58b353a1421be0/coverage-7.10.6-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:0de434f4fbbe5af4fa7989521c655c8c779afb61c53ab561b64dcee6149e4c65", size = 218080, upload-time = "2025-08-29T15:34:38.919Z" }, + { url = "https://files.pythonhosted.org/packages/a9/c4/b1c5d2bd7cc412cbeb035e257fd06ed4e3e139ac871d16a07434e145d18d/coverage-7.10.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6e31b8155150c57e5ac43ccd289d079eb3f825187d7c66e755a055d2c85794c6", size = 218293, upload-time = "2025-08-29T15:34:40.425Z" }, + { url = "https://files.pythonhosted.org/packages/3f/07/4468d37c94724bf6ec354e4ec2f205fda194343e3e85fd2e59cec57e6a54/coverage-7.10.6-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:98cede73eb83c31e2118ae8d379c12e3e42736903a8afcca92a7218e1f2903b0", size = 259800, upload-time = "2025-08-29T15:34:41.996Z" }, + { url = "https://files.pythonhosted.org/packages/82/d8/f8fb351be5fee31690cd8da768fd62f1cfab33c31d9f7baba6cd8960f6b8/coverage-7.10.6-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f863c08f4ff6b64fa8045b1e3da480f5374779ef187f07b82e0538c68cb4ff8e", size = 261965, upload-time = "2025-08-29T15:34:43.61Z" }, + { url = "https://files.pythonhosted.org/packages/e8/70/65d4d7cfc75c5c6eb2fed3ee5cdf420fd8ae09c4808723a89a81d5b1b9c3/coverage-7.10.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2b38261034fda87be356f2c3f42221fdb4171c3ce7658066ae449241485390d5", size = 264220, upload-time = "2025-08-29T15:34:45.387Z" }, + { url = "https://files.pythonhosted.org/packages/98/3c/069df106d19024324cde10e4ec379fe2fb978017d25e97ebee23002fbadf/coverage-7.10.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0e93b1476b79eae849dc3872faeb0bf7948fd9ea34869590bc16a2a00b9c82a7", size = 261660, upload-time = "2025-08-29T15:34:47.288Z" }, + { url = "https://files.pythonhosted.org/packages/fc/8a/2974d53904080c5dc91af798b3a54a4ccb99a45595cc0dcec6eb9616a57d/coverage-7.10.6-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ff8a991f70f4c0cf53088abf1e3886edcc87d53004c7bb94e78650b4d3dac3b5", size = 259417, upload-time = "2025-08-29T15:34:48.779Z" }, + { url = "https://files.pythonhosted.org/packages/30/38/9616a6b49c686394b318974d7f6e08f38b8af2270ce7488e879888d1e5db/coverage-7.10.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ac765b026c9f33044419cbba1da913cfb82cca1b60598ac1c7a5ed6aac4621a0", size = 260567, upload-time = "2025-08-29T15:34:50.718Z" }, + { url = "https://files.pythonhosted.org/packages/76/16/3ed2d6312b371a8cf804abf4e14895b70e4c3491c6e53536d63fd0958a8d/coverage-7.10.6-cp314-cp314t-win32.whl", hash = "sha256:441c357d55f4936875636ef2cfb3bee36e466dcf50df9afbd398ce79dba1ebb7", size = 220831, upload-time = "2025-08-29T15:34:52.653Z" }, + { url = "https://files.pythonhosted.org/packages/d5/e5/d38d0cb830abede2adb8b147770d2a3d0e7fecc7228245b9b1ae6c24930a/coverage-7.10.6-cp314-cp314t-win_amd64.whl", hash = "sha256:073711de3181b2e204e4870ac83a7c4853115b42e9cd4d145f2231e12d670930", size = 221950, upload-time = "2025-08-29T15:34:54.212Z" }, + { url = "https://files.pythonhosted.org/packages/f4/51/e48e550f6279349895b0ffcd6d2a690e3131ba3a7f4eafccc141966d4dea/coverage-7.10.6-cp314-cp314t-win_arm64.whl", hash = "sha256:137921f2bac5559334ba66122b753db6dc5d1cf01eb7b64eb412bb0d064ef35b", size = 219969, upload-time = "2025-08-29T15:34:55.83Z" }, + { url = "https://files.pythonhosted.org/packages/44/0c/50db5379b615854b5cf89146f8f5bd1d5a9693d7f3a987e269693521c404/coverage-7.10.6-py3-none-any.whl", hash = "sha256:92c4ecf6bf11b2e85fd4d8204814dc26e6a19f0c9d938c207c5cb0eadfcabbe3", size = 208986, upload-time = "2025-08-29T15:35:14.506Z" }, ] [package.optional-dependencies] @@ -1341,7 +1367,7 @@ wheels = [ [[package]] name = "locust" -version = "2.39.1" +version = "2.40.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "configargparse" }, @@ -1353,6 +1379,7 @@ dependencies = [ { name = "locust-cloud" }, { name = "msgpack" }, { name = "psutil" }, + { name = "pytest" }, { name = "python-engineio" }, { name = "python-socketio", extra = ["client"] }, { name = "pywin32", marker = "sys_platform == 'win32'" }, @@ -1360,12 +1387,12 @@ dependencies = [ { name = "requests" }, { name = "setuptools" }, { name = "tomli", marker = "python_full_version < '3.11'" }, - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.12'" }, { name = "werkzeug" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/95/c8/10aa5445c404eed389b56877e6714c1787190cc09dd70059ce3765979ec5/locust-2.39.1.tar.gz", hash = "sha256:6bdd19e27edf9a1c84391d6cf6e9a737dfb832be7dfbf39053191ae31b9cc498", size = 1409902, upload-time = "2025-08-29T17:41:01.544Z" } +sdist = { url = "https://files.pythonhosted.org/packages/27/e0/a99401e233ad1b9ad26265ad8f45f2466abb6ef954e7747e8484864eb6df/locust-2.40.2.tar.gz", hash = "sha256:9ffdf900d1ad949d4c5809e2a4e526bba582175f025f24da2755f43f4b5cb23e", size = 1411854, upload-time = "2025-09-08T12:55:28.664Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/b3/b2f4b2ca88b1e72eba7be2b2982533b887f8b709d222db78eb9602aa5121/locust-2.39.1-py3-none-any.whl", hash = "sha256:fd5148f2f1a4ed34aee968abc4393674e69d1b5e1b54db50a397f6eb09ce0b04", size = 1428155, upload-time = "2025-08-29T17:41:00.245Z" }, + { url = "https://files.pythonhosted.org/packages/f5/e7/85ddb125d91b3a2bfa2a52eeae2d4c7da062239aaa475d6aebddb5688f41/locust-2.40.2-py3-none-any.whl", hash = "sha256:c8f0060d2bd8479034e9e61e6473669c4c8216930d99ee61ec0e627340b89d3e", size = 1430483, upload-time = "2025-09-08T12:55:25.659Z" }, ] [[package]] @@ -2204,7 +2231,7 @@ wheels = [ [[package]] name = "pytest" -version = "8.4.1" +version = "8.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -2215,9 +2242,9 @@ dependencies = [ { name = "pygments" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/08/ba/45911d754e8eba3d5a841a5ce61a65a685ff1798421ac054f85aa8747dfb/pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c", size = 1517714, upload-time = "2025-06-18T05:48:06.109Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a3/5c/00a0e072241553e1a7496d638deababa67c5058571567b92a7eaa258397c/pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01", size = 1519618, upload-time = "2025-09-04T14:34:22.711Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/29/16/c8a903f4c4dffe7a12843191437d7cd8e32751d5de349d45d3fe69544e87/pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", size = 365474, upload-time = "2025-06-18T05:48:03.955Z" }, + { url = "https://files.pythonhosted.org/packages/a8/a4/20da314d277121d6534b3a980b29035dcd51e6744bd79075a6ce8fa4eb8d/pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79", size = 365750, upload-time = "2025-09-04T14:34:20.226Z" }, ] [[package]] @@ -2235,28 +2262,28 @@ wheels = [ [[package]] name = "pytest-cov" -version = "6.2.1" +version = "7.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "coverage", extra = ["toml"] }, { name = "pluggy" }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/18/99/668cade231f434aaa59bbfbf49469068d2ddd945000621d3d165d2e7dd7b/pytest_cov-6.2.1.tar.gz", hash = "sha256:25cc6cc0a5358204b8108ecedc51a9b57b34cc6b8c967cc2c01a4e00d8a67da2", size = 69432, upload-time = "2025-06-12T10:47:47.684Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/f7/c933acc76f5208b3b00089573cf6a2bc26dc80a8aece8f52bb7d6b1855ca/pytest_cov-7.0.0.tar.gz", hash = "sha256:33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1", size = 54328, upload-time = "2025-09-09T10:57:02.113Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bc/16/4ea354101abb1287856baa4af2732be351c7bee728065aed451b678153fd/pytest_cov-6.2.1-py3-none-any.whl", hash = "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5", size = 24644, upload-time = "2025-06-12T10:47:45.932Z" }, + { url = "https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl", hash = "sha256:3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861", size = 22424, upload-time = "2025-09-09T10:57:00.695Z" }, ] [[package]] name = "pytest-mock" -version = "3.14.1" +version = "3.15.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/71/28/67172c96ba684058a4d24ffe144d64783d2a270d0af0d9e792737bddc75c/pytest_mock-3.14.1.tar.gz", hash = "sha256:159e9edac4c451ce77a5cdb9fc5d1100708d2dd4ba3c3df572f14097351af80e", size = 33241, upload-time = "2025-05-26T13:58:45.167Z" } +sdist = { url = "https://files.pythonhosted.org/packages/61/99/3323ee5c16b3637b4d941c362182d3e749c11e400bea31018c42219f3a98/pytest_mock-3.15.0.tar.gz", hash = "sha256:ab896bd190316b9d5d87b277569dfcdf718b2d049a2ccff5f7aca279c002a1cf", size = 33838, upload-time = "2025-09-04T20:57:48.679Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b2/05/77b60e520511c53d1c1ca75f1930c7dd8e971d0c4379b7f4b3f9644685ba/pytest_mock-3.14.1-py3-none-any.whl", hash = "sha256:178aefcd11307d874b4cd3100344e7e2d888d9791a6a1d9bfe90fbc1b74fd1d0", size = 9923, upload-time = "2025-05-26T13:58:43.487Z" }, + { url = "https://files.pythonhosted.org/packages/2b/b3/7fefc43fb706380144bcd293cc6e446e6f637ddfa8b83f48d1734156b529/pytest_mock-3.15.0-py3-none-any.whl", hash = "sha256:ef2219485fb1bd256b00e7ad7466ce26729b30eadfc7cbcdb4fa9a92ca68db6f", size = 10050, upload-time = "2025-09-04T20:57:47.274Z" }, ] [[package]] @@ -2532,28 +2559,28 @@ wheels = [ [[package]] name = "ruff" -version = "0.12.11" +version = "0.13.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/de/55/16ab6a7d88d93001e1ae4c34cbdcfb376652d761799459ff27c1dc20f6fa/ruff-0.12.11.tar.gz", hash = "sha256:c6b09ae8426a65bbee5425b9d0b82796dbb07cb1af045743c79bfb163001165d", size = 5347103, upload-time = "2025-08-28T13:59:08.87Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6e/1a/1f4b722862840295bcaba8c9e5261572347509548faaa99b2d57ee7bfe6a/ruff-0.13.0.tar.gz", hash = "sha256:5b4b1ee7eb35afae128ab94459b13b2baaed282b1fb0f472a73c82c996c8ae60", size = 5372863, upload-time = "2025-09-10T16:25:37.917Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d6/a2/3b3573e474de39a7a475f3fbaf36a25600bfeb238e1a90392799163b64a0/ruff-0.12.11-py3-none-linux_armv6l.whl", hash = "sha256:93fce71e1cac3a8bf9200e63a38ac5c078f3b6baebffb74ba5274fb2ab276065", size = 11979885, upload-time = "2025-08-28T13:58:26.654Z" }, - { url = "https://files.pythonhosted.org/packages/76/e4/235ad6d1785a2012d3ded2350fd9bc5c5af8c6f56820e696b0118dfe7d24/ruff-0.12.11-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b8e33ac7b28c772440afa80cebb972ffd823621ded90404f29e5ab6d1e2d4b93", size = 12742364, upload-time = "2025-08-28T13:58:30.256Z" }, - { url = "https://files.pythonhosted.org/packages/2c/0d/15b72c5fe6b1e402a543aa9d8960e0a7e19dfb079f5b0b424db48b7febab/ruff-0.12.11-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d69fb9d4937aa19adb2e9f058bc4fbfe986c2040acb1a4a9747734834eaa0bfd", size = 11920111, upload-time = "2025-08-28T13:58:33.677Z" }, - { url = "https://files.pythonhosted.org/packages/3e/c0/f66339d7893798ad3e17fa5a1e587d6fd9806f7c1c062b63f8b09dda6702/ruff-0.12.11-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:411954eca8464595077a93e580e2918d0a01a19317af0a72132283e28ae21bee", size = 12160060, upload-time = "2025-08-28T13:58:35.74Z" }, - { url = "https://files.pythonhosted.org/packages/03/69/9870368326db26f20c946205fb2d0008988aea552dbaec35fbacbb46efaa/ruff-0.12.11-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a2c0a2e1a450f387bf2c6237c727dd22191ae8c00e448e0672d624b2bbd7fb0", size = 11799848, upload-time = "2025-08-28T13:58:38.051Z" }, - { url = "https://files.pythonhosted.org/packages/25/8c/dd2c7f990e9b3a8a55eee09d4e675027d31727ce33cdb29eab32d025bdc9/ruff-0.12.11-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ca4c3a7f937725fd2413c0e884b5248a19369ab9bdd850b5781348ba283f644", size = 13536288, upload-time = "2025-08-28T13:58:40.046Z" }, - { url = "https://files.pythonhosted.org/packages/7a/30/d5496fa09aba59b5e01ea76775a4c8897b13055884f56f1c35a4194c2297/ruff-0.12.11-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:4d1df0098124006f6a66ecf3581a7f7e754c4df7644b2e6704cd7ca80ff95211", size = 14490633, upload-time = "2025-08-28T13:58:42.285Z" }, - { url = "https://files.pythonhosted.org/packages/9b/2f/81f998180ad53445d403c386549d6946d0748e536d58fce5b5e173511183/ruff-0.12.11-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a8dd5f230efc99a24ace3b77e3555d3fbc0343aeed3fc84c8d89e75ab2ff793", size = 13888430, upload-time = "2025-08-28T13:58:44.641Z" }, - { url = "https://files.pythonhosted.org/packages/87/71/23a0d1d5892a377478c61dbbcffe82a3476b050f38b5162171942a029ef3/ruff-0.12.11-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4dc75533039d0ed04cd33fb8ca9ac9620b99672fe7ff1533b6402206901c34ee", size = 12913133, upload-time = "2025-08-28T13:58:47.039Z" }, - { url = "https://files.pythonhosted.org/packages/80/22/3c6cef96627f89b344c933781ed38329bfb87737aa438f15da95907cbfd5/ruff-0.12.11-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4fc58f9266d62c6eccc75261a665f26b4ef64840887fc6cbc552ce5b29f96cc8", size = 13169082, upload-time = "2025-08-28T13:58:49.157Z" }, - { url = "https://files.pythonhosted.org/packages/05/b5/68b3ff96160d8b49e8dd10785ff3186be18fd650d356036a3770386e6c7f/ruff-0.12.11-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:5a0113bd6eafd545146440225fe60b4e9489f59eb5f5f107acd715ba5f0b3d2f", size = 13139490, upload-time = "2025-08-28T13:58:51.593Z" }, - { url = "https://files.pythonhosted.org/packages/59/b9/050a3278ecd558f74f7ee016fbdf10591d50119df8d5f5da45a22c6afafc/ruff-0.12.11-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:0d737b4059d66295c3ea5720e6efc152623bb83fde5444209b69cd33a53e2000", size = 11958928, upload-time = "2025-08-28T13:58:53.943Z" }, - { url = "https://files.pythonhosted.org/packages/f9/bc/93be37347db854806904a43b0493af8d6873472dfb4b4b8cbb27786eb651/ruff-0.12.11-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:916fc5defee32dbc1fc1650b576a8fed68f5e8256e2180d4d9855aea43d6aab2", size = 11764513, upload-time = "2025-08-28T13:58:55.976Z" }, - { url = "https://files.pythonhosted.org/packages/7a/a1/1471751e2015a81fd8e166cd311456c11df74c7e8769d4aabfbc7584c7ac/ruff-0.12.11-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c984f07d7adb42d3ded5be894fb4007f30f82c87559438b4879fe7aa08c62b39", size = 12745154, upload-time = "2025-08-28T13:58:58.16Z" }, - { url = "https://files.pythonhosted.org/packages/68/ab/2542b14890d0f4872dd81b7b2a6aed3ac1786fae1ce9b17e11e6df9e31e3/ruff-0.12.11-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e07fbb89f2e9249f219d88331c833860489b49cdf4b032b8e4432e9b13e8a4b9", size = 13227653, upload-time = "2025-08-28T13:59:00.276Z" }, - { url = "https://files.pythonhosted.org/packages/22/16/2fbfc61047dbfd009c58a28369a693a1484ad15441723be1cd7fe69bb679/ruff-0.12.11-py3-none-win32.whl", hash = "sha256:c792e8f597c9c756e9bcd4d87cf407a00b60af77078c96f7b6366ea2ce9ba9d3", size = 11944270, upload-time = "2025-08-28T13:59:02.347Z" }, - { url = "https://files.pythonhosted.org/packages/08/a5/34276984705bfe069cd383101c45077ee029c3fe3b28225bf67aa35f0647/ruff-0.12.11-py3-none-win_amd64.whl", hash = "sha256:a3283325960307915b6deb3576b96919ee89432ebd9c48771ca12ee8afe4a0fd", size = 13046600, upload-time = "2025-08-28T13:59:04.751Z" }, - { url = "https://files.pythonhosted.org/packages/84/a8/001d4a7c2b37623a3fd7463208267fb906df40ff31db496157549cfd6e72/ruff-0.12.11-py3-none-win_arm64.whl", hash = "sha256:bae4d6e6a2676f8fb0f98b74594a048bae1b944aab17e9f5d504062303c6dbea", size = 12135290, upload-time = "2025-08-28T13:59:06.933Z" }, + { url = "https://files.pythonhosted.org/packages/ac/fe/6f87b419dbe166fd30a991390221f14c5b68946f389ea07913e1719741e0/ruff-0.13.0-py3-none-linux_armv6l.whl", hash = "sha256:137f3d65d58ee828ae136a12d1dc33d992773d8f7644bc6b82714570f31b2004", size = 12187826, upload-time = "2025-09-10T16:24:39.5Z" }, + { url = "https://files.pythonhosted.org/packages/e4/25/c92296b1fc36d2499e12b74a3fdb230f77af7bdf048fad7b0a62e94ed56a/ruff-0.13.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:21ae48151b66e71fd111b7d79f9ad358814ed58c339631450c66a4be33cc28b9", size = 12933428, upload-time = "2025-09-10T16:24:43.866Z" }, + { url = "https://files.pythonhosted.org/packages/44/cf/40bc7221a949470307d9c35b4ef5810c294e6cfa3caafb57d882731a9f42/ruff-0.13.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:64de45f4ca5441209e41742d527944635a05a6e7c05798904f39c85bafa819e3", size = 12095543, upload-time = "2025-09-10T16:24:46.638Z" }, + { url = "https://files.pythonhosted.org/packages/f1/03/8b5ff2a211efb68c63a1d03d157e924997ada87d01bebffbd13a0f3fcdeb/ruff-0.13.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b2c653ae9b9d46e0ef62fc6fbf5b979bda20a0b1d2b22f8f7eb0cde9f4963b8", size = 12312489, upload-time = "2025-09-10T16:24:49.556Z" }, + { url = "https://files.pythonhosted.org/packages/37/fc/2336ef6d5e9c8d8ea8305c5f91e767d795cd4fc171a6d97ef38a5302dadc/ruff-0.13.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4cec632534332062bc9eb5884a267b689085a1afea9801bf94e3ba7498a2d207", size = 11991631, upload-time = "2025-09-10T16:24:53.439Z" }, + { url = "https://files.pythonhosted.org/packages/39/7f/f6d574d100fca83d32637d7f5541bea2f5e473c40020bbc7fc4a4d5b7294/ruff-0.13.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dcd628101d9f7d122e120ac7c17e0a0f468b19bc925501dbe03c1cb7f5415b24", size = 13720602, upload-time = "2025-09-10T16:24:56.392Z" }, + { url = "https://files.pythonhosted.org/packages/fd/c8/a8a5b81d8729b5d1f663348d11e2a9d65a7a9bd3c399763b1a51c72be1ce/ruff-0.13.0-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:afe37db8e1466acb173bb2a39ca92df00570e0fd7c94c72d87b51b21bb63efea", size = 14697751, upload-time = "2025-09-10T16:24:59.89Z" }, + { url = "https://files.pythonhosted.org/packages/57/f5/183ec292272ce7ec5e882aea74937f7288e88ecb500198b832c24debc6d3/ruff-0.13.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f96a8d90bb258d7d3358b372905fe7333aaacf6c39e2408b9f8ba181f4b6ef2", size = 14095317, upload-time = "2025-09-10T16:25:03.025Z" }, + { url = "https://files.pythonhosted.org/packages/9f/8d/7f9771c971724701af7926c14dab31754e7b303d127b0d3f01116faef456/ruff-0.13.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94b5e3d883e4f924c5298e3f2ee0f3085819c14f68d1e5b6715597681433f153", size = 13144418, upload-time = "2025-09-10T16:25:06.272Z" }, + { url = "https://files.pythonhosted.org/packages/a8/a6/7985ad1778e60922d4bef546688cd8a25822c58873e9ff30189cfe5dc4ab/ruff-0.13.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03447f3d18479df3d24917a92d768a89f873a7181a064858ea90a804a7538991", size = 13370843, upload-time = "2025-09-10T16:25:09.965Z" }, + { url = "https://files.pythonhosted.org/packages/64/1c/bafdd5a7a05a50cc51d9f5711da704942d8dd62df3d8c70c311e98ce9f8a/ruff-0.13.0-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:fbc6b1934eb1c0033da427c805e27d164bb713f8e273a024a7e86176d7f462cf", size = 13321891, upload-time = "2025-09-10T16:25:12.969Z" }, + { url = "https://files.pythonhosted.org/packages/bc/3e/7817f989cb9725ef7e8d2cee74186bf90555279e119de50c750c4b7a72fe/ruff-0.13.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a8ab6a3e03665d39d4a25ee199d207a488724f022db0e1fe4002968abdb8001b", size = 12119119, upload-time = "2025-09-10T16:25:16.621Z" }, + { url = "https://files.pythonhosted.org/packages/58/07/9df080742e8d1080e60c426dce6e96a8faf9a371e2ce22eef662e3839c95/ruff-0.13.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d2a5c62f8ccc6dd2fe259917482de7275cecc86141ee10432727c4816235bc41", size = 11961594, upload-time = "2025-09-10T16:25:19.49Z" }, + { url = "https://files.pythonhosted.org/packages/6a/f4/ae1185349197d26a2316840cb4d6c3fba61d4ac36ed728bf0228b222d71f/ruff-0.13.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:b7b85ca27aeeb1ab421bc787009831cffe6048faae08ad80867edab9f2760945", size = 12933377, upload-time = "2025-09-10T16:25:22.371Z" }, + { url = "https://files.pythonhosted.org/packages/b6/39/e776c10a3b349fc8209a905bfb327831d7516f6058339a613a8d2aaecacd/ruff-0.13.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:79ea0c44a3032af768cabfd9616e44c24303af49d633b43e3a5096e009ebe823", size = 13418555, upload-time = "2025-09-10T16:25:25.681Z" }, + { url = "https://files.pythonhosted.org/packages/46/09/dca8df3d48e8b3f4202bf20b1658898e74b6442ac835bfe2c1816d926697/ruff-0.13.0-py3-none-win32.whl", hash = "sha256:4e473e8f0e6a04e4113f2e1de12a5039579892329ecc49958424e5568ef4f768", size = 12141613, upload-time = "2025-09-10T16:25:28.664Z" }, + { url = "https://files.pythonhosted.org/packages/61/21/0647eb71ed99b888ad50e44d8ec65d7148babc0e242d531a499a0bbcda5f/ruff-0.13.0-py3-none-win_amd64.whl", hash = "sha256:48e5c25c7a3713eea9ce755995767f4dcd1b0b9599b638b12946e892123d1efb", size = 13258250, upload-time = "2025-09-10T16:25:31.773Z" }, + { url = "https://files.pythonhosted.org/packages/e1/a3/03216a6a86c706df54422612981fb0f9041dbb452c3401501d4a22b942c9/ruff-0.13.0-py3-none-win_arm64.whl", hash = "sha256:ab80525317b1e1d38614addec8ac954f1b3e662de9d59114ecbf771d00cf613e", size = 12312357, upload-time = "2025-09-10T16:25:35.595Z" }, ] [[package]] @@ -2876,27 +2903,27 @@ wheels = [ [[package]] name = "tokenizers" -version = "0.21.4" +version = "0.22.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "huggingface-hub" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c2/2f/402986d0823f8d7ca139d969af2917fefaa9b947d1fb32f6168c509f2492/tokenizers-0.21.4.tar.gz", hash = "sha256:fa23f85fbc9a02ec5c6978da172cdcbac23498c3ca9f3645c5c68740ac007880", size = 351253, upload-time = "2025-07-28T15:48:54.325Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/b4/c1ce3699e81977da2ace8b16d2badfd42b060e7d33d75c4ccdbf9dc920fa/tokenizers-0.22.0.tar.gz", hash = "sha256:2e33b98525be8453f355927f3cab312c36cd3e44f4d7e9e97da2fa94d0a49dcb", size = 362771, upload-time = "2025-08-29T10:25:33.914Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/98/c6/fdb6f72bf6454f52eb4a2510be7fb0f614e541a2554d6210e370d85efff4/tokenizers-0.21.4-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:2ccc10a7c3bcefe0f242867dc914fc1226ee44321eb618cfe3019b5df3400133", size = 2863987, upload-time = "2025-07-28T15:48:44.877Z" }, - { url = "https://files.pythonhosted.org/packages/8d/a6/28975479e35ddc751dc1ddc97b9b69bf7fcf074db31548aab37f8116674c/tokenizers-0.21.4-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:5e2f601a8e0cd5be5cc7506b20a79112370b9b3e9cb5f13f68ab11acd6ca7d60", size = 2732457, upload-time = "2025-07-28T15:48:43.265Z" }, - { url = "https://files.pythonhosted.org/packages/aa/8f/24f39d7b5c726b7b0be95dca04f344df278a3fe3a4deb15a975d194cbb32/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39b376f5a1aee67b4d29032ee85511bbd1b99007ec735f7f35c8a2eb104eade5", size = 3012624, upload-time = "2025-07-28T13:22:43.895Z" }, - { url = "https://files.pythonhosted.org/packages/58/47/26358925717687a58cb74d7a508de96649544fad5778f0cd9827398dc499/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2107ad649e2cda4488d41dfd031469e9da3fcbfd6183e74e4958fa729ffbf9c6", size = 2939681, upload-time = "2025-07-28T13:22:47.499Z" }, - { url = "https://files.pythonhosted.org/packages/99/6f/cc300fea5db2ab5ddc2c8aea5757a27b89c84469899710c3aeddc1d39801/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c73012da95afafdf235ba80047699df4384fdc481527448a078ffd00e45a7d9", size = 3247445, upload-time = "2025-07-28T15:48:39.711Z" }, - { url = "https://files.pythonhosted.org/packages/be/bf/98cb4b9c3c4afd8be89cfa6423704337dc20b73eb4180397a6e0d456c334/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f23186c40395fc390d27f519679a58023f368a0aad234af145e0f39ad1212732", size = 3428014, upload-time = "2025-07-28T13:22:49.569Z" }, - { url = "https://files.pythonhosted.org/packages/75/c7/96c1cc780e6ca7f01a57c13235dd05b7bc1c0f3588512ebe9d1331b5f5ae/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cc88bb34e23a54cc42713d6d98af5f1bf79c07653d24fe984d2d695ba2c922a2", size = 3193197, upload-time = "2025-07-28T13:22:51.471Z" }, - { url = "https://files.pythonhosted.org/packages/f2/90/273b6c7ec78af547694eddeea9e05de771278bd20476525ab930cecaf7d8/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51b7eabb104f46c1c50b486520555715457ae833d5aee9ff6ae853d1130506ff", size = 3115426, upload-time = "2025-07-28T15:48:41.439Z" }, - { url = "https://files.pythonhosted.org/packages/91/43/c640d5a07e95f1cf9d2c92501f20a25f179ac53a4f71e1489a3dcfcc67ee/tokenizers-0.21.4-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:714b05b2e1af1288bd1bc56ce496c4cebb64a20d158ee802887757791191e6e2", size = 9089127, upload-time = "2025-07-28T15:48:46.472Z" }, - { url = "https://files.pythonhosted.org/packages/44/a1/dd23edd6271d4dca788e5200a807b49ec3e6987815cd9d0a07ad9c96c7c2/tokenizers-0.21.4-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:1340ff877ceedfa937544b7d79f5b7becf33a4cfb58f89b3b49927004ef66f78", size = 9055243, upload-time = "2025-07-28T15:48:48.539Z" }, - { url = "https://files.pythonhosted.org/packages/21/2b/b410d6e9021c4b7ddb57248304dc817c4d4970b73b6ee343674914701197/tokenizers-0.21.4-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:3c1f4317576e465ac9ef0d165b247825a2a4078bcd01cba6b54b867bdf9fdd8b", size = 9298237, upload-time = "2025-07-28T15:48:50.443Z" }, - { url = "https://files.pythonhosted.org/packages/b7/0a/42348c995c67e2e6e5c89ffb9cfd68507cbaeb84ff39c49ee6e0a6dd0fd2/tokenizers-0.21.4-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:c212aa4e45ec0bb5274b16b6f31dd3f1c41944025c2358faaa5782c754e84c24", size = 9461980, upload-time = "2025-07-28T15:48:52.325Z" }, - { url = "https://files.pythonhosted.org/packages/3d/d3/dacccd834404cd71b5c334882f3ba40331ad2120e69ded32cf5fda9a7436/tokenizers-0.21.4-cp39-abi3-win32.whl", hash = "sha256:6c42a930bc5f4c47f4ea775c91de47d27910881902b0f20e4990ebe045a415d0", size = 2329871, upload-time = "2025-07-28T15:48:56.841Z" }, - { url = "https://files.pythonhosted.org/packages/41/f2/fd673d979185f5dcbac4be7d09461cbb99751554ffb6718d0013af8604cb/tokenizers-0.21.4-cp39-abi3-win_amd64.whl", hash = "sha256:475d807a5c3eb72c59ad9b5fcdb254f6e17f53dfcbb9903233b0dfa9c943b597", size = 2507568, upload-time = "2025-07-28T15:48:55.456Z" }, + { url = "https://files.pythonhosted.org/packages/6d/b1/18c13648edabbe66baa85fe266a478a7931ddc0cd1ba618802eb7b8d9865/tokenizers-0.22.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:eaa9620122a3fb99b943f864af95ed14c8dfc0f47afa3b404ac8c16b3f2bb484", size = 3081954, upload-time = "2025-08-29T10:25:24.993Z" }, + { url = "https://files.pythonhosted.org/packages/c2/02/c3c454b641bd7c4f79e4464accfae9e7dfc913a777d2e561e168ae060362/tokenizers-0.22.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:71784b9ab5bf0ff3075bceeb198149d2c5e068549c0d18fe32d06ba0deb63f79", size = 2945644, upload-time = "2025-08-29T10:25:23.405Z" }, + { url = "https://files.pythonhosted.org/packages/55/02/d10185ba2fd8c2d111e124c9d92de398aee0264b35ce433f79fb8472f5d0/tokenizers-0.22.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec5b71f668a8076802b0241a42387d48289f25435b86b769ae1837cad4172a17", size = 3254764, upload-time = "2025-08-29T10:25:12.445Z" }, + { url = "https://files.pythonhosted.org/packages/13/89/17514bd7ef4bf5bfff58e2b131cec0f8d5cea2b1c8ffe1050a2c8de88dbb/tokenizers-0.22.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ea8562fa7498850d02a16178105b58803ea825b50dc9094d60549a7ed63654bb", size = 3161654, upload-time = "2025-08-29T10:25:15.493Z" }, + { url = "https://files.pythonhosted.org/packages/5a/d8/bac9f3a7ef6dcceec206e3857c3b61bb16c6b702ed7ae49585f5bd85c0ef/tokenizers-0.22.0-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4136e1558a9ef2e2f1de1555dcd573e1cbc4a320c1a06c4107a3d46dc8ac6e4b", size = 3511484, upload-time = "2025-08-29T10:25:20.477Z" }, + { url = "https://files.pythonhosted.org/packages/aa/27/9c9800eb6763683010a4851db4d1802d8cab9cec114c17056eccb4d4a6e0/tokenizers-0.22.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cdf5954de3962a5fd9781dc12048d24a1a6f1f5df038c6e95db328cd22964206", size = 3712829, upload-time = "2025-08-29T10:25:17.154Z" }, + { url = "https://files.pythonhosted.org/packages/10/e3/b1726dbc1f03f757260fa21752e1921445b5bc350389a8314dd3338836db/tokenizers-0.22.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8337ca75d0731fc4860e6204cc24bb36a67d9736142aa06ed320943b50b1e7ed", size = 3408934, upload-time = "2025-08-29T10:25:18.76Z" }, + { url = "https://files.pythonhosted.org/packages/d4/61/aeab3402c26874b74bb67a7f2c4b569dde29b51032c5384db592e7b216f4/tokenizers-0.22.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a89264e26f63c449d8cded9061adea7b5de53ba2346fc7e87311f7e4117c1cc8", size = 3345585, upload-time = "2025-08-29T10:25:22.08Z" }, + { url = "https://files.pythonhosted.org/packages/bc/d3/498b4a8a8764cce0900af1add0f176ff24f475d4413d55b760b8cdf00893/tokenizers-0.22.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:790bad50a1b59d4c21592f9c3cf5e5cf9c3c7ce7e1a23a739f13e01fb1be377a", size = 9322986, upload-time = "2025-08-29T10:25:26.607Z" }, + { url = "https://files.pythonhosted.org/packages/a2/62/92378eb1c2c565837ca3cb5f9569860d132ab9d195d7950c1ea2681dffd0/tokenizers-0.22.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:76cf6757c73a10ef10bf06fa937c0ec7393d90432f543f49adc8cab3fb6f26cb", size = 9276630, upload-time = "2025-08-29T10:25:28.349Z" }, + { url = "https://files.pythonhosted.org/packages/eb/f0/342d80457aa1cda7654327460f69db0d69405af1e4c453f4dc6ca7c4a76e/tokenizers-0.22.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:1626cb186e143720c62c6c6b5371e62bbc10af60481388c0da89bc903f37ea0c", size = 9547175, upload-time = "2025-08-29T10:25:29.989Z" }, + { url = "https://files.pythonhosted.org/packages/14/84/8aa9b4adfc4fbd09381e20a5bc6aa27040c9c09caa89988c01544e008d18/tokenizers-0.22.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:da589a61cbfea18ae267723d6b029b84598dc8ca78db9951d8f5beff72d8507c", size = 9692735, upload-time = "2025-08-29T10:25:32.089Z" }, + { url = "https://files.pythonhosted.org/packages/bf/24/83ee2b1dc76bfe05c3142e7d0ccdfe69f0ad2f1ebf6c726cea7f0874c0d0/tokenizers-0.22.0-cp39-abi3-win32.whl", hash = "sha256:dbf9d6851bddae3e046fedfb166f47743c1c7bd11c640f0691dd35ef0bcad3be", size = 2471915, upload-time = "2025-08-29T10:25:36.411Z" }, + { url = "https://files.pythonhosted.org/packages/d1/9b/0e0bf82214ee20231845b127aa4a8015936ad5a46779f30865d10e404167/tokenizers-0.22.0-cp39-abi3-win_amd64.whl", hash = "sha256:c78174859eeaee96021f248a56c801e36bfb6bd5b067f2e95aa82445ca324f00", size = 2680494, upload-time = "2025-08-29T10:25:35.14Z" }, ] [[package]] diff --git a/misc/release/archive-version.js b/misc/release/archive-version.js index 3ef4f58b1e..1a66963dad 100755 --- a/misc/release/archive-version.js +++ b/misc/release/archive-version.js @@ -10,7 +10,7 @@ if (!nextVersion) { const filename = './docs/static/archived-versions.json'; const oldVersions = JSON.parse(readFileSync(filename)); const newVersions = [ - { label: `v${nextVersion}`, url: `https://v${nextVersion}.archive.immich.app` }, + { label: `v${nextVersion}`, url: `https://docs.v${nextVersion}.archive.immich.app` }, ...oldVersions, ]; diff --git a/misc/release/pump-version.sh b/misc/release/pump-version.sh index 35ce9a1f33..65a2e70e50 100755 --- a/misc/release/pump-version.sh +++ b/misc/release/pump-version.sh @@ -80,7 +80,7 @@ if [ "$CURRENT_SERVER" != "$NEXT_SERVER" ]; then jq --arg version "$NEXT_SERVER" '.version = $version' e2e/package.json > e2e/package.json.tmp && mv e2e/package.json.tmp e2e/package.json pnpm install --frozen-lockfile --prefix e2e - uvx --from=toml-cli toml set --toml-path=pyproject.toml project.version "$SERVER_PUMP" + uvx --from=toml-cli toml set --toml-path=machine-learning/pyproject.toml project.version "$NEXT_SERVER" fi if [ "$CURRENT_MOBILE" != "$NEXT_MOBILE" ]; then diff --git a/mise.lock b/mise.lock deleted file mode 100644 index 112b1ca6eb..0000000000 --- a/mise.lock +++ /dev/null @@ -1,34 +0,0 @@ -[tools.dart] -version = "3.8.2" -backend = "asdf:dart" - -[tools.flutter] -version = "3.32.8-stable" -backend = "asdf:flutter" - -[tools."github:CQLabs/homebrew-dcm"] -version = "1.31.4" -backend = "github:CQLabs/homebrew-dcm" - -[tools."github:CQLabs/homebrew-dcm".platforms.linux-x64] -checksum = "blake3:e9df5b765df327e1248fccf2c6165a89d632a065667f99c01765bf3047b94955" -size = 8821083 -url = "https://github.com/CQLabs/homebrew-dcm/releases/download/1.31.4/dcm-linux-x64-release.zip" - -[tools.node] -version = "22.18.0" -backend = "core:node" - -[tools.node.platforms.linux-x64] -checksum = "sha256:a2e703725d8683be86bb5da967bf8272f4518bdaf10f21389e2b2c9eaeae8c8a" -size = 54824343 -url = "https://nodejs.org/dist/v22.18.0/node-v22.18.0-linux-x64.tar.gz" - -[tools.pnpm] -version = "10.14.0" -backend = "aqua:pnpm/pnpm" - -[tools.pnpm.platforms.linux-x64] -checksum = "blake3:13dfa46b7173d3cad3bad60a756a492ecf0bce48b23eb9f793e7ccec5a09b46d" -size = 66231525 -url = "https://github.com/pnpm/pnpm/releases/download/v10.14.0/pnpm-linux-x64" diff --git a/mise.toml b/mise.toml index 47acb66b21..275098ab55 100644 --- a/mise.toml +++ b/mise.toml @@ -1,17 +1,15 @@ [tools] -node = "22.19.0" -flutter = "3.32.8" -pnpm = "10.14.0" -dart = "3.8.2" +node = "22.20.0" +flutter = "3.35.5" +pnpm = "10.18.1" [tools."github:CQLabs/homebrew-dcm"] -version = "1.31.4" +version = "1.30.0" bin = "dcm" postinstall = "chmod +x $MISE_TOOL_INSTALL_PATH/dcm" [settings] experimental = true -lockfile = true pin = true # .github @@ -280,12 +278,7 @@ run = "prettier --write ." [tasks."web:lint"] env._.path = "web/node_modules/.bin" dir = "web" -run = "eslint . --max-warnings 0" - -[tasks."web:lint-p"] -env._.path = "web/node_modules/.bin" -dir = "web" -run = "eslint-p . --max-warnings 0 --concurrency=4" +run = "eslint . --max-warnings 0 --concurrency 4" [tasks."web:lint-fix"] run = "mise run web:lint --fix" @@ -300,7 +293,7 @@ run = "tsc --noEmit" depends = "web:svelte-kit-sync" env._.path = "web/node_modules/.bin" dir = "web" -run = "svelte-check --no-tsconfig --fail-on-warnings --compiler-warnings 'reactive_declaration_non_reactive_property:ignore' --ignore src/lib/components/photos-page/asset-grid.svelte" +run = "svelte-check --no-tsconfig --fail-on-warnings" [tasks."web:checklist"] run = [ @@ -310,3 +303,205 @@ run = [ "mise run web:test --run", "mise run web:lint", ] + + +# mobile +[tasks."mobile:codegen:dart"] +alias = "mobile:codegen" +description = "Execute build_runner to auto-generate dart code" +dir = "mobile" +sources = [ + "pubspec.yaml", + "build.yaml", + "lib/**/*.dart", + "infrastructure/**/*.drift", +] +outputs = { auto = true } +run = "dart run build_runner build --delete-conflicting-outputs" + +[tasks."mobile:codegen:pigeon"] +alias = "mobile:pigeon" +description = "Generate pigeon platform code" +dir = "mobile" +depends = [ + "mobile:pigeon:native-sync", + "mobile:pigeon:thumbnail", + "mobile:pigeon:background-worker", + "mobile:pigeon:background-worker-lock", + "mobile:pigeon:connectivity", +] + +[tasks."mobile:codegen:translation"] +alias = "mobile:translation" +description = "Generate translations from i18n JSONs" +dir = "mobile" +run = [ + { task = "i18n:format-fix" }, + { tasks = [ + "mobile:i18n:loader", + "mobile:i18n:keys", + ] }, +] + +[tasks."mobile:codegen:app-icon"] +description = "Generate app icons" +dir = "mobile" +run = "flutter pub run flutter_launcher_icons:main" + +[tasks."mobile:codegen:splash"] +description = "Generate splash screen" +dir = "mobile" +run = "flutter pub run flutter_native_splash:create" + +[tasks."mobile:test"] +description = "Run mobile tests" +dir = "mobile" +run = "flutter test" + +[tasks."mobile:lint"] +description = "Analyze Dart code" +dir = "mobile" +depends = ["mobile:analyze:dart", "mobile:analyze:dcm"] + +[tasks."mobile:lint-fix"] +description = "Auto-fix Dart code" +dir = "mobile" +depends = ["mobile:analyze:fix:dart", "mobile:analyze:fix:dcm"] + +[tasks."mobile:format"] +description = "Format Dart code" +dir = "mobile" +run = "dart format --set-exit-if-changed $(find lib -name '*.dart' -not \\( -name '*.g.dart' -o -name '*.drift.dart' -o -name '*.gr.dart' \\))" + +[tasks."mobile:build:android"] +description = "Build Android release" +dir = "mobile" +run = "flutter build appbundle" + +[tasks."mobile:drift:migration"] +alias = "mobile:migration" +description = "Generate database migrations" +dir = "mobile" +run = "dart run drift_dev make-migrations" + + +# mobile internal tasks +[tasks."mobile:pigeon:native-sync"] +description = "Generate native sync API pigeon code" +dir = "mobile" +hide = true +sources = ["pigeon/native_sync_api.dart"] +outputs = [ + "lib/platform/native_sync_api.g.dart", + "ios/Runner/Sync/Messages.g.swift", + "android/app/src/main/kotlin/app/alextran/immich/sync/Messages.g.kt", +] +run = [ + "dart run pigeon --input pigeon/native_sync_api.dart", + "dart format lib/platform/native_sync_api.g.dart", +] + +[tasks."mobile:pigeon:thumbnail"] +description = "Generate thumbnail API pigeon code" +dir = "mobile" +hide = true +sources = ["pigeon/thumbnail_api.dart"] +outputs = [ + "lib/platform/thumbnail_api.g.dart", + "ios/Runner/Images/Thumbnails.g.swift", + "android/app/src/main/kotlin/app/alextran/immich/images/Thumbnails.g.kt", +] +run = [ + "dart run pigeon --input pigeon/thumbnail_api.dart", + "dart format lib/platform/thumbnail_api.g.dart", +] + +[tasks."mobile:pigeon:background-worker"] +description = "Generate background worker API pigeon code" +dir = "mobile" +hide = true +sources = ["pigeon/background_worker_api.dart"] +outputs = [ + "lib/platform/background_worker_api.g.dart", + "ios/Runner/Background/BackgroundWorker.g.swift", + "android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorker.g.kt", +] +run = [ + "dart run pigeon --input pigeon/background_worker_api.dart", + "dart format lib/platform/background_worker_api.g.dart", +] + +[tasks."mobile:pigeon:background-worker-lock"] +description = "Generate background worker lock API pigeon code" +dir = "mobile" +hide = true +sources = ["pigeon/background_worker_lock_api.dart"] +outputs = [ + "lib/platform/background_worker_lock_api.g.dart", + "android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorkerLock.g.kt", +] +run = [ + "dart run pigeon --input pigeon/background_worker_lock_api.dart", + "dart format lib/platform/background_worker_lock_api.g.dart", +] + +[tasks."mobile:pigeon:connectivity"] +description = "Generate connectivity API pigeon code" +dir = "mobile" +hide = true +sources = ["pigeon/connectivity_api.dart"] +outputs = [ + "lib/platform/connectivity_api.g.dart", + "ios/Runner/Connectivity/Connectivity.g.swift", + "android/app/src/main/kotlin/app/alextran/immich/connectivity/Connectivity.g.kt", +] +run = [ + "dart run pigeon --input pigeon/connectivity_api.dart", + "dart format lib/platform/connectivity_api.g.dart", +] + +[tasks."mobile:i18n:loader"] +description = "Generate i18n loader" +dir = "mobile" +hide = true +sources = ["i18n/"] +outputs = "lib/generated/codegen_loader.g.dart" +run = [ + "dart run easy_localization:generate -S ../i18n", + "dart format lib/generated/codegen_loader.g.dart", +] + +[tasks."mobile:i18n:keys"] +description = "Generate i18n keys" +dir = "mobile" +hide = true +sources = ["i18n/en.json"] +outputs = "lib/generated/intl_keys.g.dart" +run = [ + "dart run bin/generate_keys.dart", + "dart format lib/generated/intl_keys.g.dart", +] + +[tasks."mobile:analyze:dart"] +description = "Run Dart analysis" +dir = "mobile" +hide = true +run = "dart analyze --fatal-infos" + +[tasks."mobile:analyze:dcm"] +description = "Run Dart Code Metrics" +dir = "mobile" +hide = true +run = "dcm analyze lib --fatal-style --fatal-warnings" + +[tasks."mobile:analyze:fix:dart"] +description = "Auto-fix Dart analysis" +dir = "mobile" +hide = true +run = "dart fix --apply" + +[tasks."mobile:analyze:fix:dcm"] +description = "Auto-fix Dart Code Metrics" +dir = "mobile" +hide = true +run = "dcm fix lib" diff --git a/mobile/.fvmrc b/mobile/.fvmrc index 3ca65ffc7c..a4d5f6d9b7 100644 --- a/mobile/.fvmrc +++ b/mobile/.fvmrc @@ -1,3 +1,3 @@ { - "flutter": "3.32.8" + "flutter": "3.35.4" } \ No newline at end of file diff --git a/mobile/.vscode/settings.json b/mobile/.vscode/settings.json index 9a9fb67ce3..9c6057e582 100644 --- a/mobile/.vscode/settings.json +++ b/mobile/.vscode/settings.json @@ -1,8 +1,8 @@ { - "dart.flutterSdkPath": ".fvm/versions/3.32.8", + "dart.flutterSdkPath": ".fvm/versions/3.35.4", "dart.lineLength": 120, "[dart]": { - "editor.rulers": [120], + "editor.rulers": [120] }, "search.exclude": { "**/.fvm": true diff --git a/mobile/README.md b/mobile/README.md index 436b0a4c34..59b2d9340c 100644 --- a/mobile/README.md +++ b/mobile/README.md @@ -84,4 +84,4 @@ Below is how your code needs to be structured: ## Contributing -Please refer to the [architecture](https://immich.app/docs/developer/architecture/) for contributing to the mobile app! +Please refer to the [architecture](https://docs.immich.app/developer/architecture/) for contributing to the mobile app! diff --git a/mobile/analysis_options.yaml b/mobile/analysis_options.yaml index bef051bff2..c04e1dafdc 100644 --- a/mobile/analysis_options.yaml +++ b/mobile/analysis_options.yaml @@ -43,8 +43,9 @@ analyzer: - lib/**/*.g.dart - lib/**/*.drift.dart - plugins: - - custom_lint + # TODO: Re-enable after upgrading custom_lint + # plugins: + # - custom_lint custom_lint: debug: true @@ -134,6 +135,13 @@ custom_lint: dart_code_metrics: rules: + - banned-usage: + entries: + - name: debugPrint + description: Use dPrint instead of debugPrint for proper tree-shaking in release builds. + exclude-paths: + - 'lib/utils/debug_print.dart' + severity: perf # All rules from "recommended" preset # Show potential errors # - avoid-cascade-after-if-null diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/ImmichApp.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/ImmichApp.kt index 4237643233..4474c63e09 100644 --- a/mobile/android/app/src/main/kotlin/app/alextran/immich/ImmichApp.kt +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/ImmichApp.kt @@ -1,8 +1,12 @@ package app.alextran.immich import android.app.Application +import android.os.Handler +import android.os.Looper import androidx.work.Configuration import androidx.work.WorkManager +import app.alextran.immich.background.BackgroundEngineLock +import app.alextran.immich.background.BackgroundWorkerApiImpl class ImmichApp : Application() { override fun onCreate() { @@ -14,6 +18,13 @@ class ImmichApp : Application() { // Thus, the BackupWorker is not started. If the system kills the process after each initialization // (because of low memory etc.), the backup is never performed. // As a workaround, we also run a backup check when initializing the application + ContentObserverWorker.startBackupWorker(context = this, delayMilliseconds = 0) + Handler(Looper.getMainLooper()).postDelayed({ + // We can only check the engine count and not the status of the lock here, + // as the previous start might have been killed without unlocking. + if (BackgroundEngineLock.connectEngines > 0) return@postDelayed + BackgroundWorkerApiImpl.enqueueBackgroundWorker(this) + }, 5000) } } diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/MainActivity.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/MainActivity.kt index a87feddd1a..034f5ee72e 100644 --- a/mobile/android/app/src/main/kotlin/app/alextran/immich/MainActivity.kt +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/MainActivity.kt @@ -3,8 +3,12 @@ package app.alextran.immich import android.content.Context import android.os.Build import android.os.ext.SdkExtensions +import app.alextran.immich.background.BackgroundEngineLock import app.alextran.immich.background.BackgroundWorkerApiImpl import app.alextran.immich.background.BackgroundWorkerFgHostApi +import app.alextran.immich.background.BackgroundWorkerLockApi +import app.alextran.immich.connectivity.ConnectivityApi +import app.alextran.immich.connectivity.ConnectivityApiImpl import app.alextran.immich.images.ThumbnailApi import app.alextran.immich.images.ThumbnailsImpl import app.alextran.immich.sync.NativeSyncApi @@ -21,10 +25,9 @@ class MainActivity : FlutterFragmentActivity() { companion object { fun registerPlugins(ctx: Context, flutterEngine: FlutterEngine) { - flutterEngine.plugins.add(BackgroundServicePlugin()) - flutterEngine.plugins.add(HttpSSLOptionsPlugin()) - val messenger = flutterEngine.dartExecutor.binaryMessenger + val backgroundEngineLockImpl = BackgroundEngineLock(ctx) + BackgroundWorkerLockApi.setUp(messenger, backgroundEngineLockImpl) val nativeSyncApiImpl = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R || SdkExtensions.getExtensionVersion(Build.VERSION_CODES.R) < 1) { NativeSyncApiImpl26(ctx) @@ -34,6 +37,11 @@ class MainActivity : FlutterFragmentActivity() { NativeSyncApi.setUp(messenger, nativeSyncApiImpl) ThumbnailApi.setUp(messenger, ThumbnailsImpl(ctx)) BackgroundWorkerFgHostApi.setUp(messenger, BackgroundWorkerApiImpl(ctx)) + ConnectivityApi.setUp(messenger, ConnectivityApiImpl(ctx)) + + flutterEngine.plugins.add(BackgroundServicePlugin()) + flutterEngine.plugins.add(HttpSSLOptionsPlugin()) + flutterEngine.plugins.add(backgroundEngineLockImpl) } } } diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundEngineLock.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundEngineLock.kt new file mode 100644 index 0000000000..504267a4e5 --- /dev/null +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundEngineLock.kt @@ -0,0 +1,53 @@ +package app.alextran.immich.background + +import android.content.Context +import android.util.Log +import io.flutter.embedding.engine.plugins.FlutterPlugin +import java.util.concurrent.atomic.AtomicInteger + +private const val TAG = "BackgroundEngineLock" + +class BackgroundEngineLock(context: Context) : BackgroundWorkerLockApi, FlutterPlugin { + private val ctx: Context = context.applicationContext + + companion object { + + private var engineCount = AtomicInteger(0) + + val connectEngines: Int + get() = engineCount.get() + + private fun checkAndEnforceBackgroundLock(ctx: Context) { + // work manager task is running while the main app is opened, cancel the worker + if (BackgroundWorkerPreferences(ctx).isLocked() && + connectEngines > 1 && + BackgroundWorkerApiImpl.isBackgroundWorkerRunning() + ) { + Log.i(TAG, "Background worker is locked, cancelling the background worker") + BackgroundWorkerApiImpl.cancelBackgroundWorker(ctx) + } + } + } + + override fun lock() { + BackgroundWorkerPreferences(ctx).setLocked(true) + checkAndEnforceBackgroundLock(ctx) + Log.i(TAG, "Background worker is locked") + } + + override fun unlock() { + BackgroundWorkerPreferences(ctx).setLocked(false) + Log.i(TAG, "Background worker is unlocked") + } + + override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) { + checkAndEnforceBackgroundLock(binding.applicationContext) + engineCount.incrementAndGet() + Log.i(TAG, "Flutter engine attached. Attached Engines count: $engineCount") + } + + override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { + engineCount.decrementAndGet() + Log.i(TAG, "Flutter engine detached. Attached Engines count: $engineCount") + } +} diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorker.g.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorker.g.kt index b9826f80e9..5857453ad3 100644 --- a/mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorker.g.kt +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorker.g.kt @@ -37,6 +37,36 @@ private object BackgroundWorkerPigeonUtils { ) } } + fun deepEquals(a: Any?, b: Any?): Boolean { + if (a is ByteArray && b is ByteArray) { + return a.contentEquals(b) + } + if (a is IntArray && b is IntArray) { + return a.contentEquals(b) + } + if (a is LongArray && b is LongArray) { + return a.contentEquals(b) + } + if (a is DoubleArray && b is DoubleArray) { + return a.contentEquals(b) + } + if (a is Array<*> && b is Array<*>) { + return a.size == b.size && + a.indices.all{ deepEquals(a[it], b[it]) } + } + if (a is List<*> && b is List<*>) { + return a.size == b.size && + a.indices.all{ deepEquals(a[it], b[it]) } + } + if (a is Map<*, *> && b is Map<*, *>) { + return a.size == b.size && a.all { + (b as Map).containsKey(it.key) && + deepEquals(it.value, b[it.key]) + } + } + return a == b + } + } /** @@ -50,18 +80,64 @@ class FlutterError ( override val message: String? = null, val details: Any? = null ) : Throwable() + +/** Generated class from Pigeon that represents data sent in messages. */ +data class BackgroundWorkerSettings ( + val requiresCharging: Boolean, + val minimumDelaySeconds: Long +) + { + companion object { + fun fromList(pigeonVar_list: List): BackgroundWorkerSettings { + val requiresCharging = pigeonVar_list[0] as Boolean + val minimumDelaySeconds = pigeonVar_list[1] as Long + return BackgroundWorkerSettings(requiresCharging, minimumDelaySeconds) + } + } + fun toList(): List { + return listOf( + requiresCharging, + minimumDelaySeconds, + ) + } + override fun equals(other: Any?): Boolean { + if (other !is BackgroundWorkerSettings) { + return false + } + if (this === other) { + return true + } + return BackgroundWorkerPigeonUtils.deepEquals(toList(), other.toList()) } + + override fun hashCode(): Int = toList().hashCode() +} private open class BackgroundWorkerPigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { - return super.readValueOfType(type, buffer) + return when (type) { + 129.toByte() -> { + return (readValue(buffer) as? List)?.let { + BackgroundWorkerSettings.fromList(it) + } + } + else -> super.readValueOfType(type, buffer) + } } override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { - super.writeValue(stream, value) + when (value) { + is BackgroundWorkerSettings -> { + stream.write(129) + writeValue(stream, value.toList()) + } + else -> super.writeValue(stream, value) + } } } /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ interface BackgroundWorkerFgHostApi { fun enable() + fun saveNotificationMessage(title: String, body: String) + fun configure(settings: BackgroundWorkerSettings) fun disable() companion object { @@ -89,6 +165,43 @@ interface BackgroundWorkerFgHostApi { channel.setMessageHandler(null) } } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.saveNotificationMessage$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val titleArg = args[0] as String + val bodyArg = args[1] as String + val wrapped: List = try { + api.saveNotificationMessage(titleArg, bodyArg) + listOf(null) + } catch (exception: Throwable) { + BackgroundWorkerPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.configure$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val settingsArg = args[0] as BackgroundWorkerSettings + val wrapped: List = try { + api.configure(settingsArg) + listOf(null) + } catch (exception: Throwable) { + BackgroundWorkerPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } run { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.disable$separatedMessageChannelSuffix", codec) if (api != null) { diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorker.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorker.kt index 43124a957e..e59cee2c16 100644 --- a/mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorker.kt +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorker.kt @@ -1,18 +1,28 @@ package app.alextran.immich.background +import android.app.NotificationChannel +import android.app.NotificationManager import android.content.Context +import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC +import android.os.Build import android.os.Handler import android.os.Looper +import android.os.PowerManager import android.util.Log +import androidx.core.app.NotificationCompat +import androidx.work.ForegroundInfo import androidx.work.ListenableWorker import androidx.work.WorkerParameters import app.alextran.immich.MainActivity +import app.alextran.immich.R import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.SettableFuture import io.flutter.FlutterInjector import io.flutter.embedding.engine.FlutterEngine +import io.flutter.embedding.engine.FlutterEngineCache import io.flutter.embedding.engine.dart.DartExecutor import io.flutter.embedding.engine.loader.FlutterLoader +import java.util.concurrent.TimeUnit private const val TAG = "BackgroundWorker" @@ -40,17 +50,35 @@ class BackgroundWorker(context: Context, params: WorkerParameters) : /// Flag to track whether the background task has completed to prevent duplicate completions private var isComplete = false - init { - if (!loader.initialized()) { - loader.startInitialization(ctx) - } + private val notificationManager = + ctx.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + + private var foregroundFuture: ListenableFuture? = null + + companion object { + private const val NOTIFICATION_CHANNEL_ID = "immich::background_worker::notif" + private const val NOTIFICATION_ID = 100 } override fun startWork(): ListenableFuture { Log.i(TAG, "Starting background upload worker") + if (!loader.initialized()) { + loader.startInitialization(ctx) + } + + val notificationChannel = NotificationChannel( + NOTIFICATION_CHANNEL_ID, + NOTIFICATION_CHANNEL_ID, + NotificationManager.IMPORTANCE_LOW + ) + notificationManager.createNotificationChannel(notificationChannel) + val notificationConfig = BackgroundWorkerPreferences(ctx).getNotificationConfig() + showNotification(notificationConfig.first, notificationConfig.second) + loader.ensureInitializationCompleteAsync(ctx, null, Handler(Looper.getMainLooper())) { engine = FlutterEngine(ctx) + FlutterEngineCache.getInstance().put(BackgroundWorkerApiImpl.ENGINE_CACHE_KEY, engine!!) // Register custom plugins MainActivity.registerPlugins(ctx, engine!!) @@ -82,6 +110,34 @@ class BackgroundWorker(context: Context, params: WorkerParameters) : flutterApi?.onAndroidUpload { handleHostResult(it) } } + // TODO: Move this to a separate NotificationManager class + private fun showNotification(title: String, content: String) { + val notification = NotificationCompat.Builder(applicationContext, NOTIFICATION_CHANNEL_ID) + .setSmallIcon(R.drawable.notification_icon) + .setOnlyAlertOnce(true) + .setOngoing(true) + .setTicker(title) + .setContentTitle(title) + .setContentText(content) + .build() + + if (isIgnoringBatteryOptimizations()) { + foregroundFuture = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + setForegroundAsync( + ForegroundInfo( + NOTIFICATION_ID, + notification, + FOREGROUND_SERVICE_TYPE_DATA_SYNC + ) + ) + } else { + setForegroundAsync(ForegroundInfo(NOTIFICATION_ID, notification)) + } + } else { + notificationManager.notify(NOTIFICATION_ID, notification) + } + } + override fun close() { if (isComplete) { return @@ -95,6 +151,8 @@ class BackgroundWorker(context: Context, params: WorkerParameters) : } } + waitForForegroundPromotion() + Handler(Looper.getMainLooper()).postDelayed({ complete(Result.failure()) }, 5000) @@ -135,6 +193,33 @@ class BackgroundWorker(context: Context, params: WorkerParameters) : engine?.destroy() engine = null flutterApi = null + notificationManager.cancel(NOTIFICATION_ID) + FlutterEngineCache.getInstance().remove(BackgroundWorkerApiImpl.ENGINE_CACHE_KEY) + waitForForegroundPromotion() completionHandler.set(success) } + + /** + * Returns `true` if the app is ignoring battery optimizations + */ + private fun isIgnoringBatteryOptimizations(): Boolean { + val powerManager = ctx.getSystemService(Context.POWER_SERVICE) as PowerManager + return powerManager.isIgnoringBatteryOptimizations(ctx.packageName) + } + + /** + * Calls to setForegroundAsync() that do not complete before completion of a ListenableWorker will signal an IllegalStateException + * https://android-review.googlesource.com/c/platform/frameworks/support/+/1262743 + * Wait for a short period of time for the foreground promotion to complete before completing the worker + */ + private fun waitForForegroundPromotion() { + val foregroundFuture = this.foregroundFuture + if (foregroundFuture != null && !foregroundFuture.isCancelled && !foregroundFuture.isDone) { + try { + foregroundFuture.get(500, TimeUnit.MILLISECONDS) + } catch (e: Exception) { + // ignored, there is nothing to be done + } + } + } } diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorkerApiImpl.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorkerApiImpl.kt index 4c2d98be71..a78db3c5ea 100644 --- a/mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorkerApiImpl.kt +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorkerApiImpl.kt @@ -8,9 +8,10 @@ import androidx.work.Constraints import androidx.work.ExistingWorkPolicy import androidx.work.OneTimeWorkRequest import androidx.work.WorkManager +import io.flutter.embedding.engine.FlutterEngineCache import java.util.concurrent.TimeUnit -private const val TAG = "BackgroundUploadImpl" +private const val TAG = "BackgroundWorkerApiImpl" class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi { private val ctx: Context = context.applicationContext @@ -19,25 +20,40 @@ class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi { enqueueMediaObserver(ctx) } + override fun saveNotificationMessage(title: String, body: String) { + BackgroundWorkerPreferences(ctx).updateNotificationConfig(title, body) + } + + override fun configure(settings: BackgroundWorkerSettings) { + BackgroundWorkerPreferences(ctx).updateSettings(settings) + enqueueMediaObserver(ctx) + } + override fun disable() { - WorkManager.getInstance(ctx).cancelUniqueWork(OBSERVER_WORKER_NAME) - WorkManager.getInstance(ctx).cancelUniqueWork(BACKGROUND_WORKER_NAME) + WorkManager.getInstance(ctx).apply { + cancelUniqueWork(OBSERVER_WORKER_NAME) + cancelUniqueWork(BACKGROUND_WORKER_NAME) + } Log.i(TAG, "Cancelled background upload tasks") } companion object { private const val BACKGROUND_WORKER_NAME = "immich/BackgroundWorkerV1" private const val OBSERVER_WORKER_NAME = "immich/MediaObserverV1" + const val ENGINE_CACHE_KEY = "immich::background_worker::engine" + fun enqueueMediaObserver(ctx: Context) { - val constraints = Constraints.Builder() - .addContentUriTrigger(MediaStore.Images.Media.INTERNAL_CONTENT_URI, true) - .addContentUriTrigger(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true) - .addContentUriTrigger(MediaStore.Video.Media.INTERNAL_CONTENT_URI, true) - .addContentUriTrigger(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, true) - .setTriggerContentUpdateDelay(30, TimeUnit.SECONDS) - .setTriggerContentMaxDelay(3, TimeUnit.MINUTES) - .build() + val settings = BackgroundWorkerPreferences(ctx).getSettings() + val constraints = Constraints.Builder().apply { + addContentUriTrigger(MediaStore.Images.Media.INTERNAL_CONTENT_URI, true) + addContentUriTrigger(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true) + addContentUriTrigger(MediaStore.Video.Media.INTERNAL_CONTENT_URI, true) + addContentUriTrigger(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, true) + setTriggerContentUpdateDelay(settings.minimumDelaySeconds, TimeUnit.SECONDS) + setTriggerContentMaxDelay(settings.minimumDelaySeconds * 10, TimeUnit.SECONDS) + setRequiresCharging(settings.requiresCharging) + }.build() val work = OneTimeWorkRequest.Builder(MediaObserver::class.java) .setConstraints(constraints) @@ -45,7 +61,10 @@ class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi { WorkManager.getInstance(ctx) .enqueueUniqueWork(OBSERVER_WORKER_NAME, ExistingWorkPolicy.REPLACE, work) - Log.i(TAG, "Enqueued media observer worker with name: $OBSERVER_WORKER_NAME") + Log.i( + TAG, + "Enqueued media observer worker with name: $OBSERVER_WORKER_NAME and settings: $settings" + ) } fun enqueueBackgroundWorker(ctx: Context) { @@ -56,9 +75,22 @@ class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi { .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES) .build() WorkManager.getInstance(ctx) - .enqueueUniqueWork(BACKGROUND_WORKER_NAME, ExistingWorkPolicy.REPLACE, work) + .enqueueUniqueWork(BACKGROUND_WORKER_NAME, ExistingWorkPolicy.KEEP, work) Log.i(TAG, "Enqueued background worker with name: $BACKGROUND_WORKER_NAME") } + + fun isBackgroundWorkerRunning(): Boolean { + // Easier to check if the engine is cached as we always cache the engine when starting the worker + // and remove it when the worker is finished + return FlutterEngineCache.getInstance().get(ENGINE_CACHE_KEY) != null + } + + fun cancelBackgroundWorker(ctx: Context) { + WorkManager.getInstance(ctx).cancelUniqueWork(BACKGROUND_WORKER_NAME) + FlutterEngineCache.getInstance().remove(ENGINE_CACHE_KEY) + + Log.i(TAG, "Cancelled background upload task") + } } } diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorkerLock.g.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorkerLock.g.kt new file mode 100644 index 0000000000..3d00bafba2 --- /dev/null +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorkerLock.g.kt @@ -0,0 +1,95 @@ +// Autogenerated from Pigeon (v26.0.0), do not edit directly. +// See also: https://pub.dev/packages/pigeon +@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") + +package app.alextran.immich.background + +import android.util.Log +import io.flutter.plugin.common.BasicMessageChannel +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.EventChannel +import io.flutter.plugin.common.MessageCodec +import io.flutter.plugin.common.StandardMethodCodec +import io.flutter.plugin.common.StandardMessageCodec +import java.io.ByteArrayOutputStream +import java.nio.ByteBuffer +private object BackgroundWorkerLockPigeonUtils { + + fun wrapResult(result: Any?): List { + return listOf(result) + } + + fun wrapError(exception: Throwable): List { + return if (exception is FlutterError) { + listOf( + exception.code, + exception.message, + exception.details + ) + } else { + listOf( + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) + ) + } + } +} +private open class BackgroundWorkerLockPigeonCodec : StandardMessageCodec() { + override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { + return super.readValueOfType(type, buffer) + } + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + super.writeValue(stream, value) + } +} + +/** Generated interface from Pigeon that represents a handler of messages from Flutter. */ +interface BackgroundWorkerLockApi { + fun lock() + fun unlock() + + companion object { + /** The codec used by BackgroundWorkerLockApi. */ + val codec: MessageCodec by lazy { + BackgroundWorkerLockPigeonCodec() + } + /** Sets up an instance of `BackgroundWorkerLockApi` to handle messages through the `binaryMessenger`. */ + @JvmOverloads + fun setUp(binaryMessenger: BinaryMessenger, api: BackgroundWorkerLockApi?, messageChannelSuffix: String = "") { + val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerLockApi.lock$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { _, reply -> + val wrapped: List = try { + api.lock() + listOf(null) + } catch (exception: Throwable) { + BackgroundWorkerLockPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerLockApi.unlock$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { _, reply -> + val wrapped: List = try { + api.unlock() + listOf(null) + } catch (exception: Throwable) { + BackgroundWorkerLockPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + } + } +} diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorkerPreferences.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorkerPreferences.kt new file mode 100644 index 0000000000..450113e5b0 --- /dev/null +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorkerPreferences.kt @@ -0,0 +1,69 @@ +package app.alextran.immich.background + +import android.content.Context +import android.content.SharedPreferences +import androidx.core.content.edit + +class BackgroundWorkerPreferences(private val ctx: Context) { + companion object { + const val SHARED_PREF_NAME = "Immich::BackgroundWorker" + private const val SHARED_PREF_MIN_DELAY_KEY = "BackgroundWorker::minDelaySeconds" + private const val SHARED_PREF_REQUIRE_CHARGING_KEY = "BackgroundWorker::requireCharging" + private const val SHARED_PREF_LOCK_KEY = "BackgroundWorker::isLocked" + private const val SHARED_PREF_NOTIF_TITLE_KEY = "BackgroundWorker::notificationTitle" + private const val SHARED_PREF_NOTIF_MSG_KEY = "BackgroundWorker::notificationMessage" + + private const val DEFAULT_MIN_DELAY_SECONDS = 30L + private const val DEFAULT_REQUIRE_CHARGING = false + private const val DEFAULT_NOTIF_TITLE = "Uploading media" + private const val DEFAULT_NOTIF_MSG = "Checking for new assetsâ€Ļ" + } + + private val sp: SharedPreferences by lazy { + ctx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE) + } + + fun updateSettings(settings: BackgroundWorkerSettings) { + sp.edit { + putLong(SHARED_PREF_MIN_DELAY_KEY, settings.minimumDelaySeconds) + putBoolean(SHARED_PREF_REQUIRE_CHARGING_KEY, settings.requiresCharging) + } + } + + fun getSettings(): BackgroundWorkerSettings { + val delaySeconds = sp.getLong(SHARED_PREF_MIN_DELAY_KEY, DEFAULT_MIN_DELAY_SECONDS) + + return BackgroundWorkerSettings( + minimumDelaySeconds = if (delaySeconds >= 1000) delaySeconds / 1000 else delaySeconds, + requiresCharging = sp.getBoolean( + SHARED_PREF_REQUIRE_CHARGING_KEY, + DEFAULT_REQUIRE_CHARGING + ), + ) + } + + fun updateNotificationConfig(title: String, message: String) { + sp.edit { + putString(SHARED_PREF_NOTIF_TITLE_KEY, title) + putString(SHARED_PREF_NOTIF_MSG_KEY, message) + } + } + + fun getNotificationConfig(): Pair { + val title = + sp.getString(SHARED_PREF_NOTIF_TITLE_KEY, DEFAULT_NOTIF_TITLE) ?: DEFAULT_NOTIF_TITLE + val message = sp.getString(SHARED_PREF_NOTIF_MSG_KEY, DEFAULT_NOTIF_MSG) ?: DEFAULT_NOTIF_MSG + return Pair(title, message) + } + + fun setLocked(paused: Boolean) { + sp.edit { + putBoolean(SHARED_PREF_LOCK_KEY, paused) + } + } + + fun isLocked(): Boolean { + return sp.getBoolean(SHARED_PREF_LOCK_KEY, true) + } +} + diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/connectivity/Connectivity.g.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/connectivity/Connectivity.g.kt new file mode 100644 index 0000000000..434ba47ca1 --- /dev/null +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/connectivity/Connectivity.g.kt @@ -0,0 +1,116 @@ +// Autogenerated from Pigeon (v26.0.0), do not edit directly. +// See also: https://pub.dev/packages/pigeon +@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") + +package app.alextran.immich.connectivity + +import android.util.Log +import io.flutter.plugin.common.BasicMessageChannel +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.EventChannel +import io.flutter.plugin.common.MessageCodec +import io.flutter.plugin.common.StandardMethodCodec +import io.flutter.plugin.common.StandardMessageCodec +import java.io.ByteArrayOutputStream +import java.nio.ByteBuffer +private object ConnectivityPigeonUtils { + + fun wrapResult(result: Any?): List { + return listOf(result) + } + + fun wrapError(exception: Throwable): List { + return if (exception is FlutterError) { + listOf( + exception.code, + exception.message, + exception.details + ) + } else { + listOf( + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) + ) + } + } +} + +/** + * Error class for passing custom error details to Flutter via a thrown PlatformException. + * @property code The error code. + * @property message The error message. + * @property details The error details. Must be a datatype supported by the api codec. + */ +class FlutterError ( + val code: String, + override val message: String? = null, + val details: Any? = null +) : Throwable() + +enum class NetworkCapability(val raw: Int) { + CELLULAR(0), + WIFI(1), + VPN(2), + UNMETERED(3); + + companion object { + fun ofRaw(raw: Int): NetworkCapability? { + return values().firstOrNull { it.raw == raw } + } + } +} +private open class ConnectivityPigeonCodec : StandardMessageCodec() { + override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { + return when (type) { + 129.toByte() -> { + return (readValue(buffer) as Long?)?.let { + NetworkCapability.ofRaw(it.toInt()) + } + } + else -> super.readValueOfType(type, buffer) + } + } + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + when (value) { + is NetworkCapability -> { + stream.write(129) + writeValue(stream, value.raw) + } + else -> super.writeValue(stream, value) + } + } +} + +/** Generated interface from Pigeon that represents a handler of messages from Flutter. */ +interface ConnectivityApi { + fun getCapabilities(): List + + companion object { + /** The codec used by ConnectivityApi. */ + val codec: MessageCodec by lazy { + ConnectivityPigeonCodec() + } + /** Sets up an instance of `ConnectivityApi` to handle messages through the `binaryMessenger`. */ + @JvmOverloads + fun setUp(binaryMessenger: BinaryMessenger, api: ConnectivityApi?, messageChannelSuffix: String = "") { + val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" + val taskQueue = binaryMessenger.makeBackgroundTaskQueue() + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.immich_mobile.ConnectivityApi.getCapabilities$separatedMessageChannelSuffix", codec, taskQueue) + if (api != null) { + channel.setMessageHandler { _, reply -> + val wrapped: List = try { + listOf(api.getCapabilities()) + } catch (exception: Throwable) { + ConnectivityPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + } + } +} diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/connectivity/ConnectivityApiImpl.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/connectivity/ConnectivityApiImpl.kt new file mode 100644 index 0000000000..e8554dd63a --- /dev/null +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/connectivity/ConnectivityApiImpl.kt @@ -0,0 +1,39 @@ +package app.alextran.immich.connectivity + +import android.content.Context +import android.net.ConnectivityManager +import android.net.NetworkCapabilities +import android.net.wifi.WifiManager + +class ConnectivityApiImpl(context: Context) : ConnectivityApi { + private val connectivityManager = + context.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + private val wifiManager = + context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager + + override fun getCapabilities(): List { + val capabilities = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork) + ?: return emptyList() + + val hasWifi = capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || + capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI_AWARE) + val hasCellular = capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) + val hasVpn = capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN) + val isUnmetered = capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) + + return buildList { + if (hasWifi) add(NetworkCapability.WIFI) + if (hasCellular) add(NetworkCapability.CELLULAR) + if (hasVpn) { + add(NetworkCapability.VPN) + if (!hasWifi && !hasCellular) { + if (wifiManager.isWifiEnabled) add(NetworkCapability.WIFI) + // If VPN is active, but neither WIFI nor CELLULAR is reported as active, + // assume CELLULAR if WIFI is not enabled + else add(NetworkCapability.CELLULAR) + } + } + if (isUnmetered) add(NetworkCapability.UNMETERED) + } + } +} diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/images/ThumbnailsImpl.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/images/ThumbnailsImpl.kt index 1b1716f55c..a9d602c19c 100644 --- a/mobile/android/app/src/main/kotlin/app/alextran/immich/images/ThumbnailsImpl.kt +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/images/ThumbnailsImpl.kt @@ -8,7 +8,6 @@ import android.net.Uri import android.os.Build import android.os.CancellationSignal import android.os.OperationCanceledException -import android.provider.MediaStore import android.provider.MediaStore.Images import android.provider.MediaStore.Video import android.util.Size @@ -18,8 +17,8 @@ import java.util.concurrent.Executors import com.bumptech.glide.Glide import com.bumptech.glide.Priority import com.bumptech.glide.load.DecodeFormat +import com.bumptech.glide.request.target.Target.SIZE_ORIGINAL import java.util.Base64 -import java.util.HashMap import java.util.concurrent.CancellationException import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.Future @@ -122,15 +121,14 @@ class ThumbnailsImpl(context: Context) : ThumbnailApi { signal: CancellationSignal ) { signal.throwIfCanceled() - val targetWidth = width.toInt() - val targetHeight = height.toInt() + val size = Size(width.toInt(), height.toInt()) val id = assetId.toLong() signal.throwIfCanceled() val bitmap = if (isVideo) { - decodeVideoThumbnail(id, targetWidth, targetHeight, signal) + decodeVideoThumbnail(id, size, signal) } else { - decodeImage(id, targetWidth, targetHeight, signal) + decodeImage(id, size, signal) } processBitmap(bitmap, callback, signal) @@ -153,9 +151,7 @@ class ThumbnailsImpl(context: Context) : ThumbnailApi { bitmap.recycle() signal.throwIfCanceled() val res = mapOf( - "pointer" to pointer, - "width" to actualWidth.toLong(), - "height" to actualHeight.toLong() + "pointer" to pointer, "width" to actualWidth.toLong(), "height" to actualHeight.toLong() ) callback(Result.success(res)) } catch (e: Exception) { @@ -164,53 +160,54 @@ class ThumbnailsImpl(context: Context) : ThumbnailApi { } } - private fun decodeImage( - id: Long, targetWidth: Int, targetHeight: Int, signal: CancellationSignal - ): Bitmap { + private fun decodeImage(id: Long, size: Size, signal: CancellationSignal): Bitmap { signal.throwIfCanceled() val uri = ContentUris.withAppendedId(Images.Media.EXTERNAL_CONTENT_URI, id) - if (targetHeight > 768 || targetWidth > 768) { - return decodeSource(uri, targetWidth, targetHeight, signal) + if (size.width <= 0 || size.height <= 0 || size.width > 768 || size.height > 768) { + return decodeSource(uri, size, signal) } return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - resolver.loadThumbnail(uri, Size(targetWidth, targetHeight), signal) + resolver.loadThumbnail(uri, size, signal) } else { signal.setOnCancelListener { Images.Thumbnails.cancelThumbnailRequest(resolver, id) } Images.Thumbnails.getThumbnail(resolver, id, Images.Thumbnails.MINI_KIND, OPTIONS) } } - private fun decodeVideoThumbnail( - id: Long, targetWidth: Int, targetHeight: Int, signal: CancellationSignal - ): Bitmap { + private fun decodeVideoThumbnail(id: Long, target: Size, signal: CancellationSignal): Bitmap { signal.throwIfCanceled() return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { val uri = ContentUris.withAppendedId(Video.Media.EXTERNAL_CONTENT_URI, id) - resolver.loadThumbnail(uri, Size(targetWidth, targetHeight), signal) + // ensure a valid resolution as the thumbnail is used for videos even when no scaling is needed + val size = if (target.width > 0 && target.height > 0) target else Size(768, 768) + resolver.loadThumbnail(uri, size, signal) } else { signal.setOnCancelListener { Video.Thumbnails.cancelThumbnailRequest(resolver, id) } Video.Thumbnails.getThumbnail(resolver, id, Video.Thumbnails.MINI_KIND, OPTIONS) } } - private fun decodeSource( - uri: Uri, targetWidth: Int, targetHeight: Int, signal: CancellationSignal - ): Bitmap { + private fun decodeSource(uri: Uri, target: Size, signal: CancellationSignal): Bitmap { signal.throwIfCanceled() return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { val source = ImageDecoder.createSource(resolver, uri) signal.throwIfCanceled() ImageDecoder.decodeBitmap(source) { decoder, info, _ -> - val sampleSize = max(1, min(info.size.width / targetWidth, info.size.height / targetHeight)) - decoder.setTargetSampleSize(sampleSize) + if (target.width > 0 && target.height > 0) { + val sample = max(1, min(info.size.width / target.width, info.size.height / target.height)) + decoder.setTargetSampleSize(sample) + } decoder.allocator = ImageDecoder.ALLOCATOR_SOFTWARE decoder.setTargetColorSpace(ColorSpace.get(ColorSpace.Named.SRGB)) } } else { - val ref = Glide.with(ctx).asBitmap().priority(Priority.IMMEDIATE).load(uri) - .disallowHardwareConfig().format(DecodeFormat.PREFER_ARGB_8888) - .submit(targetWidth, targetHeight) + val ref = + Glide.with(ctx).asBitmap().priority(Priority.IMMEDIATE).load(uri).disallowHardwareConfig() + .format(DecodeFormat.PREFER_ARGB_8888).submit( + if (target.width > 0) target.width else SIZE_ORIGINAL, + if (target.height > 0) target.height else SIZE_ORIGINAL, + ) signal.setOnCancelListener { Glide.with(ctx).clear(ref) } ref.get() } diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/sync/Messages.g.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/sync/Messages.g.kt index 9c618d9ed0..28400c803f 100644 --- a/mobile/android/app/src/main/kotlin/app/alextran/immich/sync/Messages.g.kt +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/sync/Messages.g.kt @@ -209,6 +209,40 @@ data class SyncDelta ( override fun hashCode(): Int = toList().hashCode() } + +/** Generated class from Pigeon that represents data sent in messages. */ +data class HashResult ( + val assetId: String, + val error: String? = null, + val hash: String? = null +) + { + companion object { + fun fromList(pigeonVar_list: List): HashResult { + val assetId = pigeonVar_list[0] as String + val error = pigeonVar_list[1] as String? + val hash = pigeonVar_list[2] as String? + return HashResult(assetId, error, hash) + } + } + fun toList(): List { + return listOf( + assetId, + error, + hash, + ) + } + override fun equals(other: Any?): Boolean { + if (other !is HashResult) { + return false + } + if (this === other) { + return true + } + return MessagesPigeonUtils.deepEquals(toList(), other.toList()) } + + override fun hashCode(): Int = toList().hashCode() +} private open class MessagesPigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { return when (type) { @@ -227,6 +261,11 @@ private open class MessagesPigeonCodec : StandardMessageCodec() { SyncDelta.fromList(it) } } + 132.toByte() -> { + return (readValue(buffer) as? List)?.let { + HashResult.fromList(it) + } + } else -> super.readValueOfType(type, buffer) } } @@ -244,11 +283,16 @@ private open class MessagesPigeonCodec : StandardMessageCodec() { stream.write(131) writeValue(stream, value.toList()) } + is HashResult -> { + stream.write(132) + writeValue(stream, value.toList()) + } else -> super.writeValue(stream, value) } } } + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ interface NativeSyncApi { fun shouldFullSync(): Boolean @@ -259,7 +303,8 @@ interface NativeSyncApi { fun getAlbums(): List fun getAssetsCountSince(albumId: String, timestamp: Long): Long fun getAssetsForAlbum(albumId: String, updatedTimeCond: Long?): List - fun hashPaths(paths: List): List + fun hashAssets(assetIds: List, allowNetworkAccess: Boolean, callback: (Result>) -> Unit) + fun cancelHashing() companion object { /** The codec used by NativeSyncApi. */ @@ -402,13 +447,33 @@ interface NativeSyncApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.hashPaths$separatedMessageChannelSuffix", codec, taskQueue) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.hashAssets$separatedMessageChannelSuffix", codec, taskQueue) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List - val pathsArg = args[0] as List + val assetIdsArg = args[0] as List + val allowNetworkAccessArg = args[1] as Boolean + api.hashAssets(assetIdsArg, allowNetworkAccessArg) { result: Result> -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(MessagesPigeonUtils.wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(MessagesPigeonUtils.wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NativeSyncApi.cancelHashing$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { _, reply -> val wrapped: List = try { - listOf(api.hashPaths(pathsArg)) + api.cancelHashing() + listOf(null) } catch (exception: Throwable) { MessagesPigeonUtils.wrapError(exception) } diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/sync/MessagesImplBase.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/sync/MessagesImplBase.kt index b2ceb8a9f2..868f3c6cdd 100644 --- a/mobile/android/app/src/main/kotlin/app/alextran/immich/sync/MessagesImplBase.kt +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/sync/MessagesImplBase.kt @@ -1,14 +1,25 @@ package app.alextran.immich.sync import android.annotation.SuppressLint +import android.content.ContentUris import android.content.Context import android.database.Cursor import android.provider.MediaStore -import android.util.Log +import android.util.Base64 import androidx.core.database.getStringOrNull +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.ensureActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.sync.Semaphore +import kotlinx.coroutines.sync.withPermit import java.io.File -import java.io.FileInputStream import java.security.MessageDigest +import kotlin.coroutines.cancellation.CancellationException +import kotlin.coroutines.coroutineContext sealed class AssetResult { data class ValidAsset(val asset: PlatformAsset, val albumId: String) : AssetResult() @@ -19,8 +30,12 @@ sealed class AssetResult { open class NativeSyncApiImplBase(context: Context) { private val ctx: Context = context.applicationContext + private var hashTask: Job? = null + companion object { - private const val TAG = "NativeSyncApiImplBase" + private const val MAX_CONCURRENT_HASH_OPERATIONS = 16 + private val hashSemaphore = Semaphore(MAX_CONCURRENT_HASH_OPERATIONS) + private const val HASHING_CANCELLED_CODE = "HASH_CANCELLED" const val MEDIA_SELECTION = "(${MediaStore.Files.FileColumns.MEDIA_TYPE} = ? OR ${MediaStore.Files.FileColumns.MEDIA_TYPE} = ?)" @@ -215,23 +230,74 @@ open class NativeSyncApiImplBase(context: Context) { .toList() } - fun hashPaths(paths: List): List { - val buffer = ByteArray(HASH_BUFFER_SIZE) - val digest = MessageDigest.getInstance("SHA-1") + fun hashAssets( + assetIds: List, + // allowNetworkAccess is only used on the iOS implementation + @Suppress("UNUSED_PARAMETER") allowNetworkAccess: Boolean, + callback: (Result>) -> Unit + ) { + if (assetIds.isEmpty()) { + callback(Result.success(emptyList())) + return + } - return paths.map { path -> + hashTask?.cancel() + hashTask = CoroutineScope(Dispatchers.IO).launch { try { - FileInputStream(path).use { file -> - var bytesRead: Int - while (file.read(buffer).also { bytesRead = it } > 0) { - digest.update(buffer, 0, bytesRead) + val results = assetIds.map { assetId -> + async { + hashSemaphore.withPermit { + ensureActive() + hashAsset(assetId) + } } - } - digest.digest() + }.awaitAll() + + callback(Result.success(results)) + } catch (e: CancellationException) { + callback( + Result.failure( + FlutterError( + HASHING_CANCELLED_CODE, + "Hashing operation was cancelled", + null + ) + ) + ) } catch (e: Exception) { - Log.w(TAG, "Failed to hash file $path: $e") - null + callback(Result.failure(e)) } } } + + private suspend fun hashAsset(assetId: String): HashResult { + return try { + val assetUri = ContentUris.withAppendedId( + MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL), + assetId.toLong() + ) + + val digest = MessageDigest.getInstance("SHA-1") + ctx.contentResolver.openInputStream(assetUri)?.use { inputStream -> + var bytesRead: Int + val buffer = ByteArray(HASH_BUFFER_SIZE) + while (inputStream.read(buffer).also { bytesRead = it } > 0) { + coroutineContext.ensureActive() + digest.update(buffer, 0, bytesRead) + } + } ?: return HashResult(assetId, "Cannot open input stream for asset", null) + + val hashString = Base64.encodeToString(digest.digest(), Base64.NO_WRAP) + HashResult(assetId, null, hashString) + } catch (e: SecurityException) { + HashResult(assetId, "Permission denied accessing asset: ${e.message}", null) + } catch (e: Exception) { + HashResult(assetId, "Failed to hash asset: ${e.message}", null) + } + } + + fun cancelHashing() { + hashTask?.cancel() + hashTask = null + } } diff --git a/mobile/android/build.gradle b/mobile/android/build.gradle index bcf3daa1c8..719c946bd6 100644 --- a/mobile/android/build.gradle +++ b/mobile/android/build.gradle @@ -1,5 +1,5 @@ allprojects { - ext.kotlin_version = '2.0.20' + ext.kotlin_version = '2.2.20' repositories { google() @@ -16,8 +16,8 @@ subprojects { if (project.plugins.hasPlugin("com.android.application") || project.plugins.hasPlugin("com.android.library")) { project.android { - compileSdkVersion 35 - buildToolsVersion "35.0.0" + compileSdkVersion 36 + buildToolsVersion "36.0.0" } } } diff --git a/mobile/android/fastlane/Fastfile b/mobile/android/fastlane/Fastfile index 9375b599fa..4c1df0d700 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" => 3013, - "android.injected.version.name" => "1.141.1", + "android.injected.version.code" => 3022, + "android.injected.version.name" => "2.1.0", } ) 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/android/gradle/wrapper/gradle-wrapper.properties b/mobile/android/gradle/wrapper/gradle-wrapper.properties index dedd5d1e69..ed4c299adb 100644 --- a/mobile/android/gradle/wrapper/gradle-wrapper.properties +++ b/mobile/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/mobile/android/settings.gradle b/mobile/android/settings.gradle index 29c3a7c056..fbed55a3e3 100644 --- a/mobile/android/settings.gradle +++ b/mobile/android/settings.gradle @@ -18,10 +18,10 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version '8.7.2' apply false - id "org.jetbrains.kotlin.android" version "2.0.20" apply false + id "com.android.application" version '8.11.2' apply false + id "org.jetbrains.kotlin.android" version "2.2.20" apply false id 'org.jetbrains.kotlin.plugin.serialization' version '1.9.22' apply false - id 'com.google.devtools.ksp' version '2.0.20-1.0.24' apply false + id 'com.google.devtools.ksp' version '2.2.20-2.0.3' apply false } include ":app" diff --git a/mobile/drift_schemas/main/drift_schema_v10.json b/mobile/drift_schemas/main/drift_schema_v10.json new file mode 100644 index 0000000000..aba030da04 --- /dev/null +++ b/mobile/drift_schemas/main/drift_schema_v10.json @@ -0,0 +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":"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":"email","getter_name":"email","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"has_profile_image","getter_name":"hasProfileImage","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"has_profile_image\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"has_profile_image\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"profile_changed_at","getter_name":"profileChangedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"avatar_color","getter_name":"avatarColor","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AvatarColor.values)","dart_type_name":"AvatarColor"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":1,"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":"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":[]},{"name":"duration_in_seconds","getter_name":"durationInSeconds","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"id","getter_name":"id","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":false,"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":[]},{"name":"owner_id","getter_name":"ownerId","moor_type":"string","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":"thumb_hash","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":[]},{"name":"live_photo_video_id","getter_name":"livePhotoVideoId","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"visibility","getter_name":"visibility","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AssetVisibility.values)","dart_type_name":"AssetVisibility"}},{"name":"stack_id","getter_name":"stackId","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"library_id","getter_name":"libraryId","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":["id"]}},{"id":2,"references":[0],"type":"table","data":{"name":"stack_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":"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":"owner_id","getter_name":"ownerId","moor_type":"string","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":"primary_asset_id","getter_name":"primaryAssetId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["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":"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":[]},{"name":"duration_in_seconds","getter_name":"durationInSeconds","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"id","getter_name":"id","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":[]},{"name":"orientation","getter_name":"orientation","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":4,"references":[0,1],"type":"table","data":{"name":"remote_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":"description","getter_name":"description","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('\\'\\'')","default_client_dart":null,"dsl_features":[]},{"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":"owner_id","getter_name":"ownerId","moor_type":"string","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":"thumbnail_asset_id","getter_name":"thumbnailAssetId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE SET NULL","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (id) ON DELETE SET NULL"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"is_activity_enabled","getter_name":"isActivityEnabled","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_activity_enabled\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_activity_enabled\" IN (0, 1))"},"default_dart":"const CustomExpression('1')","default_client_dart":null,"dsl_features":[]},{"name":"order","getter_name":"order","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AlbumAssetOrder.values)","dart_type_name":"AlbumAssetOrder"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":5,"references":[4],"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":"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_ios_shared_album","getter_name":"isIosSharedAlbum","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_ios_shared_album\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_ios_shared_album\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"linked_remote_album_id","getter_name":"linkedRemoteAlbumId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES remote_album_entity (id) ON DELETE SET NULL","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_album_entity (id) ON DELETE SET NULL"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"marker","getter_name":"marker_","moor_type":"bool","nullable":true,"customConstraints":null,"defaultConstraints":"CHECK (\"marker\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"marker\" IN (0, 1))"},"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":6,"references":[3,5],"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 (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES local_asset_entity (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":7,"references":[3],"type":"index","data":{"on":3,"name":"idx_local_asset_checksum","sql":"CREATE INDEX IF NOT EXISTS idx_local_asset_checksum ON local_asset_entity (checksum)","unique":false,"columns":[]}},{"id":8,"references":[1],"type":"index","data":{"on":1,"name":"idx_remote_asset_owner_checksum","sql":"CREATE INDEX IF NOT EXISTS idx_remote_asset_owner_checksum ON remote_asset_entity (owner_id, checksum)","unique":false,"columns":[]}},{"id":9,"references":[1],"type":"index","data":{"on":1,"name":"UQ_remote_assets_owner_checksum","sql":"CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_checksum\nON remote_asset_entity (owner_id, checksum)\nWHERE (library_id IS NULL);\n","unique":true,"columns":[]}},{"id":10,"references":[1],"type":"index","data":{"on":1,"name":"UQ_remote_assets_owner_library_checksum","sql":"CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_library_checksum\nON remote_asset_entity (owner_id, library_id, checksum)\nWHERE (library_id IS NOT NULL);\n","unique":true,"columns":[]}},{"id":11,"references":[1],"type":"index","data":{"on":1,"name":"idx_remote_asset_checksum","sql":"CREATE INDEX IF NOT EXISTS idx_remote_asset_checksum ON remote_asset_entity (checksum)","unique":false,"columns":[]}},{"id":12,"references":[],"type":"table","data":{"name":"auth_user_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":"email","getter_name":"email","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":"has_profile_image","getter_name":"hasProfileImage","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"has_profile_image\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"has_profile_image\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"profile_changed_at","getter_name":"profileChangedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"avatar_color","getter_name":"avatarColor","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AvatarColor.values)","dart_type_name":"AvatarColor"}},{"name":"quota_size_in_bytes","getter_name":"quotaSizeInBytes","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","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":[]},{"name":"pin_code","getter_name":"pinCode","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":["id"]}},{"id":13,"references":[0],"type":"table","data":{"name":"user_metadata_entity","was_declared_in_moor":false,"columns":[{"name":"user_id","getter_name":"userId","moor_type":"string","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":"key","getter_name":"key","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(UserMetadataKey.values)","dart_type_name":"UserMetadataKey"}},{"name":"value","getter_name":"value","moor_type":"blob","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"userMetadataConverter","dart_type_name":"Map"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["user_id","key"]}},{"id":14,"references":[0],"type":"table","data":{"name":"partner_entity","was_declared_in_moor":false,"columns":[{"name":"shared_by_id","getter_name":"sharedById","moor_type":"string","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":"string","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":15,"references":[1],"type":"table","data":{"name":"remote_exif_entity","was_declared_in_moor":false,"columns":[{"name":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (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":"double","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":"double","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"latitude","getter_name":"latitude","moor_type":"double","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"longitude","getter_name":"longitude","moor_type":"double","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":"lens","getter_name":"lens","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":16,"references":[1,4],"type":"table","data":{"name":"remote_album_asset_entity","was_declared_in_moor":false,"columns":[{"name":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (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 remote_album_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_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":17,"references":[4,0],"type":"table","data":{"name":"remote_album_user_entity","was_declared_in_moor":false,"columns":[{"name":"album_id","getter_name":"albumId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_album_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_album_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"user_id","getter_name":"userId","moor_type":"string","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":"role","getter_name":"role","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AlbumUserRole.values)","dart_type_name":"AlbumUserRole"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["album_id","user_id"]}},{"id":18,"references":[0],"type":"table","data":{"name":"memory_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":"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":"deleted_at","getter_name":"deletedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"owner_id","getter_name":"ownerId","moor_type":"string","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":"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(MemoryTypeEnum.values)","dart_type_name":"MemoryTypeEnum"}},{"name":"data","getter_name":"data","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_saved","getter_name":"isSaved","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_saved\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_saved\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"memory_at","getter_name":"memoryAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"seen_at","getter_name":"seenAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"show_at","getter_name":"showAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"hide_at","getter_name":"hideAt","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":["id"]}},{"id":19,"references":[1,18],"type":"table","data":{"name":"memory_asset_entity","was_declared_in_moor":false,"columns":[{"name":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"memory_id","getter_name":"memoryId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES memory_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES memory_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","memory_id"]}},{"id":20,"references":[0],"type":"table","data":{"name":"person_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":"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":"owner_id","getter_name":"ownerId","moor_type":"string","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":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"face_asset_id","getter_name":"faceAssetId","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":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_hidden","getter_name":"isHidden","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_hidden\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_hidden\" IN (0, 1))"},"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"color","getter_name":"color","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"birth_date","getter_name":"birthDate","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":["id"]}},{"id":21,"references":[1,20],"type":"table","data":{"name":"asset_face_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":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"person_id","getter_name":"personId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES person_entity (id) ON DELETE SET NULL","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES person_entity (id) ON DELETE SET NULL"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"image_width","getter_name":"imageWidth","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"image_height","getter_name":"imageHeight","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"bounding_box_x1","getter_name":"boundingBoxX1","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"bounding_box_y1","getter_name":"boundingBoxY1","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"bounding_box_x2","getter_name":"boundingBoxX2","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"bounding_box_y2","getter_name":"boundingBoxY2","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"source_type","getter_name":"sourceType","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":22,"references":[],"type":"table","data":{"name":"store_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"string_value","getter_name":"stringValue","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"int_value","getter_name":"intValue","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":["id"]}},{"id":23,"references":[15],"type":"index","data":{"on":15,"name":"idx_lat_lng","sql":"CREATE INDEX IF NOT EXISTS idx_lat_lng ON remote_exif_entity (latitude, longitude)","unique":false,"columns":[]}}]} \ No newline at end of file diff --git a/mobile/drift_schemas/main/drift_schema_v11.json b/mobile/drift_schemas/main/drift_schema_v11.json new file mode 100644 index 0000000000..1c100ab37f --- /dev/null +++ b/mobile/drift_schemas/main/drift_schema_v11.json @@ -0,0 +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":"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":"email","getter_name":"email","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"has_profile_image","getter_name":"hasProfileImage","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"has_profile_image\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"has_profile_image\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"profile_changed_at","getter_name":"profileChangedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"avatar_color","getter_name":"avatarColor","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AvatarColor.values)","dart_type_name":"AvatarColor"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":1,"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":"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":[]},{"name":"duration_in_seconds","getter_name":"durationInSeconds","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"id","getter_name":"id","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":false,"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":[]},{"name":"owner_id","getter_name":"ownerId","moor_type":"string","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":"thumb_hash","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":[]},{"name":"live_photo_video_id","getter_name":"livePhotoVideoId","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"visibility","getter_name":"visibility","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AssetVisibility.values)","dart_type_name":"AssetVisibility"}},{"name":"stack_id","getter_name":"stackId","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"library_id","getter_name":"libraryId","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":["id"]}},{"id":2,"references":[0],"type":"table","data":{"name":"stack_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":"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":"owner_id","getter_name":"ownerId","moor_type":"string","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":"primary_asset_id","getter_name":"primaryAssetId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["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":"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":[]},{"name":"duration_in_seconds","getter_name":"durationInSeconds","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"id","getter_name":"id","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":[]},{"name":"orientation","getter_name":"orientation","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":4,"references":[0,1],"type":"table","data":{"name":"remote_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":"description","getter_name":"description","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('\\'\\'')","default_client_dart":null,"dsl_features":[]},{"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":"owner_id","getter_name":"ownerId","moor_type":"string","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":"thumbnail_asset_id","getter_name":"thumbnailAssetId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE SET NULL","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (id) ON DELETE SET NULL"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"is_activity_enabled","getter_name":"isActivityEnabled","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_activity_enabled\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_activity_enabled\" IN (0, 1))"},"default_dart":"const CustomExpression('1')","default_client_dart":null,"dsl_features":[]},{"name":"order","getter_name":"order","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AlbumAssetOrder.values)","dart_type_name":"AlbumAssetOrder"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":5,"references":[4],"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":"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_ios_shared_album","getter_name":"isIosSharedAlbum","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_ios_shared_album\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_ios_shared_album\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"linked_remote_album_id","getter_name":"linkedRemoteAlbumId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES remote_album_entity (id) ON DELETE SET NULL","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_album_entity (id) ON DELETE SET NULL"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"marker","getter_name":"marker_","moor_type":"bool","nullable":true,"customConstraints":null,"defaultConstraints":"CHECK (\"marker\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"marker\" IN (0, 1))"},"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":6,"references":[3,5],"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 (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES local_asset_entity (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"]},{"name":"marker","getter_name":"marker_","moor_type":"bool","nullable":true,"customConstraints":null,"defaultConstraints":"CHECK (\"marker\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"marker\" IN (0, 1))"},"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["asset_id","album_id"]}},{"id":7,"references":[3],"type":"index","data":{"on":3,"name":"idx_local_asset_checksum","sql":"CREATE INDEX IF NOT EXISTS idx_local_asset_checksum ON local_asset_entity (checksum)","unique":false,"columns":[]}},{"id":8,"references":[1],"type":"index","data":{"on":1,"name":"idx_remote_asset_owner_checksum","sql":"CREATE INDEX IF NOT EXISTS idx_remote_asset_owner_checksum ON remote_asset_entity (owner_id, checksum)","unique":false,"columns":[]}},{"id":9,"references":[1],"type":"index","data":{"on":1,"name":"UQ_remote_assets_owner_checksum","sql":"CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_checksum\nON remote_asset_entity (owner_id, checksum)\nWHERE (library_id IS NULL);\n","unique":true,"columns":[]}},{"id":10,"references":[1],"type":"index","data":{"on":1,"name":"UQ_remote_assets_owner_library_checksum","sql":"CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_library_checksum\nON remote_asset_entity (owner_id, library_id, checksum)\nWHERE (library_id IS NOT NULL);\n","unique":true,"columns":[]}},{"id":11,"references":[1],"type":"index","data":{"on":1,"name":"idx_remote_asset_checksum","sql":"CREATE INDEX IF NOT EXISTS idx_remote_asset_checksum ON remote_asset_entity (checksum)","unique":false,"columns":[]}},{"id":12,"references":[],"type":"table","data":{"name":"auth_user_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":"email","getter_name":"email","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":"has_profile_image","getter_name":"hasProfileImage","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"has_profile_image\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"has_profile_image\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"profile_changed_at","getter_name":"profileChangedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"avatar_color","getter_name":"avatarColor","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AvatarColor.values)","dart_type_name":"AvatarColor"}},{"name":"quota_size_in_bytes","getter_name":"quotaSizeInBytes","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","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":[]},{"name":"pin_code","getter_name":"pinCode","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":["id"]}},{"id":13,"references":[0],"type":"table","data":{"name":"user_metadata_entity","was_declared_in_moor":false,"columns":[{"name":"user_id","getter_name":"userId","moor_type":"string","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":"key","getter_name":"key","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(UserMetadataKey.values)","dart_type_name":"UserMetadataKey"}},{"name":"value","getter_name":"value","moor_type":"blob","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"userMetadataConverter","dart_type_name":"Map"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["user_id","key"]}},{"id":14,"references":[0],"type":"table","data":{"name":"partner_entity","was_declared_in_moor":false,"columns":[{"name":"shared_by_id","getter_name":"sharedById","moor_type":"string","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":"string","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":15,"references":[1],"type":"table","data":{"name":"remote_exif_entity","was_declared_in_moor":false,"columns":[{"name":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (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":"double","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":"double","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"latitude","getter_name":"latitude","moor_type":"double","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"longitude","getter_name":"longitude","moor_type":"double","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":"lens","getter_name":"lens","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":16,"references":[1,4],"type":"table","data":{"name":"remote_album_asset_entity","was_declared_in_moor":false,"columns":[{"name":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (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 remote_album_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_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":17,"references":[4,0],"type":"table","data":{"name":"remote_album_user_entity","was_declared_in_moor":false,"columns":[{"name":"album_id","getter_name":"albumId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_album_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_album_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"user_id","getter_name":"userId","moor_type":"string","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":"role","getter_name":"role","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AlbumUserRole.values)","dart_type_name":"AlbumUserRole"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["album_id","user_id"]}},{"id":18,"references":[0],"type":"table","data":{"name":"memory_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":"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":"deleted_at","getter_name":"deletedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"owner_id","getter_name":"ownerId","moor_type":"string","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":"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(MemoryTypeEnum.values)","dart_type_name":"MemoryTypeEnum"}},{"name":"data","getter_name":"data","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_saved","getter_name":"isSaved","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_saved\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_saved\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"memory_at","getter_name":"memoryAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"seen_at","getter_name":"seenAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"show_at","getter_name":"showAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"hide_at","getter_name":"hideAt","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":["id"]}},{"id":19,"references":[1,18],"type":"table","data":{"name":"memory_asset_entity","was_declared_in_moor":false,"columns":[{"name":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"memory_id","getter_name":"memoryId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES memory_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES memory_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","memory_id"]}},{"id":20,"references":[0],"type":"table","data":{"name":"person_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":"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":"owner_id","getter_name":"ownerId","moor_type":"string","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":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"face_asset_id","getter_name":"faceAssetId","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":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_hidden","getter_name":"isHidden","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_hidden\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_hidden\" IN (0, 1))"},"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"color","getter_name":"color","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"birth_date","getter_name":"birthDate","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":["id"]}},{"id":21,"references":[1,20],"type":"table","data":{"name":"asset_face_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":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"person_id","getter_name":"personId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES person_entity (id) ON DELETE SET NULL","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES person_entity (id) ON DELETE SET NULL"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"image_width","getter_name":"imageWidth","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"image_height","getter_name":"imageHeight","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"bounding_box_x1","getter_name":"boundingBoxX1","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"bounding_box_y1","getter_name":"boundingBoxY1","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"bounding_box_x2","getter_name":"boundingBoxX2","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"bounding_box_y2","getter_name":"boundingBoxY2","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"source_type","getter_name":"sourceType","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":22,"references":[],"type":"table","data":{"name":"store_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"string_value","getter_name":"stringValue","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"int_value","getter_name":"intValue","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":["id"]}},{"id":23,"references":[15],"type":"index","data":{"on":15,"name":"idx_lat_lng","sql":"CREATE INDEX IF NOT EXISTS idx_lat_lng ON remote_exif_entity (latitude, longitude)","unique":false,"columns":[]}}]} \ No newline at end of file diff --git a/mobile/drift_schemas/main/drift_schema_v12.json b/mobile/drift_schemas/main/drift_schema_v12.json new file mode 100644 index 0000000000..1c100ab37f --- /dev/null +++ b/mobile/drift_schemas/main/drift_schema_v12.json @@ -0,0 +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":"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":"email","getter_name":"email","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"has_profile_image","getter_name":"hasProfileImage","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"has_profile_image\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"has_profile_image\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"profile_changed_at","getter_name":"profileChangedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"avatar_color","getter_name":"avatarColor","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AvatarColor.values)","dart_type_name":"AvatarColor"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":1,"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":"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":[]},{"name":"duration_in_seconds","getter_name":"durationInSeconds","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"id","getter_name":"id","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":false,"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":[]},{"name":"owner_id","getter_name":"ownerId","moor_type":"string","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":"thumb_hash","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":[]},{"name":"live_photo_video_id","getter_name":"livePhotoVideoId","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"visibility","getter_name":"visibility","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AssetVisibility.values)","dart_type_name":"AssetVisibility"}},{"name":"stack_id","getter_name":"stackId","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"library_id","getter_name":"libraryId","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":["id"]}},{"id":2,"references":[0],"type":"table","data":{"name":"stack_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":"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":"owner_id","getter_name":"ownerId","moor_type":"string","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":"primary_asset_id","getter_name":"primaryAssetId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["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":"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":[]},{"name":"duration_in_seconds","getter_name":"durationInSeconds","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"id","getter_name":"id","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":[]},{"name":"orientation","getter_name":"orientation","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":4,"references":[0,1],"type":"table","data":{"name":"remote_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":"description","getter_name":"description","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('\\'\\'')","default_client_dart":null,"dsl_features":[]},{"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":"owner_id","getter_name":"ownerId","moor_type":"string","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":"thumbnail_asset_id","getter_name":"thumbnailAssetId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE SET NULL","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (id) ON DELETE SET NULL"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"is_activity_enabled","getter_name":"isActivityEnabled","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_activity_enabled\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_activity_enabled\" IN (0, 1))"},"default_dart":"const CustomExpression('1')","default_client_dart":null,"dsl_features":[]},{"name":"order","getter_name":"order","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AlbumAssetOrder.values)","dart_type_name":"AlbumAssetOrder"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":5,"references":[4],"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":"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_ios_shared_album","getter_name":"isIosSharedAlbum","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_ios_shared_album\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_ios_shared_album\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"linked_remote_album_id","getter_name":"linkedRemoteAlbumId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES remote_album_entity (id) ON DELETE SET NULL","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_album_entity (id) ON DELETE SET NULL"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"marker","getter_name":"marker_","moor_type":"bool","nullable":true,"customConstraints":null,"defaultConstraints":"CHECK (\"marker\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"marker\" IN (0, 1))"},"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":6,"references":[3,5],"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 (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES local_asset_entity (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"]},{"name":"marker","getter_name":"marker_","moor_type":"bool","nullable":true,"customConstraints":null,"defaultConstraints":"CHECK (\"marker\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"marker\" IN (0, 1))"},"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["asset_id","album_id"]}},{"id":7,"references":[3],"type":"index","data":{"on":3,"name":"idx_local_asset_checksum","sql":"CREATE INDEX IF NOT EXISTS idx_local_asset_checksum ON local_asset_entity (checksum)","unique":false,"columns":[]}},{"id":8,"references":[1],"type":"index","data":{"on":1,"name":"idx_remote_asset_owner_checksum","sql":"CREATE INDEX IF NOT EXISTS idx_remote_asset_owner_checksum ON remote_asset_entity (owner_id, checksum)","unique":false,"columns":[]}},{"id":9,"references":[1],"type":"index","data":{"on":1,"name":"UQ_remote_assets_owner_checksum","sql":"CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_checksum\nON remote_asset_entity (owner_id, checksum)\nWHERE (library_id IS NULL);\n","unique":true,"columns":[]}},{"id":10,"references":[1],"type":"index","data":{"on":1,"name":"UQ_remote_assets_owner_library_checksum","sql":"CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_library_checksum\nON remote_asset_entity (owner_id, library_id, checksum)\nWHERE (library_id IS NOT NULL);\n","unique":true,"columns":[]}},{"id":11,"references":[1],"type":"index","data":{"on":1,"name":"idx_remote_asset_checksum","sql":"CREATE INDEX IF NOT EXISTS idx_remote_asset_checksum ON remote_asset_entity (checksum)","unique":false,"columns":[]}},{"id":12,"references":[],"type":"table","data":{"name":"auth_user_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":"email","getter_name":"email","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":"has_profile_image","getter_name":"hasProfileImage","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"has_profile_image\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"has_profile_image\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"profile_changed_at","getter_name":"profileChangedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"avatar_color","getter_name":"avatarColor","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AvatarColor.values)","dart_type_name":"AvatarColor"}},{"name":"quota_size_in_bytes","getter_name":"quotaSizeInBytes","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","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":[]},{"name":"pin_code","getter_name":"pinCode","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":["id"]}},{"id":13,"references":[0],"type":"table","data":{"name":"user_metadata_entity","was_declared_in_moor":false,"columns":[{"name":"user_id","getter_name":"userId","moor_type":"string","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":"key","getter_name":"key","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(UserMetadataKey.values)","dart_type_name":"UserMetadataKey"}},{"name":"value","getter_name":"value","moor_type":"blob","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"userMetadataConverter","dart_type_name":"Map"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["user_id","key"]}},{"id":14,"references":[0],"type":"table","data":{"name":"partner_entity","was_declared_in_moor":false,"columns":[{"name":"shared_by_id","getter_name":"sharedById","moor_type":"string","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":"string","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":15,"references":[1],"type":"table","data":{"name":"remote_exif_entity","was_declared_in_moor":false,"columns":[{"name":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (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":"double","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":"double","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"latitude","getter_name":"latitude","moor_type":"double","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"longitude","getter_name":"longitude","moor_type":"double","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":"lens","getter_name":"lens","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":16,"references":[1,4],"type":"table","data":{"name":"remote_album_asset_entity","was_declared_in_moor":false,"columns":[{"name":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (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 remote_album_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_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":17,"references":[4,0],"type":"table","data":{"name":"remote_album_user_entity","was_declared_in_moor":false,"columns":[{"name":"album_id","getter_name":"albumId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_album_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_album_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"user_id","getter_name":"userId","moor_type":"string","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":"role","getter_name":"role","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AlbumUserRole.values)","dart_type_name":"AlbumUserRole"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["album_id","user_id"]}},{"id":18,"references":[0],"type":"table","data":{"name":"memory_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":"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":"deleted_at","getter_name":"deletedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"owner_id","getter_name":"ownerId","moor_type":"string","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":"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(MemoryTypeEnum.values)","dart_type_name":"MemoryTypeEnum"}},{"name":"data","getter_name":"data","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_saved","getter_name":"isSaved","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_saved\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_saved\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"memory_at","getter_name":"memoryAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"seen_at","getter_name":"seenAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"show_at","getter_name":"showAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"hide_at","getter_name":"hideAt","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":["id"]}},{"id":19,"references":[1,18],"type":"table","data":{"name":"memory_asset_entity","was_declared_in_moor":false,"columns":[{"name":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"memory_id","getter_name":"memoryId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES memory_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES memory_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","memory_id"]}},{"id":20,"references":[0],"type":"table","data":{"name":"person_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":"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":"owner_id","getter_name":"ownerId","moor_type":"string","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":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"face_asset_id","getter_name":"faceAssetId","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":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_hidden","getter_name":"isHidden","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_hidden\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_hidden\" IN (0, 1))"},"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"color","getter_name":"color","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"birth_date","getter_name":"birthDate","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":["id"]}},{"id":21,"references":[1,20],"type":"table","data":{"name":"asset_face_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":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"person_id","getter_name":"personId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES person_entity (id) ON DELETE SET NULL","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES person_entity (id) ON DELETE SET NULL"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"image_width","getter_name":"imageWidth","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"image_height","getter_name":"imageHeight","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"bounding_box_x1","getter_name":"boundingBoxX1","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"bounding_box_y1","getter_name":"boundingBoxY1","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"bounding_box_x2","getter_name":"boundingBoxX2","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"bounding_box_y2","getter_name":"boundingBoxY2","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"source_type","getter_name":"sourceType","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":22,"references":[],"type":"table","data":{"name":"store_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"string_value","getter_name":"stringValue","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"int_value","getter_name":"intValue","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":["id"]}},{"id":23,"references":[15],"type":"index","data":{"on":15,"name":"idx_lat_lng","sql":"CREATE INDEX IF NOT EXISTS idx_lat_lng ON remote_exif_entity (latitude, longitude)","unique":false,"columns":[]}}]} \ No newline at end of file diff --git a/mobile/ios/.gitignore b/mobile/ios/.gitignore index f312f249a3..e32cadbf68 100644 --- a/mobile/ios/.gitignore +++ b/mobile/ios/.gitignore @@ -4,7 +4,6 @@ *.moved-aside *.pbxuser *.perspectivev3 -**/*sync/ .sconsign.dblite .tags* **/.vagrant/ diff --git a/mobile/ios/Flutter/AppFrameworkInfo.plist b/mobile/ios/Flutter/AppFrameworkInfo.plist index 7c56964006..1dc6cf7652 100644 --- a/mobile/ios/Flutter/AppFrameworkInfo.plist +++ b/mobile/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 12.0 + 13.0 diff --git a/mobile/ios/Podfile.lock b/mobile/ios/Podfile.lock index 09bd36022b..9bff8cd8e2 100644 --- a/mobile/ios/Podfile.lock +++ b/mobile/ios/Podfile.lock @@ -64,7 +64,7 @@ PODS: - Flutter - integration_test (0.0.1): - Flutter - - isar_flutter_libs (1.0.0): + - isar_community_flutter_libs (1.0.0): - Flutter - local_auth_darwin (0.0.1): - Flutter @@ -149,7 +149,7 @@ DEPENDENCIES: - home_widget (from `.symlinks/plugins/home_widget/ios`) - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) - integration_test (from `.symlinks/plugins/integration_test/ios`) - - isar_flutter_libs (from `.symlinks/plugins/isar_flutter_libs/ios`) + - isar_community_flutter_libs (from `.symlinks/plugins/isar_community_flutter_libs/ios`) - local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`) - maplibre_gl (from `.symlinks/plugins/maplibre_gl/ios`) - native_video_player (from `.symlinks/plugins/native_video_player/ios`) @@ -210,8 +210,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/image_picker_ios/ios" integration_test: :path: ".symlinks/plugins/integration_test/ios" - isar_flutter_libs: - :path: ".symlinks/plugins/isar_flutter_libs/ios" + isar_community_flutter_libs: + :path: ".symlinks/plugins/isar_community_flutter_libs/ios" local_auth_darwin: :path: ".symlinks/plugins/local_auth_darwin/darwin" maplibre_gl: @@ -253,7 +253,7 @@ SPEC CHECKSUMS: DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be - Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 flutter_local_notifications: ad39620c743ea4c15127860f4b5641649a988100 flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13 @@ -264,7 +264,7 @@ SPEC CHECKSUMS: home_widget: f169fc41fd807b4d46ab6615dc44d62adbf9f64f image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a integration_test: 4a889634ef21a45d28d50d622cf412dc6d9f586e - isar_flutter_libs: bc909e72c3d756c2759f14c8776c13b5b0556e26 + isar_community_flutter_libs: bede843185a61a05ff364a05c9b23209523f7e0d local_auth_darwin: 553ce4f9b16d3fdfeafce9cf042e7c9f77c1c391 MapLibre: 69e572367f4ef6287e18246cfafc39c80cdcabcd maplibre_gl: 3c924e44725147b03dda33430ad216005b40555f diff --git a/mobile/ios/Runner.xcodeproj/project.pbxproj b/mobile/ios/Runner.xcodeproj/project.pbxproj index 4e68390113..3f00b6c6aa 100644 --- a/mobile/ios/Runner.xcodeproj/project.pbxproj +++ b/mobile/ios/Runner.xcodeproj/project.pbxproj @@ -18,6 +18,8 @@ 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; B21E34AA2E5AFD2B0031FDB9 /* BackgroundWorkerApiImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = B21E34A92E5AFD210031FDB9 /* BackgroundWorkerApiImpl.swift */; }; B21E34AC2E5B09190031FDB9 /* BackgroundWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = B21E34AB2E5B09100031FDB9 /* BackgroundWorker.swift */; }; + B25D377A2E72CA15008B6CA7 /* Connectivity.g.swift in Sources */ = {isa = PBXBuildFile; fileRef = B25D37782E72CA15008B6CA7 /* Connectivity.g.swift */; }; + B25D377C2E72CA26008B6CA7 /* ConnectivityApiImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = B25D377B2E72CA20008B6CA7 /* ConnectivityApiImpl.swift */; }; B2BE315F2E5E5229006EEF88 /* BackgroundWorker.g.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2BE315E2E5E5229006EEF88 /* BackgroundWorker.g.swift */; }; D218389C4A4C4693F141F7D1 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 886774DBDDE6B35BF2B4F2CD /* Pods_Runner.framework */; }; F02538E92DFBCBDD008C3FA3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; @@ -97,6 +99,8 @@ B1FBA9EE014DE20271B0FE77 /* Pods-ShareExtension.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareExtension.profile.xcconfig"; path = "Target Support Files/Pods-ShareExtension/Pods-ShareExtension.profile.xcconfig"; sourceTree = ""; }; B21E34A92E5AFD210031FDB9 /* BackgroundWorkerApiImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundWorkerApiImpl.swift; sourceTree = ""; }; B21E34AB2E5B09100031FDB9 /* BackgroundWorker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundWorker.swift; sourceTree = ""; }; + B25D37782E72CA15008B6CA7 /* Connectivity.g.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Connectivity.g.swift; sourceTree = ""; }; + B25D377B2E72CA20008B6CA7 /* ConnectivityApiImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectivityApiImpl.swift; sourceTree = ""; }; B2BE315E2E5E5229006EEF88 /* BackgroundWorker.g.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundWorker.g.swift; sourceTree = ""; }; E0E99CDC17B3EB7FA8BA2332 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; F0B57D382DF764BD00DC5BCC /* WidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = WidgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -127,6 +131,13 @@ /* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ /* Begin PBXFileSystemSynchronizedRootGroup section */ + B231F52D2E93A44A00BC45D1 /* Core */ = { + isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + ); + path = Core; + sourceTree = ""; + }; B2CF7F8C2DDE4EBB00744BF6 /* Sync */ = { isa = PBXFileSystemSynchronizedRootGroup; exceptions = ( @@ -243,6 +254,8 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( + B231F52D2E93A44A00BC45D1 /* Core */, + B25D37792E72CA15008B6CA7 /* Connectivity */, B21E34A62E5AF9760031FDB9 /* Background */, B2CF7F8C2DDE4EBB00744BF6 /* Sync */, FA9973382CF6DF4B000EF859 /* Runner.entitlements */, @@ -271,6 +284,15 @@ path = Background; sourceTree = ""; }; + B25D37792E72CA15008B6CA7 /* Connectivity */ = { + isa = PBXGroup; + children = ( + B25D377B2E72CA20008B6CA7 /* ConnectivityApiImpl.swift */, + B25D37782E72CA15008B6CA7 /* Connectivity.g.swift */, + ); + path = Connectivity; + sourceTree = ""; + }; FAC6F8B62D287F120078CB2F /* ShareExtension */ = { isa = PBXGroup; children = ( @@ -317,6 +339,7 @@ F0B57D482DF764BE00DC5BCC /* PBXTargetDependency */, ); fileSystemSynchronizedGroups = ( + B231F52D2E93A44A00BC45D1 /* Core */, B2CF7F8C2DDE4EBB00744BF6 /* Sync */, ); name = Runner; @@ -558,7 +581,9 @@ 65F32F31299BD2F800CE9261 /* BackgroundServicePlugin.swift in Sources */, 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, B21E34AC2E5B09190031FDB9 /* BackgroundWorker.swift in Sources */, + B25D377A2E72CA15008B6CA7 /* Connectivity.g.swift in Sources */, FEAFA8732E4D42F4001E47FE /* Thumbhash.swift in Sources */, + B25D377C2E72CA26008B6CA7 /* ConnectivityApiImpl.swift in Sources */, FED3B1962E253E9B0030FD97 /* ThumbnailsImpl.swift in Sources */, B21E34AA2E5AFD2B0031FDB9 /* BackgroundWorkerApiImpl.swift in Sources */, FED3B1972E253E9B0030FD97 /* Thumbnails.g.swift in Sources */, @@ -689,7 +714,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 219; + CURRENT_PROJECT_VERSION = 231; CUSTOM_GROUP_ID = group.app.immich.share; DEVELOPMENT_TEAM = 2F67MQ8R79; ENABLE_BITCODE = NO; @@ -833,7 +858,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 219; + CURRENT_PROJECT_VERSION = 231; CUSTOM_GROUP_ID = group.app.immich.share; DEVELOPMENT_TEAM = 2F67MQ8R79; ENABLE_BITCODE = NO; @@ -863,7 +888,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 219; + CURRENT_PROJECT_VERSION = 231; CUSTOM_GROUP_ID = group.app.immich.share; DEVELOPMENT_TEAM = 2F67MQ8R79; ENABLE_BITCODE = NO; @@ -897,7 +922,7 @@ CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 219; + CURRENT_PROJECT_VERSION = 231; DEVELOPMENT_TEAM = 2F67MQ8R79; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; @@ -940,7 +965,7 @@ CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 219; + CURRENT_PROJECT_VERSION = 231; DEVELOPMENT_TEAM = 2F67MQ8R79; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; @@ -980,7 +1005,7 @@ CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 219; + CURRENT_PROJECT_VERSION = 231; DEVELOPMENT_TEAM = 2F67MQ8R79; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; @@ -1019,7 +1044,7 @@ CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 219; + CURRENT_PROJECT_VERSION = 231; CUSTOM_GROUP_ID = group.app.immich.share; DEVELOPMENT_TEAM = 2F67MQ8R79; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -1063,7 +1088,7 @@ CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 219; + CURRENT_PROJECT_VERSION = 231; CUSTOM_GROUP_ID = group.app.immich.share; DEVELOPMENT_TEAM = 2F67MQ8R79; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -1104,7 +1129,7 @@ CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 219; + CURRENT_PROJECT_VERSION = 231; CUSTOM_GROUP_ID = group.app.immich.share; DEVELOPMENT_TEAM = 2F67MQ8R79; ENABLE_USER_SCRIPT_SANDBOXING = YES; diff --git a/mobile/ios/Runner/AppDelegate.swift b/mobile/ios/Runner/AppDelegate.swift index 3476030923..4e4cb2ed13 100644 --- a/mobile/ios/Runner/AppDelegate.swift +++ b/mobile/ios/Runner/AppDelegate.swift @@ -20,7 +20,7 @@ import UIKit GeneratedPluginRegistrant.register(with: self) let controller: FlutterViewController = window?.rootViewController as! FlutterViewController - AppDelegate.registerPlugins(binaryMessenger: controller.binaryMessenger) + AppDelegate.registerPlugins(with: controller.engine) BackgroundServicePlugin.register(with: self.registrar(forPlugin: "BackgroundServicePlugin")!) BackgroundServicePlugin.registerBackgroundProcessing() @@ -51,9 +51,13 @@ import UIKit return super.application(application, didFinishLaunchingWithOptions: launchOptions) } - public static func registerPlugins(binaryMessenger: FlutterBinaryMessenger) { - NativeSyncApiSetup.setUp(binaryMessenger: binaryMessenger, api: NativeSyncApiImpl()) - ThumbnailApiSetup.setUp(binaryMessenger: binaryMessenger, api: ThumbnailApiImpl()) - BackgroundWorkerFgHostApiSetup.setUp(binaryMessenger: binaryMessenger, api: BackgroundWorkerApiImpl()) + public static func registerPlugins(with engine: FlutterEngine) { + NativeSyncApiImpl.register(with: engine.registrar(forPlugin: NativeSyncApiImpl.name)!) + ThumbnailApiSetup.setUp(binaryMessenger: engine.binaryMessenger, api: ThumbnailApiImpl()) + BackgroundWorkerFgHostApiSetup.setUp(binaryMessenger: engine.binaryMessenger, api: BackgroundWorkerApiImpl()) + } + + public static func cancelPlugins(with engine: FlutterEngine) { + (engine.valuePublished(byPlugin: NativeSyncApiImpl.name) as? NativeSyncApiImpl)?.detachFromEngine() } } diff --git a/mobile/ios/Runner/Background/BackgroundWorker.g.swift b/mobile/ios/Runner/Background/BackgroundWorker.g.swift index bfc0b26d9b..e339f150e7 100644 --- a/mobile/ios/Runner/Background/BackgroundWorker.g.swift +++ b/mobile/ios/Runner/Background/BackgroundWorker.g.swift @@ -50,11 +50,119 @@ private func nilOrValue(_ value: Any?) -> T? { return value as! T? } +func deepEqualsBackgroundWorker(_ lhs: Any?, _ rhs: Any?) -> Bool { + let cleanLhs = nilOrValue(lhs) as Any? + let cleanRhs = nilOrValue(rhs) as Any? + switch (cleanLhs, cleanRhs) { + case (nil, nil): + return true + + case (nil, _), (_, nil): + return false + + case is (Void, Void): + return true + + case let (cleanLhsHashable, cleanRhsHashable) as (AnyHashable, AnyHashable): + return cleanLhsHashable == cleanRhsHashable + + case let (cleanLhsArray, cleanRhsArray) as ([Any?], [Any?]): + guard cleanLhsArray.count == cleanRhsArray.count else { return false } + for (index, element) in cleanLhsArray.enumerated() { + if !deepEqualsBackgroundWorker(element, cleanRhsArray[index]) { + return false + } + } + return true + + case let (cleanLhsDictionary, cleanRhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): + guard cleanLhsDictionary.count == cleanRhsDictionary.count else { return false } + for (key, cleanLhsValue) in cleanLhsDictionary { + guard cleanRhsDictionary.index(forKey: key) != nil else { return false } + if !deepEqualsBackgroundWorker(cleanLhsValue, cleanRhsDictionary[key]!) { + return false + } + } + return true + + default: + // Any other type shouldn't be able to be used with pigeon. File an issue if you find this to be untrue. + return false + } +} + +func deepHashBackgroundWorker(value: Any?, hasher: inout Hasher) { + if let valueList = value as? [AnyHashable] { + for item in valueList { deepHashBackgroundWorker(value: item, hasher: &hasher) } + return + } + + if let valueDict = value as? [AnyHashable: AnyHashable] { + for key in valueDict.keys { + hasher.combine(key) + deepHashBackgroundWorker(value: valueDict[key]!, hasher: &hasher) + } + return + } + + if let hashableValue = value as? AnyHashable { + hasher.combine(hashableValue.hashValue) + } + + return hasher.combine(String(describing: value)) +} + + + +/// Generated class from Pigeon that represents data sent in messages. +struct BackgroundWorkerSettings: Hashable { + var requiresCharging: Bool + var minimumDelaySeconds: Int64 + + + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> BackgroundWorkerSettings? { + let requiresCharging = pigeonVar_list[0] as! Bool + let minimumDelaySeconds = pigeonVar_list[1] as! Int64 + + return BackgroundWorkerSettings( + requiresCharging: requiresCharging, + minimumDelaySeconds: minimumDelaySeconds + ) + } + func toList() -> [Any?] { + return [ + requiresCharging, + minimumDelaySeconds, + ] + } + static func == (lhs: BackgroundWorkerSettings, rhs: BackgroundWorkerSettings) -> Bool { + return deepEqualsBackgroundWorker(lhs.toList(), rhs.toList()) } + func hash(into hasher: inout Hasher) { + deepHashBackgroundWorker(value: toList(), hasher: &hasher) + } +} private class BackgroundWorkerPigeonCodecReader: FlutterStandardReader { + override func readValue(ofType type: UInt8) -> Any? { + switch type { + case 129: + return BackgroundWorkerSettings.fromList(self.readValue() as! [Any?]) + default: + return super.readValue(ofType: type) + } + } } private class BackgroundWorkerPigeonCodecWriter: FlutterStandardWriter { + override func writeValue(_ value: Any) { + if let value = value as? BackgroundWorkerSettings { + super.writeByte(129) + super.writeValue(value.toList()) + } else { + super.writeValue(value) + } + } } private class BackgroundWorkerPigeonCodecReaderWriter: FlutterStandardReaderWriter { @@ -74,6 +182,8 @@ class BackgroundWorkerPigeonCodec: FlutterStandardMessageCodec, @unchecked Senda /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol BackgroundWorkerFgHostApi { func enable() throws + func saveNotificationMessage(title: String, body: String) throws + func configure(settings: BackgroundWorkerSettings) throws func disable() throws } @@ -96,6 +206,37 @@ class BackgroundWorkerFgHostApiSetup { } else { enableChannel.setMessageHandler(nil) } + let saveNotificationMessageChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.saveNotificationMessage\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + saveNotificationMessageChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let titleArg = args[0] as! String + let bodyArg = args[1] as! String + do { + try api.saveNotificationMessage(title: titleArg, body: bodyArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + saveNotificationMessageChannel.setMessageHandler(nil) + } + let configureChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.configure\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + configureChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let settingsArg = args[0] as! BackgroundWorkerSettings + do { + try api.configure(settings: settingsArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + configureChannel.setMessageHandler(nil) + } let disableChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.disable\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { disableChannel.setMessageHandler { _, reply in diff --git a/mobile/ios/Runner/Background/BackgroundWorker.swift b/mobile/ios/Runner/Background/BackgroundWorker.swift index 835632a5d0..7dc450d76e 100644 --- a/mobile/ios/Runner/Background/BackgroundWorker.swift +++ b/mobile/ios/Runner/Background/BackgroundWorker.swift @@ -95,7 +95,7 @@ class BackgroundWorker: BackgroundWorkerBgHostApi { // Register plugins in the new engine GeneratedPluginRegistrant.register(with: engine) // Register custom plugins - AppDelegate.registerPlugins(binaryMessenger: engine.binaryMessenger) + AppDelegate.registerPlugins(with: engine) flutterApi = BackgroundWorkerFlutterApi(binaryMessenger: engine.binaryMessenger) BackgroundWorkerBgHostApiSetup.setUp(binaryMessenger: engine.binaryMessenger, api: self) @@ -129,7 +129,6 @@ class BackgroundWorker: BackgroundWorkerBgHostApi { return } - isComplete = true flutterApi?.cancel { result in self.complete(success: false) } @@ -169,7 +168,9 @@ class BackgroundWorker: BackgroundWorkerBgHostApi { } isComplete = true + AppDelegate.cancelPlugins(with: engine) engine.destroyContext() + flutterApi = nil completionHandler(success) } } diff --git a/mobile/ios/Runner/Background/BackgroundWorkerApiImpl.swift b/mobile/ios/Runner/Background/BackgroundWorkerApiImpl.swift index 941e90cd44..a7bbc31ceb 100644 --- a/mobile/ios/Runner/Background/BackgroundWorkerApiImpl.swift +++ b/mobile/ios/Runner/Background/BackgroundWorkerApiImpl.swift @@ -5,17 +5,26 @@ class BackgroundWorkerApiImpl: BackgroundWorkerFgHostApi { func enable() throws { BackgroundWorkerApiImpl.scheduleRefreshWorker() BackgroundWorkerApiImpl.scheduleProcessingWorker() - print("BackgroundUploadImpl:enbale Background worker scheduled") + print("BackgroundWorkerApiImpl:enable Background worker scheduled") + } + + func configure(settings: BackgroundWorkerSettings) throws { + // Android only + } + + func saveNotificationMessage(title: String, body: String) throws { + // Android only } func disable() throws { BGTaskScheduler.shared.cancel(taskRequestWithIdentifier: BackgroundWorkerApiImpl.refreshTaskID); BGTaskScheduler.shared.cancel(taskRequestWithIdentifier: BackgroundWorkerApiImpl.processingTaskID); - print("BackgroundUploadImpl:disableUploadWorker Disabled background workers") + print("BackgroundWorkerApiImpl:disableUploadWorker Disabled background workers") } private static let refreshTaskID = "app.alextran.immich.background.refreshUpload" private static let processingTaskID = "app.alextran.immich.background.processingUpload" + private static let taskSemaphore = DispatchSemaphore(value: 1) public static func registerBackgroundWorkers() { BGTaskScheduler.shared.register( @@ -59,12 +68,18 @@ class BackgroundWorkerApiImpl: BackgroundWorkerFgHostApi { private static func handleBackgroundRefresh(task: BGAppRefreshTask) { scheduleRefreshWorker() - // Restrict the refresh task to run only for a maximum of (maxSeconds) seconds - runBackgroundWorker(task: task, taskType: .refresh, maxSeconds: 20) + // If another task is running, cede the background time back to the OS + if taskSemaphore.wait(timeout: .now()) == .success { + // Restrict the refresh task to run only for a maximum of (maxSeconds) seconds + runBackgroundWorker(task: task, taskType: .refresh, maxSeconds: 20) + } else { + task.setTaskCompleted(success: false) + } } private static func handleBackgroundProcessing(task: BGProcessingTask) { scheduleProcessingWorker() + taskSemaphore.wait() // There are no restrictions for processing tasks. Although, the OS could signal expiration at any time runBackgroundWorker(task: task, taskType: .processing, maxSeconds: nil) } @@ -80,6 +95,7 @@ class BackgroundWorkerApiImpl: BackgroundWorkerFgHostApi { * - maxSeconds: Optional timeout for the operation in seconds */ private static func runBackgroundWorker(task: BGTask, taskType: BackgroundTaskType, maxSeconds: Int?) { + defer { taskSemaphore.signal() } let semaphore = DispatchSemaphore(value: 0) var isSuccess = true diff --git a/mobile/ios/Runner/Connectivity/Connectivity.g.swift b/mobile/ios/Runner/Connectivity/Connectivity.g.swift new file mode 100644 index 0000000000..45333f03d8 --- /dev/null +++ b/mobile/ios/Runner/Connectivity/Connectivity.g.swift @@ -0,0 +1,129 @@ +// Autogenerated from Pigeon (v26.0.0), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +import Foundation + +#if os(iOS) + import Flutter +#elseif os(macOS) + import FlutterMacOS +#else + #error("Unsupported platform.") +#endif + +private func wrapResult(_ result: Any?) -> [Any?] { + return [result] +} + +private func wrapError(_ error: Any) -> [Any?] { + if let pigeonError = error as? PigeonError { + return [ + pigeonError.code, + pigeonError.message, + pigeonError.details, + ] + } + if let flutterError = error as? FlutterError { + return [ + flutterError.code, + flutterError.message, + flutterError.details, + ] + } + return [ + "\(error)", + "\(type(of: error))", + "Stacktrace: \(Thread.callStackSymbols)", + ] +} + +private func isNullish(_ value: Any?) -> Bool { + return value is NSNull || value == nil +} + +private func nilOrValue(_ value: Any?) -> T? { + if value is NSNull { return nil } + return value as! T? +} + + +enum NetworkCapability: Int { + case cellular = 0 + case wifi = 1 + case vpn = 2 + case unmetered = 3 +} + +private class ConnectivityPigeonCodecReader: FlutterStandardReader { + override func readValue(ofType type: UInt8) -> Any? { + switch type { + case 129: + let enumResultAsInt: Int? = nilOrValue(self.readValue() as! Int?) + if let enumResultAsInt = enumResultAsInt { + return NetworkCapability(rawValue: enumResultAsInt) + } + return nil + default: + return super.readValue(ofType: type) + } + } +} + +private class ConnectivityPigeonCodecWriter: FlutterStandardWriter { + override func writeValue(_ value: Any) { + if let value = value as? NetworkCapability { + super.writeByte(129) + super.writeValue(value.rawValue) + } else { + super.writeValue(value) + } + } +} + +private class ConnectivityPigeonCodecReaderWriter: FlutterStandardReaderWriter { + override func reader(with data: Data) -> FlutterStandardReader { + return ConnectivityPigeonCodecReader(data: data) + } + + override func writer(with data: NSMutableData) -> FlutterStandardWriter { + return ConnectivityPigeonCodecWriter(data: data) + } +} + +class ConnectivityPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { + static let shared = ConnectivityPigeonCodec(readerWriter: ConnectivityPigeonCodecReaderWriter()) +} + +/// Generated protocol from Pigeon that represents a handler of messages from Flutter. +protocol ConnectivityApi { + func getCapabilities() throws -> [NetworkCapability] +} + +/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. +class ConnectivityApiSetup { + static var codec: FlutterStandardMessageCodec { ConnectivityPigeonCodec.shared } + /// Sets up an instance of `ConnectivityApi` to handle messages through the `binaryMessenger`. + static func setUp(binaryMessenger: FlutterBinaryMessenger, api: ConnectivityApi?, messageChannelSuffix: String = "") { + let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" + #if os(iOS) + let taskQueue = binaryMessenger.makeBackgroundTaskQueue?() + #else + let taskQueue: FlutterTaskQueue? = nil + #endif + let getCapabilitiesChannel = taskQueue == nil + ? FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.ConnectivityApi.getCapabilities\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + : FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.ConnectivityApi.getCapabilities\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec, taskQueue: taskQueue) + if let api = api { + getCapabilitiesChannel.setMessageHandler { _, reply in + do { + let result = try api.getCapabilities() + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + getCapabilitiesChannel.setMessageHandler(nil) + } + } +} diff --git a/mobile/ios/Runner/Connectivity/ConnectivityApiImpl.swift b/mobile/ios/Runner/Connectivity/ConnectivityApiImpl.swift new file mode 100644 index 0000000000..0261cb26fb --- /dev/null +++ b/mobile/ios/Runner/Connectivity/ConnectivityApiImpl.swift @@ -0,0 +1,6 @@ + +class ConnectivityApiImpl: ConnectivityApi { + func getCapabilities() throws -> [NetworkCapability] { + [] + } +} diff --git a/mobile/ios/Runner/Core/ImmichPlugin.swift b/mobile/ios/Runner/Core/ImmichPlugin.swift new file mode 100644 index 0000000000..db10b7a75d --- /dev/null +++ b/mobile/ios/Runner/Core/ImmichPlugin.swift @@ -0,0 +1,17 @@ +class ImmichPlugin: NSObject { + var detached: Bool + + override init() { + detached = false + super.init() + } + + func detachFromEngine() { + self.detached = true + } + + func completeWhenActive(for completion: @escaping (T) -> Void, with value: T) { + guard !self.detached else { return } + completion(value) + } +} diff --git a/mobile/ios/Runner/Images/ThumbnailsImpl.swift b/mobile/ios/Runner/Images/ThumbnailsImpl.swift index d1ea2cc0e0..452ca62377 100644 --- a/mobile/ios/Runner/Images/ThumbnailsImpl.swift +++ b/mobile/ios/Runner/Images/ThumbnailsImpl.swift @@ -105,7 +105,7 @@ class ThumbnailApiImpl: ThumbnailApi { var image: UIImage? Self.imageManager.requestImage( for: asset, - targetSize: CGSize(width: Double(width), height: Double(height)), + targetSize: width > 0 && height > 0 ? CGSize(width: Double(width), height: Double(height)) : PHImageManagerMaximumSize, contentMode: .aspectFill, options: Self.requestOptions, resultHandler: { (_image, info) -> Void in diff --git a/mobile/ios/Runner/Info.plist b/mobile/ios/Runner/Info.plist index 04e5e01392..1dc55468da 100644 --- a/mobile/ios/Runner/Info.plist +++ b/mobile/ios/Runner/Info.plist @@ -80,7 +80,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.140.0 + 2.1.0 CFBundleSignature ???? CFBundleURLTypes @@ -107,7 +107,7 @@ CFBundleVersion - 219 + 231 FLTEnableImpeller ITSAppUsesNonExemptEncryption diff --git a/mobile/ios/Runner/Sync/Messages.g.swift b/mobile/ios/Runner/Sync/Messages.g.swift index 19f4384672..305aca5266 100644 --- a/mobile/ios/Runner/Sync/Messages.g.swift +++ b/mobile/ios/Runner/Sync/Messages.g.swift @@ -267,6 +267,39 @@ struct SyncDelta: Hashable { } } +/// Generated class from Pigeon that represents data sent in messages. +struct HashResult: Hashable { + var assetId: String + var error: String? = nil + var hash: String? = nil + + + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> HashResult? { + let assetId = pigeonVar_list[0] as! String + let error: String? = nilOrValue(pigeonVar_list[1]) + let hash: String? = nilOrValue(pigeonVar_list[2]) + + return HashResult( + assetId: assetId, + error: error, + hash: hash + ) + } + func toList() -> [Any?] { + return [ + assetId, + error, + hash, + ] + } + static func == (lhs: HashResult, rhs: HashResult) -> Bool { + return deepEqualsMessages(lhs.toList(), rhs.toList()) } + func hash(into hasher: inout Hasher) { + deepHashMessages(value: toList(), hasher: &hasher) + } +} + private class MessagesPigeonCodecReader: FlutterStandardReader { override func readValue(ofType type: UInt8) -> Any? { switch type { @@ -276,6 +309,8 @@ private class MessagesPigeonCodecReader: FlutterStandardReader { return PlatformAlbum.fromList(self.readValue() as! [Any?]) case 131: return SyncDelta.fromList(self.readValue() as! [Any?]) + case 132: + return HashResult.fromList(self.readValue() as! [Any?]) default: return super.readValue(ofType: type) } @@ -293,6 +328,9 @@ private class MessagesPigeonCodecWriter: FlutterStandardWriter { } else if let value = value as? SyncDelta { super.writeByte(131) super.writeValue(value.toList()) + } else if let value = value as? HashResult { + super.writeByte(132) + super.writeValue(value.toList()) } else { super.writeValue(value) } @@ -313,6 +351,7 @@ class MessagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { static let shared = MessagesPigeonCodec(readerWriter: MessagesPigeonCodecReaderWriter()) } + /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol NativeSyncApi { func shouldFullSync() throws -> Bool @@ -323,7 +362,8 @@ protocol NativeSyncApi { func getAlbums() throws -> [PlatformAlbum] func getAssetsCountSince(albumId: String, timestamp: Int64) throws -> Int64 func getAssetsForAlbum(albumId: String, updatedTimeCond: Int64?) throws -> [PlatformAsset] - func hashPaths(paths: [String]) throws -> [FlutterStandardTypedData?] + func hashAssets(assetIds: [String], allowNetworkAccess: Bool, completion: @escaping (Result<[HashResult], Error>) -> Void) + func cancelHashing() throws } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. @@ -459,22 +499,38 @@ class NativeSyncApiSetup { } else { getAssetsForAlbumChannel.setMessageHandler(nil) } - let hashPathsChannel = taskQueue == nil - ? FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.hashPaths\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - : FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.hashPaths\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec, taskQueue: taskQueue) + let hashAssetsChannel = taskQueue == nil + ? FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.hashAssets\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + : FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.hashAssets\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec, taskQueue: taskQueue) if let api = api { - hashPathsChannel.setMessageHandler { message, reply in + hashAssetsChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let pathsArg = args[0] as! [String] + let assetIdsArg = args[0] as! [String] + let allowNetworkAccessArg = args[1] as! Bool + api.hashAssets(assetIds: assetIdsArg, allowNetworkAccess: allowNetworkAccessArg) { result in + switch result { + case .success(let res): + reply(wrapResult(res)) + case .failure(let error): + reply(wrapError(error)) + } + } + } + } else { + hashAssetsChannel.setMessageHandler(nil) + } + let cancelHashingChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NativeSyncApi.cancelHashing\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + cancelHashingChannel.setMessageHandler { _, reply in do { - let result = try api.hashPaths(paths: pathsArg) - reply(wrapResult(result)) + try api.cancelHashing() + reply(wrapResult(nil)) } catch { reply(wrapError(error)) } } } else { - hashPathsChannel.setMessageHandler(nil) + cancelHashingChannel.setMessageHandler(nil) } } } diff --git a/mobile/ios/Runner/Sync/MessagesImpl.swift b/mobile/ios/Runner/Sync/MessagesImpl.swift index 2810dee7c1..75981fb7ea 100644 --- a/mobile/ios/Runner/Sync/MessagesImpl.swift +++ b/mobile/ios/Runner/Sync/MessagesImpl.swift @@ -17,30 +17,28 @@ struct AssetWrapper: Hashable, Equatable { } } -extension PHAsset { - func toPlatformAsset() -> PlatformAsset { - return PlatformAsset( - id: localIdentifier, - name: title(), - type: Int64(mediaType.rawValue), - createdAt: creationDate.map { Int64($0.timeIntervalSince1970) }, - updatedAt: modificationDate.map { Int64($0.timeIntervalSince1970) }, - width: Int64(pixelWidth), - height: Int64(pixelHeight), - durationInSeconds: Int64(duration), - orientation: 0, - isFavorite: isFavorite - ) +class NativeSyncApiImpl: ImmichPlugin, NativeSyncApi, FlutterPlugin { + static let name = "NativeSyncApi" + + static func register(with registrar: any FlutterPluginRegistrar) { + let instance = NativeSyncApiImpl() + NativeSyncApiSetup.setUp(binaryMessenger: registrar.messenger(), api: instance) + registrar.publish(instance) } -} - -class NativeSyncApiImpl: NativeSyncApi { + + func detachFromEngine(for registrar: any FlutterPluginRegistrar) { + super.detachFromEngine() + } + private let defaults: UserDefaults private let changeTokenKey = "immich:changeToken" private let albumTypes: [PHAssetCollectionType] = [.album, .smartAlbum] private let recoveredAlbumSubType = 1000000219 - private let hashBufferSize = 2 * 1024 * 1024 + private var hashTask: Task? + private static let hashCancelledCode = "HASH_CANCELLED" + private static let hashCancelled = Result<[HashResult], Error>.failure(PigeonError(code: hashCancelledCode, message: "Hashing cancelled", details: nil)) + init(with defaults: UserDefaults = .standard) { self.defaults = defaults @@ -96,7 +94,7 @@ class NativeSyncApiImpl: NativeSyncApi { let collections = PHAssetCollection.fetchAssetCollections(with: type, subtype: .any, options: nil) for i in 0.. %@ OR modificationDate > %@", date, date) options.includeHiddenAssets = false - let assets = PHAsset.fetchAssets(in: album, options: options) + let assets = getAssetsFromAlbum(in: album, options: options) return Int64(assets.count) } @@ -254,8 +254,8 @@ class NativeSyncApiImpl: NativeSyncApi { let date = NSDate(timeIntervalSince1970: TimeInterval(updatedTimeCond!)) options.predicate = NSPredicate(format: "creationDate > %@ OR modificationDate > %@", date, date) } - - let result = PHAsset.fetchAssets(in: album, options: options) + + let result = getAssetsFromAlbum(in: album, options: options) if(result.count == 0) { return [] } @@ -267,23 +267,123 @@ class NativeSyncApiImpl: NativeSyncApi { return assets } - func hashPaths(paths: [String]) throws -> [FlutterStandardTypedData?] { - return paths.map { path in - guard let file = FileHandle(forReadingAtPath: path) else { - print("Cannot open file: \(path)") - return nil - } - - var hasher = Insecure.SHA1() - while autoreleasepool(invoking: { - let chunk = file.readData(ofLength: hashBufferSize) - guard !chunk.isEmpty else { return false } - hasher.update(data: chunk) - return true - }) { } - - let digest = hasher.finalize() - return FlutterStandardTypedData(bytes: Data(digest)) + func hashAssets(assetIds: [String], allowNetworkAccess: Bool, completion: @escaping (Result<[HashResult], Error>) -> Void) { + if let prevTask = hashTask { + prevTask.cancel() + hashTask = nil + } + hashTask = Task { [weak self] in + var missingAssetIds = Set(assetIds) + var assets = [PHAsset]() + assets.reserveCapacity(assetIds.count) + PHAsset.fetchAssets(withLocalIdentifiers: assetIds, options: nil).enumerateObjects { (asset, _, stop) in + if Task.isCancelled { + stop.pointee = true + return + } + missingAssetIds.remove(asset.localIdentifier) + assets.append(asset) } + + if Task.isCancelled { + return self?.completeWhenActive(for: completion, with: Self.hashCancelled) + } + + await withTaskGroup(of: HashResult?.self) { taskGroup in + var results = [HashResult]() + results.reserveCapacity(assets.count) + for asset in assets { + if Task.isCancelled { + return self?.completeWhenActive(for: completion, with: Self.hashCancelled) + } + taskGroup.addTask { + guard let self = self else { return nil } + return await self.hashAsset(asset, allowNetworkAccess: allowNetworkAccess) + } + } + + for await result in taskGroup { + guard let result = result else { + return self?.completeWhenActive(for: completion, with: Self.hashCancelled) + } + results.append(result) + } + + for missing in missingAssetIds { + results.append(HashResult(assetId: missing, error: "Asset not found in library", hash: nil)) + } + + return self?.completeWhenActive(for: completion, with: .success(results)) + } + } + } + + func cancelHashing() { + hashTask?.cancel() + hashTask = nil + } + + private func hashAsset(_ asset: PHAsset, allowNetworkAccess: Bool) async -> HashResult? { + class RequestRef { + var id: PHAssetResourceDataRequestID? + } + let requestRef = RequestRef() + return await withTaskCancellationHandler(operation: { + if Task.isCancelled { + return nil + } + + guard let resource = asset.getResource() else { + return HashResult(assetId: asset.localIdentifier, error: "Cannot get asset resource", hash: nil) + } + + if Task.isCancelled { + return nil + } + + let options = PHAssetResourceRequestOptions() + options.isNetworkAccessAllowed = allowNetworkAccess + + return await withCheckedContinuation { continuation in + var hasher = Insecure.SHA1() + + requestRef.id = PHAssetResourceManager.default().requestData( + for: resource, + options: options, + dataReceivedHandler: { data in + hasher.update(data: data) + }, + completionHandler: { error in + let result: HashResult? = switch (error) { + case let e as PHPhotosError where e.code == .userCancelled: nil + case let .some(e): HashResult( + assetId: asset.localIdentifier, + error: "Failed to hash asset: \(e.localizedDescription)", + hash: nil + ) + case .none: + HashResult( + assetId: asset.localIdentifier, + error: nil, + hash: Data(hasher.finalize()).base64EncodedString() + ) + } + continuation.resume(returning: result) + } + ) + } + }, onCancel: { + guard let requestId = requestRef.id else { return } + PHAssetResourceManager.default().cancelDataRequest(requestId) + }) + } + + private func getAssetsFromAlbum(in album: PHAssetCollection, options: PHFetchOptions) -> PHFetchResult { + // Ensure to actually getting all assets for the Recents album + if (album.assetCollectionSubtype == .smartAlbumUserLibrary) { + return PHAsset.fetchAssets(with: options) + } else { + return PHAsset.fetchAssets(in: album, options: options) + } } } diff --git a/mobile/ios/Runner/Sync/PHAssetExtensions.swift b/mobile/ios/Runner/Sync/PHAssetExtensions.swift new file mode 100644 index 0000000000..2b1ef6ac88 --- /dev/null +++ b/mobile/ios/Runner/Sync/PHAssetExtensions.swift @@ -0,0 +1,77 @@ +import Photos + +extension PHAsset { + func toPlatformAsset() -> PlatformAsset { + return PlatformAsset( + id: localIdentifier, + name: title, + type: Int64(mediaType.rawValue), + createdAt: creationDate.map { Int64($0.timeIntervalSince1970) }, + updatedAt: modificationDate.map { Int64($0.timeIntervalSince1970) }, + width: Int64(pixelWidth), + height: Int64(pixelHeight), + durationInSeconds: Int64(duration), + orientation: 0, + isFavorite: isFavorite + ) + } + + var title: String { + return filename ?? originalFilename ?? "" + } + + var filename: String? { + return value(forKey: "filename") as? String + } + + // This method is expected to be slow as it goes through the asset resources to fetch the originalFilename + var originalFilename: String? { + return getResource()?.originalFilename + } + + func getResource() -> PHAssetResource? { + let resources = PHAssetResource.assetResources(for: self) + + let filteredResources = resources.filter { $0.isMediaResource && isValidResourceType($0.type) } + + guard !filteredResources.isEmpty else { + return nil + } + + if filteredResources.count == 1 { + return filteredResources.first + } + + if let currentResource = filteredResources.first(where: { $0.isCurrent }) { + return currentResource + } + + if let fullSizeResource = filteredResources.first(where: { isFullSizeResourceType($0.type) }) { + return fullSizeResource + } + + return nil + } + + private func isValidResourceType(_ type: PHAssetResourceType) -> Bool { + switch mediaType { + case .image: + return [.photo, .alternatePhoto, .fullSizePhoto].contains(type) + case .video: + return [.video, .fullSizeVideo, .fullSizePairedVideo].contains(type) + default: + return false + } + } + + private func isFullSizeResourceType(_ type: PHAssetResourceType) -> Bool { + switch mediaType { + case .image: + return type == .fullSizePhoto + case .video: + return type == .fullSizeVideo + default: + return false + } + } +} diff --git a/mobile/ios/Runner/Sync/PHAssetResourceExtensions.swift b/mobile/ios/Runner/Sync/PHAssetResourceExtensions.swift new file mode 100644 index 0000000000..699d55a98d --- /dev/null +++ b/mobile/ios/Runner/Sync/PHAssetResourceExtensions.swift @@ -0,0 +1,16 @@ + +import Photos + +extension PHAssetResource { + var isCurrent: Bool { + return value(forKey: "isCurrent") as? Bool ?? false + } + + var isMediaResource: Bool { + var isMedia = type != .adjustmentData + if #available(iOS 17, *) { + isMedia = isMedia && type != .photoProxy + } + return isMedia + } +} diff --git a/mobile/ios/WidgetExtension/widgets/MemoryWidget.swift b/mobile/ios/WidgetExtension/widgets/MemoryWidget.swift index d0a3e8c29d..22414fbec4 100644 --- a/mobile/ios/WidgetExtension/widgets/MemoryWidget.swift +++ b/mobile/ios/WidgetExtension/widgets/MemoryWidget.swift @@ -114,7 +114,7 @@ struct ImmichMemoryProvider: TimelineProvider { } } - // If we didnt add any memory images (some failure occured or no images in memory), + // If we didn't add any memory images (some failure occurred or no images in memory), // default to 12 hours of random photos if entries.count == 0 { // this must be a do/catch since we need to diff --git a/mobile/ios/fastlane/Fastfile b/mobile/ios/fastlane/Fastfile index d546a6493f..57c853e751 100644 --- a/mobile/ios/fastlane/Fastfile +++ b/mobile/ios/fastlane/Fastfile @@ -22,7 +22,7 @@ platform :ios do path: "./Runner.xcodeproj", ) increment_version_number( - version_number: "1.141.1" + version_number: "2.1.0" ) increment_build_number( build_number: latest_testflight_build_number + 1, diff --git a/mobile/lib/constants/constants.dart b/mobile/lib/constants/constants.dart index 0cfc0c57e3..7429616f14 100644 --- a/mobile/lib/constants/constants.dart +++ b/mobile/lib/constants/constants.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + const int noDbId = -9223372036854775808; // from Isar const double downloadCompleted = -1; const double downloadFailed = -2; @@ -10,7 +12,7 @@ const int kSyncEventBatchSize = 5000; const int kFetchLocalAssetsBatchSize = 40000; // Hash batch limits -const int kBatchHashFileLimit = 256; +final int kBatchHashFileLimit = Platform.isIOS ? 32 : 512; const int kBatchHashSizeLimit = 1024 * 1024 * 1024; // 1GB // Secure storage keys @@ -45,3 +47,5 @@ const List<(String, String)> kWidgetNames = [ const double kUploadStatusFailed = -1.0; const double kUploadStatusCanceled = -2.0; + +const int kMinMonthsToEnableScrubberSnap = 12; diff --git a/mobile/lib/domain/models/asset/base_asset.model.dart b/mobile/lib/domain/models/asset/base_asset.model.dart index 4d40be2d32..5774a13c90 100644 --- a/mobile/lib/domain/models/asset/base_asset.model.dart +++ b/mobile/lib/domain/models/asset/base_asset.model.dart @@ -56,6 +56,8 @@ sealed class BaseAsset { // Overridden in subclasses AssetState get storage; + String? get localId; + String? get remoteId; String get heroTag; @override diff --git a/mobile/lib/domain/models/asset/local_asset.model.dart b/mobile/lib/domain/models/asset/local_asset.model.dart index 9cd20acb0a..6f2f4c06ba 100644 --- a/mobile/lib/domain/models/asset/local_asset.model.dart +++ b/mobile/lib/domain/models/asset/local_asset.model.dart @@ -2,12 +2,12 @@ part of 'base_asset.model.dart'; class LocalAsset extends BaseAsset { final String id; - final String? remoteId; + final String? remoteAssetId; final int orientation; const LocalAsset({ required this.id, - this.remoteId, + String? remoteId, required super.name, super.checksum, required super.type, @@ -19,7 +19,13 @@ class LocalAsset extends BaseAsset { super.isFavorite = false, super.livePhotoVideoId, this.orientation = 0, - }); + }) : remoteAssetId = remoteId; + + @override + String? get localId => id; + + @override + String? get remoteId => remoteAssetId; @override AssetState get storage => remoteId == null ? AssetState.local : AssetState.merged; diff --git a/mobile/lib/domain/models/asset/remote_asset.model.dart b/mobile/lib/domain/models/asset/remote_asset.model.dart index 8648255167..4974dc9118 100644 --- a/mobile/lib/domain/models/asset/remote_asset.model.dart +++ b/mobile/lib/domain/models/asset/remote_asset.model.dart @@ -5,7 +5,7 @@ enum AssetVisibility { timeline, hidden, archive, locked } // Model for an asset stored in the server class RemoteAsset extends BaseAsset { final String id; - final String? localId; + final String? localAssetId; final String? thumbHash; final AssetVisibility visibility; final String ownerId; @@ -13,7 +13,7 @@ class RemoteAsset extends BaseAsset { const RemoteAsset({ required this.id, - this.localId, + String? localId, required super.name, required this.ownerId, required super.checksum, @@ -28,7 +28,13 @@ class RemoteAsset extends BaseAsset { this.visibility = AssetVisibility.timeline, super.livePhotoVideoId, this.stackId, - }); + }) : localAssetId = localId; + + @override + String? get localId => localAssetId; + + @override + String? get remoteId => id; @override AssetState get storage => localId == null ? AssetState.remote : AssetState.merged; diff --git a/mobile/lib/domain/models/search_result.model.dart b/mobile/lib/domain/models/search_result.model.dart index bae8b8e821..947bc6192f 100644 --- a/mobile/lib/domain/models/search_result.model.dart +++ b/mobile/lib/domain/models/search_result.model.dart @@ -3,27 +3,30 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; class SearchResult { final List assets; + final double scrollOffset; final int? nextPage; - const SearchResult({required this.assets, this.nextPage}); + const SearchResult({required this.assets, this.scrollOffset = 0.0, this.nextPage}); - int get totalAssets => assets.length; - - SearchResult copyWith({List? assets, int? nextPage}) { - return SearchResult(assets: assets ?? this.assets, nextPage: nextPage ?? this.nextPage); + SearchResult copyWith({List? assets, int? nextPage, double? scrollOffset}) { + return SearchResult( + assets: assets ?? this.assets, + nextPage: nextPage ?? this.nextPage, + scrollOffset: scrollOffset ?? this.scrollOffset, + ); } @override - String toString() => 'SearchResult(assets: $assets, nextPage: $nextPage)'; + String toString() => 'SearchResult(assets: ${assets.length}, nextPage: $nextPage, scrollOffset: $scrollOffset)'; @override bool operator ==(covariant SearchResult other) { if (identical(this, other)) return true; final listEquals = const DeepCollectionEquality().equals; - return listEquals(other.assets, assets) && other.nextPage == nextPage; + return listEquals(other.assets, assets) && other.nextPage == nextPage && other.scrollOffset == scrollOffset; } @override - int get hashCode => assets.hashCode ^ nextPage.hashCode; + int get hashCode => assets.hashCode ^ nextPage.hashCode ^ scrollOffset.hashCode; } diff --git a/mobile/lib/domain/models/setting.model.dart b/mobile/lib/domain/models/setting.model.dart index f427d93285..2c46507331 100644 --- a/mobile/lib/domain/models/setting.model.dart +++ b/mobile/lib/domain/models/setting.model.dart @@ -6,6 +6,7 @@ enum Setting { showStorageIndicator(StoreKey.storageIndicator, true), loadOriginal(StoreKey.loadOriginal, false), loadOriginalVideo(StoreKey.loadOriginalVideo, false), + autoPlayVideo(StoreKey.autoPlayVideo, true), preferRemoteImage(StoreKey.preferRemoteImage, false), advancedTroubleshooting(StoreKey.advancedTroubleshooting, false), enableBackup(StoreKey.enableBackup, false); diff --git a/mobile/lib/domain/models/store.model.dart b/mobile/lib/domain/models/store.model.dart index 6dcd81774a..d8404db409 100644 --- a/mobile/lib/domain/models/store.model.dart +++ b/mobile/lib/domain/models/store.model.dart @@ -70,13 +70,18 @@ enum StoreKey { // Read-only Mode settings readonlyModeEnabled._(138), + autoPlayVideo._(139), + // Experimental stuff photoManagerCustomFilter._(1000), betaPromptShown._(1001), betaTimeline._(1002), enableBackup._(1003), useWifiForUploadVideos._(1004), - useWifiForUploadPhotos._(1005); + useWifiForUploadPhotos._(1005), + needBetaMigration._(1006), + // TODO: Remove this after patching open-api + shouldResetSync._(1007); const StoreKey._(this.id); final int id; diff --git a/mobile/lib/domain/models/user.model.dart b/mobile/lib/domain/models/user.model.dart index aaf6d81934..380295b4b3 100644 --- a/mobile/lib/domain/models/user.model.dart +++ b/mobile/lib/domain/models/user.model.dart @@ -1,7 +1,36 @@ // ignore_for_file: public_member_api_docs, sort_constructors_first import 'dart:convert'; +import 'dart:ui'; -import 'package:immich_mobile/domain/models/user_metadata.model.dart'; +enum AvatarColor { + // do not change this order or reuse indices for other purposes, adding is OK + primary("primary"), + pink("pink"), + red("red"), + yellow("yellow"), + blue("blue"), + green("green"), + purple("purple"), + orange("orange"), + gray("gray"), + amber("amber"); + + final String value; + const AvatarColor(this.value); + + Color toColor({bool isDarkTheme = false}) => switch (this) { + AvatarColor.primary => isDarkTheme ? const Color(0xFFABCBFA) : const Color(0xFF4250AF), + AvatarColor.pink => const Color.fromARGB(255, 244, 114, 182), + AvatarColor.red => const Color.fromARGB(255, 239, 68, 68), + AvatarColor.yellow => const Color.fromARGB(255, 234, 179, 8), + AvatarColor.blue => const Color.fromARGB(255, 59, 130, 246), + AvatarColor.green => const Color.fromARGB(255, 22, 163, 74), + AvatarColor.purple => const Color.fromARGB(255, 147, 51, 234), + AvatarColor.orange => const Color.fromARGB(255, 234, 88, 12), + AvatarColor.gray => const Color.fromARGB(255, 75, 85, 99), + AvatarColor.amber => const Color.fromARGB(255, 217, 119, 6), + }; +} // TODO: Rename to User once Isar is removed class UserDto { @@ -9,7 +38,7 @@ class UserDto { final String email; final String name; final bool isAdmin; - final DateTime updatedAt; + final DateTime? updatedAt; final AvatarColor avatarColor; @@ -31,8 +60,8 @@ class UserDto { required this.id, required this.email, required this.name, - required this.isAdmin, - required this.updatedAt, + this.isAdmin = false, + this.updatedAt, required this.profileChangedAt, this.avatarColor = AvatarColor.primary, this.memoryEnabled = true, @@ -99,7 +128,8 @@ profileChangedAt: $profileChangedAt if (identical(this, other)) return true; return other.id == id && - other.updatedAt.isAtSameMomentAs(updatedAt) && + ((updatedAt == null && other.updatedAt == null) || + (updatedAt != null && other.updatedAt != null && other.updatedAt!.isAtSameMomentAs(updatedAt!))) && other.avatarColor == avatarColor && other.email == email && other.name == name && diff --git a/mobile/lib/domain/models/user_metadata.model.dart b/mobile/lib/domain/models/user_metadata.model.dart index c477be1a41..af404051a7 100644 --- a/mobile/lib/domain/models/user_metadata.model.dart +++ b/mobile/lib/domain/models/user_metadata.model.dart @@ -1,4 +1,4 @@ -import 'dart:ui'; +import 'package:immich_mobile/domain/models/user.model.dart'; enum UserMetadataKey { // do not change this order! @@ -7,36 +7,6 @@ enum UserMetadataKey { license, } -enum AvatarColor { - // do not change this order or reuse indices for other purposes, adding is OK - primary("primary"), - pink("pink"), - red("red"), - yellow("yellow"), - blue("blue"), - green("green"), - purple("purple"), - orange("orange"), - gray("gray"), - amber("amber"); - - final String value; - const AvatarColor(this.value); - - Color toColor({bool isDarkTheme = false}) => switch (this) { - AvatarColor.primary => isDarkTheme ? const Color(0xFFABCBFA) : const Color(0xFF4250AF), - AvatarColor.pink => const Color.fromARGB(255, 244, 114, 182), - AvatarColor.red => const Color.fromARGB(255, 239, 68, 68), - AvatarColor.yellow => const Color.fromARGB(255, 234, 179, 8), - AvatarColor.blue => const Color.fromARGB(255, 59, 130, 246), - AvatarColor.green => const Color.fromARGB(255, 22, 163, 74), - AvatarColor.purple => const Color.fromARGB(255, 147, 51, 234), - AvatarColor.orange => const Color.fromARGB(255, 234, 88, 12), - AvatarColor.gray => const Color.fromARGB(255, 75, 85, 99), - AvatarColor.amber => const Color.fromARGB(255, 217, 119, 6), - }; -} - class Onboarding { final bool isOnboarded; diff --git a/mobile/lib/domain/services/asset.service.dart b/mobile/lib/domain/services/asset.service.dart index df34a41e54..7f8ade313c 100644 --- a/mobile/lib/domain/services/asset.service.dart +++ b/mobile/lib/domain/services/asset.service.dart @@ -1,21 +1,20 @@ +import 'package:immich_mobile/domain/models/album/local_album.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/exif.model.dart'; +import 'package:immich_mobile/extensions/platform_extensions.dart'; import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/remote_asset.repository.dart'; import 'package:immich_mobile/infrastructure/utils/exif.converter.dart'; -import 'package:platform/platform.dart'; class AssetService { final RemoteAssetRepository _remoteAssetRepository; final DriftLocalAssetRepository _localAssetRepository; - final Platform _platform; const AssetService({ required RemoteAssetRepository remoteAssetRepository, required DriftLocalAssetRepository localAssetRepository, }) : _remoteAssetRepository = remoteAssetRepository, - _localAssetRepository = localAssetRepository, - _platform = const LocalPlatform(); + _localAssetRepository = localAssetRepository; Future getAsset(BaseAsset asset) { final id = asset is LocalAsset ? asset.id : (asset as RemoteAsset).id; @@ -27,19 +26,26 @@ class AssetService { return asset is LocalAsset ? _localAssetRepository.watch(id) : _remoteAssetRepository.watch(id); } + Future> getLocalAssetsByChecksum(String checksum) { + return _localAssetRepository.getByChecksum(checksum); + } + + Future getRemoteAssetByChecksum(String checksum) { + return _remoteAssetRepository.getByChecksum(checksum); + } + Future getRemoteAsset(String id) { return _remoteAssetRepository.get(id); } Future> getStack(RemoteAsset asset) async { if (asset.stackId == null) { - return []; + return const []; } - return _remoteAssetRepository.getStackChildren(asset).then((assets) { - // Include the primary asset in the stack as the first item - return [asset, ...assets]; - }); + final stack = await _remoteAssetRepository.getStackChildren(asset); + // Include the primary asset in the stack as the first item + return [asset, ...stack]; } Future getExif(BaseAsset asset) async { @@ -62,7 +68,7 @@ class AssetService { width = exif?.width ?? asset.width?.toDouble(); height = exif?.height ?? asset.height?.toDouble(); } else if (asset is LocalAsset) { - isFlipped = _platform.isAndroid && (asset.orientation == 90 || asset.orientation == 270); + isFlipped = CurrentPlatform.isAndroid && (asset.orientation == 90 || asset.orientation == 270); width = asset.width?.toDouble(); height = asset.height?.toDouble(); } else { @@ -78,8 +84,8 @@ class AssetService { return 1.0; } - Future> getPlaces() { - return _remoteAssetRepository.getPlaces(); + Future> getPlaces(String userId) { + return _remoteAssetRepository.getPlaces(userId); } Future<(int local, int remote)> getAssetCounts() async { @@ -89,4 +95,8 @@ class AssetService { Future getLocalHashedCount() { return _localAssetRepository.getHashedCount(); } + + Future> getSourceAlbums(String localAssetId, {BackupSelection? backupSelection}) { + return _localAssetRepository.getSourceAlbums(localAssetId, backupSelection: backupSelection); + } } diff --git a/mobile/lib/domain/services/background_worker.service.dart b/mobile/lib/domain/services/background_worker.service.dart index 9f366ad30b..78ba5b7088 100644 --- a/mobile/lib/domain/services/background_worker.service.dart +++ b/mobile/lib/domain/services/background_worker.service.dart @@ -1,19 +1,26 @@ import 'dart:async'; +import 'dart:io'; import 'dart:ui'; import 'package:background_downloader/background_downloader.dart'; +import 'package:cancellation_token_http/http.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/constants.dart'; -import 'package:immich_mobile/domain/utils/isolate_lock_manager.dart'; +import 'package:immich_mobile/domain/services/log.service.dart'; +import 'package:immich_mobile/entities/store.entity.dart'; +import 'package:immich_mobile/extensions/network_capability_extensions.dart'; +import 'package:immich_mobile/extensions/platform_extensions.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/logger_db.repository.dart'; import 'package:immich_mobile/platform/background_worker_api.g.dart'; +import 'package:immich_mobile/platform/background_worker_lock_api.g.dart'; import 'package:immich_mobile/providers/app_settings.provider.dart'; import 'package:immich_mobile/providers/background_sync.provider.dart'; import 'package:immich_mobile/providers/backup/drift_backup.provider.dart'; import 'package:immich_mobile/providers/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/platform.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; import 'package:immich_mobile/repositories/file_media.repository.dart'; import 'package:immich_mobile/services/app_settings.service.dart'; @@ -21,9 +28,11 @@ import 'package:immich_mobile/services/auth.service.dart'; import 'package:immich_mobile/services/localization.service.dart'; import 'package:immich_mobile/services/upload.service.dart'; import 'package:immich_mobile/utils/bootstrap.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; import 'package:immich_mobile/utils/http_ssl_options.dart'; import 'package:isar/isar.dart'; import 'package:logging/logging.dart'; +import 'package:worker_manager/worker_manager.dart'; class BackgroundWorkerFgService { final BackgroundWorkerFgHostApi _foregroundHostApi; @@ -33,17 +42,31 @@ class BackgroundWorkerFgService { // TODO: Move this call to native side once old timeline is removed Future enable() => _foregroundHostApi.enable(); + Future saveNotificationMessage(String title, String body) => + _foregroundHostApi.saveNotificationMessage(title, body); + + Future configure({int? minimumDelaySeconds, bool? requireCharging}) => _foregroundHostApi.configure( + BackgroundWorkerSettings( + minimumDelaySeconds: + minimumDelaySeconds ?? + Store.get(AppSettingsEnum.backupTriggerDelay.storeKey, AppSettingsEnum.backupTriggerDelay.defaultValue), + requiresCharging: + requireCharging ?? + Store.get(AppSettingsEnum.backupRequireCharging.storeKey, AppSettingsEnum.backupRequireCharging.defaultValue), + ), + ); + Future disable() => _foregroundHostApi.disable(); } class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi { - late final ProviderContainer _ref; + ProviderContainer? _ref; final Isar _isar; final Drift _drift; final DriftLogger _driftLogger; final BackgroundWorkerBgHostApi _backgroundHostApi; - final Logger _logger = Logger('BackgroundUploadBgService'); - late final IsolateLockManager _lockManager; + final CancellationToken _cancellationToken = CancellationToken(); + final Logger _logger = Logger('BackgroundWorkerBgService'); bool _isCleanedUp = false; @@ -59,49 +82,39 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi { driftProvider.overrideWith(driftOverride(drift)), ], ); - _lockManager = IsolateLockManager(onCloseRequest: _cleanup); BackgroundWorkerFlutterApi.setUp(this); } - bool get _isBackupEnabled => _ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableBackup); + bool get _isBackupEnabled => _ref?.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableBackup) ?? false; Future init() async { try { - await loadTranslations(); HttpSSLOptions.apply(applyNative: false); - await _ref.read(authServiceProvider).setOpenApiServiceEndpoint(); - // Initialize the file downloader - await FileDownloader().configure( - globalConfig: [ - // maxConcurrent: 6, maxConcurrentByHost(server):6, maxConcurrentByGroup: 3 - (Config.holdingQueue, (6, 6, 3)), - // On Android, if files are larger than 256MB, run in foreground service - (Config.runInForegroundIfFileLargerThan, 256), - ], + await Future.wait( + [ + loadTranslations(), + workerManager.init(dynamicSpawning: true), + _ref?.read(authServiceProvider).setOpenApiServiceEndpoint(), + // Initialize the file downloader + FileDownloader().configure( + globalConfig: [ + // maxConcurrent: 6, maxConcurrentByHost(server):6, maxConcurrentByGroup: 3 + (Config.holdingQueue, (6, 6, 3)), + // On Android, if files are larger than 256MB, run in foreground service + (Config.runInForegroundIfFileLargerThan, 256), + ], + ), + FileDownloader().trackTasksInGroup(kDownloadGroupLivePhoto, markDownloadedComplete: false), + FileDownloader().trackTasks(), + _ref?.read(fileMediaRepositoryProvider).enableBackgroundAccess(), + ].nonNulls, ); - await FileDownloader().trackTasksInGroup(kDownloadGroupLivePhoto, markDownloadedComplete: false); - await FileDownloader().trackTasks(); + configureFileDownloaderNotifications(); - await _ref.read(fileMediaRepositoryProvider).enableBackgroundAccess(); - // Notify the host that the background upload service has been initialized and is ready to use - debugPrint("Acquiring background worker lock"); - if (await _lockManager.acquireLock().timeout( - const Duration(seconds: 5), - onTimeout: () { - _lockManager.cancel(); - return false; - }, - )) { - _logger.info("Acquired background worker lock"); - await _backgroundHostApi.onInitialized(); - return; - } - - _logger.warning("Failed to acquire background worker lock"); - await _cleanup(); - await _backgroundHostApi.close(); + // Notify the host that the background worker service has been initialized and is ready to use + _backgroundHostApi.onInitialized(); } catch (error, stack) { _logger.severe("Failed to initialize background worker", error, stack); _backgroundHostApi.close(); @@ -110,30 +123,33 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi { @override Future onAndroidUpload() async { + _logger.info('Android background processing started'); + final sw = Stopwatch()..start(); try { - _logger.info('Android background processing started'); - final sw = Stopwatch()..start(); - - await _syncAssets(hashTimeout: Duration(minutes: _isBackupEnabled ? 3 : 6)); - await _handleBackup(processBulk: false); - - sw.stop(); - _logger.info("Android background processing completed in ${sw.elapsed.inSeconds}s"); + if (!await _syncAssets(hashTimeout: Duration(minutes: _isBackupEnabled ? 3 : 6))) { + _logger.warning("Remote sync did not complete successfully, skipping backup"); + return; + } + await _handleBackup(); } catch (error, stack) { _logger.severe("Failed to complete Android background processing", error, stack); } finally { + sw.stop(); + _logger.info("Android background processing completed in ${sw.elapsed.inSeconds}s"); await _cleanup(); } } @override Future onIosUpload(bool isRefresh, int? maxSeconds) async { + _logger.info('iOS background upload started with maxSeconds: ${maxSeconds}s'); + final sw = Stopwatch()..start(); try { - _logger.info('iOS background upload started with maxSeconds: ${maxSeconds}s'); - final sw = Stopwatch()..start(); - final timeout = isRefresh ? const Duration(seconds: 5) : Duration(minutes: _isBackupEnabled ? 3 : 6); - await _syncAssets(hashTimeout: timeout); + if (!await _syncAssets(hashTimeout: timeout)) { + _logger.warning("Remote sync did not complete successfully, skipping backup"); + return; + } final backupFuture = _handleBackup(); if (maxSeconds != null) { @@ -141,12 +157,11 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi { } else { await backupFuture; } - - sw.stop(); - _logger.info("iOS background upload completed in ${sw.elapsed.inSeconds}s"); } catch (error, stack) { _logger.severe("Failed to complete iOS background upload", error, stack); } finally { + sw.stop(); + _logger.info("iOS background upload completed in ${sw.elapsed.inSeconds}s"); await _cleanup(); } } @@ -157,80 +172,121 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi { try { await _cleanup(); } catch (error, stack) { - debugPrint('Failed to cleanup background worker: $error with stack: $stack'); + dPrint(() => 'Failed to cleanup background worker: $error with stack: $stack'); } } Future _cleanup() async { - if (_isCleanedUp) { + // If ref is null, it means the service was never initialized properly + if (_isCleanedUp || _ref == null) { return; } try { _isCleanedUp = true; + final backgroundSyncManager = _ref?.read(backgroundSyncProvider); + final nativeSyncApi = _ref?.read(nativeSyncApiProvider); + _ref?.dispose(); + _ref = null; + + _cancellationToken.cancel(); _logger.info("Cleaning up background worker"); - await _ref.read(backgroundSyncProvider).cancel(); - await _ref.read(backgroundSyncProvider).cancelLocal(); + final cleanupFutures = [ + nativeSyncApi?.cancelHashing(), + workerManager.dispose().catchError((_) async { + // Discard any errors on the dispose call + return; + }), + LogService.I.dispose(), + Store.dispose(), + _drift.close(), + _driftLogger.close(), + backgroundSyncManager?.cancel(), + ]; + if (_isar.isOpen) { - await _isar.close(); + cleanupFutures.add(_isar.close()); } - await _drift.close(); - await _driftLogger.close(); - _ref.dispose(); - _lockManager.releaseLock(); + await Future.wait(cleanupFutures.nonNulls); _logger.info("Background worker resources cleaned up"); } catch (error, stack) { - debugPrint('Failed to cleanup background worker: $error with stack: $stack'); + dPrint(() => 'Failed to cleanup background worker: $error with stack: $stack'); } } - Future _handleBackup({bool processBulk = true}) async { - if (!_isBackupEnabled) { - return; + Future _handleBackup() async { + await runZonedGuarded( + () async { + if (_isCleanedUp) { + return; + } + + if (!_isBackupEnabled) { + _logger.info("Backup is disabled. Skipping backup routine"); + return; + } + + final currentUser = _ref?.read(currentUserProvider); + if (currentUser == null) { + _logger.warning("No current user found. Skipping backup from background"); + return; + } + + if (Platform.isIOS) { + return _ref?.read(driftBackupProvider.notifier).handleBackupResume(currentUser.id); + } + + final networkCapabilities = await _ref?.read(connectivityApiProvider).getCapabilities() ?? []; + return _ref + ?.read(uploadServiceProvider) + .startBackupWithHttpClient(currentUser.id, networkCapabilities.hasWifi, _cancellationToken); + }, + (error, stack) { + dPrint(() => "Error in backup zone $error, $stack"); + }, + ); + } + + Future _syncAssets({Duration? hashTimeout}) async { + await _ref?.read(backgroundSyncProvider).syncLocal(); + if (_isCleanedUp) { + return false; } - final currentUser = _ref.read(currentUserProvider); - if (currentUser == null) { - return; + final isSuccess = await _ref?.read(backgroundSyncProvider).syncRemote() ?? false; + if (_isCleanedUp) { + return isSuccess; } - if (processBulk) { - return _ref.read(driftBackupProvider.notifier).handleBackupResume(currentUser.id); + var hashFuture = _ref?.read(backgroundSyncProvider).hashAssets(); + if (hashTimeout != null && hashFuture != null) { + hashFuture = hashFuture.timeout( + hashTimeout, + onTimeout: () { + // Consume cancellation errors as we want to continue processing + }, + ); } - final activeTask = await _ref.read(uploadServiceProvider).getActiveTasks(currentUser.id); - if (activeTask.isNotEmpty) { - await _ref.read(uploadServiceProvider).resumeBackup(); - } else { - await _ref.read(uploadServiceProvider).startBackupSerial(currentUser.id); + await hashFuture; + return isSuccess; + } +} + +class BackgroundWorkerLockService { + final BackgroundWorkerLockApi _hostApi; + const BackgroundWorkerLockService(this._hostApi); + + Future lock() async { + if (CurrentPlatform.isAndroid) { + return _hostApi.lock(); } } - Future _syncAssets({Duration? hashTimeout}) async { - final futures = >[]; - - final localSyncFuture = _ref.read(backgroundSyncProvider).syncLocal().then((_) async { - if (_isCleanedUp) { - return; - } - - var hashFuture = _ref.read(backgroundSyncProvider).hashAssets(); - if (hashTimeout != null) { - hashFuture = hashFuture.timeout( - hashTimeout, - onTimeout: () { - // Consume cancellation errors as we want to continue processing - }, - ); - } - - return hashFuture; - }); - - futures.add(localSyncFuture); - futures.add(_ref.read(backgroundSyncProvider).syncRemote()); - - await Future.wait(futures); + Future unlock() async { + if (CurrentPlatform.isAndroid) { + return _hostApi.unlock(); + } } } @@ -242,6 +298,6 @@ Future backgroundSyncNativeEntrypoint() async { DartPluginRegistrant.ensureInitialized(); final (isar, drift, logDB) = await Bootstrap.initDB(); - await Bootstrap.initDomain(isar, drift, logDB, shouldBufferLogs: false); + await Bootstrap.initDomain(isar, drift, logDB, shouldBufferLogs: false, listenStoreUpdates: false); await BackgroundWorkerBgService(isar: isar, drift: drift, driftLogger: logDB).init(); } diff --git a/mobile/lib/domain/services/hash.service.dart b/mobile/lib/domain/services/hash.service.dart index 8044b298d3..90f29b8bc1 100644 --- a/mobile/lib/domain/services/hash.service.dart +++ b/mobile/lib/domain/services/hash.service.dart @@ -1,20 +1,18 @@ -import 'dart:convert'; - +import 'package:flutter/services.dart'; import 'package:immich_mobile/constants/constants.dart'; import 'package:immich_mobile/domain/models/album/local_album.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart'; -import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart'; import 'package:immich_mobile/platform/native_sync_api.g.dart'; import 'package:logging/logging.dart'; +const String _kHashCancelledCode = "HASH_CANCELLED"; + class HashService { - final int batchSizeLimit; - final int batchFileLimit; + final int _batchSize; final DriftLocalAlbumRepository _localAlbumRepository; final DriftLocalAssetRepository _localAssetRepository; - final StorageRepository _storageRepository; final NativeSyncApi _nativeSyncApi; final bool Function()? _cancelChecker; final _log = Logger('HashService'); @@ -22,37 +20,42 @@ class HashService { HashService({ required DriftLocalAlbumRepository localAlbumRepository, required DriftLocalAssetRepository localAssetRepository, - required StorageRepository storageRepository, required NativeSyncApi nativeSyncApi, bool Function()? cancelChecker, - this.batchSizeLimit = kBatchHashSizeLimit, - this.batchFileLimit = kBatchHashFileLimit, + int? batchSize, }) : _localAlbumRepository = localAlbumRepository, _localAssetRepository = localAssetRepository, - _storageRepository = storageRepository, _cancelChecker = cancelChecker, - _nativeSyncApi = nativeSyncApi; + _nativeSyncApi = nativeSyncApi, + _batchSize = batchSize ?? kBatchHashFileLimit; bool get isCancelled => _cancelChecker?.call() ?? false; Future hashAssets() async { _log.info("Starting hashing of assets"); final Stopwatch stopwatch = Stopwatch()..start(); - // Sorted by backupSelection followed by isCloud - final localAlbums = await _localAlbumRepository.getAll( - sortBy: {SortLocalAlbumsBy.backupSelection, SortLocalAlbumsBy.isIosSharedAlbum}, - ); + try { + // Sorted by backupSelection followed by isCloud + final localAlbums = await _localAlbumRepository.getBackupAlbums(); - for (final album in localAlbums) { - if (isCancelled) { - _log.warning("Hashing cancelled. Stopped processing albums."); - break; - } + for (final album in localAlbums) { + if (isCancelled) { + _log.warning("Hashing cancelled. Stopped processing albums."); + break; + } - final assetsToHash = await _localAlbumRepository.getAssetsToHash(album.id); - if (assetsToHash.isNotEmpty) { - await _hashAssets(album, assetsToHash); + final assetsToHash = await _localAlbumRepository.getAssetsToHash(album.id); + if (assetsToHash.isNotEmpty) { + await _hashAssets(album, assetsToHash); + } } + } on PlatformException catch (e) { + if (e.code == _kHashCancelledCode) { + _log.warning("Hashing cancelled by platform"); + return; + } + } catch (e, s) { + _log.severe("Error during hashing", e, s); } stopwatch.stop(); @@ -63,8 +66,7 @@ class HashService { /// with hash for those that were successfully hashed. Hashes are looked up in a table /// [LocalAssetHashEntity] by local id. Only missing entries are newly hashed and added to the DB. Future _hashAssets(LocalAlbum album, List assetsToHash) async { - int bytesProcessed = 0; - final toHash = <_AssetToPath>[]; + final toHash = {}; for (final asset in assetsToHash) { if (isCancelled) { @@ -72,21 +74,10 @@ class HashService { return; } - final file = await _storageRepository.getFileForAsset(asset.id); - if (file == null) { - _log.warning( - "Cannot get file for asset ${asset.id}, name: ${asset.name}, created on: ${asset.createdAt} from album: ${album.name}", - ); - continue; - } - - bytesProcessed += await file.length(); - toHash.add(_AssetToPath(asset: asset, path: file.path)); - - if (toHash.length >= batchFileLimit || bytesProcessed >= batchSizeLimit) { + toHash[asset.id] = asset; + if (toHash.length == _batchSize) { await _processBatch(album, toHash); toHash.clear(); - bytesProcessed = 0; } } @@ -94,33 +85,36 @@ class HashService { } /// Processes a batch of assets. - Future _processBatch(LocalAlbum album, List<_AssetToPath> toHash) async { + Future _processBatch(LocalAlbum album, Map toHash) async { if (toHash.isEmpty) { return; } _log.fine("Hashing ${toHash.length} files"); - final hashed = []; - final hashes = await _nativeSyncApi.hashPaths(toHash.map((e) => e.path).toList()); + final hashed = {}; + final hashResults = await _nativeSyncApi.hashAssets( + toHash.keys.toList(), + allowNetworkAccess: album.backupSelection == BackupSelection.selected, + ); assert( - hashes.length == toHash.length, - "Hashes length does not match toHash length: ${hashes.length} != ${toHash.length}", + hashResults.length == toHash.length, + "Hashes length does not match toHash length: ${hashResults.length} != ${toHash.length}", ); - for (int i = 0; i < hashes.length; i++) { + for (int i = 0; i < hashResults.length; i++) { if (isCancelled) { _log.warning("Hashing cancelled. Stopped processing batch."); return; } - final hash = hashes[i]; - final asset = toHash[i].asset; - if (hash?.length == 20) { - hashed.add(asset.copyWith(checksum: base64.encode(hash!))); + final hashResult = hashResults[i]; + if (hashResult.hash != null) { + hashed[hashResult.assetId] = hashResult.hash!; } else { + final asset = toHash[hashResult.assetId]; _log.warning( - "Failed to hash file for ${asset.id}: ${asset.name} created at ${asset.createdAt} from album: ${album.name}", + "Failed to hash asset with id: ${hashResult.assetId}, name: ${asset?.name}, createdAt: ${asset?.createdAt}, from album: ${album.name}. Error: ${hashResult.error ?? "unknown"}", ); } } @@ -128,13 +122,5 @@ class HashService { _log.fine("Hashed ${hashed.length}/${toHash.length} assets"); await _localAssetRepository.updateHashes(hashed); - await _storageRepository.clearCache(); } } - -class _AssetToPath { - final LocalAsset asset; - final String path; - - const _AssetToPath({required this.asset, required this.path}); -} diff --git a/mobile/lib/domain/services/local_sync.service.dart b/mobile/lib/domain/services/local_sync.service.dart index 5ab10bdf09..ca356c80d8 100644 --- a/mobile/lib/domain/services/local_sync.service.dart +++ b/mobile/lib/domain/services/local_sync.service.dart @@ -1,29 +1,24 @@ import 'dart:async'; import 'package:collection/collection.dart'; -import 'package:flutter/widgets.dart'; +import 'package:flutter/foundation.dart'; import 'package:immich_mobile/domain/models/album/local_album.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; +import 'package:immich_mobile/extensions/platform_extensions.dart'; import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart'; import 'package:immich_mobile/platform/native_sync_api.g.dart'; import 'package:immich_mobile/utils/datetime_helpers.dart'; import 'package:immich_mobile/utils/diff.dart'; import 'package:logging/logging.dart'; -import 'package:platform/platform.dart'; class LocalSyncService { final DriftLocalAlbumRepository _localAlbumRepository; final NativeSyncApi _nativeSyncApi; - final Platform _platform; final Logger _log = Logger("DeviceSyncService"); - LocalSyncService({ - required DriftLocalAlbumRepository localAlbumRepository, - required NativeSyncApi nativeSyncApi, - Platform? platform, - }) : _localAlbumRepository = localAlbumRepository, - _nativeSyncApi = nativeSyncApi, - _platform = platform ?? const LocalPlatform(); + LocalSyncService({required DriftLocalAlbumRepository localAlbumRepository, required NativeSyncApi nativeSyncApi}) + : _localAlbumRepository = localAlbumRepository, + _nativeSyncApi = nativeSyncApi; Future sync({bool full = false}) async { final Stopwatch stopwatch = Stopwatch()..start(); @@ -53,14 +48,14 @@ class LocalSyncService { final dbAlbums = await _localAlbumRepository.getAll(); // On Android, we need to sync all albums since it is not possible to // detect album deletions from the native side - if (_platform.isAndroid) { + if (CurrentPlatform.isAndroid) { for (final album in dbAlbums) { final deviceIds = await _nativeSyncApi.getAssetIdsForAlbum(album.id); await _localAlbumRepository.syncDeletes(album.id, deviceIds); } } - if (_platform.isIOS) { + if (CurrentPlatform.isIOS) { // On iOS, we need to full sync albums that are marked as cloud as the delta sync // does not include changes for cloud albums. If ignoreIcloudAssets is enabled, // remove the albums from the local database from the previous sync @@ -286,7 +281,7 @@ extension on Iterable { (e) => LocalAlbum( id: e.id, name: e.name, - updatedAt: tryFromSecondsSinceEpoch(e.updatedAt) ?? DateTime.now(), + updatedAt: tryFromSecondsSinceEpoch(e.updatedAt, isUtc: true) ?? DateTime.timestamp(), assetCount: e.assetCount, ), ).toList(); @@ -301,8 +296,8 @@ extension on Iterable { name: e.name, checksum: null, type: AssetType.values.elementAtOrNull(e.type) ?? AssetType.other, - createdAt: tryFromSecondsSinceEpoch(e.createdAt) ?? DateTime.now(), - updatedAt: tryFromSecondsSinceEpoch(e.updatedAt) ?? DateTime.now(), + createdAt: tryFromSecondsSinceEpoch(e.createdAt, isUtc: true) ?? DateTime.timestamp(), + updatedAt: tryFromSecondsSinceEpoch(e.updatedAt, isUtc: true) ?? DateTime.timestamp(), width: e.width, height: e.height, durationInSeconds: e.durationInSeconds, diff --git a/mobile/lib/domain/services/log.service.dart b/mobile/lib/domain/services/log.service.dart index d21cb7ab09..64010b9220 100644 --- a/mobile/lib/domain/services/log.service.dart +++ b/mobile/lib/domain/services/log.service.dart @@ -1,11 +1,11 @@ import 'dart:async'; -import 'package:flutter/foundation.dart'; import 'package:immich_mobile/constants/constants.dart'; import 'package:immich_mobile/domain/models/log.model.dart'; import 'package:immich_mobile/domain/models/store.model.dart'; import 'package:immich_mobile/infrastructure/repositories/log.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/store.repository.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; import 'package:logging/logging.dart'; /// Service responsible for handling application logging. @@ -66,13 +66,12 @@ class LogService { } void _handleLogRecord(LogRecord r) { - if (kDebugMode) { - debugPrint( - '[${r.level.name}] [${r.time}] [${r.loggerName}] ${r.message}' - '${r.error == null ? '' : '\nError: ${r.error}'}' - '${r.stackTrace == null ? '' : '\nStack: ${r.stackTrace}'}', - ); - } + dPrint( + () => + '[${r.level.name}] [${r.time}] [${r.loggerName}] ${r.message}' + '${r.error == null ? '' : '\nError: ${r.error}'}' + '${r.stackTrace == null ? '' : '\nStack: ${r.stackTrace}'}', + ); final record = LogMessage( message: r.message, diff --git a/mobile/lib/domain/services/partner.service.dart b/mobile/lib/domain/services/partner.service.dart index 7733b5be6b..ce1bd9557b 100644 --- a/mobile/lib/domain/services/partner.service.dart +++ b/mobile/lib/domain/services/partner.service.dart @@ -1,7 +1,7 @@ -import 'package:flutter/foundation.dart'; import 'package:immich_mobile/domain/models/user.model.dart'; import 'package:immich_mobile/infrastructure/repositories/partner.repository.dart'; import 'package:immich_mobile/repositories/partner_api.repository.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; class DriftPartnerService { final DriftPartnerRepository _driftPartnerRepository; @@ -30,7 +30,7 @@ class DriftPartnerService { Future toggleShowInTimeline(String partnerId, String userId) async { final partner = await _driftPartnerRepository.getPartner(partnerId, userId); if (partner == null) { - debugPrint("Partner not found: $partnerId for user: $userId"); + dPrint(() => "Partner not found: $partnerId for user: $userId"); return; } diff --git a/mobile/lib/domain/services/remote_album.service.dart b/mobile/lib/domain/services/remote_album.service.dart index cc28dfafd5..13dfadb8d8 100644 --- a/mobile/lib/domain/services/remote_album.service.dart +++ b/mobile/lib/domain/services/remote_album.service.dart @@ -120,6 +120,10 @@ class RemoteAlbumService { return _repository.getSharedUsers(albumId); } + Future getUserRole(String albumId, String userId) { + return _repository.getUserRole(albumId, userId); + } + Future> getAssets(String albumId) { return _repository.getAssets(albumId); } diff --git a/mobile/lib/domain/services/store.service.dart b/mobile/lib/domain/services/store.service.dart index 3347134ae6..0098c3d262 100644 --- a/mobile/lib/domain/services/store.service.dart +++ b/mobile/lib/domain/services/store.service.dart @@ -10,7 +10,7 @@ class StoreService { /// In-memory cache. Keys are [StoreKey.id] final Map _cache = {}; - late final StreamSubscription> _storeUpdateSubscription; + StreamSubscription>? _storeUpdateSubscription; StoreService._({required IStoreRepository isarStoreRepository}) : _storeRepository = isarStoreRepository; @@ -24,15 +24,17 @@ class StoreService { } // TODO: Replace the implementation with the one from create after removing the typedef - static Future init({required IStoreRepository storeRepository}) async { - _instance ??= await create(storeRepository: storeRepository); + static Future init({required IStoreRepository storeRepository, bool listenUpdates = true}) async { + _instance ??= await create(storeRepository: storeRepository, listenUpdates: listenUpdates); return _instance!; } - static Future create({required IStoreRepository storeRepository}) async { + static Future create({required IStoreRepository storeRepository, bool listenUpdates = true}) async { final instance = StoreService._(isarStoreRepository: storeRepository); await instance.populateCache(); - instance._storeUpdateSubscription = instance._listenForChange(); + if (listenUpdates) { + instance._storeUpdateSubscription = instance._listenForChange(); + } return instance; } @@ -50,8 +52,8 @@ class StoreService { }); /// Disposes the store and cancels the subscription. To reuse the store call init() again - void dispose() async { - await _storeUpdateSubscription.cancel(); + Future dispose() async { + await _storeUpdateSubscription?.cancel(); _cache.clear(); } @@ -84,13 +86,13 @@ class StoreService { _cache.remove(key.id); } - /// Clears all values from thw store (cache and DB) + /// Clears all values from the store (cache and DB) Future clear() async { await _storeRepository.deleteAll(); _cache.clear(); } - bool get isBetaTimelineEnabled => tryGet(StoreKey.betaTimeline) ?? false; + bool get isBetaTimelineEnabled => tryGet(StoreKey.betaTimeline) ?? true; } class StoreKeyNotFoundException implements Exception { diff --git a/mobile/lib/domain/services/sync_linked_album.service.dart b/mobile/lib/domain/services/sync_linked_album.service.dart index 37e52e6c16..b61ca1c965 100644 --- a/mobile/lib/domain/services/sync_linked_album.service.dart +++ b/mobile/lib/domain/services/sync_linked_album.service.dart @@ -1,10 +1,11 @@ -import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/album/local_album.model.dart'; import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/remote_album.repository.dart'; import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; import 'package:immich_mobile/repositories/drift_album_api_repository.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; +import 'package:logging/logging.dart'; final syncLinkedAlbumServiceProvider = Provider( (ref) => SyncLinkedAlbumService( @@ -19,7 +20,9 @@ class SyncLinkedAlbumService { final DriftRemoteAlbumRepository _remoteAlbumRepository; final DriftAlbumApiRepository _albumApiRepository; - const SyncLinkedAlbumService(this._localAlbumRepository, this._remoteAlbumRepository, this._albumApiRepository); + SyncLinkedAlbumService(this._localAlbumRepository, this._remoteAlbumRepository, this._albumApiRepository); + + final _log = Logger("SyncLinkedAlbumService"); Future syncLinkedAlbums(String userId) async { final selectedAlbums = await _localAlbumRepository.getBackupAlbums(); @@ -28,17 +31,19 @@ class SyncLinkedAlbumService { selectedAlbums.map((localAlbum) async { final linkedRemoteAlbumId = localAlbum.linkedRemoteAlbumId; if (linkedRemoteAlbumId == null) { + _log.warning("No linked remote album ID found for local album: ${localAlbum.name}"); return; } final remoteAlbum = await _remoteAlbumRepository.get(linkedRemoteAlbumId); if (remoteAlbum == null) { + _log.warning("Linked remote album not found for ID: $linkedRemoteAlbumId"); return; } // get assets that are uploaded but not in the remote album final assetIds = await _remoteAlbumRepository.getLinkedAssetIds(userId, localAlbum.id, linkedRemoteAlbumId); - + _log.fine("Syncing ${assetIds.length} assets to remote album: ${remoteAlbum.name}"); if (assetIds.isNotEmpty) { final album = await _albumApiRepository.addAssets(remoteAlbum.id, assetIds); await _remoteAlbumRepository.addAssets(remoteAlbum.id, album.added); @@ -48,8 +53,12 @@ class SyncLinkedAlbumService { } Future manageLinkedAlbums(List localAlbums, String ownerId) async { - for (final album in localAlbums) { - await _processLocalAlbum(album, ownerId); + try { + for (final album in localAlbums) { + await _processLocalAlbum(album, ownerId); + } + } catch (error, stackTrace) { + _log.severe("Error managing linked albums", error, stackTrace); } } @@ -93,7 +102,7 @@ class SyncLinkedAlbumService { /// Creates a new remote album and links it to the local album Future _createAndLinkNewRemoteAlbum(LocalAlbum localAlbum) async { - debugPrint("Creating new remote album for local album: ${localAlbum.name}"); + dPrint(() => "Creating new remote album for local album: ${localAlbum.name}"); final newRemoteAlbum = await _albumApiRepository.createDriftAlbum(localAlbum.name, assetIds: []); await _remoteAlbumRepository.create(newRemoteAlbum, []); return _localAlbumRepository.linkRemoteAlbum(localAlbum.id, newRemoteAlbum.id); diff --git a/mobile/lib/domain/services/sync_stream.service.dart b/mobile/lib/domain/services/sync_stream.service.dart index f18f54258b..bec7e6afda 100644 --- a/mobile/lib/domain/services/sync_stream.service.dart +++ b/mobile/lib/domain/services/sync_stream.service.dart @@ -23,14 +23,16 @@ class SyncStreamService { bool get isCancelled => _cancelChecker?.call() ?? false; - Future sync() async { + Future sync() async { _logger.info("Remote sync request for user"); // Start the sync stream and handle events bool shouldReset = false; await _syncApiRepository.streamChanges(_handleEvents, onReset: () => shouldReset = true); if (shouldReset) { + _logger.info("Resetting sync state as requested by server"); await _syncApiRepository.streamChanges(_handleEvents); } + return true; } Future _handleEvents(List events, Function() abort, Function() reset) async { @@ -70,6 +72,8 @@ class SyncStreamService { Future _handleSyncData(SyncEntityType type, Iterable data) async { _logger.fine("Processing sync data for $type of length ${data.length}"); switch (type) { + case SyncEntityType.authUserV1: + return _syncStreamRepository.updateAuthUsersV1(data.cast()); case SyncEntityType.userV1: return _syncStreamRepository.updateUsersV1(data.cast()); case SyncEntityType.userDeleteV1: diff --git a/mobile/lib/domain/services/timeline.service.dart b/mobile/lib/domain/services/timeline.service.dart index ab623720b7..85fc5fc55d 100644 --- a/mobile/lib/domain/services/timeline.service.dart +++ b/mobile/lib/domain/services/timeline.service.dart @@ -16,7 +16,24 @@ typedef TimelineAssetSource = Future> Function(int index, int co typedef TimelineBucketSource = Stream> Function(); -typedef TimelineQuery = ({TimelineAssetSource assetSource, TimelineBucketSource bucketSource}); +typedef TimelineQuery = ({TimelineAssetSource assetSource, TimelineBucketSource bucketSource, TimelineOrigin origin}); + +enum TimelineOrigin { + main, + localAlbum, + remoteAlbum, + remoteAssets, + favorite, + trash, + archive, + lockedFolder, + video, + place, + person, + map, + search, + deepLink, +} class TimelineFactory { final DriftTimelineRepository _timelineRepository; @@ -57,14 +74,17 @@ class TimelineFactory { TimelineService person(String userId, String personId) => TimelineService(_timelineRepository.person(userId, personId, groupBy)); - TimelineService fromAssets(List assets) => TimelineService(_timelineRepository.fromAssets(assets)); + TimelineService fromAssets(List assets, TimelineOrigin type) => + TimelineService(_timelineRepository.fromAssets(assets, type)); - TimelineService map(LatLngBounds bounds) => TimelineService(_timelineRepository.map(bounds, groupBy)); + TimelineService map(String userId, LatLngBounds bounds) => + TimelineService(_timelineRepository.map(userId, bounds, groupBy)); } class TimelineService { final TimelineAssetSource _assetSource; final TimelineBucketSource _bucketSource; + final TimelineOrigin origin; final AsyncMutex _mutex = AsyncMutex(); int _bufferOffset = 0; List _buffer = []; @@ -73,11 +93,15 @@ class TimelineService { int _totalAssets = 0; int get totalAssets => _totalAssets; - TimelineService(TimelineQuery query) : this._(assetSource: query.assetSource, bucketSource: query.bucketSource); + TimelineService(TimelineQuery query) + : this._(assetSource: query.assetSource, bucketSource: query.bucketSource, origin: query.origin); - TimelineService._({required TimelineAssetSource assetSource, required TimelineBucketSource bucketSource}) - : _assetSource = assetSource, - _bucketSource = bucketSource { + TimelineService._({ + required TimelineAssetSource assetSource, + required TimelineBucketSource bucketSource, + required this.origin, + }) : _assetSource = assetSource, + _bucketSource = bucketSource { _bucketSubscription = _bucketSource().listen((buckets) { _mutex.run(() async { final totalAssets = buckets.fold(0, (acc, bucket) => acc + bucket.assetCount); @@ -202,7 +226,7 @@ class TimelineService { Future dispose() async { await _bucketSubscription?.cancel(); _bucketSubscription = null; - _buffer.clear(); + _buffer = []; _bufferOffset = 0; } } diff --git a/mobile/lib/domain/utils/background_sync.dart b/mobile/lib/domain/utils/background_sync.dart index 4160a5f7bc..38e249b9f1 100644 --- a/mobile/lib/domain/utils/background_sync.dart +++ b/mobile/lib/domain/utils/background_sync.dart @@ -6,11 +6,12 @@ import 'package:immich_mobile/utils/isolate.dart'; import 'package:worker_manager/worker_manager.dart'; typedef SyncCallback = void Function(); +typedef SyncCallbackWithResult = void Function(T result); typedef SyncErrorCallback = void Function(String error); class BackgroundSyncManager { final SyncCallback? onRemoteSyncStart; - final SyncCallback? onRemoteSyncComplete; + final SyncCallbackWithResult? onRemoteSyncComplete; final SyncErrorCallback? onRemoteSyncError; final SyncCallback? onLocalSyncStart; @@ -21,7 +22,7 @@ class BackgroundSyncManager { final SyncCallback? onHashingComplete; final SyncErrorCallback? onHashingError; - Cancelable? _syncTask; + Cancelable? _syncTask; Cancelable? _syncWebsocketTask; Cancelable? _deviceAlbumSyncTask; Cancelable? _linkedAlbumSyncTask; @@ -100,8 +101,14 @@ class BackgroundSyncManager { // We use a ternary operator to avoid [_deviceAlbumSyncTask] from being // captured by the closure passed to [runInIsolateGentle]. _deviceAlbumSyncTask = full - ? runInIsolateGentle(computation: (ref) => ref.read(localSyncServiceProvider).sync(full: true)) - : runInIsolateGentle(computation: (ref) => ref.read(localSyncServiceProvider).sync(full: false)); + ? runInIsolateGentle( + computation: (ref) => ref.read(localSyncServiceProvider).sync(full: true), + debugLabel: 'local-sync-full-true', + ) + : runInIsolateGentle( + computation: (ref) => ref.read(localSyncServiceProvider).sync(full: false), + debugLabel: 'local-sync-full-false', + ); return _deviceAlbumSyncTask! .whenComplete(() { @@ -122,7 +129,10 @@ class BackgroundSyncManager { onHashingStart?.call(); - _hashTask = runInIsolateGentle(computation: (ref) => ref.read(hashServiceProvider).hashAssets()); + _hashTask = runInIsolateGentle( + computation: (ref) => ref.read(hashServiceProvider).hashAssets(), + debugLabel: 'hash-assets', + ); return _hashTask! .whenComplete(() { @@ -135,22 +145,30 @@ class BackgroundSyncManager { }); } - Future syncRemote() { + Future syncRemote() { if (_syncTask != null) { - return _syncTask!.future; + return _syncTask!.future.then((result) => result ?? false).catchError((_) => false); } onRemoteSyncStart?.call(); - _syncTask = runInIsolateGentle(computation: (ref) => ref.read(syncStreamServiceProvider).sync()); + _syncTask = runInIsolateGentle( + computation: (ref) => ref.read(syncStreamServiceProvider).sync(), + debugLabel: 'remote-sync', + ); return _syncTask! - .whenComplete(() { - onRemoteSyncComplete?.call(); - _syncTask = null; + .then((result) { + final success = result ?? false; + onRemoteSyncComplete?.call(success); + return success; }) .catchError((error) { onRemoteSyncError?.call(error.toString()); _syncTask = null; + return false; + }) + .whenComplete(() { + _syncTask = null; }); } @@ -169,7 +187,7 @@ class BackgroundSyncManager { return _linkedAlbumSyncTask!.future; } - _linkedAlbumSyncTask = runInIsolateGentle(computation: syncLinkedAlbumsIsolated); + _linkedAlbumSyncTask = runInIsolateGentle(computation: syncLinkedAlbumsIsolated, debugLabel: 'linked-album-sync'); return _linkedAlbumSyncTask!.whenComplete(() { _linkedAlbumSyncTask = null; }); @@ -178,4 +196,5 @@ class BackgroundSyncManager { Cancelable _handleWsAssetUploadReadyV1Batch(List batchData) => runInIsolateGentle( computation: (ref) => ref.read(syncStreamServiceProvider).handleWsAssetUploadReadyV1Batch(batchData), + debugLabel: 'websocket-batch', ); diff --git a/mobile/lib/domain/utils/isolate_lock_manager.dart b/mobile/lib/domain/utils/isolate_lock_manager.dart deleted file mode 100644 index 37de649204..0000000000 --- a/mobile/lib/domain/utils/isolate_lock_manager.dart +++ /dev/null @@ -1,235 +0,0 @@ -import 'dart:isolate'; -import 'dart:ui'; - -import 'package:flutter/foundation.dart'; -import 'package:logging/logging.dart'; - -const String kIsolateLockManagerPort = "immich://isolate_mutex"; - -enum _LockStatus { active, released } - -class _IsolateRequest { - const _IsolateRequest(); -} - -class _HeartbeatRequest extends _IsolateRequest { - // Port for the receiver to send replies back - final SendPort sendPort; - - const _HeartbeatRequest(this.sendPort); - - Map toJson() { - return {'type': 'heartbeat', 'sendPort': sendPort}; - } -} - -class _CloseRequest extends _IsolateRequest { - const _CloseRequest(); - - Map toJson() { - return {'type': 'close'}; - } -} - -class _IsolateResponse { - const _IsolateResponse(); -} - -class _HeartbeatResponse extends _IsolateResponse { - final _LockStatus status; - - const _HeartbeatResponse(this.status); - - Map toJson() { - return {'type': 'heartbeat', 'status': status.index}; - } -} - -typedef OnCloseLockHolderRequest = void Function(); - -class IsolateLockManager { - final String _portName; - bool _hasLock = false; - ReceivePort? _receivePort; - final OnCloseLockHolderRequest? _onCloseRequest; - final Set _waitingIsolates = {}; - // Token object - a new one is created for each acquisition attempt - Object? _currentAcquisitionToken; - - IsolateLockManager({String? portName, OnCloseLockHolderRequest? onCloseRequest}) - : _portName = portName ?? kIsolateLockManagerPort, - _onCloseRequest = onCloseRequest; - - Future acquireLock() async { - if (_hasLock) { - Logger('BackgroundWorkerLockManager').warning("WARNING: [acquireLock] called more than once"); - return true; - } - - // Create a new token - this invalidates any previous attempt - final token = _currentAcquisitionToken = Object(); - - final ReceivePort rp = _receivePort = ReceivePort(_portName); - final SendPort sp = rp.sendPort; - - while (!IsolateNameServer.registerPortWithName(sp, _portName)) { - // This attempt was superseded by a newer one in the same isolate - if (_currentAcquisitionToken != token) { - return false; - } - - await _lockReleasedByHolder(token); - } - - _hasLock = true; - rp.listen(_onRequest); - return true; - } - - Future _lockReleasedByHolder(Object token) async { - SendPort? holder = IsolateNameServer.lookupPortByName(_portName); - debugPrint("Found lock holder: $holder"); - if (holder == null) { - // No holder, try and acquire lock - return; - } - - final ReceivePort tempRp = ReceivePort(); - final SendPort tempSp = tempRp.sendPort; - final bs = tempRp.asBroadcastStream(); - - try { - while (true) { - // Send a heartbeat request with the send port to receive reply from the holder - - debugPrint("Sending heartbeat request to lock holder"); - holder.send(_HeartbeatRequest(tempSp).toJson()); - dynamic answer = await bs.first.timeout(const Duration(seconds: 3), onTimeout: () => null); - - debugPrint("Received heartbeat response from lock holder: $answer"); - // This attempt was superseded by a newer one in the same isolate - if (_currentAcquisitionToken != token) { - break; - } - - if (answer == null) { - // Holder failed, most likely killed without calling releaseLock - // Check if a different waiting isolate took the lock - if (holder == IsolateNameServer.lookupPortByName(_portName)) { - // No, remove the stale lock - IsolateNameServer.removePortNameMapping(_portName); - } - break; - } - - // Unknown message type received for heartbeat request. Try again - _IsolateResponse? response = _parseResponse(answer); - if (response == null || response is! _HeartbeatResponse) { - break; - } - - if (response.status == _LockStatus.released) { - // Holder has released the lock - break; - } - - // If the _LockStatus is active, we check again if the task completed - // by sending a released messaged again, if not, send a new heartbeat again - - // Check if the holder completed its task after the heartbeat - answer = await bs.first.timeout( - const Duration(seconds: 3), - onTimeout: () => const _HeartbeatResponse(_LockStatus.active).toJson(), - ); - - response = _parseResponse(answer); - if (response is _HeartbeatResponse && response.status == _LockStatus.released) { - break; - } - } - } catch (e) { - // Timeout or error - } finally { - tempRp.close(); - } - return; - } - - _IsolateRequest? _parseRequest(dynamic msg) { - if (msg is! Map) { - return null; - } - - return switch (msg['type']) { - 'heartbeat' => _HeartbeatRequest(msg['sendPort']), - 'close' => const _CloseRequest(), - _ => null, - }; - } - - _IsolateResponse? _parseResponse(dynamic msg) { - if (msg is! Map) { - return null; - } - - return switch (msg['type']) { - 'heartbeat' => _HeartbeatResponse(_LockStatus.values[msg['status']]), - _ => null, - }; - } - - // Executed in the isolate with the lock - void _onRequest(dynamic msg) { - final request = _parseRequest(msg); - if (request == null) { - return; - } - - if (request is _HeartbeatRequest) { - // Add the send port to the list of waiting isolates - _waitingIsolates.add(request.sendPort); - request.sendPort.send(const _HeartbeatResponse(_LockStatus.active).toJson()); - return; - } - - if (request is _CloseRequest) { - _onCloseRequest?.call(); - return; - } - } - - void releaseLock() { - if (_hasLock) { - IsolateNameServer.removePortNameMapping(_portName); - - // Notify waiting isolates - for (final port in _waitingIsolates) { - port.send(const _HeartbeatResponse(_LockStatus.released).toJson()); - } - _waitingIsolates.clear(); - - _hasLock = false; - } - - _receivePort?.close(); - _receivePort = null; - } - - void cancel() { - if (_hasLock) { - return; - } - - debugPrint("Cancelling ongoing acquire lock attempts"); - // Create a new token to invalidate ongoing acquire lock attempts - _currentAcquisitionToken = Object(); - } - - void requestHolderToClose() { - if (_hasLock) { - return; - } - - IsolateNameServer.lookupPortByName(_portName)?.send(const _CloseRequest().toJson()); - } -} diff --git a/mobile/lib/domain/utils/sync_linked_album.dart b/mobile/lib/domain/utils/sync_linked_album.dart index 9df69799ae..7bfadc96e7 100644 --- a/mobile/lib/domain/utils/sync_linked_album.dart +++ b/mobile/lib/domain/utils/sync_linked_album.dart @@ -1,10 +1,13 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/domain/models/store.model.dart'; import 'package:immich_mobile/domain/services/sync_linked_album.service.dart'; -import 'package:immich_mobile/providers/user.provider.dart'; +import 'package:immich_mobile/entities/store.entity.dart'; +import 'package:logging/logging.dart'; Future syncLinkedAlbumsIsolated(ProviderContainer ref) { - final user = ref.read(currentUserProvider); + final user = Store.tryGet(StoreKey.currentUser); if (user == null) { + Logger("SyncLinkedAlbum").warning("No user logged in, skipping linked album sync"); return Future.value(); } return ref.read(syncLinkedAlbumServiceProvider).syncLinkedAlbums(user.id); diff --git a/mobile/lib/entities/album.entity.g.dart b/mobile/lib/entities/album.entity.g.dart index e6ecde7f9a..ecbbab48c2 100644 --- a/mobile/lib/entities/album.entity.g.dart +++ b/mobile/lib/entities/album.entity.g.dart @@ -132,7 +132,7 @@ const AlbumSchema = CollectionSchema( getId: _albumGetId, getLinks: _albumGetLinks, attach: _albumAttach, - version: '3.1.8', + version: '3.3.0-dev.3', ); int _albumEstimateSize( diff --git a/mobile/lib/entities/android_device_asset.entity.g.dart b/mobile/lib/entities/android_device_asset.entity.g.dart index 9034709b8e..f8b1e32c72 100644 --- a/mobile/lib/entities/android_device_asset.entity.g.dart +++ b/mobile/lib/entities/android_device_asset.entity.g.dart @@ -47,7 +47,7 @@ const AndroidDeviceAssetSchema = CollectionSchema( getId: _androidDeviceAssetGetId, getLinks: _androidDeviceAssetGetLinks, attach: _androidDeviceAssetAttach, - version: '3.1.8', + version: '3.3.0-dev.3', ); int _androidDeviceAssetEstimateSize( diff --git a/mobile/lib/entities/asset.entity.g.dart b/mobile/lib/entities/asset.entity.g.dart index be5b427d01..db6bc72331 100644 --- a/mobile/lib/entities/asset.entity.g.dart +++ b/mobile/lib/entities/asset.entity.g.dart @@ -168,7 +168,7 @@ const AssetSchema = CollectionSchema( getId: _assetGetId, getLinks: _assetGetLinks, attach: _assetAttach, - version: '3.1.8', + version: '3.3.0-dev.3', ); int _assetEstimateSize( diff --git a/mobile/lib/entities/backup_album.entity.g.dart b/mobile/lib/entities/backup_album.entity.g.dart index ed98503119..583aa55c4d 100644 --- a/mobile/lib/entities/backup_album.entity.g.dart +++ b/mobile/lib/entities/backup_album.entity.g.dart @@ -43,7 +43,7 @@ const BackupAlbumSchema = CollectionSchema( getId: _backupAlbumGetId, getLinks: _backupAlbumGetLinks, attach: _backupAlbumAttach, - version: '3.1.8', + version: '3.3.0-dev.3', ); int _backupAlbumEstimateSize( diff --git a/mobile/lib/entities/duplicated_asset.entity.g.dart b/mobile/lib/entities/duplicated_asset.entity.g.dart index 6cf08ad9cc..80d2f344e6 100644 --- a/mobile/lib/entities/duplicated_asset.entity.g.dart +++ b/mobile/lib/entities/duplicated_asset.entity.g.dart @@ -32,7 +32,7 @@ const DuplicatedAssetSchema = CollectionSchema( getId: _duplicatedAssetGetId, getLinks: _duplicatedAssetGetLinks, attach: _duplicatedAssetAttach, - version: '3.1.8', + version: '3.3.0-dev.3', ); int _duplicatedAssetEstimateSize( diff --git a/mobile/lib/entities/etag.entity.g.dart b/mobile/lib/entities/etag.entity.g.dart index b1abba6bb7..03b4ea9918 100644 --- a/mobile/lib/entities/etag.entity.g.dart +++ b/mobile/lib/entities/etag.entity.g.dart @@ -52,7 +52,7 @@ const ETagSchema = CollectionSchema( getId: _eTagGetId, getLinks: _eTagGetLinks, attach: _eTagAttach, - version: '3.1.8', + version: '3.3.0-dev.3', ); int _eTagEstimateSize( diff --git a/mobile/lib/entities/ios_device_asset.entity.g.dart b/mobile/lib/entities/ios_device_asset.entity.g.dart index 8d8fec945b..252fe127bb 100644 --- a/mobile/lib/entities/ios_device_asset.entity.g.dart +++ b/mobile/lib/entities/ios_device_asset.entity.g.dart @@ -60,7 +60,7 @@ const IOSDeviceAssetSchema = CollectionSchema( getId: _iOSDeviceAssetGetId, getLinks: _iOSDeviceAssetGetLinks, attach: _iOSDeviceAssetAttach, - version: '3.1.8', + version: '3.3.0-dev.3', ); int _iOSDeviceAssetEstimateSize( diff --git a/mobile/lib/extensions/network_capability_extensions.dart b/mobile/lib/extensions/network_capability_extensions.dart new file mode 100644 index 0000000000..aeefc11e39 --- /dev/null +++ b/mobile/lib/extensions/network_capability_extensions.dart @@ -0,0 +1,8 @@ +import 'package:immich_mobile/platform/connectivity_api.g.dart'; + +extension NetworkCapabilitiesGetters on List { + bool get hasCellular => contains(NetworkCapability.cellular); + bool get hasWifi => contains(NetworkCapability.wifi); + bool get hasVpn => contains(NetworkCapability.vpn); + bool get isUnmetered => contains(NetworkCapability.unmetered); +} diff --git a/mobile/lib/extensions/platform_extensions.dart b/mobile/lib/extensions/platform_extensions.dart new file mode 100644 index 0000000000..7353fbc6f6 --- /dev/null +++ b/mobile/lib/extensions/platform_extensions.dart @@ -0,0 +1,9 @@ +import 'package:flutter/foundation.dart'; + +extension CurrentPlatform on TargetPlatform { + @pragma('vm:prefer-inline') + static bool get isIOS => defaultTargetPlatform == TargetPlatform.iOS; + + @pragma('vm:prefer-inline') + static bool get isAndroid => defaultTargetPlatform == TargetPlatform.android; +} diff --git a/mobile/lib/extensions/string_extensions.dart b/mobile/lib/extensions/string_extensions.dart index 6cd6e1e4b4..ae31565044 100644 --- a/mobile/lib/extensions/string_extensions.dart +++ b/mobile/lib/extensions/string_extensions.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + extension StringExtension on String { String capitalize() { return split(" ").map((str) => str.isEmpty ? str : str[0].toUpperCase() + str.substring(1)).join(" "); @@ -23,3 +25,11 @@ extension DurationExtension on String { return int.parse(this); } } + +Map? tryJsonDecode(dynamic json) { + try { + return jsonDecode(json) as Map; + } catch (e) { + return null; + } +} diff --git a/mobile/lib/extensions/translate_extensions.dart b/mobile/lib/extensions/translate_extensions.dart index cfd8c8cd1f..7677f3cbd8 100644 --- a/mobile/lib/extensions/translate_extensions.dart +++ b/mobile/lib/extensions/translate_extensions.dart @@ -1,6 +1,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:intl/message_format.dart'; import 'package:flutter/material.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; extension StringTranslateExtension on String { String t({BuildContext? context, Map? args}) { @@ -39,7 +40,7 @@ String _translateHelper(BuildContext? context, String key, [Map? ? MessageFormat(translatedMessage, locale: Intl.defaultLocale ?? 'en').format(args) : translatedMessage; } catch (e) { - debugPrint('Translation failed for key "$key". Error: $e'); + dPrint(() => 'Translation failed for key "$key". Error: $e'); return key; } } diff --git a/mobile/lib/infrastructure/entities/auth_user.entity.dart b/mobile/lib/infrastructure/entities/auth_user.entity.dart new file mode 100644 index 0000000000..cbbeaf536f --- /dev/null +++ b/mobile/lib/infrastructure/entities/auth_user.entity.dart @@ -0,0 +1,27 @@ +import 'package:drift/drift.dart'; +import 'package:immich_mobile/domain/models/user.model.dart'; +import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart'; + +class AuthUserEntity extends Table with DriftDefaultsMixin { + const AuthUserEntity(); + + TextColumn get id => text()(); + TextColumn get name => text()(); + TextColumn get email => text()(); + BoolColumn get isAdmin => boolean().withDefault(const Constant(false))(); + + // Profile image + BoolColumn get hasProfileImage => boolean().withDefault(const Constant(false))(); + DateTimeColumn get profileChangedAt => dateTime().withDefault(currentDateAndTime)(); + IntColumn get avatarColor => intEnum()(); + + // Quota + IntColumn get quotaSizeInBytes => integer().withDefault(const Constant(0))(); + IntColumn get quotaUsageInBytes => integer().withDefault(const Constant(0))(); + + // Locked Folder + TextColumn get pinCode => text().nullable()(); + + @override + Set get primaryKey => {id}; +} diff --git a/mobile/lib/infrastructure/entities/auth_user.entity.drift.dart b/mobile/lib/infrastructure/entities/auth_user.entity.drift.dart new file mode 100644 index 0000000000..4dba1c42fb --- /dev/null +++ b/mobile/lib/infrastructure/entities/auth_user.entity.drift.dart @@ -0,0 +1,933 @@ +// dart format width=80 +// ignore_for_file: type=lint +import 'package:drift/drift.dart' as i0; +import 'package:immich_mobile/infrastructure/entities/auth_user.entity.drift.dart' + as i1; +import 'package:immich_mobile/domain/models/user.model.dart' as i2; +import 'package:immich_mobile/infrastructure/entities/auth_user.entity.dart' + as i3; +import 'package:drift/src/runtime/query_builder/query_builder.dart' as i4; + +typedef $$AuthUserEntityTableCreateCompanionBuilder = + i1.AuthUserEntityCompanion Function({ + required String id, + required String name, + required String email, + i0.Value isAdmin, + i0.Value hasProfileImage, + i0.Value profileChangedAt, + required i2.AvatarColor avatarColor, + i0.Value quotaSizeInBytes, + i0.Value quotaUsageInBytes, + i0.Value pinCode, + }); +typedef $$AuthUserEntityTableUpdateCompanionBuilder = + i1.AuthUserEntityCompanion Function({ + i0.Value id, + i0.Value name, + i0.Value email, + i0.Value isAdmin, + i0.Value hasProfileImage, + i0.Value profileChangedAt, + i0.Value avatarColor, + i0.Value quotaSizeInBytes, + i0.Value quotaUsageInBytes, + i0.Value pinCode, + }); + +class $$AuthUserEntityTableFilterComposer + extends i0.Composer { + $$AuthUserEntityTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + i0.ColumnFilters get id => $composableBuilder( + column: $table.id, + builder: (column) => i0.ColumnFilters(column), + ); + + i0.ColumnFilters get name => $composableBuilder( + column: $table.name, + builder: (column) => i0.ColumnFilters(column), + ); + + i0.ColumnFilters get email => $composableBuilder( + column: $table.email, + builder: (column) => i0.ColumnFilters(column), + ); + + i0.ColumnFilters get isAdmin => $composableBuilder( + column: $table.isAdmin, + builder: (column) => i0.ColumnFilters(column), + ); + + i0.ColumnFilters get hasProfileImage => $composableBuilder( + column: $table.hasProfileImage, + builder: (column) => i0.ColumnFilters(column), + ); + + i0.ColumnFilters get profileChangedAt => $composableBuilder( + column: $table.profileChangedAt, + builder: (column) => i0.ColumnFilters(column), + ); + + i0.ColumnWithTypeConverterFilters + get avatarColor => $composableBuilder( + column: $table.avatarColor, + builder: (column) => i0.ColumnWithTypeConverterFilters(column), + ); + + i0.ColumnFilters get quotaSizeInBytes => $composableBuilder( + column: $table.quotaSizeInBytes, + builder: (column) => i0.ColumnFilters(column), + ); + + i0.ColumnFilters get quotaUsageInBytes => $composableBuilder( + column: $table.quotaUsageInBytes, + builder: (column) => i0.ColumnFilters(column), + ); + + i0.ColumnFilters get pinCode => $composableBuilder( + column: $table.pinCode, + builder: (column) => i0.ColumnFilters(column), + ); +} + +class $$AuthUserEntityTableOrderingComposer + extends i0.Composer { + $$AuthUserEntityTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + i0.ColumnOrderings get id => $composableBuilder( + column: $table.id, + builder: (column) => i0.ColumnOrderings(column), + ); + + i0.ColumnOrderings get name => $composableBuilder( + column: $table.name, + builder: (column) => i0.ColumnOrderings(column), + ); + + i0.ColumnOrderings get email => $composableBuilder( + column: $table.email, + builder: (column) => i0.ColumnOrderings(column), + ); + + i0.ColumnOrderings get isAdmin => $composableBuilder( + column: $table.isAdmin, + builder: (column) => i0.ColumnOrderings(column), + ); + + i0.ColumnOrderings get hasProfileImage => $composableBuilder( + column: $table.hasProfileImage, + builder: (column) => i0.ColumnOrderings(column), + ); + + i0.ColumnOrderings get profileChangedAt => $composableBuilder( + column: $table.profileChangedAt, + builder: (column) => i0.ColumnOrderings(column), + ); + + i0.ColumnOrderings get avatarColor => $composableBuilder( + column: $table.avatarColor, + builder: (column) => i0.ColumnOrderings(column), + ); + + i0.ColumnOrderings get quotaSizeInBytes => $composableBuilder( + column: $table.quotaSizeInBytes, + builder: (column) => i0.ColumnOrderings(column), + ); + + i0.ColumnOrderings get quotaUsageInBytes => $composableBuilder( + column: $table.quotaUsageInBytes, + builder: (column) => i0.ColumnOrderings(column), + ); + + i0.ColumnOrderings get pinCode => $composableBuilder( + column: $table.pinCode, + builder: (column) => i0.ColumnOrderings(column), + ); +} + +class $$AuthUserEntityTableAnnotationComposer + extends i0.Composer { + $$AuthUserEntityTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + i0.GeneratedColumn get id => + $composableBuilder(column: $table.id, builder: (column) => column); + + i0.GeneratedColumn get name => + $composableBuilder(column: $table.name, builder: (column) => column); + + i0.GeneratedColumn get email => + $composableBuilder(column: $table.email, builder: (column) => column); + + i0.GeneratedColumn get isAdmin => + $composableBuilder(column: $table.isAdmin, builder: (column) => column); + + i0.GeneratedColumn get hasProfileImage => $composableBuilder( + column: $table.hasProfileImage, + builder: (column) => column, + ); + + i0.GeneratedColumn get profileChangedAt => $composableBuilder( + column: $table.profileChangedAt, + builder: (column) => column, + ); + + i0.GeneratedColumnWithTypeConverter get avatarColor => + $composableBuilder( + column: $table.avatarColor, + builder: (column) => column, + ); + + i0.GeneratedColumn get quotaSizeInBytes => $composableBuilder( + column: $table.quotaSizeInBytes, + builder: (column) => column, + ); + + i0.GeneratedColumn get quotaUsageInBytes => $composableBuilder( + column: $table.quotaUsageInBytes, + builder: (column) => column, + ); + + i0.GeneratedColumn get pinCode => + $composableBuilder(column: $table.pinCode, builder: (column) => column); +} + +class $$AuthUserEntityTableTableManager + extends + i0.RootTableManager< + i0.GeneratedDatabase, + i1.$AuthUserEntityTable, + i1.AuthUserEntityData, + i1.$$AuthUserEntityTableFilterComposer, + i1.$$AuthUserEntityTableOrderingComposer, + i1.$$AuthUserEntityTableAnnotationComposer, + $$AuthUserEntityTableCreateCompanionBuilder, + $$AuthUserEntityTableUpdateCompanionBuilder, + ( + i1.AuthUserEntityData, + i0.BaseReferences< + i0.GeneratedDatabase, + i1.$AuthUserEntityTable, + i1.AuthUserEntityData + >, + ), + i1.AuthUserEntityData, + i0.PrefetchHooks Function() + > { + $$AuthUserEntityTableTableManager( + i0.GeneratedDatabase db, + i1.$AuthUserEntityTable table, + ) : super( + i0.TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + i1.$$AuthUserEntityTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + i1.$$AuthUserEntityTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => i1 + .$$AuthUserEntityTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: + ({ + i0.Value id = const i0.Value.absent(), + i0.Value name = const i0.Value.absent(), + i0.Value email = const i0.Value.absent(), + i0.Value isAdmin = const i0.Value.absent(), + i0.Value hasProfileImage = const i0.Value.absent(), + i0.Value profileChangedAt = const i0.Value.absent(), + i0.Value avatarColor = const i0.Value.absent(), + i0.Value quotaSizeInBytes = const i0.Value.absent(), + i0.Value quotaUsageInBytes = const i0.Value.absent(), + i0.Value pinCode = const i0.Value.absent(), + }) => i1.AuthUserEntityCompanion( + id: id, + name: name, + email: email, + isAdmin: isAdmin, + hasProfileImage: hasProfileImage, + profileChangedAt: profileChangedAt, + avatarColor: avatarColor, + quotaSizeInBytes: quotaSizeInBytes, + quotaUsageInBytes: quotaUsageInBytes, + pinCode: pinCode, + ), + createCompanionCallback: + ({ + required String id, + required String name, + required String email, + i0.Value isAdmin = const i0.Value.absent(), + i0.Value hasProfileImage = const i0.Value.absent(), + i0.Value profileChangedAt = const i0.Value.absent(), + required i2.AvatarColor avatarColor, + i0.Value quotaSizeInBytes = const i0.Value.absent(), + i0.Value quotaUsageInBytes = const i0.Value.absent(), + i0.Value pinCode = const i0.Value.absent(), + }) => i1.AuthUserEntityCompanion.insert( + id: id, + name: name, + email: email, + isAdmin: isAdmin, + hasProfileImage: hasProfileImage, + profileChangedAt: profileChangedAt, + avatarColor: avatarColor, + quotaSizeInBytes: quotaSizeInBytes, + quotaUsageInBytes: quotaUsageInBytes, + pinCode: pinCode, + ), + withReferenceMapper: (p0) => p0 + .map((e) => (e.readTable(table), i0.BaseReferences(db, table, e))) + .toList(), + prefetchHooksCallback: null, + ), + ); +} + +typedef $$AuthUserEntityTableProcessedTableManager = + i0.ProcessedTableManager< + i0.GeneratedDatabase, + i1.$AuthUserEntityTable, + i1.AuthUserEntityData, + i1.$$AuthUserEntityTableFilterComposer, + i1.$$AuthUserEntityTableOrderingComposer, + i1.$$AuthUserEntityTableAnnotationComposer, + $$AuthUserEntityTableCreateCompanionBuilder, + $$AuthUserEntityTableUpdateCompanionBuilder, + ( + i1.AuthUserEntityData, + i0.BaseReferences< + i0.GeneratedDatabase, + i1.$AuthUserEntityTable, + i1.AuthUserEntityData + >, + ), + i1.AuthUserEntityData, + i0.PrefetchHooks Function() + >; + +class $AuthUserEntityTable extends i3.AuthUserEntity + with i0.TableInfo<$AuthUserEntityTable, i1.AuthUserEntityData> { + @override + final i0.GeneratedDatabase attachedDatabase; + final String? _alias; + $AuthUserEntityTable(this.attachedDatabase, [this._alias]); + static const i0.VerificationMeta _idMeta = const i0.VerificationMeta('id'); + @override + late final i0.GeneratedColumn id = i0.GeneratedColumn( + 'id', + aliasedName, + false, + type: i0.DriftSqlType.string, + requiredDuringInsert: true, + ); + static const i0.VerificationMeta _nameMeta = const i0.VerificationMeta( + 'name', + ); + @override + late final i0.GeneratedColumn name = i0.GeneratedColumn( + 'name', + aliasedName, + false, + type: i0.DriftSqlType.string, + requiredDuringInsert: true, + ); + static const i0.VerificationMeta _emailMeta = const i0.VerificationMeta( + 'email', + ); + @override + late final i0.GeneratedColumn email = i0.GeneratedColumn( + 'email', + aliasedName, + false, + type: i0.DriftSqlType.string, + requiredDuringInsert: true, + ); + static const i0.VerificationMeta _isAdminMeta = const i0.VerificationMeta( + 'isAdmin', + ); + @override + late final i0.GeneratedColumn isAdmin = i0.GeneratedColumn( + 'is_admin', + aliasedName, + false, + type: i0.DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: i0.GeneratedColumn.constraintIsAlways( + 'CHECK ("is_admin" IN (0, 1))', + ), + defaultValue: const i4.Constant(false), + ); + static const i0.VerificationMeta _hasProfileImageMeta = + const i0.VerificationMeta('hasProfileImage'); + @override + late final i0.GeneratedColumn hasProfileImage = + i0.GeneratedColumn( + 'has_profile_image', + aliasedName, + false, + type: i0.DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: i0.GeneratedColumn.constraintIsAlways( + 'CHECK ("has_profile_image" IN (0, 1))', + ), + defaultValue: const i4.Constant(false), + ); + static const i0.VerificationMeta _profileChangedAtMeta = + const i0.VerificationMeta('profileChangedAt'); + @override + late final i0.GeneratedColumn profileChangedAt = + i0.GeneratedColumn( + 'profile_changed_at', + aliasedName, + false, + type: i0.DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: i4.currentDateAndTime, + ); + @override + late final i0.GeneratedColumnWithTypeConverter + avatarColor = + i0.GeneratedColumn( + 'avatar_color', + aliasedName, + false, + type: i0.DriftSqlType.int, + requiredDuringInsert: true, + ).withConverter( + i1.$AuthUserEntityTable.$converteravatarColor, + ); + static const i0.VerificationMeta _quotaSizeInBytesMeta = + const i0.VerificationMeta('quotaSizeInBytes'); + @override + late final i0.GeneratedColumn quotaSizeInBytes = i0.GeneratedColumn( + 'quota_size_in_bytes', + aliasedName, + false, + type: i0.DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const i4.Constant(0), + ); + static const i0.VerificationMeta _quotaUsageInBytesMeta = + const i0.VerificationMeta('quotaUsageInBytes'); + @override + late final i0.GeneratedColumn quotaUsageInBytes = + i0.GeneratedColumn( + 'quota_usage_in_bytes', + aliasedName, + false, + type: i0.DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const i4.Constant(0), + ); + static const i0.VerificationMeta _pinCodeMeta = const i0.VerificationMeta( + 'pinCode', + ); + @override + late final i0.GeneratedColumn pinCode = i0.GeneratedColumn( + 'pin_code', + aliasedName, + true, + type: i0.DriftSqlType.string, + requiredDuringInsert: false, + ); + @override + List get $columns => [ + id, + name, + email, + isAdmin, + hasProfileImage, + profileChangedAt, + avatarColor, + quotaSizeInBytes, + quotaUsageInBytes, + pinCode, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'auth_user_entity'; + @override + i0.VerificationContext validateIntegrity( + i0.Insertable instance, { + bool isInserting = false, + }) { + final context = i0.VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta)); + } else if (isInserting) { + context.missing(_idMeta); + } + if (data.containsKey('name')) { + context.handle( + _nameMeta, + name.isAcceptableOrUnknown(data['name']!, _nameMeta), + ); + } else if (isInserting) { + context.missing(_nameMeta); + } + if (data.containsKey('email')) { + context.handle( + _emailMeta, + email.isAcceptableOrUnknown(data['email']!, _emailMeta), + ); + } else if (isInserting) { + context.missing(_emailMeta); + } + if (data.containsKey('is_admin')) { + context.handle( + _isAdminMeta, + isAdmin.isAcceptableOrUnknown(data['is_admin']!, _isAdminMeta), + ); + } + if (data.containsKey('has_profile_image')) { + context.handle( + _hasProfileImageMeta, + hasProfileImage.isAcceptableOrUnknown( + data['has_profile_image']!, + _hasProfileImageMeta, + ), + ); + } + if (data.containsKey('profile_changed_at')) { + context.handle( + _profileChangedAtMeta, + profileChangedAt.isAcceptableOrUnknown( + data['profile_changed_at']!, + _profileChangedAtMeta, + ), + ); + } + if (data.containsKey('quota_size_in_bytes')) { + context.handle( + _quotaSizeInBytesMeta, + quotaSizeInBytes.isAcceptableOrUnknown( + data['quota_size_in_bytes']!, + _quotaSizeInBytesMeta, + ), + ); + } + if (data.containsKey('quota_usage_in_bytes')) { + context.handle( + _quotaUsageInBytesMeta, + quotaUsageInBytes.isAcceptableOrUnknown( + data['quota_usage_in_bytes']!, + _quotaUsageInBytesMeta, + ), + ); + } + if (data.containsKey('pin_code')) { + context.handle( + _pinCodeMeta, + pinCode.isAcceptableOrUnknown(data['pin_code']!, _pinCodeMeta), + ); + } + return context; + } + + @override + Set get $primaryKey => {id}; + @override + i1.AuthUserEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return i1.AuthUserEntityData( + id: attachedDatabase.typeMapping.read( + i0.DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + name: attachedDatabase.typeMapping.read( + i0.DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + email: attachedDatabase.typeMapping.read( + i0.DriftSqlType.string, + data['${effectivePrefix}email'], + )!, + isAdmin: attachedDatabase.typeMapping.read( + i0.DriftSqlType.bool, + data['${effectivePrefix}is_admin'], + )!, + hasProfileImage: attachedDatabase.typeMapping.read( + i0.DriftSqlType.bool, + data['${effectivePrefix}has_profile_image'], + )!, + profileChangedAt: attachedDatabase.typeMapping.read( + i0.DriftSqlType.dateTime, + data['${effectivePrefix}profile_changed_at'], + )!, + avatarColor: i1.$AuthUserEntityTable.$converteravatarColor.fromSql( + attachedDatabase.typeMapping.read( + i0.DriftSqlType.int, + data['${effectivePrefix}avatar_color'], + )!, + ), + quotaSizeInBytes: attachedDatabase.typeMapping.read( + i0.DriftSqlType.int, + data['${effectivePrefix}quota_size_in_bytes'], + )!, + quotaUsageInBytes: attachedDatabase.typeMapping.read( + i0.DriftSqlType.int, + data['${effectivePrefix}quota_usage_in_bytes'], + )!, + pinCode: attachedDatabase.typeMapping.read( + i0.DriftSqlType.string, + data['${effectivePrefix}pin_code'], + ), + ); + } + + @override + $AuthUserEntityTable createAlias(String alias) { + return $AuthUserEntityTable(attachedDatabase, alias); + } + + static i0.JsonTypeConverter2 $converteravatarColor = + const i0.EnumIndexConverter(i2.AvatarColor.values); + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class AuthUserEntityData extends i0.DataClass + implements i0.Insertable { + final String id; + final String name; + final String email; + final bool isAdmin; + final bool hasProfileImage; + final DateTime profileChangedAt; + final i2.AvatarColor avatarColor; + final int quotaSizeInBytes; + final int quotaUsageInBytes; + final String? pinCode; + const AuthUserEntityData({ + required this.id, + required this.name, + required this.email, + required this.isAdmin, + required this.hasProfileImage, + required this.profileChangedAt, + required this.avatarColor, + required this.quotaSizeInBytes, + required this.quotaUsageInBytes, + this.pinCode, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = i0.Variable(id); + map['name'] = i0.Variable(name); + map['email'] = i0.Variable(email); + map['is_admin'] = i0.Variable(isAdmin); + map['has_profile_image'] = i0.Variable(hasProfileImage); + map['profile_changed_at'] = i0.Variable(profileChangedAt); + { + map['avatar_color'] = i0.Variable( + i1.$AuthUserEntityTable.$converteravatarColor.toSql(avatarColor), + ); + } + map['quota_size_in_bytes'] = i0.Variable(quotaSizeInBytes); + map['quota_usage_in_bytes'] = i0.Variable(quotaUsageInBytes); + if (!nullToAbsent || pinCode != null) { + map['pin_code'] = i0.Variable(pinCode); + } + return map; + } + + factory AuthUserEntityData.fromJson( + Map json, { + i0.ValueSerializer? serializer, + }) { + serializer ??= i0.driftRuntimeOptions.defaultSerializer; + return AuthUserEntityData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + email: serializer.fromJson(json['email']), + isAdmin: serializer.fromJson(json['isAdmin']), + hasProfileImage: serializer.fromJson(json['hasProfileImage']), + profileChangedAt: serializer.fromJson(json['profileChangedAt']), + avatarColor: i1.$AuthUserEntityTable.$converteravatarColor.fromJson( + serializer.fromJson(json['avatarColor']), + ), + quotaSizeInBytes: serializer.fromJson(json['quotaSizeInBytes']), + quotaUsageInBytes: serializer.fromJson(json['quotaUsageInBytes']), + pinCode: serializer.fromJson(json['pinCode']), + ); + } + @override + Map toJson({i0.ValueSerializer? serializer}) { + serializer ??= i0.driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'email': serializer.toJson(email), + 'isAdmin': serializer.toJson(isAdmin), + 'hasProfileImage': serializer.toJson(hasProfileImage), + 'profileChangedAt': serializer.toJson(profileChangedAt), + 'avatarColor': serializer.toJson( + i1.$AuthUserEntityTable.$converteravatarColor.toJson(avatarColor), + ), + 'quotaSizeInBytes': serializer.toJson(quotaSizeInBytes), + 'quotaUsageInBytes': serializer.toJson(quotaUsageInBytes), + 'pinCode': serializer.toJson(pinCode), + }; + } + + i1.AuthUserEntityData copyWith({ + String? id, + String? name, + String? email, + bool? isAdmin, + bool? hasProfileImage, + DateTime? profileChangedAt, + i2.AvatarColor? avatarColor, + int? quotaSizeInBytes, + int? quotaUsageInBytes, + i0.Value pinCode = const i0.Value.absent(), + }) => i1.AuthUserEntityData( + id: id ?? this.id, + name: name ?? this.name, + email: email ?? this.email, + isAdmin: isAdmin ?? this.isAdmin, + hasProfileImage: hasProfileImage ?? this.hasProfileImage, + profileChangedAt: profileChangedAt ?? this.profileChangedAt, + avatarColor: avatarColor ?? this.avatarColor, + quotaSizeInBytes: quotaSizeInBytes ?? this.quotaSizeInBytes, + quotaUsageInBytes: quotaUsageInBytes ?? this.quotaUsageInBytes, + pinCode: pinCode.present ? pinCode.value : this.pinCode, + ); + AuthUserEntityData copyWithCompanion(i1.AuthUserEntityCompanion data) { + return AuthUserEntityData( + id: data.id.present ? data.id.value : this.id, + name: data.name.present ? data.name.value : this.name, + email: data.email.present ? data.email.value : this.email, + isAdmin: data.isAdmin.present ? data.isAdmin.value : this.isAdmin, + hasProfileImage: data.hasProfileImage.present + ? data.hasProfileImage.value + : this.hasProfileImage, + profileChangedAt: data.profileChangedAt.present + ? data.profileChangedAt.value + : this.profileChangedAt, + avatarColor: data.avatarColor.present + ? data.avatarColor.value + : this.avatarColor, + quotaSizeInBytes: data.quotaSizeInBytes.present + ? data.quotaSizeInBytes.value + : this.quotaSizeInBytes, + quotaUsageInBytes: data.quotaUsageInBytes.present + ? data.quotaUsageInBytes.value + : this.quotaUsageInBytes, + pinCode: data.pinCode.present ? data.pinCode.value : this.pinCode, + ); + } + + @override + String toString() { + return (StringBuffer('AuthUserEntityData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('email: $email, ') + ..write('isAdmin: $isAdmin, ') + ..write('hasProfileImage: $hasProfileImage, ') + ..write('profileChangedAt: $profileChangedAt, ') + ..write('avatarColor: $avatarColor, ') + ..write('quotaSizeInBytes: $quotaSizeInBytes, ') + ..write('quotaUsageInBytes: $quotaUsageInBytes, ') + ..write('pinCode: $pinCode') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + name, + email, + isAdmin, + hasProfileImage, + profileChangedAt, + avatarColor, + quotaSizeInBytes, + quotaUsageInBytes, + pinCode, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is i1.AuthUserEntityData && + other.id == this.id && + other.name == this.name && + other.email == this.email && + other.isAdmin == this.isAdmin && + other.hasProfileImage == this.hasProfileImage && + other.profileChangedAt == this.profileChangedAt && + other.avatarColor == this.avatarColor && + other.quotaSizeInBytes == this.quotaSizeInBytes && + other.quotaUsageInBytes == this.quotaUsageInBytes && + other.pinCode == this.pinCode); +} + +class AuthUserEntityCompanion + extends i0.UpdateCompanion { + final i0.Value id; + final i0.Value name; + final i0.Value email; + final i0.Value isAdmin; + final i0.Value hasProfileImage; + final i0.Value profileChangedAt; + final i0.Value avatarColor; + final i0.Value quotaSizeInBytes; + final i0.Value quotaUsageInBytes; + final i0.Value pinCode; + const AuthUserEntityCompanion({ + this.id = const i0.Value.absent(), + this.name = const i0.Value.absent(), + this.email = const i0.Value.absent(), + this.isAdmin = const i0.Value.absent(), + this.hasProfileImage = const i0.Value.absent(), + this.profileChangedAt = const i0.Value.absent(), + this.avatarColor = const i0.Value.absent(), + this.quotaSizeInBytes = const i0.Value.absent(), + this.quotaUsageInBytes = const i0.Value.absent(), + this.pinCode = const i0.Value.absent(), + }); + AuthUserEntityCompanion.insert({ + required String id, + required String name, + required String email, + this.isAdmin = const i0.Value.absent(), + this.hasProfileImage = const i0.Value.absent(), + this.profileChangedAt = const i0.Value.absent(), + required i2.AvatarColor avatarColor, + this.quotaSizeInBytes = const i0.Value.absent(), + this.quotaUsageInBytes = const i0.Value.absent(), + this.pinCode = const i0.Value.absent(), + }) : id = i0.Value(id), + name = i0.Value(name), + email = i0.Value(email), + avatarColor = i0.Value(avatarColor); + static i0.Insertable custom({ + i0.Expression? id, + i0.Expression? name, + i0.Expression? email, + i0.Expression? isAdmin, + i0.Expression? hasProfileImage, + i0.Expression? profileChangedAt, + i0.Expression? avatarColor, + i0.Expression? quotaSizeInBytes, + i0.Expression? quotaUsageInBytes, + i0.Expression? pinCode, + }) { + return i0.RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (email != null) 'email': email, + if (isAdmin != null) 'is_admin': isAdmin, + if (hasProfileImage != null) 'has_profile_image': hasProfileImage, + if (profileChangedAt != null) 'profile_changed_at': profileChangedAt, + if (avatarColor != null) 'avatar_color': avatarColor, + if (quotaSizeInBytes != null) 'quota_size_in_bytes': quotaSizeInBytes, + if (quotaUsageInBytes != null) 'quota_usage_in_bytes': quotaUsageInBytes, + if (pinCode != null) 'pin_code': pinCode, + }); + } + + i1.AuthUserEntityCompanion copyWith({ + i0.Value? id, + i0.Value? name, + i0.Value? email, + i0.Value? isAdmin, + i0.Value? hasProfileImage, + i0.Value? profileChangedAt, + i0.Value? avatarColor, + i0.Value? quotaSizeInBytes, + i0.Value? quotaUsageInBytes, + i0.Value? pinCode, + }) { + return i1.AuthUserEntityCompanion( + id: id ?? this.id, + name: name ?? this.name, + email: email ?? this.email, + isAdmin: isAdmin ?? this.isAdmin, + hasProfileImage: hasProfileImage ?? this.hasProfileImage, + profileChangedAt: profileChangedAt ?? this.profileChangedAt, + avatarColor: avatarColor ?? this.avatarColor, + quotaSizeInBytes: quotaSizeInBytes ?? this.quotaSizeInBytes, + quotaUsageInBytes: quotaUsageInBytes ?? this.quotaUsageInBytes, + pinCode: pinCode ?? this.pinCode, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = i0.Variable(id.value); + } + if (name.present) { + map['name'] = i0.Variable(name.value); + } + if (email.present) { + map['email'] = i0.Variable(email.value); + } + if (isAdmin.present) { + map['is_admin'] = i0.Variable(isAdmin.value); + } + if (hasProfileImage.present) { + map['has_profile_image'] = i0.Variable(hasProfileImage.value); + } + if (profileChangedAt.present) { + map['profile_changed_at'] = i0.Variable(profileChangedAt.value); + } + if (avatarColor.present) { + map['avatar_color'] = i0.Variable( + i1.$AuthUserEntityTable.$converteravatarColor.toSql(avatarColor.value), + ); + } + if (quotaSizeInBytes.present) { + map['quota_size_in_bytes'] = i0.Variable(quotaSizeInBytes.value); + } + if (quotaUsageInBytes.present) { + map['quota_usage_in_bytes'] = i0.Variable(quotaUsageInBytes.value); + } + if (pinCode.present) { + map['pin_code'] = i0.Variable(pinCode.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('AuthUserEntityCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('email: $email, ') + ..write('isAdmin: $isAdmin, ') + ..write('hasProfileImage: $hasProfileImage, ') + ..write('profileChangedAt: $profileChangedAt, ') + ..write('avatarColor: $avatarColor, ') + ..write('quotaSizeInBytes: $quotaSizeInBytes, ') + ..write('quotaUsageInBytes: $quotaUsageInBytes, ') + ..write('pinCode: $pinCode') + ..write(')')) + .toString(); + } +} diff --git a/mobile/lib/infrastructure/entities/device_asset.entity.g.dart b/mobile/lib/infrastructure/entities/device_asset.entity.g.dart index 87ae54ad40..b6c30aca6f 100644 --- a/mobile/lib/infrastructure/entities/device_asset.entity.g.dart +++ b/mobile/lib/infrastructure/entities/device_asset.entity.g.dart @@ -65,7 +65,7 @@ const DeviceAssetEntitySchema = CollectionSchema( getId: _deviceAssetEntityGetId, getLinks: _deviceAssetEntityGetLinks, attach: _deviceAssetEntityAttach, - version: '3.1.8', + version: '3.3.0-dev.3', ); int _deviceAssetEntityEstimateSize( diff --git a/mobile/lib/infrastructure/entities/exif.entity.g.dart b/mobile/lib/infrastructure/entities/exif.entity.g.dart index d2f9ebda27..ffbfd0d8f0 100644 --- a/mobile/lib/infrastructure/entities/exif.entity.g.dart +++ b/mobile/lib/infrastructure/entities/exif.entity.g.dart @@ -68,7 +68,7 @@ const ExifInfoSchema = CollectionSchema( getId: _exifInfoGetId, getLinks: _exifInfoGetLinks, attach: _exifInfoAttach, - version: '3.1.8', + version: '3.3.0-dev.3', ); int _exifInfoEstimateSize( diff --git a/mobile/lib/infrastructure/entities/local_album_asset.entity.dart b/mobile/lib/infrastructure/entities/local_album_asset.entity.dart index 8de879a09d..53f1a10662 100644 --- a/mobile/lib/infrastructure/entities/local_album_asset.entity.dart +++ b/mobile/lib/infrastructure/entities/local_album_asset.entity.dart @@ -10,6 +10,9 @@ class LocalAlbumAssetEntity extends Table with DriftDefaultsMixin { TextColumn get albumId => text().references(LocalAlbumEntity, #id, onDelete: KeyAction.cascade)(); + // Used for mark & sweep + BoolColumn get marker_ => boolean().nullable()(); + @override Set get primaryKey => {assetId, albumId}; } diff --git a/mobile/lib/infrastructure/entities/local_album_asset.entity.drift.dart b/mobile/lib/infrastructure/entities/local_album_asset.entity.drift.dart index 78da361f62..70c298332b 100644 --- a/mobile/lib/infrastructure/entities/local_album_asset.entity.drift.dart +++ b/mobile/lib/infrastructure/entities/local_album_asset.entity.drift.dart @@ -15,11 +15,13 @@ typedef $$LocalAlbumAssetEntityTableCreateCompanionBuilder = i1.LocalAlbumAssetEntityCompanion Function({ required String assetId, required String albumId, + i0.Value marker_, }); typedef $$LocalAlbumAssetEntityTableUpdateCompanionBuilder = i1.LocalAlbumAssetEntityCompanion Function({ i0.Value assetId, i0.Value albumId, + i0.Value marker_, }); final class $$LocalAlbumAssetEntityTableReferences @@ -113,6 +115,11 @@ class $$LocalAlbumAssetEntityTableFilterComposer super.$addJoinBuilderToRootComposer, super.$removeJoinBuilderFromRootComposer, }); + i0.ColumnFilters get marker_ => $composableBuilder( + column: $table.marker_, + builder: (column) => i0.ColumnFilters(column), + ); + i3.$$LocalAssetEntityTableFilterComposer get assetId { final i3.$$LocalAssetEntityTableFilterComposer composer = $composerBuilder( composer: this, @@ -177,6 +184,11 @@ class $$LocalAlbumAssetEntityTableOrderingComposer super.$addJoinBuilderToRootComposer, super.$removeJoinBuilderFromRootComposer, }); + i0.ColumnOrderings get marker_ => $composableBuilder( + column: $table.marker_, + builder: (column) => i0.ColumnOrderings(column), + ); + i3.$$LocalAssetEntityTableOrderingComposer get assetId { final i3.$$LocalAssetEntityTableOrderingComposer composer = $composerBuilder( @@ -243,6 +255,9 @@ class $$LocalAlbumAssetEntityTableAnnotationComposer super.$addJoinBuilderToRootComposer, super.$removeJoinBuilderFromRootComposer, }); + i0.GeneratedColumn get marker_ => + $composableBuilder(column: $table.marker_, builder: (column) => column); + i3.$$LocalAssetEntityTableAnnotationComposer get assetId { final i3.$$LocalAssetEntityTableAnnotationComposer composer = $composerBuilder( @@ -344,16 +359,22 @@ class $$LocalAlbumAssetEntityTableTableManager ({ i0.Value assetId = const i0.Value.absent(), i0.Value albumId = const i0.Value.absent(), + i0.Value marker_ = const i0.Value.absent(), }) => i1.LocalAlbumAssetEntityCompanion( assetId: assetId, albumId: albumId, + marker_: marker_, ), createCompanionCallback: - ({required String assetId, required String albumId}) => - i1.LocalAlbumAssetEntityCompanion.insert( - assetId: assetId, - albumId: albumId, - ), + ({ + required String assetId, + required String albumId, + i0.Value marker_ = const i0.Value.absent(), + }) => i1.LocalAlbumAssetEntityCompanion.insert( + assetId: assetId, + albumId: albumId, + marker_: marker_, + ), withReferenceMapper: (p0) => p0 .map( (e) => ( @@ -477,8 +498,22 @@ class $LocalAlbumAssetEntityTable extends i2.LocalAlbumAssetEntity 'REFERENCES local_album_entity (id) ON DELETE CASCADE', ), ); + static const i0.VerificationMeta _marker_Meta = const i0.VerificationMeta( + 'marker_', + ); @override - List get $columns => [assetId, albumId]; + late final i0.GeneratedColumn marker_ = i0.GeneratedColumn( + 'marker', + aliasedName, + true, + type: i0.DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: i0.GeneratedColumn.constraintIsAlways( + 'CHECK ("marker" IN (0, 1))', + ), + ); + @override + List get $columns => [assetId, albumId, marker_]; @override String get aliasedName => _alias ?? actualTableName; @override @@ -507,6 +542,12 @@ class $LocalAlbumAssetEntityTable extends i2.LocalAlbumAssetEntity } else if (isInserting) { context.missing(_albumIdMeta); } + if (data.containsKey('marker')) { + context.handle( + _marker_Meta, + marker_.isAcceptableOrUnknown(data['marker']!, _marker_Meta), + ); + } return context; } @@ -527,6 +568,10 @@ class $LocalAlbumAssetEntityTable extends i2.LocalAlbumAssetEntity i0.DriftSqlType.string, data['${effectivePrefix}album_id'], )!, + marker_: attachedDatabase.typeMapping.read( + i0.DriftSqlType.bool, + data['${effectivePrefix}marker'], + ), ); } @@ -545,15 +590,20 @@ class LocalAlbumAssetEntityData extends i0.DataClass implements i0.Insertable { final String assetId; final String albumId; + final bool? marker_; const LocalAlbumAssetEntityData({ required this.assetId, required this.albumId, + this.marker_, }); @override Map toColumns(bool nullToAbsent) { final map = {}; map['asset_id'] = i0.Variable(assetId); map['album_id'] = i0.Variable(albumId); + if (!nullToAbsent || marker_ != null) { + map['marker'] = i0.Variable(marker_); + } return map; } @@ -565,6 +615,7 @@ class LocalAlbumAssetEntityData extends i0.DataClass return LocalAlbumAssetEntityData( assetId: serializer.fromJson(json['assetId']), albumId: serializer.fromJson(json['albumId']), + marker_: serializer.fromJson(json['marker_']), ); } @override @@ -573,20 +624,26 @@ class LocalAlbumAssetEntityData extends i0.DataClass return { 'assetId': serializer.toJson(assetId), 'albumId': serializer.toJson(albumId), + 'marker_': serializer.toJson(marker_), }; } - i1.LocalAlbumAssetEntityData copyWith({String? assetId, String? albumId}) => - i1.LocalAlbumAssetEntityData( - assetId: assetId ?? this.assetId, - albumId: albumId ?? this.albumId, - ); + i1.LocalAlbumAssetEntityData copyWith({ + String? assetId, + String? albumId, + i0.Value marker_ = const i0.Value.absent(), + }) => i1.LocalAlbumAssetEntityData( + assetId: assetId ?? this.assetId, + albumId: albumId ?? this.albumId, + marker_: marker_.present ? marker_.value : this.marker_, + ); LocalAlbumAssetEntityData copyWithCompanion( i1.LocalAlbumAssetEntityCompanion data, ) { return LocalAlbumAssetEntityData( assetId: data.assetId.present ? data.assetId.value : this.assetId, albumId: data.albumId.present ? data.albumId.value : this.albumId, + marker_: data.marker_.present ? data.marker_.value : this.marker_, ); } @@ -594,51 +651,60 @@ class LocalAlbumAssetEntityData extends i0.DataClass String toString() { return (StringBuffer('LocalAlbumAssetEntityData(') ..write('assetId: $assetId, ') - ..write('albumId: $albumId') + ..write('albumId: $albumId, ') + ..write('marker_: $marker_') ..write(')')) .toString(); } @override - int get hashCode => Object.hash(assetId, albumId); + int get hashCode => Object.hash(assetId, albumId, marker_); @override bool operator ==(Object other) => identical(this, other) || (other is i1.LocalAlbumAssetEntityData && other.assetId == this.assetId && - other.albumId == this.albumId); + other.albumId == this.albumId && + other.marker_ == this.marker_); } class LocalAlbumAssetEntityCompanion extends i0.UpdateCompanion { final i0.Value assetId; final i0.Value albumId; + final i0.Value marker_; const LocalAlbumAssetEntityCompanion({ this.assetId = const i0.Value.absent(), this.albumId = const i0.Value.absent(), + this.marker_ = const i0.Value.absent(), }); LocalAlbumAssetEntityCompanion.insert({ required String assetId, required String albumId, + this.marker_ = const i0.Value.absent(), }) : assetId = i0.Value(assetId), albumId = i0.Value(albumId); static i0.Insertable custom({ i0.Expression? assetId, i0.Expression? albumId, + i0.Expression? marker_, }) { return i0.RawValuesInsertable({ if (assetId != null) 'asset_id': assetId, if (albumId != null) 'album_id': albumId, + if (marker_ != null) 'marker': marker_, }); } i1.LocalAlbumAssetEntityCompanion copyWith({ i0.Value? assetId, i0.Value? albumId, + i0.Value? marker_, }) { return i1.LocalAlbumAssetEntityCompanion( assetId: assetId ?? this.assetId, albumId: albumId ?? this.albumId, + marker_: marker_ ?? this.marker_, ); } @@ -651,6 +717,9 @@ class LocalAlbumAssetEntityCompanion if (albumId.present) { map['album_id'] = i0.Variable(albumId.value); } + if (marker_.present) { + map['marker'] = i0.Variable(marker_.value); + } return map; } @@ -658,7 +727,8 @@ class LocalAlbumAssetEntityCompanion String toString() { return (StringBuffer('LocalAlbumAssetEntityCompanion(') ..write('assetId: $assetId, ') - ..write('albumId: $albumId') + ..write('albumId: $albumId, ') + ..write('marker_: $marker_') ..write(')')) .toString(); } diff --git a/mobile/lib/infrastructure/entities/local_asset.entity.dart b/mobile/lib/infrastructure/entities/local_asset.entity.dart index 337a6d728d..8b253f83a3 100644 --- a/mobile/lib/infrastructure/entities/local_asset.entity.dart +++ b/mobile/lib/infrastructure/entities/local_asset.entity.dart @@ -21,7 +21,7 @@ class LocalAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin { } extension LocalAssetEntityDataDomainExtension on LocalAssetEntityData { - LocalAsset toDto() => LocalAsset( + LocalAsset toDto({String? remoteId}) => LocalAsset( id: id, name: name, checksum: checksum, @@ -32,7 +32,7 @@ extension LocalAssetEntityDataDomainExtension on LocalAssetEntityData { isFavorite: isFavorite, height: height, width: width, - remoteId: null, + remoteId: remoteId, orientation: orientation, ); } diff --git a/mobile/lib/infrastructure/entities/remote_asset.entity.dart b/mobile/lib/infrastructure/entities/remote_asset.entity.dart index 4426974413..dcc885a2a9 100644 --- a/mobile/lib/infrastructure/entities/remote_asset.entity.dart +++ b/mobile/lib/infrastructure/entities/remote_asset.entity.dart @@ -49,7 +49,7 @@ class RemoteAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin } extension RemoteAssetEntityDataDomainEx on RemoteAssetEntityData { - RemoteAsset toDto() => RemoteAsset( + RemoteAsset toDto({String? localId}) => RemoteAsset( id: id, name: name, ownerId: ownerId, @@ -64,7 +64,7 @@ extension RemoteAssetEntityDataDomainEx on RemoteAssetEntityData { thumbHash: thumbHash, visibility: visibility, livePhotoVideoId: livePhotoVideoId, - localId: null, + localId: localId, stackId: stackId, ); } diff --git a/mobile/lib/infrastructure/entities/store.entity.g.dart b/mobile/lib/infrastructure/entities/store.entity.g.dart index 7da92cf778..626c3084fe 100644 --- a/mobile/lib/infrastructure/entities/store.entity.g.dart +++ b/mobile/lib/infrastructure/entities/store.entity.g.dart @@ -37,7 +37,7 @@ const StoreValueSchema = CollectionSchema( getId: _storeValueGetId, getLinks: _storeValueGetLinks, attach: _storeValueAttach, - version: '3.1.8', + version: '3.3.0-dev.3', ); int _storeValueEstimateSize( diff --git a/mobile/lib/infrastructure/entities/user.entity.dart b/mobile/lib/infrastructure/entities/user.entity.dart index c3612cb8c6..667a9d6a59 100644 --- a/mobile/lib/infrastructure/entities/user.entity.dart +++ b/mobile/lib/infrastructure/entities/user.entity.dart @@ -1,6 +1,5 @@ import 'package:drift/drift.dart' hide Index; import 'package:immich_mobile/domain/models/user.model.dart'; -import 'package:immich_mobile/domain/models/user_metadata.model.dart'; import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart'; import 'package:immich_mobile/utils/hash.dart'; import 'package:isar/isar.dart'; @@ -44,7 +43,7 @@ class User { static User fromDto(UserDto dto) => User( id: dto.id, - updatedAt: dto.updatedAt, + updatedAt: dto.updatedAt ?? DateTime(2025), email: dto.email, name: dto.name, isAdmin: dto.isAdmin, @@ -81,13 +80,12 @@ class UserEntity extends Table with DriftDefaultsMixin { TextColumn get id => text()(); TextColumn get name => text()(); - BoolColumn get isAdmin => boolean().withDefault(const Constant(false))(); TextColumn get email => text()(); + // Profile image BoolColumn get hasProfileImage => boolean().withDefault(const Constant(false))(); DateTimeColumn get profileChangedAt => dateTime().withDefault(currentDateAndTime)(); - - DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)(); + IntColumn get avatarColor => intEnum().withDefault(const Constant(0))(); @override Set get primaryKey => {id}; diff --git a/mobile/lib/infrastructure/entities/user.entity.drift.dart b/mobile/lib/infrastructure/entities/user.entity.drift.dart index dbfddab4a0..083c14a095 100644 --- a/mobile/lib/infrastructure/entities/user.entity.drift.dart +++ b/mobile/lib/infrastructure/entities/user.entity.drift.dart @@ -3,28 +3,27 @@ import 'package:drift/drift.dart' as i0; import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart' as i1; -import 'package:immich_mobile/infrastructure/entities/user.entity.dart' as i2; -import 'package:drift/src/runtime/query_builder/query_builder.dart' as i3; +import 'package:immich_mobile/domain/models/user.model.dart' as i2; +import 'package:immich_mobile/infrastructure/entities/user.entity.dart' as i3; +import 'package:drift/src/runtime/query_builder/query_builder.dart' as i4; typedef $$UserEntityTableCreateCompanionBuilder = i1.UserEntityCompanion Function({ required String id, required String name, - i0.Value isAdmin, required String email, i0.Value hasProfileImage, i0.Value profileChangedAt, - i0.Value updatedAt, + i0.Value avatarColor, }); typedef $$UserEntityTableUpdateCompanionBuilder = i1.UserEntityCompanion Function({ i0.Value id, i0.Value name, - i0.Value isAdmin, i0.Value email, i0.Value hasProfileImage, i0.Value profileChangedAt, - i0.Value updatedAt, + i0.Value avatarColor, }); class $$UserEntityTableFilterComposer @@ -46,11 +45,6 @@ class $$UserEntityTableFilterComposer builder: (column) => i0.ColumnFilters(column), ); - i0.ColumnFilters get isAdmin => $composableBuilder( - column: $table.isAdmin, - builder: (column) => i0.ColumnFilters(column), - ); - i0.ColumnFilters get email => $composableBuilder( column: $table.email, builder: (column) => i0.ColumnFilters(column), @@ -66,9 +60,10 @@ class $$UserEntityTableFilterComposer builder: (column) => i0.ColumnFilters(column), ); - i0.ColumnFilters get updatedAt => $composableBuilder( - column: $table.updatedAt, - builder: (column) => i0.ColumnFilters(column), + i0.ColumnWithTypeConverterFilters + get avatarColor => $composableBuilder( + column: $table.avatarColor, + builder: (column) => i0.ColumnWithTypeConverterFilters(column), ); } @@ -91,11 +86,6 @@ class $$UserEntityTableOrderingComposer builder: (column) => i0.ColumnOrderings(column), ); - i0.ColumnOrderings get isAdmin => $composableBuilder( - column: $table.isAdmin, - builder: (column) => i0.ColumnOrderings(column), - ); - i0.ColumnOrderings get email => $composableBuilder( column: $table.email, builder: (column) => i0.ColumnOrderings(column), @@ -111,8 +101,8 @@ class $$UserEntityTableOrderingComposer builder: (column) => i0.ColumnOrderings(column), ); - i0.ColumnOrderings get updatedAt => $composableBuilder( - column: $table.updatedAt, + i0.ColumnOrderings get avatarColor => $composableBuilder( + column: $table.avatarColor, builder: (column) => i0.ColumnOrderings(column), ); } @@ -132,9 +122,6 @@ class $$UserEntityTableAnnotationComposer i0.GeneratedColumn get name => $composableBuilder(column: $table.name, builder: (column) => column); - i0.GeneratedColumn get isAdmin => - $composableBuilder(column: $table.isAdmin, builder: (column) => column); - i0.GeneratedColumn get email => $composableBuilder(column: $table.email, builder: (column) => column); @@ -148,8 +135,11 @@ class $$UserEntityTableAnnotationComposer builder: (column) => column, ); - i0.GeneratedColumn get updatedAt => - $composableBuilder(column: $table.updatedAt, builder: (column) => column); + i0.GeneratedColumnWithTypeConverter get avatarColor => + $composableBuilder( + column: $table.avatarColor, + builder: (column) => column, + ); } class $$UserEntityTableTableManager @@ -191,37 +181,33 @@ class $$UserEntityTableTableManager ({ i0.Value id = const i0.Value.absent(), i0.Value name = const i0.Value.absent(), - i0.Value isAdmin = const i0.Value.absent(), i0.Value email = const i0.Value.absent(), i0.Value hasProfileImage = const i0.Value.absent(), i0.Value profileChangedAt = const i0.Value.absent(), - i0.Value updatedAt = const i0.Value.absent(), + i0.Value avatarColor = const i0.Value.absent(), }) => i1.UserEntityCompanion( id: id, name: name, - isAdmin: isAdmin, email: email, hasProfileImage: hasProfileImage, profileChangedAt: profileChangedAt, - updatedAt: updatedAt, + avatarColor: avatarColor, ), createCompanionCallback: ({ required String id, required String name, - i0.Value isAdmin = const i0.Value.absent(), required String email, i0.Value hasProfileImage = const i0.Value.absent(), i0.Value profileChangedAt = const i0.Value.absent(), - i0.Value updatedAt = const i0.Value.absent(), + i0.Value avatarColor = const i0.Value.absent(), }) => i1.UserEntityCompanion.insert( id: id, name: name, - isAdmin: isAdmin, email: email, hasProfileImage: hasProfileImage, profileChangedAt: profileChangedAt, - updatedAt: updatedAt, + avatarColor: avatarColor, ), withReferenceMapper: (p0) => p0 .map((e) => (e.readTable(table), i0.BaseReferences(db, table, e))) @@ -253,7 +239,7 @@ typedef $$UserEntityTableProcessedTableManager = i0.PrefetchHooks Function() >; -class $UserEntityTable extends i2.UserEntity +class $UserEntityTable extends i3.UserEntity with i0.TableInfo<$UserEntityTable, i1.UserEntityData> { @override final i0.GeneratedDatabase attachedDatabase; @@ -279,21 +265,6 @@ class $UserEntityTable extends i2.UserEntity type: i0.DriftSqlType.string, requiredDuringInsert: true, ); - static const i0.VerificationMeta _isAdminMeta = const i0.VerificationMeta( - 'isAdmin', - ); - @override - late final i0.GeneratedColumn isAdmin = i0.GeneratedColumn( - 'is_admin', - aliasedName, - false, - type: i0.DriftSqlType.bool, - requiredDuringInsert: false, - defaultConstraints: i0.GeneratedColumn.constraintIsAlways( - 'CHECK ("is_admin" IN (0, 1))', - ), - defaultValue: const i3.Constant(false), - ); static const i0.VerificationMeta _emailMeta = const i0.VerificationMeta( 'email', ); @@ -318,7 +289,7 @@ class $UserEntityTable extends i2.UserEntity defaultConstraints: i0.GeneratedColumn.constraintIsAlways( 'CHECK ("has_profile_image" IN (0, 1))', ), - defaultValue: const i3.Constant(false), + defaultValue: const i4.Constant(false), ); static const i0.VerificationMeta _profileChangedAtMeta = const i0.VerificationMeta('profileChangedAt'); @@ -330,30 +301,26 @@ class $UserEntityTable extends i2.UserEntity false, type: i0.DriftSqlType.dateTime, requiredDuringInsert: false, - defaultValue: i3.currentDateAndTime, + defaultValue: i4.currentDateAndTime, ); - static const i0.VerificationMeta _updatedAtMeta = const i0.VerificationMeta( - 'updatedAt', - ); @override - late final i0.GeneratedColumn updatedAt = - i0.GeneratedColumn( - 'updated_at', - aliasedName, - false, - type: i0.DriftSqlType.dateTime, - requiredDuringInsert: false, - defaultValue: i3.currentDateAndTime, - ); + late final i0.GeneratedColumnWithTypeConverter + avatarColor = i0.GeneratedColumn( + 'avatar_color', + aliasedName, + false, + type: i0.DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const i4.Constant(0), + ).withConverter(i1.$UserEntityTable.$converteravatarColor); @override List get $columns => [ id, name, - isAdmin, email, hasProfileImage, profileChangedAt, - updatedAt, + avatarColor, ]; @override String get aliasedName => _alias ?? actualTableName; @@ -380,12 +347,6 @@ class $UserEntityTable extends i2.UserEntity } else if (isInserting) { context.missing(_nameMeta); } - if (data.containsKey('is_admin')) { - context.handle( - _isAdminMeta, - isAdmin.isAcceptableOrUnknown(data['is_admin']!, _isAdminMeta), - ); - } if (data.containsKey('email')) { context.handle( _emailMeta, @@ -412,12 +373,6 @@ class $UserEntityTable extends i2.UserEntity ), ); } - if (data.containsKey('updated_at')) { - context.handle( - _updatedAtMeta, - updatedAt.isAcceptableOrUnknown(data['updated_at']!, _updatedAtMeta), - ); - } return context; } @@ -435,10 +390,6 @@ class $UserEntityTable extends i2.UserEntity i0.DriftSqlType.string, data['${effectivePrefix}name'], )!, - isAdmin: attachedDatabase.typeMapping.read( - i0.DriftSqlType.bool, - data['${effectivePrefix}is_admin'], - )!, email: attachedDatabase.typeMapping.read( i0.DriftSqlType.string, data['${effectivePrefix}email'], @@ -451,10 +402,12 @@ class $UserEntityTable extends i2.UserEntity i0.DriftSqlType.dateTime, data['${effectivePrefix}profile_changed_at'], )!, - updatedAt: attachedDatabase.typeMapping.read( - i0.DriftSqlType.dateTime, - data['${effectivePrefix}updated_at'], - )!, + avatarColor: i1.$UserEntityTable.$converteravatarColor.fromSql( + attachedDatabase.typeMapping.read( + i0.DriftSqlType.int, + data['${effectivePrefix}avatar_color'], + )!, + ), ); } @@ -463,6 +416,8 @@ class $UserEntityTable extends i2.UserEntity return $UserEntityTable(attachedDatabase, alias); } + static i0.JsonTypeConverter2 $converteravatarColor = + const i0.EnumIndexConverter(i2.AvatarColor.values); @override bool get withoutRowId => true; @override @@ -473,30 +428,31 @@ class UserEntityData extends i0.DataClass implements i0.Insertable { final String id; final String name; - final bool isAdmin; final String email; final bool hasProfileImage; final DateTime profileChangedAt; - final DateTime updatedAt; + final i2.AvatarColor avatarColor; const UserEntityData({ required this.id, required this.name, - required this.isAdmin, required this.email, required this.hasProfileImage, required this.profileChangedAt, - required this.updatedAt, + required this.avatarColor, }); @override Map toColumns(bool nullToAbsent) { final map = {}; map['id'] = i0.Variable(id); map['name'] = i0.Variable(name); - map['is_admin'] = i0.Variable(isAdmin); map['email'] = i0.Variable(email); map['has_profile_image'] = i0.Variable(hasProfileImage); map['profile_changed_at'] = i0.Variable(profileChangedAt); - map['updated_at'] = i0.Variable(updatedAt); + { + map['avatar_color'] = i0.Variable( + i1.$UserEntityTable.$converteravatarColor.toSql(avatarColor), + ); + } return map; } @@ -508,11 +464,12 @@ class UserEntityData extends i0.DataClass return UserEntityData( id: serializer.fromJson(json['id']), name: serializer.fromJson(json['name']), - isAdmin: serializer.fromJson(json['isAdmin']), email: serializer.fromJson(json['email']), hasProfileImage: serializer.fromJson(json['hasProfileImage']), profileChangedAt: serializer.fromJson(json['profileChangedAt']), - updatedAt: serializer.fromJson(json['updatedAt']), + avatarColor: i1.$UserEntityTable.$converteravatarColor.fromJson( + serializer.fromJson(json['avatarColor']), + ), ); } @override @@ -521,36 +478,34 @@ class UserEntityData extends i0.DataClass return { 'id': serializer.toJson(id), 'name': serializer.toJson(name), - 'isAdmin': serializer.toJson(isAdmin), 'email': serializer.toJson(email), 'hasProfileImage': serializer.toJson(hasProfileImage), 'profileChangedAt': serializer.toJson(profileChangedAt), - 'updatedAt': serializer.toJson(updatedAt), + 'avatarColor': serializer.toJson( + i1.$UserEntityTable.$converteravatarColor.toJson(avatarColor), + ), }; } i1.UserEntityData copyWith({ String? id, String? name, - bool? isAdmin, String? email, bool? hasProfileImage, DateTime? profileChangedAt, - DateTime? updatedAt, + i2.AvatarColor? avatarColor, }) => i1.UserEntityData( id: id ?? this.id, name: name ?? this.name, - isAdmin: isAdmin ?? this.isAdmin, email: email ?? this.email, hasProfileImage: hasProfileImage ?? this.hasProfileImage, profileChangedAt: profileChangedAt ?? this.profileChangedAt, - updatedAt: updatedAt ?? this.updatedAt, + avatarColor: avatarColor ?? this.avatarColor, ); UserEntityData copyWithCompanion(i1.UserEntityCompanion data) { return UserEntityData( id: data.id.present ? data.id.value : this.id, name: data.name.present ? data.name.value : this.name, - isAdmin: data.isAdmin.present ? data.isAdmin.value : this.isAdmin, email: data.email.present ? data.email.value : this.email, hasProfileImage: data.hasProfileImage.present ? data.hasProfileImage.value @@ -558,7 +513,9 @@ class UserEntityData extends i0.DataClass profileChangedAt: data.profileChangedAt.present ? data.profileChangedAt.value : this.profileChangedAt, - updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + avatarColor: data.avatarColor.present + ? data.avatarColor.value + : this.avatarColor, ); } @@ -567,11 +524,10 @@ class UserEntityData extends i0.DataClass return (StringBuffer('UserEntityData(') ..write('id: $id, ') ..write('name: $name, ') - ..write('isAdmin: $isAdmin, ') ..write('email: $email, ') ..write('hasProfileImage: $hasProfileImage, ') ..write('profileChangedAt: $profileChangedAt, ') - ..write('updatedAt: $updatedAt') + ..write('avatarColor: $avatarColor') ..write(')')) .toString(); } @@ -580,11 +536,10 @@ class UserEntityData extends i0.DataClass int get hashCode => Object.hash( id, name, - isAdmin, email, hasProfileImage, profileChangedAt, - updatedAt, + avatarColor, ); @override bool operator ==(Object other) => @@ -592,78 +547,70 @@ class UserEntityData extends i0.DataClass (other is i1.UserEntityData && other.id == this.id && other.name == this.name && - other.isAdmin == this.isAdmin && other.email == this.email && other.hasProfileImage == this.hasProfileImage && other.profileChangedAt == this.profileChangedAt && - other.updatedAt == this.updatedAt); + other.avatarColor == this.avatarColor); } class UserEntityCompanion extends i0.UpdateCompanion { final i0.Value id; final i0.Value name; - final i0.Value isAdmin; final i0.Value email; final i0.Value hasProfileImage; final i0.Value profileChangedAt; - final i0.Value updatedAt; + final i0.Value avatarColor; const UserEntityCompanion({ this.id = const i0.Value.absent(), this.name = const i0.Value.absent(), - this.isAdmin = const i0.Value.absent(), this.email = const i0.Value.absent(), this.hasProfileImage = const i0.Value.absent(), this.profileChangedAt = const i0.Value.absent(), - this.updatedAt = const i0.Value.absent(), + this.avatarColor = const i0.Value.absent(), }); UserEntityCompanion.insert({ required String id, required String name, - this.isAdmin = const i0.Value.absent(), required String email, this.hasProfileImage = const i0.Value.absent(), this.profileChangedAt = const i0.Value.absent(), - this.updatedAt = const i0.Value.absent(), + this.avatarColor = const i0.Value.absent(), }) : id = i0.Value(id), name = i0.Value(name), email = i0.Value(email); static i0.Insertable custom({ i0.Expression? id, i0.Expression? name, - i0.Expression? isAdmin, i0.Expression? email, i0.Expression? hasProfileImage, i0.Expression? profileChangedAt, - i0.Expression? updatedAt, + i0.Expression? avatarColor, }) { return i0.RawValuesInsertable({ if (id != null) 'id': id, if (name != null) 'name': name, - if (isAdmin != null) 'is_admin': isAdmin, if (email != null) 'email': email, if (hasProfileImage != null) 'has_profile_image': hasProfileImage, if (profileChangedAt != null) 'profile_changed_at': profileChangedAt, - if (updatedAt != null) 'updated_at': updatedAt, + if (avatarColor != null) 'avatar_color': avatarColor, }); } i1.UserEntityCompanion copyWith({ i0.Value? id, i0.Value? name, - i0.Value? isAdmin, i0.Value? email, i0.Value? hasProfileImage, i0.Value? profileChangedAt, - i0.Value? updatedAt, + i0.Value? avatarColor, }) { return i1.UserEntityCompanion( id: id ?? this.id, name: name ?? this.name, - isAdmin: isAdmin ?? this.isAdmin, email: email ?? this.email, hasProfileImage: hasProfileImage ?? this.hasProfileImage, profileChangedAt: profileChangedAt ?? this.profileChangedAt, - updatedAt: updatedAt ?? this.updatedAt, + avatarColor: avatarColor ?? this.avatarColor, ); } @@ -676,9 +623,6 @@ class UserEntityCompanion extends i0.UpdateCompanion { if (name.present) { map['name'] = i0.Variable(name.value); } - if (isAdmin.present) { - map['is_admin'] = i0.Variable(isAdmin.value); - } if (email.present) { map['email'] = i0.Variable(email.value); } @@ -688,8 +632,10 @@ class UserEntityCompanion extends i0.UpdateCompanion { if (profileChangedAt.present) { map['profile_changed_at'] = i0.Variable(profileChangedAt.value); } - if (updatedAt.present) { - map['updated_at'] = i0.Variable(updatedAt.value); + if (avatarColor.present) { + map['avatar_color'] = i0.Variable( + i1.$UserEntityTable.$converteravatarColor.toSql(avatarColor.value), + ); } return map; } @@ -699,11 +645,10 @@ class UserEntityCompanion extends i0.UpdateCompanion { return (StringBuffer('UserEntityCompanion(') ..write('id: $id, ') ..write('name: $name, ') - ..write('isAdmin: $isAdmin, ') ..write('email: $email, ') ..write('hasProfileImage: $hasProfileImage, ') ..write('profileChangedAt: $profileChangedAt, ') - ..write('updatedAt: $updatedAt') + ..write('avatarColor: $avatarColor') ..write(')')) .toString(); } diff --git a/mobile/lib/infrastructure/entities/user.entity.g.dart b/mobile/lib/infrastructure/entities/user.entity.g.dart index bb87051731..7e0af41b77 100644 --- a/mobile/lib/infrastructure/entities/user.entity.g.dart +++ b/mobile/lib/infrastructure/entities/user.entity.g.dart @@ -95,7 +95,7 @@ const UserSchema = CollectionSchema( getId: _userGetId, getLinks: _userGetLinks, attach: _userAttach, - version: '3.1.8', + version: '3.3.0-dev.3', ); int _userEstimateSize( diff --git a/mobile/lib/infrastructure/repositories/backup.repository.dart b/mobile/lib/infrastructure/repositories/backup.repository.dart index 057c7a7bf6..0241711d4b 100644 --- a/mobile/lib/infrastructure/repositories/backup.repository.dart +++ b/mobile/lib/infrastructure/repositories/backup.repository.dart @@ -4,7 +4,6 @@ import 'package:drift/drift.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/album/local_album.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; -import 'package:immich_mobile/infrastructure/entities/local_album.entity.dart'; import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; @@ -30,85 +29,59 @@ class DriftBackupRepository extends DriftDatabaseRepository { ..where(_db.localAlbumEntity.backupSelection.equalsValue(BackupSelection.excluded)); } - Future getTotalCount() async { - final query = _db.localAlbumAssetEntity.selectOnly(distinct: true) - ..addColumns([_db.localAlbumAssetEntity.assetId]) - ..join([ - innerJoin( - _db.localAlbumEntity, - _db.localAlbumAssetEntity.albumId.equalsExp(_db.localAlbumEntity.id), - useColumns: false, - ), - ]) - ..where( - _db.localAlbumEntity.backupSelection.equalsValue(BackupSelection.selected) & - _db.localAlbumAssetEntity.assetId.isNotInQuery(_getExcludedSubquery()), - ); + /// Returns all backup-related counts in a single query. + /// + /// - total: number of distinct assets in selected albums, excluding those that are also in excluded albums + /// - backup: number of those assets that already exist on the server for [userId] + /// - remainder: number of those assets that do not yet exist on the server for [userId] + /// (includes processing) + /// - processing: number of those assets that are still preparing/have a null checksum + Future<({int total, int remainder, int processing})> getAllCounts(String userId) async { + const sql = ''' + SELECT + COUNT(*) AS total_count, + COUNT(*) FILTER (WHERE lae.checksum IS NULL) AS processing_count, + COUNT(*) FILTER (WHERE rae.id IS NULL) AS remainder_count + FROM local_asset_entity lae + LEFT JOIN main.remote_asset_entity rae + ON lae.checksum = rae.checksum AND rae.owner_id = ?1 + WHERE EXISTS ( + SELECT 1 + FROM local_album_asset_entity laa + INNER JOIN main.local_album_entity la on laa.album_id = la.id + WHERE laa.asset_id = lae.id + AND la.backup_selection = ?2 + ) + AND NOT EXISTS ( + SELECT 1 + FROM local_album_asset_entity laa + INNER JOIN main.local_album_entity la on laa.album_id = la.id + WHERE laa.asset_id = lae.id + AND la.backup_selection = ?3 + ); + '''; - return query.get().then((rows) => rows.length); + final row = await _db + .customSelect( + sql, + variables: [ + Variable.withString(userId), + Variable.withInt(BackupSelection.selected.index), + Variable.withInt(BackupSelection.excluded.index), + ], + readsFrom: {_db.localAlbumAssetEntity, _db.localAlbumEntity, _db.localAssetEntity, _db.remoteAssetEntity}, + ) + .getSingle(); + + final data = row.data; + return ( + total: (data['total_count'] as int?) ?? 0, + remainder: (data['remainder_count'] as int?) ?? 0, + processing: (data['processing_count'] as int?) ?? 0, + ); } - Future getRemainderCount(String userId) async { - final query = _db.localAlbumAssetEntity.selectOnly(distinct: true) - ..addColumns([_db.localAlbumAssetEntity.assetId]) - ..join([ - innerJoin( - _db.localAlbumEntity, - _db.localAlbumAssetEntity.albumId.equalsExp(_db.localAlbumEntity.id), - useColumns: false, - ), - innerJoin( - _db.localAssetEntity, - _db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id), - useColumns: false, - ), - leftOuterJoin( - _db.remoteAssetEntity, - _db.localAssetEntity.checksum.equalsExp(_db.remoteAssetEntity.checksum) & - _db.remoteAssetEntity.ownerId.equals(userId), - useColumns: false, - ), - ]) - ..where( - _db.localAlbumEntity.backupSelection.equalsValue(BackupSelection.selected) & - _db.remoteAssetEntity.id.isNull() & - _db.localAlbumAssetEntity.assetId.isNotInQuery(_getExcludedSubquery()), - ); - - return query.get().then((rows) => rows.length); - } - - Future getBackupCount(String userId) async { - final query = _db.localAlbumAssetEntity.selectOnly(distinct: true) - ..addColumns([_db.localAlbumAssetEntity.assetId]) - ..join([ - innerJoin( - _db.localAlbumEntity, - _db.localAlbumAssetEntity.albumId.equalsExp(_db.localAlbumEntity.id), - useColumns: false, - ), - innerJoin( - _db.localAssetEntity, - _db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id), - useColumns: false, - ), - innerJoin( - _db.remoteAssetEntity, - _db.localAssetEntity.checksum.equalsExp(_db.remoteAssetEntity.checksum), - useColumns: false, - ), - ]) - ..where( - _db.localAlbumEntity.backupSelection.equalsValue(BackupSelection.selected) & - _db.remoteAssetEntity.id.isNotNull() & - _db.remoteAssetEntity.ownerId.equals(userId) & - _db.localAlbumAssetEntity.assetId.isNotInQuery(_getExcludedSubquery()), - ); - - return query.get().then((rows) => rows.length); - } - - Future> getCandidates(String userId) async { + Future> getCandidates(String userId, {bool onlyHashed = true}) async { final selectedAlbumIds = _db.localAlbumEntity.selectOnly(distinct: true) ..addColumns([_db.localAlbumEntity.id]) ..where(_db.localAlbumEntity.backupSelection.equalsValue(BackupSelection.selected)); @@ -116,7 +89,6 @@ class DriftBackupRepository extends DriftDatabaseRepository { final query = _db.localAssetEntity.select() ..where( (lae) => - lae.checksum.isNotNull() & existsQuery( _db.localAlbumAssetEntity.selectOnly() ..addColumns([_db.localAlbumAssetEntity.assetId]) @@ -136,24 +108,10 @@ class DriftBackupRepository extends DriftDatabaseRepository { ) ..orderBy([(localAsset) => OrderingTerm.desc(localAsset.createdAt)]); + if (onlyHashed) { + query.where((lae) => lae.checksum.isNotNull()); + } + return query.map((localAsset) => localAsset.toDto()).get(); } - - FutureOr> getSourceAlbums(String localAssetId) { - final query = _db.localAlbumEntity.select() - ..where( - (lae) => - existsQuery( - _db.localAlbumAssetEntity.selectOnly() - ..addColumns([_db.localAlbumAssetEntity.albumId]) - ..where( - _db.localAlbumAssetEntity.albumId.equalsExp(lae.id) & - _db.localAlbumAssetEntity.assetId.equals(localAssetId), - ), - ) & - lae.backupSelection.equalsValue(BackupSelection.selected), - ) - ..orderBy([(lae) => OrderingTerm.asc(lae.name)]); - return query.map((localAlbum) => localAlbum.toDto()).get(); - } } diff --git a/mobile/lib/infrastructure/repositories/db.repository.dart b/mobile/lib/infrastructure/repositories/db.repository.dart index f8de114f85..7291c3a97b 100644 --- a/mobile/lib/infrastructure/repositories/db.repository.dart +++ b/mobile/lib/infrastructure/repositories/db.repository.dart @@ -5,6 +5,7 @@ import 'package:drift_flutter/drift_flutter.dart'; import 'package:flutter/foundation.dart'; import 'package:immich_mobile/domain/interfaces/db.interface.dart'; import 'package:immich_mobile/infrastructure/entities/asset_face.entity.dart'; +import 'package:immich_mobile/infrastructure/entities/auth_user.entity.dart'; import 'package:immich_mobile/infrastructure/entities/exif.entity.dart'; import 'package:immich_mobile/infrastructure/entities/local_album.entity.dart'; import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.dart'; @@ -43,6 +44,7 @@ class IsarDatabaseRepository implements IDatabaseRepository { @DriftDatabase( tables: [ + AuthUserEntity, UserEntity, UserMetadataEntity, PartnerEntity, @@ -67,8 +69,31 @@ class Drift extends $Drift implements IDatabaseRepository { Drift([QueryExecutor? executor]) : super(executor ?? driftDatabase(name: 'immich', native: const DriftNativeOptions(shareAcrossIsolates: true))); + Future reset() async { + // https://github.com/simolus3/drift/commit/bd80a46264b6dd833ef4fd87fffc03f5a832ab41#diff-3f879e03b4a35779344ef16170b9353608dd9c42385f5402ec6035aac4dd8a04R76-R94 + await exclusively(() async { + // https://stackoverflow.com/a/65743498/25690041 + await customStatement('PRAGMA writable_schema = 1;'); + await customStatement('DELETE FROM sqlite_master;'); + await customStatement('VACUUM;'); + await customStatement('PRAGMA writable_schema = 0;'); + await customStatement('PRAGMA integrity_check'); + + await customStatement('PRAGMA user_version = 0'); + await beforeOpen( + // ignore: invalid_use_of_internal_member + resolvedEngine.executor, + OpeningDetails(null, schemaVersion), + ); + await customStatement('PRAGMA user_version = $schemaVersion'); + + // Refresh all stream queries + notifyUpdates({for (final table in allTables) TableUpdate.onTable(table)}); + }); + } + @override - int get schemaVersion => 9; + int get schemaVersion => 12; @override MigrationStrategy get migration => MigrationStrategy( @@ -126,6 +151,33 @@ class Drift extends $Drift implements IDatabaseRepository { from8To9: (m, v9) async { await m.addColumn(v9.localAlbumEntity, v9.localAlbumEntity.linkedRemoteAlbumId); }, + from9To10: (m, v10) async { + await m.createTable(v10.authUserEntity); + await m.addColumn(v10.userEntity, v10.userEntity.avatarColor); + await m.alterTable(TableMigration(v10.userEntity)); + }, + from10To11: (m, v11) async { + await m.addColumn(v11.localAlbumAssetEntity, v11.localAlbumAssetEntity.marker_); + }, + from11To12: (m, v12) async { + final localToUTCMapping = { + v12.localAssetEntity: [v12.localAssetEntity.createdAt, v12.localAssetEntity.updatedAt], + v12.localAlbumEntity: [v12.localAlbumEntity.updatedAt], + }; + + for (final entry in localToUTCMapping.entries) { + final table = entry.key; + await m.alterTable( + TableMigration( + table, + columnTransformer: { + for (final column in entry.value) + column: column.modify(const DateTimeModifier.utc()).strftime('%Y-%m-%dT%H:%M:%fZ'), + }, + ), + ); + } + }, ), ); @@ -141,7 +193,7 @@ class Drift extends $Drift implements IDatabaseRepository { await customStatement('PRAGMA foreign_keys = ON'); await customStatement('PRAGMA synchronous = NORMAL'); await customStatement('PRAGMA journal_mode = WAL'); - await customStatement('PRAGMA busy_timeout = 500'); + await customStatement('PRAGMA busy_timeout = 30000'); }, ); } diff --git a/mobile/lib/infrastructure/repositories/db.repository.drift.dart b/mobile/lib/infrastructure/repositories/db.repository.drift.dart index 035f7b0c03..e39ed8a560 100644 --- a/mobile/lib/infrastructure/repositories/db.repository.drift.dart +++ b/mobile/lib/infrastructure/repositories/db.repository.drift.dart @@ -15,29 +15,31 @@ import 'package:immich_mobile/infrastructure/entities/local_album.entity.drift.d as i6; import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.drift.dart' as i7; -import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.drift.dart' +import 'package:immich_mobile/infrastructure/entities/auth_user.entity.drift.dart' as i8; -import 'package:immich_mobile/infrastructure/entities/partner.entity.drift.dart' +import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.drift.dart' as i9; -import 'package:immich_mobile/infrastructure/entities/exif.entity.drift.dart' +import 'package:immich_mobile/infrastructure/entities/partner.entity.drift.dart' as i10; -import 'package:immich_mobile/infrastructure/entities/remote_album_asset.entity.drift.dart' +import 'package:immich_mobile/infrastructure/entities/exif.entity.drift.dart' as i11; -import 'package:immich_mobile/infrastructure/entities/remote_album_user.entity.drift.dart' +import 'package:immich_mobile/infrastructure/entities/remote_album_asset.entity.drift.dart' as i12; -import 'package:immich_mobile/infrastructure/entities/memory.entity.drift.dart' +import 'package:immich_mobile/infrastructure/entities/remote_album_user.entity.drift.dart' as i13; -import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.drift.dart' +import 'package:immich_mobile/infrastructure/entities/memory.entity.drift.dart' as i14; -import 'package:immich_mobile/infrastructure/entities/person.entity.drift.dart' +import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.drift.dart' as i15; -import 'package:immich_mobile/infrastructure/entities/asset_face.entity.drift.dart' +import 'package:immich_mobile/infrastructure/entities/person.entity.drift.dart' as i16; -import 'package:immich_mobile/infrastructure/entities/store.entity.drift.dart' +import 'package:immich_mobile/infrastructure/entities/asset_face.entity.drift.dart' as i17; -import 'package:immich_mobile/infrastructure/entities/merged_asset.drift.dart' +import 'package:immich_mobile/infrastructure/entities/store.entity.drift.dart' as i18; -import 'package:drift/internal/modular.dart' as i19; +import 'package:immich_mobile/infrastructure/entities/merged_asset.drift.dart' + as i19; +import 'package:drift/internal/modular.dart' as i20; abstract class $Drift extends i0.GeneratedDatabase { $Drift(i0.QueryExecutor e) : super(e); @@ -54,27 +56,30 @@ abstract class $Drift extends i0.GeneratedDatabase { .$LocalAlbumEntityTable(this); late final i7.$LocalAlbumAssetEntityTable localAlbumAssetEntity = i7 .$LocalAlbumAssetEntityTable(this); - late final i8.$UserMetadataEntityTable userMetadataEntity = i8 - .$UserMetadataEntityTable(this); - late final i9.$PartnerEntityTable partnerEntity = i9.$PartnerEntityTable( + late final i8.$AuthUserEntityTable authUserEntity = i8.$AuthUserEntityTable( this, ); - late final i10.$RemoteExifEntityTable remoteExifEntity = i10 - .$RemoteExifEntityTable(this); - late final i11.$RemoteAlbumAssetEntityTable remoteAlbumAssetEntity = i11 - .$RemoteAlbumAssetEntityTable(this); - late final i12.$RemoteAlbumUserEntityTable remoteAlbumUserEntity = i12 - .$RemoteAlbumUserEntityTable(this); - late final i13.$MemoryEntityTable memoryEntity = i13.$MemoryEntityTable(this); - late final i14.$MemoryAssetEntityTable memoryAssetEntity = i14 - .$MemoryAssetEntityTable(this); - late final i15.$PersonEntityTable personEntity = i15.$PersonEntityTable(this); - late final i16.$AssetFaceEntityTable assetFaceEntity = i16 - .$AssetFaceEntityTable(this); - late final i17.$StoreEntityTable storeEntity = i17.$StoreEntityTable(this); - i18.MergedAssetDrift get mergedAssetDrift => i19.ReadDatabaseContainer( + late final i9.$UserMetadataEntityTable userMetadataEntity = i9 + .$UserMetadataEntityTable(this); + late final i10.$PartnerEntityTable partnerEntity = i10.$PartnerEntityTable( this, - ).accessor(i18.MergedAssetDrift.new); + ); + late final i11.$RemoteExifEntityTable remoteExifEntity = i11 + .$RemoteExifEntityTable(this); + late final i12.$RemoteAlbumAssetEntityTable remoteAlbumAssetEntity = i12 + .$RemoteAlbumAssetEntityTable(this); + late final i13.$RemoteAlbumUserEntityTable remoteAlbumUserEntity = i13 + .$RemoteAlbumUserEntityTable(this); + late final i14.$MemoryEntityTable memoryEntity = i14.$MemoryEntityTable(this); + late final i15.$MemoryAssetEntityTable memoryAssetEntity = i15 + .$MemoryAssetEntityTable(this); + late final i16.$PersonEntityTable personEntity = i16.$PersonEntityTable(this); + late final i17.$AssetFaceEntityTable assetFaceEntity = i17 + .$AssetFaceEntityTable(this); + late final i18.$StoreEntityTable storeEntity = i18.$StoreEntityTable(this); + i19.MergedAssetDrift get mergedAssetDrift => i20.ReadDatabaseContainer( + this, + ).accessor(i19.MergedAssetDrift.new); @override Iterable> get allTables => allSchemaEntities.whereType>(); @@ -92,6 +97,7 @@ abstract class $Drift extends i0.GeneratedDatabase { i2.uQRemoteAssetsOwnerChecksum, i2.uQRemoteAssetsOwnerLibraryChecksum, i2.idxRemoteAssetChecksum, + authUserEntity, userMetadataEntity, partnerEntity, remoteExifEntity, @@ -102,7 +108,7 @@ abstract class $Drift extends i0.GeneratedDatabase { personEntity, assetFaceEntity, storeEntity, - i10.idxLatLng, + i11.idxLatLng, ]; @override i0.StreamQueryUpdateRules @@ -305,27 +311,29 @@ class $DriftManager { i6.$$LocalAlbumEntityTableTableManager(_db, _db.localAlbumEntity); i7.$$LocalAlbumAssetEntityTableTableManager get localAlbumAssetEntity => i7 .$$LocalAlbumAssetEntityTableTableManager(_db, _db.localAlbumAssetEntity); - i8.$$UserMetadataEntityTableTableManager get userMetadataEntity => - i8.$$UserMetadataEntityTableTableManager(_db, _db.userMetadataEntity); - i9.$$PartnerEntityTableTableManager get partnerEntity => - i9.$$PartnerEntityTableTableManager(_db, _db.partnerEntity); - i10.$$RemoteExifEntityTableTableManager get remoteExifEntity => - i10.$$RemoteExifEntityTableTableManager(_db, _db.remoteExifEntity); - i11.$$RemoteAlbumAssetEntityTableTableManager get remoteAlbumAssetEntity => - i11.$$RemoteAlbumAssetEntityTableTableManager( + i8.$$AuthUserEntityTableTableManager get authUserEntity => + i8.$$AuthUserEntityTableTableManager(_db, _db.authUserEntity); + i9.$$UserMetadataEntityTableTableManager get userMetadataEntity => + i9.$$UserMetadataEntityTableTableManager(_db, _db.userMetadataEntity); + i10.$$PartnerEntityTableTableManager get partnerEntity => + i10.$$PartnerEntityTableTableManager(_db, _db.partnerEntity); + i11.$$RemoteExifEntityTableTableManager get remoteExifEntity => + i11.$$RemoteExifEntityTableTableManager(_db, _db.remoteExifEntity); + i12.$$RemoteAlbumAssetEntityTableTableManager get remoteAlbumAssetEntity => + i12.$$RemoteAlbumAssetEntityTableTableManager( _db, _db.remoteAlbumAssetEntity, ); - i12.$$RemoteAlbumUserEntityTableTableManager get remoteAlbumUserEntity => i12 + i13.$$RemoteAlbumUserEntityTableTableManager get remoteAlbumUserEntity => i13 .$$RemoteAlbumUserEntityTableTableManager(_db, _db.remoteAlbumUserEntity); - i13.$$MemoryEntityTableTableManager get memoryEntity => - i13.$$MemoryEntityTableTableManager(_db, _db.memoryEntity); - i14.$$MemoryAssetEntityTableTableManager get memoryAssetEntity => - i14.$$MemoryAssetEntityTableTableManager(_db, _db.memoryAssetEntity); - i15.$$PersonEntityTableTableManager get personEntity => - i15.$$PersonEntityTableTableManager(_db, _db.personEntity); - i16.$$AssetFaceEntityTableTableManager get assetFaceEntity => - i16.$$AssetFaceEntityTableTableManager(_db, _db.assetFaceEntity); - i17.$$StoreEntityTableTableManager get storeEntity => - i17.$$StoreEntityTableTableManager(_db, _db.storeEntity); + i14.$$MemoryEntityTableTableManager get memoryEntity => + i14.$$MemoryEntityTableTableManager(_db, _db.memoryEntity); + i15.$$MemoryAssetEntityTableTableManager get memoryAssetEntity => + i15.$$MemoryAssetEntityTableTableManager(_db, _db.memoryAssetEntity); + i16.$$PersonEntityTableTableManager get personEntity => + i16.$$PersonEntityTableTableManager(_db, _db.personEntity); + i17.$$AssetFaceEntityTableTableManager get assetFaceEntity => + i17.$$AssetFaceEntityTableTableManager(_db, _db.assetFaceEntity); + i18.$$StoreEntityTableTableManager get storeEntity => + i18.$$StoreEntityTableTableManager(_db, _db.storeEntity); } diff --git a/mobile/lib/infrastructure/repositories/db.repository.steps.dart b/mobile/lib/infrastructure/repositories/db.repository.steps.dart index 2325c2bcb7..c973cd6f13 100644 --- a/mobile/lib/infrastructure/repositories/db.repository.steps.dart +++ b/mobile/lib/infrastructure/repositories/db.repository.steps.dart @@ -3820,6 +3820,1223 @@ i1.GeneratedColumn _column_90(String aliasedName) => 'REFERENCES remote_album_entity (id) ON DELETE SET NULL', ), ); + +final class Schema10 extends i0.VersionedSchema { + Schema10({required super.database}) : super(version: 10); + @override + late final List entities = [ + userEntity, + remoteAssetEntity, + stackEntity, + localAssetEntity, + remoteAlbumEntity, + localAlbumEntity, + localAlbumAssetEntity, + idxLocalAssetChecksum, + idxRemoteAssetOwnerChecksum, + uQRemoteAssetsOwnerChecksum, + uQRemoteAssetsOwnerLibraryChecksum, + idxRemoteAssetChecksum, + authUserEntity, + userMetadataEntity, + partnerEntity, + remoteExifEntity, + remoteAlbumAssetEntity, + remoteAlbumUserEntity, + memoryEntity, + memoryAssetEntity, + personEntity, + assetFaceEntity, + storeEntity, + idxLatLng, + ]; + late final Shape20 userEntity = Shape20( + source: i0.VersionedTable( + entityName: 'user_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_1, + _column_3, + _column_84, + _column_85, + _column_91, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape17 remoteAssetEntity = Shape17( + source: i0.VersionedTable( + entityName: 'remote_asset_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_1, + _column_8, + _column_9, + _column_5, + _column_10, + _column_11, + _column_12, + _column_0, + _column_13, + _column_14, + _column_15, + _column_16, + _column_17, + _column_18, + _column_19, + _column_20, + _column_21, + _column_86, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape3 stackEntity = Shape3( + source: i0.VersionedTable( + entityName: 'stack_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [_column_0, _column_9, _column_5, _column_15, _column_75], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape2 localAssetEntity = Shape2( + source: i0.VersionedTable( + entityName: 'local_asset_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_1, + _column_8, + _column_9, + _column_5, + _column_10, + _column_11, + _column_12, + _column_0, + _column_22, + _column_14, + _column_23, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape9 remoteAlbumEntity = Shape9( + source: i0.VersionedTable( + entityName: 'remote_album_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_1, + _column_56, + _column_9, + _column_5, + _column_15, + _column_57, + _column_58, + _column_59, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape19 localAlbumEntity = Shape19( + source: i0.VersionedTable( + entityName: 'local_album_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_1, + _column_5, + _column_31, + _column_32, + _column_90, + _column_33, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape7 localAlbumAssetEntity = Shape7( + source: i0.VersionedTable( + entityName: 'local_album_asset_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(asset_id, album_id)'], + columns: [_column_34, _column_35], + attachedDatabase: database, + ), + alias: null, + ); + final i1.Index idxLocalAssetChecksum = i1.Index( + 'idx_local_asset_checksum', + 'CREATE INDEX IF NOT EXISTS idx_local_asset_checksum ON local_asset_entity (checksum)', + ); + final i1.Index idxRemoteAssetOwnerChecksum = i1.Index( + 'idx_remote_asset_owner_checksum', + 'CREATE INDEX IF NOT EXISTS idx_remote_asset_owner_checksum ON remote_asset_entity (owner_id, checksum)', + ); + final i1.Index uQRemoteAssetsOwnerChecksum = i1.Index( + 'UQ_remote_assets_owner_checksum', + 'CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_checksum ON remote_asset_entity (owner_id, checksum) WHERE(library_id IS NULL)', + ); + final i1.Index uQRemoteAssetsOwnerLibraryChecksum = i1.Index( + 'UQ_remote_assets_owner_library_checksum', + 'CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_library_checksum ON remote_asset_entity (owner_id, library_id, checksum) WHERE(library_id IS NOT NULL)', + ); + final i1.Index idxRemoteAssetChecksum = i1.Index( + 'idx_remote_asset_checksum', + 'CREATE INDEX IF NOT EXISTS idx_remote_asset_checksum ON remote_asset_entity (checksum)', + ); + late final Shape21 authUserEntity = Shape21( + source: i0.VersionedTable( + entityName: 'auth_user_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_1, + _column_3, + _column_2, + _column_84, + _column_85, + _column_92, + _column_93, + _column_7, + _column_94, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape4 userMetadataEntity = Shape4( + source: i0.VersionedTable( + entityName: 'user_metadata_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(user_id, "key")'], + columns: [_column_25, _column_26, _column_27], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape5 partnerEntity = Shape5( + source: i0.VersionedTable( + entityName: 'partner_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(shared_by_id, shared_with_id)'], + columns: [_column_28, _column_29, _column_30], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape8 remoteExifEntity = Shape8( + source: i0.VersionedTable( + entityName: 'remote_exif_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(asset_id)'], + columns: [ + _column_36, + _column_37, + _column_38, + _column_39, + _column_40, + _column_41, + _column_11, + _column_10, + _column_42, + _column_43, + _column_44, + _column_45, + _column_46, + _column_47, + _column_48, + _column_49, + _column_50, + _column_51, + _column_52, + _column_53, + _column_54, + _column_55, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape7 remoteAlbumAssetEntity = Shape7( + source: i0.VersionedTable( + entityName: 'remote_album_asset_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(asset_id, album_id)'], + columns: [_column_36, _column_60], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape10 remoteAlbumUserEntity = Shape10( + source: i0.VersionedTable( + entityName: 'remote_album_user_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(album_id, user_id)'], + columns: [_column_60, _column_25, _column_61], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape11 memoryEntity = Shape11( + source: i0.VersionedTable( + entityName: 'memory_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_9, + _column_5, + _column_18, + _column_15, + _column_8, + _column_62, + _column_63, + _column_64, + _column_65, + _column_66, + _column_67, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape12 memoryAssetEntity = Shape12( + source: i0.VersionedTable( + entityName: 'memory_asset_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(asset_id, memory_id)'], + columns: [_column_36, _column_68], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape14 personEntity = Shape14( + source: i0.VersionedTable( + entityName: 'person_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_9, + _column_5, + _column_15, + _column_1, + _column_69, + _column_71, + _column_72, + _column_73, + _column_74, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape15 assetFaceEntity = Shape15( + source: i0.VersionedTable( + entityName: 'asset_face_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_36, + _column_76, + _column_77, + _column_78, + _column_79, + _column_80, + _column_81, + _column_82, + _column_83, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape18 storeEntity = Shape18( + source: i0.VersionedTable( + entityName: 'store_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [_column_87, _column_88, _column_89], + attachedDatabase: database, + ), + alias: null, + ); + final i1.Index idxLatLng = i1.Index( + 'idx_lat_lng', + 'CREATE INDEX IF NOT EXISTS idx_lat_lng ON remote_exif_entity (latitude, longitude)', + ); +} + +class Shape20 extends i0.VersionedTable { + Shape20({required super.source, required super.alias}) : super.aliased(); + i1.GeneratedColumn get id => + columnsByName['id']! as i1.GeneratedColumn; + i1.GeneratedColumn get name => + columnsByName['name']! as i1.GeneratedColumn; + i1.GeneratedColumn get email => + columnsByName['email']! as i1.GeneratedColumn; + i1.GeneratedColumn get hasProfileImage => + columnsByName['has_profile_image']! as i1.GeneratedColumn; + i1.GeneratedColumn get profileChangedAt => + columnsByName['profile_changed_at']! as i1.GeneratedColumn; + i1.GeneratedColumn get avatarColor => + columnsByName['avatar_color']! as i1.GeneratedColumn; +} + +i1.GeneratedColumn _column_91(String aliasedName) => + i1.GeneratedColumn( + 'avatar_color', + aliasedName, + false, + type: i1.DriftSqlType.int, + defaultValue: const CustomExpression('0'), + ); + +class Shape21 extends i0.VersionedTable { + Shape21({required super.source, required super.alias}) : super.aliased(); + i1.GeneratedColumn get id => + columnsByName['id']! as i1.GeneratedColumn; + i1.GeneratedColumn get name => + columnsByName['name']! as i1.GeneratedColumn; + i1.GeneratedColumn get email => + columnsByName['email']! as i1.GeneratedColumn; + i1.GeneratedColumn get isAdmin => + columnsByName['is_admin']! as i1.GeneratedColumn; + i1.GeneratedColumn get hasProfileImage => + columnsByName['has_profile_image']! as i1.GeneratedColumn; + i1.GeneratedColumn get profileChangedAt => + columnsByName['profile_changed_at']! as i1.GeneratedColumn; + i1.GeneratedColumn get avatarColor => + columnsByName['avatar_color']! as i1.GeneratedColumn; + i1.GeneratedColumn get quotaSizeInBytes => + columnsByName['quota_size_in_bytes']! as i1.GeneratedColumn; + i1.GeneratedColumn get quotaUsageInBytes => + columnsByName['quota_usage_in_bytes']! as i1.GeneratedColumn; + i1.GeneratedColumn get pinCode => + columnsByName['pin_code']! as i1.GeneratedColumn; +} + +i1.GeneratedColumn _column_92(String aliasedName) => + i1.GeneratedColumn( + 'avatar_color', + aliasedName, + false, + type: i1.DriftSqlType.int, + ); +i1.GeneratedColumn _column_93(String aliasedName) => + i1.GeneratedColumn( + 'quota_size_in_bytes', + aliasedName, + false, + type: i1.DriftSqlType.int, + defaultValue: const CustomExpression('0'), + ); +i1.GeneratedColumn _column_94(String aliasedName) => + i1.GeneratedColumn( + 'pin_code', + aliasedName, + true, + type: i1.DriftSqlType.string, + ); + +final class Schema11 extends i0.VersionedSchema { + Schema11({required super.database}) : super(version: 11); + @override + late final List entities = [ + userEntity, + remoteAssetEntity, + stackEntity, + localAssetEntity, + remoteAlbumEntity, + localAlbumEntity, + localAlbumAssetEntity, + idxLocalAssetChecksum, + idxRemoteAssetOwnerChecksum, + uQRemoteAssetsOwnerChecksum, + uQRemoteAssetsOwnerLibraryChecksum, + idxRemoteAssetChecksum, + authUserEntity, + userMetadataEntity, + partnerEntity, + remoteExifEntity, + remoteAlbumAssetEntity, + remoteAlbumUserEntity, + memoryEntity, + memoryAssetEntity, + personEntity, + assetFaceEntity, + storeEntity, + idxLatLng, + ]; + late final Shape20 userEntity = Shape20( + source: i0.VersionedTable( + entityName: 'user_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_1, + _column_3, + _column_84, + _column_85, + _column_91, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape17 remoteAssetEntity = Shape17( + source: i0.VersionedTable( + entityName: 'remote_asset_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_1, + _column_8, + _column_9, + _column_5, + _column_10, + _column_11, + _column_12, + _column_0, + _column_13, + _column_14, + _column_15, + _column_16, + _column_17, + _column_18, + _column_19, + _column_20, + _column_21, + _column_86, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape3 stackEntity = Shape3( + source: i0.VersionedTable( + entityName: 'stack_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [_column_0, _column_9, _column_5, _column_15, _column_75], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape2 localAssetEntity = Shape2( + source: i0.VersionedTable( + entityName: 'local_asset_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_1, + _column_8, + _column_9, + _column_5, + _column_10, + _column_11, + _column_12, + _column_0, + _column_22, + _column_14, + _column_23, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape9 remoteAlbumEntity = Shape9( + source: i0.VersionedTable( + entityName: 'remote_album_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_1, + _column_56, + _column_9, + _column_5, + _column_15, + _column_57, + _column_58, + _column_59, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape19 localAlbumEntity = Shape19( + source: i0.VersionedTable( + entityName: 'local_album_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_1, + _column_5, + _column_31, + _column_32, + _column_90, + _column_33, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape22 localAlbumAssetEntity = Shape22( + source: i0.VersionedTable( + entityName: 'local_album_asset_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(asset_id, album_id)'], + columns: [_column_34, _column_35, _column_33], + attachedDatabase: database, + ), + alias: null, + ); + final i1.Index idxLocalAssetChecksum = i1.Index( + 'idx_local_asset_checksum', + 'CREATE INDEX IF NOT EXISTS idx_local_asset_checksum ON local_asset_entity (checksum)', + ); + final i1.Index idxRemoteAssetOwnerChecksum = i1.Index( + 'idx_remote_asset_owner_checksum', + 'CREATE INDEX IF NOT EXISTS idx_remote_asset_owner_checksum ON remote_asset_entity (owner_id, checksum)', + ); + final i1.Index uQRemoteAssetsOwnerChecksum = i1.Index( + 'UQ_remote_assets_owner_checksum', + 'CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_checksum ON remote_asset_entity (owner_id, checksum) WHERE(library_id IS NULL)', + ); + final i1.Index uQRemoteAssetsOwnerLibraryChecksum = i1.Index( + 'UQ_remote_assets_owner_library_checksum', + 'CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_library_checksum ON remote_asset_entity (owner_id, library_id, checksum) WHERE(library_id IS NOT NULL)', + ); + final i1.Index idxRemoteAssetChecksum = i1.Index( + 'idx_remote_asset_checksum', + 'CREATE INDEX IF NOT EXISTS idx_remote_asset_checksum ON remote_asset_entity (checksum)', + ); + late final Shape21 authUserEntity = Shape21( + source: i0.VersionedTable( + entityName: 'auth_user_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_1, + _column_3, + _column_2, + _column_84, + _column_85, + _column_92, + _column_93, + _column_7, + _column_94, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape4 userMetadataEntity = Shape4( + source: i0.VersionedTable( + entityName: 'user_metadata_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(user_id, "key")'], + columns: [_column_25, _column_26, _column_27], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape5 partnerEntity = Shape5( + source: i0.VersionedTable( + entityName: 'partner_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(shared_by_id, shared_with_id)'], + columns: [_column_28, _column_29, _column_30], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape8 remoteExifEntity = Shape8( + source: i0.VersionedTable( + entityName: 'remote_exif_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(asset_id)'], + columns: [ + _column_36, + _column_37, + _column_38, + _column_39, + _column_40, + _column_41, + _column_11, + _column_10, + _column_42, + _column_43, + _column_44, + _column_45, + _column_46, + _column_47, + _column_48, + _column_49, + _column_50, + _column_51, + _column_52, + _column_53, + _column_54, + _column_55, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape7 remoteAlbumAssetEntity = Shape7( + source: i0.VersionedTable( + entityName: 'remote_album_asset_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(asset_id, album_id)'], + columns: [_column_36, _column_60], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape10 remoteAlbumUserEntity = Shape10( + source: i0.VersionedTable( + entityName: 'remote_album_user_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(album_id, user_id)'], + columns: [_column_60, _column_25, _column_61], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape11 memoryEntity = Shape11( + source: i0.VersionedTable( + entityName: 'memory_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_9, + _column_5, + _column_18, + _column_15, + _column_8, + _column_62, + _column_63, + _column_64, + _column_65, + _column_66, + _column_67, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape12 memoryAssetEntity = Shape12( + source: i0.VersionedTable( + entityName: 'memory_asset_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(asset_id, memory_id)'], + columns: [_column_36, _column_68], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape14 personEntity = Shape14( + source: i0.VersionedTable( + entityName: 'person_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_9, + _column_5, + _column_15, + _column_1, + _column_69, + _column_71, + _column_72, + _column_73, + _column_74, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape15 assetFaceEntity = Shape15( + source: i0.VersionedTable( + entityName: 'asset_face_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_36, + _column_76, + _column_77, + _column_78, + _column_79, + _column_80, + _column_81, + _column_82, + _column_83, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape18 storeEntity = Shape18( + source: i0.VersionedTable( + entityName: 'store_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [_column_87, _column_88, _column_89], + attachedDatabase: database, + ), + alias: null, + ); + final i1.Index idxLatLng = i1.Index( + 'idx_lat_lng', + 'CREATE INDEX IF NOT EXISTS idx_lat_lng ON remote_exif_entity (latitude, longitude)', + ); +} + +class Shape22 extends i0.VersionedTable { + Shape22({required super.source, required super.alias}) : super.aliased(); + i1.GeneratedColumn get assetId => + columnsByName['asset_id']! as i1.GeneratedColumn; + i1.GeneratedColumn get albumId => + columnsByName['album_id']! as i1.GeneratedColumn; + i1.GeneratedColumn get marker_ => + columnsByName['marker']! as i1.GeneratedColumn; +} + +final class Schema12 extends i0.VersionedSchema { + Schema12({required super.database}) : super(version: 12); + @override + late final List entities = [ + userEntity, + remoteAssetEntity, + stackEntity, + localAssetEntity, + remoteAlbumEntity, + localAlbumEntity, + localAlbumAssetEntity, + idxLocalAssetChecksum, + idxRemoteAssetOwnerChecksum, + uQRemoteAssetsOwnerChecksum, + uQRemoteAssetsOwnerLibraryChecksum, + idxRemoteAssetChecksum, + authUserEntity, + userMetadataEntity, + partnerEntity, + remoteExifEntity, + remoteAlbumAssetEntity, + remoteAlbumUserEntity, + memoryEntity, + memoryAssetEntity, + personEntity, + assetFaceEntity, + storeEntity, + idxLatLng, + ]; + late final Shape20 userEntity = Shape20( + source: i0.VersionedTable( + entityName: 'user_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_1, + _column_3, + _column_84, + _column_85, + _column_91, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape17 remoteAssetEntity = Shape17( + source: i0.VersionedTable( + entityName: 'remote_asset_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_1, + _column_8, + _column_9, + _column_5, + _column_10, + _column_11, + _column_12, + _column_0, + _column_13, + _column_14, + _column_15, + _column_16, + _column_17, + _column_18, + _column_19, + _column_20, + _column_21, + _column_86, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape3 stackEntity = Shape3( + source: i0.VersionedTable( + entityName: 'stack_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [_column_0, _column_9, _column_5, _column_15, _column_75], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape2 localAssetEntity = Shape2( + source: i0.VersionedTable( + entityName: 'local_asset_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_1, + _column_8, + _column_9, + _column_5, + _column_10, + _column_11, + _column_12, + _column_0, + _column_22, + _column_14, + _column_23, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape9 remoteAlbumEntity = Shape9( + source: i0.VersionedTable( + entityName: 'remote_album_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_1, + _column_56, + _column_9, + _column_5, + _column_15, + _column_57, + _column_58, + _column_59, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape19 localAlbumEntity = Shape19( + source: i0.VersionedTable( + entityName: 'local_album_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_1, + _column_5, + _column_31, + _column_32, + _column_90, + _column_33, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape22 localAlbumAssetEntity = Shape22( + source: i0.VersionedTable( + entityName: 'local_album_asset_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(asset_id, album_id)'], + columns: [_column_34, _column_35, _column_33], + attachedDatabase: database, + ), + alias: null, + ); + final i1.Index idxLocalAssetChecksum = i1.Index( + 'idx_local_asset_checksum', + 'CREATE INDEX IF NOT EXISTS idx_local_asset_checksum ON local_asset_entity (checksum)', + ); + final i1.Index idxRemoteAssetOwnerChecksum = i1.Index( + 'idx_remote_asset_owner_checksum', + 'CREATE INDEX IF NOT EXISTS idx_remote_asset_owner_checksum ON remote_asset_entity (owner_id, checksum)', + ); + final i1.Index uQRemoteAssetsOwnerChecksum = i1.Index( + 'UQ_remote_assets_owner_checksum', + 'CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_checksum ON remote_asset_entity (owner_id, checksum) WHERE(library_id IS NULL)', + ); + final i1.Index uQRemoteAssetsOwnerLibraryChecksum = i1.Index( + 'UQ_remote_assets_owner_library_checksum', + 'CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_library_checksum ON remote_asset_entity (owner_id, library_id, checksum) WHERE(library_id IS NOT NULL)', + ); + final i1.Index idxRemoteAssetChecksum = i1.Index( + 'idx_remote_asset_checksum', + 'CREATE INDEX IF NOT EXISTS idx_remote_asset_checksum ON remote_asset_entity (checksum)', + ); + late final Shape21 authUserEntity = Shape21( + source: i0.VersionedTable( + entityName: 'auth_user_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_1, + _column_3, + _column_2, + _column_84, + _column_85, + _column_92, + _column_93, + _column_7, + _column_94, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape4 userMetadataEntity = Shape4( + source: i0.VersionedTable( + entityName: 'user_metadata_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(user_id, "key")'], + columns: [_column_25, _column_26, _column_27], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape5 partnerEntity = Shape5( + source: i0.VersionedTable( + entityName: 'partner_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(shared_by_id, shared_with_id)'], + columns: [_column_28, _column_29, _column_30], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape8 remoteExifEntity = Shape8( + source: i0.VersionedTable( + entityName: 'remote_exif_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(asset_id)'], + columns: [ + _column_36, + _column_37, + _column_38, + _column_39, + _column_40, + _column_41, + _column_11, + _column_10, + _column_42, + _column_43, + _column_44, + _column_45, + _column_46, + _column_47, + _column_48, + _column_49, + _column_50, + _column_51, + _column_52, + _column_53, + _column_54, + _column_55, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape7 remoteAlbumAssetEntity = Shape7( + source: i0.VersionedTable( + entityName: 'remote_album_asset_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(asset_id, album_id)'], + columns: [_column_36, _column_60], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape10 remoteAlbumUserEntity = Shape10( + source: i0.VersionedTable( + entityName: 'remote_album_user_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(album_id, user_id)'], + columns: [_column_60, _column_25, _column_61], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape11 memoryEntity = Shape11( + source: i0.VersionedTable( + entityName: 'memory_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_9, + _column_5, + _column_18, + _column_15, + _column_8, + _column_62, + _column_63, + _column_64, + _column_65, + _column_66, + _column_67, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape12 memoryAssetEntity = Shape12( + source: i0.VersionedTable( + entityName: 'memory_asset_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(asset_id, memory_id)'], + columns: [_column_36, _column_68], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape14 personEntity = Shape14( + source: i0.VersionedTable( + entityName: 'person_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_9, + _column_5, + _column_15, + _column_1, + _column_69, + _column_71, + _column_72, + _column_73, + _column_74, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape15 assetFaceEntity = Shape15( + source: i0.VersionedTable( + entityName: 'asset_face_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_36, + _column_76, + _column_77, + _column_78, + _column_79, + _column_80, + _column_81, + _column_82, + _column_83, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape18 storeEntity = Shape18( + source: i0.VersionedTable( + entityName: 'store_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [_column_87, _column_88, _column_89], + attachedDatabase: database, + ), + alias: null, + ); + final i1.Index idxLatLng = i1.Index( + 'idx_lat_lng', + 'CREATE INDEX IF NOT EXISTS idx_lat_lng ON remote_exif_entity (latitude, longitude)', + ); +} + i0.MigrationStepWithVersion migrationSteps({ required Future Function(i1.Migrator m, Schema2 schema) from1To2, required Future Function(i1.Migrator m, Schema3 schema) from2To3, @@ -3829,6 +5046,9 @@ i0.MigrationStepWithVersion migrationSteps({ required Future Function(i1.Migrator m, Schema7 schema) from6To7, required Future Function(i1.Migrator m, Schema8 schema) from7To8, required Future Function(i1.Migrator m, Schema9 schema) from8To9, + required Future Function(i1.Migrator m, Schema10 schema) from9To10, + required Future Function(i1.Migrator m, Schema11 schema) from10To11, + required Future Function(i1.Migrator m, Schema12 schema) from11To12, }) { return (currentVersion, database) async { switch (currentVersion) { @@ -3872,6 +5092,21 @@ i0.MigrationStepWithVersion migrationSteps({ final migrator = i1.Migrator(database, schema); await from8To9(migrator, schema); return 9; + case 9: + final schema = Schema10(database: database); + final migrator = i1.Migrator(database, schema); + await from9To10(migrator, schema); + return 10; + case 10: + final schema = Schema11(database: database); + final migrator = i1.Migrator(database, schema); + await from10To11(migrator, schema); + return 11; + case 11: + final schema = Schema12(database: database); + final migrator = i1.Migrator(database, schema); + await from11To12(migrator, schema); + return 12; default: throw ArgumentError.value('Unknown migration from $currentVersion'); } @@ -3887,6 +5122,9 @@ i1.OnUpgrade stepByStep({ required Future Function(i1.Migrator m, Schema7 schema) from6To7, required Future Function(i1.Migrator m, Schema8 schema) from7To8, required Future Function(i1.Migrator m, Schema9 schema) from8To9, + required Future Function(i1.Migrator m, Schema10 schema) from9To10, + required Future Function(i1.Migrator m, Schema11 schema) from10To11, + required Future Function(i1.Migrator m, Schema12 schema) from11To12, }) => i0.VersionedSchema.stepByStepHelper( step: migrationSteps( from1To2: from1To2, @@ -3897,5 +5135,8 @@ i1.OnUpgrade stepByStep({ from6To7: from6To7, from7To8: from7To8, from8To9: from8To9, + from9To10: from9To10, + from10To11: from10To11, + from11To12: from11To12, ), ); diff --git a/mobile/lib/infrastructure/repositories/local_album.repository.dart b/mobile/lib/infrastructure/repositories/local_album.repository.dart index 923d6e0a68..e4bff24879 100644 --- a/mobile/lib/infrastructure/repositories/local_album.repository.dart +++ b/mobile/lib/infrastructure/repositories/local_album.repository.dart @@ -1,22 +1,20 @@ import 'package:drift/drift.dart'; import 'package:immich_mobile/domain/models/album/local_album.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; +import 'package:immich_mobile/extensions/platform_extensions.dart'; import 'package:immich_mobile/infrastructure/entities/local_album.entity.dart'; import 'package:immich_mobile/infrastructure/entities/local_album.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart'; import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; -import 'package:platform/platform.dart'; enum SortLocalAlbumsBy { id, backupSelection, isIosSharedAlbum, name, assetCount, newestAsset } class DriftLocalAlbumRepository extends DriftDatabaseRepository { final Drift _db; - final Platform _platform; - const DriftLocalAlbumRepository(this._db, {Platform? platform}) - : _platform = platform ?? const LocalPlatform(), - super(_db); + + const DriftLocalAlbumRepository(this._db) : super(_db); Future> getAll({Set sortBy = const {}}) { final assetCount = _db.localAlbumAssetEntity.assetId.count(); @@ -61,7 +59,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository { // Remove all assets that are only in this particular album // We cannot remove all assets in the album because they might be in other albums in iOS // That is not the case on Android since asset <-> album has one:one mapping - final assetsToDelete = _platform.isIOS ? await _getUniqueAssetsInAlbum(albumId) : await getAssetIds(albumId); + final assetsToDelete = CurrentPlatform.isIOS ? await _getUniqueAssetsInAlbum(albumId) : await getAssetIds(albumId); await _deleteAssets(assetsToDelete); await _db.managers.localAlbumEntity @@ -74,17 +72,33 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository { return Future.value(); } - final deleteSmt = _db.localAssetEntity.delete(); - deleteSmt.where((localAsset) { - final subQuery = _db.localAlbumAssetEntity.selectOnly() - ..addColumns([_db.localAlbumAssetEntity.assetId]) - ..join([innerJoin(_db.localAlbumEntity, _db.localAlbumAssetEntity.albumId.equalsExp(_db.localAlbumEntity.id))]); - subQuery.where( - _db.localAlbumEntity.id.equals(albumId) & _db.localAlbumAssetEntity.assetId.isNotIn(assetIdsToKeep), - ); - return localAsset.id.isInQuery(subQuery); + return _db.transaction(() async { + await _db.managers.localAlbumAssetEntity + .filter((row) => row.albumId.id.equals(albumId)) + .update((album) => album(marker_: const Value(true))); + + await _db.batch((batch) { + for (final assetId in assetIdsToKeep) { + batch.update( + _db.localAlbumAssetEntity, + const LocalAlbumAssetEntityCompanion(marker_: Value(null)), + where: (row) => row.assetId.equals(assetId) & row.albumId.equals(albumId), + ); + } + }); + + final query = _db.localAssetEntity.delete() + ..where( + (row) => row.id.isInQuery( + _db.localAlbumAssetEntity.selectOnly() + ..addColumns([_db.localAlbumAssetEntity.assetId]) + ..where( + _db.localAlbumAssetEntity.albumId.equals(albumId) & _db.localAlbumAssetEntity.marker_.isNotNull(), + ), + ), + ); + await query.go(); }); - await deleteSmt.go(); } Future upsert( @@ -144,7 +158,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository { } }); - if (_platform.isAndroid) { + if (CurrentPlatform.isAndroid) { // On Android, an asset can only be in one album // So, get the albums that are marked for deletion // and delete all the assets that are in those albums @@ -200,10 +214,9 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository { // List await _db.batch((batch) async { assetAlbums.cast>().forEach((assetId, albumIds) { - batch.deleteWhere( - _db.localAlbumAssetEntity, - (f) => f.albumId.isNotIn(albumIds.cast().nonNulls) & f.assetId.equals(assetId), - ); + for (final albumId in albumIds.cast().nonNulls) { + batch.deleteWhere(_db.localAlbumAssetEntity, (f) => f.albumId.equals(albumId) & f.assetId.equals(assetId)); + } }); }); await _db.batch((batch) async { @@ -265,7 +278,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository { return Future.value(); } - if (_platform.isAndroid) { + if (CurrentPlatform.isAndroid) { return _deleteAssets(assetIds); } @@ -290,12 +303,14 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository { return transaction(() async { if (assetsToUnLink.isNotEmpty) { - await _db.batch( - (batch) => batch.deleteWhere( - _db.localAlbumAssetEntity, - (f) => f.assetId.isIn(assetsToUnLink) & f.albumId.equals(albumId), - ), - ); + await _db.batch((batch) { + for (final assetId in assetsToUnLink) { + batch.deleteWhere( + _db.localAlbumAssetEntity, + (row) => row.assetId.equals(assetId) & row.albumId.equals(albumId), + ); + } + }); } await _deleteAssets(assetsToDelete); @@ -322,7 +337,9 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository { } return _db.batch((batch) { - batch.deleteWhere(_db.localAssetEntity, (f) => f.id.isIn(ids)); + for (final id in ids) { + batch.deleteWhere(_db.localAssetEntity, (row) => row.id.equals(id)); + } }); } diff --git a/mobile/lib/infrastructure/repositories/local_asset.repository.dart b/mobile/lib/infrastructure/repositories/local_asset.repository.dart index 5865447064..2b76472c9e 100644 --- a/mobile/lib/infrastructure/repositories/local_asset.repository.dart +++ b/mobile/lib/infrastructure/repositories/local_asset.repository.dart @@ -1,6 +1,7 @@ -import 'package:collection/collection.dart'; import 'package:drift/drift.dart'; +import 'package:immich_mobile/domain/models/album/local_album.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; +import 'package:immich_mobile/infrastructure/entities/local_album.entity.dart'; import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart'; import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; @@ -26,19 +27,25 @@ class DriftLocalAssetRepository extends DriftDatabaseRepository { Future get(String id) => _assetSelectable(id).getSingleOrNull(); + Future> getByChecksum(String checksum) { + final query = _db.localAssetEntity.select()..where((lae) => lae.checksum.equals(checksum)); + + return query.map((row) => row.toDto()).get(); + } + Stream watch(String id) => _assetSelectable(id).watchSingleOrNull(); - Future updateHashes(Iterable hashes) { + Future updateHashes(Map hashes) { if (hashes.isEmpty) { return Future.value(); } return _db.batch((batch) async { - for (final asset in hashes) { + for (final entry in hashes.entries) { batch.update( _db.localAssetEntity, - LocalAssetEntityCompanion(checksum: Value(asset.checksum)), - where: (e) => e.id.equals(asset.id), + LocalAssetEntityCompanion(checksum: Value(entry.value)), + where: (e) => e.id.equals(entry.key), ); } }); @@ -50,8 +57,8 @@ class DriftLocalAssetRepository extends DriftDatabaseRepository { } return _db.batch((batch) { - for (final slice in ids.slices(32000)) { - batch.deleteWhere(_db.localAssetEntity, (e) => e.id.isIn(slice)); + for (final id in ids) { + batch.deleteWhere(_db.localAssetEntity, (e) => e.id.equals(id)); } }); } @@ -69,4 +76,23 @@ class DriftLocalAssetRepository extends DriftDatabaseRepository { Future getHashedCount() { return _db.managers.localAssetEntity.filter((e) => e.checksum.isNull().not()).count(); } + + Future> getSourceAlbums(String localAssetId, {BackupSelection? backupSelection}) { + final query = _db.localAlbumEntity.select() + ..where( + (lae) => existsQuery( + _db.localAlbumAssetEntity.selectOnly() + ..addColumns([_db.localAlbumAssetEntity.albumId]) + ..where( + _db.localAlbumAssetEntity.albumId.equalsExp(lae.id) & + _db.localAlbumAssetEntity.assetId.equals(localAssetId), + ), + ), + ) + ..orderBy([(lae) => OrderingTerm.asc(lae.name)]); + if (backupSelection != null) { + query.where((lae) => lae.backupSelection.equalsValue(backupSelection)); + } + return query.map((localAlbum) => localAlbum.toDto()).get(); + } } diff --git a/mobile/lib/infrastructure/repositories/remote_album.repository.dart b/mobile/lib/infrastructure/repositories/remote_album.repository.dart index 41f167b3e8..0526cfb7aa 100644 --- a/mobile/lib/infrastructure/repositories/remote_album.repository.dart +++ b/mobile/lib/infrastructure/repositories/remote_album.repository.dart @@ -62,7 +62,7 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository { .toDto( assetCount: row.read(assetCount) ?? 0, ownerName: row.read(_db.userEntity.name)!, - isShared: row.read(_db.remoteAlbumUserEntity.userId.count(distinct: true))! > 2, + isShared: row.read(_db.remoteAlbumUserEntity.userId.count(distinct: true))! > 0, ), ) .get(); @@ -107,7 +107,7 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository { .toDto( assetCount: row.read(assetCount) ?? 0, ownerName: row.read(_db.userEntity.name)!, - isShared: row.read(_db.remoteAlbumUserEntity.userId.count(distinct: true))! > 2, + isShared: row.read(_db.remoteAlbumUserEntity.userId.count(distinct: true))! > 0, ), ) .getSingleOrNull(); @@ -166,8 +166,15 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository { ); } - Future removeAssets(String albumId, List assetIds) { - return _db.remoteAlbumAssetEntity.deleteWhere((tbl) => tbl.albumId.equals(albumId) & tbl.assetId.isIn(assetIds)); + Future removeAssets(String albumId, List assetIds) { + return _db.batch((batch) { + for (final assetId in assetIds) { + batch.deleteWhere( + _db.remoteAlbumAssetEntity, + (row) => row.albumId.equals(albumId) & row.assetId.equals(assetId), + ); + } + }); } FutureOr<(DateTime, DateTime)> getDateRange(String albumId) { @@ -202,19 +209,27 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository { id: user.id, email: user.email, name: user.name, - isAdmin: user.isAdmin, - updatedAt: user.updatedAt, memoryEnabled: true, inTimeline: false, isPartnerSharedBy: false, isPartnerSharedWith: false, profileChangedAt: user.profileChangedAt, hasProfileImage: user.hasProfileImage, + avatarColor: user.avatarColor, ), ) .get(); } + Future getUserRole(String albumId, String userId) async { + final query = _db.remoteAlbumUserEntity.select() + ..where((row) => row.albumId.equals(albumId) & row.userId.equals(userId)) + ..limit(1); + + final result = await query.getSingleOrNull(); + return result?.role; + } + Future> getAssets(String albumId) { final query = _db.remoteAlbumAssetEntity.select().join([ innerJoin(_db.remoteAssetEntity, _db.remoteAssetEntity.id.equalsExp(_db.remoteAlbumAssetEntity.assetId)), @@ -299,8 +314,9 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository { .readTable(_db.remoteAlbumEntity) .toDto( ownerName: row.read(_db.userEntity.name)!, - isShared: row.read(_db.remoteAlbumUserEntity.userId.count(distinct: true))! > 2, + isShared: row.read(_db.remoteAlbumUserEntity.userId.count(distinct: true))! > 0, ); + return album; }).watchSingleOrNull(); } diff --git a/mobile/lib/infrastructure/repositories/remote_asset.repository.dart b/mobile/lib/infrastructure/repositories/remote_asset.repository.dart index 3ed7dddfe8..be55c21afc 100644 --- a/mobile/lib/infrastructure/repositories/remote_asset.repository.dart +++ b/mobile/lib/infrastructure/repositories/remote_asset.repository.dart @@ -55,13 +55,20 @@ class RemoteAssetRepository extends DriftDatabaseRepository { return _assetSelectable(id).getSingleOrNull(); } + Future getByChecksum(String checksum) { + final query = _db.remoteAssetEntity.select()..where((row) => row.checksum.equals(checksum)); + + return query.map((row) => row.toDto()).getSingleOrNull(); + } + Future> getStackChildren(RemoteAsset asset) { - if (asset.stackId == null) { - return Future.value([]); + final stackId = asset.stackId; + if (stackId == null) { + return Future.value(const []); } final query = _db.remoteAssetEntity.select() - ..where((row) => row.stackId.equals(asset.stackId!) & row.id.equals(asset.id).not()) + ..where((row) => row.stackId.equals(stackId) & row.id.equals(asset.id).not()) ..orderBy([(row) => OrderingTerm.desc(row.createdAt)]); return query.map((row) => row.toDto()).get(); @@ -74,9 +81,11 @@ class RemoteAssetRepository extends DriftDatabaseRepository { .getSingleOrNull(); } - Future> getPlaces() { + Future> getPlaces(String userId) { final asset = Subquery( - _db.remoteAssetEntity.select()..orderBy([(row) => OrderingTerm.desc(row.createdAt)]), + _db.remoteAssetEntity.select() + ..where((row) => row.ownerId.equals(userId)) + ..orderBy([(row) => OrderingTerm.desc(row.createdAt)]), "asset", ); @@ -153,7 +162,11 @@ class RemoteAssetRepository extends DriftDatabaseRepository { } Future delete(List ids) { - return _db.remoteAssetEntity.deleteWhere((row) => row.id.isIn(ids)); + return _db.batch((batch) { + for (final id in ids) { + batch.deleteWhere(_db.remoteAssetEntity, (row) => row.id.equals(id)); + } + }); } Future updateLocation(List ids, LatLng location) { @@ -192,7 +205,11 @@ class RemoteAssetRepository extends DriftDatabaseRepository { .map((row) => row.id) .get(); - await _db.stackEntity.deleteWhere((row) => row.id.isIn(stackIds)); + await _db.batch((batch) { + for (final stackId in stackIds) { + batch.deleteWhere(_db.stackEntity, (row) => row.id.equals(stackId)); + } + }); await _db.batch((batch) { final companion = StackEntityCompanion(ownerId: Value(userId), primaryAssetId: Value(stack.primaryAssetId)); @@ -212,15 +229,21 @@ class RemoteAssetRepository extends DriftDatabaseRepository { Future unStack(List stackIds) { return _db.transaction(() async { - await _db.stackEntity.deleteWhere((row) => row.id.isIn(stackIds)); + await _db.batch((batch) { + for (final stackId in stackIds) { + batch.deleteWhere(_db.stackEntity, (row) => row.id.equals(stackId)); + } + }); // TODO: delete this after adding foreign key on stackId await _db.batch((batch) { - batch.update( - _db.remoteAssetEntity, - const RemoteAssetEntityCompanion(stackId: Value(null)), - where: (e) => e.stackId.isIn(stackIds), - ); + for (final stackId in stackIds) { + batch.update( + _db.remoteAssetEntity, + const RemoteAssetEntityCompanion(stackId: Value(null)), + where: (e) => e.stackId.equals(stackId), + ); + } }); }); } diff --git a/mobile/lib/infrastructure/repositories/search_api.repository.dart b/mobile/lib/infrastructure/repositories/search_api.repository.dart index 129746120b..dd72333398 100644 --- a/mobile/lib/infrastructure/repositories/search_api.repository.dart +++ b/mobile/lib/infrastructure/repositories/search_api.repository.dart @@ -33,7 +33,7 @@ class SearchApiRepository extends ApiRepository { personIds: filter.people.map((e) => e.id).toList(), type: type, page: page, - size: 1000, + size: 100, ), ); } diff --git a/mobile/lib/infrastructure/repositories/store.repository.dart b/mobile/lib/infrastructure/repositories/store.repository.dart index 5aea631171..d4e34a02f5 100644 --- a/mobile/lib/infrastructure/repositories/store.repository.dart +++ b/mobile/lib/infrastructure/repositories/store.repository.dart @@ -173,7 +173,7 @@ class DriftStoreRepository extends DriftDatabaseRepository implements IStoreRepo const (bool) => entity.intValue == 1, const (DateTime) => entity.intValue == null ? null : DateTime.fromMillisecondsSinceEpoch(entity.intValue!), const (UserDto) => - entity.stringValue == null ? null : await DriftUserRepository(_db).get(entity.stringValue!), + entity.stringValue == null ? null : await DriftAuthUserRepository(_db).get(entity.stringValue!), _ => null, } as T?; @@ -184,7 +184,7 @@ class DriftStoreRepository extends DriftDatabaseRepository implements IStoreRepo const (String) => (null, value as String), const (bool) => ((value as bool) ? 1 : 0, null), const (DateTime) => ((value as DateTime).millisecondsSinceEpoch, null), - const (UserDto) => (null, (await DriftUserRepository(_db).upsert(value as UserDto)).id), + const (UserDto) => (null, (await DriftAuthUserRepository(_db).upsert(value as UserDto)).id), _ => throw UnsupportedError("Unsupported primitive type: ${key.type} for key: ${key.name}"), }; return StoreEntityCompanion(id: Value(key.id), intValue: Value(intValue), stringValue: Value(strValue)); diff --git a/mobile/lib/infrastructure/repositories/sync_api.repository.dart b/mobile/lib/infrastructure/repositories/sync_api.repository.dart index 7af1141659..8bf2e80579 100644 --- a/mobile/lib/infrastructure/repositories/sync_api.repository.dart +++ b/mobile/lib/infrastructure/repositories/sync_api.repository.dart @@ -3,7 +3,9 @@ import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:immich_mobile/constants/constants.dart'; +import 'package:immich_mobile/domain/models/store.model.dart'; import 'package:immich_mobile/domain/models/sync_event.model.dart'; +import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/services/api.service.dart'; import 'package:logging/logging.dart'; import 'package:openapi/api.dart'; @@ -33,11 +35,13 @@ class SyncApiRepository { await _api.applyToParams([], headerParams); headers.addAll(headerParams); + final shouldReset = Store.get(StoreKey.shouldResetSync, false); final request = http.Request('POST', Uri.parse(endpoint)); request.headers.addAll(headers); request.body = jsonEncode( SyncStreamDto( types: [ + SyncRequestType.authUsersV1, SyncRequestType.usersV1, SyncRequestType.assetsV1, SyncRequestType.assetExifsV1, @@ -57,6 +61,7 @@ class SyncApiRepository { SyncRequestType.peopleV1, SyncRequestType.assetFacesV1, ], + reset: shouldReset, ).toJson(), ); @@ -80,6 +85,9 @@ class SyncApiRepository { throw ApiException(response.statusCode, 'Failed to get sync stream: $errorBody'); } + // Reset after successful stream start + await Store.put(StoreKey.shouldResetSync, false); + await for (final chunk in response.stream.transform(utf8.decoder)) { if (shouldAbort) { break; @@ -102,7 +110,6 @@ class SyncApiRepository { await onData(_parseLines(lines), abort, reset); } } catch (error, stack) { - _logger.severe("Error processing stream", error, stack); return Future.error(error, stack); } finally { client.close(); @@ -133,6 +140,7 @@ class SyncApiRepository { } const _kResponseMap = { + SyncEntityType.authUserV1: SyncAuthUserV1.fromJson, SyncEntityType.userV1: SyncUserV1.fromJson, SyncEntityType.userDeleteV1: SyncUserDeleteV1.fromJson, SyncEntityType.partnerV1: SyncPartnerV1.fromJson, diff --git a/mobile/lib/infrastructure/repositories/sync_stream.repository.dart b/mobile/lib/infrastructure/repositories/sync_stream.repository.dart index 0fed400083..3f74fe25d1 100644 --- a/mobile/lib/infrastructure/repositories/sync_stream.repository.dart +++ b/mobile/lib/infrastructure/repositories/sync_stream.repository.dart @@ -1,11 +1,14 @@ import 'dart:convert'; +import 'package:collection/collection.dart'; import 'package:drift/drift.dart'; import 'package:immich_mobile/domain/models/album/album.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/memory.model.dart'; +import 'package:immich_mobile/domain/models/user.model.dart'; import 'package:immich_mobile/domain/models/user_metadata.model.dart'; import 'package:immich_mobile/infrastructure/entities/asset_face.entity.drift.dart'; +import 'package:immich_mobile/infrastructure/entities/auth_user.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/exif.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/memory.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.drift.dart'; @@ -48,6 +51,7 @@ class SyncStreamRepository extends DriftDatabaseRepository { await _db.remoteAssetEntity.deleteAll(); await _db.remoteExifEntity.deleteAll(); await _db.stackEntity.deleteAll(); + await _db.authUserEntity.deleteAll(); await _db.userEntity.deleteAll(); await _db.userMetadataEntity.deleteAll(); }); @@ -59,9 +63,42 @@ class SyncStreamRepository extends DriftDatabaseRepository { } } + Future updateAuthUsersV1(Iterable data) async { + try { + await _db.batch((batch) { + for (final user in data) { + final companion = AuthUserEntityCompanion( + name: Value(user.name), + email: Value(user.email), + hasProfileImage: Value(user.hasProfileImage), + profileChangedAt: Value(user.profileChangedAt), + avatarColor: Value(user.avatarColor?.toAvatarColor() ?? AvatarColor.primary), + isAdmin: Value(user.isAdmin), + pinCode: Value(user.pinCode), + quotaSizeInBytes: Value(user.quotaSizeInBytes ?? 0), + quotaUsageInBytes: Value(user.quotaUsageInBytes), + ); + + batch.insert( + _db.authUserEntity, + companion.copyWith(id: Value(user.id)), + onConflict: DoUpdate((_) => companion), + ); + } + }); + } catch (error, stack) { + _logger.severe('Error: SyncAuthUserV1', error, stack); + rethrow; + } + } + Future deleteUsersV1(Iterable data) async { try { - await _db.userEntity.deleteWhere((row) => row.id.isIn(data.map((e) => e.userId))); + await _db.batch((batch) { + for (final user in data) { + batch.deleteWhere(_db.userEntity, (row) => row.id.equals(user.userId)); + } + }); } catch (error, stack) { _logger.severe('Error: SyncUserDeleteV1', error, stack); rethrow; @@ -77,6 +114,7 @@ class SyncStreamRepository extends DriftDatabaseRepository { email: Value(user.email), hasProfileImage: Value(user.hasProfileImage), profileChangedAt: Value(user.profileChangedAt), + avatarColor: Value(user.avatarColor?.toAvatarColor() ?? AvatarColor.primary), ); batch.insert(_db.userEntity, companion.copyWith(id: Value(user.id)), onConflict: DoUpdate((_) => companion)); @@ -125,7 +163,11 @@ class SyncStreamRepository extends DriftDatabaseRepository { Future deleteAssetsV1(Iterable data, {String debugLabel = 'user'}) async { try { - await _db.remoteAssetEntity.deleteWhere((row) => row.id.isIn(data.map((e) => e.assetId))); + await _db.batch((batch) { + for (final asset in data) { + batch.deleteWhere(_db.remoteAssetEntity, (row) => row.id.equals(asset.assetId)); + } + }); } catch (error, stack) { _logger.severe('Error: deleteAssetsV1 - $debugLabel', error, stack); rethrow; @@ -210,7 +252,11 @@ class SyncStreamRepository extends DriftDatabaseRepository { Future deleteAlbumsV1(Iterable data) async { try { - await _db.remoteAlbumEntity.deleteWhere((row) => row.id.isIn(data.map((e) => e.albumId))); + await _db.batch((batch) { + for (final album in data) { + batch.deleteWhere(_db.remoteAlbumEntity, (row) => row.id.equals(album.albumId)); + } + }); } catch (error, stack) { _logger.severe('Error: deleteAlbumsV1', error, stack); rethrow; @@ -346,7 +392,11 @@ class SyncStreamRepository extends DriftDatabaseRepository { Future deleteMemoriesV1(Iterable data) async { try { - await _db.memoryEntity.deleteWhere((row) => row.id.isIn(data.map((e) => e.memoryId))); + await _db.batch((batch) { + for (final memory in data) { + batch.deleteWhere(_db.memoryEntity, (row) => row.id.equals(memory.memoryId)); + } + }); } catch (error, stack) { _logger.severe('Error: deleteMemoriesV1', error, stack); rethrow; @@ -410,7 +460,11 @@ class SyncStreamRepository extends DriftDatabaseRepository { Future deleteStacksV1(Iterable data, {String debugLabel = 'user'}) async { try { - await _db.stackEntity.deleteWhere((row) => row.id.isIn(data.map((e) => e.stackId))); + await _db.batch((batch) { + for (final stack in data) { + batch.deleteWhere(_db.stackEntity, (row) => row.id.equals(stack.stackId)); + } + }); } catch (error, stack) { _logger.severe('Error: deleteStacksV1 - $debugLabel', error, stack); rethrow; @@ -603,3 +657,7 @@ extension on String { } } } + +extension on UserAvatarColor { + AvatarColor? toAvatarColor() => AvatarColor.values.firstWhereOrNull((c) => c.name == value); +} diff --git a/mobile/lib/infrastructure/repositories/timeline.repository.dart b/mobile/lib/infrastructure/repositories/timeline.repository.dart index 61428ede92..1fc0ee43e5 100644 --- a/mobile/lib/infrastructure/repositories/timeline.repository.dart +++ b/mobile/lib/infrastructure/repositories/timeline.repository.dart @@ -35,6 +35,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository { TimelineQuery main(List userIds, GroupAssetsBy groupBy) => ( bucketSource: () => _watchMainBucket(userIds, groupBy: groupBy), assetSource: (offset, count) => _getMainBucketAssets(userIds, offset: offset, count: count), + origin: TimelineOrigin.main, ); Stream> _watchMainBucket(List userIds, {GroupAssetsBy groupBy = GroupAssetsBy.day}) { @@ -42,14 +43,10 @@ class DriftTimelineRepository extends DriftDatabaseRepository { throw UnsupportedError("GroupAssetsBy.none is not supported for watchMainBucket"); } - return _db.mergedAssetDrift - .mergedBucket(userIds: userIds, groupBy: groupBy.index) - .map((row) { - final date = row.bucketDate.dateFmt(groupBy); - return TimeBucket(date: date, assetCount: row.assetCount); - }) - .watch() - .throttle(const Duration(seconds: 3), trailing: true); + return _db.mergedAssetDrift.mergedBucket(userIds: userIds, groupBy: groupBy.index).map((row) { + final date = row.bucketDate.truncateDate(groupBy); + return TimeBucket(date: date, assetCount: row.assetCount); + }).watch(); } Future> _getMainBucketAssets(List userIds, {required int offset, required int count}) { @@ -95,6 +92,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository { TimelineQuery localAlbum(String albumId, GroupAssetsBy groupBy) => ( bucketSource: () => _watchLocalAlbumBucket(albumId, groupBy: groupBy), assetSource: (offset, count) => _getLocalAlbumBucketAssets(albumId, offset: offset, count: count), + origin: TimelineOrigin.localAlbum, ); Stream> _watchLocalAlbumBucket(String albumId, {GroupAssetsBy groupBy = GroupAssetsBy.day}) { @@ -127,7 +125,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository { ..orderBy([OrderingTerm.desc(dateExp)]); return query.map((row) { - final timeline = row.read(dateExp)!.dateFmt(groupBy); + final timeline = row.read(dateExp)!.truncateDate(groupBy); final assetCount = row.read(assetCountExp)!; return TimeBucket(date: timeline, assetCount: assetCount); }).watch(); @@ -152,15 +150,15 @@ class DriftTimelineRepository extends DriftDatabaseRepository { ..orderBy([OrderingTerm.desc(_db.localAssetEntity.createdAt)]) ..limit(count, offset: offset); - return query.map((row) { - final asset = row.readTable(_db.localAssetEntity).toDto(); - return asset.copyWith(remoteId: row.read(_db.remoteAssetEntity.id)); - }).get(); + return query + .map((row) => row.readTable(_db.localAssetEntity).toDto(remoteId: row.read(_db.remoteAssetEntity.id))) + .get(); } TimelineQuery remoteAlbum(String albumId, GroupAssetsBy groupBy) => ( bucketSource: () => _watchRemoteAlbumBucket(albumId, groupBy: groupBy), assetSource: (offset, count) => _getRemoteAlbumBucketAssets(albumId, offset: offset, count: count), + origin: TimelineOrigin.remoteAlbum, ); Stream> _watchRemoteAlbumBucket(String albumId, {GroupAssetsBy groupBy = GroupAssetsBy.day}) { @@ -169,17 +167,15 @@ class DriftTimelineRepository extends DriftDatabaseRepository { .count(where: (row) => row.albumId.equals(albumId)) .map(_generateBuckets) .watch() - .map((results) => results.isNotEmpty ? results.first : []) - .handleError((error) { - return []; - }); + .map((results) => results.isNotEmpty ? results.first : const []) + .handleError((error) => const []); } return (_db.remoteAlbumEntity.select()..where((row) => row.id.equals(albumId))) .watch() .switchMap((albums) { if (albums.isEmpty) { - return Stream.value([]); + return Stream.value(const []); } final album = albums.first; @@ -206,15 +202,13 @@ class DriftTimelineRepository extends DriftDatabaseRepository { } return query.map((row) { - final timeline = row.read(dateExp)!.dateFmt(groupBy); + final timeline = row.read(dateExp)!.truncateDate(groupBy); final assetCount = row.read(assetCountExp)!; return TimeBucket(date: timeline, assetCount: assetCount); }).watch(); }) - .handleError((error) { - // If there's an error (e.g., album was deleted), return empty buckets - return []; - }); + // If there's an error (e.g., album was deleted), return empty buckets + .handleError((error) => const []); } Future> _getRemoteAlbumBucketAssets(String albumId, {required int offset, required int count}) async { @@ -222,17 +216,22 @@ class DriftTimelineRepository extends DriftDatabaseRepository { // If album doesn't exist (was deleted), return empty list if (albumData == null) { - return []; + return const []; } final isAscending = albumData.order == AlbumAssetOrder.asc; - final query = _db.remoteAssetEntity.select().join([ + final query = _db.remoteAssetEntity.select().addColumns([_db.localAssetEntity.id]).join([ innerJoin( _db.remoteAlbumAssetEntity, _db.remoteAlbumAssetEntity.assetId.equalsExp(_db.remoteAssetEntity.id), useColumns: false, ), + leftOuterJoin( + _db.localAssetEntity, + _db.remoteAssetEntity.checksum.equalsExp(_db.localAssetEntity.checksum), + useColumns: false, + ), ])..where(_db.remoteAssetEntity.deletedAt.isNull() & _db.remoteAlbumAssetEntity.albumId.equals(albumId)); if (isAscending) { @@ -243,18 +242,22 @@ class DriftTimelineRepository extends DriftDatabaseRepository { query.limit(count, offset: offset); - return query.map((row) => row.readTable(_db.remoteAssetEntity).toDto()).get(); + return query + .map((row) => row.readTable(_db.remoteAssetEntity).toDto(localId: row.read(_db.localAssetEntity.id))) + .get(); } - TimelineQuery fromAssets(List assets) => ( + TimelineQuery fromAssets(List assets, TimelineOrigin origin) => ( bucketSource: () => Stream.value(_generateBuckets(assets.length)), - assetSource: (offset, count) => Future.value(assets.skip(offset).take(count).toList()), + assetSource: (offset, count) => Future.value(assets.skip(offset).take(count).toList(growable: false)), + origin: origin, ); TimelineQuery remote(String ownerId, GroupAssetsBy groupBy) => _remoteQueryBuilder( filter: (row) => row.deletedAt.isNull() & row.visibility.equalsValue(AssetVisibility.timeline) & row.ownerId.equals(ownerId), groupBy: groupBy, + origin: TimelineOrigin.remoteAssets, ); TimelineQuery favorite(String userId, GroupAssetsBy groupBy) => _remoteQueryBuilder( @@ -264,11 +267,13 @@ class DriftTimelineRepository extends DriftDatabaseRepository { row.ownerId.equals(userId) & row.visibility.equalsValue(AssetVisibility.timeline), groupBy: groupBy, + origin: TimelineOrigin.favorite, ); TimelineQuery trash(String userId, GroupAssetsBy groupBy) => _remoteQueryBuilder( filter: (row) => row.deletedAt.isNotNull() & row.ownerId.equals(userId), groupBy: groupBy, + origin: TimelineOrigin.trash, joinLocal: true, ); @@ -276,11 +281,13 @@ class DriftTimelineRepository extends DriftDatabaseRepository { filter: (row) => row.deletedAt.isNull() & row.ownerId.equals(userId) & row.visibility.equalsValue(AssetVisibility.archive), groupBy: groupBy, + origin: TimelineOrigin.archive, ); TimelineQuery locked(String userId, GroupAssetsBy groupBy) => _remoteQueryBuilder( filter: (row) => row.deletedAt.isNull() & row.visibility.equalsValue(AssetVisibility.locked) & row.ownerId.equals(userId), + origin: TimelineOrigin.lockedFolder, groupBy: groupBy, ); @@ -290,17 +297,20 @@ class DriftTimelineRepository extends DriftDatabaseRepository { row.type.equalsValue(AssetType.video) & row.visibility.equalsValue(AssetVisibility.timeline) & row.ownerId.equals(userId), + origin: TimelineOrigin.video, groupBy: groupBy, ); TimelineQuery place(String place, GroupAssetsBy groupBy) => ( bucketSource: () => _watchPlaceBucket(place, groupBy: groupBy), assetSource: (offset, count) => _getPlaceBucketAssets(place, offset: offset, count: count), + origin: TimelineOrigin.place, ); TimelineQuery person(String userId, String personId, GroupAssetsBy groupBy) => ( bucketSource: () => _watchPersonBucket(userId, personId, groupBy: groupBy), assetSource: (offset, count) => _getPersonBucketAssets(userId, personId, offset: offset, count: count), + origin: TimelineOrigin.person, ); Stream> _watchPlaceBucket(String place, {GroupAssetsBy groupBy = GroupAssetsBy.day}) { @@ -330,7 +340,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository { ..orderBy([OrderingTerm.desc(dateExp)]); return query.map((row) { - final timeline = row.read(dateExp)!.dateFmt(groupBy); + final timeline = row.read(dateExp)!.truncateDate(groupBy); final assetCount = row.read(assetCountExp)!; return TimeBucket(date: timeline, assetCount: assetCount); }).watch(); @@ -401,7 +411,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository { ..orderBy([OrderingTerm.desc(dateExp)]); return query.map((row) { - final timeline = row.read(dateExp)!.dateFmt(groupBy); + final timeline = row.read(dateExp)!.truncateDate(groupBy); final assetCount = row.read(assetCountExp)!; return TimeBucket(date: timeline, assetCount: assetCount); }).watch(); @@ -433,12 +443,17 @@ class DriftTimelineRepository extends DriftDatabaseRepository { return query.map((row) => row.readTable(_db.remoteAssetEntity).toDto()).get(); } - TimelineQuery map(LatLngBounds bounds, GroupAssetsBy groupBy) => ( - bucketSource: () => _watchMapBucket(bounds, groupBy: groupBy), - assetSource: (offset, count) => _getMapBucketAssets(bounds, offset: offset, count: count), + TimelineQuery map(String userId, LatLngBounds bounds, GroupAssetsBy groupBy) => ( + bucketSource: () => _watchMapBucket(userId, bounds, groupBy: groupBy), + assetSource: (offset, count) => _getMapBucketAssets(userId, bounds, offset: offset, count: count), + origin: TimelineOrigin.map, ); - Stream> _watchMapBucket(LatLngBounds bounds, {GroupAssetsBy groupBy = GroupAssetsBy.day}) { + Stream> _watchMapBucket( + String userId, + LatLngBounds bounds, { + GroupAssetsBy groupBy = GroupAssetsBy.day, + }) { if (groupBy == GroupAssetsBy.none) { // TODO: Support GroupAssetsBy.none throw UnsupportedError("GroupAssetsBy.none is not supported for _watchMapBucket"); @@ -457,7 +472,8 @@ class DriftTimelineRepository extends DriftDatabaseRepository { ), ]) ..where( - _db.remoteExifEntity.inBounds(bounds) & + _db.remoteAssetEntity.ownerId.equals(userId) & + _db.remoteExifEntity.inBounds(bounds) & _db.remoteAssetEntity.visibility.equalsValue(AssetVisibility.timeline) & _db.remoteAssetEntity.deletedAt.isNull(), ) @@ -465,13 +481,18 @@ class DriftTimelineRepository extends DriftDatabaseRepository { ..orderBy([OrderingTerm.desc(dateExp)]); return query.map((row) { - final timeline = row.read(dateExp)!.dateFmt(groupBy); + final timeline = row.read(dateExp)!.truncateDate(groupBy); final assetCount = row.read(assetCountExp)!; return TimeBucket(date: timeline, assetCount: assetCount); }).watch(); } - Future> _getMapBucketAssets(LatLngBounds bounds, {required int offset, required int count}) { + Future> _getMapBucketAssets( + String userId, + LatLngBounds bounds, { + required int offset, + required int count, + }) { final query = _db.remoteAssetEntity.select().join([ innerJoin( @@ -481,7 +502,8 @@ class DriftTimelineRepository extends DriftDatabaseRepository { ), ]) ..where( - _db.remoteExifEntity.inBounds(bounds) & + _db.remoteAssetEntity.ownerId.equals(userId) & + _db.remoteExifEntity.inBounds(bounds) & _db.remoteAssetEntity.visibility.equalsValue(AssetVisibility.timeline) & _db.remoteAssetEntity.deletedAt.isNull(), ) @@ -490,8 +512,10 @@ class DriftTimelineRepository extends DriftDatabaseRepository { return query.map((row) => row.readTable(_db.remoteAssetEntity).toDto()).get(); } + @pragma('vm:prefer-inline') TimelineQuery _remoteQueryBuilder({ required Expression Function($RemoteAssetEntityTable row) filter, + required TimelineOrigin origin, GroupAssetsBy groupBy = GroupAssetsBy.day, bool joinLocal = false, }) { @@ -499,6 +523,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository { bucketSource: () => _watchRemoteBucket(filter: filter, groupBy: groupBy), assetSource: (offset, count) => _getRemoteAssets(filter: filter, offset: offset, count: count, joinLocal: joinLocal), + origin: origin, ); } @@ -521,12 +546,13 @@ class DriftTimelineRepository extends DriftDatabaseRepository { ..orderBy([OrderingTerm.desc(dateExp)]); return query.map((row) { - final timeline = row.read(dateExp)!.dateFmt(groupBy); + final timeline = row.read(dateExp)!.truncateDate(groupBy); final assetCount = row.read(assetCountExp)!; return TimeBucket(date: timeline, assetCount: assetCount); }).watch(); } + @pragma('vm:prefer-inline') Future> _getRemoteAssets({ required Expression Function($RemoteAssetEntityTable row) filter, required int offset, @@ -547,11 +573,9 @@ class DriftTimelineRepository extends DriftDatabaseRepository { ..orderBy([OrderingTerm.desc(_db.remoteAssetEntity.createdAt)]) ..limit(count, offset: offset); - return query.map((row) { - final asset = row.readTable(_db.remoteAssetEntity).toDto(); - final localId = row.read(_db.localAssetEntity.id); - return asset.copyWith(localId: localId); - }).get(); + return query + .map((row) => row.readTable(_db.remoteAssetEntity).toDto(localId: row.read(_db.localAssetEntity.id))) + .get(); } else { final query = _db.remoteAssetEntity.select() ..where(filter) @@ -564,12 +588,12 @@ class DriftTimelineRepository extends DriftDatabaseRepository { } List _generateBuckets(int count) { - final buckets = List.generate( - (count / kTimelineNoneSegmentSize).floor(), - (_) => const Bucket(assetCount: kTimelineNoneSegmentSize), + final buckets = List.filled( + (count / kTimelineNoneSegmentSize).ceil(), + const Bucket(assetCount: kTimelineNoneSegmentSize), ); if (count % kTimelineNoneSegmentSize != 0) { - buckets.add(Bucket(assetCount: count % kTimelineNoneSegmentSize)); + buckets[buckets.length - 1] = Bucket(assetCount: count % kTimelineNoneSegmentSize); } return buckets; } @@ -588,16 +612,12 @@ extension on Expression { } extension on String { - DateTime dateFmt(GroupAssetsBy groupBy) { + DateTime truncateDate(GroupAssetsBy groupBy) { final format = switch (groupBy) { GroupAssetsBy.day || GroupAssetsBy.auto => "y-M-d", GroupAssetsBy.month => "y-M", GroupAssetsBy.none => throw ArgumentError("GroupAssetsBy.none is not supported for date formatting"), }; - try { - return DateFormat(format).parse(this); - } catch (e) { - throw FormatException("Invalid date format: $this", e); - } + return DateFormat(format, 'en').parse(this); } } diff --git a/mobile/lib/infrastructure/repositories/user.repository.dart b/mobile/lib/infrastructure/repositories/user.repository.dart index 3081aee1a9..d4eb1ceed6 100644 --- a/mobile/lib/infrastructure/repositories/user.repository.dart +++ b/mobile/lib/infrastructure/repositories/user.repository.dart @@ -2,8 +2,8 @@ import 'package:drift/drift.dart'; import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/domain/models/user.model.dart'; import 'package:immich_mobile/domain/models/user_metadata.model.dart'; +import 'package:immich_mobile/infrastructure/entities/auth_user.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/user.entity.dart' as entity; -import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/user_metadata.repository.dart'; import 'package:isar/isar.dart'; @@ -68,12 +68,12 @@ class IsarUserRepository extends IsarDatabaseRepository { } } -class DriftUserRepository extends DriftDatabaseRepository { +class DriftAuthUserRepository extends DriftDatabaseRepository { final Drift _db; - const DriftUserRepository(super.db) : _db = db; + const DriftAuthUserRepository(super.db) : _db = db; Future get(String id) async { - final user = await _db.managers.userEntity.filter((user) => user.id.equals(id)).getSingleOrNull(); + final user = await _db.managers.authUserEntity.filter((user) => user.id.equals(id)).getSingleOrNull(); if (user == null) return null; @@ -84,43 +84,30 @@ class DriftUserRepository extends DriftDatabaseRepository { } Future upsert(UserDto user) async { - await _db.userEntity.insertOnConflictUpdate( - UserEntityCompanion( + await _db.authUserEntity.insertOnConflictUpdate( + AuthUserEntityCompanion( id: Value(user.id), - isAdmin: Value(user.isAdmin), - updatedAt: Value(user.updatedAt), name: Value(user.name), email: Value(user.email), hasProfileImage: Value(user.hasProfileImage), profileChangedAt: Value(user.profileChangedAt), + isAdmin: Value(user.isAdmin), + quotaSizeInBytes: Value(user.quotaSizeInBytes), + quotaUsageInBytes: Value(user.quotaUsageInBytes), + avatarColor: Value(user.avatarColor), ), ); return user; } - - Future> getAll() async { - final users = await _db.userEntity.select().get(); - final List result = []; - - for (final user in users) { - final query = _db.userMetadataEntity.select()..where((e) => e.userId.equals(user.id)); - final metadata = await query.map((row) => row.toDto()).get(); - result.add(user.toDto(metadata)); - } - - return result; - } } -extension on UserEntityData { +extension on AuthUserEntityData { UserDto toDto([List? metadata]) { - AvatarColor avatarColor = AvatarColor.primary; bool memoryEnabled = true; if (metadata != null) { for (final meta in metadata) { if (meta.key == UserMetadataKey.preferences && meta.preferences != null) { - avatarColor = meta.preferences?.userAvatarColor ?? AvatarColor.primary; memoryEnabled = meta.preferences?.memoriesEnabled ?? true; } } @@ -130,12 +117,13 @@ extension on UserEntityData { id: id, email: email, name: name, - isAdmin: isAdmin, - updatedAt: updatedAt, profileChangedAt: profileChangedAt, hasProfileImage: hasProfileImage, avatarColor: avatarColor, memoryEnabled: memoryEnabled, + isAdmin: isAdmin, + quotaSizeInBytes: quotaSizeInBytes, + quotaUsageInBytes: quotaUsageInBytes, ); } } diff --git a/mobile/lib/infrastructure/utils/user.converter.dart b/mobile/lib/infrastructure/utils/user.converter.dart index bf35077e1f..826649b247 100644 --- a/mobile/lib/infrastructure/utils/user.converter.dart +++ b/mobile/lib/infrastructure/utils/user.converter.dart @@ -1,5 +1,4 @@ import 'package:immich_mobile/domain/models/user.model.dart'; -import 'package:immich_mobile/domain/models/user_metadata.model.dart'; import 'package:openapi/api.dart'; // TODO: Move to repository once all classes are refactored diff --git a/mobile/lib/main.dart b/mobile/lib/main.dart index 9066c5bfc7..263a5ef769 100644 --- a/mobile/lib/main.dart +++ b/mobile/lib/main.dart @@ -12,14 +12,18 @@ import 'package:flutter_displaymode/flutter_displaymode.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/constants.dart'; import 'package:immich_mobile/constants/locales.dart'; +import 'package:immich_mobile/domain/services/background_worker.service.dart'; import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/generated/codegen_loader.g.dart'; +import 'package:immich_mobile/generated/intl_keys.g.dart'; +import 'package:immich_mobile/platform/background_worker_lock_api.g.dart'; import 'package:immich_mobile/providers/app_life_cycle.provider.dart'; import 'package:immich_mobile/providers/asset_viewer/share_intent_upload.provider.dart'; -import 'package:immich_mobile/providers/backup/backup.provider.dart'; import 'package:immich_mobile/providers/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/platform.provider.dart'; import 'package:immich_mobile/providers/locale_provider.dart'; import 'package:immich_mobile/providers/routes.provider.dart'; import 'package:immich_mobile/providers/theme.provider.dart'; @@ -32,6 +36,7 @@ import 'package:immich_mobile/theme/dynamic_theme.dart'; import 'package:immich_mobile/theme/theme_data.dart'; import 'package:immich_mobile/utils/bootstrap.dart'; import 'package:immich_mobile/utils/cache/widgets_binding.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; import 'package:immich_mobile/utils/http_ssl_options.dart'; import 'package:immich_mobile/utils/licenses.dart'; import 'package:immich_mobile/utils/migration.dart'; @@ -42,6 +47,7 @@ import 'package:worker_manager/worker_manager.dart'; void main() async { ImmichWidgetsBinding(); + unawaited(BackgroundWorkerLockService(BackgroundWorkerLockApi()).lock()); final (isar, drift, logDb) = await Bootstrap.initDB(); await Bootstrap.initDomain(isar, drift, logDb); await initApp(); @@ -69,9 +75,9 @@ Future initApp() async { if (kReleaseMode && Platform.isAndroid) { try { await FlutterDisplayMode.setHighRefreshRate(); - debugPrint("Enabled high refresh mode"); + dPrint(() => "Enabled high refresh mode"); } catch (e) { - debugPrint("Error setting high refresh rate: $e"); + dPrint(() => "Error setting high refresh rate: $e"); } } @@ -126,23 +132,23 @@ class ImmichAppState extends ConsumerState with WidgetsBindingObserve void didChangeAppLifecycleState(AppLifecycleState state) { switch (state) { case AppLifecycleState.resumed: - debugPrint("[APP STATE] resumed"); + dPrint(() => "[APP STATE] resumed"); ref.read(appStateProvider.notifier).handleAppResume(); break; case AppLifecycleState.inactive: - debugPrint("[APP STATE] inactive"); + dPrint(() => "[APP STATE] inactive"); ref.read(appStateProvider.notifier).handleAppInactivity(); break; case AppLifecycleState.paused: - debugPrint("[APP STATE] paused"); + dPrint(() => "[APP STATE] paused"); ref.read(appStateProvider.notifier).handleAppPause(); break; case AppLifecycleState.detached: - debugPrint("[APP STATE] detached"); + dPrint(() => "[APP STATE] detached"); ref.read(appStateProvider.notifier).handleAppDetached(); break; case AppLifecycleState.hidden: - debugPrint("[APP STATE] hidden"); + dPrint(() => "[APP STATE] hidden"); ref.read(appStateProvider.notifier).handleAppHidden(); break; } @@ -200,14 +206,22 @@ class ImmichAppState extends ConsumerState with WidgetsBindingObserve @override initState() { super.initState(); - initApp().then((_) => debugPrint("App Init Completed")); + initApp().then((_) => dPrint(() => "App Init Completed")); WidgetsBinding.instance.addPostFrameCallback((_) { // needs to be delayed so that EasyLocalization is working if (Store.isBetaTimelineEnabled) { ref.read(backgroundServiceProvider).disableService(); - ref.read(driftBackgroundUploadFgService).enable(); + ref.read(backgroundWorkerFgServiceProvider).enable(); + if (Platform.isAndroid) { + ref + .read(backgroundWorkerFgServiceProvider) + .saveNotificationMessage( + IntlKeys.uploading_media.t(), + IntlKeys.backup_background_service_default_notification.t(), + ); + } } else { - ref.read(driftBackgroundUploadFgService).disable(); + ref.read(backgroundWorkerFgServiceProvider).disable(); ref.read(backgroundServiceProvider).resumeServiceIfEnabled(); } }); @@ -239,7 +253,7 @@ class ImmichAppState extends ConsumerState with WidgetsBindingObserve theme: getThemeData(colorScheme: immichTheme.light, locale: context.locale), routerConfig: router.config( deepLinkBuilder: _deepLinkBuilder, - navigatorObservers: () => [AppNavigationObserver(ref: ref), HeroController()], + navigatorObservers: () => [AppNavigationObserver(ref: ref)], ), ), ); diff --git a/mobile/lib/pages/album/album_options.page.dart b/mobile/lib/pages/album/album_options.page.dart index e659340f26..20d4dbd325 100644 --- a/mobile/lib/pages/album/album_options.page.dart +++ b/mobile/lib/pages/album/album_options.page.dart @@ -169,7 +169,7 @@ class AlbumOptionsPage extends HookConsumerWidget { album.activityEnabled = value; } }, - activeColor: activityEnabled.value ? context.primaryColor : context.themeData.disabledColor, + activeThumbColor: activityEnabled.value ? context.primaryColor : context.themeData.disabledColor, dense: true, title: Text( "comments_and_likes", diff --git a/mobile/lib/pages/backup/backup_controller.page.dart b/mobile/lib/pages/backup/backup_controller.page.dart index 093ff952ae..4f55d00ea0 100644 --- a/mobile/lib/pages/backup/backup_controller.page.dart +++ b/mobile/lib/pages/backup/backup_controller.page.dart @@ -205,9 +205,9 @@ class BackupControllerPage extends HookConsumerWidget { } buildBackgroundBackupInfo() { - return const ListTile( - leading: Icon(Icons.info_outline_rounded), - title: Text("Background backup is currently running, cannot start manual backup"), + return ListTile( + leading: const Icon(Icons.info_outline_rounded), + title: Text('background_backup_running_error'.tr()), ); } diff --git a/mobile/lib/pages/backup/drift_backup.page.dart b/mobile/lib/pages/backup/drift_backup.page.dart index b125c35908..2e7c3e946c 100644 --- a/mobile/lib/pages/backup/drift_backup.page.dart +++ b/mobile/lib/pages/backup/drift_backup.page.dart @@ -1,18 +1,26 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/album/local_album.model.dart'; +import 'package:immich_mobile/domain/models/store.model.dart'; +import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/theme_extensions.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart'; +import 'package:immich_mobile/generated/intl_keys.g.dart'; import 'package:immich_mobile/presentation/widgets/backup/backup_toggle_button.widget.dart'; import 'package:immich_mobile/providers/background_sync.provider.dart'; import 'package:immich_mobile/providers/backup/backup_album.provider.dart'; import 'package:immich_mobile/providers/backup/drift_backup.provider.dart'; +import 'package:immich_mobile/providers/sync_status.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/widgets/backup/backup_info_card.dart'; +import 'package:logging/logging.dart'; +import 'package:wakelock_plus/wakelock_plus.dart'; @RoutePage() class DriftBackupPage extends ConsumerStatefulWidget { @@ -23,30 +31,36 @@ class DriftBackupPage extends ConsumerStatefulWidget { } class _DriftBackupPageState extends ConsumerState { + bool? syncSuccess; + @override void initState() { super.initState(); + + WakelockPlus.enable(); + final currentUser = ref.read(currentUserProvider); if (currentUser == null) { return; } - ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id); + WidgetsBinding.instance.addPostFrameCallback((_) async { + await ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id); + + ref.read(driftBackupProvider.notifier).updateSyncing(true); + syncSuccess = await ref.read(backgroundSyncProvider).syncRemote(); + ref.read(driftBackupProvider.notifier).updateSyncing(false); + + if (mounted) { + await ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id); + } + }); } - Future startBackup() async { - final currentUser = ref.read(currentUserProvider); - if (currentUser == null) { - return; - } - - await ref.read(backgroundSyncProvider).syncRemote(); - await ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id); - await ref.read(driftBackupProvider.notifier).startBackup(currentUser.id); - } - - Future stopBackup() async { - await ref.read(driftBackupProvider.notifier).cancel(); + @override + dispose() { + super.dispose(); + WakelockPlus.disable(); } @override @@ -56,6 +70,36 @@ class _DriftBackupPageState extends ConsumerState { .where((album) => album.backupSelection == BackupSelection.selected) .toList(); + final error = ref.watch(driftBackupProvider.select((p) => p.error)); + + final backupNotifier = ref.read(driftBackupProvider.notifier); + final backupSyncManager = ref.read(backgroundSyncProvider); + + Future startBackup() async { + final currentUser = Store.tryGet(StoreKey.currentUser); + if (currentUser == null) { + return; + } + + if (syncSuccess == null) { + ref.read(driftBackupProvider.notifier).updateSyncing(true); + syncSuccess = await backupSyncManager.syncRemote(); + ref.read(driftBackupProvider.notifier).updateSyncing(false); + } + + await backupNotifier.getBackupStatus(currentUser.id); + + if (syncSuccess == false) { + Logger("DriftBackupPage").warning("Remote sync did not complete successfully, skipping backup"); + return; + } + await backupNotifier.startBackup(currentUser.id); + } + + Future stopBackup() async { + await backupNotifier.cancel(); + } + return Scaffold( appBar: AppBar( elevation: 0, @@ -90,7 +134,33 @@ class _DriftBackupPageState extends ConsumerState { const _BackupCard(), const _RemainderCard(), const Divider(), - BackupToggleButton(onStart: () async => await startBackup(), onStop: () async => await stopBackup()), + BackupToggleButton( + onStart: () async => await startBackup(), + onStop: () async { + syncSuccess = null; + await stopBackup(); + }, + ), + switch (error) { + BackupError.none => const SizedBox.shrink(), + BackupError.syncFailed => Padding( + padding: const EdgeInsets.only(top: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + Icon(Icons.warning_rounded, color: context.colorScheme.error, fill: 1), + const SizedBox(width: 8), + Text( + IntlKeys.backup_error_sync_failed.t(), + style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.error), + textAlign: TextAlign.center, + ), + ], + ), + ), + }, TextButton.icon( icon: const Icon(Icons.info_outline_rounded), onPressed: () => context.pushRoute(const DriftUploadDetailRoute()), @@ -230,11 +300,13 @@ class _BackupCard extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final backupCount = ref.watch(driftBackupProvider.select((p) => p.backupCount)); + final syncStatus = ref.watch(syncStatusProvider); return BackupInfoCard( title: "backup_controller_page_backup".tr(), subtitle: "backup_controller_page_backup_sub".tr(), info: backupCount.toString(), + isLoading: syncStatus.isRemoteSyncing, ); } } @@ -245,11 +317,207 @@ class _RemainderCard extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final remainderCount = ref.watch(driftBackupProvider.select((p) => p.remainderCount)); - return BackupInfoCard( - title: "backup_controller_page_remainder".tr(), - subtitle: "backup_controller_page_remainder_sub".tr(), - info: remainderCount.toString(), - onTap: () => context.pushRoute(const DriftBackupAssetDetailRoute()), + final syncStatus = ref.watch(syncStatusProvider); + + return Card( + shape: RoundedRectangleBorder( + borderRadius: const BorderRadius.all(Radius.circular(20)), + side: BorderSide(color: context.colorScheme.outlineVariant, width: 1), + ), + elevation: 0, + borderOnForeground: false, + child: Column( + children: [ + ListTile( + minVerticalPadding: 18, + isThreeLine: true, + title: Text("backup_controller_page_remainder".t(context: context), style: context.textTheme.titleMedium), + subtitle: Padding( + padding: const EdgeInsets.only(top: 4.0, right: 18.0), + child: Text( + "backup_controller_page_remainder_sub".t(context: context), + style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary), + ), + ), + trailing: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Stack( + children: [ + Text( + remainderCount.toString(), + style: context.textTheme.titleLarge?.copyWith( + color: context.colorScheme.onSurface.withAlpha(syncStatus.isRemoteSyncing ? 50 : 255), + ), + ), + if (syncStatus.isRemoteSyncing) + Positioned.fill( + child: Align( + alignment: Alignment.center, + child: SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator( + strokeWidth: 2, + color: context.colorScheme.onSurface.withAlpha(150), + ), + ), + ), + ), + ], + ), + Text( + "backup_info_card_assets", + style: context.textTheme.labelLarge?.copyWith( + color: context.colorScheme.onSurface.withAlpha(syncStatus.isRemoteSyncing ? 50 : 255), + ), + ).tr(), + ], + ), + ), + const Divider(height: 0), + const _PreparingStatus(), + const Divider(height: 0), + + ListTile( + enableFeedback: true, + visualDensity: VisualDensity.compact, + contentPadding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 0.0), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only(bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20)), + ), + onTap: () => context.pushRoute(const DriftBackupAssetDetailRoute()), + title: Text( + "view_details".t(context: context), + style: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurface.withAlpha(200)), + ), + trailing: Icon(Icons.arrow_forward_ios, size: 16, color: context.colorScheme.onSurfaceVariant), + ), + ], + ), + ); + } +} + +class _PreparingStatus extends ConsumerStatefulWidget { + const _PreparingStatus(); + + @override + _PreparingStatusState createState() => _PreparingStatusState(); +} + +class _PreparingStatusState extends ConsumerState { + Timer? _pollingTimer; + + @override + void dispose() { + _pollingTimer?.cancel(); + super.dispose(); + } + + void _startPollingIfNeeded() { + if (_pollingTimer != null) return; + + _pollingTimer = Timer.periodic(const Duration(seconds: 3), (timer) async { + final currentUser = ref.read(currentUserProvider); + if (currentUser != null && mounted) { + await ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id); + + // Stop polling if processing count reaches 0 + final updatedProcessingCount = ref.read(driftBackupProvider.select((p) => p.processingCount)); + if (updatedProcessingCount == 0) { + timer.cancel(); + _pollingTimer = null; + } + } else { + timer.cancel(); + _pollingTimer = null; + } + }); + } + + @override + Widget build(BuildContext context) { + final syncStatus = ref.watch(syncStatusProvider); + final remainderCount = ref.watch(driftBackupProvider.select((p) => p.remainderCount)); + final processingCount = ref.watch(driftBackupProvider.select((p) => p.processingCount)); + final readyForUploadCount = remainderCount - processingCount; + + ref.listen(driftBackupProvider.select((p) => p.processingCount), (previous, next) { + if (next > 0 && _pollingTimer == null) { + _startPollingIfNeeded(); + } else if (next == 0 && _pollingTimer != null) { + _pollingTimer?.cancel(); + _pollingTimer = null; + } + }); + + if (!syncStatus.isHashing) { + return const SizedBox.shrink(); + } + + return Row( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.only(left: 1.0), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8), + decoration: BoxDecoration( + color: context.colorScheme.surfaceContainerHigh.withValues(alpha: 0.5), + shape: BoxShape.rectangle, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + "preparing".t(context: context), + style: context.textTheme.labelLarge?.copyWith( + color: context.colorScheme.onSurface.withAlpha(200), + ), + ), + const SizedBox(width: 18, height: 18, child: CircularProgressIndicator(strokeWidth: 1.5)), + ], + ), + const SizedBox(height: 2), + Text( + processingCount.toString(), + style: context.textTheme.titleMedium?.copyWith( + color: context.colorScheme.primary, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + ), + ), + Expanded( + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8), + decoration: BoxDecoration(color: context.colorScheme.primary.withValues(alpha: 0.1)), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + "ready_for_upload".t(context: context), + style: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurface.withAlpha(200)), + ), + const SizedBox(height: 2), + Text( + readyForUploadCount.toString(), + style: context.textTheme.titleMedium?.copyWith( + color: context.primaryColor, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + ), + ], ); } } diff --git a/mobile/lib/pages/backup/drift_backup_album_selection.page.dart b/mobile/lib/pages/backup/drift_backup_album_selection.page.dart index e734dc300c..cae9f0a408 100644 --- a/mobile/lib/pages/backup/drift_backup_album_selection.page.dart +++ b/mobile/lib/pages/backup/drift_backup_album_selection.page.dart @@ -1,19 +1,24 @@ +import 'dart:async'; import 'dart:io'; import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/album/local_album.model.dart'; +import 'package:immich_mobile/domain/services/sync_linked_album.service.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/providers/app_settings.provider.dart'; -import 'package:immich_mobile/domain/services/sync_linked_album.service.dart'; +import 'package:immich_mobile/providers/background_sync.provider.dart'; import 'package:immich_mobile/providers/backup/backup_album.provider.dart'; import 'package:immich_mobile/providers/backup/drift_backup.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/platform.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; import 'package:immich_mobile/services/app_settings.service.dart'; import 'package:immich_mobile/widgets/backup/drift_album_info_list_tile.dart'; import 'package:immich_mobile/widgets/common/search_field.dart'; +import 'package:logging/logging.dart'; @RoutePage() class DriftBackupAlbumSelectionPage extends ConsumerStatefulWidget { @@ -63,16 +68,6 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState p.totalCount)); - final totalChanged = currentTotalAssetCount != _initialTotalAssetCount; - final isBackupEnabled = ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableBackup); - - if (totalChanged && isBackupEnabled) { - await ref.read(driftBackupProvider.notifier).cancel(); - await ref.read(driftBackupProvider.notifier).startBackup(user.id); - } } @override @@ -101,6 +96,37 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState p.totalCount)); + final totalChanged = currentTotalAssetCount != _initialTotalAssetCount; + final backupNotifier = ref.read(driftBackupProvider.notifier); + final backgroundSync = ref.read(backgroundSyncProvider); + final nativeSync = ref.read(nativeSyncApiProvider); + if (totalChanged) { + // Waits for hashing to be cancelled before starting a new one + unawaited(nativeSync.cancelHashing().whenComplete(() => backgroundSync.hashAssets())); + if (isBackupEnabled) { + unawaited( + backupNotifier.cancel().whenComplete( + () => backgroundSync.syncRemote().then((success) { + if (success) { + return backupNotifier.startBackup(user.id); + } else { + Logger('DriftBackupAlbumSelectionPage').warning('Background sync failed, not starting backup'); + } + }), + ), + ); + } + } + Navigator.of(context).pop(); } }, @@ -249,7 +275,7 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState - Text('Error: $error', style: TextStyle(color: context.colorScheme.error)), + error: (error, stackTrace) => Text( + 'error_saving_image'.tr(args: [error.toString()]), + style: TextStyle(color: context.colorScheme.error), + ), loading: () => const SizedBox(height: 16, width: 16, child: CircularProgressIndicator.adaptive()), ), ], @@ -83,7 +86,7 @@ class DriftBackupAssetDetailPage extends ConsumerWidget { ); }, error: (Object error, StackTrace stackTrace) { - return Center(child: Text('Error: $error')); + return Center(child: Text('error_saving_image'.tr(args: [error.toString()]))); }, loading: () { return const SizedBox(height: 48, width: 48, child: Center(child: CircularProgressIndicator.adaptive())); diff --git a/mobile/lib/pages/backup/drift_backup_options.page.dart b/mobile/lib/pages/backup/drift_backup_options.page.dart index 92f911ae1e..1e5c326478 100644 --- a/mobile/lib/pages/backup/drift_backup_options.page.dart +++ b/mobile/lib/pages/backup/drift_backup_options.page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -5,10 +7,12 @@ import 'package:immich_mobile/domain/models/store.model.dart'; import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/providers/app_settings.provider.dart'; +import 'package:immich_mobile/providers/background_sync.provider.dart'; import 'package:immich_mobile/providers/backup/drift_backup.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; import 'package:immich_mobile/services/app_settings.service.dart'; import 'package:immich_mobile/widgets/settings/backup_settings/drift_backup_settings.dart'; +import 'package:logging/logging.dart'; @RoutePage() class DriftBackupOptionsPage extends ConsumerWidget { @@ -54,9 +58,18 @@ class DriftBackupOptionsPage extends ConsumerWidget { ); final backupNotifier = ref.read(driftBackupProvider.notifier); - backupNotifier.cancel().then((_) { - backupNotifier.startBackup(currentUser.id); - }); + final backgroundSync = ref.read(backgroundSyncProvider); + unawaited( + backupNotifier.cancel().whenComplete( + () => backgroundSync.syncRemote().then((success) { + if (success) { + return backupNotifier.startBackup(currentUser.id); + } else { + Logger('DriftBackupOptionsPage').warning('Background sync failed, not starting backup'); + } + }), + ), + ); } }, child: Scaffold( diff --git a/mobile/lib/pages/backup/drift_upload_detail.page.dart b/mobile/lib/pages/backup/drift_upload_detail.page.dart index bececddc7f..80956b708f 100644 --- a/mobile/lib/pages/backup/drift_upload_detail.page.dart +++ b/mobile/lib/pages/backup/drift_upload_detail.page.dart @@ -1,12 +1,12 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart'; -import 'package:immich_mobile/providers/backup/drift_backup.provider.dart'; -import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; -import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart'; +import 'package:immich_mobile/providers/backup/drift_backup.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; import 'package:immich_mobile/utils/bytes_units.dart'; import 'package:path/path.dart' as path; @@ -82,6 +82,7 @@ class DriftUploadDetailPage extends ConsumerWidget { Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, + spacing: 4, children: [ Text( path.basename(item.filename), @@ -89,7 +90,13 @@ class DriftUploadDetailPage extends ConsumerWidget { maxLines: 1, overflow: TextOverflow.ellipsis, ), - const SizedBox(height: 4), + if (item.error != null) + Text( + item.error!, + style: context.textTheme.bodySmall?.copyWith( + color: context.colorScheme.onErrorContainer.withValues(alpha: 0.6), + ), + ), Text( 'Tap for more details', style: context.textTheme.bodySmall?.copyWith( diff --git a/mobile/lib/pages/common/app_log.page.dart b/mobile/lib/pages/common/app_log.page.dart index fe0c0ea442..37aec2f13c 100644 --- a/mobile/lib/pages/common/app_log.page.dart +++ b/mobile/lib/pages/common/app_log.page.dart @@ -1,4 +1,5 @@ import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -8,7 +9,6 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/theme_extensions.dart'; import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/services/immich_logger.service.dart'; -import 'package:intl/intl.dart'; @RoutePage() class AppLogPage extends HookConsumerWidget { @@ -49,7 +49,7 @@ class AppLogPage extends HookConsumerWidget { return Scaffold( appBar: AppBar( - title: const Text("Logs", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0)), + title: Text('logs'.tr(), style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0)), scrolledUnderElevation: 1, elevation: 2, actions: [ diff --git a/mobile/lib/pages/common/app_log_detail.page.dart b/mobile/lib/pages/common/app_log_detail.page.dart index c9773f36e1..de9604b7ad 100644 --- a/mobile/lib/pages/common/app_log_detail.page.dart +++ b/mobile/lib/pages/common/app_log_detail.page.dart @@ -1,4 +1,5 @@ import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -36,7 +37,7 @@ class AppLogDetailPage extends HookConsumerWidget { context.scaffoldMessenger.showSnackBar( SnackBar( content: Text( - "Copied to clipboard", + "copied_to_clipboard".tr(), style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor), ), ), @@ -97,7 +98,7 @@ class AppLogDetailPage extends HookConsumerWidget { } return Scaffold( - appBar: AppBar(title: const Text("Log Detail")), + appBar: AppBar(title: Text("log_detail_title".tr())), body: SafeArea( child: ListView( children: [ diff --git a/mobile/lib/pages/common/change_experience.page.dart b/mobile/lib/pages/common/change_experience.page.dart index ffdba1fb71..2cc3dede1e 100644 --- a/mobile/lib/pages/common/change_experience.page.dart +++ b/mobile/lib/pages/common/change_experience.page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -13,8 +15,10 @@ import 'package:immich_mobile/providers/backup/backup.provider.dart'; import 'package:immich_mobile/providers/backup/manual_upload.provider.dart'; import 'package:immich_mobile/providers/gallery_permission.provider.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/platform.provider.dart'; import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.dart'; import 'package:immich_mobile/providers/websocket.provider.dart'; +import 'package:immich_mobile/services/app_settings.service.dart'; import 'package:immich_mobile/services/background.service.dart'; import 'package:immich_mobile/utils/migration.dart'; import 'package:logging/logging.dart'; @@ -41,49 +45,13 @@ class _ChangeExperiencePageState extends ConsumerState { Future _handleMigration() async { try { - if (widget.switchingToBeta) { - final assetNotifier = ref.read(assetProvider.notifier); - if (assetNotifier.mounted) { - assetNotifier.dispose(); - } - final albumNotifier = ref.read(albumProvider.notifier); - if (albumNotifier.mounted) { - albumNotifier.dispose(); - } - - // Cancel uploads - await Store.put(StoreKey.backgroundBackup, false); - ref - .read(backupProvider.notifier) - .configureBackgroundBackup(enabled: false, onBatteryInfo: () {}, onError: (_) {}); - ref.read(backupProvider.notifier).setAutoBackup(false); - ref.read(backupProvider.notifier).cancelBackup(); - ref.read(manualUploadProvider.notifier).cancelBackup(); - // Start listening to new websocket events - ref.read(websocketProvider.notifier).stopListenToOldEvents(); - ref.read(websocketProvider.notifier).startListeningToBetaEvents(); - - final permission = await ref.read(galleryPermissionNotifier.notifier).requestGalleryPermission(); - - if (permission.isGranted) { - await ref.read(backgroundSyncProvider).syncLocal(full: true); - await migrateDeviceAssetToSqlite(ref.read(isarProvider), ref.read(driftProvider)); - await migrateBackupAlbumsToSqlite(ref.read(isarProvider), ref.read(driftProvider)); - await migrateStoreToSqlite(ref.read(isarProvider), ref.read(driftProvider)); - await ref.read(backgroundServiceProvider).disableService(); - } - } else { - await ref.read(backgroundSyncProvider).cancel(); - ref.read(websocketProvider.notifier).stopListeningToBetaEvents(); - ref.read(websocketProvider.notifier).startListeningToOldEvents(); - ref.read(readonlyModeProvider.notifier).setReadonlyMode(false); - await migrateStoreToIsar(ref.read(isarProvider), ref.read(driftProvider)); - await ref.read(backgroundServiceProvider).resumeServiceIfEnabled(); - await ref.read(driftBackgroundUploadFgService).disable(); - } - - await IsarStoreRepository(ref.read(isarProvider)).upsert(StoreKey.betaTimeline, widget.switchingToBeta); - await DriftStoreRepository(ref.read(driftProvider)).upsert(StoreKey.betaTimeline, widget.switchingToBeta); + await _performMigrationLogic().timeout( + const Duration(minutes: 3), + onTimeout: () async { + await IsarStoreRepository(ref.read(isarProvider)).upsert(StoreKey.betaTimeline, widget.switchingToBeta); + await DriftStoreRepository(ref.read(driftProvider)).upsert(StoreKey.betaTimeline, widget.switchingToBeta); + }, + ); if (mounted) { setState(() { @@ -101,6 +69,58 @@ class _ChangeExperiencePageState extends ConsumerState { } } + Future _performMigrationLogic() async { + if (widget.switchingToBeta) { + final assetNotifier = ref.read(assetProvider.notifier); + if (assetNotifier.mounted) { + assetNotifier.dispose(); + } + final albumNotifier = ref.read(albumProvider.notifier); + if (albumNotifier.mounted) { + albumNotifier.dispose(); + } + + // Cancel uploads + await Store.put(StoreKey.backgroundBackup, false); + ref + .read(backupProvider.notifier) + .configureBackgroundBackup(enabled: false, onBatteryInfo: () {}, onError: (_) {}); + ref.read(backupProvider.notifier).setAutoBackup(false); + ref.read(backupProvider.notifier).cancelBackup(); + ref.read(manualUploadProvider.notifier).cancelBackup(); + // Start listening to new websocket events + ref.read(websocketProvider.notifier).stopListenToOldEvents(); + ref.read(websocketProvider.notifier).startListeningToBetaEvents(); + + await ref.read(driftProvider).reset(); + await Store.put(StoreKey.shouldResetSync, true); + final delay = Store.get(StoreKey.backupTriggerDelay, AppSettingsEnum.backupTriggerDelay.defaultValue); + if (delay >= 1000) { + await Store.put(StoreKey.backupTriggerDelay, (delay / 1000).toInt()); + } + final permission = await ref.read(galleryPermissionNotifier.notifier).requestGalleryPermission(); + + if (permission.isGranted) { + await ref.read(backgroundSyncProvider).syncLocal(full: true); + await migrateDeviceAssetToSqlite(ref.read(isarProvider), ref.read(driftProvider)); + await migrateBackupAlbumsToSqlite(ref.read(isarProvider), ref.read(driftProvider)); + await migrateStoreToSqlite(ref.read(isarProvider), ref.read(driftProvider)); + await ref.read(backgroundServiceProvider).disableService(); + } + } else { + await ref.read(backgroundSyncProvider).cancel(); + ref.read(websocketProvider.notifier).stopListeningToBetaEvents(); + ref.read(websocketProvider.notifier).startListeningToOldEvents(); + ref.read(readonlyModeProvider.notifier).setReadonlyMode(false); + await migrateStoreToIsar(ref.read(isarProvider), ref.read(driftProvider)); + await ref.read(backgroundServiceProvider).resumeServiceIfEnabled(); + await ref.read(backgroundWorkerFgServiceProvider).disable(); + } + + await IsarStoreRepository(ref.read(isarProvider)).upsert(StoreKey.betaTimeline, widget.switchingToBeta); + await DriftStoreRepository(ref.read(driftProvider)).upsert(StoreKey.betaTimeline, widget.switchingToBeta); + } + @override Widget build(BuildContext context) { return Scaffold( diff --git a/mobile/lib/pages/common/native_video_viewer.page.dart b/mobile/lib/pages/common/native_video_viewer.page.dart index d8b6db2276..7f39d07ec0 100644 --- a/mobile/lib/pages/common/native_video_viewer.page.dart +++ b/mobile/lib/pages/common/native_video_viewer.page.dart @@ -190,7 +190,10 @@ class NativeVideoViewerPage extends HookConsumerWidget { isVideoReady.value = true; try { - await videoController.play(); + final autoPlayVideo = ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.autoPlayVideo); + if (autoPlayVideo) { + await videoController.play(); + } await videoController.setVolume(0.9); } catch (error) { log.severe('Error playing video: $error'); diff --git a/mobile/lib/pages/common/settings.page.dart b/mobile/lib/pages/common/settings.page.dart index 7bc8cd2b3a..0fe2ccec09 100644 --- a/mobile/lib/pages/common/settings.page.dart +++ b/mobile/lib/pages/common/settings.page.dart @@ -11,8 +11,7 @@ import 'package:immich_mobile/widgets/settings/asset_list_settings/asset_list_se import 'package:immich_mobile/widgets/settings/asset_viewer_settings/asset_viewer_settings.dart'; import 'package:immich_mobile/widgets/settings/backup_settings/backup_settings.dart'; import 'package:immich_mobile/widgets/settings/backup_settings/drift_backup_settings.dart'; -import 'package:immich_mobile/widgets/settings/beta_sync_settings/beta_sync_settings.dart'; -import 'package:immich_mobile/widgets/settings/beta_timeline_list_tile.dart'; +import 'package:immich_mobile/widgets/settings/beta_sync_settings/sync_status_and_actions.dart'; import 'package:immich_mobile/widgets/settings/language_settings.dart'; import 'package:immich_mobile/widgets/settings/networking_settings/networking_settings.dart'; import 'package:immich_mobile/widgets/settings/notification_setting.dart'; @@ -20,7 +19,6 @@ import 'package:immich_mobile/widgets/settings/preference_settings/preference_se import 'package:immich_mobile/widgets/settings/settings_card.dart'; enum SettingSection { - beta('beta_sync', Icons.sync_outlined, "beta_sync_subtitle"), advanced('advanced', Icons.build_outlined, "advanced_settings_tile_subtitle"), assetViewer('asset_viewer_settings_title', Icons.image_outlined, "asset_viewer_settings_subtitle"), backup('backup', Icons.cloud_upload_outlined, "backup_settings_subtitle"), @@ -28,14 +26,14 @@ enum SettingSection { networking('networking_settings', Icons.wifi, "networking_subtitle"), notifications('notifications', Icons.notifications_none_rounded, "setting_notifications_subtitle"), preferences('preferences_settings_title', Icons.interests_outlined, "preferences_settings_subtitle"), - timeline('asset_list_settings_title', Icons.auto_awesome_mosaic_outlined, "asset_list_settings_subtitle"); + timeline('asset_list_settings_title', Icons.auto_awesome_mosaic_outlined, "asset_list_settings_subtitle"), + beta('sync_status', Icons.sync_outlined, "sync_status_subtitle"); final String title; final String subtitle; final IconData icon; Widget get widget => switch (this) { - SettingSection.beta => const _BetaLandscapeToggle(), SettingSection.advanced => const AdvancedSettings(), SettingSection.assetViewer => const AssetViewerSettings(), SettingSection.backup => @@ -45,6 +43,7 @@ enum SettingSection { SettingSection.notifications => const NotificationSetting(), SettingSection.preferences => const PreferenceSetting(), SettingSection.timeline => const AssetListSettings(), + SettingSection.beta => const SyncStatusAndActions(), }; const SettingSection(this.title, this.icon, this.subtitle); @@ -59,7 +58,7 @@ class SettingsPage extends StatelessWidget { context.locale; return Scaffold( appBar: AppBar(centerTitle: false, title: const Text('settings').tr()), - body: context.isMobile ? const _MobileLayout() : const _TabletLayout(), + body: context.isMobile ? const SafeArea(child: _MobileLayout()) : const SafeArea(child: _TabletLayout()), ); } } @@ -72,13 +71,12 @@ class _MobileLayout extends StatelessWidget { .expand( (setting) => setting == SettingSection.beta ? [ - const BetaTimelineListTile(), if (Store.isBetaTimelineEnabled) SettingsCard( icon: Icons.sync_outlined, - title: 'beta_sync'.tr(), - subtitle: 'beta_sync_subtitle'.tr(), - settingRoute: const BetaSyncSettingsRoute(), + title: 'sync_status'.tr(), + subtitle: 'sync_status_subtitle'.tr(), + settingRoute: const SyncStatusRoute(), ), ] : [ @@ -93,7 +91,7 @@ class _MobileLayout extends StatelessWidget { .toList(); return ListView( physics: const ClampingScrollPhysics(), - padding: const EdgeInsets.only(top: 10.0, bottom: 56), + padding: const EdgeInsets.only(top: 10.0, bottom: 16), children: [...settings], ); } @@ -134,21 +132,6 @@ class _TabletLayout extends HookWidget { } } -class _BetaLandscapeToggle extends HookWidget { - const _BetaLandscapeToggle(); - - @override - Widget build(BuildContext context) { - return Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - const SizedBox(height: 100, child: BetaTimelineListTile()), - if (Store.isBetaTimelineEnabled) const Expanded(child: BetaSyncSettings()), - ], - ); - } -} - @RoutePage() class SettingsSubPage extends StatelessWidget { const SettingsSubPage(this.section, {super.key}); diff --git a/mobile/lib/pages/common/splash_screen.page.dart b/mobile/lib/pages/common/splash_screen.page.dart index 64db7daee6..29b3dcd3be 100644 --- a/mobile/lib/pages/common/splash_screen.page.dart +++ b/mobile/lib/pages/common/splash_screen.page.dart @@ -1,12 +1,14 @@ +import 'dart:async'; + import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/store.model.dart'; -import 'package:immich_mobile/domain/utils/isolate_lock_manager.dart'; import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/providers/auth.provider.dart'; import 'package:immich_mobile/providers/background_sync.provider.dart'; import 'package:immich_mobile/providers/backup/backup.provider.dart'; +import 'package:immich_mobile/providers/backup/drift_backup.provider.dart'; import 'package:immich_mobile/providers/gallery_permission.provider.dart'; import 'package:immich_mobile/providers/server_info.provider.dart'; import 'package:immich_mobile/providers/websocket.provider.dart'; @@ -27,19 +29,11 @@ class SplashScreenPageState extends ConsumerState { @override void initState() { super.initState(); - final lockManager = ref.read(isolateLockManagerProvider(kIsolateLockManagerPort)); - - lockManager.requestHolderToClose(); - lockManager - .acquireLock() - .timeout(const Duration(seconds: 5)) - .whenComplete( - () => ref - .read(authProvider.notifier) - .setOpenApiServiceEndpoint() - .then(logConnectionInfo) - .whenComplete(() => resumeSession()), - ); + ref + .read(authProvider.notifier) + .setOpenApiServiceEndpoint() + .then(logConnectionInfo) + .whenComplete(() => resumeSession()); } void logConnectionInfo(String? endpoint) { @@ -58,11 +52,37 @@ class SplashScreenPageState extends ConsumerState { if (accessToken != null && serverUrl != null && endpoint != null) { final infoProvider = ref.read(serverInfoProvider.notifier); final wsProvider = ref.read(websocketProvider.notifier); + final backgroundManager = ref.read(backgroundSyncProvider); + final backupProvider = ref.read(driftBackupProvider.notifier); + ref.read(authProvider.notifier).saveAuthInfo(accessToken: accessToken).then( - (a) { + (_) async { try { wsProvider.connect(); infoProvider.getServerInfo(); + + if (Store.isBetaTimelineEnabled) { + bool syncSuccess = false; + await Future.wait([ + backgroundManager.syncLocal(), + backgroundManager.syncRemote().then((success) => syncSuccess = success), + ]); + + if (syncSuccess) { + await Future.wait([ + backgroundManager.hashAssets().then((_) { + _resumeBackup(backupProvider); + }), + _resumeBackup(backupProvider), + ]); + } else { + await backgroundManager.hashAssets(); + } + + if (Store.get(StoreKey.syncAlbums, false)) { + await backgroundManager.syncLinkedAlbum(); + } + } } catch (e) { log.severe('Failed establishing connection to the server: $e'); } @@ -80,7 +100,16 @@ class SplashScreenPageState extends ConsumerState { return; } + // clean install - change the default of the flag + // current install not using beta timeline if (context.router.current.name == SplashScreenRoute.name) { + final needBetaMigration = Store.get(StoreKey.needBetaMigration, false); + if (needBetaMigration) { + await Store.put(StoreKey.needBetaMigration, false); + context.router.replaceAll([ChangeExperienceRoute(switchingToBeta: true)]); + return; + } + context.replaceRoute(Store.isBetaTimelineEnabled ? const TabShellRoute() : const TabControllerRoute()); } @@ -95,6 +124,17 @@ class SplashScreenPageState extends ConsumerState { } } + Future _resumeBackup(DriftBackupNotifier notifier) async { + final isEnableBackup = Store.get(StoreKey.enableBackup, false); + + if (isEnableBackup) { + final currentUser = Store.tryGet(StoreKey.currentUser); + if (currentUser != null) { + notifier.handleBackupResume(currentUser.id); + } + } + } + @override Widget build(BuildContext context) { return const Scaffold( diff --git a/mobile/lib/pages/common/tab_shell.page.dart b/mobile/lib/pages/common/tab_shell.page.dart index 8b68a8b9c0..b60fe1ddc1 100644 --- a/mobile/lib/pages/common/tab_shell.page.dart +++ b/mobile/lib/pages/common/tab_shell.page.dart @@ -7,8 +7,6 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/timeline.model.dart'; import 'package:immich_mobile/domain/utils/event_stream.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; -import 'package:immich_mobile/providers/app_settings.provider.dart'; -import 'package:immich_mobile/providers/backup/drift_backup.provider.dart'; import 'package:immich_mobile/providers/haptic_feedback.provider.dart'; import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; import 'package:immich_mobile/providers/infrastructure/memory.provider.dart'; @@ -17,11 +15,7 @@ import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.da import 'package:immich_mobile/providers/search/search_input_focus.provider.dart'; import 'package:immich_mobile/providers/tab.provider.dart'; import 'package:immich_mobile/providers/timeline/multiselect.provider.dart'; -import 'package:immich_mobile/providers/user.provider.dart'; -import 'package:immich_mobile/providers/websocket.provider.dart'; import 'package:immich_mobile/routing/router.dart'; -import 'package:immich_mobile/services/app_settings.service.dart'; -import 'package:immich_mobile/utils/migration.dart'; @RoutePage() class TabShellPage extends ConsumerStatefulWidget { @@ -32,28 +26,6 @@ class TabShellPage extends ConsumerStatefulWidget { } class _TabShellPageState extends ConsumerState { - @override - void initState() { - super.initState(); - - WidgetsBinding.instance.addPostFrameCallback((_) async { - ref.read(websocketProvider.notifier).connect(); - - final isEnableBackup = ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableBackup); - - await runNewSync(ref, full: true).then((_) async { - if (isEnableBackup) { - final currentUser = ref.read(currentUserProvider); - if (currentUser == null) { - return; - } - - await ref.read(driftBackupProvider.notifier).handleBackupResume(currentUser.id); - } - }); - }); - } - @override Widget build(BuildContext context) { final isScreenLandscape = context.orientation == Orientation.landscape; diff --git a/mobile/lib/pages/library/partner/drift_partner.page.dart b/mobile/lib/pages/library/partner/drift_partner.page.dart index 834e55ffd4..d81cc44c76 100644 --- a/mobile/lib/pages/library/partner/drift_partner.page.dart +++ b/mobile/lib/pages/library/partner/drift_partner.page.dart @@ -134,7 +134,7 @@ class _SharedToPartnerList extends ConsumerWidget { ); }, loading: () => const Center(child: CircularProgressIndicator()), - error: (error, stack) => Center(child: Text("Error loading partners: $error")), + error: (error, stack) => Center(child: Text('error_loading_partners'.tr(args: [error.toString()]))), ); } } diff --git a/mobile/lib/pages/library/places/places_collection.page.dart b/mobile/lib/pages/library/places/places_collection.page.dart index 73c38a109c..f376709316 100644 --- a/mobile/lib/pages/library/places/places_collection.page.dart +++ b/mobile/lib/pages/library/places/places_collection.page.dart @@ -85,7 +85,7 @@ class PlacesCollectionPage extends HookConsumerWidget { }, ); }, - error: (error, stask) => const Text('Error getting places'), + error: (error, stask) => Text('error_getting_places'.tr()), loading: () => const Center(child: CircularProgressIndicator()), ), ], diff --git a/mobile/lib/pages/library/shared_link/shared_link_edit.page.dart b/mobile/lib/pages/library/shared_link/shared_link_edit.page.dart index c78a9d5138..8b66bb231f 100644 --- a/mobile/lib/pages/library/shared_link/shared_link_edit.page.dart +++ b/mobile/lib/pages/library/shared_link/shared_link_edit.page.dart @@ -112,7 +112,7 @@ class SharedLinkEditPage extends HookConsumerWidget { return SwitchListTile.adaptive( value: showMetadata.value, onChanged: newShareLink.value.isEmpty ? (value) => showMetadata.value = value : null, - activeColor: colorScheme.primary, + activeThumbColor: colorScheme.primary, dense: true, title: Text("show_metadata", style: themeData.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold)).tr(), ); @@ -122,7 +122,7 @@ class SharedLinkEditPage extends HookConsumerWidget { return SwitchListTile.adaptive( value: allowDownload.value, onChanged: newShareLink.value.isEmpty ? (value) => allowDownload.value = value : null, - activeColor: colorScheme.primary, + activeThumbColor: colorScheme.primary, dense: true, title: Text( "allow_public_user_to_download", @@ -135,7 +135,7 @@ class SharedLinkEditPage extends HookConsumerWidget { return SwitchListTile.adaptive( value: allowUpload.value, onChanged: newShareLink.value.isEmpty ? (value) => allowUpload.value = value : null, - activeColor: colorScheme.primary, + activeThumbColor: colorScheme.primary, dense: true, title: Text( "allow_public_user_to_upload", @@ -148,7 +148,7 @@ class SharedLinkEditPage extends HookConsumerWidget { return SwitchListTile.adaptive( value: editExpiry.value, onChanged: newShareLink.value.isEmpty ? (value) => editExpiry.value = value : null, - activeColor: colorScheme.primary, + activeThumbColor: colorScheme.primary, dense: true, title: Text( "change_expiration_time", diff --git a/mobile/lib/pages/search/search.page.dart b/mobile/lib/pages/search/search.page.dart index 97205e000c..acfa2fd59f 100644 --- a/mobile/lib/pages/search/search.page.dart +++ b/mobile/lib/pages/search/search.page.dart @@ -435,7 +435,7 @@ class SearchPage extends HookConsumerWidget { } }, icon: const Icon(Icons.more_vert_rounded), - tooltip: 'Show text search menu', + tooltip: 'show_text_search_menu'.tr(), ); }, menuChildren: [ diff --git a/mobile/lib/pages/settings/beta_sync_settings.page.dart b/mobile/lib/pages/settings/sync_status.page.dart similarity index 71% rename from mobile/lib/pages/settings/beta_sync_settings.page.dart rename to mobile/lib/pages/settings/sync_status.page.dart index 992557b7c6..d54ba89e5d 100644 --- a/mobile/lib/pages/settings/beta_sync_settings.page.dart +++ b/mobile/lib/pages/settings/sync_status.page.dart @@ -1,25 +1,25 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart'; -import 'package:immich_mobile/widgets/settings/beta_sync_settings/beta_sync_settings.dart'; +import 'package:immich_mobile/widgets/settings/beta_sync_settings/sync_status_and_actions.dart'; @RoutePage() -class BetaSyncSettingsPage extends StatelessWidget { - const BetaSyncSettingsPage({super.key}); +class SyncStatusPage extends StatelessWidget { + const SyncStatusPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( elevation: 0, - title: const Text("beta_sync").t(context: context), + title: const Text("sync_status").t(context: context), leading: IconButton( onPressed: () => context.maybePop(true), splashRadius: 24, icon: const Icon(Icons.arrow_back_ios_rounded), ), ), - body: const BetaSyncSettings(), + body: const SyncStatusAndActions(), ); } } diff --git a/mobile/lib/platform/background_worker_api.g.dart b/mobile/lib/platform/background_worker_api.g.dart index 4b5689f4df..22325603c0 100644 --- a/mobile/lib/platform/background_worker_api.g.dart +++ b/mobile/lib/platform/background_worker_api.g.dart @@ -25,6 +25,57 @@ List wrapResponse({Object? result, PlatformException? error, bool empty return [error.code, error.message, error.details]; } +bool _deepEquals(Object? a, Object? b) { + if (a is List && b is List) { + return a.length == b.length && a.indexed.every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1])); + } + if (a is Map && b is Map) { + return a.length == b.length && + a.entries.every( + (MapEntry entry) => + (b as Map).containsKey(entry.key) && _deepEquals(entry.value, b[entry.key]), + ); + } + return a == b; +} + +class BackgroundWorkerSettings { + BackgroundWorkerSettings({required this.requiresCharging, required this.minimumDelaySeconds}); + + bool requiresCharging; + + int minimumDelaySeconds; + + List _toList() { + return [requiresCharging, minimumDelaySeconds]; + } + + Object encode() { + return _toList(); + } + + static BackgroundWorkerSettings decode(Object result) { + result as List; + return BackgroundWorkerSettings(requiresCharging: result[0]! as bool, minimumDelaySeconds: result[1]! as int); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! BackgroundWorkerSettings || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(encode(), other.encode()); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => Object.hashAll(_toList()); +} + class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -32,6 +83,9 @@ class _PigeonCodec extends StandardMessageCodec { if (value is int) { buffer.putUint8(4); buffer.putInt64(value); + } else if (value is BackgroundWorkerSettings) { + buffer.putUint8(129); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -40,6 +94,8 @@ class _PigeonCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { + case 129: + return BackgroundWorkerSettings.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); } @@ -82,6 +138,52 @@ class BackgroundWorkerFgHostApi { } } + Future saveNotificationMessage(String title, String body) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.saveNotificationMessage$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([title, body]); + final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } + + Future configure(BackgroundWorkerSettings settings) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.configure$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([settings]); + final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } + Future disable() async { final String pigeonVar_channelName = 'dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.disable$pigeonVar_messageChannelSuffix'; diff --git a/mobile/lib/platform/background_worker_lock_api.g.dart b/mobile/lib/platform/background_worker_lock_api.g.dart new file mode 100644 index 0000000000..9f00017dc8 --- /dev/null +++ b/mobile/lib/platform/background_worker_lock_api.g.dart @@ -0,0 +1,97 @@ +// Autogenerated from Pigeon (v26.0.0), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers + +import 'dart:async'; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; + +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; +import 'package:flutter/services.dart'; + +PlatformException _createConnectionError(String channelName) { + return PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); +} + +class _PigeonCodec extends StandardMessageCodec { + const _PigeonCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is int) { + buffer.putUint8(4); + buffer.putInt64(value); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + default: + return super.readValueOfType(type, buffer); + } + } +} + +class BackgroundWorkerLockApi { + /// Constructor for [BackgroundWorkerLockApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + BackgroundWorkerLockApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + final BinaryMessenger? pigeonVar_binaryMessenger; + + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); + + final String pigeonVar_messageChannelSuffix; + + Future lock() async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.immich_mobile.BackgroundWorkerLockApi.lock$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); + final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } + + Future unlock() async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.immich_mobile.BackgroundWorkerLockApi.unlock$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); + final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } +} diff --git a/mobile/lib/platform/connectivity_api.g.dart b/mobile/lib/platform/connectivity_api.g.dart new file mode 100644 index 0000000000..c348356f81 --- /dev/null +++ b/mobile/lib/platform/connectivity_api.g.dart @@ -0,0 +1,87 @@ +// Autogenerated from Pigeon (v26.0.0), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers + +import 'dart:async'; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; + +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; +import 'package:flutter/services.dart'; + +PlatformException _createConnectionError(String channelName) { + return PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); +} + +enum NetworkCapability { cellular, wifi, vpn, unmetered } + +class _PigeonCodec extends StandardMessageCodec { + const _PigeonCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is int) { + buffer.putUint8(4); + buffer.putInt64(value); + } else if (value is NetworkCapability) { + buffer.putUint8(129); + writeValue(buffer, value.index); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 129: + final int? value = readValue(buffer) as int?; + return value == null ? null : NetworkCapability.values[value]; + default: + return super.readValueOfType(type, buffer); + } + } +} + +class ConnectivityApi { + /// Constructor for [ConnectivityApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + ConnectivityApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + final BinaryMessenger? pigeonVar_binaryMessenger; + + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); + + final String pigeonVar_messageChannelSuffix; + + Future> getCapabilities() async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.immich_mobile.ConnectivityApi.getCapabilities$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); + final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as List?)!.cast(); + } + } +} diff --git a/mobile/lib/platform/native_sync_api.g.dart b/mobile/lib/platform/native_sync_api.g.dart index 6fc96f5046..01237f8c19 100644 --- a/mobile/lib/platform/native_sync_api.g.dart +++ b/mobile/lib/platform/native_sync_api.g.dart @@ -205,6 +205,45 @@ class SyncDelta { int get hashCode => Object.hashAll(_toList()); } +class HashResult { + HashResult({required this.assetId, this.error, this.hash}); + + String assetId; + + String? error; + + String? hash; + + List _toList() { + return [assetId, error, hash]; + } + + Object encode() { + return _toList(); + } + + static HashResult decode(Object result) { + result as List; + return HashResult(assetId: result[0]! as String, error: result[1] as String?, hash: result[2] as String?); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! HashResult || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(encode(), other.encode()); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => Object.hashAll(_toList()); +} + class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -221,6 +260,9 @@ class _PigeonCodec extends StandardMessageCodec { } else if (value is SyncDelta) { buffer.putUint8(131); writeValue(buffer, value.encode()); + } else if (value is HashResult) { + buffer.putUint8(132); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -235,6 +277,8 @@ class _PigeonCodec extends StandardMessageCodec { return PlatformAlbum.decode(readValue(buffer)!); case 131: return SyncDelta.decode(readValue(buffer)!); + case 132: + return HashResult.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); } @@ -468,15 +512,15 @@ class NativeSyncApi { } } - Future> hashPaths(List paths) async { + Future> hashAssets(List assetIds, {bool allowNetworkAccess = false}) async { final String pigeonVar_channelName = - 'dev.flutter.pigeon.immich_mobile.NativeSyncApi.hashPaths$pigeonVar_messageChannelSuffix'; + 'dev.flutter.pigeon.immich_mobile.NativeSyncApi.hashAssets$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([paths]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([assetIds, allowNetworkAccess]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -492,7 +536,30 @@ class NativeSyncApi { message: 'Host platform returned null value for non-null return value.', ); } else { - return (pigeonVar_replyList[0] as List?)!.cast(); + return (pigeonVar_replyList[0] as List?)!.cast(); + } + } + + Future cancelHashing() async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.immich_mobile.NativeSyncApi.cancelHashing$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); + final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; } } } diff --git a/mobile/lib/presentation/pages/dev/feat_in_development.page.dart b/mobile/lib/presentation/pages/dev/feat_in_development.page.dart index d3f0e3c1bc..491c38e7a8 100644 --- a/mobile/lib/presentation/pages/dev/feat_in_development.page.dart +++ b/mobile/lib/presentation/pages/dev/feat_in_development.page.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:auto_route/auto_route.dart'; import 'package:drift/drift.dart' hide Column; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; @@ -135,7 +136,7 @@ class FeatInDevPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text('Features in Development'), centerTitle: true), + appBar: AppBar(title: Text('features_in_development'.tr()), centerTitle: true), body: Column( children: [ Flexible( diff --git a/mobile/lib/presentation/pages/dev/main_timeline.page.dart b/mobile/lib/presentation/pages/dev/main_timeline.page.dart index 60a296a22c..5ec946858d 100644 --- a/mobile/lib/presentation/pages/dev/main_timeline.page.dart +++ b/mobile/lib/presentation/pages/dev/main_timeline.page.dart @@ -15,6 +15,7 @@ class MainTimelinePage extends ConsumerWidget { return Timeline( topSliverWidget: const SliverToBoxAdapter(child: DriftMemoryLane()), topSliverWidgetHeight: hasMemories ? 200 : 0, + showStorageIndicator: true, ); } } diff --git a/mobile/lib/presentation/pages/dev/media_stat.page.dart b/mobile/lib/presentation/pages/dev/media_stat.page.dart index b48d8fc307..4c18a09200 100644 --- a/mobile/lib/presentation/pages/dev/media_stat.page.dart +++ b/mobile/lib/presentation/pages/dev/media_stat.page.dart @@ -1,5 +1,6 @@ import 'package:auto_route/auto_route.dart'; import 'package:collection/collection.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; @@ -55,7 +56,7 @@ class LocalMediaSummaryPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text('Local Media Summary')), + appBar: AppBar(title: Text('local_media_summary'.tr())), body: Consumer( builder: (ctx, ref, __) { final db = ref.watch(driftProvider); @@ -78,7 +79,7 @@ class LocalMediaSummaryPage extends StatelessWidget { const Divider(), Padding( padding: const EdgeInsets.only(left: 15), - child: Text("Album summary", style: ctx.textTheme.titleMedium), + child: Text("album_summary".tr(), style: ctx.textTheme.titleMedium), ), ], ), @@ -135,7 +136,7 @@ class RemoteMediaSummaryPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text('Remote Media Summary')), + appBar: AppBar(title: Text('remote_media_summary'.tr())), body: Consumer( builder: (ctx, ref, __) { final db = ref.watch(driftProvider); @@ -158,7 +159,7 @@ class RemoteMediaSummaryPage extends StatelessWidget { const Divider(), Padding( padding: const EdgeInsets.only(left: 15), - child: Text("Album summary", style: ctx.textTheme.titleMedium), + child: Text("album_summary".tr(), style: ctx.textTheme.titleMedium), ), ], ), diff --git a/mobile/lib/presentation/pages/download_info.page.dart b/mobile/lib/presentation/pages/download_info.page.dart new file mode 100644 index 0000000000..e805458e76 --- /dev/null +++ b/mobile/lib/presentation/pages/download_info.page.dart @@ -0,0 +1,57 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_mobile/extensions/translate_extensions.dart'; +import 'package:immich_mobile/pages/common/download_panel.dart'; +import 'package:immich_mobile/providers/asset_viewer/download.provider.dart'; + +@RoutePage() +class DownloadInfoPage extends ConsumerWidget { + const DownloadInfoPage({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final tasks = ref.watch(downloadStateProvider.select((state) => state.taskProgress)).entries.toList(); + + onCancelDownload(String id) { + ref.watch(downloadStateProvider.notifier).cancelDownload(id); + } + + return Scaffold( + appBar: AppBar( + title: Text("download".t(context: context)), + actions: [], + ), + body: ListView.builder( + physics: const ClampingScrollPhysics(), + shrinkWrap: true, + itemCount: tasks.length, + itemBuilder: (context, index) { + final task = tasks[index]; + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0), + child: DownloadTaskTile( + progress: task.value.progress, + fileName: task.value.fileName, + status: task.value.status, + onCancelDownload: () => onCancelDownload(task.key), + ), + ); + }, + ), + persistentFooterButtons: [ + OutlinedButton( + onPressed: () { + tasks.map((e) => e.key).forEach(onCancelDownload); + }, + style: OutlinedButton.styleFrom(side: BorderSide(color: context.colorScheme.primary)), + child: Text( + 'clear_all'.t(context: context), + style: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.primary), + ), + ), + ], + ); + } +} diff --git a/mobile/lib/presentation/pages/drift_album_options.page.dart b/mobile/lib/presentation/pages/drift_album_options.page.dart index b8dcbd91f9..7f49a1ff79 100644 --- a/mobile/lib/presentation/pages/drift_album_options.page.dart +++ b/mobile/lib/presentation/pages/drift_album_options.page.dart @@ -208,7 +208,7 @@ class DriftAlbumOptionsPage extends HookConsumerWidget { activityEnabled.value = value; await ref.read(remoteAlbumProvider.notifier).setActivityStatus(album.id, value); }, - activeColor: activityEnabled.value ? context.primaryColor : context.themeData.disabledColor, + activeThumbColor: activityEnabled.value ? context.primaryColor : context.themeData.disabledColor, dense: true, title: Text( "comments_and_likes", diff --git a/mobile/lib/presentation/pages/drift_asset_troubleshoot.page.dart b/mobile/lib/presentation/pages/drift_asset_troubleshoot.page.dart new file mode 100644 index 0000000000..7a899f4e72 --- /dev/null +++ b/mobile/lib/presentation/pages/drift_asset_troubleshoot.page.dart @@ -0,0 +1,352 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; +import 'package:immich_mobile/domain/models/exif.model.dart'; +import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; + +@RoutePage() +class AssetTroubleshootPage extends ConsumerWidget { + final BaseAsset asset; + + const AssetTroubleshootPage({super.key, required this.asset}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return Scaffold( + appBar: AppBar(title: Text('asset_troubleshoot'.tr())), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: _AssetDetailsView(asset: asset), + ), + ), + ); + } +} + +class _AssetDetailsView extends ConsumerWidget { + final BaseAsset asset; + + const _AssetDetailsView({required this.asset}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _AssetPropertiesSection(asset: asset), + const SizedBox(height: 16), + Text( + 'matching_assets'.tr(), + style: Theme.of(context).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold), + ), + if (asset.checksum != null) ...[ + _LocalAssetsSection(asset: asset), + const SizedBox(height: 16), + _RemoteAssetSection(asset: asset), + ] else ...[ + _PropertySectionCard( + title: 'Local Assets', + properties: [_PropertyItem(label: 'Status', value: 'no_checksum_local'.tr())], + ), + const SizedBox(height: 16), + _PropertySectionCard( + title: 'Remote Assets', + properties: [_PropertyItem(label: 'Status', value: 'no_checksum_remote'.tr())], + ), + ], + ], + ); + } +} + +class _AssetPropertiesSection extends ConsumerStatefulWidget { + final BaseAsset asset; + + const _AssetPropertiesSection({required this.asset}); + + @override + ConsumerState createState() => _AssetPropertiesSectionState(); +} + +class _AssetPropertiesSectionState extends ConsumerState<_AssetPropertiesSection> { + List<_PropertyItem> properties = []; + + @override + void initState() { + super.initState(); + _buildAssetProperties(widget.asset).whenComplete(() { + if (mounted) { + setState(() {}); + } + }); + } + + @override + Widget build(BuildContext context) { + final title = _getAssetTypeTitle(widget.asset); + + return _PropertySectionCard(title: title, properties: properties); + } + + Future _buildAssetProperties(BaseAsset asset) async { + _addCommonProperties(); + + if (asset is LocalAsset) { + await _addLocalAssetProperties(asset); + } else if (asset is RemoteAsset) { + await _addRemoteAssetProperties(asset); + } + } + + void _addCommonProperties() { + final asset = widget.asset; + properties.addAll([ + _PropertyItem(label: 'Name', value: asset.name), + _PropertyItem(label: 'Checksum', value: asset.checksum), + _PropertyItem(label: 'Type', value: asset.type.toString()), + _PropertyItem(label: 'Created At', value: asset.createdAt.toString()), + _PropertyItem(label: 'Updated At', value: asset.updatedAt.toString()), + _PropertyItem(label: 'Width', value: asset.width?.toString()), + _PropertyItem(label: 'Height', value: asset.height?.toString()), + _PropertyItem( + label: 'Duration', + value: asset.durationInSeconds != null ? '${asset.durationInSeconds} seconds' : null, + ), + _PropertyItem(label: 'Is Favorite', value: asset.isFavorite.toString()), + _PropertyItem(label: 'Live Photo Video ID', value: asset.livePhotoVideoId), + ]); + } + + Future _addLocalAssetProperties(LocalAsset asset) async { + properties.insertAll(0, [ + _PropertyItem(label: 'Local ID', value: asset.id), + _PropertyItem(label: 'Remote ID', value: asset.remoteId), + ]); + + properties.insert(4, _PropertyItem(label: 'Orientation', value: asset.orientation.toString())); + final albums = await ref.read(assetServiceProvider).getSourceAlbums(asset.id); + properties.add(_PropertyItem(label: 'Album', value: albums.map((a) => a.name).join(', '))); + } + + Future _addRemoteAssetProperties(RemoteAsset asset) async { + properties.insertAll(0, [ + _PropertyItem(label: 'Remote ID', value: asset.id), + _PropertyItem(label: 'Local ID', value: asset.localId), + _PropertyItem(label: 'Owner ID', value: asset.ownerId), + ]); + + final additionalProps = <_PropertyItem>[ + _PropertyItem(label: 'Thumb Hash', value: asset.thumbHash), + _PropertyItem(label: 'Visibility', value: asset.visibility.toString()), + _PropertyItem(label: 'Stack ID', value: asset.stackId), + ]; + + properties.insertAll(4, additionalProps); + + final exif = await ref.read(assetServiceProvider).getExif(asset); + if (exif != null) { + _addExifProperties(exif); + } else { + properties.add(const _PropertyItem(label: 'EXIF', value: null)); + } + } + + void _addExifProperties(ExifInfo exif) { + properties.addAll([ + _PropertyItem( + label: 'File Size', + value: exif.fileSize != null ? '${(exif.fileSize! / 1024 / 1024).toStringAsFixed(2)} MB' : null, + ), + _PropertyItem(label: 'Description', value: exif.description), + _PropertyItem(label: 'EXIF Width', value: exif.width?.toString()), + _PropertyItem(label: 'EXIF Height', value: exif.height?.toString()), + _PropertyItem(label: 'Date Taken', value: exif.dateTimeOriginal?.toString()), + _PropertyItem(label: 'Time Zone', value: exif.timeZone), + _PropertyItem(label: 'Camera Make', value: exif.make), + _PropertyItem(label: 'Camera Model', value: exif.model), + _PropertyItem(label: 'Lens', value: exif.lens), + _PropertyItem(label: 'F-Number', value: exif.f != null ? 'f/${exif.fNumber}' : null), + _PropertyItem(label: 'Focal Length', value: exif.mm != null ? '${exif.focalLength}mm' : null), + _PropertyItem(label: 'ISO', value: exif.iso?.toString()), + _PropertyItem(label: 'Exposure Time', value: exif.exposureTime.isNotEmpty ? exif.exposureTime : null), + _PropertyItem( + label: 'GPS Coordinates', + value: exif.hasCoordinates ? '${exif.latitude}, ${exif.longitude}' : null, + ), + _PropertyItem( + label: 'Location', + value: [exif.city, exif.state, exif.country].where((e) => e != null && e.isNotEmpty).join(', '), + ), + ]); + } + + String _getAssetTypeTitle(BaseAsset asset) { + if (asset is LocalAsset) return 'Local Asset'; + if (asset is RemoteAsset) return 'Remote Asset'; + return 'Base Asset'; + } +} + +class _LocalAssetsSection extends ConsumerWidget { + final BaseAsset asset; + + const _LocalAssetsSection({required this.asset}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final assetService = ref.watch(assetServiceProvider); + + return FutureBuilder>( + future: assetService.getLocalAssetsByChecksum(asset.checksum!), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const _PropertySectionCard( + title: 'Local Assets', + properties: [_PropertyItem(label: 'Status', value: 'Loading...')], + ); + } + + if (snapshot.hasError) { + return _PropertySectionCard( + title: 'Local Assets', + properties: [_PropertyItem(label: 'Error', value: snapshot.error.toString())], + ); + } + + final localAssets = snapshot.data?.cast() ?? []; + if (asset is LocalAsset) { + localAssets.removeWhere((a) => a.id == (asset as LocalAsset).id); + + if (localAssets.isEmpty) { + return const SizedBox.shrink(); + } + } + + if (localAssets.isEmpty) { + return _PropertySectionCard( + title: 'Local Assets', + properties: [_PropertyItem(label: 'Status', value: 'no_local_assets_found'.tr())], + ); + } + + return Column( + children: [ + if (localAssets.length > 1) + _PropertySectionCard( + title: 'Local Assets Summary', + properties: [_PropertyItem(label: 'Total Count', value: localAssets.length.toString())], + ), + ...localAssets.map((localAsset) { + return Padding( + padding: const EdgeInsets.only(top: 16), + child: _AssetPropertiesSection(asset: localAsset), + ); + }), + ], + ); + }, + ); + } +} + +class _RemoteAssetSection extends ConsumerWidget { + final BaseAsset asset; + + const _RemoteAssetSection({required this.asset}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final assetService = ref.watch(assetServiceProvider); + + if (asset is RemoteAsset) { + return const SizedBox.shrink(); + } + + return FutureBuilder( + future: assetService.getRemoteAssetByChecksum(asset.checksum!), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const _PropertySectionCard( + title: 'Remote Assets', + properties: [_PropertyItem(label: 'Status', value: 'Loading...')], + ); + } + + if (snapshot.hasError) { + return _PropertySectionCard( + title: 'Remote Assets', + properties: [_PropertyItem(label: 'Error', value: snapshot.error.toString())], + ); + } + + final remoteAsset = snapshot.data; + + if (remoteAsset == null) { + return _PropertySectionCard( + title: 'Remote Assets', + properties: [_PropertyItem(label: 'Status', value: 'no_remote_assets_found'.tr())], + ); + } + + return _AssetPropertiesSection(asset: remoteAsset); + }, + ); + } +} + +class _PropertySectionCard extends StatelessWidget { + final String title; + final List<_PropertyItem> properties; + + const _PropertySectionCard({required this.title, required this.properties}); + + @override + Widget build(BuildContext context) { + return Card( + margin: const EdgeInsets.symmetric(vertical: 8), + child: Padding( + padding: const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(title, style: Theme.of(context).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold)), + const SizedBox(height: 8), + ...properties, + ], + ), + ), + ); + } +} + +class _PropertyItem extends StatelessWidget { + final String label; + final String? value; + + const _PropertyItem({required this.label, this.value}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: 120, + child: Text('$label:', style: const TextStyle(fontWeight: FontWeight.w500)), + ), + Expanded( + child: Text( + value ?? 'not_available'.tr(), + style: TextStyle(color: Theme.of(context).colorScheme.secondary), + ), + ), + ], + ), + ); + } +} diff --git a/mobile/lib/presentation/pages/drift_library.page.dart b/mobile/lib/presentation/pages/drift_library.page.dart index af7014bbdc..d1d663e4f4 100644 --- a/mobile/lib/presentation/pages/drift_library.page.dart +++ b/mobile/lib/presentation/pages/drift_library.page.dart @@ -1,4 +1,5 @@ import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/user.model.dart'; @@ -302,7 +303,9 @@ class _LocalAlbumsCollectionCard extends ConsumerWidget { }).toList(); }, error: (error, _) { - return [Center(child: Text('Error: $error'))]; + return [ + Center(child: Text('error_saving_image'.tr(args: [error.toString()]))), + ]; }, loading: () { return [const Center(child: CircularProgressIndicator())]; diff --git a/mobile/lib/presentation/pages/drift_local_album.page.dart b/mobile/lib/presentation/pages/drift_local_album.page.dart index 536d9d82e2..6b133f7a6f 100644 --- a/mobile/lib/presentation/pages/drift_local_album.page.dart +++ b/mobile/lib/presentation/pages/drift_local_album.page.dart @@ -1,4 +1,5 @@ import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; @@ -46,9 +47,9 @@ class _AlbumList extends ConsumerWidget { ), data: (albums) { if (albums.isEmpty) { - return const SliverToBoxAdapter( + return SliverToBoxAdapter( child: Center( - child: Padding(padding: EdgeInsets.all(20.0), child: Text('No albums found')), + child: Padding(padding: const EdgeInsets.all(20.0), child: Text('no_albums_yet'.tr())), ), ); } diff --git a/mobile/lib/presentation/pages/drift_map.page.dart b/mobile/lib/presentation/pages/drift_map.page.dart index 30da6410b5..de8dde7714 100644 --- a/mobile/lib/presentation/pages/drift_map.page.dart +++ b/mobile/lib/presentation/pages/drift_map.page.dart @@ -25,9 +25,10 @@ class DriftMapPage extends StatelessWidget { onPressed: () => context.pop(), icon: const Icon(Icons.arrow_back_ios_new_rounded), style: IconButton.styleFrom( - shape: const CircleBorder(side: BorderSide(width: 1, color: Colors.black26)), padding: const EdgeInsets.all(8), - backgroundColor: Colors.indigo.withValues(alpha: 0.7), + backgroundColor: Colors.indigo, + shadowColor: Colors.black26, + elevation: 4, ), ), ), diff --git a/mobile/lib/presentation/pages/drift_partner_detail.page.dart b/mobile/lib/presentation/pages/drift_partner_detail.page.dart index 95c5b008b3..f8a19b6b70 100644 --- a/mobile/lib/presentation/pages/drift_partner_detail.page.dart +++ b/mobile/lib/presentation/pages/drift_partner_detail.page.dart @@ -10,6 +10,7 @@ import 'package:immich_mobile/providers/infrastructure/user.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart'; import 'package:immich_mobile/widgets/common/mesmerizing_sliver_app_bar.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; @RoutePage() class DriftPartnerDetailPage extends StatelessWidget { @@ -68,7 +69,7 @@ class _InfoBoxState extends ConsumerState<_InfoBox> { _inTimeline = !_inTimeline; }); } catch (error, stack) { - debugPrint("Failed to toggle in timeline: $error $stack"); + dPrint(() => "Failed to toggle in timeline: $error $stack"); ImmichToast.show( context: context, toastType: ToastType.error, diff --git a/mobile/lib/presentation/pages/drift_remote_album.page.dart b/mobile/lib/presentation/pages/drift_remote_album.page.dart index e0fe5ee62b..23d82dcb92 100644 --- a/mobile/lib/presentation/pages/drift_remote_album.page.dart +++ b/mobile/lib/presentation/pages/drift_remote_album.page.dart @@ -169,9 +169,11 @@ class _RemoteAlbumPageState extends ConsumerState { context.pushRoute(const DriftActivitiesRoute()); } - void showOptionSheet(BuildContext context) { + Future showOptionSheet(BuildContext context) async { final user = ref.watch(currentUserProvider); final isOwner = user != null ? user.id == _album.ownerId : false; + final canAddPhotos = + await ref.read(remoteAlbumServiceProvider).getUserRole(_album.id, user?.id ?? '') == AlbumUserRole.editor; showModalBottomSheet( context: context, @@ -193,22 +195,30 @@ class _RemoteAlbumPageState extends ConsumerState { context.pop(); } : null, - onAddPhotos: () async { - await addAssets(context); - context.pop(); - }, - onToggleAlbumOrder: () async { - await toggleAlbumOrder(); - context.pop(); - }, - onEditAlbum: () async { - context.pop(); - await showEditTitleAndDescription(context); - }, - onCreateSharedLink: () async { - context.pop(); - context.pushRoute(SharedLinkEditRoute(albumId: _album.id)); - }, + onAddPhotos: isOwner || canAddPhotos + ? () async { + await addAssets(context); + context.pop(); + } + : null, + onToggleAlbumOrder: isOwner + ? () async { + await toggleAlbumOrder(); + context.pop(); + } + : null, + onEditAlbum: isOwner + ? () async { + context.pop(); + await showEditTitleAndDescription(context); + } + : null, + onCreateSharedLink: isOwner + ? () async { + context.pop(); + context.pushRoute(SharedLinkEditRoute(albumId: _album.id)); + } + : null, onShowOptions: () { context.pop(); context.pushRoute(const DriftAlbumOptionsRoute()); @@ -220,6 +230,9 @@ class _RemoteAlbumPageState extends ConsumerState { @override Widget build(BuildContext context) { + final user = ref.watch(currentUserProvider); + final isOwner = user != null ? user.id == _album.ownerId : false; + return PopScope( onPopInvokedWithResult: (didPop, _) { if (didPop) { @@ -243,8 +256,8 @@ class _RemoteAlbumPageState extends ConsumerState { appBar: RemoteAlbumSliverAppBar( icon: Icons.photo_album_outlined, onShowOptions: () => showOptionSheet(context), - onToggleAlbumOrder: () => toggleAlbumOrder(), - onEditTitle: () => showEditTitleAndDescription(context), + onToggleAlbumOrder: isOwner ? () => toggleAlbumOrder() : null, + onEditTitle: isOwner ? () => showEditTitleAndDescription(context) : null, onActivity: () => showActivity(context), ), bottomSheet: RemoteAlbumBottomSheet(album: _album), @@ -300,7 +313,7 @@ class _EditAlbumDialogState extends ConsumerState<_EditAlbumDialog> { await ref .read(remoteAlbumProvider.notifier) - .updateAlbum(widget.album.id, name: newTitle, description: newDescription.isEmpty ? null : newDescription); + .updateAlbum(widget.album.id, name: newTitle, description: newDescription); if (mounted) { Navigator.of( diff --git a/mobile/lib/presentation/pages/drift_trash.page.dart b/mobile/lib/presentation/pages/drift_trash.page.dart index 43e9217cdf..8713166027 100644 --- a/mobile/lib/presentation/pages/drift_trash.page.dart +++ b/mobile/lib/presentation/pages/drift_trash.page.dart @@ -44,10 +44,7 @@ class DriftTrashPage extends StatelessWidget { return SliverPadding( padding: const EdgeInsets.all(16.0), sliver: SliverToBoxAdapter( - child: SizedBox( - height: 24.0, - child: const Text("trash_page_info").t(context: context, args: {"days": "$trashDays"}), - ), + child: const Text("trash_page_info").t(context: context, args: {"days": "$trashDays"}), ), ); }, diff --git a/mobile/lib/presentation/pages/drift_user_selection.page.dart b/mobile/lib/presentation/pages/drift_user_selection.page.dart index 5bd32aaf81..b73913fd02 100644 --- a/mobile/lib/presentation/pages/drift_user_selection.page.dart +++ b/mobile/lib/presentation/pages/drift_user_selection.page.dart @@ -3,9 +3,8 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:immich_mobile/domain/models/user.model.dart'; import 'package:immich_mobile/domain/models/album/album.model.dart'; -import 'package:immich_mobile/domain/models/user_metadata.model.dart'; +import 'package:immich_mobile/domain/models/user.model.dart'; import 'package:immich_mobile/extensions/asyncvalue_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; @@ -26,11 +25,9 @@ final driftUsersProvider = FutureProvider.autoDispose>((ref) async id: entity.id, name: entity.name, email: entity.email, - isAdmin: entity.isAdmin, - updatedAt: entity.updatedAt, isPartnerSharedBy: false, isPartnerSharedWith: false, - avatarColor: AvatarColor.primary, + avatarColor: entity.avatarColor, memoryEnabled: true, inTimeline: true, profileChangedAt: entity.profileChangedAt, diff --git a/mobile/lib/presentation/pages/editing/drift_edit.page.dart b/mobile/lib/presentation/pages/editing/drift_edit.page.dart index da62d49b49..e24a1967f2 100644 --- a/mobile/lib/presentation/pages/editing/drift_edit.page.dart +++ b/mobile/lib/presentation/pages/editing/drift_edit.page.dart @@ -50,6 +50,11 @@ class DriftEditImagePage extends ConsumerWidget { return completer.future; } + void _exitEditing(BuildContext context) { + // this assumes that the only way to get to this page is from the AssetViewerRoute + context.navigator.popUntil((route) => route.data?.name == AssetViewerRoute.name); + } + Future _saveEditedImage(BuildContext context, BaseAsset asset, Image image, WidgetRef ref) async { try { final Uint8List imageData = await _imageToUint8List(image); @@ -66,7 +71,7 @@ class DriftEditImagePage extends ConsumerWidget { } ref.read(backgroundSyncProvider).syncLocal(full: true); - context.navigator.popUntil((route) => route.isFirst); + _exitEditing(context); ImmichToast.show(durationInSecond: 3, context: context, msg: 'Image Saved!'); if (localAsset == null) { @@ -91,7 +96,7 @@ class DriftEditImagePage extends ConsumerWidget { backgroundColor: context.scaffoldBackgroundColor, leading: IconButton( icon: Icon(Icons.close_rounded, color: context.primaryColor, size: 24), - onPressed: () => context.navigator.popUntil((route) => route.isFirst), + onPressed: () => _exitEditing(context), ), actions: [ TextButton( diff --git a/mobile/lib/presentation/pages/local_timeline.page.dart b/mobile/lib/presentation/pages/local_timeline.page.dart index c53b18d9e7..67bc17cb37 100644 --- a/mobile/lib/presentation/pages/local_timeline.page.dart +++ b/mobile/lib/presentation/pages/local_timeline.page.dart @@ -26,6 +26,7 @@ class LocalTimelinePage extends StatelessWidget { child: Timeline( appBar: MesmerizingSliverAppBar(title: album.name), bottomSheet: const LocalAlbumBottomSheet(), + showStorageIndicator: true, ), ); } diff --git a/mobile/lib/presentation/pages/search/drift_search.page.dart b/mobile/lib/presentation/pages/search/drift_search.page.dart index d44b215b03..425c4985e9 100644 --- a/mobile/lib/presentation/pages/search/drift_search.page.dart +++ b/mobile/lib/presentation/pages/search/drift_search.page.dart @@ -8,6 +8,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/domain/models/person.model.dart'; import 'package:immich_mobile/domain/models/timeline.model.dart'; +import 'package:immich_mobile/domain/services/timeline.service.dart'; import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart'; @@ -440,7 +441,7 @@ class DriftSearchPage extends HookConsumerWidget { } }, icon: const Icon(Icons.more_vert_rounded), - tooltip: 'Show text search menu', + tooltip: 'show_text_search_menu'.tr(), ); }, menuChildren: [ @@ -599,9 +600,9 @@ class _SearchResultGrid extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final searchResult = ref.watch(paginatedSearchProvider); + final assets = ref.watch(paginatedSearchProvider.select((s) => s.assets)); - if (searchResult.totalAssets == 0) { + if (assets.isEmpty) { return const _SearchEmptyContent(); } @@ -615,6 +616,7 @@ class _SearchResultGrid extends ConsumerWidget { if (metrics.pixels >= metrics.maxScrollExtent && isVerticalScroll && !isBottomSheetNotification) { onScrollEnd(); + ref.read(paginatedSearchProvider.notifier).setScrollOffset(metrics.maxScrollExtent); } return true; @@ -623,16 +625,18 @@ class _SearchResultGrid extends ConsumerWidget { child: ProviderScope( overrides: [ timelineServiceProvider.overrideWith((ref) { - final timelineService = ref.watch(timelineFactoryProvider).fromAssets(searchResult.assets); + final timelineService = ref.watch(timelineFactoryProvider).fromAssets(assets, TimelineOrigin.search); ref.onDispose(timelineService.dispose); return timelineService; }), ], child: Timeline( - key: ValueKey(searchResult.totalAssets), + key: ValueKey(assets.length), groupBy: GroupAssetsBy.none, appBar: null, bottomSheet: const GeneralBottomSheet(minChildSize: 0.20), + snapToMonth: false, + initialScrollOffset: ref.read(paginatedSearchProvider.select((s) => s.scrollOffset)), ), ), ), diff --git a/mobile/lib/presentation/pages/search/paginated_search.provider.dart b/mobile/lib/presentation/pages/search/paginated_search.provider.dart index 718a241ba4..c0c822198d 100644 --- a/mobile/lib/presentation/pages/search/paginated_search.provider.dart +++ b/mobile/lib/presentation/pages/search/paginated_search.provider.dart @@ -24,12 +24,20 @@ class PaginatedSearchNotifier extends StateNotifier { return false; } - state = SearchResult(assets: [...state.assets, ...result.assets], nextPage: result.nextPage); + state = SearchResult( + assets: [...state.assets, ...result.assets], + nextPage: result.nextPage, + scrollOffset: state.scrollOffset, + ); return true; } + void setScrollOffset(double offset) { + state = state.copyWith(scrollOffset: offset); + } + clear() { - state = const SearchResult(assets: [], nextPage: 1); + state = const SearchResult(assets: [], nextPage: 1, scrollOffset: 0.0); } } diff --git a/mobile/lib/presentation/widgets/action_buttons/advanced_info_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/advanced_info_action_button.widget.dart new file mode 100644 index 0000000000..170f827fdb --- /dev/null +++ b/mobile/lib/presentation/widgets/action_buttons/advanced_info_action_button.widget.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/constants/enums.dart'; +import 'package:immich_mobile/extensions/translate_extensions.dart'; +import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart'; +import 'package:immich_mobile/providers/infrastructure/action.provider.dart'; + +class AdvancedInfoActionButton extends ConsumerWidget { + final ActionSource source; + + const AdvancedInfoActionButton({super.key, required this.source}); + + void _onTap(BuildContext context, WidgetRef ref) async { + if (!context.mounted) { + return; + } + + ref.read(actionProvider.notifier).troubleshoot(source, context); + } + + @override + Widget build(BuildContext context, WidgetRef ref) { + return BaseActionButton( + maxWidth: 115.0, + iconData: Icons.help_outline_rounded, + label: "troubleshoot".t(context: context), + onPressed: () => _onTap(context, ref), + ); + } +} diff --git a/mobile/lib/presentation/widgets/action_buttons/delete_local_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/delete_local_action_button.widget.dart index cccdee9b3a..9445daa2ad 100644 --- a/mobile/lib/presentation/widgets/action_buttons/delete_local_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/delete_local_action_button.widget.dart @@ -8,6 +8,7 @@ import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_bu import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_viewer.state.dart'; import 'package:immich_mobile/providers/infrastructure/action.provider.dart'; import 'package:immich_mobile/providers/timeline/multiselect.provider.dart'; +import 'package:immich_mobile/widgets/asset_grid/delete_dialog.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart'; /// This delete action has the following behavior: @@ -22,7 +23,17 @@ class DeleteLocalActionButton extends ConsumerWidget { return; } - final result = await ref.read(actionProvider.notifier).deleteLocal(source); + bool? backedUpOnly = await showDialog( + context: context, + builder: (BuildContext context) => DeleteLocalOnlyDialog(onDeleteLocal: (_) {}), + ); + + if (backedUpOnly == null) { + // User cancelled the dialog + return; + } + + final result = await ref.read(actionProvider.notifier).deleteLocal(source, backedUpOnly); ref.read(multiSelectProvider.notifier).reset(); if (source == ActionSource.viewer) { diff --git a/mobile/lib/presentation/widgets/action_buttons/download_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/download_action_button.widget.dart index 7c0db5ed9a..cb898f069a 100644 --- a/mobile/lib/presentation/widgets/action_buttons/download_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/download_action_button.widget.dart @@ -1,54 +1,45 @@ -import 'package:fluttertoast/fluttertoast.dart'; import 'package:immich_mobile/constants/enums.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/domain/utils/background_sync.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart'; +import 'package:immich_mobile/providers/background_sync.provider.dart'; import 'package:immich_mobile/providers/infrastructure/action.provider.dart'; import 'package:immich_mobile/providers/timeline/multiselect.provider.dart'; -import 'package:immich_mobile/widgets/common/immich_toast.dart'; class DownloadActionButton extends ConsumerWidget { final ActionSource source; + final bool menuItem; + const DownloadActionButton({super.key, required this.source, this.menuItem = false}); - const DownloadActionButton({super.key, required this.source}); - - void _onTap(BuildContext context, WidgetRef ref) async { + void _onTap(BuildContext context, WidgetRef ref, BackgroundSyncManager backgroundSyncManager) async { if (!context.mounted) { return; } - final result = await ref.read(actionProvider.notifier).downloadAll(source); - ref.read(multiSelectProvider.notifier).reset(); + try { + await ref.read(actionProvider.notifier).downloadAll(source); - if (!context.mounted) { - return; - } - - if (!result.success) { - ImmichToast.show( - context: context, - msg: 'scaffold_body_error_occurred'.t(context: context), - gravity: ToastGravity.BOTTOM, - toastType: ToastType.error, - ); - } else if (result.count > 0) { - ImmichToast.show( - context: context, - msg: 'download_action_prompt'.t(context: context, args: {'count': result.count.toString()}), - gravity: ToastGravity.BOTTOM, - toastType: ToastType.success, - ); + Future.delayed(const Duration(seconds: 1), () async { + await backgroundSyncManager.syncLocal(); + await backgroundSyncManager.hashAssets(); + }); + } finally { + ref.read(multiSelectProvider.notifier).reset(); } } @override Widget build(BuildContext context, WidgetRef ref) { + final backgroundManager = ref.watch(backgroundSyncProvider); + return BaseActionButton( iconData: Icons.download, maxWidth: 95, label: "download".t(context: context), - onPressed: () => _onTap(context, ref), + menuItem: menuItem, + onPressed: () => _onTap(context, ref, backgroundManager), ); } } diff --git a/mobile/lib/presentation/widgets/action_buttons/download_status_floating_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/download_status_floating_button.widget.dart new file mode 100644 index 0000000000..efa7f5c6d0 --- /dev/null +++ b/mobile/lib/presentation/widgets/action_buttons/download_status_floating_button.widget.dart @@ -0,0 +1,64 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_mobile/providers/asset_viewer/download.provider.dart'; +import 'package:immich_mobile/routing/router.dart'; + +class DownloadStatusFloatingButton extends ConsumerWidget { + const DownloadStatusFloatingButton({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final shouldShow = ref.watch(downloadStateProvider.select((state) => state.showProgress)); + final itemCount = ref.watch(downloadStateProvider.select((state) => state.taskProgress.length)); + final isDownloading = ref + .watch(downloadStateProvider.select((state) => state.taskProgress)) + .values + .where((element) => element.progress != 1) + .isNotEmpty; + + return shouldShow + ? Badge.count( + count: itemCount, + textColor: context.colorScheme.onPrimary, + backgroundColor: context.colorScheme.primary, + child: FloatingActionButton( + shape: RoundedRectangleBorder( + borderRadius: const BorderRadius.all(Radius.circular(20)), + side: BorderSide(color: context.colorScheme.outlineVariant, width: 1), + ), + backgroundColor: context.isDarkTheme + ? context.colorScheme.surfaceContainer + : context.colorScheme.surfaceBright, + elevation: 2, + onPressed: () { + context.pushRoute(const DownloadInfoRoute()); + }, + child: Stack( + alignment: AlignmentDirectional.center, + children: [ + isDownloading + ? Icon(Icons.downloading_rounded, color: context.colorScheme.primary, size: 28) + : Icon( + Icons.download_done, + color: context.isDarkTheme ? Colors.green[200] : Colors.green[400], + size: 28, + ), + if (isDownloading) + const SizedBox( + height: 31, + width: 31, + child: CircularProgressIndicator( + strokeWidth: 2, + backgroundColor: Colors.transparent, + value: null, // Indeterminate progress + ), + ), + ], + ), + ), + ) + : const SizedBox.shrink(); + } +} diff --git a/mobile/lib/presentation/widgets/action_buttons/edit_image_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/edit_image_action_button.widget.dart index cde0db8e18..4c7b6ffbdc 100644 --- a/mobile/lib/presentation/widgets/action_buttons/edit_image_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/edit_image_action_button.widget.dart @@ -1,11 +1,11 @@ +import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart'; -import 'package:immich_mobile/presentation/pages/editing/drift_edit.page.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/images/image_provider.dart'; import 'package:immich_mobile/providers/infrastructure/asset_viewer/current_asset.provider.dart'; +import 'package:immich_mobile/routing/router.dart'; class EditImageActionButton extends ConsumerWidget { const EditImageActionButton({super.key}); @@ -20,12 +20,7 @@ class EditImageActionButton extends ConsumerWidget { } final image = Image(image: getFullImageProvider(currentAsset)); - - context.navigator.push( - MaterialPageRoute( - builder: (context) => DriftEditImagePage(asset: currentAsset, image: image, isEdited: false), - ), - ); + context.pushRoute(DriftEditImageRoute(asset: currentAsset, image: image, isEdited: false)); } return BaseActionButton( diff --git a/mobile/lib/presentation/widgets/action_buttons/like_activity_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/like_activity_action_button.widget.dart index d143f600ce..33794eae11 100644 --- a/mobile/lib/presentation/widgets/action_buttons/like_activity_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/like_activity_action_button.widget.dart @@ -1,4 +1,5 @@ import 'package:collection/collection.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; @@ -58,7 +59,7 @@ class LikeActivityActionButton extends ConsumerWidget { label: "like".t(context: context), menuItem: menuItem, ), - error: (error, stack) => Text("Error: $error"), + error: (error, stack) => Text('error_saving_image'.tr(args: [error.toString()])), ); } } diff --git a/mobile/lib/presentation/widgets/action_buttons/share_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/share_action_button.widget.dart index 3c943f0501..740ac528b0 100644 --- a/mobile/lib/presentation/widgets/action_buttons/share_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/share_action_button.widget.dart @@ -42,7 +42,7 @@ class ShareActionButton extends ConsumerWidget { showDialog( context: context, builder: (BuildContext buildContext) { - ref.read(actionProvider.notifier).shareAssets(source).then((ActionResult result) { + ref.read(actionProvider.notifier).shareAssets(source, context).then((ActionResult result) { ref.read(multiSelectProvider.notifier).reset(); if (!context.mounted) { diff --git a/mobile/lib/presentation/widgets/action_buttons/unstack_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/unstack_action_button.widget.dart index ecc8a39c74..a07803ace5 100644 --- a/mobile/lib/presentation/widgets/action_buttons/unstack_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/unstack_action_button.widget.dart @@ -36,7 +36,7 @@ class UnStackActionButton extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { return BaseActionButton( - iconData: Icons.filter_none_rounded, + iconData: Icons.layers_clear_outlined, label: "unstack".t(context: context), onPressed: () => _onTap(context, ref), ); diff --git a/mobile/lib/presentation/widgets/album/album_selector.widget.dart b/mobile/lib/presentation/widgets/album/album_selector.widget.dart index ce98728089..bffe3d3941 100644 --- a/mobile/lib/presentation/widgets/album/album_selector.widget.dart +++ b/mobile/lib/presentation/widgets/album/album_selector.widget.dart @@ -40,6 +40,7 @@ class AlbumSelector extends ConsumerStatefulWidget { class _AlbumSelectorState extends ConsumerState { bool isGrid = false; final searchController = TextEditingController(); + final menuController = MenuController(); final searchFocusNode = FocusNode(); List sortedAlbums = []; List shownAlbums = []; @@ -157,34 +158,45 @@ class _AlbumSelectorState extends ConsumerState { await sortAlbums(); }); - return MultiSliver( - children: [ - _SearchBar( - searchController: searchController, - searchFocusNode: searchFocusNode, - onSearch: onSearch, - filterMode: filter.mode, - onClearSearch: clearSearch, - ), - _QuickFilterButtonRow( - filterMode: filter.mode, - onChangeFilter: changeFilter, - onSearch: onSearch, - searchController: searchController, - ), - _QuickSortAndViewMode(isGrid: isGrid, onToggleViewMode: toggleViewMode, onSortChanged: changeSort), - isGrid - ? _AlbumGrid(albums: shownAlbums, userId: userId, onAlbumSelected: widget.onAlbumSelected) - : _AlbumList(albums: shownAlbums, userId: userId, onAlbumSelected: widget.onAlbumSelected), - ], + return PopScope( + onPopInvokedWithResult: (didPop, _) { + menuController.close(); + }, + child: MultiSliver( + children: [ + _SearchBar( + searchController: searchController, + searchFocusNode: searchFocusNode, + onSearch: onSearch, + filterMode: filter.mode, + onClearSearch: clearSearch, + ), + _QuickFilterButtonRow( + filterMode: filter.mode, + onChangeFilter: changeFilter, + onSearch: onSearch, + searchController: searchController, + ), + _QuickSortAndViewMode( + isGrid: isGrid, + onToggleViewMode: toggleViewMode, + onSortChanged: changeSort, + controller: menuController, + ), + isGrid + ? _AlbumGrid(albums: shownAlbums, userId: userId, onAlbumSelected: widget.onAlbumSelected) + : _AlbumList(albums: shownAlbums, userId: userId, onAlbumSelected: widget.onAlbumSelected), + ], + ), ); } } class _SortButton extends ConsumerStatefulWidget { - const _SortButton(this.onSortChanged); + const _SortButton(this.onSortChanged, {this.controller}); final Future Function(AlbumSort) onSortChanged; + final MenuController? controller; @override ConsumerState<_SortButton> createState() => _SortButtonState(); @@ -220,6 +232,7 @@ class _SortButtonState extends ConsumerState<_SortButton> { @override Widget build(BuildContext context) { return MenuAnchor( + controller: widget.controller, style: MenuStyle( elevation: const WidgetStatePropertyAll(1), shape: WidgetStateProperty.all( @@ -449,10 +462,16 @@ class _QuickFilterButton extends StatelessWidget { } class _QuickSortAndViewMode extends StatelessWidget { - const _QuickSortAndViewMode({required this.isGrid, required this.onToggleViewMode, required this.onSortChanged}); + const _QuickSortAndViewMode({ + required this.isGrid, + required this.onToggleViewMode, + required this.onSortChanged, + this.controller, + }); final bool isGrid; final VoidCallback onToggleViewMode; + final MenuController? controller; final Future Function(AlbumSort) onSortChanged; @override @@ -463,7 +482,7 @@ class _QuickSortAndViewMode extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - _SortButton(onSortChanged), + _SortButton(onSortChanged, controller: controller), IconButton( icon: Icon(isGrid ? Icons.view_list_outlined : Icons.grid_view_outlined, size: 24), onPressed: onToggleViewMode, @@ -485,15 +504,15 @@ class _AlbumList extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { if (albums.isEmpty) { - return const SliverToBoxAdapter( + return SliverToBoxAdapter( child: Center( - child: Padding(padding: EdgeInsets.all(20.0), child: Text('No albums found')), + child: Padding(padding: const EdgeInsets.all(20.0), child: Text('album_search_not_found'.tr())), ), ); } return SliverPadding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), + padding: const EdgeInsets.only(left: 16.0, right: 16, bottom: 64), sliver: SliverList.builder( itemBuilder: (_, index) { final album = albums[index]; @@ -580,9 +599,9 @@ class _AlbumGrid extends StatelessWidget { @override Widget build(BuildContext context) { if (albums.isEmpty) { - return const SliverToBoxAdapter( + return SliverToBoxAdapter( child: Center( - child: Padding(padding: EdgeInsets.all(20.0), child: Text('No albums found')), + child: Padding(padding: const EdgeInsets.all(20.0), child: Text('album_search_not_found'.tr())), ), ); } diff --git a/mobile/lib/presentation/widgets/asset_viewer/asset_stack.provider.dart b/mobile/lib/presentation/widgets/asset_viewer/asset_stack.provider.dart index 1eb3366e30..dae6db568c 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/asset_stack.provider.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/asset_stack.provider.dart @@ -2,11 +2,11 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; -class StackChildrenNotifier extends AutoDisposeFamilyAsyncNotifier, BaseAsset?> { +class StackChildrenNotifier extends AutoDisposeFamilyAsyncNotifier, BaseAsset> { @override - Future> build(BaseAsset? asset) async { - if (asset == null || asset is! RemoteAsset || asset.stackId == null) { - return const []; + Future> build(BaseAsset asset) { + if (asset is! RemoteAsset || asset.stackId == null) { + return Future.value(const []); } return ref.watch(assetServiceProvider).getStack(asset); @@ -14,4 +14,4 @@ class StackChildrenNotifier extends AutoDisposeFamilyAsyncNotifier, BaseAsset?>(StackChildrenNotifier.new); + .family, BaseAsset>(StackChildrenNotifier.new); diff --git a/mobile/lib/presentation/widgets/asset_viewer/asset_stack.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/asset_stack.widget.dart index e5d1487d53..0978b3c9af 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/asset_stack.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/asset_stack.widget.dart @@ -3,7 +3,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_stack.provider.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_viewer.state.dart'; -import 'package:immich_mobile/presentation/widgets/images/image_provider.dart'; +import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart'; import 'package:immich_mobile/providers/infrastructure/asset_viewer/current_asset.provider.dart'; class AssetStackRow extends ConsumerWidget { @@ -11,27 +11,25 @@ class AssetStackRow extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - int opacity = ref.watch(assetViewerProvider.select((state) => state.backgroundOpacity)); - final showControls = ref.watch(assetViewerProvider.select((s) => s.showingControls)); - - if (!showControls) { - opacity = 0; + final asset = ref.watch(assetViewerProvider.select((state) => state.currentAsset)); + if (asset == null) { + return const SizedBox.shrink(); } - final asset = ref.watch(assetViewerProvider.select((s) => s.currentAsset)); + final stackChildren = ref.watch(stackChildrenNotifier(asset)).valueOrNull; + if (stackChildren == null || stackChildren.isEmpty) { + return const SizedBox.shrink(); + } + + final showControls = ref.watch(assetViewerProvider.select((s) => s.showingControls)); + final opacity = showControls ? ref.watch(assetViewerProvider.select((state) => state.backgroundOpacity)) : 0; return IgnorePointer( ignoring: opacity < 255, child: AnimatedOpacity( opacity: opacity / 255, duration: Durations.short2, - child: ref - .watch(stackChildrenNotifier(asset)) - .when( - data: (state) => SizedBox.square(dimension: 80, child: _StackList(stack: state)), - error: (_, __) => const SizedBox.shrink(), - loading: () => const SizedBox.shrink(), - ), + child: _StackList(stack: stackChildren), ), ); } @@ -44,58 +42,77 @@ class _StackList extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - return ListView.builder( - scrollDirection: Axis.horizontal, - padding: const EdgeInsets.only(left: 5, right: 5, bottom: 30), - itemCount: stack.length, - itemBuilder: (ctx, index) { - final asset = stack[index]; - return Padding( - padding: const EdgeInsets.only(right: 5), - child: GestureDetector( - onTap: () { - ref.read(assetViewerProvider.notifier).setStackIndex(index); - ref.read(currentAssetNotifier.notifier).setAsset(asset); - }, - child: Container( - height: 60, - width: 60, - decoration: index == ref.watch(assetViewerProvider.select((s) => s.stackIndex)) - ? const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(6)), - border: Border.fromBorderSide(BorderSide(color: Colors.white, width: 2)), - ) - : const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(6)), - border: null, - ), - child: ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(4)), - child: Stack( - fit: StackFit.expand, - children: [ - Image( - fit: BoxFit.cover, - image: getThumbnailImageProvider(remoteId: asset.id, size: const Size.square(60)), - ), - if (asset.isVideo) - const Icon( - Icons.play_circle_outline_rounded, - color: Colors.white, - size: 16, - shadows: [ - Shadow(blurRadius: 5.0, color: Color.fromRGBO(0, 0, 0, 0.6), offset: Offset(0.0, 0.0)), - ], - ), - ], - ), - ), - ), + return Center( + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Padding( + padding: const EdgeInsets.only(left: 10.0, right: 10.0, bottom: 20.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + spacing: 5.0, + children: List.generate(stack.length, (i) { + final asset = stack[i]; + return _StackItem(key: ValueKey(asset.heroTag), asset: asset, index: i); + }), ), - ); - }, + ), + ), + ); + } +} + +class _StackItem extends ConsumerStatefulWidget { + final RemoteAsset asset; + final int index; + + const _StackItem({super.key, required this.asset, required this.index}); + + @override + ConsumerState<_StackItem> createState() => _StackItemState(); +} + +class _StackItemState extends ConsumerState<_StackItem> { + void _onTap() { + ref.read(currentAssetNotifier.notifier).setAsset(widget.asset); + ref.read(assetViewerProvider.notifier).setStackIndex(widget.index); + } + + @override + Widget build(BuildContext context) { + const playIcon = Center( + child: Icon( + Icons.play_circle_outline_rounded, + color: Colors.white, + size: 16, + shadows: [Shadow(blurRadius: 5.0, color: Color.fromRGBO(0, 0, 0, 0.6), offset: Offset(0.0, 0.0))], + ), + ); + const selectedDecoration = BoxDecoration( + border: Border.fromBorderSide(BorderSide(color: Colors.white, width: 2)), + borderRadius: BorderRadius.all(Radius.circular(10)), + ); + const unselectedDecoration = BoxDecoration( + border: Border.fromBorderSide(BorderSide(color: Colors.grey, width: 0.5)), + borderRadius: BorderRadius.all(Radius.circular(10)), + ); + + Widget thumbnail = Thumbnail.fromAsset(asset: widget.asset, size: const Size(60, 40)); + if (widget.asset.isVideo) { + thumbnail = Stack(children: [thumbnail, playIcon]); + } + thumbnail = ClipRRect(borderRadius: const BorderRadius.all(Radius.circular(10)), child: thumbnail); + final isSelected = ref.watch(assetViewerProvider.select((s) => s.stackIndex == widget.index)); + return SizedBox( + width: 60, + height: 40, + child: GestureDetector( + onTap: _onTap, + child: DecoratedBox( + decoration: isSelected ? selectedDecoration : unselectedDecoration, + position: DecorationPosition.foreground, + child: thumbnail, + ), + ), ); } } diff --git a/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.page.dart b/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.page.dart index 899b6ed545..e3106c7f7f 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.page.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.page.dart @@ -10,7 +10,9 @@ import 'package:immich_mobile/domain/models/timeline.model.dart'; import 'package:immich_mobile/domain/services/timeline.service.dart'; import 'package:immich_mobile/domain/utils/event_stream.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_mobile/extensions/platform_extensions.dart'; import 'package:immich_mobile/extensions/scroll_extensions.dart'; +import 'package:immich_mobile/presentation/widgets/action_buttons/download_status_floating_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_stack.provider.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_stack.widget.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_viewer.state.dart'; @@ -30,7 +32,6 @@ import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart'; import 'package:immich_mobile/widgets/common/immich_loading_indicator.dart'; import 'package:immich_mobile/widgets/photo_view/photo_view.dart'; import 'package:immich_mobile/widgets/photo_view/photo_view_gallery.dart'; -import 'package:platform/platform.dart'; @RoutePage() class AssetViewerPage extends StatelessWidget { @@ -53,15 +54,23 @@ class AssetViewerPage extends StatelessWidget { class AssetViewer extends ConsumerStatefulWidget { final int initialIndex; - final Platform? platform; final int? heroOffset; - const AssetViewer({super.key, required this.initialIndex, this.platform, this.heroOffset}); + const AssetViewer({super.key, required this.initialIndex, this.heroOffset}); @override ConsumerState createState() => _AssetViewerState(); static void setAsset(WidgetRef ref, BaseAsset asset) { + ref.read(assetViewerProvider.notifier).reset(); + _setAsset(ref, asset); + } + + void changeAsset(WidgetRef ref, BaseAsset asset) { + _setAsset(ref, asset); + } + + static void _setAsset(WidgetRef ref, BaseAsset asset) { // Always holds the current asset from the timeline ref.read(assetViewerProvider.notifier).setAsset(asset); // The currentAssetNotifier actually holds the current asset that is displayed @@ -86,7 +95,6 @@ class _AssetViewerState extends ConsumerState { PhotoViewControllerBase? viewController; StreamSubscription? reloadSubscription; - late Platform platform; late final int heroOffset; late PhotoViewControllerValue initialPhotoViewState; bool? hasDraggedDown; @@ -109,17 +117,22 @@ class _AssetViewerState extends ConsumerState { ImageStream? _prevPreCacheStream; ImageStream? _nextPreCacheStream; + KeepAliveLink? _stackChildrenKeepAlive; + @override void initState() { super.initState(); assert(ref.read(currentAssetNotifier) != null, "Current asset should not be null when opening the AssetViewer"); pageController = PageController(initialPage: widget.initialIndex); - platform = widget.platform ?? const LocalPlatform(); totalAssets = ref.read(timelineServiceProvider).totalAssets; bottomSheetController = DraggableScrollableController(); WidgetsBinding.instance.addPostFrameCallback(_onAssetInit); reloadSubscription = EventStream.shared.listen(_onEvent); heroOffset = widget.heroOffset ?? TabsRouterScope.of(context)?.controller.activeIndex ?? 0; + final asset = ref.read(currentAssetNotifier); + if (asset != null) { + _stackChildrenKeepAlive = ref.read(stackChildrenNotifier(asset).notifier).ref.keepAlive(); + } } @override @@ -131,6 +144,7 @@ class _AssetViewerState extends ConsumerState { _prevPreCacheStream?.removeListener(_dummyListener); _nextPreCacheStream?.removeListener(_dummyListener); SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); + _stackChildrenKeepAlive?.close(); super.dispose(); } @@ -191,9 +205,11 @@ class _AssetViewerState extends ConsumerState { return; } - AssetViewer.setAsset(ref, asset); + widget.changeAsset(ref, asset); _precacheAssets(index); _handleCasting(); + _stackChildrenKeepAlive?.close(); + _stackChildrenKeepAlive = ref.read(stackChildrenNotifier(asset).notifier).ref.keepAlive(); } void _handleCasting() { @@ -205,10 +221,8 @@ class _AssetViewerState extends ConsumerState { context.scaffoldMessenger.hideCurrentSnackBar(); // send image to casting if the server has it - if (asset.hasRemote) { - final remoteAsset = asset as RemoteAsset; - - ref.read(castProvider.notifier).loadMedia(remoteAsset, false); + if (asset is RemoteAsset) { + ref.read(castProvider.notifier).loadMedia(asset, false); } else { // casting cannot show local assets context.scaffoldMessenger.clearSnackBars(); @@ -521,7 +535,7 @@ class _AssetViewerState extends ConsumerState { BaseAsset displayAsset = asset; final stackChildren = ref.read(stackChildrenNotifier(asset)).valueOrNull; if (stackChildren != null && stackChildren.isNotEmpty) { - displayAsset = stackChildren.elementAt(ref.read(assetViewerProvider.select((s) => s.stackIndex))); + displayAsset = stackChildren.elementAt(ref.read(assetViewerProvider).stackIndex); } final isPlayingMotionVideo = ref.read(isPlayingMotionVideoProvider); @@ -634,20 +648,25 @@ class _AssetViewerState extends ConsumerState { appBar: const ViewerTopAppBar(), extendBody: true, extendBodyBehindAppBar: true, - body: PhotoViewGallery.builder( - gaplessPlayback: true, - loadingBuilder: _placeholderBuilder, - pageController: pageController, - scrollPhysics: platform.isIOS - ? const FastScrollPhysics() // Use bouncing physics for iOS - : const FastClampingScrollPhysics(), // Use heavy physics for Android - itemCount: totalAssets, - onPageChanged: _onPageChanged, - onPageBuild: _onPageBuild, - scaleStateChangedCallback: _onScaleStateChanged, - builder: _assetBuilder, - backgroundDecoration: BoxDecoration(color: backgroundColor), - enablePanAlways: true, + floatingActionButton: const DownloadStatusFloatingButton(), + body: Stack( + children: [ + PhotoViewGallery.builder( + gaplessPlayback: true, + loadingBuilder: _placeholderBuilder, + pageController: pageController, + scrollPhysics: CurrentPlatform.isIOS + ? const FastScrollPhysics() // Use bouncing physics for iOS + : const FastClampingScrollPhysics(), // Use heavy physics for Android + itemCount: totalAssets, + onPageChanged: _onPageChanged, + onPageBuild: _onPageBuild, + scaleStateChangedCallback: _onScaleStateChanged, + builder: _assetBuilder, + backgroundDecoration: BoxDecoration(color: backgroundColor), + enablePanAlways: true, + ), + ], ), bottomNavigationBar: showingBottomSheet ? const SizedBox.shrink() diff --git a/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.state.dart b/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.state.dart index 94e0a70538..354902c9d7 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.state.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.state.dart @@ -68,12 +68,16 @@ class AssetViewerState { stackIndex.hashCode; } -class AssetViewerStateNotifier extends AutoDisposeNotifier { +class AssetViewerStateNotifier extends Notifier { @override AssetViewerState build() { return const AssetViewerState(); } + void reset() { + state = const AssetViewerState(); + } + void setAsset(BaseAsset? asset) { if (asset == state.currentAsset) { return; @@ -117,6 +121,4 @@ class AssetViewerStateNotifier extends AutoDisposeNotifier { } } -final assetViewerProvider = AutoDisposeNotifierProvider( - AssetViewerStateNotifier.new, -); +final assetViewerProvider = NotifierProvider(AssetViewerStateNotifier.new); diff --git a/mobile/lib/presentation/widgets/asset_viewer/bottom_bar.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/bottom_bar.widget.dart index 3111512823..44660e440c 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/bottom_bar.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/bottom_bar.widget.dart @@ -43,7 +43,7 @@ class ViewerBottomBar extends ConsumerWidget { final actions = [ const ShareActionButton(source: ActionSource.viewer), if (asset.isLocalOnly) const UploadActionButton(source: ActionSource.viewer), - if (asset.type == AssetType.image) const EditImageActionButton(), + if (asset.type == AssetType.image && isOwner) const EditImageActionButton(), if (isOwner) ...[ if (asset.hasRemote && isOwner && isArchived) const UnArchiveActionButton(source: ActionSource.viewer) diff --git a/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet.widget.dart index ae55fb671b..9d29b19bff 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet.widget.dart @@ -5,6 +5,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/exif.model.dart'; +import 'package:immich_mobile/domain/models/setting.model.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/bottom_sheet/sheet_location_details.widget.dart'; @@ -14,6 +15,7 @@ import 'package:immich_mobile/providers/haptic_feedback.provider.dart'; import 'package:immich_mobile/providers/infrastructure/action.provider.dart'; import 'package:immich_mobile/providers/infrastructure/asset_viewer/current_asset.provider.dart'; import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/setting.provider.dart'; import 'package:immich_mobile/providers/routes.provider.dart'; import 'package:immich_mobile/providers/server_info.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; @@ -41,6 +43,7 @@ class AssetDetailBottomSheet extends ConsumerWidget { final isInLockedView = ref.watch(inLockedViewProvider); final currentAlbum = ref.watch(currentRemoteAlbumProvider); final isArchived = asset is RemoteAsset && asset.visibility == AssetVisibility.archive; + final advancedTroubleshooting = ref.watch(settingsProvider.notifier).get(Setting.advancedTroubleshooting); final buttonContext = ActionButtonContext( asset: asset, @@ -48,7 +51,9 @@ class AssetDetailBottomSheet extends ConsumerWidget { isArchived: isArchived, isTrashEnabled: isTrashEnable, isInLockedView: isInLockedView, + isStacked: asset is RemoteAsset && asset.stackId != null, currentAlbum: currentAlbum, + advancedTroubleshooting: advancedTroubleshooting, source: ActionSource.viewer, ); @@ -122,6 +127,10 @@ class _AssetDetailBottomSheet extends ConsumerWidget { return [fNumber, exposureTime, focalLength, iso].where((spec) => spec != null && spec.isNotEmpty).join(_kSeparator); } + Future _editDateTime(BuildContext context, WidgetRef ref) async { + await ref.read(actionProvider.notifier).editDateTime(ActionSource.viewer, context); + } + @override Widget build(BuildContext context, WidgetRef ref) { final asset = ref.watch(currentAssetNotifier); @@ -131,10 +140,7 @@ class _AssetDetailBottomSheet extends ConsumerWidget { final exifInfo = ref.watch(currentAssetExifProvider).valueOrNull; final cameraTitle = _getCameraInfoTitle(exifInfo); - - Future editDateTime() async { - await ref.read(actionProvider.notifier).editDateTime(ActionSource.viewer, context); - } + final isOwner = ref.watch(currentUserProvider)?.id == (asset is RemoteAsset ? asset.ownerId : null); return SliverList.list( children: [ @@ -142,10 +148,10 @@ class _AssetDetailBottomSheet extends ConsumerWidget { _SheetTile( title: _getDateTime(context, asset), titleStyle: context.textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w600), - trailing: asset.hasRemote ? const Icon(Icons.edit, size: 18) : null, - onTap: asset.hasRemote ? () async => await editDateTime() : null, + trailing: asset.hasRemote && isOwner ? const Icon(Icons.edit, size: 18) : null, + onTap: asset.hasRemote && isOwner ? () async => await _editDateTime(context, ref) : null, ), - if (exifInfo != null) _SheetAssetDescription(exif: exifInfo), + if (exifInfo != null) _SheetAssetDescription(exif: exifInfo, isEditable: isOwner), const SheetPeopleDetails(), const SheetLocationDetails(), // Details header @@ -181,6 +187,7 @@ class _AssetDetailBottomSheet extends ConsumerWidget { color: context.textTheme.bodyMedium?.color?.withAlpha(155), ), ), + const SizedBox(height: 64), ], ); } @@ -259,8 +266,9 @@ class _SheetTile extends ConsumerWidget { class _SheetAssetDescription extends ConsumerStatefulWidget { final ExifInfo exif; + final bool isEditable; - const _SheetAssetDescription({required this.exif}); + const _SheetAssetDescription({required this.exif, this.isEditable = true}); @override ConsumerState<_SheetAssetDescription> createState() => _SheetAssetDescriptionState(); @@ -306,27 +314,33 @@ class _SheetAssetDescriptionState extends ConsumerState<_SheetAssetDescription> // Update controller text when EXIF data changes final currentDescription = currentExifInfo?.description ?? ''; + final hintText = (widget.isEditable ? 'exif_bottom_sheet_description' : 'exif_bottom_sheet_no_description').t( + context: context, + ); if (_controller.text != currentDescription && !_descriptionFocus.hasFocus) { _controller.text = currentDescription; } return Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8), - child: TextField( - controller: _controller, - keyboardType: TextInputType.multiline, - focusNode: _descriptionFocus, - maxLines: null, // makes it grow as text is added - decoration: InputDecoration( - hintText: 'exif_bottom_sheet_description'.t(context: context), - border: InputBorder.none, - enabledBorder: InputBorder.none, - focusedBorder: InputBorder.none, - disabledBorder: InputBorder.none, - errorBorder: InputBorder.none, - focusedErrorBorder: InputBorder.none, + child: IgnorePointer( + ignoring: !widget.isEditable, + child: TextField( + controller: _controller, + keyboardType: TextInputType.multiline, + focusNode: _descriptionFocus, + maxLines: null, // makes it grow as text is added + decoration: InputDecoration( + hintText: hintText, + border: InputBorder.none, + enabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + disabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + focusedErrorBorder: InputBorder.none, + ), + onTapOutside: (_) => saveDescription(currentExifInfo?.description), ), - onTapOutside: (_) => saveDescription(currentExifInfo?.description), ), ); } diff --git a/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet/sheet_people_details.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet/sheet_people_details.widget.dart index fee34bca1b..64f22eca92 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet/sheet_people_details.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet/sheet_people_details.widget.dart @@ -11,8 +11,8 @@ import 'package:immich_mobile/providers/infrastructure/people.provider.dart'; import 'package:immich_mobile/providers/routes.provider.dart'; import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/services/api.service.dart'; -import 'package:immich_mobile/utils/people.utils.dart'; import 'package:immich_mobile/utils/image_url_builder.dart'; +import 'package:immich_mobile/utils/people.utils.dart'; class SheetPeopleDetails extends ConsumerStatefulWidget { const SheetPeopleDetails({super.key}); @@ -158,11 +158,14 @@ class _PeopleAvatar extends StatelessWidget { maxLines: 1, ), if (person.birthDate != null) - Text( - formatAge(person.birthDate!, assetFileCreatedAt), - textAlign: TextAlign.center, - style: context.textTheme.bodyMedium?.copyWith( - color: context.textTheme.bodyMedium?.color?.withAlpha(175), + FittedBox( + fit: BoxFit.scaleDown, + child: Text( + formatAge(person.birthDate!, assetFileCreatedAt), + textAlign: TextAlign.center, + style: context.textTheme.bodyMedium?.copyWith( + color: context.textTheme.bodyMedium?.color?.withAlpha(175), + ), ), ), ], diff --git a/mobile/lib/presentation/widgets/asset_viewer/top_app_bar.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/top_app_bar.widget.dart index 570df1afbb..38ad9d17de 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/top_app_bar.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/top_app_bar.widget.dart @@ -4,18 +4,21 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/timeline.model.dart'; +import 'package:immich_mobile/domain/services/timeline.service.dart'; import 'package:immich_mobile/domain/utils/event_stream.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/cast_action_button.widget.dart'; +import 'package:immich_mobile/presentation/widgets/action_buttons/download_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/favorite_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/motion_photo_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/unfavorite_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_viewer.state.dart'; import 'package:immich_mobile/providers/cast.provider.dart'; import 'package:immich_mobile/providers/infrastructure/asset_viewer/current_asset.provider.dart'; -import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.dart'; import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart'; import 'package:immich_mobile/providers/routes.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; import 'package:immich_mobile/routing/router.dart'; @@ -37,11 +40,14 @@ class ViewerTopAppBar extends ConsumerWidget implements PreferredSizeWidget { final isInLockedView = ref.watch(inLockedViewProvider); final isReadonlyModeEnabled = ref.watch(readonlyModeProvider); - final previousRouteName = ref.watch(previousRouteNameProvider); + final timelineOrigin = ref.read(timelineServiceProvider).origin; final showViewInTimelineButton = - previousRouteName != TabShellRoute.name && - previousRouteName != AssetViewerRoute.name && - previousRouteName != null; + timelineOrigin != TimelineOrigin.main && + timelineOrigin != TimelineOrigin.deepLink && + timelineOrigin != TimelineOrigin.trash && + timelineOrigin != TimelineOrigin.archive && + timelineOrigin != TimelineOrigin.localAlbum && + isOwner; final isShowingSheet = ref.watch(assetViewerProvider.select((state) => state.showingBottomSheet)); int opacity = ref.watch(assetViewerProvider.select((state) => state.backgroundOpacity)); @@ -54,6 +60,7 @@ class ViewerTopAppBar extends ConsumerWidget implements PreferredSizeWidget { final isCasting = ref.watch(castProvider.select((c) => c.isCasting)); final actions = [ + if (asset.isRemoteOnly) const DownloadActionButton(source: ActionSource.viewer, menuItem: true), if (isCasting || (asset.hasRemote)) const CastActionButton(menuItem: true), if (album != null && album.isActivityEnabled && album.isShared) IconButton( diff --git a/mobile/lib/presentation/widgets/asset_viewer/video_viewer.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/video_viewer.widget.dart index fa7f204596..3af31950ad 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/video_viewer.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/video_viewer.widget.dart @@ -7,6 +7,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/setting.model.dart'; import 'package:immich_mobile/domain/models/store.model.dart'; +import 'package:immich_mobile/domain/services/setting.service.dart'; import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_viewer.state.dart'; @@ -88,10 +89,18 @@ class NativeVideoViewer extends HookConsumerWidget { } final videoAsset = await ref.read(assetServiceProvider).getAsset(asset) ?? asset; + if (!context.mounted) { + return null; + } + try { if (videoAsset.hasLocal && videoAsset.livePhotoVideoId == null) { final id = videoAsset is LocalAsset ? videoAsset.id : (videoAsset as RemoteAsset).localId!; final file = await const StorageRepository().getFileForAsset(id); + if (!context.mounted) { + return null; + } + if (file == null) { throw Exception('No file found for the video'); } @@ -210,7 +219,10 @@ class NativeVideoViewer extends HookConsumerWidget { } try { - await videoController.play(); + final autoPlayVideo = AppSetting.get(Setting.autoPlayVideo); + if (autoPlayVideo) { + await videoController.play(); + } await videoController.setVolume(0.9); } catch (error) { log.severe('Error playing video: $error'); @@ -289,7 +301,7 @@ class NativeVideoViewer extends HookConsumerWidget { ref.read(videoPlaybackValueProvider.notifier).reset(); final source = await videoSource; - if (source == null) { + if (source == null || !context.mounted) { return; } @@ -314,6 +326,9 @@ class NativeVideoViewer extends HookConsumerWidget { removeListeners(playerController); } + if (value != null) { + isVisible.value = _isCurrentAsset(value, asset); + } final curAsset = currentAsset.value; if (curAsset == asset) { return; diff --git a/mobile/lib/presentation/widgets/backup/backup_toggle_button.widget.dart b/mobile/lib/presentation/widgets/backup/backup_toggle_button.widget.dart index a74c169224..8d374f74ff 100644 --- a/mobile/lib/presentation/widgets/backup/backup_toggle_button.widget.dart +++ b/mobile/lib/presentation/widgets/backup/backup_toggle_button.widget.dart @@ -65,7 +65,9 @@ class BackupToggleButtonState extends ConsumerState with Sin final uploadTasks = ref.watch(driftBackupProvider.select((state) => state.uploadItems)); - final isUploading = uploadTasks.isNotEmpty; + final isSyncing = ref.watch(driftBackupProvider.select((state) => state.isSyncing)); + + final isProcessing = uploadTasks.isNotEmpty || isSyncing; return AnimatedBuilder( animation: _animationController, @@ -129,7 +131,7 @@ class BackupToggleButtonState extends ConsumerState with Sin ], ), ), - child: isUploading + child: isProcessing ? const SizedBox(width: 24, height: 24, child: CircularProgressIndicator(strokeWidth: 2)) : Icon(Icons.cloud_upload_outlined, color: context.primaryColor, size: 24), ), diff --git a/mobile/lib/presentation/widgets/bottom_sheet/archive_bottom_sheet.widget.dart b/mobile/lib/presentation/widgets/bottom_sheet/archive_bottom_sheet.widget.dart index 45c602935d..f40e189e18 100644 --- a/mobile/lib/presentation/widgets/bottom_sheet/archive_bottom_sheet.widget.dart +++ b/mobile/lib/presentation/widgets/bottom_sheet/archive_bottom_sheet.widget.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; -import 'package:immich_mobile/presentation/widgets/action_buttons/delete_permanent_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/delete_local_action_button.widget.dart'; +import 'package:immich_mobile/presentation/widgets/action_buttons/delete_permanent_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/download_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/edit_date_time_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/edit_location_action_button.widget.dart'; @@ -13,6 +13,7 @@ import 'package:immich_mobile/presentation/widgets/action_buttons/share_link_act import 'package:immich_mobile/presentation/widgets/action_buttons/stack_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/trash_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/unarchive_action_button.widget.dart'; +import 'package:immich_mobile/presentation/widgets/action_buttons/unstack_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/upload_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart'; import 'package:immich_mobile/providers/server_info.provider.dart'; @@ -43,7 +44,8 @@ class ArchiveBottomSheet extends ConsumerWidget { const EditDateTimeActionButton(source: ActionSource.timeline), const EditLocationActionButton(source: ActionSource.timeline), const MoveToLockFolderActionButton(source: ActionSource.timeline), - const StackActionButton(source: ActionSource.timeline), + if (multiselect.selectedAssets.length > 1) const StackActionButton(source: ActionSource.timeline), + if (multiselect.hasStacked) const UnStackActionButton(source: ActionSource.timeline), ], if (multiselect.hasLocal) ...[ const DeleteLocalActionButton(source: ActionSource.timeline), diff --git a/mobile/lib/presentation/widgets/bottom_sheet/favorite_bottom_sheet.widget.dart b/mobile/lib/presentation/widgets/bottom_sheet/favorite_bottom_sheet.widget.dart index 3fb499f2a1..b2502127d4 100644 --- a/mobile/lib/presentation/widgets/bottom_sheet/favorite_bottom_sheet.widget.dart +++ b/mobile/lib/presentation/widgets/bottom_sheet/favorite_bottom_sheet.widget.dart @@ -1,9 +1,12 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; +import 'package:immich_mobile/domain/models/album/album.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; +import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/archive_action_button.widget.dart'; -import 'package:immich_mobile/presentation/widgets/action_buttons/delete_permanent_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/delete_local_action_button.widget.dart'; +import 'package:immich_mobile/presentation/widgets/action_buttons/delete_permanent_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/download_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/edit_date_time_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/edit_location_action_button.widget.dart'; @@ -13,10 +16,14 @@ import 'package:immich_mobile/presentation/widgets/action_buttons/share_link_act import 'package:immich_mobile/presentation/widgets/action_buttons/stack_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/trash_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/unfavorite_action_button.widget.dart'; +import 'package:immich_mobile/presentation/widgets/action_buttons/unstack_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/upload_action_button.widget.dart'; +import 'package:immich_mobile/presentation/widgets/album/album_selector.widget.dart'; import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart'; +import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; import 'package:immich_mobile/providers/server_info.provider.dart'; import 'package:immich_mobile/providers/timeline/multiselect.provider.dart'; +import 'package:immich_mobile/widgets/common/immich_toast.dart'; class FavoriteBottomSheet extends ConsumerWidget { const FavoriteBottomSheet({super.key}); @@ -26,9 +33,42 @@ class FavoriteBottomSheet extends ConsumerWidget { final multiselect = ref.watch(multiSelectProvider); final isTrashEnable = ref.watch(serverInfoProvider.select((state) => state.serverFeatures.trash)); + Future addAssetsToAlbum(RemoteAlbum album) async { + final selectedAssets = multiselect.selectedAssets; + if (selectedAssets.isEmpty) { + return; + } + + final remoteAssets = selectedAssets.whereType(); + final addedCount = await ref + .read(remoteAlbumProvider.notifier) + .addAssets(album.id, remoteAssets.map((e) => e.id).toList()); + + if (selectedAssets.length != remoteAssets.length) { + ImmichToast.show( + context: context, + msg: 'add_to_album_bottom_sheet_some_local_assets'.t(context: context), + ); + } + + if (addedCount != remoteAssets.length) { + ImmichToast.show( + context: context, + msg: 'add_to_album_bottom_sheet_already_exists'.t(args: {"album": album.name}), + ); + } else { + ImmichToast.show( + context: context, + msg: 'add_to_album_bottom_sheet_added'.t(args: {"album": album.name}), + ); + } + + ref.read(multiSelectProvider.notifier).reset(); + } + return BaseBottomSheet( - initialChildSize: 0.25, - maxChildSize: 0.4, + initialChildSize: 0.4, + maxChildSize: 0.7, shouldCloseOnMinExtent: false, actions: [ const ShareActionButton(source: ActionSource.timeline), @@ -43,13 +83,17 @@ class FavoriteBottomSheet extends ConsumerWidget { const EditDateTimeActionButton(source: ActionSource.timeline), const EditLocationActionButton(source: ActionSource.timeline), const MoveToLockFolderActionButton(source: ActionSource.timeline), - const StackActionButton(source: ActionSource.timeline), + if (multiselect.selectedAssets.length > 1) const StackActionButton(source: ActionSource.timeline), + if (multiselect.hasStacked) const UnStackActionButton(source: ActionSource.timeline), ], if (multiselect.hasLocal) ...[ const DeleteLocalActionButton(source: ActionSource.timeline), const UploadActionButton(source: ActionSource.timeline), ], ], + slivers: multiselect.hasRemote + ? [const AddToAlbumHeader(), AlbumSelector(onAlbumSelected: addAssetsToAlbum)] + : [], ); } } diff --git a/mobile/lib/presentation/widgets/bottom_sheet/general_bottom_sheet.widget.dart b/mobile/lib/presentation/widgets/bottom_sheet/general_bottom_sheet.widget.dart index f1f092d2e2..9436707c84 100644 --- a/mobile/lib/presentation/widgets/bottom_sheet/general_bottom_sheet.widget.dart +++ b/mobile/lib/presentation/widgets/bottom_sheet/general_bottom_sheet.widget.dart @@ -4,6 +4,9 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/domain/models/album/album.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; +import 'package:immich_mobile/domain/models/setting.model.dart'; +import 'package:immich_mobile/extensions/translate_extensions.dart'; +import 'package:immich_mobile/presentation/widgets/action_buttons/advanced_info_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/archive_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/delete_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/delete_local_action_button.widget.dart'; @@ -17,10 +20,12 @@ import 'package:immich_mobile/presentation/widgets/action_buttons/share_action_b import 'package:immich_mobile/presentation/widgets/action_buttons/share_link_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/stack_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/trash_action_button.widget.dart'; +import 'package:immich_mobile/presentation/widgets/action_buttons/unstack_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/upload_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/album/album_selector.widget.dart'; import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart'; import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/setting.provider.dart'; import 'package:immich_mobile/providers/server_info.provider.dart'; import 'package:immich_mobile/providers/timeline/multiselect.provider.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart'; @@ -51,6 +56,7 @@ class _GeneralBottomSheetState extends ConsumerState { Widget build(BuildContext context) { final multiselect = ref.watch(multiSelectProvider); final isTrashEnable = ref.watch(serverInfoProvider.select((state) => state.serverFeatures.trash)); + final advancedTroubleshooting = ref.watch(settingsProvider.notifier).get(Setting.advancedTroubleshooting); Future addAssetsToAlbum(RemoteAlbum album) async { final selectedAssets = multiselect.selectedAssets; @@ -58,11 +64,19 @@ class _GeneralBottomSheetState extends ConsumerState { return; } + final remoteAssets = selectedAssets.whereType(); final addedCount = await ref .read(remoteAlbumProvider.notifier) - .addAssets(album.id, selectedAssets.map((e) => (e as RemoteAsset).id).toList()); + .addAssets(album.id, remoteAssets.map((e) => e.id).toList()); - if (addedCount != selectedAssets.length) { + if (selectedAssets.length != remoteAssets.length) { + ImmichToast.show( + context: context, + msg: 'add_to_album_bottom_sheet_some_local_assets'.t(context: context), + ); + } + + if (addedCount != remoteAssets.length) { ImmichToast.show( context: context, msg: 'add_to_album_bottom_sheet_already_exists'.tr(namedArgs: {"album": album.name}), @@ -83,33 +97,39 @@ class _GeneralBottomSheetState extends ConsumerState { return BaseBottomSheet( controller: sheetController, - initialChildSize: 0.45, + initialChildSize: widget.minChildSize ?? 0.15, minChildSize: widget.minChildSize, maxChildSize: 0.85, shouldCloseOnMinExtent: false, actions: [ + if (multiselect.selectedAssets.length == 1 && advancedTroubleshooting) ...[ + const AdvancedInfoActionButton(source: ActionSource.timeline), + ], const ShareActionButton(source: ActionSource.timeline), if (multiselect.hasRemote) ...[ const ShareLinkActionButton(source: ActionSource.timeline), - const ArchiveActionButton(source: ActionSource.timeline), - const FavoriteActionButton(source: ActionSource.timeline), const DownloadActionButton(source: ActionSource.timeline), - const EditDateTimeActionButton(source: ActionSource.timeline), - const EditLocationActionButton(source: ActionSource.timeline), - const MoveToLockFolderActionButton(source: ActionSource.timeline), - const StackActionButton(source: ActionSource.timeline), isTrashEnable ? const TrashActionButton(source: ActionSource.timeline) : const DeletePermanentActionButton(source: ActionSource.timeline), + const FavoriteActionButton(source: ActionSource.timeline), + const ArchiveActionButton(source: ActionSource.timeline), + const EditDateTimeActionButton(source: ActionSource.timeline), + const EditLocationActionButton(source: ActionSource.timeline), + const MoveToLockFolderActionButton(source: ActionSource.timeline), + if (multiselect.selectedAssets.length > 1) const StackActionButton(source: ActionSource.timeline), + if (multiselect.hasStacked) const UnStackActionButton(source: ActionSource.timeline), const DeleteActionButton(source: ActionSource.timeline), ], if (multiselect.hasLocal || multiselect.hasMerged) const DeleteLocalActionButton(source: ActionSource.timeline), if (multiselect.hasLocal) const UploadActionButton(source: ActionSource.timeline), ], - slivers: [ - const AddToAlbumHeader(), - AlbumSelector(onAlbumSelected: addAssetsToAlbum, onKeyboardExpanded: onKeyboardExpand), - ], + slivers: multiselect.hasRemote + ? [ + const AddToAlbumHeader(), + AlbumSelector(onAlbumSelected: addAssetsToAlbum, onKeyboardExpanded: onKeyboardExpand), + ] + : [], ); } } diff --git a/mobile/lib/presentation/widgets/bottom_sheet/map_bottom_sheet.widget.dart b/mobile/lib/presentation/widgets/bottom_sheet/map_bottom_sheet.widget.dart index 19cce3392f..ac3772a02b 100644 --- a/mobile/lib/presentation/widgets/bottom_sheet/map_bottom_sheet.widget.dart +++ b/mobile/lib/presentation/widgets/bottom_sheet/map_bottom_sheet.widget.dart @@ -1,22 +1,25 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart'; import 'package:immich_mobile/presentation/widgets/map/map.state.dart'; import 'package:immich_mobile/presentation/widgets/timeline/timeline.widget.dart'; import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart'; +import 'package:immich_mobile/providers/user.provider.dart'; class MapBottomSheet extends StatelessWidget { const MapBottomSheet({super.key}); @override Widget build(BuildContext context) { - return const BaseBottomSheet( + return BaseBottomSheet( initialChildSize: 0.25, maxChildSize: 0.9, shouldCloseOnMinExtent: false, resizeOnScroll: false, actions: [], - slivers: [SliverFillRemaining(hasScrollBody: false, child: _ScopedMapTimeline())], + backgroundColor: context.themeData.colorScheme.surface, + slivers: [const SliverFillRemaining(hasScrollBody: false, child: _ScopedMapTimeline())], ); } } @@ -30,8 +33,13 @@ class _ScopedMapTimeline extends StatelessWidget { return ProviderScope( overrides: [ timelineServiceProvider.overrideWith((ref) { + final user = ref.watch(currentUserProvider); + if (user == null) { + throw Exception('User must be logged in to access archive'); + } + final bounds = ref.watch(mapStateProvider).bounds; - final timelineService = ref.watch(timelineFactoryProvider).map(bounds); + final timelineService = ref.watch(timelineFactoryProvider).map(user.id, bounds); ref.onDispose(timelineService.dispose); return timelineService; }), diff --git a/mobile/lib/presentation/widgets/bottom_sheet/remote_album_bottom_sheet.widget.dart b/mobile/lib/presentation/widgets/bottom_sheet/remote_album_bottom_sheet.widget.dart index 01daf7d2a2..7db8a80af2 100644 --- a/mobile/lib/presentation/widgets/bottom_sheet/remote_album_bottom_sheet.widget.dart +++ b/mobile/lib/presentation/widgets/bottom_sheet/remote_album_bottom_sheet.widget.dart @@ -1,12 +1,12 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/domain/models/album/album.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; +import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/archive_action_button.widget.dart'; -import 'package:immich_mobile/presentation/widgets/action_buttons/delete_permanent_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/delete_local_action_button.widget.dart'; +import 'package:immich_mobile/presentation/widgets/action_buttons/delete_permanent_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/download_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/edit_date_time_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/edit_location_action_button.widget.dart'; @@ -17,12 +17,14 @@ import 'package:immich_mobile/presentation/widgets/action_buttons/share_action_b import 'package:immich_mobile/presentation/widgets/action_buttons/share_link_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/stack_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/trash_action_button.widget.dart'; +import 'package:immich_mobile/presentation/widgets/action_buttons/unstack_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/upload_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/album/album_selector.widget.dart'; import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart'; import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; import 'package:immich_mobile/providers/server_info.provider.dart'; import 'package:immich_mobile/providers/timeline/multiselect.provider.dart'; +import 'package:immich_mobile/providers/user.provider.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart'; class RemoteAlbumBottomSheet extends ConsumerStatefulWidget { @@ -52,6 +54,7 @@ class _RemoteAlbumBottomSheetState extends ConsumerState Widget build(BuildContext context) { final multiselect = ref.watch(multiSelectProvider); final isTrashEnable = ref.watch(serverInfoProvider.select((state) => state.serverFeatures.trash)); + final ownsAlbum = ref.watch(currentUserProvider)?.id == widget.album.ownerId; Future addAssetsToAlbum(RemoteAlbum album) async { final selectedAssets = multiselect.selectedAssets; @@ -84,34 +87,43 @@ class _RemoteAlbumBottomSheetState extends ConsumerState return BaseBottomSheet( controller: sheetController, - initialChildSize: 0.45, + initialChildSize: 0.22, + minChildSize: 0.22, maxChildSize: 0.85, shouldCloseOnMinExtent: false, actions: [ const ShareActionButton(source: ActionSource.timeline), if (multiselect.hasRemote) ...[ const ShareLinkActionButton(source: ActionSource.timeline), - const ArchiveActionButton(source: ActionSource.timeline), - const FavoriteActionButton(source: ActionSource.timeline), + + if (ownsAlbum) ...[ + const ArchiveActionButton(source: ActionSource.timeline), + const FavoriteActionButton(source: ActionSource.timeline), + ], const DownloadActionButton(source: ActionSource.timeline), - isTrashEnable - ? const TrashActionButton(source: ActionSource.timeline) - : const DeletePermanentActionButton(source: ActionSource.timeline), - const EditDateTimeActionButton(source: ActionSource.timeline), - const EditLocationActionButton(source: ActionSource.timeline), - const MoveToLockFolderActionButton(source: ActionSource.timeline), - const StackActionButton(source: ActionSource.timeline), + if (ownsAlbum) ...[ + isTrashEnable + ? const TrashActionButton(source: ActionSource.timeline) + : const DeletePermanentActionButton(source: ActionSource.timeline), + const EditDateTimeActionButton(source: ActionSource.timeline), + const EditLocationActionButton(source: ActionSource.timeline), + const MoveToLockFolderActionButton(source: ActionSource.timeline), + if (multiselect.selectedAssets.length > 1) const StackActionButton(source: ActionSource.timeline), + if (multiselect.hasStacked) const UnStackActionButton(source: ActionSource.timeline), + ], ], if (multiselect.hasLocal) ...[ const DeleteLocalActionButton(source: ActionSource.timeline), const UploadActionButton(source: ActionSource.timeline), ], - RemoveFromAlbumActionButton(source: ActionSource.timeline, albumId: widget.album.id), - ], - slivers: [ - const AddToAlbumHeader(), - AlbumSelector(onAlbumSelected: addAssetsToAlbum, onKeyboardExpanded: onKeyboardExpand), + if (ownsAlbum) RemoveFromAlbumActionButton(source: ActionSource.timeline, albumId: widget.album.id), ], + slivers: ownsAlbum + ? [ + const AddToAlbumHeader(), + AlbumSelector(onAlbumSelected: addAssetsToAlbum, onKeyboardExpanded: onKeyboardExpand), + ] + : null, ); } } diff --git a/mobile/lib/presentation/widgets/images/image_provider.dart b/mobile/lib/presentation/widgets/images/image_provider.dart index dd87d2f228..810340aeb8 100644 --- a/mobile/lib/presentation/widgets/images/image_provider.dart +++ b/mobile/lib/presentation/widgets/images/image_provider.dart @@ -96,7 +96,7 @@ mixin CancellableImageProviderMixin on CancellableImageProvide final operation = cachedOperation; if (operation != null) { - this.cachedOperation = null; + cachedOperation = null; operation.cancel(); } } @@ -123,28 +123,14 @@ ImageProvider getFullImageProvider(BaseAsset asset, {Size size = const Size(1080 return provider; } -ImageProvider getThumbnailImageProvider({BaseAsset? asset, String? remoteId, Size size = kThumbnailResolution}) { - assert(asset != null || remoteId != null, 'Either asset or remoteId must be provided'); - - if (remoteId != null) { - return RemoteThumbProvider(assetId: remoteId); - } - - if (_shouldUseLocalAsset(asset!)) { +ImageProvider? getThumbnailImageProvider(BaseAsset asset, {Size size = kThumbnailResolution}) { + if (_shouldUseLocalAsset(asset)) { final id = asset is LocalAsset ? asset.id : (asset as RemoteAsset).localId!; return LocalThumbProvider(id: id, size: size, assetType: asset.type); } - final String assetId; - if (asset is LocalAsset && asset.hasRemote) { - assetId = asset.remoteId!; - } else if (asset is RemoteAsset) { - assetId = asset.id; - } else { - throw ArgumentError("Unsupported asset type: ${asset.runtimeType}"); - } - - return RemoteThumbProvider(assetId: assetId); + final assetId = asset is RemoteAsset ? asset.id : (asset as LocalAsset).remoteId; + return assetId != null ? RemoteThumbProvider(assetId: assetId) : null; } bool _shouldUseLocalAsset(BaseAsset asset) => diff --git a/mobile/lib/presentation/widgets/images/local_image_provider.dart b/mobile/lib/presentation/widgets/images/local_image_provider.dart index 223d095432..f90961ea5a 100644 --- a/mobile/lib/presentation/widgets/images/local_image_provider.dart +++ b/mobile/lib/presentation/widgets/images/local_image_provider.dart @@ -4,6 +4,8 @@ import 'dart:ui'; import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; +import 'package:immich_mobile/domain/models/store.model.dart'; +import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/infrastructure/loaders/image_request.dart'; import 'package:immich_mobile/presentation/widgets/images/image_provider.dart'; import 'package:immich_mobile/presentation/widgets/images/one_frame_multi_image_stream_completer.dart'; @@ -88,13 +90,26 @@ class LocalFullImageProvider extends CancellableImageProvider null, }, - imageProvider = switch (asset) { - RemoteAsset() => - asset.localId == null - ? RemoteThumbProvider(assetId: asset.id) - : LocalThumbProvider(id: asset.localId!, size: size, assetType: asset.type), - LocalAsset() => LocalThumbProvider(id: asset.id, size: size, assetType: asset.type), - _ => null, - }; + imageProvider = asset == null ? null : getThumbnailImageProvider(asset, size: size); @override State createState() => _ThumbnailState(); @@ -326,7 +318,7 @@ class _ThumbnailRenderBox extends RenderBox { image: _previousImage!, fit: _fit, filterQuality: FilterQuality.low, - opacity: 1.0 - _fadeValue, + opacity: 1.0, ); } else if (_image == null || _fadeValue < 1.0) { final paint = Paint()..shader = _placeholderGradient.createShader(rect); diff --git a/mobile/lib/presentation/widgets/images/thumbnail_tile.widget.dart b/mobile/lib/presentation/widgets/images/thumbnail_tile.widget.dart index cfcb7a8985..5359391261 100644 --- a/mobile/lib/presentation/widgets/images/thumbnail_tile.widget.dart +++ b/mobile/lib/presentation/widgets/images/thumbnail_tile.widget.dart @@ -16,7 +16,7 @@ class ThumbnailTile extends ConsumerWidget { this.asset, { this.size = kThumbnailResolution, this.fit = BoxFit.cover, - this.showStorageIndicator, + this.showStorageIndicator = false, this.lockSelection = false, this.heroOffset, super.key, @@ -25,7 +25,7 @@ class ThumbnailTile extends ConsumerWidget { final BaseAsset? asset; final Size size; final BoxFit fit; - final bool? showStorageIndicator; + final bool showStorageIndicator; final bool lockSelection; final int? heroOffset; @@ -54,10 +54,8 @@ class ThumbnailTile extends ConsumerWidget { ) : const BoxDecoration(); - final hasStack = asset is RemoteAsset && asset.stackId != null; - final bool storageIndicator = - showStorageIndicator ?? ref.watch(settingsProvider.select((s) => s.get(Setting.showStorageIndicator))); + ref.watch(settingsProvider.select((s) => s.get(Setting.showStorageIndicator))) && showStorageIndicator; return Stack( children: [ @@ -77,21 +75,10 @@ class ThumbnailTile extends ConsumerWidget { child: Thumbnail.fromAsset(asset: asset, size: size), ), ), - if (hasStack) + if (asset != null) Align( alignment: Alignment.topRight, - child: Padding( - padding: EdgeInsets.only(right: 10.0, top: asset.isVideo ? 24.0 : 6.0), - child: const _TileOverlayIcon(Icons.burst_mode_rounded), - ), - ), - if (asset != null && asset.isVideo) - Align( - alignment: Alignment.topRight, - child: Padding( - padding: const EdgeInsets.only(right: 10.0, top: 6.0), - child: _VideoIndicator(asset.duration), - ), + child: _AssetTypeIcons(asset: asset), ), if (storageIndicator && asset != null) switch (asset.storage) { @@ -214,3 +201,34 @@ class _TileOverlayIcon extends StatelessWidget { ); } } + +class _AssetTypeIcons extends StatelessWidget { + final BaseAsset asset; + + const _AssetTypeIcons({required this.asset}); + + @override + Widget build(BuildContext context) { + final hasStack = asset is RemoteAsset && (asset as RemoteAsset).stackId != null; + final isLivePhoto = asset is RemoteAsset && asset.livePhotoVideoId != null; + + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + if (asset.isVideo) + Padding(padding: const EdgeInsets.only(right: 10.0, top: 6.0), child: _VideoIndicator(asset.duration)), + if (hasStack) + const Padding( + padding: EdgeInsets.only(right: 10.0, top: 6.0), + child: _TileOverlayIcon(Icons.burst_mode_rounded), + ), + if (isLivePhoto) + const Padding( + padding: EdgeInsets.only(right: 10.0, top: 6.0), + child: _TileOverlayIcon(Icons.motion_photos_on_rounded), + ), + ], + ); + } +} diff --git a/mobile/lib/presentation/widgets/map/map.widget.dart b/mobile/lib/presentation/widgets/map/map.widget.dart index 0c3b37a3b4..c1d5bf6464 100644 --- a/mobile/lib/presentation/widgets/map/map.widget.dart +++ b/mobile/lib/presentation/widgets/map/map.widget.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:io'; +import 'dart:math'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; @@ -9,8 +10,8 @@ import 'package:immich_mobile/extensions/asyncvalue_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/presentation/widgets/bottom_sheet/map_bottom_sheet.widget.dart'; -import 'package:immich_mobile/presentation/widgets/map/map_utils.dart'; import 'package:immich_mobile/presentation/widgets/map/map.state.dart'; +import 'package:immich_mobile/presentation/widgets/map/map_utils.dart'; import 'package:immich_mobile/utils/async_mutex.dart'; import 'package:immich_mobile/utils/debounce.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart'; @@ -184,9 +185,13 @@ class _Map extends StatelessWidget { initialCameraPosition: initialLocation == null ? const CameraPosition(target: LatLng(0, 0), zoom: 0) : CameraPosition(target: initialLocation, zoom: MapUtils.mapZoomToAssetLevel), + compassEnabled: false, + rotateGesturesEnabled: false, styleString: style, onMapCreated: onMapCreated, onStyleLoadedCallback: onMapReady, + attributionButtonPosition: AttributionButtonPosition.topRight, + attributionButtonMargins: Platform.isIOS ? const Point(40, 12) : const Point(40, 72), ), ), ); diff --git a/mobile/lib/presentation/widgets/people/person_edit_birthday_modal.widget.dart b/mobile/lib/presentation/widgets/people/person_edit_birthday_modal.widget.dart index 8813224a5f..dd6390406b 100644 --- a/mobile/lib/presentation/widgets/people/person_edit_birthday_modal.widget.dart +++ b/mobile/lib/presentation/widgets/people/person_edit_birthday_modal.widget.dart @@ -8,6 +8,7 @@ import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/providers/infrastructure/people.provider.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart'; import 'package:scroll_date_picker/scroll_date_picker.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; class DriftPersonBirthdayEditForm extends ConsumerStatefulWidget { final DriftPerson person; @@ -36,7 +37,7 @@ class _DriftPersonNameEditFormState extends ConsumerState(_selectedDate); } } catch (error) { - debugPrint('Error updating birthday: $error'); + dPrint(() => 'Error updating birthday: $error'); if (!context.mounted) { return; diff --git a/mobile/lib/presentation/widgets/people/person_edit_name_modal.widget.dart b/mobile/lib/presentation/widgets/people/person_edit_name_modal.widget.dart index 46fd683b81..6de19000e0 100644 --- a/mobile/lib/presentation/widgets/people/person_edit_name_modal.widget.dart +++ b/mobile/lib/presentation/widgets/people/person_edit_name_modal.widget.dart @@ -7,6 +7,7 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/providers/infrastructure/people.provider.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; class DriftPersonNameEditForm extends ConsumerStatefulWidget { final DriftPerson person; @@ -34,7 +35,7 @@ class _DriftPersonNameEditFormState extends ConsumerState(newName); } } catch (error) { - debugPrint('Error updating name: $error'); + dPrint(() => 'Error updating name: $error'); if (!context.mounted) { return; diff --git a/mobile/lib/presentation/widgets/timeline/fixed/segment.model.dart b/mobile/lib/presentation/widgets/timeline/fixed/segment.model.dart index 50d04f646d..8121bb76d3 100644 --- a/mobile/lib/presentation/widgets/timeline/fixed/segment.model.dart +++ b/mobile/lib/presentation/widgets/timeline/fixed/segment.model.dart @@ -101,7 +101,6 @@ class _FixedSegmentRow extends ConsumerWidget { if (isScrubbing) { return _buildPlaceholder(context); } - if (timelineService.hasRange(assetIndex, assetCount)) { return _buildAssetRow(context, timelineService.getAssets(assetIndex, assetCount), timelineService); } diff --git a/mobile/lib/presentation/widgets/timeline/scrubber.widget.dart b/mobile/lib/presentation/widgets/timeline/scrubber.widget.dart index 6bac44cb86..58d7f933e9 100644 --- a/mobile/lib/presentation/widgets/timeline/scrubber.widget.dart +++ b/mobile/lib/presentation/widgets/timeline/scrubber.widget.dart @@ -3,14 +3,16 @@ import 'dart:async'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/constants/constants.dart'; import 'package:immich_mobile/domain/models/timeline.model.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/theme_extensions.dart'; import 'package:immich_mobile/presentation/widgets/timeline/constants.dart'; import 'package:immich_mobile/presentation/widgets/timeline/segment.model.dart'; import 'package:immich_mobile/presentation/widgets/timeline/timeline.state.dart'; -import 'package:intl/intl.dart' hide TextDirection; import 'package:immich_mobile/providers/haptic_feedback.provider.dart'; +import 'package:immich_mobile/utils/debounce.dart'; +import 'package:intl/intl.dart' hide TextDirection; /// A widget that will display a BoxScrollView with a ScrollThumb that can be dragged /// for quick navigation of the BoxScrollView. @@ -29,6 +31,11 @@ class Scrubber extends ConsumerStatefulWidget { final double? monthSegmentSnappingOffset; + final bool snapToMonth; + + /// Whether an app bar is present, affects coordinate calculations + final bool hasAppBar; + Scrubber({ super.key, Key? scrollThumbKey, @@ -37,6 +44,8 @@ class Scrubber extends ConsumerStatefulWidget { this.topPadding = 0, this.bottomPadding = 0, this.monthSegmentSnappingOffset, + this.snapToMonth = true, + this.hasAppBar = true, required this.child, }) : assert(child.scrollDirection == Axis.vertical); @@ -45,7 +54,7 @@ class Scrubber extends ConsumerStatefulWidget { } List<_Segment> _buildSegments({required List layoutSegments, required double timelineHeight}) { - const double offsetThreshold = 20.0; + const double offsetThreshold = 40.0; final segments = <_Segment>[]; if (layoutSegments.isEmpty || layoutSegments.first.bucket is! TimeBucket) { @@ -79,6 +88,9 @@ class ScrubberState extends ConsumerState with TickerProviderStateMixi double _thumbTopOffset = 0.0; bool _isDragging = false; List<_Segment> _segments = []; + int _monthCount = 0; + DateTime? _currentScrubberDate; + Debouncer? _scrubberDebouncer; late AnimationController _thumbAnimationController; Timer? _fadeOutTimer; @@ -105,6 +117,7 @@ class ScrubberState extends ConsumerState with TickerProviderStateMixi _thumbAnimationController = AnimationController(vsync: this, duration: kTimelineScrubberFadeInDuration); _thumbAnimation = CurvedAnimation(parent: _thumbAnimationController, curve: Curves.fastEaseInToSlowEaseOut); _labelAnimationController = AnimationController(vsync: this, duration: kTimelineScrubberFadeInDuration); + _monthCount = getMonthCount(); _labelAnimation = CurvedAnimation(parent: _labelAnimationController, curve: Curves.fastOutSlowIn); } @@ -121,6 +134,7 @@ class ScrubberState extends ConsumerState with TickerProviderStateMixi if (oldWidget.layoutSegments.lastOrNull?.endOffset != widget.layoutSegments.lastOrNull?.endOffset) { _segments = _buildSegments(layoutSegments: widget.layoutSegments, timelineHeight: _scrubberHeight); + _monthCount = getMonthCount(); } } @@ -129,6 +143,7 @@ class ScrubberState extends ConsumerState with TickerProviderStateMixi _thumbAnimationController.dispose(); _labelAnimationController.dispose(); _fadeOutTimer?.cancel(); + _scrubberDebouncer?.dispose(); super.dispose(); } @@ -140,6 +155,10 @@ class ScrubberState extends ConsumerState with TickerProviderStateMixi }); } + int getMonthCount() { + return _segments.map((e) => "${e.date.month}_${e.date.year}").toSet().length; + } + bool _onScrollNotification(ScrollNotification notification) { if (_isDragging) { // If the user is dragging the thumb, we don't want to update the position @@ -168,8 +187,25 @@ class ScrubberState extends ConsumerState with TickerProviderStateMixi return false; } + void _onScrubberDateChanged(DateTime date) { + if (_currentScrubberDate != date) { + // Date changed, immediately set scrubbing to true + _currentScrubberDate = date; + ref.read(timelineStateProvider.notifier).setScrubbing(true); + + // Initialize debouncer if needed + _scrubberDebouncer ??= Debouncer(interval: const Duration(milliseconds: 50)); + + // Debounce setting scrubbing to false + _scrubberDebouncer!.run(() { + if (_currentScrubberDate == date) { + ref.read(timelineStateProvider.notifier).setScrubbing(false); + } + }); + } + } + void _onDragStart(DragStartDetails _) { - ref.read(timelineStateProvider.notifier).setScrubbing(true); setState(() { _isDragging = true; _labelAnimationController.forward(); @@ -191,13 +227,27 @@ class ScrubberState extends ConsumerState with TickerProviderStateMixi final nearestMonthSegment = _findNearestMonthSegment(dragPosition); if (nearestMonthSegment != null) { - _snapToSegment(nearestMonthSegment); final label = nearestMonthSegment.scrollLabel; if (_lastLabel != label) { ref.read(hapticFeedbackProvider.notifier).selectionClick(); _lastLabel = label; + + // Notify timeline state of the new scrubber date position + if (_monthCount >= kMinMonthsToEnableScrubberSnap) { + _onScrubberDateChanged(nearestMonthSegment.date); + } } } + + if (_monthCount < kMinMonthsToEnableScrubberSnap || !widget.snapToMonth) { + // If there are less than kMinMonthsToEnableScrubberSnap months, we don't need to snap to segments + setState(() { + _thumbTopOffset = dragPosition; + _scrollController.jumpTo((dragPosition / _scrubberHeight) * _scrollController.position.maxScrollExtent); + }); + } else if (nearestMonthSegment != null) { + _snapToSegment(nearestMonthSegment); + } } /// Calculate the drag position relative to the scrubber area @@ -216,14 +266,28 @@ class ScrubberState extends ConsumerState with TickerProviderStateMixi /// - If user drags to global Y position that's 100 pixels from the top /// - The relative position would be 100 - 50 = 50 (50 pixels into the scrubber area) double _calculateDragPosition(DragUpdateDetails details) { + if (widget.hasAppBar) { + final dragAreaTop = widget.topPadding; + final dragAreaBottom = widget.timelineHeight - widget.bottomPadding; + final dragAreaHeight = dragAreaBottom - dragAreaTop; + + final relativePosition = details.globalPosition.dy - dragAreaTop; + + // Make sure the position stays within the scrubber's bounds + return relativePosition.clamp(0.0, dragAreaHeight); + } + + // Get the local position relative to the gesture detector + final RenderBox? renderBox = context.findRenderObject() as RenderBox?; + if (renderBox != null) { + final localPosition = renderBox.globalToLocal(details.globalPosition); + return localPosition.dy.clamp(0.0, _scrubberHeight); + } + + // Fallback to current logic if render box is not available final dragAreaTop = widget.topPadding; - final dragAreaBottom = widget.timelineHeight - widget.bottomPadding; - final dragAreaHeight = dragAreaBottom - dragAreaTop; - final relativePosition = details.globalPosition.dy - dragAreaTop; - - // Make sure the position stays within the scrubber's bounds - return relativePosition.clamp(0.0, dragAreaHeight); + return relativePosition.clamp(0.0, _scrubberHeight); } /// Find the segment closest to the given position @@ -274,12 +338,18 @@ class ScrubberState extends ConsumerState with TickerProviderStateMixi } void _onDragEnd(DragEndDetails _) { - ref.read(timelineStateProvider.notifier).setScrubbing(false); _labelAnimationController.reverse(); setState(() { _isDragging = false; }); + ref.read(timelineStateProvider.notifier).setScrubbing(false); + + // Reset scrubber tracking when drag ends + _currentScrubberDate = null; + _scrubberDebouncer?.dispose(); + _scrubberDebouncer = null; + _resetThumbTimer(); } @@ -370,7 +440,7 @@ class _SegmentWidget extends StatelessWidget { Widget build(BuildContext context) { return IgnorePointer( child: Container( - margin: const EdgeInsets.only(right: 12.0), + margin: const EdgeInsets.only(right: 36.0), child: Material( color: context.colorScheme.surface, borderRadius: const BorderRadius.all(Radius.circular(16.0)), diff --git a/mobile/lib/presentation/widgets/timeline/timeline.state.dart b/mobile/lib/presentation/widgets/timeline/timeline.state.dart index da1f7fcc9d..1e1d4130f7 100644 --- a/mobile/lib/presentation/widgets/timeline/timeline.state.dart +++ b/mobile/lib/presentation/widgets/timeline/timeline.state.dart @@ -14,7 +14,7 @@ class TimelineArgs { final double maxHeight; final double spacing; final int columnCount; - final bool? showStorageIndicator; + final bool showStorageIndicator; final bool withStack; final GroupAssetsBy? groupBy; @@ -23,7 +23,7 @@ class TimelineArgs { required this.maxHeight, this.spacing = kTimelineSpacing, this.columnCount = kTimelineColumnCount, - this.showStorageIndicator, + this.showStorageIndicator = false, this.withStack = false, this.groupBy, }); @@ -72,8 +72,6 @@ class TimelineState { } class TimelineStateNotifier extends Notifier { - TimelineStateNotifier(); - void setScrubbing(bool isScrubbing) { state = state.copyWith(isScrubbing: isScrubbing); } diff --git a/mobile/lib/presentation/widgets/timeline/timeline.widget.dart b/mobile/lib/presentation/widgets/timeline/timeline.widget.dart index 125f8505a1..5f1e7f27b0 100644 --- a/mobile/lib/presentation/widgets/timeline/timeline.widget.dart +++ b/mobile/lib/presentation/widgets/timeline/timeline.widget.dart @@ -14,6 +14,7 @@ import 'package:immich_mobile/domain/models/timeline.model.dart'; import 'package:immich_mobile/domain/utils/event_stream.dart'; import 'package:immich_mobile/extensions/asyncvalue_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_mobile/presentation/widgets/action_buttons/download_status_floating_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/bottom_sheet/general_bottom_sheet.widget.dart'; import 'package:immich_mobile/presentation/widgets/timeline/scrubber.widget.dart'; import 'package:immich_mobile/presentation/widgets/timeline/segment.model.dart'; @@ -32,27 +33,32 @@ class Timeline extends StatelessWidget { super.key, this.topSliverWidget, this.topSliverWidgetHeight, - this.showStorageIndicator, + this.showStorageIndicator = false, this.withStack = false, this.appBar = const ImmichSliverAppBar(floating: true, pinned: false, snap: false), - this.bottomSheet = const GeneralBottomSheet(), + this.bottomSheet = const GeneralBottomSheet(minChildSize: 0.23), this.groupBy, this.withScrubber = true, + this.snapToMonth = true, + this.initialScrollOffset, }); final Widget? topSliverWidget; final double? topSliverWidgetHeight; - final bool? showStorageIndicator; + final bool showStorageIndicator; final Widget? appBar; final Widget? bottomSheet; final bool withStack; final GroupAssetsBy? groupBy; final bool withScrubber; + final bool snapToMonth; + final double? initialScrollOffset; @override Widget build(BuildContext context) { return Scaffold( resizeToAvoidBottomInset: false, + floatingActionButton: const DownloadStatusFloatingButton(), body: LayoutBuilder( builder: (_, constraints) => ProviderScope( overrides: [ @@ -73,6 +79,8 @@ class Timeline extends StatelessWidget { appBar: appBar, bottomSheet: bottomSheet, withScrubber: withScrubber, + snapToMonth: snapToMonth, + initialScrollOffset: initialScrollOffset, ), ), ), @@ -87,6 +95,8 @@ class _SliverTimeline extends ConsumerStatefulWidget { this.appBar, this.bottomSheet, this.withScrubber = true, + this.snapToMonth = true, + this.initialScrollOffset, }); final Widget? topSliverWidget; @@ -94,13 +104,15 @@ class _SliverTimeline extends ConsumerStatefulWidget { final Widget? appBar; final Widget? bottomSheet; final bool withScrubber; + final bool snapToMonth; + final double? initialScrollOffset; @override ConsumerState createState() => _SliverTimelineState(); } class _SliverTimelineState extends ConsumerState<_SliverTimeline> { - final _scrollController = ScrollController(); + late final ScrollController _scrollController; StreamSubscription? _eventSubscription; // Drag selection state @@ -112,10 +124,15 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> { int _perRow = 4; double _scaleFactor = 3.0; double _baseScaleFactor = 3.0; + int? _scaleRestoreAssetIndex; @override void initState() { super.initState(); + _scrollController = ScrollController( + initialScrollOffset: widget.initialScrollOffset ?? 0.0, + onAttach: _restoreScalePosition, + ); _eventSubscription = EventStream.shared.listen(_onEvent); final currentTilesPerRow = ref.read(settingsProvider).get(Setting.tilesPerRow); @@ -129,7 +146,11 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> { void _onEvent(Event event) { switch (event) { case ScrollToTopEvent(): - _scrollController.animateTo(0, duration: const Duration(milliseconds: 250), curve: Curves.easeInOut); + ref.read(timelineStateProvider.notifier).setScrubbing(true); + _scrollController + .animateTo(0, duration: const Duration(milliseconds: 250), curve: Curves.easeInOut) + .whenComplete(() => ref.read(timelineStateProvider.notifier).setScrubbing(false)); + case ScrollToDateEvent scrollToDateEvent: _scrollToDate(scrollToDateEvent.date); case TimelineReloadEvent(): @@ -143,6 +164,28 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> { EventStream.shared.emit(MultiSelectToggleEvent(isEnabled)); } + void _restoreScalePosition(_) { + if (_scaleRestoreAssetIndex == null) return; + + final asyncSegments = ref.read(timelineSegmentProvider); + asyncSegments.whenData((segments) { + final targetSegment = segments.lastWhereOrNull((segment) => segment.firstAssetIndex <= _scaleRestoreAssetIndex!); + if (targetSegment != null) { + final assetIndexInSegment = _scaleRestoreAssetIndex! - targetSegment.firstAssetIndex; + final newColumnCount = ref.read(timelineArgsProvider).columnCount; + final rowIndexInSegment = (assetIndexInSegment / newColumnCount).floor(); + final targetRowIndex = targetSegment.firstIndex + 1 + rowIndexInSegment; + final targetOffset = targetSegment.indexToLayoutOffset(targetRowIndex); + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + _scrollController.jumpTo(targetOffset.clamp(0.0, _scrollController.position.maxScrollExtent)); + } + }); + } + }); + _scaleRestoreAssetIndex = null; + } + @override void dispose() { _scrollController.dispose(); @@ -177,11 +220,14 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> { if (fallbackSegment != null) { // Scroll to the segment with a small offset to show the header final targetOffset = fallbackSegment.startOffset - 50; - _scrollController.animateTo( - targetOffset.clamp(0.0, _scrollController.position.maxScrollExtent), - duration: const Duration(milliseconds: 500), - curve: Curves.easeInOut, - ); + ref.read(timelineStateProvider.notifier).setScrubbing(true); + _scrollController + .animateTo( + targetOffset.clamp(0.0, _scrollController.position.maxScrollExtent), + duration: const Duration(milliseconds: 500), + curve: Curves.easeInOut, + ) + .whenComplete(() => ref.read(timelineStateProvider.notifier).setScrubbing(false)); } }); } @@ -305,11 +351,13 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> { final Widget timeline; if (widget.withScrubber) { timeline = Scrubber( + snapToMonth: widget.snapToMonth, layoutSegments: segments, timelineHeight: maxHeight, topPadding: topPadding, bottomPadding: bottomPadding, monthSegmentSnappingOffset: widget.topSliverWidgetHeight ?? 0 + appBarExpandedHeight, + hasAppBar: widget.appBar != null, child: grid, ); } else { @@ -332,9 +380,28 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> { final newPerRow = 7 - newScaleFactor.toInt(); if (newPerRow != _perRow) { + final currentOffset = _scrollController.offset.clamp( + 0.0, + _scrollController.position.maxScrollExtent, + ); + final segment = segments.findByOffset(currentOffset) ?? segments.lastOrNull; + int? targetAssetIndex; + if (segment != null) { + final rowIndex = segment.getMinChildIndexForScrollOffset(currentOffset); + if (rowIndex > segment.firstIndex) { + final rowIndexInSegment = rowIndex - (segment.firstIndex + 1); + final assetsPerRow = ref.read(timelineArgsProvider).columnCount; + final assetIndexInSegment = rowIndexInSegment * assetsPerRow; + targetAssetIndex = segment.firstAssetIndex + assetIndexInSegment; + } else { + targetAssetIndex = segment.firstAssetIndex; + } + } + setState(() { _scaleFactor = newScaleFactor; _perRow = newPerRow; + _scaleRestoreAssetIndex = targetAssetIndex; }); ref.read(settingsProvider.notifier).set(Setting.tilesPerRow, _perRow); @@ -356,7 +423,14 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> { children: [ timeline, if (!isSelectionMode && isMultiSelectEnabled) ...[ - const Positioned(top: 60, left: 25, child: _MultiSelectStatusButton()), + Positioned( + top: MediaQuery.paddingOf(context).top, + left: 25, + child: const SizedBox( + height: kToolbarHeight, + child: Center(child: _MultiSelectStatusButton()), + ), + ), if (widget.bottomSheet != null) widget.bottomSheet!, ], ], diff --git a/mobile/lib/providers/app_life_cycle.provider.dart b/mobile/lib/providers/app_life_cycle.provider.dart index 3da653444c..3b51874ab5 100644 --- a/mobile/lib/providers/app_life_cycle.provider.dart +++ b/mobile/lib/providers/app_life_cycle.provider.dart @@ -1,8 +1,8 @@ import 'dart:async'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/domain/models/store.model.dart'; import 'package:immich_mobile/domain/services/log.service.dart'; -import 'package:immich_mobile/domain/utils/isolate_lock_manager.dart'; import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/models/backup/backup_state.model.dart'; import 'package:immich_mobile/providers/album/album.provider.dart'; @@ -15,11 +15,11 @@ import 'package:immich_mobile/providers/backup/drift_backup.provider.dart'; import 'package:immich_mobile/providers/backup/ios_background_settings.provider.dart'; import 'package:immich_mobile/providers/backup/manual_upload.provider.dart'; import 'package:immich_mobile/providers/gallery_permission.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/platform.provider.dart'; import 'package:immich_mobile/providers/memory.provider.dart'; import 'package:immich_mobile/providers/notification_permission.provider.dart'; import 'package:immich_mobile/providers/server_info.provider.dart'; import 'package:immich_mobile/providers/tab.provider.dart'; -import 'package:immich_mobile/providers/user.provider.dart'; import 'package:immich_mobile/providers/websocket.provider.dart'; import 'package:immich_mobile/services/app_settings.service.dart'; import 'package:immich_mobile/services/background.service.dart'; @@ -125,93 +125,63 @@ class AppLifeCycleNotifier extends StateNotifier { } } + Future _safeRun(Future action, String debugName) async { + if (!_shouldContinueOperation()) { + return; + } + + try { + await action; + } catch (e, stackTrace) { + _log.warning("Error during $debugName operation", e, stackTrace); + } + } + Future _handleBetaTimelineResume() async { _ref.read(backupProvider.notifier).cancelBackup(); - final lockManager = _ref.read(isolateLockManagerProvider(kIsolateLockManagerPort)); + unawaited(_ref.read(backgroundWorkerLockServiceProvider).lock()); // Give isolates time to complete any ongoing database transactions await Future.delayed(const Duration(milliseconds: 500)); - lockManager.requestHolderToClose(); - - // Add timeout to prevent deadlock on lock acquisition - try { - await lockManager.acquireLock().timeout( - const Duration(seconds: 10), - onTimeout: () { - _log.warning("Lock acquisition timed out, proceeding without lock"); - throw TimeoutException("Lock acquisition timed out", const Duration(seconds: 10)); - }, - ); - } catch (e) { - _log.warning("Failed to acquire lock: $e"); - return; - } - final backgroundManager = _ref.read(backgroundSyncProvider); final isAlbumLinkedSyncEnable = _ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.syncAlbums); try { - // Run operations sequentially with state checks and error handling for each - if (_shouldContinueOperation()) { - try { - await backgroundManager.syncLocal(); - } catch (e, stackTrace) { - _log.warning("Failed syncLocal: $e", e, stackTrace); - } + bool syncSuccess = false; + await Future.wait([ + _safeRun(backgroundManager.syncLocal(), "syncLocal"), + _safeRun(backgroundManager.syncRemote().then((success) => syncSuccess = success), "syncRemote"), + ]); + if (syncSuccess) { + await Future.wait([ + _safeRun(backgroundManager.hashAssets(), "hashAssets").then((_) { + _resumeBackup(); + }), + _resumeBackup(), + ]); + } else { + await _safeRun(backgroundManager.hashAssets(), "hashAssets"); } - // Check if app is still active before hashing - if (_shouldContinueOperation()) { - try { - await backgroundManager.hashAssets(); - } catch (e, stackTrace) { - _log.warning("Failed hashAssets: $e", e, stackTrace); - } - } - - // Check if app is still active before remote sync - if (_shouldContinueOperation()) { - try { - await backgroundManager.syncRemote(); - } catch (e, stackTrace) { - _log.warning("Failed syncRemote: $e", e, stackTrace); - } - - if (isAlbumLinkedSyncEnable && _shouldContinueOperation()) { - try { - await backgroundManager.syncLinkedAlbum(); - } catch (e, stackTrace) { - _log.warning("Failed syncLinkedAlbum: $e", e, stackTrace); - } - } - } - - // Handle backup resume only if still active - if (_shouldContinueOperation()) { - final isEnableBackup = _ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableBackup); - - if (isEnableBackup) { - final currentUser = _ref.read(currentUserProvider); - if (currentUser != null) { - try { - await _ref.read(driftBackupProvider.notifier).handleBackupResume(currentUser.id); - _log.fine("Completed backup resume"); - } catch (e, stackTrace) { - _log.warning("Failed backup resume: $e", e, stackTrace); - } - } - } + if (isAlbumLinkedSyncEnable) { + await _safeRun(backgroundManager.syncLinkedAlbum(), "syncLinkedAlbum"); } } catch (e, stackTrace) { _log.severe("Error during background sync", e, stackTrace); - } finally { - // Ensure lock is released even if operations fail - try { - lockManager.releaseLock(); - _log.fine("Lock released after background sync operations"); - } catch (lockError) { - _log.warning("Failed to release lock after error: $lockError"); + } + } + + Future _resumeBackup() async { + final isEnableBackup = _ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableBackup); + + if (isEnableBackup) { + final currentUser = Store.tryGet(StoreKey.currentUser); + if (currentUser != null) { + await _safeRun( + _ref.read(driftBackupProvider.notifier).handleBackupResume(currentUser.id), + "handleBackupResume", + ); } } } @@ -245,6 +215,9 @@ class AppLifeCycleNotifier extends StateNotifier { _pauseOperation = Completer(); try { + if (Store.isBetaTimelineEnabled) { + unawaited(_ref.read(backgroundWorkerLockServiceProvider).unlock()); + } await _performPause(); } catch (e, stackTrace) { _log.severe("Error during app pause", e, stackTrace); @@ -263,28 +236,6 @@ class AppLifeCycleNotifier extends StateNotifier { if (_ref.read(backupProvider.notifier).backupProgress != BackUpProgressEnum.manualInProgress) { _ref.read(backupProvider.notifier).cancelBackup(); } - } else { - final backgroundManager = _ref.read(backgroundSyncProvider); - - // Cancel operations with extended timeout to allow database transactions to complete - try { - await Future.wait([ - backgroundManager.cancel().timeout(const Duration(seconds: 10)), - backgroundManager.cancelLocal().timeout(const Duration(seconds: 10)), - ]).timeout(const Duration(seconds: 15)); - - // Give additional time for isolates to clean up database connections - await Future.delayed(const Duration(milliseconds: 1000)); - } catch (e) { - _log.warning("Timeout during background cancellation: $e"); - } - - // Always release the lock, even if cancellation failed - try { - _ref.read(isolateLockManagerProvider(kIsolateLockManagerPort)).releaseLock(); - } catch (e) { - _log.warning("Failed to release lock on pause: $e"); - } } _ref.read(websocketProvider.notifier).disconnect(); @@ -298,6 +249,10 @@ class AppLifeCycleNotifier extends StateNotifier { Future handleAppDetached() async { state = AppLifeCycleEnum.detached; + if (Store.isBetaTimelineEnabled) { + unawaited(_ref.read(backgroundWorkerLockServiceProvider).unlock()); + } + // Flush logs before closing database try { LogService.I.flush(); @@ -312,7 +267,6 @@ class AppLifeCycleNotifier extends StateNotifier { } catch (_) {} if (Store.isBetaTimelineEnabled) { - _ref.read(isolateLockManagerProvider(kIsolateLockManagerPort)).releaseLock(); return; } diff --git a/mobile/lib/providers/asset.provider.dart b/mobile/lib/providers/asset.provider.dart index 9c8b28e6cf..75635950ff 100644 --- a/mobile/lib/providers/asset.provider.dart +++ b/mobile/lib/providers/asset.provider.dart @@ -1,4 +1,3 @@ -import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/domain/models/store.model.dart'; @@ -13,6 +12,7 @@ import 'package:immich_mobile/services/etag.service.dart'; import 'package:immich_mobile/services/exif.service.dart'; import 'package:immich_mobile/services/sync.service.dart'; import 'package:logging/logging.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; final assetProvider = StateNotifierProvider((ref) { return AssetNotifier( @@ -68,7 +68,7 @@ class AssetNotifier extends StateNotifier { } final bool newRemote = await _assetService.refreshRemoteAssets(); final bool newLocal = await _albumService.refreshDeviceAlbums(); - debugPrint("changedUsers: $changedUsers, newRemote: $newRemote, newLocal: $newLocal"); + dPrint(() => "changedUsers: $changedUsers, newRemote: $newRemote, newLocal: $newLocal"); if (newRemote) { _ref.invalidate(memoryFutureProvider); } diff --git a/mobile/lib/providers/auth.provider.dart b/mobile/lib/providers/auth.provider.dart index 6c39eb0dec..9a15598998 100644 --- a/mobile/lib/providers/auth.provider.dart +++ b/mobile/lib/providers/auth.provider.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter_udid/flutter_udid.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/constants.dart'; @@ -18,6 +17,7 @@ import 'package:immich_mobile/services/widget.service.dart'; import 'package:immich_mobile/utils/hash.dart'; import 'package:logging/logging.dart'; import 'package:openapi/api.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; final authProvider = StateNotifierProvider((ref) { return AuthNotifier( @@ -150,10 +150,7 @@ class AuthNotifier extends StateNotifier { _log.severe("Error getting user information from the server [API EXCEPTION]", stackTrace); } catch (error, stackTrace) { _log.severe("Error getting user information from the server [CATCH ALL]", error, stackTrace); - - if (kDebugMode) { - debugPrint("Error getting user information from the server [CATCH ALL] $error $stackTrace"); - } + dPrint(() => "Error getting user information from the server [CATCH ALL] $error $stackTrace"); } // If the user is null, the login was not successful diff --git a/mobile/lib/providers/background_sync.provider.dart b/mobile/lib/providers/background_sync.provider.dart index 1981c45fb1..a61cd93022 100644 --- a/mobile/lib/providers/background_sync.provider.dart +++ b/mobile/lib/providers/background_sync.provider.dart @@ -1,13 +1,21 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/utils/background_sync.dart'; -import 'package:immich_mobile/domain/utils/isolate_lock_manager.dart'; +import 'package:immich_mobile/providers/backup/drift_backup.provider.dart'; import 'package:immich_mobile/providers/sync_status.provider.dart'; final backgroundSyncProvider = Provider((ref) { final syncStatusNotifier = ref.read(syncStatusProvider.notifier); + final backupProvider = ref.read(driftBackupProvider.notifier); + final manager = BackgroundSyncManager( - onRemoteSyncStart: syncStatusNotifier.startRemoteSync, - onRemoteSyncComplete: syncStatusNotifier.completeRemoteSync, + onRemoteSyncStart: () { + syncStatusNotifier.startRemoteSync(); + backupProvider.updateError(BackupError.none); + }, + onRemoteSyncComplete: (isSuccess) { + syncStatusNotifier.completeRemoteSync(); + backupProvider.updateError(isSuccess == true ? BackupError.none : BackupError.syncFailed); + }, onRemoteSyncError: syncStatusNotifier.errorRemoteSync, onLocalSyncStart: syncStatusNotifier.startLocalSync, onLocalSyncComplete: syncStatusNotifier.completeLocalSync, @@ -19,7 +27,3 @@ final backgroundSyncProvider = Provider((ref) { ref.onDispose(manager.cancel); return manager; }); - -final isolateLockManagerProvider = Provider.family((ref, name) { - return IsolateLockManager(portName: name); -}); diff --git a/mobile/lib/providers/backup/backup.provider.dart b/mobile/lib/providers/backup/backup.provider.dart index 6035e53e5d..03666466ff 100644 --- a/mobile/lib/providers/backup/backup.provider.dart +++ b/mobile/lib/providers/backup/backup.provider.dart @@ -2,11 +2,8 @@ import 'dart:io'; import 'package:cancellation_token_http/http.dart'; import 'package:collection/collection.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/widgets.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/store.model.dart'; -import 'package:immich_mobile/domain/services/background_worker.service.dart'; import 'package:immich_mobile/entities/album.entity.dart'; import 'package:immich_mobile/entities/backup_album.entity.dart'; import 'package:immich_mobile/entities/store.entity.dart'; @@ -18,7 +15,6 @@ import 'package:immich_mobile/models/backup/current_upload_asset.model.dart'; import 'package:immich_mobile/models/backup/error_upload_asset.model.dart'; import 'package:immich_mobile/models/backup/success_upload_asset.model.dart'; import 'package:immich_mobile/models/server_info/server_disk_info.model.dart'; -import 'package:immich_mobile/platform/background_worker_api.g.dart'; import 'package:immich_mobile/providers/app_life_cycle.provider.dart'; import 'package:immich_mobile/providers/auth.provider.dart'; import 'package:immich_mobile/providers/backup/error_backup_list.provider.dart'; @@ -35,8 +31,7 @@ import 'package:immich_mobile/utils/diff.dart'; import 'package:logging/logging.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:photo_manager/photo_manager.dart' show PMProgressHandler; - -final driftBackgroundUploadFgService = Provider((ref) => BackgroundWorkerFgService(BackgroundWorkerFgHostApi())); +import 'package:immich_mobile/utils/debug_print.dart'; final backupProvider = StateNotifierProvider((ref) { return BackupNotifier( @@ -290,7 +285,7 @@ class BackupNotifier extends StateNotifier { state = state.copyWith(selectedBackupAlbums: selectedAlbums, excludedBackupAlbums: excludedAlbums); log.info("_getBackupAlbumsInfo: Found ${availableAlbums.length} available albums"); - debugPrint("_getBackupAlbumsInfo takes ${stopwatch.elapsedMilliseconds}ms"); + dPrint(() => "_getBackupAlbumsInfo takes ${stopwatch.elapsedMilliseconds}ms"); } /// @@ -432,7 +427,7 @@ class BackupNotifier extends StateNotifier { /// Invoke backup process Future startBackupProcess() async { - debugPrint("Start backup process"); + dPrint(() => "Start backup process"); assert(state.backupProgress == BackUpProgressEnum.idle); state = state.copyWith(backupProgress: BackUpProgressEnum.inProgress); diff --git a/mobile/lib/providers/backup/drift_backup.provider.dart b/mobile/lib/providers/backup/drift_backup.provider.dart index 418410de0c..f52fc654f2 100644 --- a/mobile/lib/providers/backup/drift_backup.provider.dart +++ b/mobile/lib/providers/backup/drift_backup.provider.dart @@ -1,18 +1,18 @@ // ignore_for_file: public_member_api_docs, sort_constructors_first import 'dart:async'; -import 'dart:convert'; import 'package:background_downloader/background_downloader.dart'; import 'package:collection/collection.dart'; -import 'package:flutter/widgets.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; - import 'package:immich_mobile/constants/constants.dart'; import 'package:immich_mobile/domain/models/album/local_album.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/repositories/backup.repository.dart'; +import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; import 'package:immich_mobile/services/upload.service.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; import 'package:logging/logging.dart'; class EnqueueStatus { @@ -36,6 +36,7 @@ class DriftUploadStatus { final int fileSize; final String networkSpeedAsString; final bool? isFailed; + final String? error; const DriftUploadStatus({ required this.taskId, @@ -44,6 +45,7 @@ class DriftUploadStatus { required this.fileSize, required this.networkSpeedAsString, this.isFailed, + this.error, }); DriftUploadStatus copyWith({ @@ -53,6 +55,7 @@ class DriftUploadStatus { int? fileSize, String? networkSpeedAsString, bool? isFailed, + String? error, }) { return DriftUploadStatus( taskId: taskId ?? this.taskId, @@ -61,12 +64,13 @@ class DriftUploadStatus { fileSize: fileSize ?? this.fileSize, networkSpeedAsString: networkSpeedAsString ?? this.networkSpeedAsString, isFailed: isFailed ?? this.isFailed, + error: error ?? this.error, ); } @override String toString() { - return 'DriftUploadStatus(taskId: $taskId, filename: $filename, progress: $progress, fileSize: $fileSize, networkSpeedAsString: $networkSpeedAsString, isFailed: $isFailed)'; + return 'DriftUploadStatus(taskId: $taskId, filename: $filename, progress: $progress, fileSize: $fileSize, networkSpeedAsString: $networkSpeedAsString, isFailed: $isFailed, error: $error)'; } @override @@ -78,7 +82,8 @@ class DriftUploadStatus { other.progress == progress && other.fileSize == fileSize && other.networkSpeedAsString == networkSpeedAsString && - other.isFailed == isFailed; + other.isFailed == isFailed && + other.error == error; } @override @@ -88,46 +93,25 @@ class DriftUploadStatus { progress.hashCode ^ fileSize.hashCode ^ networkSpeedAsString.hashCode ^ - isFailed.hashCode; + isFailed.hashCode ^ + error.hashCode; } - - Map toMap() { - return { - 'taskId': taskId, - 'filename': filename, - 'progress': progress, - 'fileSize': fileSize, - 'networkSpeedAsString': networkSpeedAsString, - 'isFailed': isFailed, - }; - } - - factory DriftUploadStatus.fromMap(Map map) { - return DriftUploadStatus( - taskId: map['taskId'] as String, - filename: map['filename'] as String, - progress: map['progress'] as double, - fileSize: map['fileSize'] as int, - networkSpeedAsString: map['networkSpeedAsString'] as String, - isFailed: map['isFailed'] != null ? map['isFailed'] as bool : null, - ); - } - - String toJson() => json.encode(toMap()); - - factory DriftUploadStatus.fromJson(String source) => - DriftUploadStatus.fromMap(json.decode(source) as Map); } +enum BackupError { none, syncFailed } + class DriftBackupState { final int totalCount; final int backupCount; final int remainderCount; + final int processingCount; final int enqueueCount; final int enqueueTotalCount; + final bool isSyncing; final bool isCanceling; + final BackupError error; final Map uploadItems; @@ -135,35 +119,44 @@ class DriftBackupState { required this.totalCount, required this.backupCount, required this.remainderCount, + required this.processingCount, required this.enqueueCount, required this.enqueueTotalCount, required this.isCanceling, + required this.isSyncing, required this.uploadItems, + this.error = BackupError.none, }); DriftBackupState copyWith({ int? totalCount, int? backupCount, int? remainderCount, + int? processingCount, int? enqueueCount, int? enqueueTotalCount, bool? isCanceling, + bool? isSyncing, Map? uploadItems, + BackupError? error, }) { return DriftBackupState( totalCount: totalCount ?? this.totalCount, backupCount: backupCount ?? this.backupCount, remainderCount: remainderCount ?? this.remainderCount, + processingCount: processingCount ?? this.processingCount, enqueueCount: enqueueCount ?? this.enqueueCount, enqueueTotalCount: enqueueTotalCount ?? this.enqueueTotalCount, isCanceling: isCanceling ?? this.isCanceling, + isSyncing: isSyncing ?? this.isSyncing, uploadItems: uploadItems ?? this.uploadItems, + error: error ?? this.error, ); } @override String toString() { - return 'DriftBackupState(totalCount: $totalCount, backupCount: $backupCount, remainderCount: $remainderCount, enqueueCount: $enqueueCount, enqueueTotalCount: $enqueueTotalCount, isCanceling: $isCanceling, uploadItems: $uploadItems)'; + return 'DriftBackupState(totalCount: $totalCount, backupCount: $backupCount, remainderCount: $remainderCount, processingCount: $processingCount, enqueueCount: $enqueueCount, enqueueTotalCount: $enqueueTotalCount, isCanceling: $isCanceling, isSyncing: $isSyncing, uploadItems: $uploadItems, error: $error)'; } @override @@ -174,10 +167,13 @@ class DriftBackupState { return other.totalCount == totalCount && other.backupCount == backupCount && other.remainderCount == remainderCount && + other.processingCount == processingCount && other.enqueueCount == enqueueCount && other.enqueueTotalCount == enqueueTotalCount && other.isCanceling == isCanceling && - mapEquals(other.uploadItems, uploadItems); + other.isSyncing == isSyncing && + mapEquals(other.uploadItems, uploadItems) && + other.error == error; } @override @@ -185,10 +181,13 @@ class DriftBackupState { return totalCount.hashCode ^ backupCount.hashCode ^ remainderCount.hashCode ^ + processingCount.hashCode ^ enqueueCount.hashCode ^ enqueueTotalCount.hashCode ^ isCanceling.hashCode ^ - uploadItems.hashCode; + isSyncing.hashCode ^ + uploadItems.hashCode ^ + error.hashCode; } } @@ -203,10 +202,13 @@ class DriftBackupNotifier extends StateNotifier { totalCount: 0, backupCount: 0, remainderCount: 0, + processingCount: 0, enqueueCount: 0, enqueueTotalCount: 0, isCanceling: false, + isSyncing: false, uploadItems: {}, + error: BackupError.none, ), ) { { @@ -235,7 +237,9 @@ class DriftBackupNotifier extends StateNotifier { switch (update.status) { case TaskStatus.complete: if (update.task.group == kBackupGroup) { - state = state.copyWith(backupCount: state.backupCount + 1, remainderCount: state.remainderCount - 1); + if (update.responseStatusCode == 201) { + state = state.copyWith(backupCount: state.backupCount + 1, remainderCount: state.remainderCount - 1); + } } // Remove the completed task from the upload items @@ -257,7 +261,24 @@ class DriftBackupNotifier extends StateNotifier { return; } - state = state.copyWith(uploadItems: {...state.uploadItems, taskId: currentItem.copyWith(isFailed: true)}); + String? error; + final exception = update.exception; + if (exception != null && exception is TaskHttpException) { + final message = tryJsonDecode(exception.description)?['message'] as String?; + if (message != null) { + final responseCode = exception.httpResponseCode; + error = "${exception.exceptionType}, response code $responseCode: $message"; + } + } + error ??= update.exception?.toString(); + + state = state.copyWith( + uploadItems: { + ...state.uploadItems, + taskId: currentItem.copyWith(isFailed: true, error: error), + }, + ); + _logger.fine("Upload failed for taskId: $taskId, exception: ${update.exception}"); break; case TaskStatus.canceled: @@ -311,16 +332,26 @@ class DriftBackupNotifier extends StateNotifier { } Future getBackupStatus(String userId) async { - final [totalCount, backupCount, remainderCount] = await Future.wait([ - _uploadService.getBackupTotalCount(), - _uploadService.getBackupFinishedCount(userId), - _uploadService.getBackupRemainderCount(userId), - ]); + final counts = await _uploadService.getBackupCounts(userId); - state = state.copyWith(totalCount: totalCount, backupCount: backupCount, remainderCount: remainderCount); + state = state.copyWith( + totalCount: counts.total, + backupCount: counts.total - counts.remainder, + remainderCount: counts.remainder, + processingCount: counts.processing, + ); + } + + void updateError(BackupError error) async { + state = state.copyWith(error: error); + } + + void updateSyncing(bool isSyncing) async { + state = state.copyWith(isSyncing: isSyncing); } Future startBackup(String userId) { + state = state.copyWith(error: BackupError.none); return _uploadService.startBackup(userId, _updateEnqueueCount); } @@ -329,16 +360,16 @@ class DriftBackupNotifier extends StateNotifier { } Future cancel() async { - debugPrint("Canceling backup tasks..."); - state = state.copyWith(enqueueCount: 0, enqueueTotalCount: 0, isCanceling: true); + dPrint(() => "Canceling backup tasks..."); + state = state.copyWith(enqueueCount: 0, enqueueTotalCount: 0, isCanceling: true, error: BackupError.none); final activeTaskCount = await _uploadService.cancelBackup(); if (activeTaskCount > 0) { - debugPrint("$activeTaskCount tasks left, continuing to cancel..."); + dPrint(() => "$activeTaskCount tasks left, continuing to cancel..."); await cancel(); } else { - debugPrint("All tasks canceled successfully."); + dPrint(() => "All tasks canceled successfully."); // Clear all upload items when cancellation is complete state = state.copyWith(isCanceling: false, uploadItems: {}); } @@ -346,6 +377,7 @@ class DriftBackupNotifier extends StateNotifier { Future handleBackupResume(String userId) async { _logger.info("Resuming backup tasks..."); + state = state.copyWith(error: BackupError.none); final tasks = await _uploadService.getActiveTasks(kBackupGroup); _logger.info("Found ${tasks.length} tasks"); @@ -373,12 +405,12 @@ final driftBackupCandidateProvider = FutureProvider.autoDispose return []; } - return ref.read(backupRepositoryProvider).getCandidates(user.id); + return ref.read(backupRepositoryProvider).getCandidates(user.id, onlyHashed: false); }); final driftCandidateBackupAlbumInfoProvider = FutureProvider.autoDispose.family, String>(( ref, assetId, ) { - return ref.read(backupRepositoryProvider).getSourceAlbums(assetId); + return ref.read(localAssetRepository).getSourceAlbums(assetId, backupSelection: BackupSelection.selected); }); diff --git a/mobile/lib/providers/backup/manual_upload.provider.dart b/mobile/lib/providers/backup/manual_upload.provider.dart index 1aea7f64cb..bfc079bfa3 100644 --- a/mobile/lib/providers/backup/manual_upload.provider.dart +++ b/mobile/lib/providers/backup/manual_upload.provider.dart @@ -30,6 +30,7 @@ import 'package:immich_mobile/widgets/common/immich_toast.dart'; import 'package:logging/logging.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:photo_manager/photo_manager.dart' show PMProgressHandler; +import 'package:immich_mobile/utils/debug_print.dart'; final manualUploadProvider = StateNotifierProvider((ref) { return ManualUploadNotifier( @@ -216,7 +217,7 @@ class ManualUploadNotifier extends StateNotifier { ); if (uploadAssets.isEmpty) { - debugPrint("[_startUpload] No Assets to upload - Abort Process"); + dPrint(() => "[_startUpload] No Assets to upload - Abort Process"); _backupProvider.updateBackupProgress(BackUpProgressEnum.idle); return false; } @@ -294,10 +295,10 @@ class ManualUploadNotifier extends StateNotifier { } } else { openAppSettings(); - debugPrint("[_startUpload] Do not have permission to the gallery"); + dPrint(() => "[_startUpload] Do not have permission to the gallery"); } } catch (e) { - debugPrint("ERROR _startUpload: ${e.toString()}"); + dPrint(() => "ERROR _startUpload: ${e.toString()}"); hasErrors = true; } finally { _backupProvider.updateBackupProgress(BackUpProgressEnum.idle); @@ -340,7 +341,7 @@ class ManualUploadNotifier extends StateNotifier { // waits until it has stopped to start the backup. final bool hasLock = await ref.read(backgroundServiceProvider).acquireLock(); if (!hasLock) { - debugPrint("[uploadAssets] could not acquire lock, exiting"); + dPrint(() => "[uploadAssets] could not acquire lock, exiting"); ImmichToast.show( context: context, msg: "failed".tr(), @@ -355,18 +356,18 @@ class ManualUploadNotifier extends StateNotifier { // check if backup is already in process - then return if (_backupProvider.backupProgress == BackUpProgressEnum.manualInProgress) { - debugPrint("[uploadAssets] Manual upload is already running - abort"); + dPrint(() => "[uploadAssets] Manual upload is already running - abort"); showInProgress = true; } if (_backupProvider.backupProgress == BackUpProgressEnum.inProgress) { - debugPrint("[uploadAssets] Auto Backup is already in progress - abort"); + dPrint(() => "[uploadAssets] Auto Backup is already in progress - abort"); showInProgress = true; return false; } if (_backupProvider.backupProgress == BackUpProgressEnum.inBackground) { - debugPrint("[uploadAssets] Background backup is running - abort"); + dPrint(() => "[uploadAssets] Background backup is running - abort"); showInProgress = true; } diff --git a/mobile/lib/providers/infrastructure/action.provider.dart b/mobile/lib/providers/infrastructure/action.provider.dart index 65b4327b7a..9f38f4b0ec 100644 --- a/mobile/lib/providers/infrastructure/action.provider.dart +++ b/mobile/lib/providers/infrastructure/action.provider.dart @@ -1,11 +1,16 @@ +import 'package:auto_route/auto_route.dart'; import 'package:background_downloader/background_downloader.dart'; import 'package:flutter/material.dart'; import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; +import 'package:immich_mobile/domain/services/asset.service.dart'; import 'package:immich_mobile/models/download/livephotos_medatada.model.dart'; +import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_viewer.state.dart'; +import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; import 'package:immich_mobile/providers/infrastructure/asset_viewer/current_asset.provider.dart'; import 'package:immich_mobile/providers/timeline/multiselect.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; +import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/services/action.service.dart'; import 'package:immich_mobile/services/download.service.dart'; import 'package:immich_mobile/services/timeline.service.dart'; @@ -34,6 +39,7 @@ class ActionNotifier extends Notifier { late ActionService _service; late UploadService _uploadService; late DownloadService _downloadService; + late AssetService _assetService; ActionNotifier() : super(); @@ -41,6 +47,7 @@ class ActionNotifier extends Notifier { void build() { _uploadService = ref.watch(uploadServiceProvider); _service = ref.watch(actionServiceProvider); + _assetService = ref.watch(assetServiceProvider); _downloadService = ref.watch(downloadServiceProvider); _downloadService.onImageDownloadStatus = _downloadImageCallback; _downloadService.onVideoDownloadStatus = _downloadVideoCallback; @@ -70,11 +77,14 @@ class ActionNotifier extends Notifier { return _getAssets(source).whereType().toIds().toList(growable: false); } - List _getLocalIdsForSource(ActionSource source) { + List _getLocalIdsForSource(ActionSource source, {bool ignoreLocalOnly = false}) { final Set assets = _getAssets(source); final List localIds = []; for (final asset in assets) { + if (ignoreLocalOnly && asset.storage != AssetState.merged) { + continue; + } if (asset is LocalAsset) { localIds.add(asset.id); } else if (asset is RemoteAsset && asset.localId != null) { @@ -115,6 +125,16 @@ class ActionNotifier extends Notifier { }; } + Future troubleshoot(ActionSource source, BuildContext context) async { + final assets = _getAssets(source); + if (assets.length > 1) { + return ActionResult(count: assets.length, success: false, error: 'Cannot troubleshoot multiple assets'); + } + context.pushRoute(AssetTroubleshootRoute(asset: assets.first)); + + return ActionResult(count: assets.length, success: true); + } + Future shareLink(ActionSource source, BuildContext context) async { final ids = _getRemoteIdsForSource(source); try { @@ -172,7 +192,7 @@ class ActionNotifier extends Notifier { Future moveToLockFolder(ActionSource source) async { final ids = _getOwnedRemoteIdsForSource(source); - final localIds = _getLocalIdsForSource(source); + final localIds = _getLocalIdsForSource(source, ignoreLocalOnly: true); try { await _service.moveToLockFolder(ids, localIds); return ActionResult(count: ids.length, success: true); @@ -240,8 +260,15 @@ class ActionNotifier extends Notifier { } } - Future deleteLocal(ActionSource source) async { - final ids = _getLocalIdsForSource(source); + Future deleteLocal(ActionSource source, bool backedUpOnly) async { + final List ids; + if (backedUpOnly) { + final assets = _getAssets(source); + ids = assets.where((asset) => asset.storage == AssetState.merged).map((asset) => asset.localId!).toList(); + } else { + ids = _getLocalIdsForSource(source); + } + try { final deletedCount = await _service.deleteLocal(ids); return ActionResult(count: deletedCount, success: true); @@ -323,6 +350,14 @@ class ActionNotifier extends Notifier { final assets = _getOwnedRemoteAssetsForSource(source); try { await _service.unStack(assets.map((e) => e.stackId).nonNulls.toList()); + if (source == ActionSource.viewer) { + final updatedParent = await _assetService.getRemoteAsset(assets.first.id); + if (updatedParent != null) { + ref.read(currentAssetNotifier.notifier).setAsset(updatedParent); + ref.read(assetViewerProvider.notifier).setAsset(updatedParent); + } + } + return ActionResult(count: assets.length, success: true); } catch (error, stack) { _logger.severe('Failed to unstack assets', error, stack); @@ -330,11 +365,11 @@ class ActionNotifier extends Notifier { } } - Future shareAssets(ActionSource source) async { + Future shareAssets(ActionSource source, BuildContext context) async { final ids = _getAssets(source).toList(growable: false); try { - await _service.shareAssets(ids); + await _service.shareAssets(ids, context); return ActionResult(count: ids.length, success: true); } catch (error, stack) { _logger.severe('Failed to share assets', error, stack); @@ -344,7 +379,6 @@ class ActionNotifier extends Notifier { Future downloadAll(ActionSource source) async { final assets = _getAssets(source).whereType().toList(growable: false); - try { final didEnqueue = await _service.downloadAll(assets); final enqueueCount = didEnqueue.where((e) => e).length; diff --git a/mobile/lib/providers/infrastructure/asset.provider.dart b/mobile/lib/providers/infrastructure/asset.provider.dart index 102e6aa60c..4b51ce33bd 100644 --- a/mobile/lib/providers/infrastructure/asset.provider.dart +++ b/mobile/lib/providers/infrastructure/asset.provider.dart @@ -3,6 +3,7 @@ import 'package:immich_mobile/domain/services/asset.service.dart'; import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/remote_asset.repository.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; +import 'package:immich_mobile/providers/user.provider.dart'; final localAssetRepository = Provider( (ref) => DriftLocalAssetRepository(ref.watch(driftProvider)), @@ -19,9 +20,13 @@ final assetServiceProvider = Provider( ), ); -final placesProvider = FutureProvider>( - (ref) => AssetService( - remoteAssetRepository: ref.watch(remoteAssetRepositoryProvider), - localAssetRepository: ref.watch(localAssetRepository), - ).getPlaces(), -); +final placesProvider = FutureProvider>((ref) { + final assetService = ref.watch(assetServiceProvider); + final auth = ref.watch(currentUserProvider); + + if (auth == null) { + return Future.value(const []); + } + + return assetService.getPlaces(auth.id); +}); diff --git a/mobile/lib/providers/infrastructure/platform.provider.dart b/mobile/lib/providers/infrastructure/platform.provider.dart index 6469624c09..11c5280c02 100644 --- a/mobile/lib/providers/infrastructure/platform.provider.dart +++ b/mobile/lib/providers/infrastructure/platform.provider.dart @@ -1,7 +1,19 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/domain/services/background_worker.service.dart'; +import 'package:immich_mobile/platform/background_worker_api.g.dart'; +import 'package:immich_mobile/platform/background_worker_lock_api.g.dart'; +import 'package:immich_mobile/platform/connectivity_api.g.dart'; import 'package:immich_mobile/platform/native_sync_api.g.dart'; import 'package:immich_mobile/platform/thumbnail_api.g.dart'; +final backgroundWorkerFgServiceProvider = Provider((_) => BackgroundWorkerFgService(BackgroundWorkerFgHostApi())); + +final backgroundWorkerLockServiceProvider = Provider( + (_) => BackgroundWorkerLockService(BackgroundWorkerLockApi()), +); + final nativeSyncApiProvider = Provider((_) => NativeSyncApi()); +final connectivityApiProvider = Provider((_) => ConnectivityApi()); + final thumbnailApi = ThumbnailApi(); diff --git a/mobile/lib/providers/infrastructure/sync.provider.dart b/mobile/lib/providers/infrastructure/sync.provider.dart index ddc6eed441..f03754505c 100644 --- a/mobile/lib/providers/infrastructure/sync.provider.dart +++ b/mobile/lib/providers/infrastructure/sync.provider.dart @@ -10,7 +10,6 @@ import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; import 'package:immich_mobile/providers/infrastructure/cancel.provider.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/platform.provider.dart'; -import 'package:immich_mobile/providers/infrastructure/storage.provider.dart'; final syncStreamServiceProvider = Provider( (ref) => SyncStreamService( @@ -35,7 +34,6 @@ final hashServiceProvider = Provider( (ref) => HashService( localAlbumRepository: ref.watch(localAlbumRepository), localAssetRepository: ref.watch(localAssetRepository), - storageRepository: ref.watch(storageRepositoryProvider), nativeSyncApi: ref.watch(nativeSyncApiProvider), ), ); diff --git a/mobile/lib/providers/theme.provider.dart b/mobile/lib/providers/theme.provider.dart index 5f32e07578..1d5511f1ff 100644 --- a/mobile/lib/providers/theme.provider.dart +++ b/mobile/lib/providers/theme.provider.dart @@ -7,11 +7,12 @@ import 'package:immich_mobile/theme/theme_data.dart'; import 'package:immich_mobile/theme/dynamic_theme.dart'; import 'package:immich_mobile/providers/app_settings.provider.dart'; import 'package:immich_mobile/services/app_settings.service.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; final immichThemeModeProvider = StateProvider((ref) { final themeMode = ref.watch(appSettingsServiceProvider).getSetting(AppSettingsEnum.themeMode); - debugPrint("Current themeMode $themeMode"); + dPrint(() => "Current themeMode $themeMode"); if (themeMode == ThemeMode.light.name) { return ThemeMode.light; @@ -26,12 +27,12 @@ final immichThemePresetProvider = StateProvider((ref) { final appSettingsProvider = ref.watch(appSettingsServiceProvider); final primaryColorPreset = appSettingsProvider.getSetting(AppSettingsEnum.primaryColor); - debugPrint("Current theme preset $primaryColorPreset"); + dPrint(() => "Current theme preset $primaryColorPreset"); try { return ImmichColorPreset.values.firstWhere((e) => e.name == primaryColorPreset); } catch (e) { - debugPrint("Theme preset $primaryColorPreset not found. Applying default preset."); + dPrint(() => "Theme preset $primaryColorPreset not found. Applying default preset."); appSettingsProvider.setSetting(AppSettingsEnum.primaryColor, defaultColorPresetName); return defaultColorPreset; } diff --git a/mobile/lib/providers/timeline/multiselect.provider.dart b/mobile/lib/providers/timeline/multiselect.provider.dart index e225e0c98d..6949413cd9 100644 --- a/mobile/lib/providers/timeline/multiselect.provider.dart +++ b/mobile/lib/providers/timeline/multiselect.provider.dart @@ -28,6 +28,8 @@ class MultiSelectState { bool get hasRemote => selectedAssets.any((asset) => asset.storage == AssetState.remote || asset.storage == AssetState.merged); + bool get hasStacked => selectedAssets.any((asset) => asset is RemoteAsset && asset.stackId != null); + bool get hasLocal => selectedAssets.any((asset) => asset.storage == AssetState.local); bool get hasMerged => selectedAssets.any((asset) => asset.storage == AssetState.merged); diff --git a/mobile/lib/providers/upload_profile_image.provider.dart b/mobile/lib/providers/upload_profile_image.provider.dart index e9e467346b..5aa924ed1c 100644 --- a/mobile/lib/providers/upload_profile_image.provider.dart +++ b/mobile/lib/providers/upload_profile_image.provider.dart @@ -1,10 +1,10 @@ import 'dart:convert'; -import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:image_picker/image_picker.dart'; import 'package:immich_mobile/domain/services/user.service.dart'; import 'package:immich_mobile/providers/infrastructure/user.provider.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; enum UploadProfileStatus { idle, loading, success, failure } @@ -67,7 +67,7 @@ class UploadProfileImageNotifier extends StateNotifier var profileImagePath = await _userService.createProfileImage(file.name, await file.readAsBytes()); if (profileImagePath != null) { - debugPrint("Successfully upload profile image"); + dPrint(() => "Successfully upload profile image"); state = state.copyWith(status: UploadProfileStatus.success, profileImagePath: profileImagePath); return true; } diff --git a/mobile/lib/providers/websocket.provider.dart b/mobile/lib/providers/websocket.provider.dart index 3b0d5daab8..136c6049a7 100644 --- a/mobile/lib/providers/websocket.provider.dart +++ b/mobile/lib/providers/websocket.provider.dart @@ -2,8 +2,6 @@ import 'dart:async'; import 'dart:convert'; import 'package:collection/collection.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/widgets.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/store.model.dart'; import 'package:immich_mobile/entities/asset.entity.dart'; @@ -20,6 +18,7 @@ import 'package:immich_mobile/utils/debounce.dart'; import 'package:logging/logging.dart'; import 'package:openapi/api.dart'; import 'package:socket_io_client/socket_io_client.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; enum PendingAction { assetDelete, assetUploaded, assetHidden, assetTrash } @@ -105,7 +104,7 @@ class WebsocketNotifier extends StateNotifier { headers["Authorization"] = "Basic ${base64.encode(utf8.encode(endpoint.userInfo))}"; } - debugPrint("Attempting to connect to websocket"); + dPrint(() => "Attempting to connect to websocket"); // Configure socket transports must be specified Socket socket = io( endpoint.origin, @@ -121,12 +120,12 @@ class WebsocketNotifier extends StateNotifier { ); socket.onConnect((_) { - debugPrint("Established Websocket Connection"); + dPrint(() => "Established Websocket Connection"); state = WebsocketState(isConnected: true, socket: socket, pendingChanges: state.pendingChanges); }); socket.onDisconnect((_) { - debugPrint("Disconnect to Websocket Connection"); + dPrint(() => "Disconnect to Websocket Connection"); state = WebsocketState(isConnected: false, socket: null, pendingChanges: state.pendingChanges); }); @@ -150,13 +149,13 @@ class WebsocketNotifier extends StateNotifier { socket.on('on_config_update', _handleOnConfigUpdate); socket.on('on_new_release', _handleReleaseUpdates); } catch (e) { - debugPrint("[WEBSOCKET] Catch Websocket Error - ${e.toString()}"); + dPrint(() => "[WEBSOCKET] Catch Websocket Error - ${e.toString()}"); } } } void disconnect() { - debugPrint("Attempting to disconnect from websocket"); + dPrint(() => "Attempting to disconnect from websocket"); _batchedAssetUploadReady.clear(); @@ -200,7 +199,7 @@ class WebsocketNotifier extends StateNotifier { } void listenUploadEvent() { - debugPrint("Start listening to event on_upload_success"); + dPrint(() => "Start listening to event on_upload_success"); state.socket?.on('on_upload_success', _handleOnUploadSuccess); } @@ -321,10 +320,13 @@ class WebsocketNotifier extends StateNotifier { return; } + final isSyncAlbumEnabled = Store.get(StoreKey.syncAlbums, false); try { unawaited( _ref.read(backgroundSyncProvider).syncWebsocketBatch(_batchedAssetUploadReady.toList()).then((_) { - return _ref.read(backgroundSyncProvider).syncLinkedAlbum(); + if (isSyncAlbumEnabled) { + _ref.read(backgroundSyncProvider).syncLinkedAlbum(); + } }), ); } catch (error) { diff --git a/mobile/lib/repositories/asset_media.repository.dart b/mobile/lib/repositories/asset_media.repository.dart index 83b5dfb9fd..f71c919373 100644 --- a/mobile/lib/repositories/asset_media.repository.dart +++ b/mobile/lib/repositories/asset_media.repository.dart @@ -1,28 +1,54 @@ import 'dart:io'; +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter/widgets.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/exif.model.dart'; import 'package:immich_mobile/domain/models/store.model.dart'; import 'package:immich_mobile/entities/asset.entity.dart' as asset_entity; import 'package:immich_mobile/entities/store.entity.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_mobile/extensions/platform_extensions.dart'; +import 'package:immich_mobile/extensions/response_extensions.dart'; import 'package:immich_mobile/repositories/asset_api.repository.dart'; import 'package:immich_mobile/utils/hash.dart'; import 'package:logging/logging.dart'; import 'package:path_provider/path_provider.dart'; import 'package:photo_manager/photo_manager.dart'; -import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; -import 'package:immich_mobile/extensions/response_extensions.dart'; import 'package:share_plus/share_plus.dart'; final assetMediaRepositoryProvider = Provider((ref) => AssetMediaRepository(ref.watch(assetApiRepositoryProvider))); class AssetMediaRepository { final AssetApiRepository _assetApiRepository; + static final Logger _log = Logger("AssetMediaRepository"); const AssetMediaRepository(this._assetApiRepository); - Future> deleteAll(List ids) => PhotoManager.editor.deleteWithIds(ids); + Future _androidSupportsTrash() async { + if (Platform.isAndroid) { + DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); + AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; + int sdkVersion = androidInfo.version.sdkInt; + return sdkVersion >= 31; + } + return false; + } + + Future> deleteAll(List ids) async { + if (CurrentPlatform.isAndroid) { + if (await _androidSupportsTrash()) { + return PhotoManager.editor.android.moveToTrash( + ids.map((e) => AssetEntity(id: e, width: 1, height: 1, typeInt: 0)).toList(), + ); + } else { + return PhotoManager.editor.deleteWithIds(ids); + } + } + return PhotoManager.editor.deleteWithIds(ids); + } Future get(String id) async { final entity = await AssetEntity.fromId(id); @@ -68,8 +94,9 @@ class AssetMediaRepository { } // TODO: make this more efficient - Future shareAssets(List assets) async { + Future shareAssets(List assets, BuildContext context) async { final downloadedXFiles = []; + final tempFiles = []; for (var asset in assets) { final localId = (asset is LocalAsset) @@ -80,6 +107,9 @@ class AssetMediaRepository { if (localId != null) { File? f = await AssetEntity(id: localId, width: 1, height: 1, typeInt: 0).originFile; downloadedXFiles.add(XFile(f!.path)); + if (CurrentPlatform.isIOS) { + tempFiles.add(f); + } } else if (asset is RemoteAsset) { final tempDir = await getTemporaryDirectory(); final name = asset.name; @@ -93,6 +123,7 @@ class AssetMediaRepository { await tempFile.writeAsBytes(res.bodyBytes); downloadedXFiles.add(XFile(tempFile.path)); + tempFiles.add(tempFile); } else { _log.warning("Asset type not supported for sharing: $asset"); continue; @@ -105,11 +136,15 @@ class AssetMediaRepository { } // we dont want to await the share result since the - // "preparing" dialog will not disappear unti - Share.shareXFiles(downloadedXFiles).then((result) async { - for (var file in downloadedXFiles) { + // "preparing" dialog will not disappear until + final size = context.sizeData; + Share.shareXFiles( + downloadedXFiles, + sharePositionOrigin: Rect.fromPoints(Offset.zero, Offset(size.width / 3, size.height)), + ).then((result) async { + for (var file in tempFiles) { try { - await File(file.path).delete(); + await file.delete(); } catch (e) { _log.warning("Failed to delete temporary file: ${file.path}", e); } diff --git a/mobile/lib/repositories/download.repository.dart b/mobile/lib/repositories/download.repository.dart index c4b31e9d93..c578746a4c 100644 --- a/mobile/lib/repositories/download.repository.dart +++ b/mobile/lib/repositories/download.repository.dart @@ -90,7 +90,11 @@ class DownloadRepository { final isVideo = asset.isVideo; final url = getOriginalUrlForRemoteId(id); - if (Platform.isAndroid || livePhotoVideoId == null || isVideo) { + // on iOS it cannot link the image, check if the filename has .MP extension + // to avoid downloading the video part + final isAndroidMotionPhoto = asset.name.contains(".MP"); + + if (Platform.isAndroid || livePhotoVideoId == null || isVideo || isAndroidMotionPhoto) { tasks[taskIndex++] = DownloadTask( taskId: id, url: url, @@ -117,7 +121,7 @@ class DownloadRepository { _dummyMetadata['part'] = LivePhotosPart.video.index; tasks[taskIndex++] = DownloadTask( taskId: livePhotoVideoId, - url: url, + url: getOriginalUrlForRemoteId(livePhotoVideoId), headers: headers, filename: asset.name.toUpperCase().replaceAll(RegExp(r"\.(JPG|HEIC)$"), '.MOV'), updates: Updates.statusAndProgress, diff --git a/mobile/lib/repositories/upload.repository.dart b/mobile/lib/repositories/upload.repository.dart index c8b06ae102..38f2c22cf2 100644 --- a/mobile/lib/repositories/upload.repository.dart +++ b/mobile/lib/repositories/upload.repository.dart @@ -1,7 +1,21 @@ +import 'dart:convert'; +import 'dart:io'; + import 'package:background_downloader/background_downloader.dart'; -import 'package:flutter/material.dart'; +import 'package:cancellation_token_http/http.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/constants.dart'; +import 'package:immich_mobile/domain/models/store.model.dart'; +import 'package:immich_mobile/entities/store.entity.dart'; +import 'package:logging/logging.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; + +class UploadTaskWithFile { + final File file; + final UploadTask task; + + const UploadTaskWithFile({required this.file, required this.task}); +} final uploadRepositoryProvider = Provider((ref) => UploadRepository()); @@ -31,7 +45,7 @@ class UploadRepository { return FileDownloader().enqueue(task); } - Future enqueueBackgroundAll(List tasks) { + Future> enqueueBackgroundAll(List tasks) { return FileDownloader().enqueueAll(tasks); } @@ -65,13 +79,65 @@ class UploadRepository { FileDownloader().database.allRecordsWithStatus(TaskStatus.paused, group: kBackupGroup), ]); - debugPrint(""" + dPrint( + () => + """ Upload Info: Enqueued: ${enqueuedTasks.length} Running: ${runningTasks.length} Canceled: ${canceledTasks.length} Waiting: ${waitingTasks.length} Paused: ${pausedTasks.length} - """); + """, + ); + } + + Future backupWithDartClient(Iterable tasks, CancellationToken cancelToken) async { + final httpClient = Client(); + final String savedEndpoint = Store.get(StoreKey.serverEndpoint); + + Logger logger = Logger('UploadRepository'); + for (final candidate in tasks) { + if (cancelToken.isCancelled) { + logger.warning("Backup was cancelled by the user"); + break; + } + + try { + final fileStream = candidate.file.openRead(); + final assetRawUploadData = MultipartFile( + "assetData", + fileStream, + candidate.file.lengthSync(), + filename: candidate.task.filename, + ); + + final baseRequest = MultipartRequest('POST', Uri.parse('$savedEndpoint/assets')); + + baseRequest.headers.addAll(candidate.task.headers); + baseRequest.fields.addAll(candidate.task.fields); + baseRequest.files.add(assetRawUploadData); + + final response = await httpClient.send(baseRequest, cancellationToken: cancelToken); + + final responseBody = jsonDecode(await response.stream.bytesToString()); + + if (![200, 201].contains(response.statusCode)) { + final error = responseBody; + + logger.warning( + "Error(${error['statusCode']}) uploading ${candidate.task.filename} | Created on ${candidate.task.fields["fileCreatedAt"]} | ${error['error']}", + ); + + continue; + } + } on CancelledException { + logger.warning("Backup was cancelled by the user"); + break; + } catch (error, stackTrace) { + logger.warning("Error backup asset: ${error.toString()}: $stackTrace"); + continue; + } + } } } diff --git a/mobile/lib/routing/duplicate_guard.dart b/mobile/lib/routing/duplicate_guard.dart index 6f83d5297e..c55c7318d0 100644 --- a/mobile/lib/routing/duplicate_guard.dart +++ b/mobile/lib/routing/duplicate_guard.dart @@ -1,5 +1,5 @@ import 'package:auto_route/auto_route.dart'; -import 'package:flutter/foundation.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; /// Guards against duplicate navigation to this route class DuplicateGuard extends AutoRouteGuard { @@ -8,7 +8,7 @@ class DuplicateGuard extends AutoRouteGuard { void onNavigation(NavigationResolver resolver, StackRouter router) async { // Duplicate navigation if (resolver.route.name == router.current.name) { - debugPrint('DuplicateGuard: Preventing duplicate route navigation for ${resolver.route.name}'); + dPrint(() => 'DuplicateGuard: Preventing duplicate route navigation for ${resolver.route.name}'); resolver.next(false); } else { resolver.next(true); diff --git a/mobile/lib/routing/router.dart b/mobile/lib/routing/router.dart index b289cc3225..7554c7b1cf 100644 --- a/mobile/lib/routing/router.dart +++ b/mobile/lib/routing/router.dart @@ -76,16 +76,18 @@ 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_taken.page.dart'; import 'package:immich_mobile/pages/search/search.page.dart'; -import 'package:immich_mobile/pages/settings/beta_sync_settings.page.dart'; +import 'package:immich_mobile/pages/settings/sync_status.page.dart'; import 'package:immich_mobile/pages/share_intent/share_intent.page.dart'; import 'package:immich_mobile/presentation/pages/dev/feat_in_development.page.dart'; import 'package:immich_mobile/presentation/pages/dev/main_timeline.page.dart'; import 'package:immich_mobile/presentation/pages/dev/media_stat.page.dart'; +import 'package:immich_mobile/presentation/pages/download_info.page.dart'; import 'package:immich_mobile/presentation/pages/drift_activities.page.dart'; import 'package:immich_mobile/presentation/pages/drift_album.page.dart'; import 'package:immich_mobile/presentation/pages/drift_album_options.page.dart'; import 'package:immich_mobile/presentation/pages/drift_archive.page.dart'; import 'package:immich_mobile/presentation/pages/drift_asset_selection_timeline.page.dart'; +import 'package:immich_mobile/presentation/pages/drift_asset_troubleshoot.page.dart'; import 'package:immich_mobile/presentation/pages/drift_create_album.page.dart'; import 'package:immich_mobile/presentation/pages/drift_favorite.page.dart'; import 'package:immich_mobile/presentation/pages/drift_library.page.dart'; @@ -332,7 +334,7 @@ class AppRouter extends RootStackRouter { AutoRoute(page: ChangeExperienceRoute.page, guards: [_authGuard, _duplicateGuard]), AutoRoute(page: DriftPartnerRoute.page, guards: [_authGuard, _duplicateGuard]), AutoRoute(page: DriftUploadDetailRoute.page, guards: [_authGuard, _duplicateGuard]), - AutoRoute(page: BetaSyncSettingsRoute.page, guards: [_authGuard, _duplicateGuard]), + AutoRoute(page: SyncStatusRoute.page, guards: [_duplicateGuard]), AutoRoute(page: DriftPeopleCollectionRoute.page, guards: [_authGuard, _duplicateGuard]), AutoRoute(page: DriftPersonRoute.page, guards: [_authGuard]), AutoRoute(page: DriftBackupOptionsRoute.page, guards: [_authGuard, _duplicateGuard]), @@ -343,6 +345,8 @@ class AppRouter extends RootStackRouter { AutoRoute(page: DriftFilterImageRoute.page), AutoRoute(page: DriftActivitiesRoute.page, guards: [_authGuard, _duplicateGuard]), AutoRoute(page: DriftBackupAssetDetailRoute.page, guards: [_authGuard, _duplicateGuard]), + AutoRoute(page: AssetTroubleshootRoute.page, guards: [_authGuard, _duplicateGuard]), + AutoRoute(page: DownloadInfoRoute.page, guards: [_authGuard, _duplicateGuard]), // required to handle all deeplinks in deep_link.service.dart // auto_route_library#1722 RedirectRoute(path: '*', redirectTo: '/'), diff --git a/mobile/lib/routing/router.gr.dart b/mobile/lib/routing/router.gr.dart index 84f2685ab5..4e488a30c7 100644 --- a/mobile/lib/routing/router.gr.dart +++ b/mobile/lib/routing/router.gr.dart @@ -403,6 +403,43 @@ class ArchiveRoute extends PageRouteInfo { ); } +/// generated route for +/// [AssetTroubleshootPage] +class AssetTroubleshootRoute extends PageRouteInfo { + AssetTroubleshootRoute({ + Key? key, + required BaseAsset asset, + List? children, + }) : super( + AssetTroubleshootRoute.name, + args: AssetTroubleshootRouteArgs(key: key, asset: asset), + initialChildren: children, + ); + + static const String name = 'AssetTroubleshootRoute'; + + static PageInfo page = PageInfo( + name, + builder: (data) { + final args = data.argsAs(); + return AssetTroubleshootPage(key: args.key, asset: args.asset); + }, + ); +} + +class AssetTroubleshootRouteArgs { + const AssetTroubleshootRouteArgs({this.key, required this.asset}); + + final Key? key; + + final BaseAsset asset; + + @override + String toString() { + return 'AssetTroubleshootRouteArgs{key: $key, asset: $asset}'; + } +} + /// generated route for /// [AssetViewerPage] class AssetViewerRoute extends PageRouteInfo { @@ -509,22 +546,6 @@ class BackupOptionsRoute extends PageRouteInfo { ); } -/// generated route for -/// [BetaSyncSettingsPage] -class BetaSyncSettingsRoute extends PageRouteInfo { - const BetaSyncSettingsRoute({List? children}) - : super(BetaSyncSettingsRoute.name, initialChildren: children); - - static const String name = 'BetaSyncSettingsRoute'; - - static PageInfo page = PageInfo( - name, - builder: (data) { - return const BetaSyncSettingsPage(); - }, - ); -} - /// generated route for /// [ChangeExperiencePage] class ChangeExperienceRoute extends PageRouteInfo { @@ -667,6 +688,22 @@ class CropImageRouteArgs { } } +/// generated route for +/// [DownloadInfoPage] +class DownloadInfoRoute extends PageRouteInfo { + const DownloadInfoRoute({List? children}) + : super(DownloadInfoRoute.name, initialChildren: children); + + static const String name = 'DownloadInfoRoute'; + + static PageInfo page = PageInfo( + name, + builder: (data) { + return const DownloadInfoPage(); + }, + ); +} + /// generated route for /// [DriftActivitiesPage] class DriftActivitiesRoute extends PageRouteInfo { @@ -2629,6 +2666,22 @@ class SplashScreenRoute extends PageRouteInfo { ); } +/// generated route for +/// [SyncStatusPage] +class SyncStatusRoute extends PageRouteInfo { + const SyncStatusRoute({List? children}) + : super(SyncStatusRoute.name, initialChildren: children); + + static const String name = 'SyncStatusRoute'; + + static PageInfo page = PageInfo( + name, + builder: (data) { + return const SyncStatusPage(); + }, + ); +} + /// generated route for /// [TabControllerPage] class TabControllerRoute extends PageRouteInfo { diff --git a/mobile/lib/services/action.service.dart b/mobile/lib/services/action.service.dart index 9a12745acd..9c3768080b 100644 --- a/mobile/lib/services/action.service.dart +++ b/mobile/lib/services/action.service.dart @@ -1,7 +1,6 @@ -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:immich_mobile/repositories/download.repository.dart'; import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart'; @@ -11,6 +10,7 @@ import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; import 'package:immich_mobile/repositories/asset_api.repository.dart'; import 'package:immich_mobile/repositories/asset_media.repository.dart'; +import 'package:immich_mobile/repositories/download.repository.dart'; import 'package:immich_mobile/repositories/drift_album_api_repository.dart'; import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/widgets/common/date_time_picker.dart'; @@ -199,14 +199,11 @@ class ActionService { } Future removeFromAlbum(List remoteIds, String albumId) async { - int removedCount = 0; final result = await _albumApiRepository.removeAssets(albumId, remoteIds); - if (result.removed.isNotEmpty) { - removedCount = await _remoteAlbumRepository.removeAssets(albumId, result.removed); + await _remoteAlbumRepository.removeAssets(albumId, result.removed); } - - return removedCount; + return result.removed.length; } Future updateDescription(String assetId, String description) async { @@ -227,8 +224,8 @@ class ActionService { await _assetApiRepository.unStack(stackIds); } - Future shareAssets(List assets) { - return _assetMediaRepository.shareAssets(assets); + Future shareAssets(List assets, BuildContext context) { + return _assetMediaRepository.shareAssets(assets, context); } Future> downloadAll(List assets) { diff --git a/mobile/lib/services/album.service.dart b/mobile/lib/services/album.service.dart index 454f652035..a9eee0528e 100644 --- a/mobile/lib/services/album.service.dart +++ b/mobile/lib/services/album.service.dart @@ -3,7 +3,6 @@ import 'dart:collection'; import 'dart:io'; import 'package:collection/collection.dart'; -import 'package:flutter/foundation.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/domain/models/user.model.dart'; @@ -24,6 +23,7 @@ import 'package:immich_mobile/services/entity.service.dart'; import 'package:immich_mobile/services/sync.service.dart'; import 'package:immich_mobile/utils/hash.dart'; import 'package:logging/logging.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; final albumServiceProvider = Provider( (ref) => AlbumService( @@ -124,7 +124,7 @@ class AlbumService { } finally { _localCompleter.complete(changes); } - debugPrint("refreshDeviceAlbums took ${sw.elapsedMilliseconds}ms"); + dPrint(() => "refreshDeviceAlbums took ${sw.elapsedMilliseconds}ms"); return changes; } @@ -172,7 +172,7 @@ class AlbumService { } finally { _remoteCompleter.complete(changes); } - debugPrint("refreshRemoteAlbums took ${sw.elapsedMilliseconds}ms"); + dPrint(() => "refreshRemoteAlbums took ${sw.elapsedMilliseconds}ms"); return changes; } @@ -220,7 +220,7 @@ class AlbumService { return AlbumAddAssetsResponse(alreadyInAlbum: result.duplicates, successfullyAdded: addedAssets.length); } catch (e) { - debugPrint("Error addAssets ${e.toString()}"); + dPrint(() => "Error addAssets ${e.toString()}"); } return null; } @@ -242,7 +242,7 @@ class AlbumService { await _albumRepository.update(album); return true; } catch (e) { - debugPrint("Error setActivityEnabled ${e.toString()}"); + dPrint(() => "Error setActivityEnabled ${e.toString()}"); } return false; } @@ -271,7 +271,7 @@ class AlbumService { } return true; } catch (e) { - debugPrint("Error deleteAlbum ${e.toString()}"); + dPrint(() => "Error deleteAlbum ${e.toString()}"); } return false; } @@ -281,7 +281,7 @@ class AlbumService { await _albumApiRepository.removeUser(album.remoteId!, userId: "me"); return true; } catch (e) { - debugPrint("Error leaveAlbum ${e.toString()}"); + dPrint(() => "Error leaveAlbum ${e.toString()}"); return false; } } @@ -293,7 +293,7 @@ class AlbumService { await _updateAssets(album.id, remove: toRemove.toList()); return true; } catch (e) { - debugPrint("Error removeAssetFromAlbum ${e.toString()}"); + dPrint(() => "Error removeAssetFromAlbum ${e.toString()}"); } return false; } @@ -310,7 +310,7 @@ class AlbumService { return true; } catch (error) { - debugPrint("Error removeUser ${error.toString()}"); + dPrint(() => "Error removeUser ${error.toString()}"); return false; } } @@ -327,7 +327,7 @@ class AlbumService { return true; } catch (error) { - debugPrint("Error addUsers ${error.toString()}"); + dPrint(() => "Error addUsers ${error.toString()}"); } return false; } @@ -340,7 +340,7 @@ class AlbumService { await _albumRepository.update(album); return true; } catch (e) { - debugPrint("Error changeTitleAlbum ${e.toString()}"); + dPrint(() => "Error changeTitleAlbum ${e.toString()}"); return false; } } @@ -353,7 +353,7 @@ class AlbumService { await _albumRepository.update(album); return true; } catch (e) { - debugPrint("Error changeDescriptionAlbum ${e.toString()}"); + dPrint(() => "Error changeDescriptionAlbum ${e.toString()}"); return false; } } diff --git a/mobile/lib/services/api.service.dart b/mobile/lib/services/api.service.dart index fca9080c86..4033ffb184 100644 --- a/mobile/lib/services/api.service.dart +++ b/mobile/lib/services/api.service.dart @@ -3,7 +3,6 @@ import 'dart:convert'; import 'dart:io'; import 'package:device_info_plus/device_info_plus.dart'; -import 'package:flutter/material.dart'; import 'package:http/http.dart'; import 'package:immich_mobile/domain/models/store.model.dart'; import 'package:immich_mobile/entities/store.entity.dart'; @@ -11,6 +10,7 @@ import 'package:immich_mobile/utils/url_helper.dart'; import 'package:logging/logging.dart'; import 'package:openapi/api.dart'; import 'package:immich_mobile/utils/user_agent.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; class ApiService implements Authentication { late ApiClient _apiClient; @@ -155,7 +155,7 @@ class ApiService implements Authentication { return endpoint; } } catch (e) { - debugPrint("Could not locate /.well-known/immich at $baseUrl"); + dPrint(() => "Could not locate /.well-known/immich at $baseUrl"); } return ""; diff --git a/mobile/lib/services/app_settings.service.dart b/mobile/lib/services/app_settings.service.dart index d98b14408f..7149408e8a 100644 --- a/mobile/lib/services/app_settings.service.dart +++ b/mobile/lib/services/app_settings.service.dart @@ -34,6 +34,7 @@ enum AppSettingsEnum { preferRemoteImage(StoreKey.preferRemoteImage, null, false), loopVideo(StoreKey.loopVideo, "loopVideo", true), loadOriginalVideo(StoreKey.loadOriginalVideo, "loadOriginalVideo", false), + autoPlayVideo(StoreKey.autoPlayVideo, "autoPlayVideo", true), mapThemeMode(StoreKey.mapThemeMode, null, 0), mapShowFavoriteOnly(StoreKey.mapShowFavoriteOnly, null, false), mapIncludeArchived(StoreKey.mapIncludeArchived, null, false), @@ -46,10 +47,12 @@ enum AppSettingsEnum { syncAlbums(StoreKey.syncAlbums, null, false), autoEndpointSwitching(StoreKey.autoEndpointSwitching, null, false), photoManagerCustomFilter(StoreKey.photoManagerCustomFilter, null, true), - betaTimeline(StoreKey.betaTimeline, null, false), + betaTimeline(StoreKey.betaTimeline, null, true), enableBackup(StoreKey.enableBackup, null, false), useCellularForUploadVideos(StoreKey.useWifiForUploadVideos, null, false), useCellularForUploadPhotos(StoreKey.useWifiForUploadPhotos, null, false), + backupRequireCharging(StoreKey.backupRequireCharging, null, false), + backupTriggerDelay(StoreKey.backupTriggerDelay, null, 30), readonlyModeEnabled(StoreKey.readonlyModeEnabled, "readonlyModeEnabled", false); const AppSettingsEnum(this.storeKey, this.hiveKey, this.defaultValue); diff --git a/mobile/lib/services/asset.service.dart b/mobile/lib/services/asset.service.dart index ee61929c81..b9fab35442 100644 --- a/mobile/lib/services/asset.service.dart +++ b/mobile/lib/services/asset.service.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:collection/collection.dart'; -import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/domain/models/user.model.dart'; @@ -26,6 +25,7 @@ import 'package:immich_mobile/services/sync.service.dart'; import 'package:logging/logging.dart'; import 'package:maplibre_gl/maplibre_gl.dart'; import 'package:openapi/api.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; final assetServiceProvider = Provider( (ref) => AssetService( @@ -87,7 +87,7 @@ class AssetService { getChangedAssets: _getRemoteAssetChanges, loadAssets: _getRemoteAssets, ); - debugPrint("refreshRemoteAssets full took ${sw.elapsedMilliseconds}ms"); + dPrint(() => "refreshRemoteAssets full took ${sw.elapsedMilliseconds}ms"); return changes; } @@ -156,7 +156,7 @@ class AssetService { if (a.isInDb) { await _assetRepository.transaction(() => _assetRepository.update(a)); } else { - debugPrint("[loadExif] parameter Asset is not from DB!"); + dPrint(() => "[loadExif] parameter Asset is not from DB!"); } } } diff --git a/mobile/lib/services/background.service.dart b/mobile/lib/services/background.service.dart index e6436df244..33a8e810f1 100644 --- a/mobile/lib/services/background.service.dart +++ b/mobile/lib/services/background.service.dart @@ -7,7 +7,6 @@ import 'dart:ui' show DartPluginRegistrant, IsolateNameServer, PluginUtilities; import 'package:cancellation_token_http/http.dart'; import 'package:collection/collection.dart'; import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -29,6 +28,7 @@ import 'package:immich_mobile/services/backup.service.dart'; import 'package:immich_mobile/services/localization.service.dart'; import 'package:immich_mobile/utils/backup_progress.dart'; import 'package:immich_mobile/utils/bootstrap.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; import 'package:immich_mobile/utils/diff.dart'; import 'package:immich_mobile/utils/http_ssl_options.dart'; import 'package:path_provider_foundation/path_provider_foundation.dart'; @@ -165,7 +165,7 @@ class BackgroundService { ]); } } catch (error) { - debugPrint("[_updateNotification] failed to communicate with plugin"); + dPrint(() => "[_updateNotification] failed to communicate with plugin"); } return false; } @@ -177,7 +177,7 @@ class BackgroundService { return await _backgroundChannel.invokeMethod('showError', [title, content, individualTag]); } } catch (error) { - debugPrint("[_showErrorNotification] failed to communicate with plugin"); + dPrint(() => "[_showErrorNotification] failed to communicate with plugin"); } return false; } @@ -188,7 +188,7 @@ class BackgroundService { return await _backgroundChannel.invokeMethod('clearErrorNotifications'); } } catch (error) { - debugPrint("[_clearErrorNotifications] failed to communicate with plugin"); + dPrint(() => "[_clearErrorNotifications] failed to communicate with plugin"); } return false; } @@ -196,7 +196,7 @@ class BackgroundService { /// await to ensure this thread (foreground or background) has exclusive access Future acquireLock() async { if (_hasLock) { - debugPrint("WARNING: [acquireLock] called more than once"); + dPrint(() => "WARNING: [acquireLock] called more than once"); return true; } final int lockTime = Timeline.now; @@ -302,19 +302,19 @@ class BackgroundService { final bool hasAccess = await waitForLock; if (!hasAccess) { - debugPrint("[_callHandler] could not acquire lock, exiting"); + dPrint(() => "[_callHandler] could not acquire lock, exiting"); return false; } final translationsOk = await loadTranslations(); if (!translationsOk) { - debugPrint("[_callHandler] could not load translations"); + dPrint(() => "[_callHandler] could not load translations"); } final bool ok = await _onAssetsChanged(); return ok; } catch (error) { - debugPrint(error.toString()); + dPrint(() => error.toString()); return false; } finally { releaseLock(); @@ -324,14 +324,14 @@ class BackgroundService { _cancellationToken?.cancel(); return true; default: - debugPrint("Unknown method ${call.method}"); + dPrint(() => "Unknown method ${call.method}"); return false; } } Future _onAssetsChanged() async { final (isar, drift, logDb) = await Bootstrap.initDB(); - await Bootstrap.initDomain(isar, drift, logDb); + await Bootstrap.initDomain(isar, drift, logDb, shouldBufferLogs: false, listenStoreUpdates: false); final ref = ProviderContainer( overrides: [ @@ -344,9 +344,7 @@ class BackgroundService { HttpSSLOptions.apply(); ref.read(apiServiceProvider).setAccessToken(Store.get(StoreKey.accessToken)); await ref.read(authServiceProvider).setOpenApiServiceEndpoint(); - if (kDebugMode) { - debugPrint("[BG UPLOAD] Using endpoint: ${ref.read(apiServiceProvider).apiClient.basePath}"); - } + dPrint(() => "[BG UPLOAD] Using endpoint: ${ref.read(apiServiceProvider).apiClient.basePath}"); final selectedAlbums = await ref.read(backupAlbumRepositoryProvider).getAllBySelection(BackupSelection.select); final excludedAlbums = await ref.read(backupAlbumRepositoryProvider).getAllBySelection(BackupSelection.exclude); diff --git a/mobile/lib/services/backup.service.dart b/mobile/lib/services/backup.service.dart index 3e29222b4c..539fd1fbd9 100644 --- a/mobile/lib/services/backup.service.dart +++ b/mobile/lib/services/backup.service.dart @@ -4,7 +4,6 @@ import 'dart:io'; import 'package:cancellation_token_http/http.dart' as http; import 'package:collection/collection.dart'; -import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/store.model.dart'; import 'package:immich_mobile/entities/album.entity.dart'; @@ -29,6 +28,7 @@ import 'package:openapi/api.dart'; import 'package:path/path.dart' as p; import 'package:permission_handler/permission_handler.dart' as pm; import 'package:photo_manager/photo_manager.dart' show PMProgressHandler; +import 'package:immich_mobile/utils/debug_print.dart'; final backupServiceProvider = Provider( (ref) => BackupService( @@ -69,7 +69,7 @@ class BackupService { try { return await _apiService.assetsApi.getAllUserAssetsByDeviceId(deviceId); } catch (e) { - debugPrint('Error [getDeviceBackupAsset] ${e.toString()}'); + dPrint(() => 'Error [getDeviceBackupAsset] ${e.toString()}'); return null; } } @@ -356,8 +356,9 @@ class BackupService { final error = responseBody; final errorMessage = error['message'] ?? error['error']; - debugPrint( - "Error(${error['statusCode']}) uploading ${asset.localId} | $originalFileName | Created on ${asset.fileCreatedAt} | ${error['error']}", + dPrint( + () => + "Error(${error['statusCode']}) uploading ${asset.localId} | $originalFileName | Created on ${asset.fileCreatedAt} | ${error['error']}", ); onError( @@ -398,11 +399,11 @@ class BackupService { } } } on http.CancelledException { - debugPrint("Backup was cancelled by the user"); + dPrint(() => "Backup was cancelled by the user"); anyErrors = true; break; } catch (error, stackTrace) { - debugPrint("Error backup asset: ${error.toString()}: $stackTrace"); + dPrint(() => "Error backup asset: ${error.toString()}: $stackTrace"); anyErrors = true; continue; } finally { @@ -411,7 +412,7 @@ class BackupService { await file?.delete(); await livePhotoFile?.delete(); } catch (e) { - debugPrint("ERROR deleting file: ${e.toString()}"); + dPrint(() => "ERROR deleting file: ${e.toString()}"); } } } @@ -454,7 +455,9 @@ class BackupService { if (![200, 201].contains(response.statusCode)) { var error = responseBody; - debugPrint("Error(${error['statusCode']}) uploading livePhoto for assetId | $livePhotoTitle | ${error['error']}"); + dPrint( + () => "Error(${error['statusCode']}) uploading livePhoto for assetId | $livePhotoTitle | ${error['error']}", + ); } return responseBody.containsKey('id') ? responseBody['id'] : null; diff --git a/mobile/lib/services/deep_link.service.dart b/mobile/lib/services/deep_link.service.dart index 6226781919..7c8ddce265 100644 --- a/mobile/lib/services/deep_link.service.dart +++ b/mobile/lib/services/deep_link.service.dart @@ -8,8 +8,8 @@ import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_viewer.page.dart'; import 'package:immich_mobile/providers/album/current_album.provider.dart'; import 'package:immich_mobile/providers/asset_viewer/current_asset.provider.dart'; -import 'package:immich_mobile/providers/infrastructure/asset.provider.dart' as beta_asset_provider; import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/asset.provider.dart' as beta_asset_provider; import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart'; import 'package:immich_mobile/providers/infrastructure/memory.provider.dart'; import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart'; @@ -150,7 +150,10 @@ class DeepLinkService { } AssetViewer.setAsset(ref, asset); - return AssetViewerRoute(initialIndex: 0, timelineService: _betaTimelineFactory.fromAssets([asset])); + return AssetViewerRoute( + initialIndex: 0, + timelineService: _betaTimelineFactory.fromAssets([asset], TimelineOrigin.deepLink), + ); } else { // TODO: Remove this when beta is default final asset = await _assetService.getAssetByRemoteId(assetId); diff --git a/mobile/lib/services/hash.service.dart b/mobile/lib/services/hash.service.dart index 48302be79c..9d1f4e51e8 100644 --- a/mobile/lib/services/hash.service.dart +++ b/mobile/lib/services/hash.service.dart @@ -16,9 +16,10 @@ class HashService { required IsarDeviceAssetRepository deviceAssetRepository, required BackgroundService backgroundService, this.batchSizeLimit = kBatchHashSizeLimit, - this.batchFileLimit = kBatchHashFileLimit, + int? batchFileLimit, }) : _deviceAssetRepository = deviceAssetRepository, - _backgroundService = backgroundService; + _backgroundService = backgroundService, + batchFileLimit = batchFileLimit ?? kBatchHashFileLimit; final IsarDeviceAssetRepository _deviceAssetRepository; final BackgroundService _backgroundService; diff --git a/mobile/lib/services/local_notification.service.dart b/mobile/lib/services/local_notification.service.dart index e7fc3292e2..bf85f4a9a9 100644 --- a/mobile/lib/services/local_notification.service.dart +++ b/mobile/lib/services/local_notification.service.dart @@ -1,9 +1,9 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/providers/backup/manual_upload.provider.dart'; import 'package:immich_mobile/providers/notification_permission.provider.dart'; import 'package:permission_handler/permission_handler.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; final localNotificationService = Provider( (ref) => LocalNotificationService(ref.watch(notificationPermissionProvider), ref), @@ -110,7 +110,7 @@ class LocalNotificationService { switch (notificationResponse.actionId) { case cancelUploadActionID: { - debugPrint("User cancelled manual upload operation"); + dPrint(() => "User cancelled manual upload operation"); ref.read(manualUploadProvider.notifier).cancelBackup(); } } diff --git a/mobile/lib/services/localization.service.dart b/mobile/lib/services/localization.service.dart index 8bee710544..af63894249 100644 --- a/mobile/lib/services/localization.service.dart +++ b/mobile/lib/services/localization.service.dart @@ -2,9 +2,9 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; import 'package:easy_localization/src/localization.dart'; -import 'package:flutter/foundation.dart'; import 'package:immich_mobile/constants/locales.dart'; import 'package:immich_mobile/generated/codegen_loader.g.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; /// Workaround to manually load translations in another Isolate Future loadTranslations() async { @@ -17,7 +17,7 @@ Future loadTranslations() async { assetLoader: const CodegenLoader(), path: translationsPath, useOnlyLangCode: false, - onLoadError: (e) => debugPrint(e.toString()), + onLoadError: (e) => dPrint(() => e.toString()), fallbackLocale: locales.values.first, ); diff --git a/mobile/lib/services/search.service.dart b/mobile/lib/services/search.service.dart index 250fb67d82..f33adf80f9 100644 --- a/mobile/lib/services/search.service.dart +++ b/mobile/lib/services/search.service.dart @@ -1,4 +1,3 @@ -import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/string_extensions.dart'; import 'package:immich_mobile/infrastructure/repositories/search_api.repository.dart'; @@ -10,6 +9,7 @@ import 'package:immich_mobile/repositories/asset.repository.dart'; import 'package:immich_mobile/services/api.service.dart'; import 'package:logging/logging.dart'; import 'package:openapi/api.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; final searchServiceProvider = Provider( (ref) => SearchService( @@ -43,7 +43,7 @@ class SearchService { model: model, ); } catch (e) { - debugPrint("[ERROR] [getSearchSuggestions] ${e.toString()}"); + dPrint(() => "[ERROR] [getSearchSuggestions] ${e.toString()}"); return []; } } diff --git a/mobile/lib/services/server_info.service.dart b/mobile/lib/services/server_info.service.dart index 4319d9dbae..460e135421 100644 --- a/mobile/lib/services/server_info.service.dart +++ b/mobile/lib/services/server_info.service.dart @@ -1,4 +1,3 @@ -import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/models/server_info/server_config.model.dart'; import 'package:immich_mobile/models/server_info/server_disk_info.model.dart'; @@ -6,6 +5,7 @@ import 'package:immich_mobile/models/server_info/server_features.model.dart'; import 'package:immich_mobile/models/server_info/server_version.model.dart'; import 'package:immich_mobile/providers/api.provider.dart'; import 'package:immich_mobile/services/api.service.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; final serverInfoServiceProvider = Provider((ref) => ServerInfoService(ref.watch(apiServiceProvider))); @@ -21,7 +21,7 @@ class ServerInfoService { return ServerDiskInfo.fromDto(dto); } } catch (e) { - debugPrint("Error [getDiskInfo] ${e.toString()}"); + dPrint(() => "Error [getDiskInfo] ${e.toString()}"); } return null; } @@ -33,7 +33,7 @@ class ServerInfoService { return ServerVersion.fromDto(dto); } } catch (e) { - debugPrint("Error [getServerVersion] ${e.toString()}"); + dPrint(() => "Error [getServerVersion] ${e.toString()}"); } return null; } @@ -45,7 +45,7 @@ class ServerInfoService { return ServerFeatures.fromDto(dto); } } catch (e) { - debugPrint("Error [getServerFeatures] ${e.toString()}"); + dPrint(() => "Error [getServerFeatures] ${e.toString()}"); } return null; } @@ -57,7 +57,7 @@ class ServerInfoService { return ServerConfig.fromDto(dto); } } catch (e) { - debugPrint("Error [getServerConfig] ${e.toString()}"); + dPrint(() => "Error [getServerConfig] ${e.toString()}"); } return null; } diff --git a/mobile/lib/services/stack.service.dart b/mobile/lib/services/stack.service.dart index c24b9fb7f8..88189c6bcd 100644 --- a/mobile/lib/services/stack.service.dart +++ b/mobile/lib/services/stack.service.dart @@ -1,10 +1,10 @@ -import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/providers/api.provider.dart'; import 'package:immich_mobile/repositories/asset.repository.dart'; import 'package:immich_mobile/services/api.service.dart'; import 'package:openapi/api.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; class StackService { const StackService(this._api, this._assetRepository); @@ -16,7 +16,7 @@ class StackService { try { return _api.stacksApi.getStack(stackId); } catch (error) { - debugPrint("Error while fetching stack: $error"); + dPrint(() => "Error while fetching stack: $error"); } return null; } @@ -25,7 +25,7 @@ class StackService { try { return _api.stacksApi.createStack(StackCreateDto(assetIds: assetIds)); } catch (error) { - debugPrint("Error while creating stack: $error"); + dPrint(() => "Error while creating stack: $error"); } return null; } @@ -34,7 +34,7 @@ class StackService { try { return await _api.stacksApi.updateStack(stackId, StackUpdateDto(primaryAssetId: primaryAssetId)); } catch (error) { - debugPrint("Error while updating stack children: $error"); + dPrint(() => "Error while updating stack children: $error"); } return null; } @@ -54,7 +54,7 @@ class StackService { } await _assetRepository.transaction(() => _assetRepository.updateAll(removeAssets)); } catch (error) { - debugPrint("Error while deleting stack: $error"); + dPrint(() => "Error while deleting stack: $error"); } } } diff --git a/mobile/lib/services/sync.service.dart b/mobile/lib/services/sync.service.dart index 7b420413cf..1a5cb2a116 100644 --- a/mobile/lib/services/sync.service.dart +++ b/mobile/lib/services/sync.service.dart @@ -147,7 +147,9 @@ class SyncService { dbUsers, compare: (UserDto a, UserDto b) => a.id.compareTo(b.id), both: (UserDto a, UserDto b) { - if (!a.updatedAt.isAtSameMomentAs(b.updatedAt) || + if ((a.updatedAt == null && b.updatedAt != null) || + (a.updatedAt != null && b.updatedAt == null) || + (a.updatedAt != null && b.updatedAt != null && !a.updatedAt!.isAtSameMomentAs(b.updatedAt!)) || a.isPartnerSharedBy != b.isPartnerSharedBy || a.isPartnerSharedWith != b.isPartnerSharedWith || a.inTimeline != b.inTimeline) { diff --git a/mobile/lib/services/upload.service.dart b/mobile/lib/services/upload.service.dart index a711608e7f..e8e98562f7 100644 --- a/mobile/lib/services/upload.service.dart +++ b/mobile/lib/services/upload.service.dart @@ -3,12 +3,13 @@ import 'dart:convert'; import 'dart:io'; import 'package:background_downloader/background_downloader.dart'; -import 'package:flutter/material.dart'; +import 'package:cancellation_token_http/http.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/constants.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/store.model.dart'; import 'package:immich_mobile/entities/store.entity.dart'; +import 'package:immich_mobile/extensions/platform_extensions.dart'; import 'package:immich_mobile/infrastructure/repositories/backup.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart'; @@ -19,6 +20,8 @@ import 'package:immich_mobile/providers/infrastructure/storage.provider.dart'; import 'package:immich_mobile/repositories/upload.repository.dart'; import 'package:immich_mobile/services/api.service.dart'; import 'package:immich_mobile/services/app_settings.service.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; +import 'package:logging/logging.dart'; import 'package:path/path.dart' as p; final uploadServiceProvider = Provider((ref) { @@ -51,6 +54,7 @@ class UploadService { final StorageRepository _storageRepository; final DriftLocalAssetRepository _localAssetRepository; final AppSettingsService _appSettingsService; + final Logger _logger = Logger('UploadService'); final StreamController _taskStatusController = StreamController.broadcast(); final StreamController _taskProgressController = StreamController.broadcast(); @@ -78,7 +82,7 @@ class UploadService { _taskProgressController.close(); } - Future enqueueTasks(List tasks) { + Future> enqueueTasks(List tasks) { return _uploadRepository.enqueueBackgroundAll(tasks); } @@ -86,16 +90,8 @@ class UploadService { return _uploadRepository.getActiveTasks(group); } - Future getBackupTotalCount() { - return _backupRepository.getTotalCount(); - } - - Future getBackupRemainderCount(String userId) { - return _backupRepository.getRemainderCount(userId); - } - - Future getBackupFinishedCount(String userId) { - return _backupRepository.getBackupCount(userId); + Future<({int total, int remainder, int processing})> getBackupCounts(String userId) { + return _backupRepository.getAllCounts(userId); } Future manualBackup(List localAssets) async { @@ -138,7 +134,6 @@ class UploadService { } final batch = candidates.skip(i).take(batchSize).toList(); - List tasks = []; for (final asset in batch) { final task = await _getUploadTask(asset); @@ -156,9 +151,7 @@ class UploadService { } } - // Enqueue All does not work from the background on Android yet. This method is a temporary workaround - // that enqueues tasks one by one. - Future startBackupSerial(String userId) async { + Future startBackupWithHttpClient(String userId, bool hasWifi, CancellationToken token) async { await _storageRepository.clearCache(); shouldAbortQueuingTasks = false; @@ -168,14 +161,29 @@ class UploadService { return; } - for (final asset in candidates) { - if (shouldAbortQueuingTasks) { + const batchSize = 100; + for (int i = 0; i < candidates.length; i += batchSize) { + if (shouldAbortQueuingTasks || token.isCancelled) { break; } - final task = await _getUploadTask(asset); - if (task != null) { - await _uploadRepository.enqueueBackground(task); + final batch = candidates.skip(i).take(batchSize).toList(); + List tasks = []; + for (final asset in batch) { + final requireWifi = _shouldRequireWiFi(asset); + if (requireWifi && !hasWifi) { + _logger.warning('Skipping upload for ${asset.id} because it requires WiFi'); + continue; + } + + final task = await _getUploadTaskWithFile(asset); + if (task != null) { + tasks.add(task); + } + } + + if (tasks.isNotEmpty && !shouldAbortQueuingTasks) { + await _uploadRepository.backupWithDartClient(tasks, token); } } } @@ -198,10 +206,20 @@ class UploadService { return _uploadRepository.start(); } - void _handleTaskStatusUpdate(TaskStatusUpdate update) { + void _handleTaskStatusUpdate(TaskStatusUpdate update) async { switch (update.status) { case TaskStatus.complete: _handleLivePhoto(update); + + if (CurrentPlatform.isIOS) { + try { + final path = await update.task.filePath(); + await File(path).delete(); + } catch (e) { + _logger.severe('Error deleting file path for iOS: $e'); + } + } + break; default: @@ -238,10 +256,46 @@ class UploadService { enqueueTasks([uploadTask]); } catch (error, stackTrace) { - debugPrint("Error handling live photo upload task: $error $stackTrace"); + dPrint(() => "Error handling live photo upload task: $error $stackTrace"); } } + Future _getUploadTaskWithFile(LocalAsset asset) async { + final entity = await _storageRepository.getAssetEntityForAsset(asset); + if (entity == null) { + return null; + } + + final file = await _storageRepository.getFileForAsset(asset.id); + if (file == null) { + return null; + } + + final originalFileName = entity.isLivePhoto ? p.setExtension(asset.name, p.extension(file.path)) : asset.name; + + String metadata = UploadTaskMetadata( + localAssetId: asset.id, + isLivePhotos: entity.isLivePhoto, + livePhotoVideoId: '', + ).toJson(); + + return UploadTaskWithFile( + file: file, + task: await buildUploadTask( + file, + createdAt: asset.createdAt, + modifiedAt: asset.updatedAt, + originalFileName: originalFileName, + deviceAssetId: asset.id, + metadata: metadata, + group: "group", + priority: 0, + isFavorite: asset.isFavorite, + requiresWiFi: false, + ), + ); + } + Future _getUploadTask(LocalAsset asset, {String group = kBackupGroup, int? priority}) async { final entity = await _storageRepository.getAssetEntityForAsset(asset); if (entity == null) { diff --git a/mobile/lib/theme/dynamic_theme.dart b/mobile/lib/theme/dynamic_theme.dart index 99b949c9ac..d0cb8e646f 100644 --- a/mobile/lib/theme/dynamic_theme.dart +++ b/mobile/lib/theme/dynamic_theme.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:dynamic_color/dynamic_color.dart'; import 'package:immich_mobile/theme/theme_data.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; abstract final class DynamicTheme { const DynamicTheme._(); @@ -13,7 +14,7 @@ abstract final class DynamicTheme { final corePalette = await DynamicColorPlugin.getCorePalette(); if (corePalette != null) { final primaryColor = corePalette.toColorScheme().primary; - debugPrint('dynamic_color: Core palette detected.'); + dPrint(() => 'dynamic_color: Core palette detected.'); // Some palettes do not generate surface container colors accurately, // so we regenerate all colors using the primary color @@ -23,7 +24,7 @@ abstract final class DynamicTheme { ); } } catch (error) { - debugPrint('dynamic_color: Failed to obtain core palette: $error'); + dPrint(() => 'dynamic_color: Failed to obtain core palette: $error'); } } diff --git a/mobile/lib/utils/action_button.utils.dart b/mobile/lib/utils/action_button.utils.dart index 10facea9a2..c5a2583531 100644 --- a/mobile/lib/utils/action_button.utils.dart +++ b/mobile/lib/utils/action_button.utils.dart @@ -1,6 +1,8 @@ import 'package:flutter/widgets.dart'; import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/domain/models/album/album.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; +import 'package:immich_mobile/presentation/widgets/action_buttons/advanced_info_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/archive_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/delete_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/delete_local_action_button.widget.dart'; @@ -14,8 +16,8 @@ import 'package:immich_mobile/presentation/widgets/action_buttons/share_action_b import 'package:immich_mobile/presentation/widgets/action_buttons/share_link_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/trash_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/unarchive_action_button.widget.dart'; +import 'package:immich_mobile/presentation/widgets/action_buttons/unstack_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/upload_action_button.widget.dart'; -import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; class ActionButtonContext { final BaseAsset asset; @@ -23,7 +25,9 @@ class ActionButtonContext { final bool isArchived; final bool isTrashEnabled; final bool isInLockedView; + final bool isStacked; final RemoteAlbum? currentAlbum; + final bool advancedTroubleshooting; final ActionSource source; const ActionButtonContext({ @@ -31,13 +35,16 @@ class ActionButtonContext { required this.isOwner, required this.isArchived, required this.isTrashEnabled, + required this.isStacked, required this.isInLockedView, required this.currentAlbum, + required this.advancedTroubleshooting, required this.source, }); } enum ActionButtonType { + advancedInfo, share, shareLink, archive, @@ -51,10 +58,12 @@ enum ActionButtonType { deleteLocal, upload, removeFromAlbum, + unstack, likeActivity; bool shouldShow(ActionButtonContext context) { return switch (this) { + ActionButtonType.advancedInfo => context.advancedTroubleshooting, ActionButtonType.share => true, ActionButtonType.shareLink => !context.isInLockedView && // @@ -97,7 +106,7 @@ enum ActionButtonType { context.asset.hasRemote, ActionButtonType.deleteLocal => !context.isInLockedView && // - context.asset.storage == AssetState.local, + context.asset.hasLocal, ActionButtonType.upload => !context.isInLockedView && // context.asset.storage == AssetState.local, @@ -105,6 +114,10 @@ enum ActionButtonType { context.isOwner && // !context.isInLockedView && // context.currentAlbum != null, + ActionButtonType.unstack => + context.isOwner && // + !context.isInLockedView && // + context.isStacked, ActionButtonType.likeActivity => !context.isInLockedView && context.currentAlbum != null && @@ -115,6 +128,7 @@ enum ActionButtonType { Widget buildButton(ActionButtonContext context) { return switch (this) { + ActionButtonType.advancedInfo => AdvancedInfoActionButton(source: context.source), ActionButtonType.share => ShareActionButton(source: context.source), ActionButtonType.shareLink => ShareLinkActionButton(source: context.source), ActionButtonType.archive => ArchiveActionButton(source: context.source), @@ -132,27 +146,13 @@ enum ActionButtonType { source: context.source, ), ActionButtonType.likeActivity => const LikeActivityActionButton(), + ActionButtonType.unstack => UnStackActionButton(source: context.source), }; } } class ActionButtonBuilder { - static const List _actionTypes = [ - ActionButtonType.share, - ActionButtonType.shareLink, - ActionButtonType.likeActivity, - ActionButtonType.archive, - ActionButtonType.unarchive, - ActionButtonType.download, - ActionButtonType.trash, - ActionButtonType.deletePermanent, - ActionButtonType.delete, - ActionButtonType.moveToLockFolder, - ActionButtonType.removeFromLockFolder, - ActionButtonType.deleteLocal, - ActionButtonType.upload, - ActionButtonType.removeFromAlbum, - ]; + static const List _actionTypes = ActionButtonType.values; static List build(ActionButtonContext context) { return _actionTypes.where((type) => type.shouldShow(context)).map((type) => type.buildButton(context)).toList(); diff --git a/mobile/lib/utils/bootstrap.dart b/mobile/lib/utils/bootstrap.dart index e7abc66040..c77ceaa62d 100644 --- a/mobile/lib/utils/bootstrap.dart +++ b/mobile/lib/utils/bootstrap.dart @@ -89,11 +89,17 @@ abstract final class Bootstrap { return (isar, drift, logDb); } - static Future initDomain(Isar db, Drift drift, DriftLogger logDb, {bool shouldBufferLogs = true}) async { - final isBeta = await IsarStoreRepository(db).tryGet(StoreKey.betaTimeline) ?? false; + static Future initDomain( + Isar db, + Drift drift, + DriftLogger logDb, { + bool listenStoreUpdates = true, + bool shouldBufferLogs = true, + }) async { + final isBeta = await IsarStoreRepository(db).tryGet(StoreKey.betaTimeline) ?? true; final IStoreRepository storeRepo = isBeta ? DriftStoreRepository(drift) : IsarStoreRepository(db); - await StoreService.init(storeRepository: storeRepo); + await StoreService.init(storeRepository: storeRepo, listenUpdates: listenStoreUpdates); await LogService.init( logRepository: LogRepository(logDb), diff --git a/mobile/lib/utils/datetime_helpers.dart b/mobile/lib/utils/datetime_helpers.dart index 829f71c37e..c13c8ca312 100644 --- a/mobile/lib/utils/datetime_helpers.dart +++ b/mobile/lib/utils/datetime_helpers.dart @@ -1,7 +1,7 @@ const int _maxMillisecondsSinceEpoch = 8640000000000000; // 275760-09-13 const int _minMillisecondsSinceEpoch = -62135596800000; // 0001-01-01 -DateTime? tryFromSecondsSinceEpoch(int? secondsSinceEpoch) { +DateTime? tryFromSecondsSinceEpoch(int? secondsSinceEpoch, {bool isUtc = false}) { if (secondsSinceEpoch == null) { return null; } @@ -12,7 +12,7 @@ DateTime? tryFromSecondsSinceEpoch(int? secondsSinceEpoch) { } try { - return DateTime.fromMillisecondsSinceEpoch(milliSeconds); + return DateTime.fromMillisecondsSinceEpoch(milliSeconds, isUtc: isUtc); } catch (e) { return null; } diff --git a/mobile/lib/utils/debug_print.dart b/mobile/lib/utils/debug_print.dart new file mode 100644 index 0000000000..21f55fc6a5 --- /dev/null +++ b/mobile/lib/utils/debug_print.dart @@ -0,0 +1,8 @@ +import 'package:flutter/foundation.dart'; + +@pragma('vm:prefer-inline') +void dPrint(String Function() message) { + if (kDebugMode) { + debugPrint(message()); + } +} diff --git a/mobile/lib/utils/isolate.dart b/mobile/lib/utils/isolate.dart index cca1498e0f..1ccf00d58b 100644 --- a/mobile/lib/utils/isolate.dart +++ b/mobile/lib/utils/isolate.dart @@ -1,14 +1,15 @@ import 'dart:async'; import 'dart:ui'; -import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/services/log.service.dart'; +import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/providers/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/cancel.provider.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/utils/bootstrap.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; import 'package:immich_mobile/utils/http_ssl_options.dart'; import 'package:logging/logging.dart'; import 'package:worker_manager/worker_manager.dart'; @@ -31,55 +32,63 @@ Cancelable runInIsolateGentle({ } return workerManager.executeGentle((cancelledChecker) async { - BackgroundIsolateBinaryMessenger.ensureInitialized(token); - DartPluginRegistrant.ensureInitialized(); + T? result; + await runZonedGuarded( + () async { + BackgroundIsolateBinaryMessenger.ensureInitialized(token); + DartPluginRegistrant.ensureInitialized(); - final (isar, drift, logDb) = await Bootstrap.initDB(); - await Bootstrap.initDomain(isar, drift, logDb, shouldBufferLogs: false); - final ref = ProviderContainer( - overrides: [ - // TODO: Remove once isar is removed - dbProvider.overrideWithValue(isar), - isarProvider.overrideWithValue(isar), - cancellationProvider.overrideWithValue(cancelledChecker), - driftProvider.overrideWith(driftOverride(drift)), - ], - ); + final (isar, drift, logDb) = await Bootstrap.initDB(); + await Bootstrap.initDomain(isar, drift, logDb, shouldBufferLogs: false, listenStoreUpdates: false); + final ref = ProviderContainer( + overrides: [ + // TODO: Remove once isar is removed + dbProvider.overrideWithValue(isar), + isarProvider.overrideWithValue(isar), + cancellationProvider.overrideWithValue(cancelledChecker), + driftProvider.overrideWith(driftOverride(drift)), + ], + ); - Logger log = Logger("IsolateLogger"); + Logger log = Logger("IsolateLogger"); - try { - HttpSSLOptions.apply(applyNative: false); - return await computation(ref); - } on CanceledError { - log.warning("Computation cancelled ${debugLabel == null ? '' : ' for $debugLabel'}"); - } catch (error, stack) { - log.severe("Error in runInIsolateGentle ${debugLabel == null ? '' : ' for $debugLabel'}", error, stack); - } finally { - try { - await LogService.I.dispose(); - await logDb.close(); - await ref.read(driftProvider).close(); - - // Close Isar safely try { - final isar = ref.read(isarProvider); - if (isar.isOpen) { - await isar.close(); - } - } catch (e) { - debugPrint("Error closing Isar: $e"); - } + HttpSSLOptions.apply(applyNative: false); + result = await computation(ref); + } on CanceledError { + log.warning("Computation cancelled ${debugLabel == null ? '' : ' for $debugLabel'}"); + } catch (error, stack) { + log.severe("Error in runInIsolateGentle ${debugLabel == null ? '' : ' for $debugLabel'}", error, stack); + } finally { + try { + ref.dispose(); - ref.dispose(); - } catch (error, stack) { - debugPrint("Error closing resources in isolate: $error, $stack"); - } finally { - ref.dispose(); - // Delay to ensure all resources are released - await Future.delayed(const Duration(seconds: 2)); - } - } - return null; + await Store.dispose(); + await LogService.I.dispose(); + await logDb.close(); + await drift.close(); + + // Close Isar safely + try { + if (isar.isOpen) { + await isar.close(); + } + } catch (e) { + dPrint(() => "Error closing Isar: $e"); + } + } catch (error, stack) { + dPrint(() => "Error closing resources in isolate: $error, $stack"); + } finally { + ref.dispose(); + // Delay to ensure all resources are released + await Future.delayed(const Duration(seconds: 2)); + } + } + }, + (error, stack) { + dPrint(() => "Error in isolate $debugLabel zone: $error, $stack"); + }, + ); + return result; }); } diff --git a/mobile/lib/utils/migration.dart b/mobile/lib/utils/migration.dart index 0a786fed0b..2ed6d9549f 100644 --- a/mobile/lib/utils/migration.dart +++ b/mobile/lib/utils/migration.dart @@ -4,8 +4,6 @@ import 'dart:io'; import 'package:collection/collection.dart'; import 'package:drift/drift.dart'; -import 'package:flutter/foundation.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/album/local_album.model.dart'; import 'package:immich_mobile/domain/models/store.model.dart'; import 'package:immich_mobile/entities/album.entity.dart'; @@ -23,22 +21,19 @@ import 'package:immich_mobile/infrastructure/entities/store.entity.dart'; import 'package:immich_mobile/infrastructure/entities/store.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/user.entity.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; -import 'package:immich_mobile/providers/app_settings.provider.dart'; -import 'package:immich_mobile/providers/background_sync.provider.dart'; -import 'package:immich_mobile/providers/backup/backup.provider.dart'; +import 'package:immich_mobile/infrastructure/repositories/sync_stream.repository.dart'; import 'package:immich_mobile/services/app_settings.service.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; import 'package:immich_mobile/utils/diff.dart'; import 'package:isar/isar.dart'; -import 'package:logging/logging.dart'; // ignore: import_rule_photo_manager import 'package:photo_manager/photo_manager.dart'; -const int targetVersion = 14; +const int targetVersion = 17; Future migrateDatabaseIfNeeded(Isar db, Drift drift) async { final hasVersion = Store.tryGet(StoreKey.version) != null; final int version = Store.get(StoreKey.version, targetVersion); - if (version < 9) { await Store.put(StoreKey.version, targetVersion); final value = await db.storeValues.get(StoreKey.currentUser.id); @@ -68,6 +63,15 @@ Future migrateDatabaseIfNeeded(Isar db, Drift drift) async { await Store.populateCache(); } + await handleBetaMigration(version, await _isNewInstallation(db, drift), SyncStreamRepository(drift)); + + if (version < 17 && Store.isBetaTimelineEnabled) { + final delay = Store.get(StoreKey.backupTriggerDelay, AppSettingsEnum.backupTriggerDelay.defaultValue); + if (delay >= 1000) { + await Store.put(StoreKey.backupTriggerDelay, (delay / 1000).toInt()); + } + } + if (targetVersion >= 12) { await Store.put(StoreKey.version, targetVersion); return; @@ -80,6 +84,66 @@ Future migrateDatabaseIfNeeded(Isar db, Drift drift) async { } } +Future handleBetaMigration(int version, bool isNewInstallation, SyncStreamRepository syncStreamRepository) async { + // Handle migration only for this version + // TODO: remove when old timeline is removed + final isBeta = Store.tryGet(StoreKey.betaTimeline); + final needBetaMigration = Store.tryGet(StoreKey.needBetaMigration); + if (version <= 15 && needBetaMigration == null) { + // For new installations, no migration needed + // For existing installations, only migrate if beta timeline is not enabled (null or false) + if (isNewInstallation || isBeta == true) { + await Store.put(StoreKey.needBetaMigration, false); + await Store.put(StoreKey.betaTimeline, true); + } else { + await Store.put(StoreKey.needBetaMigration, true); + } + } + + if (version > 15) { + if (isBeta == null || isBeta) { + await Store.put(StoreKey.needBetaMigration, false); + await Store.put(StoreKey.betaTimeline, true); + } else { + await Store.put(StoreKey.needBetaMigration, false); + } + } + + if (version < 16) { + await syncStreamRepository.reset(); + await Store.put(StoreKey.shouldResetSync, true); + } +} + +Future _isNewInstallation(Isar db, Drift drift) async { + try { + final isarUserCount = await db.users.count(); + if (isarUserCount > 0) { + return false; + } + + final isarAssetCount = await db.assets.count(); + if (isarAssetCount > 0) { + return false; + } + + final driftStoreCount = await drift.storeEntity.select().get().then((list) => list.length); + if (driftStoreCount > 0) { + return false; + } + + final driftAssetCount = await drift.localAssetEntity.select().get().then((list) => list.length); + if (driftAssetCount > 0) { + return false; + } + + return true; + } catch (error) { + dPrint(() => "[MIGRATION] Error checking if new installation: $error"); + return false; + } +} + Future _migrateTo(Isar db, int version) async { await Store.delete(StoreKey.assetETag); await db.writeTxn(() async { @@ -101,10 +165,7 @@ Future _migrateDeviceAsset(Isar db) async { final PermissionState ps = await PhotoManager.requestPermissionExtend(); if (!ps.hasAccess) { - if (kDebugMode) { - debugPrint("[MIGRATION] Photo library permission not granted. Skipping device asset migration."); - } - + dPrint(() => "[MIGRATION] Photo library permission not granted. Skipping device asset migration."); return; } @@ -124,8 +185,8 @@ Future _migrateDeviceAsset(Isar db) async { 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}"); + dPrint(() => "[MIGRATION] Device Asset Ids length - ${ids.length}"); + dPrint(() => "[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 = []; @@ -140,20 +201,14 @@ Future _migrateDeviceAsset(Isar db) async { return false; }, onlyFirst: (deviceAsset) { - if (kDebugMode) { - debugPrint('[MIGRATION] Local asset not found in DeviceAsset: ${deviceAsset.assetId}'); - } + dPrint(() => '[MIGRATION] Local asset not found in DeviceAsset: ${deviceAsset.assetId}'); }, onlySecond: (asset) { - if (kDebugMode) { - debugPrint('[MIGRATION] Local asset not found in DeviceAsset: ${asset.assetId}'); - } + dPrint(() => '[MIGRATION] Local asset not found in DeviceAsset: ${asset.assetId}'); }, ); - if (kDebugMode) { - debugPrint("[MIGRATION] Total number of device assets migrated - ${toAdd.length}"); - } + dPrint(() => "[MIGRATION] Total number of device assets migrated - ${toAdd.length}"); await db.writeTxn(() async { await db.deviceAssetEntitys.putAll(toAdd); @@ -173,7 +228,7 @@ Future migrateDeviceAssetToSqlite(Isar db, Drift drift) async { } }); } catch (error) { - debugPrint("[MIGRATION] Error while migrating device assets to SQLite: $error"); + dPrint(() => "[MIGRATION] Error while migrating device assets to SQLite: $error"); } } @@ -221,7 +276,7 @@ Future migrateBackupAlbumsToSqlite(Isar db, Drift drift) async { } }); } catch (error) { - debugPrint("[MIGRATION] Error while migrating backup albums to SQLite: $error"); + dPrint(() => "[MIGRATION] Error while migrating backup albums to SQLite: $error"); } } @@ -239,7 +294,7 @@ Future migrateStoreToSqlite(Isar db, Drift drift) async { } }); } catch (error) { - debugPrint("[MIGRATION] Error while migrating store values to SQLite: $error"); + dPrint(() => "[MIGRATION] Error while migrating store values to SQLite: $error"); } } @@ -254,7 +309,7 @@ Future migrateStoreToIsar(Isar db, Drift drift) async { await db.storeValues.putAll(driftStoreValues); }); } catch (error) { - debugPrint("[MIGRATION] Error while migrating store values to Isar: $error"); + dPrint(() => "[MIGRATION] Error while migrating store values to Isar: $error"); } } @@ -265,22 +320,3 @@ class _DeviceAsset { const _DeviceAsset({required this.assetId, this.hash, this.dateTime}); } - -Future> runNewSync(WidgetRef ref, {bool full = false}) { - ref.read(backupProvider.notifier).cancelBackup(); - - final backgroundManager = ref.read(backgroundSyncProvider); - final isAlbumLinkedSyncEnable = ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.syncAlbums); - - return Future.wait([ - backgroundManager.syncLocal(full: full).then((_) { - Logger("runNewSync").fine("Hashing assets after syncLocal"); - return backgroundManager.hashAssets(); - }), - backgroundManager.syncRemote().then((_) { - if (isAlbumLinkedSyncEnable) { - return backgroundManager.syncLinkedAlbum(); - } - }), - ]); -} diff --git a/mobile/lib/widgets/asset_grid/delete_dialog.dart b/mobile/lib/widgets/asset_grid/delete_dialog.dart index e7c7775e54..adb22889a8 100644 --- a/mobile/lib/widgets/asset_grid/delete_dialog.dart +++ b/mobile/lib/widgets/asset_grid/delete_dialog.dart @@ -22,12 +22,12 @@ class DeleteLocalOnlyDialog extends StatelessWidget { @override Widget build(BuildContext context) { void onDeleteBackedUpOnly() { - context.pop(); + context.pop(true); onDeleteLocal(true); } void onForceDelete() { - context.pop(); + context.pop(false); onDeleteLocal(false); } @@ -36,26 +36,44 @@ class DeleteLocalOnlyDialog extends StatelessWidget { title: const Text("delete_dialog_title").tr(), content: const Text("delete_dialog_alert_local_non_backed_up").tr(), actions: [ - TextButton( - onPressed: () => context.pop(), - child: Text( - "cancel", - style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.bold), - ).tr(), + SizedBox( + width: double.infinity, + height: 48, + child: FilledButton( + onPressed: () => context.pop(), + style: FilledButton.styleFrom( + backgroundColor: context.colorScheme.surfaceDim, + foregroundColor: context.primaryColor, + ), + child: const Text("cancel", style: TextStyle(fontWeight: FontWeight.bold)).tr(), + ), ), - TextButton( - onPressed: onDeleteBackedUpOnly, - child: Text( - "delete_local_dialog_ok_backed_up_only", - style: TextStyle(color: context.colorScheme.tertiary, fontWeight: FontWeight.bold), - ).tr(), + const SizedBox(height: 8), + SizedBox( + width: double.infinity, + height: 48, + + child: FilledButton( + onPressed: onDeleteBackedUpOnly, + style: FilledButton.styleFrom( + backgroundColor: context.colorScheme.errorContainer, + foregroundColor: context.colorScheme.onErrorContainer, + ), + child: const Text( + "delete_local_dialog_ok_backed_up_only", + style: TextStyle(fontWeight: FontWeight.bold), + ).tr(), + ), ), - TextButton( - onPressed: onForceDelete, - child: Text( - "delete_local_dialog_ok_force", - style: TextStyle(color: Colors.red[400], fontWeight: FontWeight.bold), - ).tr(), + const SizedBox(height: 8), + SizedBox( + width: double.infinity, + height: 48, + child: FilledButton( + onPressed: onForceDelete, + style: FilledButton.styleFrom(backgroundColor: Colors.red[400], foregroundColor: Colors.white), + child: const Text("delete_local_dialog_ok_force", style: TextStyle(fontWeight: FontWeight.bold)).tr(), + ), ), ], ); diff --git a/mobile/lib/widgets/asset_viewer/bottom_gallery_bar.dart b/mobile/lib/widgets/asset_viewer/bottom_gallery_bar.dart index c7125e2200..00f7bc494d 100644 --- a/mobile/lib/widgets/asset_viewer/bottom_gallery_bar.dart +++ b/mobile/lib/widgets/asset_viewer/bottom_gallery_bar.dart @@ -98,7 +98,12 @@ class BottomGalleryBar extends ConsumerWidget { if (isDeleted) { // Can only trash assets stored in server. Local assets are always permanently removed for now if (context.mounted && asset.isRemote && isStackPrimaryAsset) { - ImmichToast.show(durationInSecond: 1, context: context, msg: 'Asset trashed', gravity: ToastGravity.BOTTOM); + ImmichToast.show( + durationInSecond: 1, + context: context, + msg: 'asset_trashed'.tr(), + gravity: ToastGravity.BOTTOM, + ); } removeAssetFromStack(); } diff --git a/mobile/lib/widgets/asset_viewer/cast_dialog.dart b/mobile/lib/widgets/asset_viewer/cast_dialog.dart index 4db1d9bb69..f7c80cca3d 100644 --- a/mobile/lib/widgets/asset_viewer/cast_dialog.dart +++ b/mobile/lib/widgets/asset_viewer/cast_dialog.dart @@ -29,7 +29,7 @@ class CastDialog extends ConsumerWidget { future: ref.read(castProvider.notifier).getDevices(), builder: (context, snapshot) { if (snapshot.hasError) { - return Text('Error: ${snapshot.error.toString()}'); + return Text('error_saving_image'.tr(args: [snapshot.error.toString()])); } else if (!snapshot.hasData) { return const SizedBox(height: 48, child: Center(child: CircularProgressIndicator())); } diff --git a/mobile/lib/widgets/asset_viewer/detail_panel/exif_map.dart b/mobile/lib/widgets/asset_viewer/detail_panel/exif_map.dart index 04d01194e9..0edafa88c5 100644 --- a/mobile/lib/widgets/asset_viewer/detail_panel/exif_map.dart +++ b/mobile/lib/widgets/asset_viewer/detail_panel/exif_map.dart @@ -5,6 +5,7 @@ import 'package:immich_mobile/domain/models/exif.model.dart'; import 'package:immich_mobile/widgets/map/map_thumbnail.dart'; import 'package:maplibre_gl/maplibre_gl.dart'; import 'package:url_launcher/url_launcher.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; class ExifMap extends StatelessWidget { final ExifInfo exifInfo; @@ -66,7 +67,7 @@ class ExifMap extends StatelessWidget { return; } - debugPrint('Opening Map Uri: $uri'); + dPrint(() => 'Opening Map Uri: $uri'); launchUrl(uri); }, onCreated: onMapCreated, diff --git a/mobile/lib/widgets/backup/backup_info_card.dart b/mobile/lib/widgets/backup/backup_info_card.dart index 6e34e89938..2ef7e24cd7 100644 --- a/mobile/lib/widgets/backup/backup_info_card.dart +++ b/mobile/lib/widgets/backup/backup_info_card.dart @@ -8,8 +8,17 @@ class BackupInfoCard extends StatelessWidget { final String title; final String subtitle; final String info; + final VoidCallback? onTap; - const BackupInfoCard({super.key, required this.title, required this.subtitle, required this.info, this.onTap}); + final bool isLoading; + const BackupInfoCard({ + super.key, + required this.title, + required this.subtitle, + required this.info, + this.onTap, + this.isLoading = false, + }); @override Widget build(BuildContext context) { @@ -38,8 +47,36 @@ class BackupInfoCard extends StatelessWidget { trailing: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text(info, style: context.textTheme.titleLarge), - Text("backup_info_card_assets", style: context.textTheme.labelLarge).tr(), + Stack( + children: [ + Text( + info, + style: context.textTheme.titleLarge?.copyWith( + color: context.colorScheme.onSurface.withAlpha(isLoading ? 50 : 255), + ), + ), + if (isLoading) + Positioned.fill( + child: Align( + alignment: Alignment.center, + child: SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator( + strokeWidth: 2, + color: context.colorScheme.onSurface.withAlpha(150), + ), + ), + ), + ), + ], + ), + Text( + "backup_info_card_assets", + style: context.textTheme.labelLarge?.copyWith( + color: context.colorScheme.onSurface.withAlpha(isLoading ? 50 : 255), + ), + ).tr(), ], ), ), diff --git a/mobile/lib/widgets/common/app_bar_dialog/app_bar_profile_info.dart b/mobile/lib/widgets/common/app_bar_dialog/app_bar_profile_info.dart index a9c7a467c2..00366ca580 100644 --- a/mobile/lib/widgets/common/app_bar_dialog/app_bar_profile_info.dart +++ b/mobile/lib/widgets/common/app_bar_dialog/app_bar_profile_info.dart @@ -90,11 +90,11 @@ class AppBarProfileInfoBox extends HookConsumerWidget { minLeadingWidth: 50, leading: GestureDetector( onTap: pickUserProfileImage, - onDoubleTap: toggleReadonlyMode, + onLongPress: toggleReadonlyMode, child: Stack( clipBehavior: Clip.none, children: [ - buildUserProfileImage(), + AbsorbPointer(child: buildUserProfileImage()), if (!isReadonlyModeEnabled) Positioned( bottom: -5, diff --git a/mobile/lib/widgets/common/immich_app_bar.dart b/mobile/lib/widgets/common/immich_app_bar.dart index 7eaedd27b5..28b5c535d2 100644 --- a/mobile/lib/widgets/common/immich_app_bar.dart +++ b/mobile/lib/widgets/common/immich_app_bar.dart @@ -129,19 +129,24 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget { title: Builder( builder: (BuildContext context) { return Row( + crossAxisAlignment: CrossAxisAlignment.center, children: [ - Builder( - builder: (context) { - return Padding( - padding: const EdgeInsets.only(top: 3.0), - child: SvgPicture.asset( - context.isDarkTheme - ? 'assets/immich-logo-inline-dark.svg' - : 'assets/immich-logo-inline-light.svg', - height: 40, - ), - ); - }, + Padding( + padding: const EdgeInsets.only(top: 3.0), + child: SvgPicture.asset( + context.isDarkTheme ? 'assets/immich-logo-inline-dark.svg' : 'assets/immich-logo-inline-light.svg', + height: 40, + ), + ), + const Tooltip( + triggerMode: TooltipTriggerMode.tap, + showDuration: Duration(seconds: 4), + message: + "The old timeline is deprecated and will be removed in a future release. Kindly switch to the new timeline under Advanced Settings.", + child: Padding( + padding: EdgeInsets.only(top: 3.0), + child: Icon(Icons.error_rounded, fill: 1, color: Colors.amber, size: 20), + ), ), ], ); diff --git a/mobile/lib/widgets/common/immich_sliver_app_bar.dart b/mobile/lib/widgets/common/immich_sliver_app_bar.dart index ee111851ad..90c213599c 100644 --- a/mobile/lib/widgets/common/immich_sliver_app_bar.dart +++ b/mobile/lib/widgets/common/immich_sliver_app_bar.dart @@ -9,8 +9,8 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/models/server_info/server_info.model.dart'; import 'package:immich_mobile/providers/backup/drift_backup.provider.dart'; import 'package:immich_mobile/providers/cast.provider.dart'; -import 'package:immich_mobile/providers/infrastructure/setting.provider.dart'; import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/setting.provider.dart'; import 'package:immich_mobile/providers/server_info.provider.dart'; import 'package:immich_mobile/providers/sync_status.provider.dart'; import 'package:immich_mobile/providers/timeline/multiselect.provider.dart'; @@ -97,29 +97,11 @@ class _ImmichLogoWithText extends StatelessWidget { children: [ Builder( builder: (context) { - return Badge( - padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4), - backgroundColor: context.primaryColor, - alignment: Alignment.centerRight, - offset: const Offset(16, -8), - label: Text( - 'β', - style: TextStyle( - fontSize: 11, - color: context.colorScheme.onPrimary, - fontWeight: FontWeight.bold, - fontFamily: 'OverpassMono', - height: 1.2, - ), - ), - child: Padding( - padding: const EdgeInsets.only(top: 3.0), - child: SvgPicture.asset( - context.isDarkTheme - ? 'assets/immich-logo-inline-dark.svg' - : 'assets/immich-logo-inline-light.svg', - height: 40, - ), + return Padding( + padding: const EdgeInsets.only(top: 3.0), + child: SvgPicture.asset( + context.isDarkTheme ? 'assets/immich-logo-inline-dark.svg' : 'assets/immich-logo-inline-light.svg', + height: 40, ), ); }, @@ -157,7 +139,7 @@ class _ProfileIndicator extends ConsumerWidget { return InkWell( onTap: () => showDialog(context: context, useRootNavigator: false, builder: (ctx) => const ImmichAppBarDialog()), - onDoubleTap: () => toggleReadonlyMode(), + onLongPress: () => toggleReadonlyMode(), borderRadius: const BorderRadius.all(Radius.circular(12)), child: Badge( label: Container( @@ -173,47 +155,39 @@ class _ProfileIndicator extends ConsumerWidget { ? const Icon(Icons.face_outlined, size: widgetSize) : Semantics( label: "logged_in_as".tr(namedArgs: {"user": user.name}), - child: UserCircleAvatar(radius: 17, size: 31, user: user), + child: AbsorbPointer(child: UserCircleAvatar(radius: 17, size: 31, user: user)), ), ), ); } } +const double _kBadgeWidgetSize = 30.0; + class _BackupIndicator extends ConsumerWidget { const _BackupIndicator(); @override Widget build(BuildContext context, WidgetRef ref) { - const widgetSize = 30.0; final indicatorIcon = _getBackupBadgeIcon(context, ref); - final badgeBackground = context.colorScheme.surfaceContainer; return InkWell( onTap: () => context.pushRoute(const DriftBackupRoute()), borderRadius: const BorderRadius.all(Radius.circular(12)), child: Badge( - label: Container( - width: widgetSize / 2, - height: widgetSize / 2, - decoration: BoxDecoration( - color: badgeBackground, - border: Border.all(color: context.colorScheme.outline.withValues(alpha: .3)), - borderRadius: BorderRadius.circular(widgetSize / 2), - ), - child: indicatorIcon, - ), + label: indicatorIcon, backgroundColor: Colors.transparent, alignment: Alignment.bottomRight, isLabelVisible: indicatorIcon != null, offset: const Offset(-2, -12), - child: Icon(Icons.backup_rounded, size: widgetSize, color: context.primaryColor), + child: Icon(Icons.backup_rounded, size: _kBadgeWidgetSize, color: context.primaryColor), ), ); } Widget? _getBackupBadgeIcon(BuildContext context, WidgetRef ref) { final backupStateStream = ref.watch(settingsProvider).watch(Setting.enableBackup); + final hasError = ref.watch(driftBackupProvider.select((state) => state.error != BackupError.none)); final isDarkTheme = context.isDarkTheme; final iconColor = isDarkTheme ? Colors.white : Colors.black; final isUploading = ref.watch(driftBackupProvider.select((state) => state.uploadItems.isNotEmpty)); @@ -225,42 +199,76 @@ class _BackupIndicator extends ConsumerWidget { final backupEnabled = snapshot.data ?? false; if (!backupEnabled) { - return Icon( - Icons.cloud_off_rounded, - size: 9, - color: iconColor, - semanticLabel: 'backup_controller_page_backup'.tr(), + return _BadgeLabel( + Icon( + Icons.cloud_off_rounded, + size: 9, + color: iconColor, + semanticLabel: 'backup_controller_page_backup'.tr(), + ), + ); + } + + if (hasError) { + return _BadgeLabel( + Icon( + Icons.warning_rounded, + size: 12, + color: context.colorScheme.error, + semanticLabel: 'backup_controller_page_backup'.tr(), + ), + backgroundColor: context.colorScheme.errorContainer, ); } if (isUploading) { - return Container( - padding: const EdgeInsets.all(3.5), - child: Theme( - data: context.themeData.copyWith( - progressIndicatorTheme: context.themeData.progressIndicatorTheme.copyWith(year2023: true), - ), - child: CircularProgressIndicator( - strokeWidth: 2, - strokeCap: StrokeCap.round, - valueColor: AlwaysStoppedAnimation(iconColor), - semanticsLabel: 'backup_controller_page_backup'.tr(), + return _BadgeLabel( + Container( + padding: const EdgeInsets.all(3.5), + child: Theme( + data: context.themeData.copyWith( + progressIndicatorTheme: context.themeData.progressIndicatorTheme.copyWith(year2023: true), + ), + child: CircularProgressIndicator( + strokeWidth: 2, + strokeCap: StrokeCap.round, + valueColor: AlwaysStoppedAnimation(iconColor), + semanticsLabel: 'backup_controller_page_backup'.tr(), + ), ), ), ); } - return Icon( - Icons.check_outlined, - size: 9, - color: iconColor, - semanticLabel: 'backup_controller_page_backup'.tr(), + return _BadgeLabel( + Icon(Icons.check_outlined, size: 9, color: iconColor, semanticLabel: 'backup_controller_page_backup'.tr()), ); }, ); } } +class _BadgeLabel extends StatelessWidget { + final Widget indicator; + final Color? backgroundColor; + + const _BadgeLabel(this.indicator, {this.backgroundColor}); + + @override + Widget build(BuildContext context) { + return Container( + width: _kBadgeWidgetSize / 2, + height: _kBadgeWidgetSize / 2, + decoration: BoxDecoration( + color: backgroundColor ?? context.colorScheme.surfaceContainer, + border: Border.all(color: context.colorScheme.outline.withValues(alpha: .3)), + borderRadius: BorderRadius.circular(_kBadgeWidgetSize / 2), + ), + child: indicator, + ); + } +} + class _SyncStatusIndicator extends ConsumerStatefulWidget { const _SyncStatusIndicator(); diff --git a/mobile/lib/widgets/common/remote_album_sliver_app_bar.dart b/mobile/lib/widgets/common/remote_album_sliver_app_bar.dart index f9768d575e..f75dd6e803 100644 --- a/mobile/lib/widgets/common/remote_album_sliver_app_bar.dart +++ b/mobile/lib/widgets/common/remote_album_sliver_app_bar.dart @@ -75,86 +75,79 @@ class _MesmerizingSliverAppBarState extends ConsumerState const SizedBox(height: 120), - _ => const SizedBox(height: 452), - }, - ); - } else { - return SliverAppBar( - expandedHeight: 400.0, - floating: false, - pinned: true, - snap: false, - elevation: 0, - leading: IconButton( - icon: Icon( - Platform.isIOS ? Icons.arrow_back_ios_new_rounded : Icons.arrow_back, - color: actionIconColor, - shadows: actionIconShadows, - ), - onPressed: () => context.navigateTo(const TabShellRoute(children: [DriftAlbumsRoute()])), - ), - actions: [ - if (widget.onToggleAlbumOrder != null) - IconButton( - icon: Icon(Icons.swap_vert_rounded, color: actionIconColor, shadows: actionIconShadows), - onPressed: widget.onToggleAlbumOrder, - ), - if (currentAlbum.isActivityEnabled && currentAlbum.isShared) - IconButton( - icon: Icon(Icons.chat_outlined, color: actionIconColor, shadows: actionIconShadows), - onPressed: widget.onActivity, - ), - if (widget.onShowOptions != null) - IconButton( - icon: Icon(Icons.more_vert, color: actionIconColor, shadows: actionIconShadows), - onPressed: widget.onShowOptions, - ), - ], - title: Builder( - builder: (context) { - final settings = context.dependOnInheritedWidgetOfExactType(); - final scrollProgress = _calculateScrollProgress(settings); - - return AnimatedSwitcher( - duration: const Duration(milliseconds: 200), - child: scrollProgress > 0.95 - ? Text( - currentAlbum.name, - style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.w600, fontSize: 18), - ) - : null, - ); - }, - ), - flexibleSpace: Builder( - builder: (context) { - final settings = context.dependOnInheritedWidgetOfExactType(); - final scrollProgress = _calculateScrollProgress(settings); - - // Update scroll progress for the leading button - WidgetsBinding.instance.addPostFrameCallback((_) { - if (mounted && _scrollProgress != scrollProgress) { - setState(() { - _scrollProgress = scrollProgress; - }); - } - }); - - return FlexibleSpaceBar( - background: _ExpandedBackground( - scrollProgress: scrollProgress, - icon: widget.icon, - onEditTitle: widget.onEditTitle, + return SliverAppBar( + expandedHeight: 400.0, + floating: false, + pinned: true, + snap: false, + elevation: 0, + leading: isMultiSelectEnabled + ? const SizedBox.shrink() + : IconButton( + icon: Icon( + Platform.isIOS ? Icons.arrow_back_ios_new_rounded : Icons.arrow_back, + color: actionIconColor, + shadows: actionIconShadows, ), - ); - }, - ), - ); - } + onPressed: () => context.navigateTo(const TabShellRoute(children: [DriftAlbumsRoute()])), + ), + actions: [ + if (widget.onToggleAlbumOrder != null) + IconButton( + icon: Icon(Icons.swap_vert_rounded, color: actionIconColor, shadows: actionIconShadows), + onPressed: widget.onToggleAlbumOrder, + ), + if (currentAlbum.isActivityEnabled && currentAlbum.isShared) + IconButton( + icon: Icon(Icons.chat_outlined, color: actionIconColor, shadows: actionIconShadows), + onPressed: widget.onActivity, + ), + if (widget.onShowOptions != null) + IconButton( + icon: Icon(Icons.more_vert, color: actionIconColor, shadows: actionIconShadows), + onPressed: widget.onShowOptions, + ), + ], + title: Builder( + builder: (context) { + final settings = context.dependOnInheritedWidgetOfExactType(); + final scrollProgress = _calculateScrollProgress(settings); + + return AnimatedSwitcher( + duration: const Duration(milliseconds: 200), + child: scrollProgress > 0.95 + ? Text( + currentAlbum.name, + style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.w600, fontSize: 18), + ) + : null, + ); + }, + ), + flexibleSpace: Builder( + builder: (context) { + final settings = context.dependOnInheritedWidgetOfExactType(); + final scrollProgress = _calculateScrollProgress(settings); + + // Update scroll progress for the leading button + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted && _scrollProgress != scrollProgress) { + setState(() { + _scrollProgress = scrollProgress; + }); + } + }); + + return FlexibleSpaceBar( + background: _ExpandedBackground( + scrollProgress: scrollProgress, + icon: widget.icon, + onEditTitle: widget.onEditTitle, + ), + ); + }, + ), + ); } } diff --git a/mobile/lib/widgets/forms/login/login_form.dart b/mobile/lib/widgets/forms/login/login_form.dart index ab78536a92..f100b58649 100644 --- a/mobile/lib/widgets/forms/login/login_form.dart +++ b/mobile/lib/widgets/forms/login/login_form.dart @@ -10,13 +10,16 @@ import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart' hide Store; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/domain/models/store.model.dart'; import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/providers/auth.provider.dart'; +import 'package:immich_mobile/providers/background_sync.provider.dart'; import 'package:immich_mobile/providers/backup/backup.provider.dart'; import 'package:immich_mobile/providers/gallery_permission.provider.dart'; import 'package:immich_mobile/providers/oauth.provider.dart'; import 'package:immich_mobile/providers/server_info.provider.dart'; +import 'package:immich_mobile/providers/websocket.provider.dart'; import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/utils/provider_utils.dart'; import 'package:immich_mobile/utils/url_helper.dart'; @@ -161,6 +164,18 @@ class LoginForm extends HookConsumerWidget { serverEndpointController.text = 'http://10.1.15.216:2283/api'; } + Future handleSyncFlow() async { + final backgroundManager = ref.read(backgroundSyncProvider); + + await backgroundManager.syncLocal(full: true); + await backgroundManager.syncRemote(); + await backgroundManager.hashAssets(); + + if (Store.get(StoreKey.syncAlbums, false)) { + await backgroundManager.syncLinkedAlbum(); + } + } + login() async { TextInput.finishAutofillContext(); @@ -178,7 +193,8 @@ class LoginForm extends HookConsumerWidget { final isBeta = Store.isBetaTimelineEnabled; if (isBeta) { await ref.read(galleryPermissionNotifier.notifier).requestGalleryPermission(); - + handleSyncFlow(); + ref.read(websocketProvider.notifier).connect(); context.replaceRoute(const TabShellRoute()); return; } @@ -276,6 +292,7 @@ class LoginForm extends HookConsumerWidget { } if (isBeta) { await ref.read(galleryPermissionNotifier.notifier).requestGalleryPermission(); + handleSyncFlow(); context.replaceRoute(const TabShellRoute()); return; } diff --git a/mobile/lib/widgets/map/map_asset_grid.dart b/mobile/lib/widgets/map/map_asset_grid.dart index 488b8480f2..b6c1e708a7 100644 --- a/mobile/lib/widgets/map/map_asset_grid.dart +++ b/mobile/lib/widgets/map/map_asset_grid.dart @@ -275,7 +275,7 @@ class _MapSheetDragRegion extends StatelessWidget { child: IconButton( icon: Icon(Icons.map_outlined, color: context.textTheme.displayLarge?.color), iconSize: 24, - tooltip: 'Zoom to bounds', + tooltip: 'zoom_to_bounds'.tr(), onPressed: () => onZoomToAsset?.call(value!), ), ), diff --git a/mobile/lib/widgets/map/map_settings/map_settings_list_tile.dart b/mobile/lib/widgets/map/map_settings/map_settings_list_tile.dart index 51567eff15..e97875fd90 100644 --- a/mobile/lib/widgets/map/map_settings/map_settings_list_tile.dart +++ b/mobile/lib/widgets/map/map_settings/map_settings_list_tile.dart @@ -13,7 +13,7 @@ class MapSettingsListTile extends StatelessWidget { @override Widget build(BuildContext context) { return SwitchListTile.adaptive( - activeColor: context.primaryColor, + activeThumbColor: context.primaryColor, title: Text(title, style: context.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold)).tr(), value: selected, onChanged: onChanged, diff --git a/mobile/lib/widgets/photo_view/src/core/photo_view_core.dart b/mobile/lib/widgets/photo_view/src/core/photo_view_core.dart index a8d53e5106..d21b49f020 100644 --- a/mobile/lib/widgets/photo_view/src/core/photo_view_core.dart +++ b/mobile/lib/widgets/photo_view/src/core/photo_view_core.dart @@ -350,8 +350,8 @@ class PhotoViewCoreState extends State final computedScale = useImageScale ? 1.0 : scale; final matrix = Matrix4.identity() - ..translate(value.position.dx, value.position.dy) - ..scale(computedScale) + ..translateByDouble(value.position.dx, value.position.dy, 0, 1.0) + ..scaleByDouble(computedScale, computedScale, computedScale, 1.0) ..rotateZ(value.rotation); final Widget customChildLayout = CustomSingleChildLayout( diff --git a/mobile/lib/widgets/search/search_filter/media_type_picker.dart b/mobile/lib/widgets/search/search_filter/media_type_picker.dart index 589ce6262b..e0e34b654e 100644 --- a/mobile/lib/widgets/search/search_filter/media_type_picker.dart +++ b/mobile/lib/widgets/search/search_filter/media_type_picker.dart @@ -13,40 +13,19 @@ class MediaTypePicker extends HookWidget { Widget build(BuildContext context) { final selectedMediaType = useState(filter ?? AssetType.other); - return ListView( - shrinkWrap: true, - children: [ - RadioListTile( - key: const Key("all"), - title: const Text("all").tr(), - value: AssetType.other, - onChanged: (value) { - selectedMediaType.value = value!; - onSelect(value); - }, - groupValue: selectedMediaType.value, - ), - RadioListTile( - key: const Key("image"), - title: const Text("image").tr(), - value: AssetType.image, - onChanged: (value) { - selectedMediaType.value = value!; - onSelect(value); - }, - groupValue: selectedMediaType.value, - ), - RadioListTile( - key: const Key("video"), - title: const Text("video").tr(), - value: AssetType.video, - onChanged: (value) { - selectedMediaType.value = value!; - onSelect(value); - }, - groupValue: selectedMediaType.value, - ), - ], + return RadioGroup( + onChanged: (value) { + selectedMediaType.value = value!; + onSelect(value); + }, + groupValue: selectedMediaType.value, + child: Column( + children: [ + RadioListTile(key: const Key("all"), title: const Text("all").tr(), value: AssetType.other), + RadioListTile(key: const Key("image"), title: const Text("image").tr(), value: AssetType.image), + RadioListTile(key: const Key("video"), title: const Text("video").tr(), value: AssetType.video), + ], + ), ); } } diff --git a/mobile/lib/widgets/settings/advanced_settings.dart b/mobile/lib/widgets/settings/advanced_settings.dart index cd2fa93b85..7a107b47d8 100644 --- a/mobile/lib/widgets/settings/advanced_settings.dart +++ b/mobile/lib/widgets/settings/advanced_settings.dart @@ -14,6 +14,7 @@ import 'package:immich_mobile/repositories/local_files_manager.repository.dart'; import 'package:immich_mobile/services/app_settings.service.dart'; import 'package:immich_mobile/utils/hooks/app_settings_update_hook.dart'; import 'package:immich_mobile/utils/http_ssl_options.dart'; +import 'package:immich_mobile/widgets/settings/beta_timeline_list_tile.dart'; import 'package:immich_mobile/widgets/settings/custom_proxy_headers_settings/custome_proxy_headers_settings.dart'; import 'package:immich_mobile/widgets/settings/local_storage_settings.dart'; import 'package:immich_mobile/widgets/settings/settings_slider_list_tile.dart'; @@ -91,7 +92,7 @@ class AdvancedSettings extends HookConsumerWidget { title: "advanced_settings_prefer_remote_title".tr(), subtitle: "advanced_settings_prefer_remote_subtitle".tr(), ), - const LocalStorageSettings(), + if (!Store.isBetaTimelineEnabled) const LocalStorageSettings(), SettingsSwitchListTile( enabled: !isLoggedIn, valueNotifier: allowSelfSignedSSLCert, @@ -101,12 +102,13 @@ class AdvancedSettings extends HookConsumerWidget { ), const CustomeProxyHeaderSettings(), SslClientCertSettings(isLoggedIn: ref.read(currentUserProvider) != null), - SettingsSwitchListTile( - valueNotifier: useAlternatePMFilter, - title: "advanced_settings_enable_alternate_media_filter_title".tr(), - subtitle: "advanced_settings_enable_alternate_media_filter_subtitle".tr(), - ), - // TODO: Remove this check when beta timeline goes stable + if (!Store.isBetaTimelineEnabled) + SettingsSwitchListTile( + valueNotifier: useAlternatePMFilter, + title: "advanced_settings_enable_alternate_media_filter_title".tr(), + subtitle: "advanced_settings_enable_alternate_media_filter_subtitle".tr(), + ), + const BetaTimelineListTile(), if (Store.isBetaTimelineEnabled) SettingsSwitchListTile( valueNotifier: readonlyModeEnabled, diff --git a/mobile/lib/widgets/settings/asset_viewer_settings/video_viewer_settings.dart b/mobile/lib/widgets/settings/asset_viewer_settings/video_viewer_settings.dart index 1d8d9812be..9a89b7e1e3 100644 --- a/mobile/lib/widgets/settings/asset_viewer_settings/video_viewer_settings.dart +++ b/mobile/lib/widgets/settings/asset_viewer_settings/video_viewer_settings.dart @@ -14,11 +14,18 @@ class VideoViewerSettings extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final useLoopVideo = useAppSettingsState(AppSettingsEnum.loopVideo); final useOriginalVideo = useAppSettingsState(AppSettingsEnum.loadOriginalVideo); + final useAutoPlayVideo = useAppSettingsState(AppSettingsEnum.autoPlayVideo); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SettingsSubTitle(title: "videos".tr()), + SettingsSwitchListTile( + valueNotifier: useAutoPlayVideo, + title: "setting_video_viewer_auto_play_title".tr(), + subtitle: "setting_video_viewer_auto_play_subtitle".tr(), + onChanged: (_) => ref.invalidate(appSettingsServiceProvider), + ), SettingsSwitchListTile( valueNotifier: useLoopVideo, title: "setting_video_viewer_looping_title".tr(), diff --git a/mobile/lib/widgets/settings/backup_settings/drift_backup_settings.dart b/mobile/lib/widgets/settings/backup_settings/drift_backup_settings.dart index ac9866d4da..743d38fc48 100644 --- a/mobile/lib/widgets/settings/backup_settings/drift_backup_settings.dart +++ b/mobile/lib/widgets/settings/backup_settings/drift_backup_settings.dart @@ -1,14 +1,19 @@ +import 'dart:async'; + +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/album/local_album.model.dart'; import 'package:immich_mobile/domain/models/store.model.dart'; +import 'package:immich_mobile/domain/services/sync_linked_album.service.dart'; import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_mobile/extensions/platform_extensions.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/providers/app_settings.provider.dart'; -import 'package:immich_mobile/domain/services/sync_linked_album.service.dart'; import 'package:immich_mobile/providers/background_sync.provider.dart'; import 'package:immich_mobile/providers/backup/backup_album.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/platform.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; import 'package:immich_mobile/services/app_settings.service.dart'; import 'package:immich_mobile/widgets/settings/settings_sub_page_scaffold.dart'; @@ -18,12 +23,40 @@ class DriftBackupSettings extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - return const SettingsSubPageScaffold( + return SettingsSubPageScaffold( settings: [ - _UseWifiForUploadVideosButton(), - _UseWifiForUploadPhotosButton(), - Divider(indent: 16, endIndent: 16), - _AlbumSyncActionButton(), + Padding( + padding: const EdgeInsets.only(left: 16.0), + child: Text( + "network_requirements".t(context: context).toUpperCase(), + style: context.textTheme.labelSmall?.copyWith(color: context.colorScheme.onSurface.withValues(alpha: 0.7)), + ), + ), + const _UseWifiForUploadVideosButton(), + const _UseWifiForUploadPhotosButton(), + if (CurrentPlatform.isAndroid) ...[ + const Divider(), + Padding( + padding: const EdgeInsets.only(left: 16.0), + child: Text( + "background_options".t(context: context).toUpperCase(), + style: context.textTheme.labelSmall?.copyWith( + color: context.colorScheme.onSurface.withValues(alpha: 0.7), + ), + ), + ), + const _BackupOnlyWhenChargingButton(), + const _BackupDelaySlider(), + ], + const Divider(), + Padding( + padding: const EdgeInsets.only(left: 16.0), + child: Text( + "backup_albums_sync".t(context: context).toUpperCase(), + style: context.textTheme.labelSmall?.copyWith(color: context.colorScheme.onSurface.withValues(alpha: 0.7)), + ), + ), + const _AlbumSyncActionButton(), ], ); } @@ -151,30 +184,59 @@ class _AlbumSyncActionButtonState extends ConsumerState<_AlbumSyncActionButton> } } -class _UseWifiForUploadVideosButton extends ConsumerWidget { - const _UseWifiForUploadVideosButton(); +class _SettingsSwitchTile extends ConsumerStatefulWidget { + final AppSettingsEnum appSettingsEnum; + final String titleKey; + final String subtitleKey; + final void Function(bool?)? onChanged; + + const _SettingsSwitchTile({ + required this.appSettingsEnum, + required this.titleKey, + required this.subtitleKey, + this.onChanged, + }); @override - Widget build(BuildContext context, WidgetRef ref) { - final valueStream = Store.watch(StoreKey.useWifiForUploadVideos); + ConsumerState createState() => _SettingsSwitchTileState(); +} +class _SettingsSwitchTileState extends ConsumerState<_SettingsSwitchTile> { + late final Stream valueStream; + late final StreamSubscription subscription; + + @override + void initState() { + super.initState(); + valueStream = Store.watch(widget.appSettingsEnum.storeKey).asBroadcastStream(); + subscription = valueStream.listen((value) { + widget.onChanged?.call(value); + }); + } + + @override + void dispose() { + subscription.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { return ListTile( title: Text( - "videos".t(context: context), + widget.titleKey.t(context: context), style: context.textTheme.titleMedium?.copyWith(color: context.primaryColor), ), - subtitle: Text("network_requirement_videos_upload".t(context: context), style: context.textTheme.labelLarge), + subtitle: Text(widget.subtitleKey.t(context: context), style: context.textTheme.labelLarge), trailing: StreamBuilder( stream: valueStream, - initialData: Store.tryGet(StoreKey.useWifiForUploadVideos) ?? false, + initialData: Store.tryGet(widget.appSettingsEnum.storeKey) ?? widget.appSettingsEnum.defaultValue, builder: (context, snapshot) { final value = snapshot.data ?? false; return Switch( value: value, onChanged: (bool newValue) async { - await ref - .read(appSettingsServiceProvider) - .setSetting(AppSettingsEnum.useCellularForUploadVideos, newValue); + await ref.read(appSettingsServiceProvider).setSetting(widget.appSettingsEnum, newValue); }, ); }, @@ -183,34 +245,135 @@ class _UseWifiForUploadVideosButton extends ConsumerWidget { } } +class _UseWifiForUploadVideosButton extends ConsumerWidget { + const _UseWifiForUploadVideosButton(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return const _SettingsSwitchTile( + appSettingsEnum: AppSettingsEnum.useCellularForUploadVideos, + titleKey: "videos", + subtitleKey: "network_requirement_videos_upload", + ); + } +} + class _UseWifiForUploadPhotosButton extends ConsumerWidget { const _UseWifiForUploadPhotosButton(); @override Widget build(BuildContext context, WidgetRef ref) { - final valueStream = Store.watch(StoreKey.useWifiForUploadPhotos); - - return ListTile( - title: Text( - "photos".t(context: context), - style: context.textTheme.titleMedium?.copyWith(color: context.primaryColor), - ), - subtitle: Text("network_requirement_photos_upload".t(context: context), style: context.textTheme.labelLarge), - trailing: StreamBuilder( - stream: valueStream, - initialData: Store.tryGet(StoreKey.useWifiForUploadPhotos) ?? false, - builder: (context, snapshot) { - final value = snapshot.data ?? false; - return Switch( - value: value, - onChanged: (bool newValue) async { - await ref - .read(appSettingsServiceProvider) - .setSetting(AppSettingsEnum.useCellularForUploadPhotos, newValue); - }, - ); - }, - ), + return const _SettingsSwitchTile( + appSettingsEnum: AppSettingsEnum.useCellularForUploadPhotos, + titleKey: "photos", + subtitleKey: "network_requirement_photos_upload", + ); + } +} + +class _BackupOnlyWhenChargingButton extends ConsumerWidget { + const _BackupOnlyWhenChargingButton(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return _SettingsSwitchTile( + appSettingsEnum: AppSettingsEnum.backupRequireCharging, + titleKey: "charging", + subtitleKey: "charging_requirement_mobile_backup", + onChanged: (value) { + ref.read(backgroundWorkerFgServiceProvider).configure(requireCharging: value ?? false); + }, + ); + } +} + +class _BackupDelaySlider extends ConsumerStatefulWidget { + const _BackupDelaySlider(); + + @override + ConsumerState<_BackupDelaySlider> createState() => _BackupDelaySliderState(); +} + +class _BackupDelaySliderState extends ConsumerState<_BackupDelaySlider> { + late final Stream valueStream; + late final StreamSubscription subscription; + late int currentValue; + + static int backupDelayToSliderValue(int ms) => switch (ms) { + 5 => 0, + 30 => 1, + 120 => 2, + _ => 3, + }; + + static int backupDelayToSeconds(int v) => switch (v) { + 0 => 5, + 1 => 30, + 2 => 120, + _ => 600, + }; + + static String formatBackupDelaySliderValue(int v) => switch (v) { + 0 => 'setting_notifications_notify_seconds'.tr(namedArgs: {'count': '5'}), + 1 => 'setting_notifications_notify_seconds'.tr(namedArgs: {'count': '30'}), + 2 => 'setting_notifications_notify_minutes'.tr(namedArgs: {'count': '2'}), + _ => 'setting_notifications_notify_minutes'.tr(namedArgs: {'count': '10'}), + }; + + @override + void initState() { + super.initState(); + final initialValue = + Store.tryGet(AppSettingsEnum.backupTriggerDelay.storeKey) ?? AppSettingsEnum.backupTriggerDelay.defaultValue; + currentValue = backupDelayToSliderValue(initialValue); + + valueStream = Store.watch(AppSettingsEnum.backupTriggerDelay.storeKey).asBroadcastStream(); + subscription = valueStream.listen((value) { + if (mounted && value != null) { + setState(() { + currentValue = backupDelayToSliderValue(value); + }); + } + }); + } + + @override + void dispose() { + subscription.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(left: 16.0, top: 8.0), + child: Text( + 'backup_controller_page_background_delay'.tr( + namedArgs: {'duration': formatBackupDelaySliderValue(currentValue)}, + ), + style: context.textTheme.titleMedium?.copyWith(color: context.primaryColor), + ), + ), + Slider( + value: currentValue.toDouble(), + onChanged: (double v) { + setState(() { + currentValue = v.toInt(); + }); + }, + onChangeEnd: (double v) async { + final milliseconds = backupDelayToSeconds(v.toInt()); + await ref.read(appSettingsServiceProvider).setSetting(AppSettingsEnum.backupTriggerDelay, milliseconds); + }, + max: 3.0, + min: 0.0, + divisions: 3, + label: formatBackupDelaySliderValue(currentValue), + ), + ], ); } } diff --git a/mobile/lib/widgets/settings/beta_sync_settings/beta_sync_settings.dart b/mobile/lib/widgets/settings/beta_sync_settings/beta_sync_settings.dart deleted file mode 100644 index e5c65a9c67..0000000000 --- a/mobile/lib/widgets/settings/beta_sync_settings/beta_sync_settings.dart +++ /dev/null @@ -1,376 +0,0 @@ -import 'dart:io'; - -import 'package:drift/drift.dart' as drift_db; -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:immich_mobile/extensions/build_context_extensions.dart'; -import 'package:immich_mobile/extensions/translate_extensions.dart'; -import 'package:immich_mobile/providers/background_sync.provider.dart'; -import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; -import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; -import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; -import 'package:immich_mobile/providers/infrastructure/memory.provider.dart'; -import 'package:immich_mobile/providers/infrastructure/storage.provider.dart'; -import 'package:immich_mobile/providers/sync_status.provider.dart'; -import 'package:immich_mobile/widgets/settings/beta_sync_settings/entity_count_tile.dart'; -import 'package:path/path.dart' as path; -import 'package:path_provider/path_provider.dart'; -import 'package:share_plus/share_plus.dart'; - -class BetaSyncSettings extends HookConsumerWidget { - const BetaSyncSettings({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final assetService = ref.watch(assetServiceProvider); - final localAlbumService = ref.watch(localAlbumServiceProvider); - final remoteAlbumService = ref.watch(remoteAlbumServiceProvider); - final memoryService = ref.watch(driftMemoryServiceProvider); - - Future> loadCounts() async { - final assetCounts = assetService.getAssetCounts(); - final localAlbumCounts = localAlbumService.getCount(); - final remoteAlbumCounts = remoteAlbumService.getCount(); - final memoryCount = memoryService.getCount(); - final getLocalHashedCount = assetService.getLocalHashedCount(); - - return await Future.wait([assetCounts, localAlbumCounts, remoteAlbumCounts, memoryCount, getLocalHashedCount]); - } - - Future resetDatabase() async { - // https://github.com/simolus3/drift/commit/bd80a46264b6dd833ef4fd87fffc03f5a832ab41#diff-3f879e03b4a35779344ef16170b9353608dd9c42385f5402ec6035aac4dd8a04R76-R94 - final drift = ref.read(driftProvider); - final database = drift.attachedDatabase; - await database.exclusively(() async { - // https://stackoverflow.com/a/65743498/25690041 - await database.customStatement('PRAGMA writable_schema = 1;'); - await database.customStatement('DELETE FROM sqlite_master;'); - await database.customStatement('VACUUM;'); - await database.customStatement('PRAGMA writable_schema = 0;'); - await database.customStatement('PRAGMA integrity_check'); - - await database.customStatement('PRAGMA user_version = 0'); - await database.beforeOpen( - // ignore: invalid_use_of_internal_member - database.resolvedEngine.executor, - drift_db.OpeningDetails(null, database.schemaVersion), - ); - await database.customStatement('PRAGMA user_version = ${database.schemaVersion}'); - - // Refresh all stream queries - database.notifyUpdates({for (final table in database.allTables) drift_db.TableUpdate.onTable(table)}); - }); - } - - Future exportDatabase() async { - try { - // WAL Checkpoint to ensure all changes are written to the database - await ref.read(driftProvider).customStatement("pragma wal_checkpoint(truncate)"); - final documentsDir = await getApplicationDocumentsDirectory(); - final dbFile = File(path.join(documentsDir.path, 'immich.sqlite')); - - if (!await dbFile.exists()) { - if (context.mounted) { - context.scaffoldMessenger.showSnackBar( - SnackBar(content: Text("Database file not found".t(context: context))), - ); - } - return; - } - - final timestamp = DateTime.now().millisecondsSinceEpoch; - final exportFile = File(path.join(documentsDir.path, 'immich_export_$timestamp.sqlite')); - - await dbFile.copy(exportFile.path); - - await Share.shareXFiles([XFile(exportFile.path)], text: 'Immich Database Export'); - - Future.delayed(const Duration(seconds: 30), () async { - if (await exportFile.exists()) { - await exportFile.delete(); - } - }); - - if (context.mounted) { - context.scaffoldMessenger.showSnackBar( - SnackBar(content: Text("Database exported successfully".t(context: context))), - ); - } - } catch (e) { - if (context.mounted) { - context.scaffoldMessenger.showSnackBar( - SnackBar(content: Text("Failed to export database: $e".t(context: context))), - ); - } - } - } - - Future clearFileCache() async { - await ref.read(storageRepositoryProvider).clearCache(); - } - - Future resetSqliteDb(BuildContext context, Future Function() resetDatabase) { - return showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: Text("reset_sqlite".t(context: context)), - content: Text("reset_sqlite_confirmation".t(context: context)), - actions: [ - TextButton( - onPressed: () => context.pop(), - child: Text("cancel".t(context: context)), - ), - TextButton( - onPressed: () async { - await resetDatabase(); - context.pop(); - context.scaffoldMessenger.showSnackBar( - SnackBar(content: Text("reset_sqlite_success".t(context: context))), - ); - }, - child: Text( - "confirm".t(context: context), - style: TextStyle(color: context.colorScheme.error), - ), - ), - ], - ); - }, - ); - } - - return FutureBuilder>( - future: loadCounts(), - builder: (context, snapshot) { - if (snapshot.connectionState != ConnectionState.done) { - return const CircularProgressIndicator(); - } - - if (snapshot.hasError) { - return ListView( - children: [ - Padding( - padding: const EdgeInsets.all(16.0), - child: Center( - child: Text( - "Error occur, reset the local database by tapping the button below", - style: context.textTheme.bodyLarge, - ), - ), - ), - - ListTile( - title: Text( - "reset_sqlite".t(context: context), - style: TextStyle(color: context.colorScheme.error, fontWeight: FontWeight.w500), - ), - leading: Icon(Icons.settings_backup_restore_rounded, color: context.colorScheme.error), - onTap: () async { - await resetSqliteDb(context, resetDatabase); - }, - ), - ], - ); - } - - final assetCounts = snapshot.data![0]! as (int, int); - final localAssetCount = assetCounts.$1; - final remoteAssetCount = assetCounts.$2; - - final localAlbumCount = snapshot.data![1]! as int; - final remoteAlbumCount = snapshot.data![2]! as int; - final memoryCount = snapshot.data![3]! as int; - final localHashedCount = snapshot.data![4]! as int; - - return Padding( - padding: const EdgeInsets.only(top: 16, bottom: 32), - child: ListView( - children: [ - _SectionHeaderText(text: "assets".t(context: context)), - Padding( - padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), - child: Flex( - direction: Axis.horizontal, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - spacing: 8.0, - children: [ - Expanded( - child: EntitiyCountTile( - label: "local".t(context: context), - count: localAssetCount, - icon: Icons.smartphone, - ), - ), - Expanded( - child: EntitiyCountTile( - label: "remote".t(context: context), - count: remoteAssetCount, - icon: Icons.cloud, - ), - ), - ], - ), - ), - _SectionHeaderText(text: "albums".t(context: context)), - Padding( - padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), - child: Flex( - direction: Axis.horizontal, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - spacing: 8.0, - children: [ - Expanded( - child: EntitiyCountTile( - label: "local".t(context: context), - count: localAlbumCount, - icon: Icons.smartphone, - ), - ), - Expanded( - child: EntitiyCountTile( - label: "remote".t(context: context), - count: remoteAlbumCount, - icon: Icons.cloud, - ), - ), - ], - ), - ), - _SectionHeaderText(text: "other".t(context: context)), - Padding( - padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), - child: Flex( - direction: Axis.horizontal, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - spacing: 8.0, - children: [ - Expanded( - child: EntitiyCountTile( - label: "memories".t(context: context), - count: memoryCount, - icon: Icons.calendar_today, - ), - ), - Expanded( - child: EntitiyCountTile( - label: "hashed_assets".t(context: context), - count: localHashedCount, - icon: Icons.tag, - ), - ), - ], - ), - ), - const Divider(height: 1, indent: 16, endIndent: 16), - const SizedBox(height: 24), - _SectionHeaderText(text: "jobs".t(context: context)), - ListTile( - title: Text( - "sync_local".t(context: context), - style: const TextStyle(fontWeight: FontWeight.w500), - ), - subtitle: Text("tap_to_run_job".t(context: context)), - leading: const Icon(Icons.sync), - trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).localSyncStatus), - onTap: () { - ref.read(backgroundSyncProvider).syncLocal(full: true); - }, - ), - ListTile( - title: Text( - "sync_remote".t(context: context), - style: const TextStyle(fontWeight: FontWeight.w500), - ), - subtitle: Text("tap_to_run_job".t(context: context)), - leading: const Icon(Icons.cloud_sync), - trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).remoteSyncStatus), - onTap: () { - ref.read(backgroundSyncProvider).syncRemote(); - }, - ), - ListTile( - title: Text( - "hash_asset".t(context: context), - style: const TextStyle(fontWeight: FontWeight.w500), - ), - leading: const Icon(Icons.tag), - subtitle: Text("tap_to_run_job".t(context: context)), - trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).hashJobStatus), - onTap: () { - ref.read(backgroundSyncProvider).hashAssets(); - }, - ), - const Divider(height: 1, indent: 16, endIndent: 16), - const SizedBox(height: 24), - _SectionHeaderText(text: "actions".t(context: context)), - ListTile( - title: Text( - "clear_file_cache".t(context: context), - style: const TextStyle(fontWeight: FontWeight.w500), - ), - leading: const Icon(Icons.playlist_remove_rounded), - onTap: clearFileCache, - ), - ListTile( - title: Text( - "export_database".t(context: context), - style: const TextStyle(fontWeight: FontWeight.w500), - ), - subtitle: Text("export_database_description".t(context: context)), - leading: const Icon(Icons.download), - onTap: exportDatabase, - ), - ListTile( - title: Text( - "reset_sqlite".t(context: context), - style: TextStyle(color: context.colorScheme.error, fontWeight: FontWeight.w500), - ), - leading: Icon(Icons.settings_backup_restore_rounded, color: context.colorScheme.error), - onTap: () async { - await resetSqliteDb(context, resetDatabase); - }, - ), - ], - ), - ); - }, - ); - } -} - -class _SyncStatusIcon extends StatelessWidget { - final SyncStatus status; - - const _SyncStatusIcon({required this.status}); - - @override - Widget build(BuildContext context) { - return switch (status) { - SyncStatus.idle => const Icon(Icons.pause_circle_outline_rounded), - SyncStatus.syncing => const SizedBox(height: 24, width: 24, child: CircularProgressIndicator(strokeWidth: 2)), - SyncStatus.success => const Icon(Icons.check_circle_outline, color: Colors.green), - SyncStatus.error => Icon(Icons.error_outline, color: context.colorScheme.error), - }; - } -} - -class _SectionHeaderText extends StatelessWidget { - final String text; - - const _SectionHeaderText({required this.text}); - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(left: 16.0), - child: Text( - text.toUpperCase(), - style: context.textTheme.labelLarge?.copyWith( - fontWeight: FontWeight.w500, - color: context.colorScheme.onSurface.withAlpha(200), - ), - ), - ); - } -} diff --git a/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart b/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart new file mode 100644 index 0000000000..a5bca24f81 --- /dev/null +++ b/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart @@ -0,0 +1,359 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_mobile/extensions/translate_extensions.dart'; +import 'package:immich_mobile/providers/background_sync.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/memory.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/storage.provider.dart'; +import 'package:immich_mobile/providers/sync_status.provider.dart'; +import 'package:immich_mobile/widgets/settings/beta_sync_settings/entity_count_tile.dart'; +import 'package:path/path.dart' as path; +import 'package:path_provider/path_provider.dart'; +import 'package:share_plus/share_plus.dart'; + +class SyncStatusAndActions extends HookConsumerWidget { + const SyncStatusAndActions({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + Future exportDatabase() async { + try { + // WAL Checkpoint to ensure all changes are written to the database + await ref.read(driftProvider).customStatement("pragma wal_checkpoint(truncate)"); + final documentsDir = await getApplicationDocumentsDirectory(); + final dbFile = File(path.join(documentsDir.path, 'immich.sqlite')); + + if (!await dbFile.exists()) { + if (context.mounted) { + context.scaffoldMessenger.showSnackBar( + SnackBar(content: Text("Database file not found".t(context: context))), + ); + } + return; + } + + final timestamp = DateTime.now().millisecondsSinceEpoch; + final exportFile = File(path.join(documentsDir.path, 'immich_export_$timestamp.sqlite')); + + await dbFile.copy(exportFile.path); + + final size = MediaQuery.of(context).size; + await Share.shareXFiles( + [XFile(exportFile.path)], + text: 'Immich Database Export', + sharePositionOrigin: Rect.fromPoints(Offset.zero, Offset(size.width / 3, size.height)), + ); + + Future.delayed(const Duration(seconds: 30), () async { + if (await exportFile.exists()) { + await exportFile.delete(); + } + }); + + if (context.mounted) { + context.scaffoldMessenger.showSnackBar( + SnackBar(content: Text("Database exported successfully".t(context: context))), + ); + } + } catch (e) { + if (context.mounted) { + context.scaffoldMessenger.showSnackBar( + SnackBar(content: Text("Failed to export database: $e".t(context: context))), + ); + } + } + } + + Future clearFileCache() async { + await ref.read(storageRepositoryProvider).clearCache(); + } + + Future resetSqliteDb(BuildContext context) { + return showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: Text("reset_sqlite".t(context: context)), + content: Text("reset_sqlite_confirmation".t(context: context)), + actions: [ + TextButton( + onPressed: () => context.pop(), + child: Text("cancel".t(context: context)), + ), + TextButton( + onPressed: () async { + await ref.read(driftProvider).reset(); + context.pop(); + context.scaffoldMessenger.showSnackBar( + SnackBar(content: Text("reset_sqlite_success".t(context: context))), + ); + }, + child: Text( + "confirm".t(context: context), + style: TextStyle(color: context.colorScheme.error), + ), + ), + ], + ); + }, + ); + } + + return Padding( + padding: const EdgeInsets.only(top: 16, bottom: 32), + child: ListView( + children: [ + const _SyncStatsCounts(), + const Divider(height: 1, indent: 16, endIndent: 16), + const SizedBox(height: 24), + _SectionHeaderText(text: "jobs".t(context: context)), + ListTile( + title: Text( + "sync_local".t(context: context), + style: const TextStyle(fontWeight: FontWeight.w500), + ), + subtitle: Text("tap_to_run_job".t(context: context)), + leading: const Icon(Icons.sync), + trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).localSyncStatus), + onTap: () { + ref.read(backgroundSyncProvider).syncLocal(full: true); + }, + ), + ListTile( + title: Text( + "sync_remote".t(context: context), + style: const TextStyle(fontWeight: FontWeight.w500), + ), + subtitle: Text("tap_to_run_job".t(context: context)), + leading: const Icon(Icons.cloud_sync), + trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).remoteSyncStatus), + onTap: () { + ref.read(backgroundSyncProvider).syncRemote(); + }, + ), + ListTile( + title: Text( + "hash_asset".t(context: context), + style: const TextStyle(fontWeight: FontWeight.w500), + ), + leading: const Icon(Icons.tag), + subtitle: Text("tap_to_run_job".t(context: context)), + trailing: _SyncStatusIcon(status: ref.watch(syncStatusProvider).hashJobStatus), + onTap: () { + ref.read(backgroundSyncProvider).hashAssets(); + }, + ), + const Divider(height: 1, indent: 16, endIndent: 16), + const SizedBox(height: 24), + _SectionHeaderText(text: "actions".t(context: context)), + ListTile( + title: Text( + "clear_file_cache".t(context: context), + style: const TextStyle(fontWeight: FontWeight.w500), + ), + leading: const Icon(Icons.playlist_remove_rounded), + onTap: clearFileCache, + ), + ListTile( + title: Text( + "export_database".t(context: context), + style: const TextStyle(fontWeight: FontWeight.w500), + ), + subtitle: Text("export_database_description".t(context: context)), + leading: const Icon(Icons.download), + onTap: exportDatabase, + ), + ListTile( + title: Text( + "reset_sqlite".t(context: context), + style: TextStyle(color: context.colorScheme.error, fontWeight: FontWeight.w500), + ), + leading: Icon(Icons.settings_backup_restore_rounded, color: context.colorScheme.error), + onTap: () async { + await resetSqliteDb(context); + }, + ), + ], + ), + ); + } +} + +class _SyncStatusIcon extends StatelessWidget { + final SyncStatus status; + + const _SyncStatusIcon({required this.status}); + + @override + Widget build(BuildContext context) { + return switch (status) { + SyncStatus.idle => const Icon(Icons.pause_circle_outline_rounded), + SyncStatus.syncing => const SizedBox(height: 24, width: 24, child: CircularProgressIndicator(strokeWidth: 2)), + SyncStatus.success => const Icon(Icons.check_circle_outline, color: Colors.green), + SyncStatus.error => Icon(Icons.error_outline, color: context.colorScheme.error), + }; + } +} + +class _SectionHeaderText extends StatelessWidget { + final String text; + + const _SectionHeaderText({required this.text}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(left: 16.0), + child: Text( + text.toUpperCase(), + style: context.textTheme.labelLarge?.copyWith( + fontWeight: FontWeight.w500, + color: context.colorScheme.onSurface.withAlpha(200), + ), + ), + ); + } +} + +class _SyncStatsCounts extends ConsumerWidget { + const _SyncStatsCounts(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final assetService = ref.watch(assetServiceProvider); + final localAlbumService = ref.watch(localAlbumServiceProvider); + final remoteAlbumService = ref.watch(remoteAlbumServiceProvider); + final memoryService = ref.watch(driftMemoryServiceProvider); + + Future> loadCounts() async { + final assetCounts = assetService.getAssetCounts(); + final localAlbumCounts = localAlbumService.getCount(); + final remoteAlbumCounts = remoteAlbumService.getCount(); + final memoryCount = memoryService.getCount(); + final getLocalHashedCount = assetService.getLocalHashedCount(); + + return await Future.wait([assetCounts, localAlbumCounts, remoteAlbumCounts, memoryCount, getLocalHashedCount]); + } + + return FutureBuilder( + future: loadCounts(), + builder: (context, snapshot) { + if (snapshot.connectionState != ConnectionState.done) { + return const Center(child: SizedBox(height: 48, width: 48, child: CircularProgressIndicator())); + } + + if (snapshot.hasError) { + return ListView( + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: Center( + child: Text( + "Error occur, reset the local database by tapping the button below", + style: context.textTheme.bodyLarge, + ), + ), + ), + ], + ); + } + + final assetCounts = snapshot.data![0]! as (int, int); + final localAssetCount = assetCounts.$1; + final remoteAssetCount = assetCounts.$2; + + final localAlbumCount = snapshot.data![1]! as int; + final remoteAlbumCount = snapshot.data![2]! as int; + final memoryCount = snapshot.data![3]! as int; + final localHashedCount = snapshot.data![4]! as int; + + return Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _SectionHeaderText(text: "assets".t(context: context)), + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), + child: Flex( + direction: Axis.horizontal, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + spacing: 8.0, + children: [ + Expanded( + child: EntitiyCountTile( + label: "local".t(context: context), + count: localAssetCount, + icon: Icons.smartphone, + ), + ), + Expanded( + child: EntitiyCountTile( + label: "remote".t(context: context), + count: remoteAssetCount, + icon: Icons.cloud, + ), + ), + ], + ), + ), + _SectionHeaderText(text: "albums".t(context: context)), + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), + child: Flex( + direction: Axis.horizontal, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + spacing: 8.0, + children: [ + Expanded( + child: EntitiyCountTile( + label: "local".t(context: context), + count: localAlbumCount, + icon: Icons.smartphone, + ), + ), + Expanded( + child: EntitiyCountTile( + label: "remote".t(context: context), + count: remoteAlbumCount, + icon: Icons.cloud, + ), + ), + ], + ), + ), + _SectionHeaderText(text: "other".t(context: context)), + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), + child: Flex( + direction: Axis.horizontal, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + spacing: 8.0, + children: [ + Expanded( + child: EntitiyCountTile( + label: "memories".t(context: context), + count: memoryCount, + icon: Icons.calendar_today, + ), + ), + Expanded( + child: EntitiyCountTile( + label: "hashed_assets".t(context: context), + count: localHashedCount, + icon: Icons.tag, + ), + ), + ], + ), + ), + ], + ); + }, + ); + } +} diff --git a/mobile/lib/widgets/settings/beta_timeline_list_tile.dart b/mobile/lib/widgets/settings/beta_timeline_list_tile.dart index a498145275..1fefb3dcfa 100644 --- a/mobile/lib/widgets/settings/beta_timeline_list_tile.dart +++ b/mobile/lib/widgets/settings/beta_timeline_list_tile.dart @@ -1,231 +1,68 @@ -import 'dart:math' as math; - import 'package:auto_route/auto_route.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/providers/app_settings.provider.dart'; import 'package:immich_mobile/providers/auth.provider.dart'; -import 'package:immich_mobile/providers/server_info.provider.dart'; import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/services/app_settings.service.dart'; -class BetaTimelineListTile extends ConsumerStatefulWidget { +class BetaTimelineListTile extends ConsumerWidget { const BetaTimelineListTile({super.key}); @override - ConsumerState createState() => _BetaTimelineListTileState(); -} - -class _BetaTimelineListTileState extends ConsumerState with SingleTickerProviderStateMixin { - late AnimationController _animationController; - late Animation _rotationAnimation; - late Animation _pulseAnimation; - late Animation _gradientAnimation; - - @override - void initState() { - super.initState(); - _animationController = AnimationController(duration: const Duration(seconds: 3), vsync: this); - - _rotationAnimation = Tween( - begin: 0, - end: 2 * math.pi, - ).animate(CurvedAnimation(parent: _animationController, curve: Curves.linear)); - - _pulseAnimation = Tween( - begin: 1, - end: 1.1, - ).animate(CurvedAnimation(parent: _animationController, curve: Curves.easeInOut)); - - _gradientAnimation = Tween( - begin: 0, - end: 1, - ).animate(CurvedAnimation(parent: _animationController, curve: Curves.easeInOut)); - - _animationController.repeat(reverse: true); - } - - @override - void dispose() { - _animationController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { final betaTimelineValue = ref.watch(appSettingsServiceProvider).getSetting(AppSettingsEnum.betaTimeline); - final serverInfo = ref.watch(serverInfoProvider); final auth = ref.watch(authProvider); - if (!auth.isAuthenticated || (serverInfo.serverVersion.minor < 136 && kReleaseMode)) { + if (!auth.isAuthenticated) { return const SizedBox.shrink(); } - return AnimatedBuilder( - animation: _animationController, - builder: (context, child) { - void onSwitchChanged(bool value) { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: value ? const Text("Enable Beta Timeline") : const Text("Disable Beta Timeline"), - content: value - ? const Text("Are you sure you want to enable the beta timeline?") - : const Text("Are you sure you want to disable the beta timeline?"), - actions: [ - TextButton( - onPressed: () { - context.pop(); - }, - child: Text( - "cancel".t(context: context), - style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500, color: context.colorScheme.outline), - ), - ), - ElevatedButton( - onPressed: () async { - Navigator.of(context).pop(); - context.router.replaceAll([ChangeExperienceRoute(switchingToBeta: value)]); - }, - child: Text("ok".t(context: context)), - ), - ], - ); - }, - ); - } - - final gradientColors = [ - Color.lerp( - context.primaryColor.withValues(alpha: 0.5), - context.primaryColor.withValues(alpha: 0.3), - _gradientAnimation.value, - )!, - Color.lerp( - context.logoPink.withValues(alpha: 0.2), - context.logoPink.withValues(alpha: 0.4), - _gradientAnimation.value, - )!, - Color.lerp( - context.logoRed.withValues(alpha: 0.3), - context.logoRed.withValues(alpha: 0.5), - _gradientAnimation.value, - )!, - ]; - - return Container( - margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), - decoration: BoxDecoration( - borderRadius: const BorderRadius.all(Radius.circular(12)), - gradient: LinearGradient( - colors: gradientColors, - stops: const [0.0, 0.5, 1.0], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - transform: GradientRotation(_rotationAnimation.value * 0.5), - ), - boxShadow: [ - BoxShadow(color: context.primaryColor.withValues(alpha: 0.1), blurRadius: 8, offset: const Offset(0, 2)), - ], - ), - child: Container( - margin: const EdgeInsets.all(2), - decoration: BoxDecoration( - borderRadius: const BorderRadius.all(Radius.circular(10.5)), - color: context.scaffoldBackgroundColor, - ), - child: Material( - borderRadius: const BorderRadius.all(Radius.circular(10.5)), - child: InkWell( - borderRadius: const BorderRadius.all(Radius.circular(10.5)), - onTap: () => onSwitchChanged(!betaTimelineValue), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), - child: Row( - children: [ - Transform.scale( - scale: _pulseAnimation.value, - child: Transform.rotate( - angle: _rotationAnimation.value * 0.02, - child: Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - shape: BoxShape.circle, - gradient: LinearGradient( - colors: [ - context.primaryColor.withValues(alpha: 0.2), - context.primaryColor.withValues(alpha: 0.1), - ], - ), - ), - child: Icon(Icons.auto_awesome, color: context.primaryColor, size: 20), - ), - ), - ), - const SizedBox(width: 28), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text( - "advanced_settings_beta_timeline_title".t(context: context), - style: context.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w600), - ), - const SizedBox(width: 8), - Container( - padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), - decoration: BoxDecoration( - borderRadius: const BorderRadius.all(Radius.circular(8)), - gradient: LinearGradient( - colors: [ - context.primaryColor.withValues(alpha: 0.8), - context.primaryColor.withValues(alpha: 0.6), - ], - ), - ), - child: Text( - 'NEW', - style: context.textTheme.labelSmall?.copyWith( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 10, - height: 1.2, - ), - ), - ), - ], - ), - const SizedBox(height: 4), - Text( - "advanced_settings_beta_timeline_subtitle".t(context: context), - style: context.textTheme.labelLarge?.copyWith( - color: context.textTheme.labelLarge?.color?.withValues(alpha: 0.9), - ), - maxLines: 2, - ), - ], - ), - ), - Switch.adaptive( - value: betaTimelineValue, - onChanged: onSwitchChanged, - activeColor: context.primaryColor, - ), - ], - ), + void onSwitchChanged(bool value) { + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: value ? const Text("Enable New Timeline") : const Text("Disable New Timeline"), + content: value + ? const Text("Are you sure you want to enable the new timeline?") + : const Text("Are you sure you want to disable the new timeline?"), + actions: [ + TextButton( + onPressed: () { + context.pop(); + }, + child: Text( + "cancel".t(context: context), + style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500, color: context.colorScheme.outline), ), ), - ), - ), - ); - }, + ElevatedButton( + onPressed: () async { + Navigator.of(context).pop(); + context.router.replaceAll([ChangeExperienceRoute(switchingToBeta: value)]); + }, + child: Text("ok".t(context: context)), + ), + ], + ); + }, + ); + } + + return Padding( + padding: const EdgeInsets.only(left: 4.0), + child: ListTile( + title: Text("new_timeline".t(context: context)), + trailing: Switch.adaptive( + value: betaTimelineValue, + onChanged: onSwitchChanged, + activeThumbColor: context.primaryColor, + ), + onTap: () => onSwitchChanged(!betaTimelineValue), + ), ); } } diff --git a/mobile/lib/widgets/settings/preference_settings/primary_color_setting.dart b/mobile/lib/widgets/settings/preference_settings/primary_color_setting.dart index ddf2cc6215..22c9154981 100644 --- a/mobile/lib/widgets/settings/preference_settings/primary_color_setting.dart +++ b/mobile/lib/widgets/settings/preference_settings/primary_color_setting.dart @@ -115,7 +115,7 @@ class PrimaryColorSetting extends HookConsumerWidget { child: SwitchListTile.adaptive( contentPadding: const EdgeInsets.symmetric(vertical: 6, horizontal: 20), dense: true, - activeColor: context.primaryColor, + activeThumbColor: context.primaryColor, tileColor: context.colorScheme.surfaceContainerHigh, shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(15))), title: Text( diff --git a/mobile/lib/widgets/settings/settings_radio_list_tile.dart b/mobile/lib/widgets/settings/settings_radio_list_tile.dart index 95224e3f59..6b02a65159 100644 --- a/mobile/lib/widgets/settings/settings_radio_list_tile.dart +++ b/mobile/lib/widgets/settings/settings_radio_list_tile.dart @@ -9,7 +9,7 @@ class SettingsRadioGroup { } class SettingsRadioListTile extends StatelessWidget { - final List groups; + final List> groups; final T groupBy; final void Function(T?) onRadioChanged; @@ -17,21 +17,23 @@ class SettingsRadioListTile extends StatelessWidget { @override Widget build(BuildContext context) { - return Column( - children: groups - .map( - (g) => RadioListTile( - contentPadding: const EdgeInsets.symmetric(horizontal: 20), - dense: true, - activeColor: context.primaryColor, - title: Text(g.title, style: context.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.w500)), - value: g.value, - groupValue: groupBy, - onChanged: onRadioChanged, - controlAffinity: ListTileControlAffinity.trailing, - ), - ) - .toList(), + return RadioGroup( + groupValue: groupBy, + onChanged: onRadioChanged, + child: Column( + children: groups + .map( + (g) => RadioListTile( + contentPadding: const EdgeInsets.symmetric(horizontal: 20), + dense: true, + activeColor: context.primaryColor, + title: Text(g.title, style: context.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.w500)), + value: g.value, + controlAffinity: ListTileControlAffinity.trailing, + ), + ) + .toList(), + ), ); } } diff --git a/mobile/lib/widgets/settings/settings_switch_list_tile.dart b/mobile/lib/widgets/settings/settings_switch_list_tile.dart index d51e2eb2ca..f5d6dfd05a 100644 --- a/mobile/lib/widgets/settings/settings_switch_list_tile.dart +++ b/mobile/lib/widgets/settings/settings_switch_list_tile.dart @@ -40,7 +40,7 @@ class SettingsSwitchListTile extends StatelessWidget { selectedTileColor: enabled ? null : context.themeData.disabledColor, value: valueNotifier.value, onChanged: onSwitchChanged, - activeColor: enabled ? context.primaryColor : context.themeData.disabledColor, + activeThumbColor: enabled ? context.primaryColor : context.themeData.disabledColor, dense: true, secondary: icon != null ? Icon(icon!, color: valueNotifier.value ? context.primaryColor : null) : null, title: Text( diff --git a/mobile/lib/widgets/shared_link/shared_link_item.dart b/mobile/lib/widgets/shared_link/shared_link_item.dart index 0eced33ce3..cbd6e1f077 100644 --- a/mobile/lib/widgets/shared_link/shared_link_item.dart +++ b/mobile/lib/widgets/shared_link/shared_link_item.dart @@ -16,6 +16,7 @@ import 'package:immich_mobile/utils/url_helper.dart'; import 'package:immich_mobile/widgets/common/confirm_dialog.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart'; import 'package:immich_mobile/widgets/search/thumbnail_with_info.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; class SharedLinkItem extends ConsumerWidget { final SharedLink sharedLink; @@ -36,7 +37,7 @@ class SharedLinkItem extends ConsumerWidget { return Text("expired", style: TextStyle(color: Colors.red[300])).tr(); } final difference = sharedLink.expiresAt!.difference(DateTime.now()); - debugPrint("Difference: $difference"); + dPrint(() => "Difference: $difference"); if (difference.inDays > 0) { var dayDifference = difference.inDays; if (difference.inHours % 24 > 12) { diff --git a/mobile/makefile b/mobile/makefile index 1a20e769ef..b90e95c902 100644 --- a/mobile/makefile +++ b/mobile/makefile @@ -9,9 +9,13 @@ pigeon: dart run pigeon --input pigeon/native_sync_api.dart dart run pigeon --input pigeon/thumbnail_api.dart dart run pigeon --input pigeon/background_worker_api.dart + dart run pigeon --input pigeon/background_worker_lock_api.dart + dart run pigeon --input pigeon/connectivity_api.dart dart format lib/platform/native_sync_api.g.dart dart format lib/platform/thumbnail_api.g.dart dart format lib/platform/background_worker_api.g.dart + dart format lib/platform/background_worker_lock_api.g.dart + dart format lib/platform/connectivity_api.g.dart watch: dart run build_runner watch --delete-conflicting-outputs diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md index 6cd26aefc4..698b9774da 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.141.1 +- API version: 2.1.0 - Generator version: 7.8.0 - Build package: org.openapitools.codegen.languages.DartClientCodegen @@ -107,7 +107,7 @@ Class | Method | HTTP request | Description *AssetsApi* | [**getAssetStatistics**](doc//AssetsApi.md#getassetstatistics) | **GET** /assets/statistics | *AssetsApi* | [**getRandom**](doc//AssetsApi.md#getrandom) | **GET** /assets/random | *AssetsApi* | [**playAssetVideo**](doc//AssetsApi.md#playassetvideo) | **GET** /assets/{id}/video/playback | -*AssetsApi* | [**replaceAsset**](doc//AssetsApi.md#replaceasset) | **PUT** /assets/{id}/original | replaceAsset +*AssetsApi* | [**replaceAsset**](doc//AssetsApi.md#replaceasset) | **PUT** /assets/{id}/original | Replace the asset with new file, without changing its id *AssetsApi* | [**runAssetJobs**](doc//AssetsApi.md#runassetjobs) | **POST** /assets/jobs | *AssetsApi* | [**updateAsset**](doc//AssetsApi.md#updateasset) | **PUT** /assets/{id} | *AssetsApi* | [**updateAssetMetadata**](doc//AssetsApi.md#updateassetmetadata) | **PUT** /assets/{id}/metadata | @@ -128,6 +128,7 @@ Class | Method | HTTP request | Description *AuthenticationApi* | [**validateAccessToken**](doc//AuthenticationApi.md#validateaccesstoken) | **POST** /auth/validateToken | *DeprecatedApi* | [**createPartnerDeprecated**](doc//DeprecatedApi.md#createpartnerdeprecated) | **POST** /partners/{id} | *DeprecatedApi* | [**getRandom**](doc//DeprecatedApi.md#getrandom) | **GET** /assets/random | +*DeprecatedApi* | [**replaceAsset**](doc//DeprecatedApi.md#replaceasset) | **PUT** /assets/{id}/original | Replace the asset with new file, without changing its id *DownloadApi* | [**downloadArchive**](doc//DownloadApi.md#downloadarchive) | **POST** /download/archive | *DownloadApi* | [**getDownloadInfo**](doc//DownloadApi.md#getdownloadinfo) | **POST** /download/info | *DuplicatesApi* | [**deleteDuplicate**](doc//DuplicatesApi.md#deleteduplicate) | **DELETE** /duplicates/{id} | @@ -358,6 +359,7 @@ Class | Method | HTTP request | Description - [CheckExistingAssetsDto](doc//CheckExistingAssetsDto.md) - [CheckExistingAssetsResponseDto](doc//CheckExistingAssetsResponseDto.md) - [Colorspace](doc//Colorspace.md) + - [ContributorCountResponseDto](doc//ContributorCountResponseDto.md) - [CreateAlbumDto](doc//CreateAlbumDto.md) - [CreateLibraryDto](doc//CreateLibraryDto.md) - [CreateProfileImageResponseDto](doc//CreateProfileImageResponseDto.md) @@ -392,6 +394,7 @@ Class | Method | HTTP request | Description - [LoginCredentialDto](doc//LoginCredentialDto.md) - [LoginResponseDto](doc//LoginResponseDto.md) - [LogoutResponseDto](doc//LogoutResponseDto.md) + - [MachineLearningAvailabilityChecksDto](doc//MachineLearningAvailabilityChecksDto.md) - [ManualJobName](doc//ManualJobName.md) - [MapMarkerResponseDto](doc//MapMarkerResponseDto.md) - [MapReverseGeocodeResponseDto](doc//MapReverseGeocodeResponseDto.md) diff --git a/mobile/openapi/lib/api.dart b/mobile/openapi/lib/api.dart index e87c160d96..a3117ede86 100644 --- a/mobile/openapi/lib/api.dart +++ b/mobile/openapi/lib/api.dart @@ -130,6 +130,7 @@ part 'model/change_password_dto.dart'; part 'model/check_existing_assets_dto.dart'; part 'model/check_existing_assets_response_dto.dart'; part 'model/colorspace.dart'; +part 'model/contributor_count_response_dto.dart'; part 'model/create_album_dto.dart'; part 'model/create_library_dto.dart'; part 'model/create_profile_image_response_dto.dart'; @@ -164,6 +165,7 @@ part 'model/log_level.dart'; part 'model/login_credential_dto.dart'; part 'model/login_response_dto.dart'; part 'model/logout_response_dto.dart'; +part 'model/machine_learning_availability_checks_dto.dart'; part 'model/manual_job_name.dart'; part 'model/map_marker_response_dto.dart'; part 'model/map_reverse_geocode_response_dto.dart'; diff --git a/mobile/openapi/lib/api/assets_api.dart b/mobile/openapi/lib/api/assets_api.dart index e16ac2f535..063f9ea43b 100644 --- a/mobile/openapi/lib/api/assets_api.dart +++ b/mobile/openapi/lib/api/assets_api.dart @@ -729,9 +729,9 @@ class AssetsApi { return null; } - /// replaceAsset + /// Replace the asset with new file, without changing its id /// - /// Replace the asset with new file, without changing its id. This endpoint requires the `asset.replace` permission. + /// This property was deprecated in v1.142.0. Replace the asset with new file, without changing its id. This endpoint requires the `asset.replace` permission. /// /// Note: This method returns the HTTP [Response]. /// @@ -823,9 +823,9 @@ class AssetsApi { ); } - /// replaceAsset + /// Replace the asset with new file, without changing its id /// - /// Replace the asset with new file, without changing its id. This endpoint requires the `asset.replace` permission. + /// This property was deprecated in v1.142.0. Replace the asset with new file, without changing its id. This endpoint requires the `asset.replace` permission. /// /// Parameters: /// diff --git a/mobile/openapi/lib/api/deprecated_api.dart b/mobile/openapi/lib/api/deprecated_api.dart index cdcd27750d..9246998ca2 100644 --- a/mobile/openapi/lib/api/deprecated_api.dart +++ b/mobile/openapi/lib/api/deprecated_api.dart @@ -127,4 +127,138 @@ class DeprecatedApi { } return null; } + + /// Replace the asset with new file, without changing its id + /// + /// This property was deprecated in v1.142.0. Replace the asset with new file, without changing its id. This endpoint requires the `asset.replace` permission. + /// + /// Note: This method returns the HTTP [Response]. + /// + /// Parameters: + /// + /// * [String] id (required): + /// + /// * [MultipartFile] assetData (required): + /// + /// * [String] deviceAssetId (required): + /// + /// * [String] deviceId (required): + /// + /// * [DateTime] fileCreatedAt (required): + /// + /// * [DateTime] fileModifiedAt (required): + /// + /// * [String] key: + /// + /// * [String] slug: + /// + /// * [String] duration: + /// + /// * [String] filename: + Future replaceAssetWithHttpInfo(String id, MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? slug, String? duration, String? filename, }) async { + // ignore: prefer_const_declarations + final apiPath = r'/assets/{id}/original' + .replaceAll('{id}', id); + + // ignore: prefer_final_locals + Object? postBody; + + final queryParams = []; + final headerParams = {}; + final formParams = {}; + + if (key != null) { + queryParams.addAll(_queryParams('', 'key', key)); + } + if (slug != null) { + queryParams.addAll(_queryParams('', 'slug', slug)); + } + + const contentTypes = ['multipart/form-data']; + + bool hasFields = false; + final mp = MultipartRequest('PUT', Uri.parse(apiPath)); + if (assetData != null) { + hasFields = true; + mp.fields[r'assetData'] = assetData.field; + mp.files.add(assetData); + } + if (deviceAssetId != null) { + hasFields = true; + mp.fields[r'deviceAssetId'] = parameterToString(deviceAssetId); + } + if (deviceId != null) { + hasFields = true; + mp.fields[r'deviceId'] = parameterToString(deviceId); + } + if (duration != null) { + hasFields = true; + mp.fields[r'duration'] = parameterToString(duration); + } + if (fileCreatedAt != null) { + hasFields = true; + mp.fields[r'fileCreatedAt'] = parameterToString(fileCreatedAt); + } + if (fileModifiedAt != null) { + hasFields = true; + mp.fields[r'fileModifiedAt'] = parameterToString(fileModifiedAt); + } + if (filename != null) { + hasFields = true; + mp.fields[r'filename'] = parameterToString(filename); + } + if (hasFields) { + postBody = mp; + } + + return apiClient.invokeAPI( + apiPath, + 'PUT', + queryParams, + postBody, + headerParams, + formParams, + contentTypes.isEmpty ? null : contentTypes.first, + ); + } + + /// Replace the asset with new file, without changing its id + /// + /// This property was deprecated in v1.142.0. Replace the asset with new file, without changing its id. This endpoint requires the `asset.replace` permission. + /// + /// Parameters: + /// + /// * [String] id (required): + /// + /// * [MultipartFile] assetData (required): + /// + /// * [String] deviceAssetId (required): + /// + /// * [String] deviceId (required): + /// + /// * [DateTime] fileCreatedAt (required): + /// + /// * [DateTime] fileModifiedAt (required): + /// + /// * [String] key: + /// + /// * [String] slug: + /// + /// * [String] duration: + /// + /// * [String] filename: + Future replaceAsset(String id, MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? slug, String? duration, String? filename, }) async { + final response = await replaceAssetWithHttpInfo(id, assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key: key, slug: slug, duration: duration, filename: filename, ); + 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), 'AssetMediaResponseDto',) as AssetMediaResponseDto; + + } + return null; + } } diff --git a/mobile/openapi/lib/api/timeline_api.dart b/mobile/openapi/lib/api/timeline_api.dart index 2d142e3d67..70ac076c9d 100644 --- a/mobile/openapi/lib/api/timeline_api.dart +++ b/mobile/openapi/lib/api/timeline_api.dart @@ -53,12 +53,15 @@ class TimelineApi { /// * [AssetVisibility] visibility: /// Filter by asset visibility status (ARCHIVE, TIMELINE, HIDDEN, LOCKED) /// + /// * [bool] withCoordinates: + /// Include location data in the response + /// /// * [bool] withPartners: /// Include assets shared by partners /// /// * [bool] withStacked: /// Include stacked assets in the response. When true, only primary assets from stacks are returned. - Future getTimeBucketWithHttpInfo(String timeBucket, { String? albumId, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, String? personId, String? slug, String? tagId, String? userId, AssetVisibility? visibility, bool? withPartners, bool? withStacked, }) async { + Future getTimeBucketWithHttpInfo(String timeBucket, { String? albumId, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, String? personId, String? slug, String? tagId, String? userId, AssetVisibility? visibility, bool? withCoordinates, bool? withPartners, bool? withStacked, }) async { // ignore: prefer_const_declarations final apiPath = r'/timeline/bucket'; @@ -100,6 +103,9 @@ class TimelineApi { if (visibility != null) { queryParams.addAll(_queryParams('', 'visibility', visibility)); } + if (withCoordinates != null) { + queryParams.addAll(_queryParams('', 'withCoordinates', withCoordinates)); + } if (withPartners != null) { queryParams.addAll(_queryParams('', 'withPartners', withPartners)); } @@ -156,13 +162,16 @@ class TimelineApi { /// * [AssetVisibility] visibility: /// Filter by asset visibility status (ARCHIVE, TIMELINE, HIDDEN, LOCKED) /// + /// * [bool] withCoordinates: + /// Include location data in the response + /// /// * [bool] withPartners: /// Include assets shared by partners /// /// * [bool] withStacked: /// Include stacked assets in the response. When true, only primary assets from stacks are returned. - Future getTimeBucket(String timeBucket, { String? albumId, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, String? personId, String? slug, String? tagId, String? userId, AssetVisibility? visibility, bool? withPartners, bool? withStacked, }) async { - final response = await getTimeBucketWithHttpInfo(timeBucket, albumId: albumId, isFavorite: isFavorite, isTrashed: isTrashed, key: key, order: order, personId: personId, slug: slug, tagId: tagId, userId: userId, visibility: visibility, withPartners: withPartners, withStacked: withStacked, ); + Future getTimeBucket(String timeBucket, { String? albumId, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, String? personId, String? slug, String? tagId, String? userId, AssetVisibility? visibility, bool? withCoordinates, bool? withPartners, bool? withStacked, }) async { + final response = await getTimeBucketWithHttpInfo(timeBucket, albumId: albumId, isFavorite: isFavorite, isTrashed: isTrashed, key: key, order: order, personId: personId, slug: slug, tagId: tagId, userId: userId, visibility: visibility, withCoordinates: withCoordinates, withPartners: withPartners, withStacked: withStacked, ); if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, await _decodeBodyBytes(response)); } @@ -210,12 +219,15 @@ class TimelineApi { /// * [AssetVisibility] visibility: /// Filter by asset visibility status (ARCHIVE, TIMELINE, HIDDEN, LOCKED) /// + /// * [bool] withCoordinates: + /// Include location data in the response + /// /// * [bool] withPartners: /// Include assets shared by partners /// /// * [bool] withStacked: /// Include stacked assets in the response. When true, only primary assets from stacks are returned. - Future getTimeBucketsWithHttpInfo({ String? albumId, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, String? personId, String? slug, String? tagId, String? userId, AssetVisibility? visibility, bool? withPartners, bool? withStacked, }) async { + Future getTimeBucketsWithHttpInfo({ String? albumId, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, String? personId, String? slug, String? tagId, String? userId, AssetVisibility? visibility, bool? withCoordinates, bool? withPartners, bool? withStacked, }) async { // ignore: prefer_const_declarations final apiPath = r'/timeline/buckets'; @@ -256,6 +268,9 @@ class TimelineApi { if (visibility != null) { queryParams.addAll(_queryParams('', 'visibility', visibility)); } + if (withCoordinates != null) { + queryParams.addAll(_queryParams('', 'withCoordinates', withCoordinates)); + } if (withPartners != null) { queryParams.addAll(_queryParams('', 'withPartners', withPartners)); } @@ -309,13 +324,16 @@ class TimelineApi { /// * [AssetVisibility] visibility: /// Filter by asset visibility status (ARCHIVE, TIMELINE, HIDDEN, LOCKED) /// + /// * [bool] withCoordinates: + /// Include location data in the response + /// /// * [bool] withPartners: /// Include assets shared by partners /// /// * [bool] withStacked: /// Include stacked assets in the response. When true, only primary assets from stacks are returned. - Future?> getTimeBuckets({ String? albumId, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, String? personId, String? slug, String? tagId, String? userId, AssetVisibility? visibility, bool? withPartners, bool? withStacked, }) async { - final response = await getTimeBucketsWithHttpInfo( albumId: albumId, isFavorite: isFavorite, isTrashed: isTrashed, key: key, order: order, personId: personId, slug: slug, tagId: tagId, userId: userId, visibility: visibility, withPartners: withPartners, withStacked: withStacked, ); + Future?> getTimeBuckets({ String? albumId, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, String? personId, String? slug, String? tagId, String? userId, AssetVisibility? visibility, bool? withCoordinates, bool? withPartners, bool? withStacked, }) async { + final response = await getTimeBucketsWithHttpInfo( albumId: albumId, isFavorite: isFavorite, isTrashed: isTrashed, key: key, order: order, personId: personId, slug: slug, tagId: tagId, userId: userId, visibility: visibility, withCoordinates: withCoordinates, withPartners: withPartners, withStacked: withStacked, ); 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 ae5fd9227b..33056cf14e 100644 --- a/mobile/openapi/lib/api_client.dart +++ b/mobile/openapi/lib/api_client.dart @@ -314,6 +314,8 @@ class ApiClient { return CheckExistingAssetsResponseDto.fromJson(value); case 'Colorspace': return ColorspaceTypeTransformer().decode(value); + case 'ContributorCountResponseDto': + return ContributorCountResponseDto.fromJson(value); case 'CreateAlbumDto': return CreateAlbumDto.fromJson(value); case 'CreateLibraryDto': @@ -382,6 +384,8 @@ class ApiClient { return LoginResponseDto.fromJson(value); case 'LogoutResponseDto': return LogoutResponseDto.fromJson(value); + case 'MachineLearningAvailabilityChecksDto': + return MachineLearningAvailabilityChecksDto.fromJson(value); case 'ManualJobName': return ManualJobNameTypeTransformer().decode(value); case 'MapMarkerResponseDto': diff --git a/mobile/openapi/lib/model/album_response_dto.dart b/mobile/openapi/lib/model/album_response_dto.dart index 547a6a70fd..2f53706e7a 100644 --- a/mobile/openapi/lib/model/album_response_dto.dart +++ b/mobile/openapi/lib/model/album_response_dto.dart @@ -18,6 +18,7 @@ class AlbumResponseDto { this.albumUsers = const [], required this.assetCount, this.assets = const [], + this.contributorCounts = const [], required this.createdAt, required this.description, this.endDate, @@ -43,6 +44,8 @@ class AlbumResponseDto { List assets; + List contributorCounts; + DateTime createdAt; String description; @@ -100,6 +103,7 @@ class AlbumResponseDto { _deepEquality.equals(other.albumUsers, albumUsers) && other.assetCount == assetCount && _deepEquality.equals(other.assets, assets) && + _deepEquality.equals(other.contributorCounts, contributorCounts) && other.createdAt == createdAt && other.description == description && other.endDate == endDate && @@ -122,6 +126,7 @@ class AlbumResponseDto { (albumUsers.hashCode) + (assetCount.hashCode) + (assets.hashCode) + + (contributorCounts.hashCode) + (createdAt.hashCode) + (description.hashCode) + (endDate == null ? 0 : endDate!.hashCode) + @@ -137,7 +142,7 @@ class AlbumResponseDto { (updatedAt.hashCode); @override - String toString() => 'AlbumResponseDto[albumName=$albumName, albumThumbnailAssetId=$albumThumbnailAssetId, albumUsers=$albumUsers, assetCount=$assetCount, assets=$assets, createdAt=$createdAt, description=$description, endDate=$endDate, hasSharedLink=$hasSharedLink, id=$id, isActivityEnabled=$isActivityEnabled, lastModifiedAssetTimestamp=$lastModifiedAssetTimestamp, order=$order, owner=$owner, ownerId=$ownerId, shared=$shared, startDate=$startDate, updatedAt=$updatedAt]'; + String toString() => 'AlbumResponseDto[albumName=$albumName, albumThumbnailAssetId=$albumThumbnailAssetId, albumUsers=$albumUsers, assetCount=$assetCount, assets=$assets, contributorCounts=$contributorCounts, createdAt=$createdAt, description=$description, endDate=$endDate, hasSharedLink=$hasSharedLink, id=$id, isActivityEnabled=$isActivityEnabled, lastModifiedAssetTimestamp=$lastModifiedAssetTimestamp, order=$order, owner=$owner, ownerId=$ownerId, shared=$shared, startDate=$startDate, updatedAt=$updatedAt]'; Map toJson() { final json = {}; @@ -150,6 +155,7 @@ class AlbumResponseDto { json[r'albumUsers'] = this.albumUsers; json[r'assetCount'] = this.assetCount; json[r'assets'] = this.assets; + json[r'contributorCounts'] = this.contributorCounts; json[r'createdAt'] = this.createdAt.toUtc().toIso8601String(); json[r'description'] = this.description; if (this.endDate != null) { @@ -196,6 +202,7 @@ class AlbumResponseDto { albumUsers: AlbumUserResponseDto.listFromJson(json[r'albumUsers']), assetCount: mapValueOfType(json, r'assetCount')!, assets: AssetResponseDto.listFromJson(json[r'assets']), + contributorCounts: ContributorCountResponseDto.listFromJson(json[r'contributorCounts']), createdAt: mapDateTime(json, r'createdAt', r'')!, description: mapValueOfType(json, r'description')!, endDate: mapDateTime(json, r'endDate', r''), diff --git a/mobile/openapi/lib/model/contributor_count_response_dto.dart b/mobile/openapi/lib/model/contributor_count_response_dto.dart new file mode 100644 index 0000000000..e0e16ee427 --- /dev/null +++ b/mobile/openapi/lib/model/contributor_count_response_dto.dart @@ -0,0 +1,107 @@ +// +// 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 ContributorCountResponseDto { + /// Returns a new [ContributorCountResponseDto] instance. + ContributorCountResponseDto({ + required this.assetCount, + required this.userId, + }); + + int assetCount; + + String userId; + + @override + bool operator ==(Object other) => identical(this, other) || other is ContributorCountResponseDto && + other.assetCount == assetCount && + other.userId == userId; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (assetCount.hashCode) + + (userId.hashCode); + + @override + String toString() => 'ContributorCountResponseDto[assetCount=$assetCount, userId=$userId]'; + + Map toJson() { + final json = {}; + json[r'assetCount'] = this.assetCount; + json[r'userId'] = this.userId; + return json; + } + + /// Returns a new [ContributorCountResponseDto] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static ContributorCountResponseDto? fromJson(dynamic value) { + upgradeDto(value, "ContributorCountResponseDto"); + if (value is Map) { + final json = value.cast(); + + return ContributorCountResponseDto( + assetCount: mapValueOfType(json, r'assetCount')!, + 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 = ContributorCountResponseDto.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 = ContributorCountResponseDto.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of ContributorCountResponseDto-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] = ContributorCountResponseDto.listFromJson(entry.value, growable: growable,); + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = { + 'assetCount', + 'userId', + }; +} + diff --git a/mobile/openapi/lib/model/machine_learning_availability_checks_dto.dart b/mobile/openapi/lib/model/machine_learning_availability_checks_dto.dart new file mode 100644 index 0000000000..84b3181426 --- /dev/null +++ b/mobile/openapi/lib/model/machine_learning_availability_checks_dto.dart @@ -0,0 +1,115 @@ +// +// 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 MachineLearningAvailabilityChecksDto { + /// Returns a new [MachineLearningAvailabilityChecksDto] instance. + MachineLearningAvailabilityChecksDto({ + required this.enabled, + required this.interval, + required this.timeout, + }); + + bool enabled; + + num interval; + + num timeout; + + @override + bool operator ==(Object other) => identical(this, other) || other is MachineLearningAvailabilityChecksDto && + other.enabled == enabled && + other.interval == interval && + other.timeout == timeout; + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (enabled.hashCode) + + (interval.hashCode) + + (timeout.hashCode); + + @override + String toString() => 'MachineLearningAvailabilityChecksDto[enabled=$enabled, interval=$interval, timeout=$timeout]'; + + Map toJson() { + final json = {}; + json[r'enabled'] = this.enabled; + json[r'interval'] = this.interval; + json[r'timeout'] = this.timeout; + return json; + } + + /// Returns a new [MachineLearningAvailabilityChecksDto] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static MachineLearningAvailabilityChecksDto? fromJson(dynamic value) { + upgradeDto(value, "MachineLearningAvailabilityChecksDto"); + if (value is Map) { + final json = value.cast(); + + return MachineLearningAvailabilityChecksDto( + enabled: mapValueOfType(json, r'enabled')!, + interval: num.parse('${json[r'interval']}'), + timeout: num.parse('${json[r'timeout']}'), + ); + } + 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 = MachineLearningAvailabilityChecksDto.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 = MachineLearningAvailabilityChecksDto.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of MachineLearningAvailabilityChecksDto-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] = MachineLearningAvailabilityChecksDto.listFromJson(entry.value, growable: growable,); + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = { + 'enabled', + 'interval', + 'timeout', + }; +} + diff --git a/mobile/openapi/lib/model/notification_type.dart b/mobile/openapi/lib/model/notification_type.dart index 436d2d190f..b5885aa441 100644 --- a/mobile/openapi/lib/model/notification_type.dart +++ b/mobile/openapi/lib/model/notification_type.dart @@ -26,6 +26,8 @@ class NotificationType { static const jobFailed = NotificationType._(r'JobFailed'); static const backupFailed = NotificationType._(r'BackupFailed'); static const systemMessage = NotificationType._(r'SystemMessage'); + static const albumInvite = NotificationType._(r'AlbumInvite'); + static const albumUpdate = NotificationType._(r'AlbumUpdate'); static const custom = NotificationType._(r'Custom'); /// List of all possible values in this [enum][NotificationType]. @@ -33,6 +35,8 @@ class NotificationType { jobFailed, backupFailed, systemMessage, + albumInvite, + albumUpdate, custom, ]; @@ -75,6 +79,8 @@ class NotificationTypeTypeTransformer { case r'JobFailed': return NotificationType.jobFailed; case r'BackupFailed': return NotificationType.backupFailed; case r'SystemMessage': return NotificationType.systemMessage; + case r'AlbumInvite': return NotificationType.albumInvite; + case r'AlbumUpdate': return NotificationType.albumUpdate; case r'Custom': return NotificationType.custom; default: if (!allowNull) { diff --git a/mobile/openapi/lib/model/system_config_machine_learning_dto.dart b/mobile/openapi/lib/model/system_config_machine_learning_dto.dart index a4a9ca7d82..d7b2566d59 100644 --- a/mobile/openapi/lib/model/system_config_machine_learning_dto.dart +++ b/mobile/openapi/lib/model/system_config_machine_learning_dto.dart @@ -13,14 +13,16 @@ part of openapi.api; class SystemConfigMachineLearningDto { /// Returns a new [SystemConfigMachineLearningDto] instance. SystemConfigMachineLearningDto({ + required this.availabilityChecks, required this.clip, required this.duplicateDetection, required this.enabled, required this.facialRecognition, - this.url, this.urls = const [], }); + MachineLearningAvailabilityChecksDto availabilityChecks; + CLIPConfig clip; DuplicateDetectionConfig duplicateDetection; @@ -29,50 +31,37 @@ class SystemConfigMachineLearningDto { FacialRecognitionConfig facialRecognition; - /// This property was deprecated in v1.122.0 - /// - /// 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? url; - List urls; @override bool operator ==(Object other) => identical(this, other) || other is SystemConfigMachineLearningDto && + other.availabilityChecks == availabilityChecks && other.clip == clip && other.duplicateDetection == duplicateDetection && other.enabled == enabled && other.facialRecognition == facialRecognition && - other.url == url && _deepEquality.equals(other.urls, urls); @override int get hashCode => // ignore: unnecessary_parenthesis + (availabilityChecks.hashCode) + (clip.hashCode) + (duplicateDetection.hashCode) + (enabled.hashCode) + (facialRecognition.hashCode) + - (url == null ? 0 : url!.hashCode) + (urls.hashCode); @override - String toString() => 'SystemConfigMachineLearningDto[clip=$clip, duplicateDetection=$duplicateDetection, enabled=$enabled, facialRecognition=$facialRecognition, url=$url, urls=$urls]'; + String toString() => 'SystemConfigMachineLearningDto[availabilityChecks=$availabilityChecks, clip=$clip, duplicateDetection=$duplicateDetection, enabled=$enabled, facialRecognition=$facialRecognition, urls=$urls]'; Map toJson() { final json = {}; + json[r'availabilityChecks'] = this.availabilityChecks; json[r'clip'] = this.clip; json[r'duplicateDetection'] = this.duplicateDetection; json[r'enabled'] = this.enabled; json[r'facialRecognition'] = this.facialRecognition; - if (this.url != null) { - json[r'url'] = this.url; - } else { - // json[r'url'] = null; - } json[r'urls'] = this.urls; return json; } @@ -86,11 +75,11 @@ class SystemConfigMachineLearningDto { final json = value.cast(); return SystemConfigMachineLearningDto( + availabilityChecks: MachineLearningAvailabilityChecksDto.fromJson(json[r'availabilityChecks'])!, clip: CLIPConfig.fromJson(json[r'clip'])!, duplicateDetection: DuplicateDetectionConfig.fromJson(json[r'duplicateDetection'])!, enabled: mapValueOfType(json, r'enabled')!, facialRecognition: FacialRecognitionConfig.fromJson(json[r'facialRecognition'])!, - url: mapValueOfType(json, r'url'), urls: json[r'urls'] is Iterable ? (json[r'urls'] as Iterable).cast().toList(growable: false) : const [], @@ -141,6 +130,7 @@ class SystemConfigMachineLearningDto { /// The list of required keys that must be present in a JSON. static const requiredKeys = { + 'availabilityChecks', 'clip', 'duplicateDetection', 'enabled', diff --git a/mobile/openapi/lib/model/time_bucket_asset_response_dto.dart b/mobile/openapi/lib/model/time_bucket_asset_response_dto.dart index 886b353f68..58032b7c51 100644 --- a/mobile/openapi/lib/model/time_bucket_asset_response_dto.dart +++ b/mobile/openapi/lib/model/time_bucket_asset_response_dto.dart @@ -21,8 +21,10 @@ class TimeBucketAssetResponseDto { this.isFavorite = const [], this.isImage = const [], this.isTrashed = const [], + this.latitude = const [], this.livePhotoVideoId = const [], this.localOffsetHours = const [], + this.longitude = const [], this.ownerId = const [], this.projectionType = const [], this.ratio = const [], @@ -55,12 +57,18 @@ class TimeBucketAssetResponseDto { /// Array indicating whether each asset is in the trash List isTrashed; + /// Array of latitude coordinates extracted from EXIF GPS data + List latitude; + /// Array of live photo video asset IDs (null for non-live photos) List livePhotoVideoId; /// Array of UTC offset hours at the time each photo was taken. Positive values are east of UTC, negative values are west of UTC. Values may be fractional (e.g., 5.5 for +05:30, -9.75 for -09:45). Applying this offset to 'fileCreatedAt' will give you the time the photo was taken from the photographer's perspective. List localOffsetHours; + /// Array of longitude coordinates extracted from EXIF GPS data + List longitude; + /// Array of owner IDs for each asset List ownerId; @@ -89,8 +97,10 @@ class TimeBucketAssetResponseDto { _deepEquality.equals(other.isFavorite, isFavorite) && _deepEquality.equals(other.isImage, isImage) && _deepEquality.equals(other.isTrashed, isTrashed) && + _deepEquality.equals(other.latitude, latitude) && _deepEquality.equals(other.livePhotoVideoId, livePhotoVideoId) && _deepEquality.equals(other.localOffsetHours, localOffsetHours) && + _deepEquality.equals(other.longitude, longitude) && _deepEquality.equals(other.ownerId, ownerId) && _deepEquality.equals(other.projectionType, projectionType) && _deepEquality.equals(other.ratio, ratio) && @@ -109,8 +119,10 @@ class TimeBucketAssetResponseDto { (isFavorite.hashCode) + (isImage.hashCode) + (isTrashed.hashCode) + + (latitude.hashCode) + (livePhotoVideoId.hashCode) + (localOffsetHours.hashCode) + + (longitude.hashCode) + (ownerId.hashCode) + (projectionType.hashCode) + (ratio.hashCode) + @@ -119,7 +131,7 @@ class TimeBucketAssetResponseDto { (visibility.hashCode); @override - String toString() => 'TimeBucketAssetResponseDto[city=$city, country=$country, duration=$duration, fileCreatedAt=$fileCreatedAt, id=$id, isFavorite=$isFavorite, isImage=$isImage, isTrashed=$isTrashed, livePhotoVideoId=$livePhotoVideoId, localOffsetHours=$localOffsetHours, ownerId=$ownerId, projectionType=$projectionType, ratio=$ratio, stack=$stack, thumbhash=$thumbhash, visibility=$visibility]'; + String toString() => 'TimeBucketAssetResponseDto[city=$city, country=$country, duration=$duration, fileCreatedAt=$fileCreatedAt, id=$id, isFavorite=$isFavorite, isImage=$isImage, isTrashed=$isTrashed, latitude=$latitude, livePhotoVideoId=$livePhotoVideoId, localOffsetHours=$localOffsetHours, longitude=$longitude, ownerId=$ownerId, projectionType=$projectionType, ratio=$ratio, stack=$stack, thumbhash=$thumbhash, visibility=$visibility]'; Map toJson() { final json = {}; @@ -131,8 +143,10 @@ class TimeBucketAssetResponseDto { json[r'isFavorite'] = this.isFavorite; json[r'isImage'] = this.isImage; json[r'isTrashed'] = this.isTrashed; + json[r'latitude'] = this.latitude; json[r'livePhotoVideoId'] = this.livePhotoVideoId; json[r'localOffsetHours'] = this.localOffsetHours; + json[r'longitude'] = this.longitude; json[r'ownerId'] = this.ownerId; json[r'projectionType'] = this.projectionType; json[r'ratio'] = this.ratio; @@ -175,12 +189,18 @@ class TimeBucketAssetResponseDto { isTrashed: json[r'isTrashed'] is Iterable ? (json[r'isTrashed'] as Iterable).cast().toList(growable: false) : const [], + latitude: json[r'latitude'] is Iterable + ? (json[r'latitude'] as Iterable).cast().toList(growable: false) + : const [], livePhotoVideoId: json[r'livePhotoVideoId'] is Iterable ? (json[r'livePhotoVideoId'] as Iterable).cast().toList(growable: false) : const [], localOffsetHours: json[r'localOffsetHours'] is Iterable ? (json[r'localOffsetHours'] as Iterable).cast().toList(growable: false) : const [], + longitude: json[r'longitude'] is Iterable + ? (json[r'longitude'] as Iterable).cast().toList(growable: false) + : const [], ownerId: json[r'ownerId'] is Iterable ? (json[r'ownerId'] as Iterable).cast().toList(growable: false) : const [], diff --git a/mobile/pigeon/background_worker_api.dart b/mobile/pigeon/background_worker_api.dart index 193bbc5832..a40d290199 100644 --- a/mobile/pigeon/background_worker_api.dart +++ b/mobile/pigeon/background_worker_api.dart @@ -11,10 +11,21 @@ import 'package:pigeon/pigeon.dart'; dartPackageName: 'immich_mobile', ), ) +class BackgroundWorkerSettings { + final bool requiresCharging; + final int minimumDelaySeconds; + + const BackgroundWorkerSettings({required this.requiresCharging, required this.minimumDelaySeconds}); +} + @HostApi() abstract class BackgroundWorkerFgHostApi { void enable(); + void saveNotificationMessage(String title, String body); + + void configure(BackgroundWorkerSettings settings); + void disable(); } diff --git a/mobile/pigeon/background_worker_lock_api.dart b/mobile/pigeon/background_worker_lock_api.dart new file mode 100644 index 0000000000..44c5220367 --- /dev/null +++ b/mobile/pigeon/background_worker_lock_api.dart @@ -0,0 +1,17 @@ +import 'package:pigeon/pigeon.dart'; + +@ConfigurePigeon( + PigeonOptions( + dartOut: 'lib/platform/background_worker_lock_api.g.dart', + kotlinOut: 'android/app/src/main/kotlin/app/alextran/immich/background/BackgroundWorkerLock.g.kt', + kotlinOptions: KotlinOptions(package: 'app.alextran.immich.background', includeErrorClass: false), + dartOptions: DartOptions(), + dartPackageName: 'immich_mobile', + ), +) +@HostApi() +abstract class BackgroundWorkerLockApi { + void lock(); + + void unlock(); +} diff --git a/mobile/pigeon/connectivity_api.dart b/mobile/pigeon/connectivity_api.dart new file mode 100644 index 0000000000..c5677ee20e --- /dev/null +++ b/mobile/pigeon/connectivity_api.dart @@ -0,0 +1,20 @@ +import 'package:pigeon/pigeon.dart'; + +@ConfigurePigeon( + PigeonOptions( + dartOut: 'lib/platform/connectivity_api.g.dart', + swiftOut: 'ios/Runner/Connectivity/Connectivity.g.swift', + swiftOptions: SwiftOptions(includeErrorClass: false), + kotlinOut: 'android/app/src/main/kotlin/app/alextran/immich/connectivity/Connectivity.g.kt', + kotlinOptions: KotlinOptions(package: 'app.alextran.immich.connectivity'), + dartOptions: DartOptions(), + dartPackageName: 'immich_mobile', + ), +) +enum NetworkCapability { cellular, wifi, vpn, unmetered } + +@HostApi() +abstract class ConnectivityApi { + @TaskQueue(type: TaskQueueType.serialBackgroundThread) + List getCapabilities(); +} diff --git a/mobile/pigeon/native_sync_api.dart b/mobile/pigeon/native_sync_api.dart index e84c814c3d..ac08a68ca3 100644 --- a/mobile/pigeon/native_sync_api.dart +++ b/mobile/pigeon/native_sync_api.dart @@ -71,6 +71,14 @@ class SyncDelta { }); } +class HashResult { + final String assetId; + final String? error; + final String? hash; + + const HashResult({required this.assetId, this.error, this.hash}); +} + @HostApi() abstract class NativeSyncApi { bool shouldFullSync(); @@ -94,6 +102,9 @@ abstract class NativeSyncApi { @TaskQueue(type: TaskQueueType.serialBackgroundThread) List getAssetsForAlbum(String albumId, {int? updatedTimeCond}); + @async @TaskQueue(type: TaskQueueType.serialBackgroundThread) - List hashPaths(List paths); + List hashAssets(List assetIds, {bool allowNetworkAccess = false}); + + void cancelHashing(); } diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 624ed1fe65..125e4d46e2 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -77,10 +77,10 @@ packages: dependency: "direct main" description: name: background_downloader - sha256: "2d4c2b7438e7643585880f9cc00ace16a52d778088751f1bfbf714627b315462" + sha256: "9ed74c55750932178f6989ba8a659687c2a102e05b70f561a1b3f047a5dda790" url: "https://pub.dev" source: hosted - version: "9.2.0" + version: "9.2.5" bonsoir: dependency: transitive description: @@ -317,10 +317,10 @@ packages: dependency: "direct main" description: name: connectivity_plus - sha256: "04bf81bb0b77de31557b58d052b24b3eee33f09a6e7a8c68a3e247c7df19ec27" + sha256: b5e72753cf63becce2c61fd04dfe0f1c430cc5278b53a1342dc5ad839eab29ec url: "https://pub.dev" source: hosted - version: "6.1.3" + version: "6.1.5" connectivity_plus_platform_interface: dependency: transitive description: @@ -437,18 +437,18 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: "306b78788d1bb569edb7c55d622953c2414ca12445b41c9117963e03afc5c513" + sha256: "49413c8ca514dea7633e8def233b25efdf83ec8522955cc2c0e3ad802927e7c6" url: "https://pub.dev" source: hosted - version: "11.3.3" + version: "12.1.0" device_info_plus_platform_interface: dependency: transitive description: name: device_info_plus_platform_interface - sha256: "0b04e02b30791224b31969eb1b50d723498f402971bff3630bca2ba839bd1ed2" + sha256: e1ea89119e34903dca74b883d0dd78eb762814f97fb6c76f35e9ff74d261a18f url: "https://pub.dev" source: hosted - version: "7.0.2" + version: "7.0.3" drift: dependency: "direct main" description: @@ -1022,25 +1022,34 @@ packages: isar: dependency: "direct main" description: - name: isar - sha256: e17a9555bc7f22ff26568b8c64d019b4ffa2dc6bd4cb1c8d9b269aefd32e53ad - url: "https://pub.isar-community.dev" - source: hosted + path: "packages/isar" + ref: bb1dca40fe87a001122e5d43bc6254718cb49f3a + resolved-ref: bb1dca40fe87a001122e5d43bc6254718cb49f3a + url: "https://github.com/immich-app/isar" + source: git version: "3.1.8" - isar_flutter_libs: + isar_community: + dependency: transitive + description: + name: isar_community + sha256: "28f59e54636c45ba0bb1b3b7f2656f1c50325f740cea6efcd101900be3fba546" + url: "https://pub.dev" + source: hosted + version: "3.3.0-dev.3" + isar_community_flutter_libs: dependency: "direct main" description: - name: isar_flutter_libs - sha256: "78710781e658ce4bff59b3f38c5b2735e899e627f4e926e1221934e77b95231a" - url: "https://pub.isar-community.dev" + name: isar_community_flutter_libs + sha256: c2934fe755bb3181cb67602fd5df0d080b3d3eb52799f98623aa4fc5acbea010 + url: "https://pub.dev" source: hosted - version: "3.1.8" + version: "3.3.0-dev.3" isar_generator: dependency: "direct dev" description: path: "packages/isar_generator" - ref: v3 - resolved-ref: ad574f60ed6f39d2995cd16fc7dc3de9a646ef30 + ref: bb1dca40fe87a001122e5d43bc6254718cb49f3a + resolved-ref: bb1dca40fe87a001122e5d43bc6254718cb49f3a url: "https://github.com/immich-app/isar" source: git version: "3.1.8" @@ -1064,26 +1073,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.9" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" lints: dependency: transitive description: @@ -1208,8 +1217,8 @@ packages: dependency: "direct main" description: path: "." - ref: "5459d54" - resolved-ref: "5459d54cdc1cf4d99e2193b310052f1ebb5dcf43" + ref: "893894b" + resolved-ref: "893894b98b832be8a995a8d5d4c2289d0ad2d246" url: "https://github.com/immich-app/native_video_player" source: git version: "1.3.1" @@ -1429,7 +1438,7 @@ packages: source: hosted version: "5.0.1" platform: - dependency: "direct main" + dependency: transitive description: name: platform sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" @@ -1877,10 +1886,10 @@ packages: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.6" thumbhash: dependency: "direct main" description: @@ -2037,10 +2046,10 @@ packages: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vm_service: dependency: transitive description: @@ -2171,4 +2180,4 @@ packages: version: "3.1.3" sdks: dart: ">=3.8.0 <4.0.0" - flutter: ">=3.32.8" + flutter: ">=3.35.4" diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 006de4f591..82ce321954 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -2,13 +2,11 @@ name: immich_mobile description: Immich - selfhosted backup media file on mobile phone publish_to: 'none' -version: 1.141.1+3013 +version: 2.1.0+3022 environment: sdk: '>=3.8.0 <4.0.0' - flutter: 3.32.8 - -isar_version: &isar_version 3.1.8 + flutter: 3.35.4 dependencies: flutter: @@ -16,7 +14,7 @@ dependencies: async: ^2.11.0 auto_route: ^9.2.0 - background_downloader: ^9.2.0 + background_downloader: ^9.2.5 cached_network_image: ^3.4.1 cancellation_token_http: ^2.1.0 cast: ^2.1.0 @@ -24,7 +22,7 @@ dependencies: connectivity_plus: ^6.1.3 crop_image: ^1.0.16 crypto: ^3.0.6 - device_info_plus: ^11.3.3 + device_info_plus: ^12.0.0 dynamic_color: ^1.7.0 easy_image_viewer: ^1.5.1 easy_localization: ^3.0.7+1 @@ -57,7 +55,6 @@ dependencies: photo_manager: ^3.6.4 photo_manager_image_provider: ^2.2.0 pinput: ^5.0.1 - platform: ^3.1.6 punycode: ^1.0.0 riverpod_annotation: ^2.6.1 scrollable_positioned_list: ^0.3.8 @@ -78,15 +75,15 @@ dependencies: native_video_player: git: url: https://github.com/immich-app/native_video_player - ref: '5459d54' + ref: '893894b' openapi: path: openapi isar: - version: *isar_version - hosted: https://pub.isar-community.dev/ - isar_flutter_libs: # contains Isar Core - version: *isar_version - hosted: https://pub.isar-community.dev/ + git: + url: https://github.com/immich-app/isar + ref: 'bb1dca40fe87a001122e5d43bc6254718cb49f3a' + path: packages/isar/ + isar_community_flutter_libs: 3.3.0-dev.3 # DB drift: ^2.23.1 drift_flutter: ^0.2.4 @@ -102,7 +99,7 @@ dev_dependencies: isar_generator: git: url: https://github.com/immich-app/isar - ref: v3 + ref: 'bb1dca40fe87a001122e5d43bc6254718cb49f3a' path: packages/isar_generator/ integration_test: sdk: flutter diff --git a/mobile/test/domain/services/hash_service_test.dart b/mobile/test/domain/services/hash_service_test.dart index 7969131e7f..20d60b6866 100644 --- a/mobile/test/domain/services/hash_service_test.dart +++ b/mobile/test/domain/services/hash_service_test.dart @@ -1,11 +1,7 @@ -import 'dart:convert'; -import 'dart:io'; -import 'dart:typed_data'; - import 'package:flutter_test/flutter_test.dart'; -import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; +import 'package:immich_mobile/domain/models/album/local_album.model.dart'; import 'package:immich_mobile/domain/services/hash.service.dart'; -import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart'; +import 'package:immich_mobile/platform/native_sync_api.g.dart'; import 'package:mocktail/mocktail.dart'; import '../../fixtures/album.stub.dart'; @@ -13,192 +9,137 @@ import '../../fixtures/asset.stub.dart'; import '../../infrastructure/repository.mock.dart'; import '../service.mock.dart'; -class MockFile extends Mock implements File {} - void main() { late HashService sut; late MockLocalAlbumRepository mockAlbumRepo; late MockLocalAssetRepository mockAssetRepo; - late MockStorageRepository mockStorageRepo; late MockNativeSyncApi mockNativeApi; - final sortBy = {SortLocalAlbumsBy.backupSelection, SortLocalAlbumsBy.isIosSharedAlbum}; setUp(() { mockAlbumRepo = MockLocalAlbumRepository(); mockAssetRepo = MockLocalAssetRepository(); - mockStorageRepo = MockStorageRepository(); mockNativeApi = MockNativeSyncApi(); sut = HashService( localAlbumRepository: mockAlbumRepo, localAssetRepository: mockAssetRepo, - storageRepository: mockStorageRepo, nativeSyncApi: mockNativeApi, ); registerFallbackValue(LocalAlbumStub.recent); registerFallbackValue(LocalAssetStub.image1); + registerFallbackValue({}); when(() => mockAssetRepo.updateHashes(any())).thenAnswer((_) async => {}); - when(() => mockStorageRepo.clearCache()).thenAnswer((_) async => {}); }); group('HashService hashAssets', () { test('skips albums with no assets to hash', () async { when( - () => mockAlbumRepo.getAll(sortBy: sortBy), + () => mockAlbumRepo.getBackupAlbums(), ).thenAnswer((_) async => [LocalAlbumStub.recent.copyWith(assetCount: 0)]); when(() => mockAlbumRepo.getAssetsToHash(LocalAlbumStub.recent.id)).thenAnswer((_) async => []); await sut.hashAssets(); - verifyNever(() => mockStorageRepo.getFileForAsset(any())); - verifyNever(() => mockNativeApi.hashPaths(any())); + verifyNever(() => mockNativeApi.hashAssets(any(), allowNetworkAccess: any(named: 'allowNetworkAccess'))); }); }); group('HashService _hashAssets', () { - test('skips assets without files', () async { + test('skips empty batches', () async { final album = LocalAlbumStub.recent; - final asset = LocalAssetStub.image1; - when(() => mockAlbumRepo.getAll(sortBy: sortBy)).thenAnswer((_) async => [album]); - when(() => mockAlbumRepo.getAssetsToHash(album.id)).thenAnswer((_) async => [asset]); - when(() => mockStorageRepo.getFileForAsset(asset.id)).thenAnswer((_) async => null); + when(() => mockAlbumRepo.getBackupAlbums()).thenAnswer((_) async => [album]); + when(() => mockAlbumRepo.getAssetsToHash(album.id)).thenAnswer((_) async => []); await sut.hashAssets(); - verifyNever(() => mockNativeApi.hashPaths(any())); + verifyNever(() => mockNativeApi.hashAssets(any(), allowNetworkAccess: any(named: 'allowNetworkAccess'))); }); test('processes assets when available', () async { final album = LocalAlbumStub.recent; final asset = LocalAssetStub.image1; - final mockFile = MockFile(); - final hash = Uint8List.fromList(List.generate(20, (i) => i)); - when(() => mockFile.length()).thenAnswer((_) async => 1000); - when(() => mockFile.path).thenReturn('image-path'); - - when(() => mockAlbumRepo.getAll(sortBy: sortBy)).thenAnswer((_) async => [album]); + when(() => mockAlbumRepo.getBackupAlbums()).thenAnswer((_) async => [album]); when(() => mockAlbumRepo.getAssetsToHash(album.id)).thenAnswer((_) async => [asset]); - when(() => mockStorageRepo.getFileForAsset(asset.id)).thenAnswer((_) async => mockFile); - when(() => mockNativeApi.hashPaths(['image-path'])).thenAnswer((_) async => [hash]); + when( + () => mockNativeApi.hashAssets([asset.id], allowNetworkAccess: false), + ).thenAnswer((_) async => [HashResult(assetId: asset.id, hash: 'test-hash')]); await sut.hashAssets(); - verify(() => mockNativeApi.hashPaths(['image-path'])).called(1); - final captured = verify(() => mockAssetRepo.updateHashes(captureAny())).captured.first as List; + verify(() => mockNativeApi.hashAssets([asset.id], allowNetworkAccess: false)).called(1); + final captured = verify(() => mockAssetRepo.updateHashes(captureAny())).captured.first as Map; expect(captured.length, 1); - expect(captured[0].checksum, base64.encode(hash)); + expect(captured[asset.id], 'test-hash'); }); test('handles failed hashes', () async { final album = LocalAlbumStub.recent; final asset = LocalAssetStub.image1; - final mockFile = MockFile(); - when(() => mockFile.length()).thenAnswer((_) async => 1000); - when(() => mockFile.path).thenReturn('image-path'); - when(() => mockAlbumRepo.getAll(sortBy: sortBy)).thenAnswer((_) async => [album]); + when(() => mockAlbumRepo.getBackupAlbums()).thenAnswer((_) async => [album]); when(() => mockAlbumRepo.getAssetsToHash(album.id)).thenAnswer((_) async => [asset]); - when(() => mockStorageRepo.getFileForAsset(asset.id)).thenAnswer((_) async => mockFile); - when(() => mockNativeApi.hashPaths(['image-path'])).thenAnswer((_) async => [null]); - when(() => mockAssetRepo.updateHashes(any())).thenAnswer((_) async => {}); + when( + () => mockNativeApi.hashAssets([asset.id], allowNetworkAccess: false), + ).thenAnswer((_) async => [HashResult(assetId: asset.id, error: 'Failed to hash')]); await sut.hashAssets(); - final captured = verify(() => mockAssetRepo.updateHashes(captureAny())).captured.first as List; + final captured = verify(() => mockAssetRepo.updateHashes(captureAny())).captured.first as Map; expect(captured.length, 0); }); - test('handles invalid hash length', () async { + test('handles null hash results', () async { final album = LocalAlbumStub.recent; final asset = LocalAssetStub.image1; - final mockFile = MockFile(); - when(() => mockFile.length()).thenAnswer((_) async => 1000); - when(() => mockFile.path).thenReturn('image-path'); - when(() => mockAlbumRepo.getAll(sortBy: sortBy)).thenAnswer((_) async => [album]); + when(() => mockAlbumRepo.getBackupAlbums()).thenAnswer((_) async => [album]); when(() => mockAlbumRepo.getAssetsToHash(album.id)).thenAnswer((_) async => [asset]); - when(() => mockStorageRepo.getFileForAsset(asset.id)).thenAnswer((_) async => mockFile); - - final invalidHash = Uint8List.fromList([1, 2, 3]); - when(() => mockNativeApi.hashPaths(['image-path'])).thenAnswer((_) async => [invalidHash]); - when(() => mockAssetRepo.updateHashes(any())).thenAnswer((_) async => {}); + when( + () => mockNativeApi.hashAssets([asset.id], allowNetworkAccess: false), + ).thenAnswer((_) async => [HashResult(assetId: asset.id, hash: null)]); await sut.hashAssets(); - final captured = verify(() => mockAssetRepo.updateHashes(captureAny())).captured.first as List; + final captured = verify(() => mockAssetRepo.updateHashes(captureAny())).captured.first as Map; expect(captured.length, 0); }); - test('batches by file count limit', () async { - final sut = HashService( - localAlbumRepository: mockAlbumRepo, - localAssetRepository: mockAssetRepo, - storageRepository: mockStorageRepo, - nativeSyncApi: mockNativeApi, - batchFileLimit: 1, - ); - - final album = LocalAlbumStub.recent; - final asset1 = LocalAssetStub.image1; - final asset2 = LocalAssetStub.image2; - final mockFile1 = MockFile(); - final mockFile2 = MockFile(); - when(() => mockFile1.length()).thenAnswer((_) async => 100); - when(() => mockFile1.path).thenReturn('path-1'); - when(() => mockFile2.length()).thenAnswer((_) async => 100); - when(() => mockFile2.path).thenReturn('path-2'); - - when(() => mockAlbumRepo.getAll(sortBy: sortBy)).thenAnswer((_) async => [album]); - when(() => mockAlbumRepo.getAssetsToHash(album.id)).thenAnswer((_) async => [asset1, asset2]); - when(() => mockStorageRepo.getFileForAsset(asset1.id)).thenAnswer((_) async => mockFile1); - when(() => mockStorageRepo.getFileForAsset(asset2.id)).thenAnswer((_) async => mockFile2); - - final hash = Uint8List.fromList(List.generate(20, (i) => i)); - when(() => mockNativeApi.hashPaths(any())).thenAnswer((_) async => [hash]); - when(() => mockAssetRepo.updateHashes(any())).thenAnswer((_) async => {}); - - await sut.hashAssets(); - - verify(() => mockNativeApi.hashPaths(['path-1'])).called(1); - verify(() => mockNativeApi.hashPaths(['path-2'])).called(1); - verify(() => mockAssetRepo.updateHashes(any())).called(2); - }); - test('batches by size limit', () async { + const batchSize = 2; final sut = HashService( localAlbumRepository: mockAlbumRepo, localAssetRepository: mockAssetRepo, - storageRepository: mockStorageRepo, nativeSyncApi: mockNativeApi, - batchSizeLimit: 80, + batchSize: batchSize, ); final album = LocalAlbumStub.recent; final asset1 = LocalAssetStub.image1; final asset2 = LocalAssetStub.image2; - final mockFile1 = MockFile(); - final mockFile2 = MockFile(); - when(() => mockFile1.length()).thenAnswer((_) async => 100); - when(() => mockFile1.path).thenReturn('path-1'); - when(() => mockFile2.length()).thenAnswer((_) async => 100); - when(() => mockFile2.path).thenReturn('path-2'); + final asset3 = LocalAssetStub.image1.copyWith(id: 'image3', name: 'image3.jpg'); - when(() => mockAlbumRepo.getAll(sortBy: sortBy)).thenAnswer((_) async => [album]); - when(() => mockAlbumRepo.getAssetsToHash(album.id)).thenAnswer((_) async => [asset1, asset2]); - when(() => mockStorageRepo.getFileForAsset(asset1.id)).thenAnswer((_) async => mockFile1); - when(() => mockStorageRepo.getFileForAsset(asset2.id)).thenAnswer((_) async => mockFile2); + final capturedCalls = >[]; - final hash = Uint8List.fromList(List.generate(20, (i) => i)); - when(() => mockNativeApi.hashPaths(any())).thenAnswer((_) async => [hash]); when(() => mockAssetRepo.updateHashes(any())).thenAnswer((_) async => {}); + when(() => mockAlbumRepo.getBackupAlbums()).thenAnswer((_) async => [album]); + when(() => mockAlbumRepo.getAssetsToHash(album.id)).thenAnswer((_) async => [asset1, asset2, asset3]); + when(() => mockNativeApi.hashAssets(any(), allowNetworkAccess: any(named: 'allowNetworkAccess'))).thenAnswer(( + invocation, + ) async { + final assetIds = invocation.positionalArguments[0] as List; + capturedCalls.add(List.from(assetIds)); + return assetIds.map((id) => HashResult(assetId: id, hash: '$id-hash')).toList(); + }); await sut.hashAssets(); - verify(() => mockNativeApi.hashPaths(['path-1'])).called(1); - verify(() => mockNativeApi.hashPaths(['path-2'])).called(1); + expect(capturedCalls.length, 2, reason: 'Should make exactly 2 calls to hashAssets'); + expect(capturedCalls[0], [asset1.id, asset2.id], reason: 'First call should batch the first two assets'); + expect(capturedCalls[1], [asset3.id], reason: 'Second call should have the remaining asset'); + verify(() => mockAssetRepo.updateHashes(any())).called(2); }); @@ -206,27 +147,43 @@ void main() { final album = LocalAlbumStub.recent; final asset1 = LocalAssetStub.image1; final asset2 = LocalAssetStub.image2; - final mockFile1 = MockFile(); - final mockFile2 = MockFile(); - when(() => mockFile1.length()).thenAnswer((_) async => 100); - when(() => mockFile1.path).thenReturn('path-1'); - when(() => mockFile2.length()).thenAnswer((_) async => 100); - when(() => mockFile2.path).thenReturn('path-2'); - when(() => mockAlbumRepo.getAll(sortBy: sortBy)).thenAnswer((_) async => [album]); + when(() => mockAlbumRepo.getBackupAlbums()).thenAnswer((_) async => [album]); when(() => mockAlbumRepo.getAssetsToHash(album.id)).thenAnswer((_) async => [asset1, asset2]); - when(() => mockStorageRepo.getFileForAsset(asset1.id)).thenAnswer((_) async => mockFile1); - when(() => mockStorageRepo.getFileForAsset(asset2.id)).thenAnswer((_) async => mockFile2); - - final validHash = Uint8List.fromList(List.generate(20, (i) => i)); - when(() => mockNativeApi.hashPaths(['path-1', 'path-2'])).thenAnswer((_) async => [validHash, null]); - when(() => mockAssetRepo.updateHashes(any())).thenAnswer((_) async => {}); + when(() => mockNativeApi.hashAssets([asset1.id, asset2.id], allowNetworkAccess: false)).thenAnswer( + (_) async => [ + HashResult(assetId: asset1.id, hash: 'asset1-hash'), + HashResult(assetId: asset2.id, error: 'Failed to hash asset2'), + ], + ); await sut.hashAssets(); - final captured = verify(() => mockAssetRepo.updateHashes(captureAny())).captured.first as List; + final captured = verify(() => mockAssetRepo.updateHashes(captureAny())).captured.first as Map; expect(captured.length, 1); - expect(captured.first.id, asset1.id); + expect(captured[asset1.id], 'asset1-hash'); + }); + + test('uses allowNetworkAccess based on album backup selection', () async { + final selectedAlbum = LocalAlbumStub.recent.copyWith(backupSelection: BackupSelection.selected); + final nonSelectedAlbum = LocalAlbumStub.recent.copyWith(id: 'album2', backupSelection: BackupSelection.excluded); + final asset1 = LocalAssetStub.image1; + final asset2 = LocalAssetStub.image2; + + when(() => mockAlbumRepo.getBackupAlbums()).thenAnswer((_) async => [selectedAlbum, nonSelectedAlbum]); + when(() => mockAlbumRepo.getAssetsToHash(selectedAlbum.id)).thenAnswer((_) async => [asset1]); + when(() => mockAlbumRepo.getAssetsToHash(nonSelectedAlbum.id)).thenAnswer((_) async => [asset2]); + when(() => mockNativeApi.hashAssets(any(), allowNetworkAccess: any(named: 'allowNetworkAccess'))).thenAnswer(( + invocation, + ) async { + final assetIds = invocation.positionalArguments[0] as List; + return assetIds.map((id) => HashResult(assetId: id, hash: '$id-hash')).toList(); + }); + + await sut.hashAssets(); + + verify(() => mockNativeApi.hashAssets([asset1.id], allowNetworkAccess: true)).called(1); + verify(() => mockNativeApi.hashAssets([asset2.id], allowNetworkAccess: false)).called(1); }); }); } diff --git a/mobile/test/drift/main/generated/schema.dart b/mobile/test/drift/main/generated/schema.dart index 413b4408c4..073a86078f 100644 --- a/mobile/test/drift/main/generated/schema.dart +++ b/mobile/test/drift/main/generated/schema.dart @@ -12,6 +12,9 @@ import 'schema_v6.dart' as v6; import 'schema_v7.dart' as v7; import 'schema_v8.dart' as v8; import 'schema_v9.dart' as v9; +import 'schema_v10.dart' as v10; +import 'schema_v11.dart' as v11; +import 'schema_v12.dart' as v12; class GeneratedHelper implements SchemaInstantiationHelper { @override @@ -35,10 +38,16 @@ class GeneratedHelper implements SchemaInstantiationHelper { return v8.DatabaseAtV8(db); case 9: return v9.DatabaseAtV9(db); + case 10: + return v10.DatabaseAtV10(db); + case 11: + return v11.DatabaseAtV11(db); + case 12: + return v12.DatabaseAtV12(db); default: throw MissingSchemaException(version, versions); } } - static const versions = const [1, 2, 3, 4, 5, 6, 7, 8, 9]; + static const versions = const [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; } diff --git a/mobile/test/drift/main/generated/schema_v10.dart b/mobile/test/drift/main/generated/schema_v10.dart new file mode 100644 index 0000000000..ba75530242 --- /dev/null +++ b/mobile/test/drift/main/generated/schema_v10.dart @@ -0,0 +1,7159 @@ +// dart format width=80 +// GENERATED CODE, DO NOT EDIT BY HAND. +// ignore_for_file: type=lint +import 'package:drift/drift.dart'; + +class UserEntity extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + UserEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn email = GeneratedColumn( + 'email', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn hasProfileImage = GeneratedColumn( + 'has_profile_image', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("has_profile_image" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn profileChangedAt = + GeneratedColumn( + 'profile_changed_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn avatarColor = GeneratedColumn( + 'avatar_color', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0'), + ); + @override + List get $columns => [ + id, + name, + email, + hasProfileImage, + profileChangedAt, + avatarColor, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'user_entity'; + @override + Set get $primaryKey => {id}; + @override + UserEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return UserEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + email: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}email'], + )!, + hasProfileImage: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}has_profile_image'], + )!, + profileChangedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}profile_changed_at'], + )!, + avatarColor: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}avatar_color'], + )!, + ); + } + + @override + UserEntity createAlias(String alias) { + return UserEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class UserEntityData extends DataClass implements Insertable { + final String id; + final String name; + final String email; + final bool hasProfileImage; + final DateTime profileChangedAt; + final int avatarColor; + const UserEntityData({ + required this.id, + required this.name, + required this.email, + required this.hasProfileImage, + required this.profileChangedAt, + required this.avatarColor, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + map['email'] = Variable(email); + map['has_profile_image'] = Variable(hasProfileImage); + map['profile_changed_at'] = Variable(profileChangedAt); + map['avatar_color'] = Variable(avatarColor); + return map; + } + + factory UserEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return UserEntityData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + email: serializer.fromJson(json['email']), + hasProfileImage: serializer.fromJson(json['hasProfileImage']), + profileChangedAt: serializer.fromJson(json['profileChangedAt']), + avatarColor: serializer.fromJson(json['avatarColor']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'email': serializer.toJson(email), + 'hasProfileImage': serializer.toJson(hasProfileImage), + 'profileChangedAt': serializer.toJson(profileChangedAt), + 'avatarColor': serializer.toJson(avatarColor), + }; + } + + UserEntityData copyWith({ + String? id, + String? name, + String? email, + bool? hasProfileImage, + DateTime? profileChangedAt, + int? avatarColor, + }) => UserEntityData( + id: id ?? this.id, + name: name ?? this.name, + email: email ?? this.email, + hasProfileImage: hasProfileImage ?? this.hasProfileImage, + profileChangedAt: profileChangedAt ?? this.profileChangedAt, + avatarColor: avatarColor ?? this.avatarColor, + ); + UserEntityData copyWithCompanion(UserEntityCompanion data) { + return UserEntityData( + id: data.id.present ? data.id.value : this.id, + name: data.name.present ? data.name.value : this.name, + email: data.email.present ? data.email.value : this.email, + hasProfileImage: data.hasProfileImage.present + ? data.hasProfileImage.value + : this.hasProfileImage, + profileChangedAt: data.profileChangedAt.present + ? data.profileChangedAt.value + : this.profileChangedAt, + avatarColor: data.avatarColor.present + ? data.avatarColor.value + : this.avatarColor, + ); + } + + @override + String toString() { + return (StringBuffer('UserEntityData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('email: $email, ') + ..write('hasProfileImage: $hasProfileImage, ') + ..write('profileChangedAt: $profileChangedAt, ') + ..write('avatarColor: $avatarColor') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + name, + email, + hasProfileImage, + profileChangedAt, + avatarColor, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is UserEntityData && + other.id == this.id && + other.name == this.name && + other.email == this.email && + other.hasProfileImage == this.hasProfileImage && + other.profileChangedAt == this.profileChangedAt && + other.avatarColor == this.avatarColor); +} + +class UserEntityCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value email; + final Value hasProfileImage; + final Value profileChangedAt; + final Value avatarColor; + const UserEntityCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.email = const Value.absent(), + this.hasProfileImage = const Value.absent(), + this.profileChangedAt = const Value.absent(), + this.avatarColor = const Value.absent(), + }); + UserEntityCompanion.insert({ + required String id, + required String name, + required String email, + this.hasProfileImage = const Value.absent(), + this.profileChangedAt = const Value.absent(), + this.avatarColor = const Value.absent(), + }) : id = Value(id), + name = Value(name), + email = Value(email); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? email, + Expression? hasProfileImage, + Expression? profileChangedAt, + Expression? avatarColor, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (email != null) 'email': email, + if (hasProfileImage != null) 'has_profile_image': hasProfileImage, + if (profileChangedAt != null) 'profile_changed_at': profileChangedAt, + if (avatarColor != null) 'avatar_color': avatarColor, + }); + } + + UserEntityCompanion copyWith({ + Value? id, + Value? name, + Value? email, + Value? hasProfileImage, + Value? profileChangedAt, + Value? avatarColor, + }) { + return UserEntityCompanion( + id: id ?? this.id, + name: name ?? this.name, + email: email ?? this.email, + hasProfileImage: hasProfileImage ?? this.hasProfileImage, + profileChangedAt: profileChangedAt ?? this.profileChangedAt, + avatarColor: avatarColor ?? this.avatarColor, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (email.present) { + map['email'] = Variable(email.value); + } + if (hasProfileImage.present) { + map['has_profile_image'] = Variable(hasProfileImage.value); + } + if (profileChangedAt.present) { + map['profile_changed_at'] = Variable(profileChangedAt.value); + } + if (avatarColor.present) { + map['avatar_color'] = Variable(avatarColor.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('UserEntityCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('email: $email, ') + ..write('hasProfileImage: $hasProfileImage, ') + ..write('profileChangedAt: $profileChangedAt, ') + ..write('avatarColor: $avatarColor') + ..write(')')) + .toString(); + } +} + +class RemoteAssetEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RemoteAssetEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn type = GeneratedColumn( + 'type', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn width = GeneratedColumn( + 'width', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn height = GeneratedColumn( + 'height', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn durationInSeconds = GeneratedColumn( + 'duration_in_seconds', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn checksum = GeneratedColumn( + 'checksum', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn isFavorite = GeneratedColumn( + 'is_favorite', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_favorite" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn ownerId = GeneratedColumn( + 'owner_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn localDateTime = + GeneratedColumn( + 'local_date_time', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn thumbHash = GeneratedColumn( + 'thumb_hash', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn deletedAt = GeneratedColumn( + 'deleted_at', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn livePhotoVideoId = GeneratedColumn( + 'live_photo_video_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn visibility = GeneratedColumn( + 'visibility', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn stackId = GeneratedColumn( + 'stack_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn libraryId = GeneratedColumn( + 'library_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + @override + List get $columns => [ + name, + type, + createdAt, + updatedAt, + width, + height, + durationInSeconds, + id, + checksum, + isFavorite, + ownerId, + localDateTime, + thumbHash, + deletedAt, + livePhotoVideoId, + visibility, + stackId, + libraryId, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'remote_asset_entity'; + @override + Set get $primaryKey => {id}; + @override + RemoteAssetEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RemoteAssetEntityData( + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + type: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}type'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + width: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}width'], + ), + height: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}height'], + ), + durationInSeconds: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}duration_in_seconds'], + ), + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + checksum: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}checksum'], + )!, + isFavorite: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_favorite'], + )!, + ownerId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}owner_id'], + )!, + localDateTime: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}local_date_time'], + ), + thumbHash: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}thumb_hash'], + ), + deletedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}deleted_at'], + ), + livePhotoVideoId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}live_photo_video_id'], + ), + visibility: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}visibility'], + )!, + stackId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}stack_id'], + ), + libraryId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}library_id'], + ), + ); + } + + @override + RemoteAssetEntity createAlias(String alias) { + return RemoteAssetEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class RemoteAssetEntityData extends DataClass + implements Insertable { + final String name; + final int type; + final DateTime createdAt; + final DateTime updatedAt; + final int? width; + final int? height; + final int? durationInSeconds; + final String id; + final String checksum; + final bool isFavorite; + final String ownerId; + final DateTime? localDateTime; + final String? thumbHash; + final DateTime? deletedAt; + final String? livePhotoVideoId; + final int visibility; + final String? stackId; + final String? libraryId; + const RemoteAssetEntityData({ + required this.name, + required this.type, + required this.createdAt, + required this.updatedAt, + this.width, + this.height, + this.durationInSeconds, + required this.id, + required this.checksum, + required this.isFavorite, + required this.ownerId, + this.localDateTime, + this.thumbHash, + this.deletedAt, + this.livePhotoVideoId, + required this.visibility, + this.stackId, + this.libraryId, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['name'] = Variable(name); + map['type'] = Variable(type); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || width != null) { + map['width'] = Variable(width); + } + if (!nullToAbsent || height != null) { + map['height'] = Variable(height); + } + if (!nullToAbsent || durationInSeconds != null) { + map['duration_in_seconds'] = Variable(durationInSeconds); + } + map['id'] = Variable(id); + map['checksum'] = Variable(checksum); + map['is_favorite'] = Variable(isFavorite); + map['owner_id'] = Variable(ownerId); + if (!nullToAbsent || localDateTime != null) { + map['local_date_time'] = Variable(localDateTime); + } + if (!nullToAbsent || thumbHash != null) { + map['thumb_hash'] = Variable(thumbHash); + } + if (!nullToAbsent || deletedAt != null) { + map['deleted_at'] = Variable(deletedAt); + } + if (!nullToAbsent || livePhotoVideoId != null) { + map['live_photo_video_id'] = Variable(livePhotoVideoId); + } + map['visibility'] = Variable(visibility); + if (!nullToAbsent || stackId != null) { + map['stack_id'] = Variable(stackId); + } + if (!nullToAbsent || libraryId != null) { + map['library_id'] = Variable(libraryId); + } + return map; + } + + factory RemoteAssetEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RemoteAssetEntityData( + name: serializer.fromJson(json['name']), + type: serializer.fromJson(json['type']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + width: serializer.fromJson(json['width']), + height: serializer.fromJson(json['height']), + durationInSeconds: serializer.fromJson(json['durationInSeconds']), + id: serializer.fromJson(json['id']), + checksum: serializer.fromJson(json['checksum']), + isFavorite: serializer.fromJson(json['isFavorite']), + ownerId: serializer.fromJson(json['ownerId']), + localDateTime: serializer.fromJson(json['localDateTime']), + thumbHash: serializer.fromJson(json['thumbHash']), + deletedAt: serializer.fromJson(json['deletedAt']), + livePhotoVideoId: serializer.fromJson(json['livePhotoVideoId']), + visibility: serializer.fromJson(json['visibility']), + stackId: serializer.fromJson(json['stackId']), + libraryId: serializer.fromJson(json['libraryId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'name': serializer.toJson(name), + 'type': serializer.toJson(type), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'width': serializer.toJson(width), + 'height': serializer.toJson(height), + 'durationInSeconds': serializer.toJson(durationInSeconds), + 'id': serializer.toJson(id), + 'checksum': serializer.toJson(checksum), + 'isFavorite': serializer.toJson(isFavorite), + 'ownerId': serializer.toJson(ownerId), + 'localDateTime': serializer.toJson(localDateTime), + 'thumbHash': serializer.toJson(thumbHash), + 'deletedAt': serializer.toJson(deletedAt), + 'livePhotoVideoId': serializer.toJson(livePhotoVideoId), + 'visibility': serializer.toJson(visibility), + 'stackId': serializer.toJson(stackId), + 'libraryId': serializer.toJson(libraryId), + }; + } + + RemoteAssetEntityData copyWith({ + String? name, + int? type, + DateTime? createdAt, + DateTime? updatedAt, + Value width = const Value.absent(), + Value height = const Value.absent(), + Value durationInSeconds = const Value.absent(), + String? id, + String? checksum, + bool? isFavorite, + String? ownerId, + Value localDateTime = const Value.absent(), + Value thumbHash = const Value.absent(), + Value deletedAt = const Value.absent(), + Value livePhotoVideoId = const Value.absent(), + int? visibility, + Value stackId = const Value.absent(), + Value libraryId = const Value.absent(), + }) => RemoteAssetEntityData( + name: name ?? this.name, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + width: width.present ? width.value : this.width, + height: height.present ? height.value : this.height, + durationInSeconds: durationInSeconds.present + ? durationInSeconds.value + : this.durationInSeconds, + id: id ?? this.id, + checksum: checksum ?? this.checksum, + isFavorite: isFavorite ?? this.isFavorite, + ownerId: ownerId ?? this.ownerId, + localDateTime: localDateTime.present + ? localDateTime.value + : this.localDateTime, + thumbHash: thumbHash.present ? thumbHash.value : this.thumbHash, + deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt, + livePhotoVideoId: livePhotoVideoId.present + ? livePhotoVideoId.value + : this.livePhotoVideoId, + visibility: visibility ?? this.visibility, + stackId: stackId.present ? stackId.value : this.stackId, + libraryId: libraryId.present ? libraryId.value : this.libraryId, + ); + RemoteAssetEntityData copyWithCompanion(RemoteAssetEntityCompanion data) { + return RemoteAssetEntityData( + name: data.name.present ? data.name.value : this.name, + type: data.type.present ? data.type.value : this.type, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + width: data.width.present ? data.width.value : this.width, + height: data.height.present ? data.height.value : this.height, + durationInSeconds: data.durationInSeconds.present + ? data.durationInSeconds.value + : this.durationInSeconds, + id: data.id.present ? data.id.value : this.id, + checksum: data.checksum.present ? data.checksum.value : this.checksum, + isFavorite: data.isFavorite.present + ? data.isFavorite.value + : this.isFavorite, + ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId, + localDateTime: data.localDateTime.present + ? data.localDateTime.value + : this.localDateTime, + thumbHash: data.thumbHash.present ? data.thumbHash.value : this.thumbHash, + deletedAt: data.deletedAt.present ? data.deletedAt.value : this.deletedAt, + livePhotoVideoId: data.livePhotoVideoId.present + ? data.livePhotoVideoId.value + : this.livePhotoVideoId, + visibility: data.visibility.present + ? data.visibility.value + : this.visibility, + stackId: data.stackId.present ? data.stackId.value : this.stackId, + libraryId: data.libraryId.present ? data.libraryId.value : this.libraryId, + ); + } + + @override + String toString() { + return (StringBuffer('RemoteAssetEntityData(') + ..write('name: $name, ') + ..write('type: $type, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('width: $width, ') + ..write('height: $height, ') + ..write('durationInSeconds: $durationInSeconds, ') + ..write('id: $id, ') + ..write('checksum: $checksum, ') + ..write('isFavorite: $isFavorite, ') + ..write('ownerId: $ownerId, ') + ..write('localDateTime: $localDateTime, ') + ..write('thumbHash: $thumbHash, ') + ..write('deletedAt: $deletedAt, ') + ..write('livePhotoVideoId: $livePhotoVideoId, ') + ..write('visibility: $visibility, ') + ..write('stackId: $stackId, ') + ..write('libraryId: $libraryId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + name, + type, + createdAt, + updatedAt, + width, + height, + durationInSeconds, + id, + checksum, + isFavorite, + ownerId, + localDateTime, + thumbHash, + deletedAt, + livePhotoVideoId, + visibility, + stackId, + libraryId, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RemoteAssetEntityData && + other.name == this.name && + other.type == this.type && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.width == this.width && + other.height == this.height && + other.durationInSeconds == this.durationInSeconds && + other.id == this.id && + other.checksum == this.checksum && + other.isFavorite == this.isFavorite && + other.ownerId == this.ownerId && + other.localDateTime == this.localDateTime && + other.thumbHash == this.thumbHash && + other.deletedAt == this.deletedAt && + other.livePhotoVideoId == this.livePhotoVideoId && + other.visibility == this.visibility && + other.stackId == this.stackId && + other.libraryId == this.libraryId); +} + +class RemoteAssetEntityCompanion + extends UpdateCompanion { + final Value name; + final Value type; + final Value createdAt; + final Value updatedAt; + final Value width; + final Value height; + final Value durationInSeconds; + final Value id; + final Value checksum; + final Value isFavorite; + final Value ownerId; + final Value localDateTime; + final Value thumbHash; + final Value deletedAt; + final Value livePhotoVideoId; + final Value visibility; + final Value stackId; + final Value libraryId; + const RemoteAssetEntityCompanion({ + this.name = const Value.absent(), + this.type = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.width = const Value.absent(), + this.height = const Value.absent(), + this.durationInSeconds = const Value.absent(), + this.id = const Value.absent(), + this.checksum = const Value.absent(), + this.isFavorite = const Value.absent(), + this.ownerId = const Value.absent(), + this.localDateTime = const Value.absent(), + this.thumbHash = const Value.absent(), + this.deletedAt = const Value.absent(), + this.livePhotoVideoId = const Value.absent(), + this.visibility = const Value.absent(), + this.stackId = const Value.absent(), + this.libraryId = const Value.absent(), + }); + RemoteAssetEntityCompanion.insert({ + required String name, + required int type, + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.width = const Value.absent(), + this.height = const Value.absent(), + this.durationInSeconds = const Value.absent(), + required String id, + required String checksum, + this.isFavorite = const Value.absent(), + required String ownerId, + this.localDateTime = const Value.absent(), + this.thumbHash = const Value.absent(), + this.deletedAt = const Value.absent(), + this.livePhotoVideoId = const Value.absent(), + required int visibility, + this.stackId = const Value.absent(), + this.libraryId = const Value.absent(), + }) : name = Value(name), + type = Value(type), + id = Value(id), + checksum = Value(checksum), + ownerId = Value(ownerId), + visibility = Value(visibility); + static Insertable custom({ + Expression? name, + Expression? type, + Expression? createdAt, + Expression? updatedAt, + Expression? width, + Expression? height, + Expression? durationInSeconds, + Expression? id, + Expression? checksum, + Expression? isFavorite, + Expression? ownerId, + Expression? localDateTime, + Expression? thumbHash, + Expression? deletedAt, + Expression? livePhotoVideoId, + Expression? visibility, + Expression? stackId, + Expression? libraryId, + }) { + return RawValuesInsertable({ + if (name != null) 'name': name, + if (type != null) 'type': type, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (width != null) 'width': width, + if (height != null) 'height': height, + if (durationInSeconds != null) 'duration_in_seconds': durationInSeconds, + if (id != null) 'id': id, + if (checksum != null) 'checksum': checksum, + if (isFavorite != null) 'is_favorite': isFavorite, + if (ownerId != null) 'owner_id': ownerId, + if (localDateTime != null) 'local_date_time': localDateTime, + if (thumbHash != null) 'thumb_hash': thumbHash, + if (deletedAt != null) 'deleted_at': deletedAt, + if (livePhotoVideoId != null) 'live_photo_video_id': livePhotoVideoId, + if (visibility != null) 'visibility': visibility, + if (stackId != null) 'stack_id': stackId, + if (libraryId != null) 'library_id': libraryId, + }); + } + + RemoteAssetEntityCompanion copyWith({ + Value? name, + Value? type, + Value? createdAt, + Value? updatedAt, + Value? width, + Value? height, + Value? durationInSeconds, + Value? id, + Value? checksum, + Value? isFavorite, + Value? ownerId, + Value? localDateTime, + Value? thumbHash, + Value? deletedAt, + Value? livePhotoVideoId, + Value? visibility, + Value? stackId, + Value? libraryId, + }) { + return RemoteAssetEntityCompanion( + name: name ?? this.name, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + width: width ?? this.width, + height: height ?? this.height, + durationInSeconds: durationInSeconds ?? this.durationInSeconds, + id: id ?? this.id, + checksum: checksum ?? this.checksum, + isFavorite: isFavorite ?? this.isFavorite, + ownerId: ownerId ?? this.ownerId, + localDateTime: localDateTime ?? this.localDateTime, + thumbHash: thumbHash ?? this.thumbHash, + deletedAt: deletedAt ?? this.deletedAt, + livePhotoVideoId: livePhotoVideoId ?? this.livePhotoVideoId, + visibility: visibility ?? this.visibility, + stackId: stackId ?? this.stackId, + libraryId: libraryId ?? this.libraryId, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (name.present) { + map['name'] = Variable(name.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (width.present) { + map['width'] = Variable(width.value); + } + if (height.present) { + map['height'] = Variable(height.value); + } + if (durationInSeconds.present) { + map['duration_in_seconds'] = Variable(durationInSeconds.value); + } + if (id.present) { + map['id'] = Variable(id.value); + } + if (checksum.present) { + map['checksum'] = Variable(checksum.value); + } + if (isFavorite.present) { + map['is_favorite'] = Variable(isFavorite.value); + } + if (ownerId.present) { + map['owner_id'] = Variable(ownerId.value); + } + if (localDateTime.present) { + map['local_date_time'] = Variable(localDateTime.value); + } + if (thumbHash.present) { + map['thumb_hash'] = Variable(thumbHash.value); + } + if (deletedAt.present) { + map['deleted_at'] = Variable(deletedAt.value); + } + if (livePhotoVideoId.present) { + map['live_photo_video_id'] = Variable(livePhotoVideoId.value); + } + if (visibility.present) { + map['visibility'] = Variable(visibility.value); + } + if (stackId.present) { + map['stack_id'] = Variable(stackId.value); + } + if (libraryId.present) { + map['library_id'] = Variable(libraryId.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RemoteAssetEntityCompanion(') + ..write('name: $name, ') + ..write('type: $type, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('width: $width, ') + ..write('height: $height, ') + ..write('durationInSeconds: $durationInSeconds, ') + ..write('id: $id, ') + ..write('checksum: $checksum, ') + ..write('isFavorite: $isFavorite, ') + ..write('ownerId: $ownerId, ') + ..write('localDateTime: $localDateTime, ') + ..write('thumbHash: $thumbHash, ') + ..write('deletedAt: $deletedAt, ') + ..write('livePhotoVideoId: $livePhotoVideoId, ') + ..write('visibility: $visibility, ') + ..write('stackId: $stackId, ') + ..write('libraryId: $libraryId') + ..write(')')) + .toString(); + } +} + +class StackEntity extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + StackEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn ownerId = GeneratedColumn( + 'owner_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn primaryAssetId = GeneratedColumn( + 'primary_asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + ownerId, + primaryAssetId, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'stack_entity'; + @override + Set get $primaryKey => {id}; + @override + StackEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return StackEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + ownerId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}owner_id'], + )!, + primaryAssetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}primary_asset_id'], + )!, + ); + } + + @override + StackEntity createAlias(String alias) { + return StackEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class StackEntityData extends DataClass implements Insertable { + final String id; + final DateTime createdAt; + final DateTime updatedAt; + final String ownerId; + final String primaryAssetId; + const StackEntityData({ + required this.id, + required this.createdAt, + required this.updatedAt, + required this.ownerId, + required this.primaryAssetId, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + map['owner_id'] = Variable(ownerId); + map['primary_asset_id'] = Variable(primaryAssetId); + return map; + } + + factory StackEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return StackEntityData( + id: serializer.fromJson(json['id']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + ownerId: serializer.fromJson(json['ownerId']), + primaryAssetId: serializer.fromJson(json['primaryAssetId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'ownerId': serializer.toJson(ownerId), + 'primaryAssetId': serializer.toJson(primaryAssetId), + }; + } + + StackEntityData copyWith({ + String? id, + DateTime? createdAt, + DateTime? updatedAt, + String? ownerId, + String? primaryAssetId, + }) => StackEntityData( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + primaryAssetId: primaryAssetId ?? this.primaryAssetId, + ); + StackEntityData copyWithCompanion(StackEntityCompanion data) { + return StackEntityData( + id: data.id.present ? data.id.value : this.id, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId, + primaryAssetId: data.primaryAssetId.present + ? data.primaryAssetId.value + : this.primaryAssetId, + ); + } + + @override + String toString() { + return (StringBuffer('StackEntityData(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('primaryAssetId: $primaryAssetId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => + Object.hash(id, createdAt, updatedAt, ownerId, primaryAssetId); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is StackEntityData && + other.id == this.id && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.ownerId == this.ownerId && + other.primaryAssetId == this.primaryAssetId); +} + +class StackEntityCompanion extends UpdateCompanion { + final Value id; + final Value createdAt; + final Value updatedAt; + final Value ownerId; + final Value primaryAssetId; + const StackEntityCompanion({ + this.id = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.ownerId = const Value.absent(), + this.primaryAssetId = const Value.absent(), + }); + StackEntityCompanion.insert({ + required String id, + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + required String ownerId, + required String primaryAssetId, + }) : id = Value(id), + ownerId = Value(ownerId), + primaryAssetId = Value(primaryAssetId); + static Insertable custom({ + Expression? id, + Expression? createdAt, + Expression? updatedAt, + Expression? ownerId, + Expression? primaryAssetId, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (ownerId != null) 'owner_id': ownerId, + if (primaryAssetId != null) 'primary_asset_id': primaryAssetId, + }); + } + + StackEntityCompanion copyWith({ + Value? id, + Value? createdAt, + Value? updatedAt, + Value? ownerId, + Value? primaryAssetId, + }) { + return StackEntityCompanion( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + primaryAssetId: primaryAssetId ?? this.primaryAssetId, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (ownerId.present) { + map['owner_id'] = Variable(ownerId.value); + } + if (primaryAssetId.present) { + map['primary_asset_id'] = Variable(primaryAssetId.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('StackEntityCompanion(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('primaryAssetId: $primaryAssetId') + ..write(')')) + .toString(); + } +} + +class LocalAssetEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + LocalAssetEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn type = GeneratedColumn( + 'type', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn width = GeneratedColumn( + 'width', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn height = GeneratedColumn( + 'height', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn durationInSeconds = GeneratedColumn( + 'duration_in_seconds', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn checksum = GeneratedColumn( + 'checksum', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn isFavorite = GeneratedColumn( + 'is_favorite', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_favorite" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn orientation = GeneratedColumn( + 'orientation', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0'), + ); + @override + List get $columns => [ + name, + type, + createdAt, + updatedAt, + width, + height, + durationInSeconds, + id, + checksum, + isFavorite, + orientation, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'local_asset_entity'; + @override + Set get $primaryKey => {id}; + @override + LocalAssetEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return LocalAssetEntityData( + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + type: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}type'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + width: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}width'], + ), + height: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}height'], + ), + durationInSeconds: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}duration_in_seconds'], + ), + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + checksum: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}checksum'], + ), + isFavorite: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_favorite'], + )!, + orientation: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}orientation'], + )!, + ); + } + + @override + LocalAssetEntity createAlias(String alias) { + return LocalAssetEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class LocalAssetEntityData extends DataClass + implements Insertable { + final String name; + final int type; + final DateTime createdAt; + final DateTime updatedAt; + final int? width; + final int? height; + final int? durationInSeconds; + final String id; + final String? checksum; + final bool isFavorite; + final int orientation; + const LocalAssetEntityData({ + required this.name, + required this.type, + required this.createdAt, + required this.updatedAt, + this.width, + this.height, + this.durationInSeconds, + required this.id, + this.checksum, + required this.isFavorite, + required this.orientation, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['name'] = Variable(name); + map['type'] = Variable(type); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || width != null) { + map['width'] = Variable(width); + } + if (!nullToAbsent || height != null) { + map['height'] = Variable(height); + } + if (!nullToAbsent || durationInSeconds != null) { + map['duration_in_seconds'] = Variable(durationInSeconds); + } + map['id'] = Variable(id); + if (!nullToAbsent || checksum != null) { + map['checksum'] = Variable(checksum); + } + map['is_favorite'] = Variable(isFavorite); + map['orientation'] = Variable(orientation); + return map; + } + + factory LocalAssetEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return LocalAssetEntityData( + name: serializer.fromJson(json['name']), + type: serializer.fromJson(json['type']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + width: serializer.fromJson(json['width']), + height: serializer.fromJson(json['height']), + durationInSeconds: serializer.fromJson(json['durationInSeconds']), + id: serializer.fromJson(json['id']), + checksum: serializer.fromJson(json['checksum']), + isFavorite: serializer.fromJson(json['isFavorite']), + orientation: serializer.fromJson(json['orientation']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'name': serializer.toJson(name), + 'type': serializer.toJson(type), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'width': serializer.toJson(width), + 'height': serializer.toJson(height), + 'durationInSeconds': serializer.toJson(durationInSeconds), + 'id': serializer.toJson(id), + 'checksum': serializer.toJson(checksum), + 'isFavorite': serializer.toJson(isFavorite), + 'orientation': serializer.toJson(orientation), + }; + } + + LocalAssetEntityData copyWith({ + String? name, + int? type, + DateTime? createdAt, + DateTime? updatedAt, + Value width = const Value.absent(), + Value height = const Value.absent(), + Value durationInSeconds = const Value.absent(), + String? id, + Value checksum = const Value.absent(), + bool? isFavorite, + int? orientation, + }) => LocalAssetEntityData( + name: name ?? this.name, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + width: width.present ? width.value : this.width, + height: height.present ? height.value : this.height, + durationInSeconds: durationInSeconds.present + ? durationInSeconds.value + : this.durationInSeconds, + id: id ?? this.id, + checksum: checksum.present ? checksum.value : this.checksum, + isFavorite: isFavorite ?? this.isFavorite, + orientation: orientation ?? this.orientation, + ); + LocalAssetEntityData copyWithCompanion(LocalAssetEntityCompanion data) { + return LocalAssetEntityData( + name: data.name.present ? data.name.value : this.name, + type: data.type.present ? data.type.value : this.type, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + width: data.width.present ? data.width.value : this.width, + height: data.height.present ? data.height.value : this.height, + durationInSeconds: data.durationInSeconds.present + ? data.durationInSeconds.value + : this.durationInSeconds, + id: data.id.present ? data.id.value : this.id, + checksum: data.checksum.present ? data.checksum.value : this.checksum, + isFavorite: data.isFavorite.present + ? data.isFavorite.value + : this.isFavorite, + orientation: data.orientation.present + ? data.orientation.value + : this.orientation, + ); + } + + @override + String toString() { + return (StringBuffer('LocalAssetEntityData(') + ..write('name: $name, ') + ..write('type: $type, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('width: $width, ') + ..write('height: $height, ') + ..write('durationInSeconds: $durationInSeconds, ') + ..write('id: $id, ') + ..write('checksum: $checksum, ') + ..write('isFavorite: $isFavorite, ') + ..write('orientation: $orientation') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + name, + type, + createdAt, + updatedAt, + width, + height, + durationInSeconds, + id, + checksum, + isFavorite, + orientation, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is LocalAssetEntityData && + other.name == this.name && + other.type == this.type && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.width == this.width && + other.height == this.height && + other.durationInSeconds == this.durationInSeconds && + other.id == this.id && + other.checksum == this.checksum && + other.isFavorite == this.isFavorite && + other.orientation == this.orientation); +} + +class LocalAssetEntityCompanion extends UpdateCompanion { + final Value name; + final Value type; + final Value createdAt; + final Value updatedAt; + final Value width; + final Value height; + final Value durationInSeconds; + final Value id; + final Value checksum; + final Value isFavorite; + final Value orientation; + const LocalAssetEntityCompanion({ + this.name = const Value.absent(), + this.type = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.width = const Value.absent(), + this.height = const Value.absent(), + this.durationInSeconds = const Value.absent(), + this.id = const Value.absent(), + this.checksum = const Value.absent(), + this.isFavorite = const Value.absent(), + this.orientation = const Value.absent(), + }); + LocalAssetEntityCompanion.insert({ + required String name, + required int type, + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.width = const Value.absent(), + this.height = const Value.absent(), + this.durationInSeconds = const Value.absent(), + required String id, + this.checksum = const Value.absent(), + this.isFavorite = const Value.absent(), + this.orientation = const Value.absent(), + }) : name = Value(name), + type = Value(type), + id = Value(id); + static Insertable custom({ + Expression? name, + Expression? type, + Expression? createdAt, + Expression? updatedAt, + Expression? width, + Expression? height, + Expression? durationInSeconds, + Expression? id, + Expression? checksum, + Expression? isFavorite, + Expression? orientation, + }) { + return RawValuesInsertable({ + if (name != null) 'name': name, + if (type != null) 'type': type, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (width != null) 'width': width, + if (height != null) 'height': height, + if (durationInSeconds != null) 'duration_in_seconds': durationInSeconds, + if (id != null) 'id': id, + if (checksum != null) 'checksum': checksum, + if (isFavorite != null) 'is_favorite': isFavorite, + if (orientation != null) 'orientation': orientation, + }); + } + + LocalAssetEntityCompanion copyWith({ + Value? name, + Value? type, + Value? createdAt, + Value? updatedAt, + Value? width, + Value? height, + Value? durationInSeconds, + Value? id, + Value? checksum, + Value? isFavorite, + Value? orientation, + }) { + return LocalAssetEntityCompanion( + name: name ?? this.name, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + width: width ?? this.width, + height: height ?? this.height, + durationInSeconds: durationInSeconds ?? this.durationInSeconds, + id: id ?? this.id, + checksum: checksum ?? this.checksum, + isFavorite: isFavorite ?? this.isFavorite, + orientation: orientation ?? this.orientation, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (name.present) { + map['name'] = Variable(name.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (width.present) { + map['width'] = Variable(width.value); + } + if (height.present) { + map['height'] = Variable(height.value); + } + if (durationInSeconds.present) { + map['duration_in_seconds'] = Variable(durationInSeconds.value); + } + if (id.present) { + map['id'] = Variable(id.value); + } + if (checksum.present) { + map['checksum'] = Variable(checksum.value); + } + if (isFavorite.present) { + map['is_favorite'] = Variable(isFavorite.value); + } + if (orientation.present) { + map['orientation'] = Variable(orientation.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('LocalAssetEntityCompanion(') + ..write('name: $name, ') + ..write('type: $type, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('width: $width, ') + ..write('height: $height, ') + ..write('durationInSeconds: $durationInSeconds, ') + ..write('id: $id, ') + ..write('checksum: $checksum, ') + ..write('isFavorite: $isFavorite, ') + ..write('orientation: $orientation') + ..write(')')) + .toString(); + } +} + +class RemoteAlbumEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RemoteAlbumEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn description = GeneratedColumn( + 'description', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'\''), + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn ownerId = GeneratedColumn( + 'owner_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn thumbnailAssetId = GeneratedColumn( + 'thumbnail_asset_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_asset_entity (id) ON DELETE SET NULL', + ), + ); + late final GeneratedColumn isActivityEnabled = GeneratedColumn( + 'is_activity_enabled', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_activity_enabled" IN (0, 1))', + ), + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn order = GeneratedColumn( + 'order', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + @override + List get $columns => [ + id, + name, + description, + createdAt, + updatedAt, + ownerId, + thumbnailAssetId, + isActivityEnabled, + order, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'remote_album_entity'; + @override + Set get $primaryKey => {id}; + @override + RemoteAlbumEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RemoteAlbumEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + description: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}description'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + ownerId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}owner_id'], + )!, + thumbnailAssetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}thumbnail_asset_id'], + ), + isActivityEnabled: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_activity_enabled'], + )!, + order: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}order'], + )!, + ); + } + + @override + RemoteAlbumEntity createAlias(String alias) { + return RemoteAlbumEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class RemoteAlbumEntityData extends DataClass + implements Insertable { + final String id; + final String name; + final String description; + final DateTime createdAt; + final DateTime updatedAt; + final String ownerId; + final String? thumbnailAssetId; + final bool isActivityEnabled; + final int order; + const RemoteAlbumEntityData({ + required this.id, + required this.name, + required this.description, + required this.createdAt, + required this.updatedAt, + required this.ownerId, + this.thumbnailAssetId, + required this.isActivityEnabled, + required this.order, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + map['description'] = Variable(description); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + map['owner_id'] = Variable(ownerId); + if (!nullToAbsent || thumbnailAssetId != null) { + map['thumbnail_asset_id'] = Variable(thumbnailAssetId); + } + map['is_activity_enabled'] = Variable(isActivityEnabled); + map['order'] = Variable(order); + return map; + } + + factory RemoteAlbumEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RemoteAlbumEntityData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + description: serializer.fromJson(json['description']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + ownerId: serializer.fromJson(json['ownerId']), + thumbnailAssetId: serializer.fromJson(json['thumbnailAssetId']), + isActivityEnabled: serializer.fromJson(json['isActivityEnabled']), + order: serializer.fromJson(json['order']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'description': serializer.toJson(description), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'ownerId': serializer.toJson(ownerId), + 'thumbnailAssetId': serializer.toJson(thumbnailAssetId), + 'isActivityEnabled': serializer.toJson(isActivityEnabled), + 'order': serializer.toJson(order), + }; + } + + RemoteAlbumEntityData copyWith({ + String? id, + String? name, + String? description, + DateTime? createdAt, + DateTime? updatedAt, + String? ownerId, + Value thumbnailAssetId = const Value.absent(), + bool? isActivityEnabled, + int? order, + }) => RemoteAlbumEntityData( + id: id ?? this.id, + name: name ?? this.name, + description: description ?? this.description, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + thumbnailAssetId: thumbnailAssetId.present + ? thumbnailAssetId.value + : this.thumbnailAssetId, + isActivityEnabled: isActivityEnabled ?? this.isActivityEnabled, + order: order ?? this.order, + ); + RemoteAlbumEntityData copyWithCompanion(RemoteAlbumEntityCompanion data) { + return RemoteAlbumEntityData( + id: data.id.present ? data.id.value : this.id, + name: data.name.present ? data.name.value : this.name, + description: data.description.present + ? data.description.value + : this.description, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId, + thumbnailAssetId: data.thumbnailAssetId.present + ? data.thumbnailAssetId.value + : this.thumbnailAssetId, + isActivityEnabled: data.isActivityEnabled.present + ? data.isActivityEnabled.value + : this.isActivityEnabled, + order: data.order.present ? data.order.value : this.order, + ); + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumEntityData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('description: $description, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('thumbnailAssetId: $thumbnailAssetId, ') + ..write('isActivityEnabled: $isActivityEnabled, ') + ..write('order: $order') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + name, + description, + createdAt, + updatedAt, + ownerId, + thumbnailAssetId, + isActivityEnabled, + order, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RemoteAlbumEntityData && + other.id == this.id && + other.name == this.name && + other.description == this.description && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.ownerId == this.ownerId && + other.thumbnailAssetId == this.thumbnailAssetId && + other.isActivityEnabled == this.isActivityEnabled && + other.order == this.order); +} + +class RemoteAlbumEntityCompanion + extends UpdateCompanion { + final Value id; + final Value name; + final Value description; + final Value createdAt; + final Value updatedAt; + final Value ownerId; + final Value thumbnailAssetId; + final Value isActivityEnabled; + final Value order; + const RemoteAlbumEntityCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.description = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.ownerId = const Value.absent(), + this.thumbnailAssetId = const Value.absent(), + this.isActivityEnabled = const Value.absent(), + this.order = const Value.absent(), + }); + RemoteAlbumEntityCompanion.insert({ + required String id, + required String name, + this.description = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + required String ownerId, + this.thumbnailAssetId = const Value.absent(), + this.isActivityEnabled = const Value.absent(), + required int order, + }) : id = Value(id), + name = Value(name), + ownerId = Value(ownerId), + order = Value(order); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? description, + Expression? createdAt, + Expression? updatedAt, + Expression? ownerId, + Expression? thumbnailAssetId, + Expression? isActivityEnabled, + Expression? order, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (description != null) 'description': description, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (ownerId != null) 'owner_id': ownerId, + if (thumbnailAssetId != null) 'thumbnail_asset_id': thumbnailAssetId, + if (isActivityEnabled != null) 'is_activity_enabled': isActivityEnabled, + if (order != null) 'order': order, + }); + } + + RemoteAlbumEntityCompanion copyWith({ + Value? id, + Value? name, + Value? description, + Value? createdAt, + Value? updatedAt, + Value? ownerId, + Value? thumbnailAssetId, + Value? isActivityEnabled, + Value? order, + }) { + return RemoteAlbumEntityCompanion( + id: id ?? this.id, + name: name ?? this.name, + description: description ?? this.description, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + thumbnailAssetId: thumbnailAssetId ?? this.thumbnailAssetId, + isActivityEnabled: isActivityEnabled ?? this.isActivityEnabled, + order: order ?? this.order, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (description.present) { + map['description'] = Variable(description.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (ownerId.present) { + map['owner_id'] = Variable(ownerId.value); + } + if (thumbnailAssetId.present) { + map['thumbnail_asset_id'] = Variable(thumbnailAssetId.value); + } + if (isActivityEnabled.present) { + map['is_activity_enabled'] = Variable(isActivityEnabled.value); + } + if (order.present) { + map['order'] = Variable(order.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumEntityCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('description: $description, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('thumbnailAssetId: $thumbnailAssetId, ') + ..write('isActivityEnabled: $isActivityEnabled, ') + ..write('order: $order') + ..write(')')) + .toString(); + } +} + +class LocalAlbumEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + LocalAlbumEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn backupSelection = GeneratedColumn( + 'backup_selection', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn isIosSharedAlbum = GeneratedColumn( + 'is_ios_shared_album', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_ios_shared_album" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn linkedRemoteAlbumId = + GeneratedColumn( + 'linked_remote_album_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_album_entity (id) ON DELETE SET NULL', + ), + ); + late final GeneratedColumn marker_ = GeneratedColumn( + 'marker', + aliasedName, + true, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("marker" IN (0, 1))', + ), + ); + @override + List get $columns => [ + id, + name, + updatedAt, + backupSelection, + isIosSharedAlbum, + linkedRemoteAlbumId, + marker_, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'local_album_entity'; + @override + Set get $primaryKey => {id}; + @override + LocalAlbumEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return LocalAlbumEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + backupSelection: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}backup_selection'], + )!, + isIosSharedAlbum: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_ios_shared_album'], + )!, + linkedRemoteAlbumId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}linked_remote_album_id'], + ), + marker_: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}marker'], + ), + ); + } + + @override + LocalAlbumEntity createAlias(String alias) { + return LocalAlbumEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class LocalAlbumEntityData extends DataClass + implements Insertable { + final String id; + final String name; + final DateTime updatedAt; + final int backupSelection; + final bool isIosSharedAlbum; + final String? linkedRemoteAlbumId; + final bool? marker_; + const LocalAlbumEntityData({ + required this.id, + required this.name, + required this.updatedAt, + required this.backupSelection, + required this.isIosSharedAlbum, + this.linkedRemoteAlbumId, + this.marker_, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + map['updated_at'] = Variable(updatedAt); + map['backup_selection'] = Variable(backupSelection); + map['is_ios_shared_album'] = Variable(isIosSharedAlbum); + if (!nullToAbsent || linkedRemoteAlbumId != null) { + map['linked_remote_album_id'] = Variable(linkedRemoteAlbumId); + } + if (!nullToAbsent || marker_ != null) { + map['marker'] = Variable(marker_); + } + return map; + } + + factory LocalAlbumEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return LocalAlbumEntityData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + updatedAt: serializer.fromJson(json['updatedAt']), + backupSelection: serializer.fromJson(json['backupSelection']), + isIosSharedAlbum: serializer.fromJson(json['isIosSharedAlbum']), + linkedRemoteAlbumId: serializer.fromJson( + json['linkedRemoteAlbumId'], + ), + marker_: serializer.fromJson(json['marker_']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'updatedAt': serializer.toJson(updatedAt), + 'backupSelection': serializer.toJson(backupSelection), + 'isIosSharedAlbum': serializer.toJson(isIosSharedAlbum), + 'linkedRemoteAlbumId': serializer.toJson(linkedRemoteAlbumId), + 'marker_': serializer.toJson(marker_), + }; + } + + LocalAlbumEntityData copyWith({ + String? id, + String? name, + DateTime? updatedAt, + int? backupSelection, + bool? isIosSharedAlbum, + Value linkedRemoteAlbumId = const Value.absent(), + Value marker_ = const Value.absent(), + }) => LocalAlbumEntityData( + id: id ?? this.id, + name: name ?? this.name, + updatedAt: updatedAt ?? this.updatedAt, + backupSelection: backupSelection ?? this.backupSelection, + isIosSharedAlbum: isIosSharedAlbum ?? this.isIosSharedAlbum, + linkedRemoteAlbumId: linkedRemoteAlbumId.present + ? linkedRemoteAlbumId.value + : this.linkedRemoteAlbumId, + marker_: marker_.present ? marker_.value : this.marker_, + ); + LocalAlbumEntityData copyWithCompanion(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, + backupSelection: data.backupSelection.present + ? data.backupSelection.value + : this.backupSelection, + isIosSharedAlbum: data.isIosSharedAlbum.present + ? data.isIosSharedAlbum.value + : this.isIosSharedAlbum, + linkedRemoteAlbumId: data.linkedRemoteAlbumId.present + ? data.linkedRemoteAlbumId.value + : this.linkedRemoteAlbumId, + marker_: data.marker_.present ? data.marker_.value : this.marker_, + ); + } + + @override + String toString() { + return (StringBuffer('LocalAlbumEntityData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('updatedAt: $updatedAt, ') + ..write('backupSelection: $backupSelection, ') + ..write('isIosSharedAlbum: $isIosSharedAlbum, ') + ..write('linkedRemoteAlbumId: $linkedRemoteAlbumId, ') + ..write('marker_: $marker_') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + name, + updatedAt, + backupSelection, + isIosSharedAlbum, + linkedRemoteAlbumId, + marker_, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is LocalAlbumEntityData && + other.id == this.id && + other.name == this.name && + other.updatedAt == this.updatedAt && + other.backupSelection == this.backupSelection && + other.isIosSharedAlbum == this.isIosSharedAlbum && + other.linkedRemoteAlbumId == this.linkedRemoteAlbumId && + other.marker_ == this.marker_); +} + +class LocalAlbumEntityCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value updatedAt; + final Value backupSelection; + final Value isIosSharedAlbum; + final Value linkedRemoteAlbumId; + final Value marker_; + const LocalAlbumEntityCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.updatedAt = const Value.absent(), + this.backupSelection = const Value.absent(), + this.isIosSharedAlbum = const Value.absent(), + this.linkedRemoteAlbumId = const Value.absent(), + this.marker_ = const Value.absent(), + }); + LocalAlbumEntityCompanion.insert({ + required String id, + required String name, + this.updatedAt = const Value.absent(), + required int backupSelection, + this.isIosSharedAlbum = const Value.absent(), + this.linkedRemoteAlbumId = const Value.absent(), + this.marker_ = const Value.absent(), + }) : id = Value(id), + name = Value(name), + backupSelection = Value(backupSelection); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? updatedAt, + Expression? backupSelection, + Expression? isIosSharedAlbum, + Expression? linkedRemoteAlbumId, + Expression? marker_, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (updatedAt != null) 'updated_at': updatedAt, + if (backupSelection != null) 'backup_selection': backupSelection, + if (isIosSharedAlbum != null) 'is_ios_shared_album': isIosSharedAlbum, + if (linkedRemoteAlbumId != null) + 'linked_remote_album_id': linkedRemoteAlbumId, + if (marker_ != null) 'marker': marker_, + }); + } + + LocalAlbumEntityCompanion copyWith({ + Value? id, + Value? name, + Value? updatedAt, + Value? backupSelection, + Value? isIosSharedAlbum, + Value? linkedRemoteAlbumId, + Value? marker_, + }) { + return LocalAlbumEntityCompanion( + id: id ?? this.id, + name: name ?? this.name, + updatedAt: updatedAt ?? this.updatedAt, + backupSelection: backupSelection ?? this.backupSelection, + isIosSharedAlbum: isIosSharedAlbum ?? this.isIosSharedAlbum, + linkedRemoteAlbumId: linkedRemoteAlbumId ?? this.linkedRemoteAlbumId, + marker_: marker_ ?? this.marker_, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (backupSelection.present) { + map['backup_selection'] = Variable(backupSelection.value); + } + if (isIosSharedAlbum.present) { + map['is_ios_shared_album'] = Variable(isIosSharedAlbum.value); + } + if (linkedRemoteAlbumId.present) { + map['linked_remote_album_id'] = Variable( + linkedRemoteAlbumId.value, + ); + } + if (marker_.present) { + map['marker'] = Variable(marker_.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('LocalAlbumEntityCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('updatedAt: $updatedAt, ') + ..write('backupSelection: $backupSelection, ') + ..write('isIosSharedAlbum: $isIosSharedAlbum, ') + ..write('linkedRemoteAlbumId: $linkedRemoteAlbumId, ') + ..write('marker_: $marker_') + ..write(')')) + .toString(); + } +} + +class LocalAlbumAssetEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + LocalAlbumAssetEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn assetId = GeneratedColumn( + 'asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES local_asset_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn albumId = GeneratedColumn( + 'album_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES local_album_entity (id) ON DELETE CASCADE', + ), + ); + @override + List get $columns => [assetId, albumId]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'local_album_asset_entity'; + @override + Set get $primaryKey => {assetId, albumId}; + @override + LocalAlbumAssetEntityData map( + Map data, { + String? tablePrefix, + }) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return LocalAlbumAssetEntityData( + assetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}asset_id'], + )!, + albumId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}album_id'], + )!, + ); + } + + @override + LocalAlbumAssetEntity createAlias(String alias) { + return LocalAlbumAssetEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class LocalAlbumAssetEntityData extends DataClass + implements Insertable { + final String assetId; + final String albumId; + const LocalAlbumAssetEntityData({ + required this.assetId, + required this.albumId, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['asset_id'] = Variable(assetId); + map['album_id'] = Variable(albumId); + return map; + } + + factory LocalAlbumAssetEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return LocalAlbumAssetEntityData( + assetId: serializer.fromJson(json['assetId']), + albumId: serializer.fromJson(json['albumId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'assetId': serializer.toJson(assetId), + 'albumId': serializer.toJson(albumId), + }; + } + + LocalAlbumAssetEntityData copyWith({String? assetId, String? albumId}) => + LocalAlbumAssetEntityData( + assetId: assetId ?? this.assetId, + albumId: albumId ?? this.albumId, + ); + LocalAlbumAssetEntityData copyWithCompanion( + LocalAlbumAssetEntityCompanion data, + ) { + return LocalAlbumAssetEntityData( + assetId: data.assetId.present ? data.assetId.value : this.assetId, + albumId: data.albumId.present ? data.albumId.value : this.albumId, + ); + } + + @override + String toString() { + return (StringBuffer('LocalAlbumAssetEntityData(') + ..write('assetId: $assetId, ') + ..write('albumId: $albumId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(assetId, albumId); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is LocalAlbumAssetEntityData && + other.assetId == this.assetId && + other.albumId == this.albumId); +} + +class LocalAlbumAssetEntityCompanion + extends UpdateCompanion { + final Value assetId; + final Value albumId; + const LocalAlbumAssetEntityCompanion({ + this.assetId = const Value.absent(), + this.albumId = const Value.absent(), + }); + LocalAlbumAssetEntityCompanion.insert({ + required String assetId, + required String albumId, + }) : assetId = Value(assetId), + albumId = Value(albumId); + static Insertable custom({ + Expression? assetId, + Expression? albumId, + }) { + return RawValuesInsertable({ + if (assetId != null) 'asset_id': assetId, + if (albumId != null) 'album_id': albumId, + }); + } + + LocalAlbumAssetEntityCompanion copyWith({ + Value? assetId, + Value? albumId, + }) { + return LocalAlbumAssetEntityCompanion( + assetId: assetId ?? this.assetId, + albumId: albumId ?? this.albumId, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (assetId.present) { + map['asset_id'] = Variable(assetId.value); + } + if (albumId.present) { + map['album_id'] = Variable(albumId.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('LocalAlbumAssetEntityCompanion(') + ..write('assetId: $assetId, ') + ..write('albumId: $albumId') + ..write(')')) + .toString(); + } +} + +class AuthUserEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + AuthUserEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn email = GeneratedColumn( + 'email', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn isAdmin = GeneratedColumn( + 'is_admin', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_admin" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn hasProfileImage = GeneratedColumn( + 'has_profile_image', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("has_profile_image" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn profileChangedAt = + GeneratedColumn( + 'profile_changed_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn avatarColor = GeneratedColumn( + 'avatar_color', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn quotaSizeInBytes = GeneratedColumn( + 'quota_size_in_bytes', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn quotaUsageInBytes = GeneratedColumn( + 'quota_usage_in_bytes', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn pinCode = GeneratedColumn( + 'pin_code', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + @override + List get $columns => [ + id, + name, + email, + isAdmin, + hasProfileImage, + profileChangedAt, + avatarColor, + quotaSizeInBytes, + quotaUsageInBytes, + pinCode, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'auth_user_entity'; + @override + Set get $primaryKey => {id}; + @override + AuthUserEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return AuthUserEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + email: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}email'], + )!, + isAdmin: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_admin'], + )!, + hasProfileImage: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}has_profile_image'], + )!, + profileChangedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}profile_changed_at'], + )!, + avatarColor: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}avatar_color'], + )!, + quotaSizeInBytes: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}quota_size_in_bytes'], + )!, + quotaUsageInBytes: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}quota_usage_in_bytes'], + )!, + pinCode: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}pin_code'], + ), + ); + } + + @override + AuthUserEntity createAlias(String alias) { + return AuthUserEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class AuthUserEntityData extends DataClass + implements Insertable { + final String id; + final String name; + final String email; + final bool isAdmin; + final bool hasProfileImage; + final DateTime profileChangedAt; + final int avatarColor; + final int quotaSizeInBytes; + final int quotaUsageInBytes; + final String? pinCode; + const AuthUserEntityData({ + required this.id, + required this.name, + required this.email, + required this.isAdmin, + required this.hasProfileImage, + required this.profileChangedAt, + required this.avatarColor, + required this.quotaSizeInBytes, + required this.quotaUsageInBytes, + this.pinCode, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + map['email'] = Variable(email); + map['is_admin'] = Variable(isAdmin); + map['has_profile_image'] = Variable(hasProfileImage); + map['profile_changed_at'] = Variable(profileChangedAt); + map['avatar_color'] = Variable(avatarColor); + map['quota_size_in_bytes'] = Variable(quotaSizeInBytes); + map['quota_usage_in_bytes'] = Variable(quotaUsageInBytes); + if (!nullToAbsent || pinCode != null) { + map['pin_code'] = Variable(pinCode); + } + return map; + } + + factory AuthUserEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return AuthUserEntityData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + email: serializer.fromJson(json['email']), + isAdmin: serializer.fromJson(json['isAdmin']), + hasProfileImage: serializer.fromJson(json['hasProfileImage']), + profileChangedAt: serializer.fromJson(json['profileChangedAt']), + avatarColor: serializer.fromJson(json['avatarColor']), + quotaSizeInBytes: serializer.fromJson(json['quotaSizeInBytes']), + quotaUsageInBytes: serializer.fromJson(json['quotaUsageInBytes']), + pinCode: serializer.fromJson(json['pinCode']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'email': serializer.toJson(email), + 'isAdmin': serializer.toJson(isAdmin), + 'hasProfileImage': serializer.toJson(hasProfileImage), + 'profileChangedAt': serializer.toJson(profileChangedAt), + 'avatarColor': serializer.toJson(avatarColor), + 'quotaSizeInBytes': serializer.toJson(quotaSizeInBytes), + 'quotaUsageInBytes': serializer.toJson(quotaUsageInBytes), + 'pinCode': serializer.toJson(pinCode), + }; + } + + AuthUserEntityData copyWith({ + String? id, + String? name, + String? email, + bool? isAdmin, + bool? hasProfileImage, + DateTime? profileChangedAt, + int? avatarColor, + int? quotaSizeInBytes, + int? quotaUsageInBytes, + Value pinCode = const Value.absent(), + }) => AuthUserEntityData( + id: id ?? this.id, + name: name ?? this.name, + email: email ?? this.email, + isAdmin: isAdmin ?? this.isAdmin, + hasProfileImage: hasProfileImage ?? this.hasProfileImage, + profileChangedAt: profileChangedAt ?? this.profileChangedAt, + avatarColor: avatarColor ?? this.avatarColor, + quotaSizeInBytes: quotaSizeInBytes ?? this.quotaSizeInBytes, + quotaUsageInBytes: quotaUsageInBytes ?? this.quotaUsageInBytes, + pinCode: pinCode.present ? pinCode.value : this.pinCode, + ); + AuthUserEntityData copyWithCompanion(AuthUserEntityCompanion data) { + return AuthUserEntityData( + id: data.id.present ? data.id.value : this.id, + name: data.name.present ? data.name.value : this.name, + email: data.email.present ? data.email.value : this.email, + isAdmin: data.isAdmin.present ? data.isAdmin.value : this.isAdmin, + hasProfileImage: data.hasProfileImage.present + ? data.hasProfileImage.value + : this.hasProfileImage, + profileChangedAt: data.profileChangedAt.present + ? data.profileChangedAt.value + : this.profileChangedAt, + avatarColor: data.avatarColor.present + ? data.avatarColor.value + : this.avatarColor, + quotaSizeInBytes: data.quotaSizeInBytes.present + ? data.quotaSizeInBytes.value + : this.quotaSizeInBytes, + quotaUsageInBytes: data.quotaUsageInBytes.present + ? data.quotaUsageInBytes.value + : this.quotaUsageInBytes, + pinCode: data.pinCode.present ? data.pinCode.value : this.pinCode, + ); + } + + @override + String toString() { + return (StringBuffer('AuthUserEntityData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('email: $email, ') + ..write('isAdmin: $isAdmin, ') + ..write('hasProfileImage: $hasProfileImage, ') + ..write('profileChangedAt: $profileChangedAt, ') + ..write('avatarColor: $avatarColor, ') + ..write('quotaSizeInBytes: $quotaSizeInBytes, ') + ..write('quotaUsageInBytes: $quotaUsageInBytes, ') + ..write('pinCode: $pinCode') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + name, + email, + isAdmin, + hasProfileImage, + profileChangedAt, + avatarColor, + quotaSizeInBytes, + quotaUsageInBytes, + pinCode, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is AuthUserEntityData && + other.id == this.id && + other.name == this.name && + other.email == this.email && + other.isAdmin == this.isAdmin && + other.hasProfileImage == this.hasProfileImage && + other.profileChangedAt == this.profileChangedAt && + other.avatarColor == this.avatarColor && + other.quotaSizeInBytes == this.quotaSizeInBytes && + other.quotaUsageInBytes == this.quotaUsageInBytes && + other.pinCode == this.pinCode); +} + +class AuthUserEntityCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value email; + final Value isAdmin; + final Value hasProfileImage; + final Value profileChangedAt; + final Value avatarColor; + final Value quotaSizeInBytes; + final Value quotaUsageInBytes; + final Value pinCode; + const AuthUserEntityCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.email = const Value.absent(), + this.isAdmin = const Value.absent(), + this.hasProfileImage = const Value.absent(), + this.profileChangedAt = const Value.absent(), + this.avatarColor = const Value.absent(), + this.quotaSizeInBytes = const Value.absent(), + this.quotaUsageInBytes = const Value.absent(), + this.pinCode = const Value.absent(), + }); + AuthUserEntityCompanion.insert({ + required String id, + required String name, + required String email, + this.isAdmin = const Value.absent(), + this.hasProfileImage = const Value.absent(), + this.profileChangedAt = const Value.absent(), + required int avatarColor, + this.quotaSizeInBytes = const Value.absent(), + this.quotaUsageInBytes = const Value.absent(), + this.pinCode = const Value.absent(), + }) : id = Value(id), + name = Value(name), + email = Value(email), + avatarColor = Value(avatarColor); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? email, + Expression? isAdmin, + Expression? hasProfileImage, + Expression? profileChangedAt, + Expression? avatarColor, + Expression? quotaSizeInBytes, + Expression? quotaUsageInBytes, + Expression? pinCode, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (email != null) 'email': email, + if (isAdmin != null) 'is_admin': isAdmin, + if (hasProfileImage != null) 'has_profile_image': hasProfileImage, + if (profileChangedAt != null) 'profile_changed_at': profileChangedAt, + if (avatarColor != null) 'avatar_color': avatarColor, + if (quotaSizeInBytes != null) 'quota_size_in_bytes': quotaSizeInBytes, + if (quotaUsageInBytes != null) 'quota_usage_in_bytes': quotaUsageInBytes, + if (pinCode != null) 'pin_code': pinCode, + }); + } + + AuthUserEntityCompanion copyWith({ + Value? id, + Value? name, + Value? email, + Value? isAdmin, + Value? hasProfileImage, + Value? profileChangedAt, + Value? avatarColor, + Value? quotaSizeInBytes, + Value? quotaUsageInBytes, + Value? pinCode, + }) { + return AuthUserEntityCompanion( + id: id ?? this.id, + name: name ?? this.name, + email: email ?? this.email, + isAdmin: isAdmin ?? this.isAdmin, + hasProfileImage: hasProfileImage ?? this.hasProfileImage, + profileChangedAt: profileChangedAt ?? this.profileChangedAt, + avatarColor: avatarColor ?? this.avatarColor, + quotaSizeInBytes: quotaSizeInBytes ?? this.quotaSizeInBytes, + quotaUsageInBytes: quotaUsageInBytes ?? this.quotaUsageInBytes, + pinCode: pinCode ?? this.pinCode, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (email.present) { + map['email'] = Variable(email.value); + } + if (isAdmin.present) { + map['is_admin'] = Variable(isAdmin.value); + } + if (hasProfileImage.present) { + map['has_profile_image'] = Variable(hasProfileImage.value); + } + if (profileChangedAt.present) { + map['profile_changed_at'] = Variable(profileChangedAt.value); + } + if (avatarColor.present) { + map['avatar_color'] = Variable(avatarColor.value); + } + if (quotaSizeInBytes.present) { + map['quota_size_in_bytes'] = Variable(quotaSizeInBytes.value); + } + if (quotaUsageInBytes.present) { + map['quota_usage_in_bytes'] = Variable(quotaUsageInBytes.value); + } + if (pinCode.present) { + map['pin_code'] = Variable(pinCode.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('AuthUserEntityCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('email: $email, ') + ..write('isAdmin: $isAdmin, ') + ..write('hasProfileImage: $hasProfileImage, ') + ..write('profileChangedAt: $profileChangedAt, ') + ..write('avatarColor: $avatarColor, ') + ..write('quotaSizeInBytes: $quotaSizeInBytes, ') + ..write('quotaUsageInBytes: $quotaUsageInBytes, ') + ..write('pinCode: $pinCode') + ..write(')')) + .toString(); + } +} + +class UserMetadataEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + UserMetadataEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn key = GeneratedColumn( + 'key', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn value = GeneratedColumn( + 'value', + aliasedName, + false, + type: DriftSqlType.blob, + requiredDuringInsert: true, + ); + @override + List get $columns => [userId, key, value]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'user_metadata_entity'; + @override + Set get $primaryKey => {userId, key}; + @override + UserMetadataEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return UserMetadataEntityData( + userId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}user_id'], + )!, + key: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}key'], + )!, + value: attachedDatabase.typeMapping.read( + DriftSqlType.blob, + data['${effectivePrefix}value'], + )!, + ); + } + + @override + UserMetadataEntity createAlias(String alias) { + return UserMetadataEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class UserMetadataEntityData extends DataClass + implements Insertable { + final String userId; + final int key; + final Uint8List value; + const UserMetadataEntityData({ + required this.userId, + required this.key, + required this.value, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['user_id'] = Variable(userId); + map['key'] = Variable(key); + map['value'] = Variable(value); + return map; + } + + factory UserMetadataEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return UserMetadataEntityData( + userId: serializer.fromJson(json['userId']), + key: serializer.fromJson(json['key']), + value: serializer.fromJson(json['value']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'userId': serializer.toJson(userId), + 'key': serializer.toJson(key), + 'value': serializer.toJson(value), + }; + } + + UserMetadataEntityData copyWith({ + String? userId, + int? key, + Uint8List? value, + }) => UserMetadataEntityData( + userId: userId ?? this.userId, + key: key ?? this.key, + value: value ?? this.value, + ); + UserMetadataEntityData copyWithCompanion(UserMetadataEntityCompanion data) { + return UserMetadataEntityData( + userId: data.userId.present ? data.userId.value : this.userId, + key: data.key.present ? data.key.value : this.key, + value: data.value.present ? data.value.value : this.value, + ); + } + + @override + String toString() { + return (StringBuffer('UserMetadataEntityData(') + ..write('userId: $userId, ') + ..write('key: $key, ') + ..write('value: $value') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(userId, key, $driftBlobEquality.hash(value)); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is UserMetadataEntityData && + other.userId == this.userId && + other.key == this.key && + $driftBlobEquality.equals(other.value, this.value)); +} + +class UserMetadataEntityCompanion + extends UpdateCompanion { + final Value userId; + final Value key; + final Value value; + const UserMetadataEntityCompanion({ + this.userId = const Value.absent(), + this.key = const Value.absent(), + this.value = const Value.absent(), + }); + UserMetadataEntityCompanion.insert({ + required String userId, + required int key, + required Uint8List value, + }) : userId = Value(userId), + key = Value(key), + value = Value(value); + static Insertable custom({ + Expression? userId, + Expression? key, + Expression? value, + }) { + return RawValuesInsertable({ + if (userId != null) 'user_id': userId, + if (key != null) 'key': key, + if (value != null) 'value': value, + }); + } + + UserMetadataEntityCompanion copyWith({ + Value? userId, + Value? key, + Value? value, + }) { + return UserMetadataEntityCompanion( + userId: userId ?? this.userId, + key: key ?? this.key, + value: value ?? this.value, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (key.present) { + map['key'] = Variable(key.value); + } + if (value.present) { + map['value'] = Variable(value.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('UserMetadataEntityCompanion(') + ..write('userId: $userId, ') + ..write('key: $key, ') + ..write('value: $value') + ..write(')')) + .toString(); + } +} + +class PartnerEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + PartnerEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn sharedById = GeneratedColumn( + 'shared_by_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn sharedWithId = GeneratedColumn( + 'shared_with_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn inTimeline = GeneratedColumn( + 'in_timeline', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("in_timeline" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + @override + List get $columns => [sharedById, sharedWithId, inTimeline]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'partner_entity'; + @override + Set get $primaryKey => {sharedById, sharedWithId}; + @override + PartnerEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return PartnerEntityData( + sharedById: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}shared_by_id'], + )!, + sharedWithId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}shared_with_id'], + )!, + inTimeline: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}in_timeline'], + )!, + ); + } + + @override + PartnerEntity createAlias(String alias) { + return PartnerEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class PartnerEntityData extends DataClass + implements Insertable { + final String sharedById; + final String sharedWithId; + final bool inTimeline; + const PartnerEntityData({ + required this.sharedById, + required this.sharedWithId, + required this.inTimeline, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['shared_by_id'] = Variable(sharedById); + map['shared_with_id'] = Variable(sharedWithId); + map['in_timeline'] = Variable(inTimeline); + return map; + } + + factory PartnerEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return PartnerEntityData( + sharedById: serializer.fromJson(json['sharedById']), + sharedWithId: serializer.fromJson(json['sharedWithId']), + inTimeline: serializer.fromJson(json['inTimeline']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'sharedById': serializer.toJson(sharedById), + 'sharedWithId': serializer.toJson(sharedWithId), + 'inTimeline': serializer.toJson(inTimeline), + }; + } + + PartnerEntityData copyWith({ + String? sharedById, + String? sharedWithId, + bool? inTimeline, + }) => PartnerEntityData( + sharedById: sharedById ?? this.sharedById, + sharedWithId: sharedWithId ?? this.sharedWithId, + inTimeline: inTimeline ?? this.inTimeline, + ); + PartnerEntityData copyWithCompanion(PartnerEntityCompanion data) { + return PartnerEntityData( + sharedById: data.sharedById.present + ? data.sharedById.value + : this.sharedById, + sharedWithId: data.sharedWithId.present + ? data.sharedWithId.value + : this.sharedWithId, + inTimeline: data.inTimeline.present + ? data.inTimeline.value + : this.inTimeline, + ); + } + + @override + String toString() { + return (StringBuffer('PartnerEntityData(') + ..write('sharedById: $sharedById, ') + ..write('sharedWithId: $sharedWithId, ') + ..write('inTimeline: $inTimeline') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(sharedById, sharedWithId, inTimeline); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is PartnerEntityData && + other.sharedById == this.sharedById && + other.sharedWithId == this.sharedWithId && + other.inTimeline == this.inTimeline); +} + +class PartnerEntityCompanion extends UpdateCompanion { + final Value sharedById; + final Value sharedWithId; + final Value inTimeline; + const PartnerEntityCompanion({ + this.sharedById = const Value.absent(), + this.sharedWithId = const Value.absent(), + this.inTimeline = const Value.absent(), + }); + PartnerEntityCompanion.insert({ + required String sharedById, + required String sharedWithId, + this.inTimeline = const Value.absent(), + }) : sharedById = Value(sharedById), + sharedWithId = Value(sharedWithId); + static Insertable custom({ + Expression? sharedById, + Expression? sharedWithId, + Expression? inTimeline, + }) { + return RawValuesInsertable({ + if (sharedById != null) 'shared_by_id': sharedById, + if (sharedWithId != null) 'shared_with_id': sharedWithId, + if (inTimeline != null) 'in_timeline': inTimeline, + }); + } + + PartnerEntityCompanion copyWith({ + Value? sharedById, + Value? sharedWithId, + Value? inTimeline, + }) { + return PartnerEntityCompanion( + sharedById: sharedById ?? this.sharedById, + sharedWithId: sharedWithId ?? this.sharedWithId, + inTimeline: inTimeline ?? this.inTimeline, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (sharedById.present) { + map['shared_by_id'] = Variable(sharedById.value); + } + if (sharedWithId.present) { + map['shared_with_id'] = Variable(sharedWithId.value); + } + if (inTimeline.present) { + map['in_timeline'] = Variable(inTimeline.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('PartnerEntityCompanion(') + ..write('sharedById: $sharedById, ') + ..write('sharedWithId: $sharedWithId, ') + ..write('inTimeline: $inTimeline') + ..write(')')) + .toString(); + } +} + +class RemoteExifEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RemoteExifEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn assetId = GeneratedColumn( + 'asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_asset_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn city = GeneratedColumn( + 'city', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn state = GeneratedColumn( + 'state', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn country = GeneratedColumn( + 'country', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn dateTimeOriginal = + GeneratedColumn( + 'date_time_original', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn description = GeneratedColumn( + 'description', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn height = GeneratedColumn( + 'height', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn width = GeneratedColumn( + 'width', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn exposureTime = GeneratedColumn( + 'exposure_time', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn fNumber = GeneratedColumn( + 'f_number', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + ); + late final GeneratedColumn fileSize = GeneratedColumn( + 'file_size', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn focalLength = GeneratedColumn( + 'focal_length', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + ); + late final GeneratedColumn latitude = GeneratedColumn( + 'latitude', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + ); + late final GeneratedColumn longitude = GeneratedColumn( + 'longitude', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + ); + late final GeneratedColumn iso = GeneratedColumn( + 'iso', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn make = GeneratedColumn( + 'make', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn model = GeneratedColumn( + 'model', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn lens = GeneratedColumn( + 'lens', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn orientation = GeneratedColumn( + 'orientation', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn timeZone = GeneratedColumn( + 'time_zone', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn rating = GeneratedColumn( + 'rating', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn projectionType = GeneratedColumn( + 'projection_type', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + @override + List get $columns => [ + assetId, + city, + state, + country, + dateTimeOriginal, + description, + height, + width, + exposureTime, + fNumber, + fileSize, + focalLength, + latitude, + longitude, + iso, + make, + model, + lens, + orientation, + timeZone, + rating, + projectionType, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'remote_exif_entity'; + @override + Set get $primaryKey => {assetId}; + @override + RemoteExifEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RemoteExifEntityData( + assetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}asset_id'], + )!, + city: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}city'], + ), + state: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}state'], + ), + country: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}country'], + ), + dateTimeOriginal: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}date_time_original'], + ), + description: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}description'], + ), + height: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}height'], + ), + width: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}width'], + ), + exposureTime: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}exposure_time'], + ), + fNumber: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}f_number'], + ), + fileSize: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}file_size'], + ), + focalLength: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}focal_length'], + ), + latitude: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}latitude'], + ), + longitude: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}longitude'], + ), + iso: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}iso'], + ), + make: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}make'], + ), + model: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}model'], + ), + lens: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}lens'], + ), + orientation: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}orientation'], + ), + timeZone: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}time_zone'], + ), + rating: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}rating'], + ), + projectionType: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}projection_type'], + ), + ); + } + + @override + RemoteExifEntity createAlias(String alias) { + return RemoteExifEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class RemoteExifEntityData extends DataClass + implements Insertable { + final String assetId; + final String? city; + final String? state; + final String? country; + final DateTime? dateTimeOriginal; + final String? description; + final int? height; + final int? width; + final String? exposureTime; + final double? fNumber; + final int? fileSize; + final double? focalLength; + final double? latitude; + final double? longitude; + final int? iso; + final String? make; + final String? model; + final String? lens; + final String? orientation; + final String? timeZone; + final int? rating; + final String? projectionType; + const RemoteExifEntityData({ + required this.assetId, + this.city, + this.state, + this.country, + this.dateTimeOriginal, + this.description, + this.height, + this.width, + this.exposureTime, + this.fNumber, + this.fileSize, + this.focalLength, + this.latitude, + this.longitude, + this.iso, + this.make, + this.model, + this.lens, + this.orientation, + this.timeZone, + this.rating, + this.projectionType, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['asset_id'] = Variable(assetId); + if (!nullToAbsent || city != null) { + map['city'] = Variable(city); + } + if (!nullToAbsent || state != null) { + map['state'] = Variable(state); + } + if (!nullToAbsent || country != null) { + map['country'] = Variable(country); + } + if (!nullToAbsent || dateTimeOriginal != null) { + map['date_time_original'] = Variable(dateTimeOriginal); + } + if (!nullToAbsent || description != null) { + map['description'] = Variable(description); + } + if (!nullToAbsent || height != null) { + map['height'] = Variable(height); + } + if (!nullToAbsent || width != null) { + map['width'] = Variable(width); + } + if (!nullToAbsent || exposureTime != null) { + map['exposure_time'] = Variable(exposureTime); + } + if (!nullToAbsent || fNumber != null) { + map['f_number'] = Variable(fNumber); + } + if (!nullToAbsent || fileSize != null) { + map['file_size'] = Variable(fileSize); + } + if (!nullToAbsent || focalLength != null) { + map['focal_length'] = Variable(focalLength); + } + if (!nullToAbsent || latitude != null) { + map['latitude'] = Variable(latitude); + } + if (!nullToAbsent || longitude != null) { + map['longitude'] = Variable(longitude); + } + if (!nullToAbsent || iso != null) { + map['iso'] = Variable(iso); + } + if (!nullToAbsent || make != null) { + map['make'] = Variable(make); + } + if (!nullToAbsent || model != null) { + map['model'] = Variable(model); + } + if (!nullToAbsent || lens != null) { + map['lens'] = Variable(lens); + } + if (!nullToAbsent || orientation != null) { + map['orientation'] = Variable(orientation); + } + if (!nullToAbsent || timeZone != null) { + map['time_zone'] = Variable(timeZone); + } + if (!nullToAbsent || rating != null) { + map['rating'] = Variable(rating); + } + if (!nullToAbsent || projectionType != null) { + map['projection_type'] = Variable(projectionType); + } + return map; + } + + factory RemoteExifEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RemoteExifEntityData( + assetId: serializer.fromJson(json['assetId']), + city: serializer.fromJson(json['city']), + state: serializer.fromJson(json['state']), + country: serializer.fromJson(json['country']), + dateTimeOriginal: serializer.fromJson( + json['dateTimeOriginal'], + ), + description: serializer.fromJson(json['description']), + height: serializer.fromJson(json['height']), + width: serializer.fromJson(json['width']), + exposureTime: serializer.fromJson(json['exposureTime']), + fNumber: serializer.fromJson(json['fNumber']), + fileSize: serializer.fromJson(json['fileSize']), + focalLength: serializer.fromJson(json['focalLength']), + latitude: serializer.fromJson(json['latitude']), + longitude: serializer.fromJson(json['longitude']), + iso: serializer.fromJson(json['iso']), + make: serializer.fromJson(json['make']), + model: serializer.fromJson(json['model']), + lens: serializer.fromJson(json['lens']), + orientation: serializer.fromJson(json['orientation']), + timeZone: serializer.fromJson(json['timeZone']), + rating: serializer.fromJson(json['rating']), + projectionType: serializer.fromJson(json['projectionType']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'assetId': serializer.toJson(assetId), + 'city': serializer.toJson(city), + 'state': serializer.toJson(state), + 'country': serializer.toJson(country), + 'dateTimeOriginal': serializer.toJson(dateTimeOriginal), + 'description': serializer.toJson(description), + 'height': serializer.toJson(height), + 'width': serializer.toJson(width), + 'exposureTime': serializer.toJson(exposureTime), + 'fNumber': serializer.toJson(fNumber), + 'fileSize': serializer.toJson(fileSize), + 'focalLength': serializer.toJson(focalLength), + 'latitude': serializer.toJson(latitude), + 'longitude': serializer.toJson(longitude), + 'iso': serializer.toJson(iso), + 'make': serializer.toJson(make), + 'model': serializer.toJson(model), + 'lens': serializer.toJson(lens), + 'orientation': serializer.toJson(orientation), + 'timeZone': serializer.toJson(timeZone), + 'rating': serializer.toJson(rating), + 'projectionType': serializer.toJson(projectionType), + }; + } + + RemoteExifEntityData copyWith({ + String? assetId, + Value city = const Value.absent(), + Value state = const Value.absent(), + Value country = const Value.absent(), + Value dateTimeOriginal = const Value.absent(), + Value description = const Value.absent(), + Value height = const Value.absent(), + Value width = const Value.absent(), + Value exposureTime = const Value.absent(), + Value fNumber = const Value.absent(), + Value fileSize = const Value.absent(), + Value focalLength = const Value.absent(), + Value latitude = const Value.absent(), + Value longitude = const Value.absent(), + Value iso = const Value.absent(), + Value make = const Value.absent(), + Value model = const Value.absent(), + Value lens = const Value.absent(), + Value orientation = const Value.absent(), + Value timeZone = const Value.absent(), + Value rating = const Value.absent(), + Value projectionType = const Value.absent(), + }) => RemoteExifEntityData( + assetId: assetId ?? this.assetId, + city: city.present ? city.value : this.city, + state: state.present ? state.value : this.state, + country: country.present ? country.value : this.country, + dateTimeOriginal: dateTimeOriginal.present + ? dateTimeOriginal.value + : this.dateTimeOriginal, + description: description.present ? description.value : this.description, + height: height.present ? height.value : this.height, + width: width.present ? width.value : this.width, + exposureTime: exposureTime.present ? exposureTime.value : this.exposureTime, + fNumber: fNumber.present ? fNumber.value : this.fNumber, + fileSize: fileSize.present ? fileSize.value : this.fileSize, + focalLength: focalLength.present ? focalLength.value : this.focalLength, + latitude: latitude.present ? latitude.value : this.latitude, + longitude: longitude.present ? longitude.value : this.longitude, + iso: iso.present ? iso.value : this.iso, + make: make.present ? make.value : this.make, + model: model.present ? model.value : this.model, + lens: lens.present ? lens.value : this.lens, + orientation: orientation.present ? orientation.value : this.orientation, + timeZone: timeZone.present ? timeZone.value : this.timeZone, + rating: rating.present ? rating.value : this.rating, + projectionType: projectionType.present + ? projectionType.value + : this.projectionType, + ); + RemoteExifEntityData copyWithCompanion(RemoteExifEntityCompanion data) { + return RemoteExifEntityData( + assetId: data.assetId.present ? data.assetId.value : this.assetId, + city: data.city.present ? data.city.value : this.city, + state: data.state.present ? data.state.value : this.state, + country: data.country.present ? data.country.value : this.country, + dateTimeOriginal: data.dateTimeOriginal.present + ? data.dateTimeOriginal.value + : this.dateTimeOriginal, + description: data.description.present + ? data.description.value + : this.description, + height: data.height.present ? data.height.value : this.height, + width: data.width.present ? data.width.value : this.width, + exposureTime: data.exposureTime.present + ? data.exposureTime.value + : this.exposureTime, + fNumber: data.fNumber.present ? data.fNumber.value : this.fNumber, + fileSize: data.fileSize.present ? data.fileSize.value : this.fileSize, + focalLength: data.focalLength.present + ? data.focalLength.value + : this.focalLength, + latitude: data.latitude.present ? data.latitude.value : this.latitude, + longitude: data.longitude.present ? data.longitude.value : this.longitude, + iso: data.iso.present ? data.iso.value : this.iso, + make: data.make.present ? data.make.value : this.make, + model: data.model.present ? data.model.value : this.model, + lens: data.lens.present ? data.lens.value : this.lens, + orientation: data.orientation.present + ? data.orientation.value + : this.orientation, + timeZone: data.timeZone.present ? data.timeZone.value : this.timeZone, + rating: data.rating.present ? data.rating.value : this.rating, + projectionType: data.projectionType.present + ? data.projectionType.value + : this.projectionType, + ); + } + + @override + String toString() { + return (StringBuffer('RemoteExifEntityData(') + ..write('assetId: $assetId, ') + ..write('city: $city, ') + ..write('state: $state, ') + ..write('country: $country, ') + ..write('dateTimeOriginal: $dateTimeOriginal, ') + ..write('description: $description, ') + ..write('height: $height, ') + ..write('width: $width, ') + ..write('exposureTime: $exposureTime, ') + ..write('fNumber: $fNumber, ') + ..write('fileSize: $fileSize, ') + ..write('focalLength: $focalLength, ') + ..write('latitude: $latitude, ') + ..write('longitude: $longitude, ') + ..write('iso: $iso, ') + ..write('make: $make, ') + ..write('model: $model, ') + ..write('lens: $lens, ') + ..write('orientation: $orientation, ') + ..write('timeZone: $timeZone, ') + ..write('rating: $rating, ') + ..write('projectionType: $projectionType') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hashAll([ + assetId, + city, + state, + country, + dateTimeOriginal, + description, + height, + width, + exposureTime, + fNumber, + fileSize, + focalLength, + latitude, + longitude, + iso, + make, + model, + lens, + orientation, + timeZone, + rating, + projectionType, + ]); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RemoteExifEntityData && + other.assetId == this.assetId && + other.city == this.city && + other.state == this.state && + other.country == this.country && + other.dateTimeOriginal == this.dateTimeOriginal && + other.description == this.description && + other.height == this.height && + other.width == this.width && + other.exposureTime == this.exposureTime && + other.fNumber == this.fNumber && + other.fileSize == this.fileSize && + other.focalLength == this.focalLength && + other.latitude == this.latitude && + other.longitude == this.longitude && + other.iso == this.iso && + other.make == this.make && + other.model == this.model && + other.lens == this.lens && + other.orientation == this.orientation && + other.timeZone == this.timeZone && + other.rating == this.rating && + other.projectionType == this.projectionType); +} + +class RemoteExifEntityCompanion extends UpdateCompanion { + final Value assetId; + final Value city; + final Value state; + final Value country; + final Value dateTimeOriginal; + final Value description; + final Value height; + final Value width; + final Value exposureTime; + final Value fNumber; + final Value fileSize; + final Value focalLength; + final Value latitude; + final Value longitude; + final Value iso; + final Value make; + final Value model; + final Value lens; + final Value orientation; + final Value timeZone; + final Value rating; + final Value projectionType; + const RemoteExifEntityCompanion({ + this.assetId = const Value.absent(), + this.city = const Value.absent(), + this.state = const Value.absent(), + this.country = const Value.absent(), + this.dateTimeOriginal = const Value.absent(), + this.description = const Value.absent(), + this.height = const Value.absent(), + this.width = const Value.absent(), + this.exposureTime = const Value.absent(), + this.fNumber = const Value.absent(), + this.fileSize = const Value.absent(), + this.focalLength = const Value.absent(), + this.latitude = const Value.absent(), + this.longitude = const Value.absent(), + this.iso = const Value.absent(), + this.make = const Value.absent(), + this.model = const Value.absent(), + this.lens = const Value.absent(), + this.orientation = const Value.absent(), + this.timeZone = const Value.absent(), + this.rating = const Value.absent(), + this.projectionType = const Value.absent(), + }); + RemoteExifEntityCompanion.insert({ + required String assetId, + this.city = const Value.absent(), + this.state = const Value.absent(), + this.country = const Value.absent(), + this.dateTimeOriginal = const Value.absent(), + this.description = const Value.absent(), + this.height = const Value.absent(), + this.width = const Value.absent(), + this.exposureTime = const Value.absent(), + this.fNumber = const Value.absent(), + this.fileSize = const Value.absent(), + this.focalLength = const Value.absent(), + this.latitude = const Value.absent(), + this.longitude = const Value.absent(), + this.iso = const Value.absent(), + this.make = const Value.absent(), + this.model = const Value.absent(), + this.lens = const Value.absent(), + this.orientation = const Value.absent(), + this.timeZone = const Value.absent(), + this.rating = const Value.absent(), + this.projectionType = const Value.absent(), + }) : assetId = Value(assetId); + static Insertable custom({ + Expression? assetId, + Expression? city, + Expression? state, + Expression? country, + Expression? dateTimeOriginal, + Expression? description, + Expression? height, + Expression? width, + Expression? exposureTime, + Expression? fNumber, + Expression? fileSize, + Expression? focalLength, + Expression? latitude, + Expression? longitude, + Expression? iso, + Expression? make, + Expression? model, + Expression? lens, + Expression? orientation, + Expression? timeZone, + Expression? rating, + Expression? projectionType, + }) { + return RawValuesInsertable({ + if (assetId != null) 'asset_id': assetId, + if (city != null) 'city': city, + if (state != null) 'state': state, + if (country != null) 'country': country, + if (dateTimeOriginal != null) 'date_time_original': dateTimeOriginal, + if (description != null) 'description': description, + if (height != null) 'height': height, + if (width != null) 'width': width, + if (exposureTime != null) 'exposure_time': exposureTime, + if (fNumber != null) 'f_number': fNumber, + if (fileSize != null) 'file_size': fileSize, + if (focalLength != null) 'focal_length': focalLength, + if (latitude != null) 'latitude': latitude, + if (longitude != null) 'longitude': longitude, + if (iso != null) 'iso': iso, + if (make != null) 'make': make, + if (model != null) 'model': model, + if (lens != null) 'lens': lens, + if (orientation != null) 'orientation': orientation, + if (timeZone != null) 'time_zone': timeZone, + if (rating != null) 'rating': rating, + if (projectionType != null) 'projection_type': projectionType, + }); + } + + RemoteExifEntityCompanion copyWith({ + Value? assetId, + Value? city, + Value? state, + Value? country, + Value? dateTimeOriginal, + Value? description, + Value? height, + Value? width, + Value? exposureTime, + Value? fNumber, + Value? fileSize, + Value? focalLength, + Value? latitude, + Value? longitude, + Value? iso, + Value? make, + Value? model, + Value? lens, + Value? orientation, + Value? timeZone, + Value? rating, + Value? projectionType, + }) { + return RemoteExifEntityCompanion( + assetId: assetId ?? this.assetId, + city: city ?? this.city, + state: state ?? this.state, + country: country ?? this.country, + dateTimeOriginal: dateTimeOriginal ?? this.dateTimeOriginal, + description: description ?? this.description, + height: height ?? this.height, + width: width ?? this.width, + exposureTime: exposureTime ?? this.exposureTime, + fNumber: fNumber ?? this.fNumber, + fileSize: fileSize ?? this.fileSize, + focalLength: focalLength ?? this.focalLength, + latitude: latitude ?? this.latitude, + longitude: longitude ?? this.longitude, + iso: iso ?? this.iso, + make: make ?? this.make, + model: model ?? this.model, + lens: lens ?? this.lens, + orientation: orientation ?? this.orientation, + timeZone: timeZone ?? this.timeZone, + rating: rating ?? this.rating, + projectionType: projectionType ?? this.projectionType, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (assetId.present) { + map['asset_id'] = Variable(assetId.value); + } + if (city.present) { + map['city'] = Variable(city.value); + } + if (state.present) { + map['state'] = Variable(state.value); + } + if (country.present) { + map['country'] = Variable(country.value); + } + if (dateTimeOriginal.present) { + map['date_time_original'] = Variable(dateTimeOriginal.value); + } + if (description.present) { + map['description'] = Variable(description.value); + } + if (height.present) { + map['height'] = Variable(height.value); + } + if (width.present) { + map['width'] = Variable(width.value); + } + if (exposureTime.present) { + map['exposure_time'] = Variable(exposureTime.value); + } + if (fNumber.present) { + map['f_number'] = Variable(fNumber.value); + } + if (fileSize.present) { + map['file_size'] = Variable(fileSize.value); + } + if (focalLength.present) { + map['focal_length'] = Variable(focalLength.value); + } + if (latitude.present) { + map['latitude'] = Variable(latitude.value); + } + if (longitude.present) { + map['longitude'] = Variable(longitude.value); + } + if (iso.present) { + map['iso'] = Variable(iso.value); + } + if (make.present) { + map['make'] = Variable(make.value); + } + if (model.present) { + map['model'] = Variable(model.value); + } + if (lens.present) { + map['lens'] = Variable(lens.value); + } + if (orientation.present) { + map['orientation'] = Variable(orientation.value); + } + if (timeZone.present) { + map['time_zone'] = Variable(timeZone.value); + } + if (rating.present) { + map['rating'] = Variable(rating.value); + } + if (projectionType.present) { + map['projection_type'] = Variable(projectionType.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RemoteExifEntityCompanion(') + ..write('assetId: $assetId, ') + ..write('city: $city, ') + ..write('state: $state, ') + ..write('country: $country, ') + ..write('dateTimeOriginal: $dateTimeOriginal, ') + ..write('description: $description, ') + ..write('height: $height, ') + ..write('width: $width, ') + ..write('exposureTime: $exposureTime, ') + ..write('fNumber: $fNumber, ') + ..write('fileSize: $fileSize, ') + ..write('focalLength: $focalLength, ') + ..write('latitude: $latitude, ') + ..write('longitude: $longitude, ') + ..write('iso: $iso, ') + ..write('make: $make, ') + ..write('model: $model, ') + ..write('lens: $lens, ') + ..write('orientation: $orientation, ') + ..write('timeZone: $timeZone, ') + ..write('rating: $rating, ') + ..write('projectionType: $projectionType') + ..write(')')) + .toString(); + } +} + +class RemoteAlbumAssetEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RemoteAlbumAssetEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn assetId = GeneratedColumn( + 'asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_asset_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn albumId = GeneratedColumn( + 'album_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_album_entity (id) ON DELETE CASCADE', + ), + ); + @override + List get $columns => [assetId, albumId]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'remote_album_asset_entity'; + @override + Set get $primaryKey => {assetId, albumId}; + @override + RemoteAlbumAssetEntityData map( + Map data, { + String? tablePrefix, + }) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RemoteAlbumAssetEntityData( + assetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}asset_id'], + )!, + albumId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}album_id'], + )!, + ); + } + + @override + RemoteAlbumAssetEntity createAlias(String alias) { + return RemoteAlbumAssetEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class RemoteAlbumAssetEntityData extends DataClass + implements Insertable { + final String assetId; + final String albumId; + const RemoteAlbumAssetEntityData({ + required this.assetId, + required this.albumId, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['asset_id'] = Variable(assetId); + map['album_id'] = Variable(albumId); + return map; + } + + factory RemoteAlbumAssetEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RemoteAlbumAssetEntityData( + assetId: serializer.fromJson(json['assetId']), + albumId: serializer.fromJson(json['albumId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'assetId': serializer.toJson(assetId), + 'albumId': serializer.toJson(albumId), + }; + } + + RemoteAlbumAssetEntityData copyWith({String? assetId, String? albumId}) => + RemoteAlbumAssetEntityData( + assetId: assetId ?? this.assetId, + albumId: albumId ?? this.albumId, + ); + RemoteAlbumAssetEntityData copyWithCompanion( + RemoteAlbumAssetEntityCompanion data, + ) { + return RemoteAlbumAssetEntityData( + assetId: data.assetId.present ? data.assetId.value : this.assetId, + albumId: data.albumId.present ? data.albumId.value : this.albumId, + ); + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumAssetEntityData(') + ..write('assetId: $assetId, ') + ..write('albumId: $albumId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(assetId, albumId); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RemoteAlbumAssetEntityData && + other.assetId == this.assetId && + other.albumId == this.albumId); +} + +class RemoteAlbumAssetEntityCompanion + extends UpdateCompanion { + final Value assetId; + final Value albumId; + const RemoteAlbumAssetEntityCompanion({ + this.assetId = const Value.absent(), + this.albumId = const Value.absent(), + }); + RemoteAlbumAssetEntityCompanion.insert({ + required String assetId, + required String albumId, + }) : assetId = Value(assetId), + albumId = Value(albumId); + static Insertable custom({ + Expression? assetId, + Expression? albumId, + }) { + return RawValuesInsertable({ + if (assetId != null) 'asset_id': assetId, + if (albumId != null) 'album_id': albumId, + }); + } + + RemoteAlbumAssetEntityCompanion copyWith({ + Value? assetId, + Value? albumId, + }) { + return RemoteAlbumAssetEntityCompanion( + assetId: assetId ?? this.assetId, + albumId: albumId ?? this.albumId, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (assetId.present) { + map['asset_id'] = Variable(assetId.value); + } + if (albumId.present) { + map['album_id'] = Variable(albumId.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumAssetEntityCompanion(') + ..write('assetId: $assetId, ') + ..write('albumId: $albumId') + ..write(')')) + .toString(); + } +} + +class RemoteAlbumUserEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RemoteAlbumUserEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn albumId = GeneratedColumn( + 'album_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_album_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn role = GeneratedColumn( + 'role', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + @override + List get $columns => [albumId, userId, role]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'remote_album_user_entity'; + @override + Set get $primaryKey => {albumId, userId}; + @override + RemoteAlbumUserEntityData map( + Map data, { + String? tablePrefix, + }) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RemoteAlbumUserEntityData( + albumId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}album_id'], + )!, + userId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}user_id'], + )!, + role: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}role'], + )!, + ); + } + + @override + RemoteAlbumUserEntity createAlias(String alias) { + return RemoteAlbumUserEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class RemoteAlbumUserEntityData extends DataClass + implements Insertable { + final String albumId; + final String userId; + final int role; + const RemoteAlbumUserEntityData({ + required this.albumId, + required this.userId, + required this.role, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['album_id'] = Variable(albumId); + map['user_id'] = Variable(userId); + map['role'] = Variable(role); + return map; + } + + factory RemoteAlbumUserEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RemoteAlbumUserEntityData( + albumId: serializer.fromJson(json['albumId']), + userId: serializer.fromJson(json['userId']), + role: serializer.fromJson(json['role']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'albumId': serializer.toJson(albumId), + 'userId': serializer.toJson(userId), + 'role': serializer.toJson(role), + }; + } + + RemoteAlbumUserEntityData copyWith({ + String? albumId, + String? userId, + int? role, + }) => RemoteAlbumUserEntityData( + albumId: albumId ?? this.albumId, + userId: userId ?? this.userId, + role: role ?? this.role, + ); + RemoteAlbumUserEntityData copyWithCompanion( + RemoteAlbumUserEntityCompanion data, + ) { + return RemoteAlbumUserEntityData( + albumId: data.albumId.present ? data.albumId.value : this.albumId, + userId: data.userId.present ? data.userId.value : this.userId, + role: data.role.present ? data.role.value : this.role, + ); + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumUserEntityData(') + ..write('albumId: $albumId, ') + ..write('userId: $userId, ') + ..write('role: $role') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(albumId, userId, role); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RemoteAlbumUserEntityData && + other.albumId == this.albumId && + other.userId == this.userId && + other.role == this.role); +} + +class RemoteAlbumUserEntityCompanion + extends UpdateCompanion { + final Value albumId; + final Value userId; + final Value role; + const RemoteAlbumUserEntityCompanion({ + this.albumId = const Value.absent(), + this.userId = const Value.absent(), + this.role = const Value.absent(), + }); + RemoteAlbumUserEntityCompanion.insert({ + required String albumId, + required String userId, + required int role, + }) : albumId = Value(albumId), + userId = Value(userId), + role = Value(role); + static Insertable custom({ + Expression? albumId, + Expression? userId, + Expression? role, + }) { + return RawValuesInsertable({ + if (albumId != null) 'album_id': albumId, + if (userId != null) 'user_id': userId, + if (role != null) 'role': role, + }); + } + + RemoteAlbumUserEntityCompanion copyWith({ + Value? albumId, + Value? userId, + Value? role, + }) { + return RemoteAlbumUserEntityCompanion( + albumId: albumId ?? this.albumId, + userId: userId ?? this.userId, + role: role ?? this.role, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (albumId.present) { + map['album_id'] = Variable(albumId.value); + } + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (role.present) { + map['role'] = Variable(role.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumUserEntityCompanion(') + ..write('albumId: $albumId, ') + ..write('userId: $userId, ') + ..write('role: $role') + ..write(')')) + .toString(); + } +} + +class MemoryEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + MemoryEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn deletedAt = GeneratedColumn( + 'deleted_at', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn ownerId = GeneratedColumn( + 'owner_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn type = GeneratedColumn( + 'type', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn data = GeneratedColumn( + 'data', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn isSaved = GeneratedColumn( + 'is_saved', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_saved" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn memoryAt = GeneratedColumn( + 'memory_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: true, + ); + late final GeneratedColumn seenAt = GeneratedColumn( + 'seen_at', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn showAt = GeneratedColumn( + 'show_at', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn hideAt = GeneratedColumn( + 'hide_at', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + deletedAt, + ownerId, + type, + data, + isSaved, + memoryAt, + seenAt, + showAt, + hideAt, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'memory_entity'; + @override + Set get $primaryKey => {id}; + @override + MemoryEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return MemoryEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + deletedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}deleted_at'], + ), + ownerId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}owner_id'], + )!, + type: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}type'], + )!, + data: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}data'], + )!, + isSaved: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_saved'], + )!, + memoryAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}memory_at'], + )!, + seenAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}seen_at'], + ), + showAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}show_at'], + ), + hideAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}hide_at'], + ), + ); + } + + @override + MemoryEntity createAlias(String alias) { + return MemoryEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class MemoryEntityData extends DataClass + implements Insertable { + final String id; + final DateTime createdAt; + final DateTime updatedAt; + final DateTime? deletedAt; + final String ownerId; + final int type; + final String data; + final bool isSaved; + final DateTime memoryAt; + final DateTime? seenAt; + final DateTime? showAt; + final DateTime? hideAt; + const MemoryEntityData({ + required this.id, + required this.createdAt, + required this.updatedAt, + this.deletedAt, + required this.ownerId, + required this.type, + required this.data, + required this.isSaved, + required this.memoryAt, + this.seenAt, + this.showAt, + this.hideAt, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || deletedAt != null) { + map['deleted_at'] = Variable(deletedAt); + } + map['owner_id'] = Variable(ownerId); + map['type'] = Variable(type); + map['data'] = Variable(data); + map['is_saved'] = Variable(isSaved); + map['memory_at'] = Variable(memoryAt); + if (!nullToAbsent || seenAt != null) { + map['seen_at'] = Variable(seenAt); + } + if (!nullToAbsent || showAt != null) { + map['show_at'] = Variable(showAt); + } + if (!nullToAbsent || hideAt != null) { + map['hide_at'] = Variable(hideAt); + } + return map; + } + + factory MemoryEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return MemoryEntityData( + id: serializer.fromJson(json['id']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + deletedAt: serializer.fromJson(json['deletedAt']), + ownerId: serializer.fromJson(json['ownerId']), + type: serializer.fromJson(json['type']), + data: serializer.fromJson(json['data']), + isSaved: serializer.fromJson(json['isSaved']), + memoryAt: serializer.fromJson(json['memoryAt']), + seenAt: serializer.fromJson(json['seenAt']), + showAt: serializer.fromJson(json['showAt']), + hideAt: serializer.fromJson(json['hideAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'deletedAt': serializer.toJson(deletedAt), + 'ownerId': serializer.toJson(ownerId), + 'type': serializer.toJson(type), + 'data': serializer.toJson(data), + 'isSaved': serializer.toJson(isSaved), + 'memoryAt': serializer.toJson(memoryAt), + 'seenAt': serializer.toJson(seenAt), + 'showAt': serializer.toJson(showAt), + 'hideAt': serializer.toJson(hideAt), + }; + } + + MemoryEntityData copyWith({ + String? id, + DateTime? createdAt, + DateTime? updatedAt, + Value deletedAt = const Value.absent(), + String? ownerId, + int? type, + String? data, + bool? isSaved, + DateTime? memoryAt, + Value seenAt = const Value.absent(), + Value showAt = const Value.absent(), + Value hideAt = const Value.absent(), + }) => MemoryEntityData( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt, + ownerId: ownerId ?? this.ownerId, + type: type ?? this.type, + data: data ?? this.data, + isSaved: isSaved ?? this.isSaved, + memoryAt: memoryAt ?? this.memoryAt, + seenAt: seenAt.present ? seenAt.value : this.seenAt, + showAt: showAt.present ? showAt.value : this.showAt, + hideAt: hideAt.present ? hideAt.value : this.hideAt, + ); + MemoryEntityData copyWithCompanion(MemoryEntityCompanion data) { + return MemoryEntityData( + id: data.id.present ? data.id.value : this.id, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + deletedAt: data.deletedAt.present ? data.deletedAt.value : this.deletedAt, + ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId, + type: data.type.present ? data.type.value : this.type, + data: data.data.present ? data.data.value : this.data, + isSaved: data.isSaved.present ? data.isSaved.value : this.isSaved, + memoryAt: data.memoryAt.present ? data.memoryAt.value : this.memoryAt, + seenAt: data.seenAt.present ? data.seenAt.value : this.seenAt, + showAt: data.showAt.present ? data.showAt.value : this.showAt, + hideAt: data.hideAt.present ? data.hideAt.value : this.hideAt, + ); + } + + @override + String toString() { + return (StringBuffer('MemoryEntityData(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('ownerId: $ownerId, ') + ..write('type: $type, ') + ..write('data: $data, ') + ..write('isSaved: $isSaved, ') + ..write('memoryAt: $memoryAt, ') + ..write('seenAt: $seenAt, ') + ..write('showAt: $showAt, ') + ..write('hideAt: $hideAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + createdAt, + updatedAt, + deletedAt, + ownerId, + type, + data, + isSaved, + memoryAt, + seenAt, + showAt, + hideAt, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is MemoryEntityData && + other.id == this.id && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.deletedAt == this.deletedAt && + other.ownerId == this.ownerId && + other.type == this.type && + other.data == this.data && + other.isSaved == this.isSaved && + other.memoryAt == this.memoryAt && + other.seenAt == this.seenAt && + other.showAt == this.showAt && + other.hideAt == this.hideAt); +} + +class MemoryEntityCompanion extends UpdateCompanion { + final Value id; + final Value createdAt; + final Value updatedAt; + final Value deletedAt; + final Value ownerId; + final Value type; + final Value data; + final Value isSaved; + final Value memoryAt; + final Value seenAt; + final Value showAt; + final Value hideAt; + const MemoryEntityCompanion({ + this.id = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.ownerId = const Value.absent(), + this.type = const Value.absent(), + this.data = const Value.absent(), + this.isSaved = const Value.absent(), + this.memoryAt = const Value.absent(), + this.seenAt = const Value.absent(), + this.showAt = const Value.absent(), + this.hideAt = const Value.absent(), + }); + MemoryEntityCompanion.insert({ + required String id, + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + required String ownerId, + required int type, + required String data, + this.isSaved = const Value.absent(), + required DateTime memoryAt, + this.seenAt = const Value.absent(), + this.showAt = const Value.absent(), + this.hideAt = const Value.absent(), + }) : id = Value(id), + ownerId = Value(ownerId), + type = Value(type), + data = Value(data), + memoryAt = Value(memoryAt); + static Insertable custom({ + Expression? id, + Expression? createdAt, + Expression? updatedAt, + Expression? deletedAt, + Expression? ownerId, + Expression? type, + Expression? data, + Expression? isSaved, + Expression? memoryAt, + Expression? seenAt, + Expression? showAt, + Expression? hideAt, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (deletedAt != null) 'deleted_at': deletedAt, + if (ownerId != null) 'owner_id': ownerId, + if (type != null) 'type': type, + if (data != null) 'data': data, + if (isSaved != null) 'is_saved': isSaved, + if (memoryAt != null) 'memory_at': memoryAt, + if (seenAt != null) 'seen_at': seenAt, + if (showAt != null) 'show_at': showAt, + if (hideAt != null) 'hide_at': hideAt, + }); + } + + MemoryEntityCompanion copyWith({ + Value? id, + Value? createdAt, + Value? updatedAt, + Value? deletedAt, + Value? ownerId, + Value? type, + Value? data, + Value? isSaved, + Value? memoryAt, + Value? seenAt, + Value? showAt, + Value? hideAt, + }) { + return MemoryEntityCompanion( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + ownerId: ownerId ?? this.ownerId, + type: type ?? this.type, + data: data ?? this.data, + isSaved: isSaved ?? this.isSaved, + memoryAt: memoryAt ?? this.memoryAt, + seenAt: seenAt ?? this.seenAt, + showAt: showAt ?? this.showAt, + hideAt: hideAt ?? this.hideAt, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (deletedAt.present) { + map['deleted_at'] = Variable(deletedAt.value); + } + if (ownerId.present) { + map['owner_id'] = Variable(ownerId.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (data.present) { + map['data'] = Variable(data.value); + } + if (isSaved.present) { + map['is_saved'] = Variable(isSaved.value); + } + if (memoryAt.present) { + map['memory_at'] = Variable(memoryAt.value); + } + if (seenAt.present) { + map['seen_at'] = Variable(seenAt.value); + } + if (showAt.present) { + map['show_at'] = Variable(showAt.value); + } + if (hideAt.present) { + map['hide_at'] = Variable(hideAt.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('MemoryEntityCompanion(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('ownerId: $ownerId, ') + ..write('type: $type, ') + ..write('data: $data, ') + ..write('isSaved: $isSaved, ') + ..write('memoryAt: $memoryAt, ') + ..write('seenAt: $seenAt, ') + ..write('showAt: $showAt, ') + ..write('hideAt: $hideAt') + ..write(')')) + .toString(); + } +} + +class MemoryAssetEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + MemoryAssetEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn assetId = GeneratedColumn( + 'asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_asset_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn memoryId = GeneratedColumn( + 'memory_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES memory_entity (id) ON DELETE CASCADE', + ), + ); + @override + List get $columns => [assetId, memoryId]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'memory_asset_entity'; + @override + Set get $primaryKey => {assetId, memoryId}; + @override + MemoryAssetEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return MemoryAssetEntityData( + assetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}asset_id'], + )!, + memoryId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}memory_id'], + )!, + ); + } + + @override + MemoryAssetEntity createAlias(String alias) { + return MemoryAssetEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class MemoryAssetEntityData extends DataClass + implements Insertable { + final String assetId; + final String memoryId; + const MemoryAssetEntityData({required this.assetId, required this.memoryId}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['asset_id'] = Variable(assetId); + map['memory_id'] = Variable(memoryId); + return map; + } + + factory MemoryAssetEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return MemoryAssetEntityData( + assetId: serializer.fromJson(json['assetId']), + memoryId: serializer.fromJson(json['memoryId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'assetId': serializer.toJson(assetId), + 'memoryId': serializer.toJson(memoryId), + }; + } + + MemoryAssetEntityData copyWith({String? assetId, String? memoryId}) => + MemoryAssetEntityData( + assetId: assetId ?? this.assetId, + memoryId: memoryId ?? this.memoryId, + ); + MemoryAssetEntityData copyWithCompanion(MemoryAssetEntityCompanion data) { + return MemoryAssetEntityData( + assetId: data.assetId.present ? data.assetId.value : this.assetId, + memoryId: data.memoryId.present ? data.memoryId.value : this.memoryId, + ); + } + + @override + String toString() { + return (StringBuffer('MemoryAssetEntityData(') + ..write('assetId: $assetId, ') + ..write('memoryId: $memoryId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(assetId, memoryId); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is MemoryAssetEntityData && + other.assetId == this.assetId && + other.memoryId == this.memoryId); +} + +class MemoryAssetEntityCompanion + extends UpdateCompanion { + final Value assetId; + final Value memoryId; + const MemoryAssetEntityCompanion({ + this.assetId = const Value.absent(), + this.memoryId = const Value.absent(), + }); + MemoryAssetEntityCompanion.insert({ + required String assetId, + required String memoryId, + }) : assetId = Value(assetId), + memoryId = Value(memoryId); + static Insertable custom({ + Expression? assetId, + Expression? memoryId, + }) { + return RawValuesInsertable({ + if (assetId != null) 'asset_id': assetId, + if (memoryId != null) 'memory_id': memoryId, + }); + } + + MemoryAssetEntityCompanion copyWith({ + Value? assetId, + Value? memoryId, + }) { + return MemoryAssetEntityCompanion( + assetId: assetId ?? this.assetId, + memoryId: memoryId ?? this.memoryId, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (assetId.present) { + map['asset_id'] = Variable(assetId.value); + } + if (memoryId.present) { + map['memory_id'] = Variable(memoryId.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('MemoryAssetEntityCompanion(') + ..write('assetId: $assetId, ') + ..write('memoryId: $memoryId') + ..write(')')) + .toString(); + } +} + +class PersonEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + PersonEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn ownerId = GeneratedColumn( + 'owner_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn faceAssetId = GeneratedColumn( + 'face_asset_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn isFavorite = GeneratedColumn( + 'is_favorite', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_favorite" IN (0, 1))', + ), + ); + late final GeneratedColumn isHidden = GeneratedColumn( + 'is_hidden', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_hidden" IN (0, 1))', + ), + ); + late final GeneratedColumn color = GeneratedColumn( + 'color', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn birthDate = GeneratedColumn( + 'birth_date', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + ownerId, + name, + faceAssetId, + isFavorite, + isHidden, + color, + birthDate, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'person_entity'; + @override + Set get $primaryKey => {id}; + @override + PersonEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return PersonEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + ownerId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}owner_id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + faceAssetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}face_asset_id'], + ), + isFavorite: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_favorite'], + )!, + isHidden: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_hidden'], + )!, + color: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}color'], + ), + birthDate: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}birth_date'], + ), + ); + } + + @override + PersonEntity createAlias(String alias) { + return PersonEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class PersonEntityData extends DataClass + implements Insertable { + final String id; + final DateTime createdAt; + final DateTime updatedAt; + final String ownerId; + final String name; + final String? faceAssetId; + final bool isFavorite; + final bool isHidden; + final String? color; + final DateTime? birthDate; + const PersonEntityData({ + required this.id, + required this.createdAt, + required this.updatedAt, + required this.ownerId, + required this.name, + this.faceAssetId, + required this.isFavorite, + required this.isHidden, + this.color, + this.birthDate, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + map['owner_id'] = Variable(ownerId); + map['name'] = Variable(name); + if (!nullToAbsent || faceAssetId != null) { + map['face_asset_id'] = Variable(faceAssetId); + } + map['is_favorite'] = Variable(isFavorite); + map['is_hidden'] = Variable(isHidden); + if (!nullToAbsent || color != null) { + map['color'] = Variable(color); + } + if (!nullToAbsent || birthDate != null) { + map['birth_date'] = Variable(birthDate); + } + return map; + } + + factory PersonEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return PersonEntityData( + id: serializer.fromJson(json['id']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + ownerId: serializer.fromJson(json['ownerId']), + name: serializer.fromJson(json['name']), + faceAssetId: serializer.fromJson(json['faceAssetId']), + isFavorite: serializer.fromJson(json['isFavorite']), + isHidden: serializer.fromJson(json['isHidden']), + color: serializer.fromJson(json['color']), + birthDate: serializer.fromJson(json['birthDate']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'ownerId': serializer.toJson(ownerId), + 'name': serializer.toJson(name), + 'faceAssetId': serializer.toJson(faceAssetId), + 'isFavorite': serializer.toJson(isFavorite), + 'isHidden': serializer.toJson(isHidden), + 'color': serializer.toJson(color), + 'birthDate': serializer.toJson(birthDate), + }; + } + + PersonEntityData copyWith({ + String? id, + DateTime? createdAt, + DateTime? updatedAt, + String? ownerId, + String? name, + Value faceAssetId = const Value.absent(), + bool? isFavorite, + bool? isHidden, + Value color = const Value.absent(), + Value birthDate = const Value.absent(), + }) => PersonEntityData( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + name: name ?? this.name, + faceAssetId: faceAssetId.present ? faceAssetId.value : this.faceAssetId, + isFavorite: isFavorite ?? this.isFavorite, + isHidden: isHidden ?? this.isHidden, + color: color.present ? color.value : this.color, + birthDate: birthDate.present ? birthDate.value : this.birthDate, + ); + PersonEntityData copyWithCompanion(PersonEntityCompanion data) { + return PersonEntityData( + id: data.id.present ? data.id.value : this.id, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId, + name: data.name.present ? data.name.value : this.name, + faceAssetId: data.faceAssetId.present + ? data.faceAssetId.value + : this.faceAssetId, + isFavorite: data.isFavorite.present + ? data.isFavorite.value + : this.isFavorite, + isHidden: data.isHidden.present ? data.isHidden.value : this.isHidden, + color: data.color.present ? data.color.value : this.color, + birthDate: data.birthDate.present ? data.birthDate.value : this.birthDate, + ); + } + + @override + String toString() { + return (StringBuffer('PersonEntityData(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('name: $name, ') + ..write('faceAssetId: $faceAssetId, ') + ..write('isFavorite: $isFavorite, ') + ..write('isHidden: $isHidden, ') + ..write('color: $color, ') + ..write('birthDate: $birthDate') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + createdAt, + updatedAt, + ownerId, + name, + faceAssetId, + isFavorite, + isHidden, + color, + birthDate, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is PersonEntityData && + other.id == this.id && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.ownerId == this.ownerId && + other.name == this.name && + other.faceAssetId == this.faceAssetId && + other.isFavorite == this.isFavorite && + other.isHidden == this.isHidden && + other.color == this.color && + other.birthDate == this.birthDate); +} + +class PersonEntityCompanion extends UpdateCompanion { + final Value id; + final Value createdAt; + final Value updatedAt; + final Value ownerId; + final Value name; + final Value faceAssetId; + final Value isFavorite; + final Value isHidden; + final Value color; + final Value birthDate; + const PersonEntityCompanion({ + this.id = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.ownerId = const Value.absent(), + this.name = const Value.absent(), + this.faceAssetId = const Value.absent(), + this.isFavorite = const Value.absent(), + this.isHidden = const Value.absent(), + this.color = const Value.absent(), + this.birthDate = const Value.absent(), + }); + PersonEntityCompanion.insert({ + required String id, + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + required String ownerId, + required String name, + this.faceAssetId = const Value.absent(), + required bool isFavorite, + required bool isHidden, + this.color = const Value.absent(), + this.birthDate = const Value.absent(), + }) : id = Value(id), + ownerId = Value(ownerId), + name = Value(name), + isFavorite = Value(isFavorite), + isHidden = Value(isHidden); + static Insertable custom({ + Expression? id, + Expression? createdAt, + Expression? updatedAt, + Expression? ownerId, + Expression? name, + Expression? faceAssetId, + Expression? isFavorite, + Expression? isHidden, + Expression? color, + Expression? birthDate, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (ownerId != null) 'owner_id': ownerId, + if (name != null) 'name': name, + if (faceAssetId != null) 'face_asset_id': faceAssetId, + if (isFavorite != null) 'is_favorite': isFavorite, + if (isHidden != null) 'is_hidden': isHidden, + if (color != null) 'color': color, + if (birthDate != null) 'birth_date': birthDate, + }); + } + + PersonEntityCompanion copyWith({ + Value? id, + Value? createdAt, + Value? updatedAt, + Value? ownerId, + Value? name, + Value? faceAssetId, + Value? isFavorite, + Value? isHidden, + Value? color, + Value? birthDate, + }) { + return PersonEntityCompanion( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + name: name ?? this.name, + faceAssetId: faceAssetId ?? this.faceAssetId, + isFavorite: isFavorite ?? this.isFavorite, + isHidden: isHidden ?? this.isHidden, + color: color ?? this.color, + birthDate: birthDate ?? this.birthDate, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (ownerId.present) { + map['owner_id'] = Variable(ownerId.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (faceAssetId.present) { + map['face_asset_id'] = Variable(faceAssetId.value); + } + if (isFavorite.present) { + map['is_favorite'] = Variable(isFavorite.value); + } + if (isHidden.present) { + map['is_hidden'] = Variable(isHidden.value); + } + if (color.present) { + map['color'] = Variable(color.value); + } + if (birthDate.present) { + map['birth_date'] = Variable(birthDate.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('PersonEntityCompanion(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('name: $name, ') + ..write('faceAssetId: $faceAssetId, ') + ..write('isFavorite: $isFavorite, ') + ..write('isHidden: $isHidden, ') + ..write('color: $color, ') + ..write('birthDate: $birthDate') + ..write(')')) + .toString(); + } +} + +class AssetFaceEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + AssetFaceEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn assetId = GeneratedColumn( + 'asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_asset_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn personId = GeneratedColumn( + 'person_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES person_entity (id) ON DELETE SET NULL', + ), + ); + late final GeneratedColumn imageWidth = GeneratedColumn( + 'image_width', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn imageHeight = GeneratedColumn( + 'image_height', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn boundingBoxX1 = GeneratedColumn( + 'bounding_box_x1', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn boundingBoxY1 = GeneratedColumn( + 'bounding_box_y1', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn boundingBoxX2 = GeneratedColumn( + 'bounding_box_x2', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn boundingBoxY2 = GeneratedColumn( + 'bounding_box_y2', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn sourceType = GeneratedColumn( + 'source_type', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + @override + List get $columns => [ + id, + assetId, + personId, + imageWidth, + imageHeight, + boundingBoxX1, + boundingBoxY1, + boundingBoxX2, + boundingBoxY2, + sourceType, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'asset_face_entity'; + @override + Set get $primaryKey => {id}; + @override + AssetFaceEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return AssetFaceEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + assetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}asset_id'], + )!, + personId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}person_id'], + ), + imageWidth: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}image_width'], + )!, + imageHeight: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}image_height'], + )!, + boundingBoxX1: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}bounding_box_x1'], + )!, + boundingBoxY1: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}bounding_box_y1'], + )!, + boundingBoxX2: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}bounding_box_x2'], + )!, + boundingBoxY2: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}bounding_box_y2'], + )!, + sourceType: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}source_type'], + )!, + ); + } + + @override + AssetFaceEntity createAlias(String alias) { + return AssetFaceEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class AssetFaceEntityData extends DataClass + implements Insertable { + final String id; + final String assetId; + final String? personId; + final int imageWidth; + final int imageHeight; + final int boundingBoxX1; + final int boundingBoxY1; + final int boundingBoxX2; + final int boundingBoxY2; + final String sourceType; + const AssetFaceEntityData({ + required this.id, + required this.assetId, + this.personId, + required this.imageWidth, + required this.imageHeight, + required this.boundingBoxX1, + required this.boundingBoxY1, + required this.boundingBoxX2, + required this.boundingBoxY2, + required this.sourceType, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['asset_id'] = Variable(assetId); + if (!nullToAbsent || personId != null) { + map['person_id'] = Variable(personId); + } + map['image_width'] = Variable(imageWidth); + map['image_height'] = Variable(imageHeight); + map['bounding_box_x1'] = Variable(boundingBoxX1); + map['bounding_box_y1'] = Variable(boundingBoxY1); + map['bounding_box_x2'] = Variable(boundingBoxX2); + map['bounding_box_y2'] = Variable(boundingBoxY2); + map['source_type'] = Variable(sourceType); + return map; + } + + factory AssetFaceEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return AssetFaceEntityData( + id: serializer.fromJson(json['id']), + assetId: serializer.fromJson(json['assetId']), + personId: serializer.fromJson(json['personId']), + imageWidth: serializer.fromJson(json['imageWidth']), + imageHeight: serializer.fromJson(json['imageHeight']), + boundingBoxX1: serializer.fromJson(json['boundingBoxX1']), + boundingBoxY1: serializer.fromJson(json['boundingBoxY1']), + boundingBoxX2: serializer.fromJson(json['boundingBoxX2']), + boundingBoxY2: serializer.fromJson(json['boundingBoxY2']), + sourceType: serializer.fromJson(json['sourceType']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'assetId': serializer.toJson(assetId), + 'personId': serializer.toJson(personId), + 'imageWidth': serializer.toJson(imageWidth), + 'imageHeight': serializer.toJson(imageHeight), + 'boundingBoxX1': serializer.toJson(boundingBoxX1), + 'boundingBoxY1': serializer.toJson(boundingBoxY1), + 'boundingBoxX2': serializer.toJson(boundingBoxX2), + 'boundingBoxY2': serializer.toJson(boundingBoxY2), + 'sourceType': serializer.toJson(sourceType), + }; + } + + AssetFaceEntityData copyWith({ + String? id, + String? assetId, + Value personId = const Value.absent(), + int? imageWidth, + int? imageHeight, + int? boundingBoxX1, + int? boundingBoxY1, + int? boundingBoxX2, + int? boundingBoxY2, + String? sourceType, + }) => AssetFaceEntityData( + id: id ?? this.id, + assetId: assetId ?? this.assetId, + personId: personId.present ? personId.value : this.personId, + imageWidth: imageWidth ?? this.imageWidth, + imageHeight: imageHeight ?? this.imageHeight, + boundingBoxX1: boundingBoxX1 ?? this.boundingBoxX1, + boundingBoxY1: boundingBoxY1 ?? this.boundingBoxY1, + boundingBoxX2: boundingBoxX2 ?? this.boundingBoxX2, + boundingBoxY2: boundingBoxY2 ?? this.boundingBoxY2, + sourceType: sourceType ?? this.sourceType, + ); + AssetFaceEntityData copyWithCompanion(AssetFaceEntityCompanion data) { + return AssetFaceEntityData( + id: data.id.present ? data.id.value : this.id, + assetId: data.assetId.present ? data.assetId.value : this.assetId, + personId: data.personId.present ? data.personId.value : this.personId, + imageWidth: data.imageWidth.present + ? data.imageWidth.value + : this.imageWidth, + imageHeight: data.imageHeight.present + ? data.imageHeight.value + : this.imageHeight, + boundingBoxX1: data.boundingBoxX1.present + ? data.boundingBoxX1.value + : this.boundingBoxX1, + boundingBoxY1: data.boundingBoxY1.present + ? data.boundingBoxY1.value + : this.boundingBoxY1, + boundingBoxX2: data.boundingBoxX2.present + ? data.boundingBoxX2.value + : this.boundingBoxX2, + boundingBoxY2: data.boundingBoxY2.present + ? data.boundingBoxY2.value + : this.boundingBoxY2, + sourceType: data.sourceType.present + ? data.sourceType.value + : this.sourceType, + ); + } + + @override + String toString() { + return (StringBuffer('AssetFaceEntityData(') + ..write('id: $id, ') + ..write('assetId: $assetId, ') + ..write('personId: $personId, ') + ..write('imageWidth: $imageWidth, ') + ..write('imageHeight: $imageHeight, ') + ..write('boundingBoxX1: $boundingBoxX1, ') + ..write('boundingBoxY1: $boundingBoxY1, ') + ..write('boundingBoxX2: $boundingBoxX2, ') + ..write('boundingBoxY2: $boundingBoxY2, ') + ..write('sourceType: $sourceType') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + assetId, + personId, + imageWidth, + imageHeight, + boundingBoxX1, + boundingBoxY1, + boundingBoxX2, + boundingBoxY2, + sourceType, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is AssetFaceEntityData && + other.id == this.id && + other.assetId == this.assetId && + other.personId == this.personId && + other.imageWidth == this.imageWidth && + other.imageHeight == this.imageHeight && + other.boundingBoxX1 == this.boundingBoxX1 && + other.boundingBoxY1 == this.boundingBoxY1 && + other.boundingBoxX2 == this.boundingBoxX2 && + other.boundingBoxY2 == this.boundingBoxY2 && + other.sourceType == this.sourceType); +} + +class AssetFaceEntityCompanion extends UpdateCompanion { + final Value id; + final Value assetId; + final Value personId; + final Value imageWidth; + final Value imageHeight; + final Value boundingBoxX1; + final Value boundingBoxY1; + final Value boundingBoxX2; + final Value boundingBoxY2; + final Value sourceType; + const AssetFaceEntityCompanion({ + this.id = const Value.absent(), + this.assetId = const Value.absent(), + this.personId = const Value.absent(), + this.imageWidth = const Value.absent(), + this.imageHeight = const Value.absent(), + this.boundingBoxX1 = const Value.absent(), + this.boundingBoxY1 = const Value.absent(), + this.boundingBoxX2 = const Value.absent(), + this.boundingBoxY2 = const Value.absent(), + this.sourceType = const Value.absent(), + }); + AssetFaceEntityCompanion.insert({ + required String id, + required String assetId, + this.personId = const Value.absent(), + required int imageWidth, + required int imageHeight, + required int boundingBoxX1, + required int boundingBoxY1, + required int boundingBoxX2, + required int boundingBoxY2, + required String sourceType, + }) : id = Value(id), + assetId = Value(assetId), + imageWidth = Value(imageWidth), + imageHeight = Value(imageHeight), + boundingBoxX1 = Value(boundingBoxX1), + boundingBoxY1 = Value(boundingBoxY1), + boundingBoxX2 = Value(boundingBoxX2), + boundingBoxY2 = Value(boundingBoxY2), + sourceType = Value(sourceType); + static Insertable custom({ + Expression? id, + Expression? assetId, + Expression? personId, + Expression? imageWidth, + Expression? imageHeight, + Expression? boundingBoxX1, + Expression? boundingBoxY1, + Expression? boundingBoxX2, + Expression? boundingBoxY2, + Expression? sourceType, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (assetId != null) 'asset_id': assetId, + if (personId != null) 'person_id': personId, + if (imageWidth != null) 'image_width': imageWidth, + if (imageHeight != null) 'image_height': imageHeight, + if (boundingBoxX1 != null) 'bounding_box_x1': boundingBoxX1, + if (boundingBoxY1 != null) 'bounding_box_y1': boundingBoxY1, + if (boundingBoxX2 != null) 'bounding_box_x2': boundingBoxX2, + if (boundingBoxY2 != null) 'bounding_box_y2': boundingBoxY2, + if (sourceType != null) 'source_type': sourceType, + }); + } + + AssetFaceEntityCompanion copyWith({ + Value? id, + Value? assetId, + Value? personId, + Value? imageWidth, + Value? imageHeight, + Value? boundingBoxX1, + Value? boundingBoxY1, + Value? boundingBoxX2, + Value? boundingBoxY2, + Value? sourceType, + }) { + return AssetFaceEntityCompanion( + id: id ?? this.id, + assetId: assetId ?? this.assetId, + personId: personId ?? this.personId, + imageWidth: imageWidth ?? this.imageWidth, + imageHeight: imageHeight ?? this.imageHeight, + boundingBoxX1: boundingBoxX1 ?? this.boundingBoxX1, + boundingBoxY1: boundingBoxY1 ?? this.boundingBoxY1, + boundingBoxX2: boundingBoxX2 ?? this.boundingBoxX2, + boundingBoxY2: boundingBoxY2 ?? this.boundingBoxY2, + sourceType: sourceType ?? this.sourceType, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (assetId.present) { + map['asset_id'] = Variable(assetId.value); + } + if (personId.present) { + map['person_id'] = Variable(personId.value); + } + if (imageWidth.present) { + map['image_width'] = Variable(imageWidth.value); + } + if (imageHeight.present) { + map['image_height'] = Variable(imageHeight.value); + } + if (boundingBoxX1.present) { + map['bounding_box_x1'] = Variable(boundingBoxX1.value); + } + if (boundingBoxY1.present) { + map['bounding_box_y1'] = Variable(boundingBoxY1.value); + } + if (boundingBoxX2.present) { + map['bounding_box_x2'] = Variable(boundingBoxX2.value); + } + if (boundingBoxY2.present) { + map['bounding_box_y2'] = Variable(boundingBoxY2.value); + } + if (sourceType.present) { + map['source_type'] = Variable(sourceType.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('AssetFaceEntityCompanion(') + ..write('id: $id, ') + ..write('assetId: $assetId, ') + ..write('personId: $personId, ') + ..write('imageWidth: $imageWidth, ') + ..write('imageHeight: $imageHeight, ') + ..write('boundingBoxX1: $boundingBoxX1, ') + ..write('boundingBoxY1: $boundingBoxY1, ') + ..write('boundingBoxX2: $boundingBoxX2, ') + ..write('boundingBoxY2: $boundingBoxY2, ') + ..write('sourceType: $sourceType') + ..write(')')) + .toString(); + } +} + +class StoreEntity extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + StoreEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn stringValue = GeneratedColumn( + 'string_value', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn intValue = GeneratedColumn( + 'int_value', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + @override + List get $columns => [id, stringValue, intValue]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'store_entity'; + @override + Set get $primaryKey => {id}; + @override + StoreEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return StoreEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}id'], + )!, + stringValue: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}string_value'], + ), + intValue: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}int_value'], + ), + ); + } + + @override + StoreEntity createAlias(String alias) { + return StoreEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class StoreEntityData extends DataClass implements Insertable { + final int id; + final String? stringValue; + final int? intValue; + const StoreEntityData({required this.id, this.stringValue, this.intValue}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + if (!nullToAbsent || stringValue != null) { + map['string_value'] = Variable(stringValue); + } + if (!nullToAbsent || intValue != null) { + map['int_value'] = Variable(intValue); + } + return map; + } + + factory StoreEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return StoreEntityData( + id: serializer.fromJson(json['id']), + stringValue: serializer.fromJson(json['stringValue']), + intValue: serializer.fromJson(json['intValue']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'stringValue': serializer.toJson(stringValue), + 'intValue': serializer.toJson(intValue), + }; + } + + StoreEntityData copyWith({ + int? id, + Value stringValue = const Value.absent(), + Value intValue = const Value.absent(), + }) => StoreEntityData( + id: id ?? this.id, + stringValue: stringValue.present ? stringValue.value : this.stringValue, + intValue: intValue.present ? intValue.value : this.intValue, + ); + StoreEntityData copyWithCompanion(StoreEntityCompanion data) { + return StoreEntityData( + id: data.id.present ? data.id.value : this.id, + stringValue: data.stringValue.present + ? data.stringValue.value + : this.stringValue, + intValue: data.intValue.present ? data.intValue.value : this.intValue, + ); + } + + @override + String toString() { + return (StringBuffer('StoreEntityData(') + ..write('id: $id, ') + ..write('stringValue: $stringValue, ') + ..write('intValue: $intValue') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, stringValue, intValue); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is StoreEntityData && + other.id == this.id && + other.stringValue == this.stringValue && + other.intValue == this.intValue); +} + +class StoreEntityCompanion extends UpdateCompanion { + final Value id; + final Value stringValue; + final Value intValue; + const StoreEntityCompanion({ + this.id = const Value.absent(), + this.stringValue = const Value.absent(), + this.intValue = const Value.absent(), + }); + StoreEntityCompanion.insert({ + required int id, + this.stringValue = const Value.absent(), + this.intValue = const Value.absent(), + }) : id = Value(id); + static Insertable custom({ + Expression? id, + Expression? stringValue, + Expression? intValue, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (stringValue != null) 'string_value': stringValue, + if (intValue != null) 'int_value': intValue, + }); + } + + StoreEntityCompanion copyWith({ + Value? id, + Value? stringValue, + Value? intValue, + }) { + return StoreEntityCompanion( + id: id ?? this.id, + stringValue: stringValue ?? this.stringValue, + intValue: intValue ?? this.intValue, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (stringValue.present) { + map['string_value'] = Variable(stringValue.value); + } + if (intValue.present) { + map['int_value'] = Variable(intValue.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('StoreEntityCompanion(') + ..write('id: $id, ') + ..write('stringValue: $stringValue, ') + ..write('intValue: $intValue') + ..write(')')) + .toString(); + } +} + +class DatabaseAtV10 extends GeneratedDatabase { + DatabaseAtV10(QueryExecutor e) : super(e); + late final UserEntity userEntity = UserEntity(this); + late final RemoteAssetEntity remoteAssetEntity = RemoteAssetEntity(this); + late final StackEntity stackEntity = StackEntity(this); + late final LocalAssetEntity localAssetEntity = LocalAssetEntity(this); + late final RemoteAlbumEntity remoteAlbumEntity = RemoteAlbumEntity(this); + late final LocalAlbumEntity localAlbumEntity = LocalAlbumEntity(this); + late final LocalAlbumAssetEntity localAlbumAssetEntity = + LocalAlbumAssetEntity(this); + late final Index idxLocalAssetChecksum = Index( + 'idx_local_asset_checksum', + 'CREATE INDEX IF NOT EXISTS idx_local_asset_checksum ON local_asset_entity (checksum)', + ); + late final Index idxRemoteAssetOwnerChecksum = Index( + 'idx_remote_asset_owner_checksum', + 'CREATE INDEX IF NOT EXISTS idx_remote_asset_owner_checksum ON remote_asset_entity (owner_id, checksum)', + ); + late final Index uQRemoteAssetsOwnerChecksum = Index( + 'UQ_remote_assets_owner_checksum', + 'CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_checksum ON remote_asset_entity (owner_id, checksum) WHERE(library_id IS NULL)', + ); + late final Index uQRemoteAssetsOwnerLibraryChecksum = Index( + 'UQ_remote_assets_owner_library_checksum', + 'CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_library_checksum ON remote_asset_entity (owner_id, library_id, checksum) WHERE(library_id IS NOT NULL)', + ); + late final Index idxRemoteAssetChecksum = Index( + 'idx_remote_asset_checksum', + 'CREATE INDEX IF NOT EXISTS idx_remote_asset_checksum ON remote_asset_entity (checksum)', + ); + late final AuthUserEntity authUserEntity = AuthUserEntity(this); + late final UserMetadataEntity userMetadataEntity = UserMetadataEntity(this); + late final PartnerEntity partnerEntity = PartnerEntity(this); + late final RemoteExifEntity remoteExifEntity = RemoteExifEntity(this); + late final RemoteAlbumAssetEntity remoteAlbumAssetEntity = + RemoteAlbumAssetEntity(this); + late final RemoteAlbumUserEntity remoteAlbumUserEntity = + RemoteAlbumUserEntity(this); + late final MemoryEntity memoryEntity = MemoryEntity(this); + late final MemoryAssetEntity memoryAssetEntity = MemoryAssetEntity(this); + late final PersonEntity personEntity = PersonEntity(this); + late final AssetFaceEntity assetFaceEntity = AssetFaceEntity(this); + late final StoreEntity storeEntity = StoreEntity(this); + late final Index idxLatLng = Index( + 'idx_lat_lng', + 'CREATE INDEX IF NOT EXISTS idx_lat_lng ON remote_exif_entity (latitude, longitude)', + ); + @override + Iterable> get allTables => + allSchemaEntities.whereType>(); + @override + List get allSchemaEntities => [ + userEntity, + remoteAssetEntity, + stackEntity, + localAssetEntity, + remoteAlbumEntity, + localAlbumEntity, + localAlbumAssetEntity, + idxLocalAssetChecksum, + idxRemoteAssetOwnerChecksum, + uQRemoteAssetsOwnerChecksum, + uQRemoteAssetsOwnerLibraryChecksum, + idxRemoteAssetChecksum, + authUserEntity, + userMetadataEntity, + partnerEntity, + remoteExifEntity, + remoteAlbumAssetEntity, + remoteAlbumUserEntity, + memoryEntity, + memoryAssetEntity, + personEntity, + assetFaceEntity, + storeEntity, + idxLatLng, + ]; + @override + int get schemaVersion => 10; + @override + DriftDatabaseOptions get options => + const DriftDatabaseOptions(storeDateTimeAsText: true); +} diff --git a/mobile/test/drift/main/generated/schema_v11.dart b/mobile/test/drift/main/generated/schema_v11.dart new file mode 100644 index 0000000000..fe27f1bb3d --- /dev/null +++ b/mobile/test/drift/main/generated/schema_v11.dart @@ -0,0 +1,7198 @@ +// dart format width=80 +// GENERATED CODE, DO NOT EDIT BY HAND. +// ignore_for_file: type=lint +import 'package:drift/drift.dart'; + +class UserEntity extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + UserEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn email = GeneratedColumn( + 'email', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn hasProfileImage = GeneratedColumn( + 'has_profile_image', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("has_profile_image" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn profileChangedAt = + GeneratedColumn( + 'profile_changed_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn avatarColor = GeneratedColumn( + 'avatar_color', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0'), + ); + @override + List get $columns => [ + id, + name, + email, + hasProfileImage, + profileChangedAt, + avatarColor, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'user_entity'; + @override + Set get $primaryKey => {id}; + @override + UserEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return UserEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + email: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}email'], + )!, + hasProfileImage: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}has_profile_image'], + )!, + profileChangedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}profile_changed_at'], + )!, + avatarColor: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}avatar_color'], + )!, + ); + } + + @override + UserEntity createAlias(String alias) { + return UserEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class UserEntityData extends DataClass implements Insertable { + final String id; + final String name; + final String email; + final bool hasProfileImage; + final DateTime profileChangedAt; + final int avatarColor; + const UserEntityData({ + required this.id, + required this.name, + required this.email, + required this.hasProfileImage, + required this.profileChangedAt, + required this.avatarColor, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + map['email'] = Variable(email); + map['has_profile_image'] = Variable(hasProfileImage); + map['profile_changed_at'] = Variable(profileChangedAt); + map['avatar_color'] = Variable(avatarColor); + return map; + } + + factory UserEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return UserEntityData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + email: serializer.fromJson(json['email']), + hasProfileImage: serializer.fromJson(json['hasProfileImage']), + profileChangedAt: serializer.fromJson(json['profileChangedAt']), + avatarColor: serializer.fromJson(json['avatarColor']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'email': serializer.toJson(email), + 'hasProfileImage': serializer.toJson(hasProfileImage), + 'profileChangedAt': serializer.toJson(profileChangedAt), + 'avatarColor': serializer.toJson(avatarColor), + }; + } + + UserEntityData copyWith({ + String? id, + String? name, + String? email, + bool? hasProfileImage, + DateTime? profileChangedAt, + int? avatarColor, + }) => UserEntityData( + id: id ?? this.id, + name: name ?? this.name, + email: email ?? this.email, + hasProfileImage: hasProfileImage ?? this.hasProfileImage, + profileChangedAt: profileChangedAt ?? this.profileChangedAt, + avatarColor: avatarColor ?? this.avatarColor, + ); + UserEntityData copyWithCompanion(UserEntityCompanion data) { + return UserEntityData( + id: data.id.present ? data.id.value : this.id, + name: data.name.present ? data.name.value : this.name, + email: data.email.present ? data.email.value : this.email, + hasProfileImage: data.hasProfileImage.present + ? data.hasProfileImage.value + : this.hasProfileImage, + profileChangedAt: data.profileChangedAt.present + ? data.profileChangedAt.value + : this.profileChangedAt, + avatarColor: data.avatarColor.present + ? data.avatarColor.value + : this.avatarColor, + ); + } + + @override + String toString() { + return (StringBuffer('UserEntityData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('email: $email, ') + ..write('hasProfileImage: $hasProfileImage, ') + ..write('profileChangedAt: $profileChangedAt, ') + ..write('avatarColor: $avatarColor') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + name, + email, + hasProfileImage, + profileChangedAt, + avatarColor, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is UserEntityData && + other.id == this.id && + other.name == this.name && + other.email == this.email && + other.hasProfileImage == this.hasProfileImage && + other.profileChangedAt == this.profileChangedAt && + other.avatarColor == this.avatarColor); +} + +class UserEntityCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value email; + final Value hasProfileImage; + final Value profileChangedAt; + final Value avatarColor; + const UserEntityCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.email = const Value.absent(), + this.hasProfileImage = const Value.absent(), + this.profileChangedAt = const Value.absent(), + this.avatarColor = const Value.absent(), + }); + UserEntityCompanion.insert({ + required String id, + required String name, + required String email, + this.hasProfileImage = const Value.absent(), + this.profileChangedAt = const Value.absent(), + this.avatarColor = const Value.absent(), + }) : id = Value(id), + name = Value(name), + email = Value(email); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? email, + Expression? hasProfileImage, + Expression? profileChangedAt, + Expression? avatarColor, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (email != null) 'email': email, + if (hasProfileImage != null) 'has_profile_image': hasProfileImage, + if (profileChangedAt != null) 'profile_changed_at': profileChangedAt, + if (avatarColor != null) 'avatar_color': avatarColor, + }); + } + + UserEntityCompanion copyWith({ + Value? id, + Value? name, + Value? email, + Value? hasProfileImage, + Value? profileChangedAt, + Value? avatarColor, + }) { + return UserEntityCompanion( + id: id ?? this.id, + name: name ?? this.name, + email: email ?? this.email, + hasProfileImage: hasProfileImage ?? this.hasProfileImage, + profileChangedAt: profileChangedAt ?? this.profileChangedAt, + avatarColor: avatarColor ?? this.avatarColor, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (email.present) { + map['email'] = Variable(email.value); + } + if (hasProfileImage.present) { + map['has_profile_image'] = Variable(hasProfileImage.value); + } + if (profileChangedAt.present) { + map['profile_changed_at'] = Variable(profileChangedAt.value); + } + if (avatarColor.present) { + map['avatar_color'] = Variable(avatarColor.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('UserEntityCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('email: $email, ') + ..write('hasProfileImage: $hasProfileImage, ') + ..write('profileChangedAt: $profileChangedAt, ') + ..write('avatarColor: $avatarColor') + ..write(')')) + .toString(); + } +} + +class RemoteAssetEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RemoteAssetEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn type = GeneratedColumn( + 'type', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn width = GeneratedColumn( + 'width', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn height = GeneratedColumn( + 'height', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn durationInSeconds = GeneratedColumn( + 'duration_in_seconds', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn checksum = GeneratedColumn( + 'checksum', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn isFavorite = GeneratedColumn( + 'is_favorite', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_favorite" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn ownerId = GeneratedColumn( + 'owner_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn localDateTime = + GeneratedColumn( + 'local_date_time', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn thumbHash = GeneratedColumn( + 'thumb_hash', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn deletedAt = GeneratedColumn( + 'deleted_at', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn livePhotoVideoId = GeneratedColumn( + 'live_photo_video_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn visibility = GeneratedColumn( + 'visibility', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn stackId = GeneratedColumn( + 'stack_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn libraryId = GeneratedColumn( + 'library_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + @override + List get $columns => [ + name, + type, + createdAt, + updatedAt, + width, + height, + durationInSeconds, + id, + checksum, + isFavorite, + ownerId, + localDateTime, + thumbHash, + deletedAt, + livePhotoVideoId, + visibility, + stackId, + libraryId, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'remote_asset_entity'; + @override + Set get $primaryKey => {id}; + @override + RemoteAssetEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RemoteAssetEntityData( + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + type: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}type'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + width: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}width'], + ), + height: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}height'], + ), + durationInSeconds: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}duration_in_seconds'], + ), + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + checksum: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}checksum'], + )!, + isFavorite: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_favorite'], + )!, + ownerId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}owner_id'], + )!, + localDateTime: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}local_date_time'], + ), + thumbHash: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}thumb_hash'], + ), + deletedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}deleted_at'], + ), + livePhotoVideoId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}live_photo_video_id'], + ), + visibility: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}visibility'], + )!, + stackId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}stack_id'], + ), + libraryId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}library_id'], + ), + ); + } + + @override + RemoteAssetEntity createAlias(String alias) { + return RemoteAssetEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class RemoteAssetEntityData extends DataClass + implements Insertable { + final String name; + final int type; + final DateTime createdAt; + final DateTime updatedAt; + final int? width; + final int? height; + final int? durationInSeconds; + final String id; + final String checksum; + final bool isFavorite; + final String ownerId; + final DateTime? localDateTime; + final String? thumbHash; + final DateTime? deletedAt; + final String? livePhotoVideoId; + final int visibility; + final String? stackId; + final String? libraryId; + const RemoteAssetEntityData({ + required this.name, + required this.type, + required this.createdAt, + required this.updatedAt, + this.width, + this.height, + this.durationInSeconds, + required this.id, + required this.checksum, + required this.isFavorite, + required this.ownerId, + this.localDateTime, + this.thumbHash, + this.deletedAt, + this.livePhotoVideoId, + required this.visibility, + this.stackId, + this.libraryId, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['name'] = Variable(name); + map['type'] = Variable(type); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || width != null) { + map['width'] = Variable(width); + } + if (!nullToAbsent || height != null) { + map['height'] = Variable(height); + } + if (!nullToAbsent || durationInSeconds != null) { + map['duration_in_seconds'] = Variable(durationInSeconds); + } + map['id'] = Variable(id); + map['checksum'] = Variable(checksum); + map['is_favorite'] = Variable(isFavorite); + map['owner_id'] = Variable(ownerId); + if (!nullToAbsent || localDateTime != null) { + map['local_date_time'] = Variable(localDateTime); + } + if (!nullToAbsent || thumbHash != null) { + map['thumb_hash'] = Variable(thumbHash); + } + if (!nullToAbsent || deletedAt != null) { + map['deleted_at'] = Variable(deletedAt); + } + if (!nullToAbsent || livePhotoVideoId != null) { + map['live_photo_video_id'] = Variable(livePhotoVideoId); + } + map['visibility'] = Variable(visibility); + if (!nullToAbsent || stackId != null) { + map['stack_id'] = Variable(stackId); + } + if (!nullToAbsent || libraryId != null) { + map['library_id'] = Variable(libraryId); + } + return map; + } + + factory RemoteAssetEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RemoteAssetEntityData( + name: serializer.fromJson(json['name']), + type: serializer.fromJson(json['type']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + width: serializer.fromJson(json['width']), + height: serializer.fromJson(json['height']), + durationInSeconds: serializer.fromJson(json['durationInSeconds']), + id: serializer.fromJson(json['id']), + checksum: serializer.fromJson(json['checksum']), + isFavorite: serializer.fromJson(json['isFavorite']), + ownerId: serializer.fromJson(json['ownerId']), + localDateTime: serializer.fromJson(json['localDateTime']), + thumbHash: serializer.fromJson(json['thumbHash']), + deletedAt: serializer.fromJson(json['deletedAt']), + livePhotoVideoId: serializer.fromJson(json['livePhotoVideoId']), + visibility: serializer.fromJson(json['visibility']), + stackId: serializer.fromJson(json['stackId']), + libraryId: serializer.fromJson(json['libraryId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'name': serializer.toJson(name), + 'type': serializer.toJson(type), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'width': serializer.toJson(width), + 'height': serializer.toJson(height), + 'durationInSeconds': serializer.toJson(durationInSeconds), + 'id': serializer.toJson(id), + 'checksum': serializer.toJson(checksum), + 'isFavorite': serializer.toJson(isFavorite), + 'ownerId': serializer.toJson(ownerId), + 'localDateTime': serializer.toJson(localDateTime), + 'thumbHash': serializer.toJson(thumbHash), + 'deletedAt': serializer.toJson(deletedAt), + 'livePhotoVideoId': serializer.toJson(livePhotoVideoId), + 'visibility': serializer.toJson(visibility), + 'stackId': serializer.toJson(stackId), + 'libraryId': serializer.toJson(libraryId), + }; + } + + RemoteAssetEntityData copyWith({ + String? name, + int? type, + DateTime? createdAt, + DateTime? updatedAt, + Value width = const Value.absent(), + Value height = const Value.absent(), + Value durationInSeconds = const Value.absent(), + String? id, + String? checksum, + bool? isFavorite, + String? ownerId, + Value localDateTime = const Value.absent(), + Value thumbHash = const Value.absent(), + Value deletedAt = const Value.absent(), + Value livePhotoVideoId = const Value.absent(), + int? visibility, + Value stackId = const Value.absent(), + Value libraryId = const Value.absent(), + }) => RemoteAssetEntityData( + name: name ?? this.name, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + width: width.present ? width.value : this.width, + height: height.present ? height.value : this.height, + durationInSeconds: durationInSeconds.present + ? durationInSeconds.value + : this.durationInSeconds, + id: id ?? this.id, + checksum: checksum ?? this.checksum, + isFavorite: isFavorite ?? this.isFavorite, + ownerId: ownerId ?? this.ownerId, + localDateTime: localDateTime.present + ? localDateTime.value + : this.localDateTime, + thumbHash: thumbHash.present ? thumbHash.value : this.thumbHash, + deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt, + livePhotoVideoId: livePhotoVideoId.present + ? livePhotoVideoId.value + : this.livePhotoVideoId, + visibility: visibility ?? this.visibility, + stackId: stackId.present ? stackId.value : this.stackId, + libraryId: libraryId.present ? libraryId.value : this.libraryId, + ); + RemoteAssetEntityData copyWithCompanion(RemoteAssetEntityCompanion data) { + return RemoteAssetEntityData( + name: data.name.present ? data.name.value : this.name, + type: data.type.present ? data.type.value : this.type, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + width: data.width.present ? data.width.value : this.width, + height: data.height.present ? data.height.value : this.height, + durationInSeconds: data.durationInSeconds.present + ? data.durationInSeconds.value + : this.durationInSeconds, + id: data.id.present ? data.id.value : this.id, + checksum: data.checksum.present ? data.checksum.value : this.checksum, + isFavorite: data.isFavorite.present + ? data.isFavorite.value + : this.isFavorite, + ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId, + localDateTime: data.localDateTime.present + ? data.localDateTime.value + : this.localDateTime, + thumbHash: data.thumbHash.present ? data.thumbHash.value : this.thumbHash, + deletedAt: data.deletedAt.present ? data.deletedAt.value : this.deletedAt, + livePhotoVideoId: data.livePhotoVideoId.present + ? data.livePhotoVideoId.value + : this.livePhotoVideoId, + visibility: data.visibility.present + ? data.visibility.value + : this.visibility, + stackId: data.stackId.present ? data.stackId.value : this.stackId, + libraryId: data.libraryId.present ? data.libraryId.value : this.libraryId, + ); + } + + @override + String toString() { + return (StringBuffer('RemoteAssetEntityData(') + ..write('name: $name, ') + ..write('type: $type, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('width: $width, ') + ..write('height: $height, ') + ..write('durationInSeconds: $durationInSeconds, ') + ..write('id: $id, ') + ..write('checksum: $checksum, ') + ..write('isFavorite: $isFavorite, ') + ..write('ownerId: $ownerId, ') + ..write('localDateTime: $localDateTime, ') + ..write('thumbHash: $thumbHash, ') + ..write('deletedAt: $deletedAt, ') + ..write('livePhotoVideoId: $livePhotoVideoId, ') + ..write('visibility: $visibility, ') + ..write('stackId: $stackId, ') + ..write('libraryId: $libraryId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + name, + type, + createdAt, + updatedAt, + width, + height, + durationInSeconds, + id, + checksum, + isFavorite, + ownerId, + localDateTime, + thumbHash, + deletedAt, + livePhotoVideoId, + visibility, + stackId, + libraryId, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RemoteAssetEntityData && + other.name == this.name && + other.type == this.type && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.width == this.width && + other.height == this.height && + other.durationInSeconds == this.durationInSeconds && + other.id == this.id && + other.checksum == this.checksum && + other.isFavorite == this.isFavorite && + other.ownerId == this.ownerId && + other.localDateTime == this.localDateTime && + other.thumbHash == this.thumbHash && + other.deletedAt == this.deletedAt && + other.livePhotoVideoId == this.livePhotoVideoId && + other.visibility == this.visibility && + other.stackId == this.stackId && + other.libraryId == this.libraryId); +} + +class RemoteAssetEntityCompanion + extends UpdateCompanion { + final Value name; + final Value type; + final Value createdAt; + final Value updatedAt; + final Value width; + final Value height; + final Value durationInSeconds; + final Value id; + final Value checksum; + final Value isFavorite; + final Value ownerId; + final Value localDateTime; + final Value thumbHash; + final Value deletedAt; + final Value livePhotoVideoId; + final Value visibility; + final Value stackId; + final Value libraryId; + const RemoteAssetEntityCompanion({ + this.name = const Value.absent(), + this.type = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.width = const Value.absent(), + this.height = const Value.absent(), + this.durationInSeconds = const Value.absent(), + this.id = const Value.absent(), + this.checksum = const Value.absent(), + this.isFavorite = const Value.absent(), + this.ownerId = const Value.absent(), + this.localDateTime = const Value.absent(), + this.thumbHash = const Value.absent(), + this.deletedAt = const Value.absent(), + this.livePhotoVideoId = const Value.absent(), + this.visibility = const Value.absent(), + this.stackId = const Value.absent(), + this.libraryId = const Value.absent(), + }); + RemoteAssetEntityCompanion.insert({ + required String name, + required int type, + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.width = const Value.absent(), + this.height = const Value.absent(), + this.durationInSeconds = const Value.absent(), + required String id, + required String checksum, + this.isFavorite = const Value.absent(), + required String ownerId, + this.localDateTime = const Value.absent(), + this.thumbHash = const Value.absent(), + this.deletedAt = const Value.absent(), + this.livePhotoVideoId = const Value.absent(), + required int visibility, + this.stackId = const Value.absent(), + this.libraryId = const Value.absent(), + }) : name = Value(name), + type = Value(type), + id = Value(id), + checksum = Value(checksum), + ownerId = Value(ownerId), + visibility = Value(visibility); + static Insertable custom({ + Expression? name, + Expression? type, + Expression? createdAt, + Expression? updatedAt, + Expression? width, + Expression? height, + Expression? durationInSeconds, + Expression? id, + Expression? checksum, + Expression? isFavorite, + Expression? ownerId, + Expression? localDateTime, + Expression? thumbHash, + Expression? deletedAt, + Expression? livePhotoVideoId, + Expression? visibility, + Expression? stackId, + Expression? libraryId, + }) { + return RawValuesInsertable({ + if (name != null) 'name': name, + if (type != null) 'type': type, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (width != null) 'width': width, + if (height != null) 'height': height, + if (durationInSeconds != null) 'duration_in_seconds': durationInSeconds, + if (id != null) 'id': id, + if (checksum != null) 'checksum': checksum, + if (isFavorite != null) 'is_favorite': isFavorite, + if (ownerId != null) 'owner_id': ownerId, + if (localDateTime != null) 'local_date_time': localDateTime, + if (thumbHash != null) 'thumb_hash': thumbHash, + if (deletedAt != null) 'deleted_at': deletedAt, + if (livePhotoVideoId != null) 'live_photo_video_id': livePhotoVideoId, + if (visibility != null) 'visibility': visibility, + if (stackId != null) 'stack_id': stackId, + if (libraryId != null) 'library_id': libraryId, + }); + } + + RemoteAssetEntityCompanion copyWith({ + Value? name, + Value? type, + Value? createdAt, + Value? updatedAt, + Value? width, + Value? height, + Value? durationInSeconds, + Value? id, + Value? checksum, + Value? isFavorite, + Value? ownerId, + Value? localDateTime, + Value? thumbHash, + Value? deletedAt, + Value? livePhotoVideoId, + Value? visibility, + Value? stackId, + Value? libraryId, + }) { + return RemoteAssetEntityCompanion( + name: name ?? this.name, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + width: width ?? this.width, + height: height ?? this.height, + durationInSeconds: durationInSeconds ?? this.durationInSeconds, + id: id ?? this.id, + checksum: checksum ?? this.checksum, + isFavorite: isFavorite ?? this.isFavorite, + ownerId: ownerId ?? this.ownerId, + localDateTime: localDateTime ?? this.localDateTime, + thumbHash: thumbHash ?? this.thumbHash, + deletedAt: deletedAt ?? this.deletedAt, + livePhotoVideoId: livePhotoVideoId ?? this.livePhotoVideoId, + visibility: visibility ?? this.visibility, + stackId: stackId ?? this.stackId, + libraryId: libraryId ?? this.libraryId, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (name.present) { + map['name'] = Variable(name.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (width.present) { + map['width'] = Variable(width.value); + } + if (height.present) { + map['height'] = Variable(height.value); + } + if (durationInSeconds.present) { + map['duration_in_seconds'] = Variable(durationInSeconds.value); + } + if (id.present) { + map['id'] = Variable(id.value); + } + if (checksum.present) { + map['checksum'] = Variable(checksum.value); + } + if (isFavorite.present) { + map['is_favorite'] = Variable(isFavorite.value); + } + if (ownerId.present) { + map['owner_id'] = Variable(ownerId.value); + } + if (localDateTime.present) { + map['local_date_time'] = Variable(localDateTime.value); + } + if (thumbHash.present) { + map['thumb_hash'] = Variable(thumbHash.value); + } + if (deletedAt.present) { + map['deleted_at'] = Variable(deletedAt.value); + } + if (livePhotoVideoId.present) { + map['live_photo_video_id'] = Variable(livePhotoVideoId.value); + } + if (visibility.present) { + map['visibility'] = Variable(visibility.value); + } + if (stackId.present) { + map['stack_id'] = Variable(stackId.value); + } + if (libraryId.present) { + map['library_id'] = Variable(libraryId.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RemoteAssetEntityCompanion(') + ..write('name: $name, ') + ..write('type: $type, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('width: $width, ') + ..write('height: $height, ') + ..write('durationInSeconds: $durationInSeconds, ') + ..write('id: $id, ') + ..write('checksum: $checksum, ') + ..write('isFavorite: $isFavorite, ') + ..write('ownerId: $ownerId, ') + ..write('localDateTime: $localDateTime, ') + ..write('thumbHash: $thumbHash, ') + ..write('deletedAt: $deletedAt, ') + ..write('livePhotoVideoId: $livePhotoVideoId, ') + ..write('visibility: $visibility, ') + ..write('stackId: $stackId, ') + ..write('libraryId: $libraryId') + ..write(')')) + .toString(); + } +} + +class StackEntity extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + StackEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn ownerId = GeneratedColumn( + 'owner_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn primaryAssetId = GeneratedColumn( + 'primary_asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + ownerId, + primaryAssetId, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'stack_entity'; + @override + Set get $primaryKey => {id}; + @override + StackEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return StackEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + ownerId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}owner_id'], + )!, + primaryAssetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}primary_asset_id'], + )!, + ); + } + + @override + StackEntity createAlias(String alias) { + return StackEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class StackEntityData extends DataClass implements Insertable { + final String id; + final DateTime createdAt; + final DateTime updatedAt; + final String ownerId; + final String primaryAssetId; + const StackEntityData({ + required this.id, + required this.createdAt, + required this.updatedAt, + required this.ownerId, + required this.primaryAssetId, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + map['owner_id'] = Variable(ownerId); + map['primary_asset_id'] = Variable(primaryAssetId); + return map; + } + + factory StackEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return StackEntityData( + id: serializer.fromJson(json['id']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + ownerId: serializer.fromJson(json['ownerId']), + primaryAssetId: serializer.fromJson(json['primaryAssetId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'ownerId': serializer.toJson(ownerId), + 'primaryAssetId': serializer.toJson(primaryAssetId), + }; + } + + StackEntityData copyWith({ + String? id, + DateTime? createdAt, + DateTime? updatedAt, + String? ownerId, + String? primaryAssetId, + }) => StackEntityData( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + primaryAssetId: primaryAssetId ?? this.primaryAssetId, + ); + StackEntityData copyWithCompanion(StackEntityCompanion data) { + return StackEntityData( + id: data.id.present ? data.id.value : this.id, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId, + primaryAssetId: data.primaryAssetId.present + ? data.primaryAssetId.value + : this.primaryAssetId, + ); + } + + @override + String toString() { + return (StringBuffer('StackEntityData(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('primaryAssetId: $primaryAssetId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => + Object.hash(id, createdAt, updatedAt, ownerId, primaryAssetId); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is StackEntityData && + other.id == this.id && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.ownerId == this.ownerId && + other.primaryAssetId == this.primaryAssetId); +} + +class StackEntityCompanion extends UpdateCompanion { + final Value id; + final Value createdAt; + final Value updatedAt; + final Value ownerId; + final Value primaryAssetId; + const StackEntityCompanion({ + this.id = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.ownerId = const Value.absent(), + this.primaryAssetId = const Value.absent(), + }); + StackEntityCompanion.insert({ + required String id, + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + required String ownerId, + required String primaryAssetId, + }) : id = Value(id), + ownerId = Value(ownerId), + primaryAssetId = Value(primaryAssetId); + static Insertable custom({ + Expression? id, + Expression? createdAt, + Expression? updatedAt, + Expression? ownerId, + Expression? primaryAssetId, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (ownerId != null) 'owner_id': ownerId, + if (primaryAssetId != null) 'primary_asset_id': primaryAssetId, + }); + } + + StackEntityCompanion copyWith({ + Value? id, + Value? createdAt, + Value? updatedAt, + Value? ownerId, + Value? primaryAssetId, + }) { + return StackEntityCompanion( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + primaryAssetId: primaryAssetId ?? this.primaryAssetId, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (ownerId.present) { + map['owner_id'] = Variable(ownerId.value); + } + if (primaryAssetId.present) { + map['primary_asset_id'] = Variable(primaryAssetId.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('StackEntityCompanion(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('primaryAssetId: $primaryAssetId') + ..write(')')) + .toString(); + } +} + +class LocalAssetEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + LocalAssetEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn type = GeneratedColumn( + 'type', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn width = GeneratedColumn( + 'width', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn height = GeneratedColumn( + 'height', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn durationInSeconds = GeneratedColumn( + 'duration_in_seconds', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn checksum = GeneratedColumn( + 'checksum', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn isFavorite = GeneratedColumn( + 'is_favorite', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_favorite" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn orientation = GeneratedColumn( + 'orientation', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0'), + ); + @override + List get $columns => [ + name, + type, + createdAt, + updatedAt, + width, + height, + durationInSeconds, + id, + checksum, + isFavorite, + orientation, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'local_asset_entity'; + @override + Set get $primaryKey => {id}; + @override + LocalAssetEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return LocalAssetEntityData( + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + type: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}type'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + width: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}width'], + ), + height: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}height'], + ), + durationInSeconds: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}duration_in_seconds'], + ), + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + checksum: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}checksum'], + ), + isFavorite: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_favorite'], + )!, + orientation: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}orientation'], + )!, + ); + } + + @override + LocalAssetEntity createAlias(String alias) { + return LocalAssetEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class LocalAssetEntityData extends DataClass + implements Insertable { + final String name; + final int type; + final DateTime createdAt; + final DateTime updatedAt; + final int? width; + final int? height; + final int? durationInSeconds; + final String id; + final String? checksum; + final bool isFavorite; + final int orientation; + const LocalAssetEntityData({ + required this.name, + required this.type, + required this.createdAt, + required this.updatedAt, + this.width, + this.height, + this.durationInSeconds, + required this.id, + this.checksum, + required this.isFavorite, + required this.orientation, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['name'] = Variable(name); + map['type'] = Variable(type); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || width != null) { + map['width'] = Variable(width); + } + if (!nullToAbsent || height != null) { + map['height'] = Variable(height); + } + if (!nullToAbsent || durationInSeconds != null) { + map['duration_in_seconds'] = Variable(durationInSeconds); + } + map['id'] = Variable(id); + if (!nullToAbsent || checksum != null) { + map['checksum'] = Variable(checksum); + } + map['is_favorite'] = Variable(isFavorite); + map['orientation'] = Variable(orientation); + return map; + } + + factory LocalAssetEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return LocalAssetEntityData( + name: serializer.fromJson(json['name']), + type: serializer.fromJson(json['type']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + width: serializer.fromJson(json['width']), + height: serializer.fromJson(json['height']), + durationInSeconds: serializer.fromJson(json['durationInSeconds']), + id: serializer.fromJson(json['id']), + checksum: serializer.fromJson(json['checksum']), + isFavorite: serializer.fromJson(json['isFavorite']), + orientation: serializer.fromJson(json['orientation']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'name': serializer.toJson(name), + 'type': serializer.toJson(type), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'width': serializer.toJson(width), + 'height': serializer.toJson(height), + 'durationInSeconds': serializer.toJson(durationInSeconds), + 'id': serializer.toJson(id), + 'checksum': serializer.toJson(checksum), + 'isFavorite': serializer.toJson(isFavorite), + 'orientation': serializer.toJson(orientation), + }; + } + + LocalAssetEntityData copyWith({ + String? name, + int? type, + DateTime? createdAt, + DateTime? updatedAt, + Value width = const Value.absent(), + Value height = const Value.absent(), + Value durationInSeconds = const Value.absent(), + String? id, + Value checksum = const Value.absent(), + bool? isFavorite, + int? orientation, + }) => LocalAssetEntityData( + name: name ?? this.name, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + width: width.present ? width.value : this.width, + height: height.present ? height.value : this.height, + durationInSeconds: durationInSeconds.present + ? durationInSeconds.value + : this.durationInSeconds, + id: id ?? this.id, + checksum: checksum.present ? checksum.value : this.checksum, + isFavorite: isFavorite ?? this.isFavorite, + orientation: orientation ?? this.orientation, + ); + LocalAssetEntityData copyWithCompanion(LocalAssetEntityCompanion data) { + return LocalAssetEntityData( + name: data.name.present ? data.name.value : this.name, + type: data.type.present ? data.type.value : this.type, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + width: data.width.present ? data.width.value : this.width, + height: data.height.present ? data.height.value : this.height, + durationInSeconds: data.durationInSeconds.present + ? data.durationInSeconds.value + : this.durationInSeconds, + id: data.id.present ? data.id.value : this.id, + checksum: data.checksum.present ? data.checksum.value : this.checksum, + isFavorite: data.isFavorite.present + ? data.isFavorite.value + : this.isFavorite, + orientation: data.orientation.present + ? data.orientation.value + : this.orientation, + ); + } + + @override + String toString() { + return (StringBuffer('LocalAssetEntityData(') + ..write('name: $name, ') + ..write('type: $type, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('width: $width, ') + ..write('height: $height, ') + ..write('durationInSeconds: $durationInSeconds, ') + ..write('id: $id, ') + ..write('checksum: $checksum, ') + ..write('isFavorite: $isFavorite, ') + ..write('orientation: $orientation') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + name, + type, + createdAt, + updatedAt, + width, + height, + durationInSeconds, + id, + checksum, + isFavorite, + orientation, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is LocalAssetEntityData && + other.name == this.name && + other.type == this.type && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.width == this.width && + other.height == this.height && + other.durationInSeconds == this.durationInSeconds && + other.id == this.id && + other.checksum == this.checksum && + other.isFavorite == this.isFavorite && + other.orientation == this.orientation); +} + +class LocalAssetEntityCompanion extends UpdateCompanion { + final Value name; + final Value type; + final Value createdAt; + final Value updatedAt; + final Value width; + final Value height; + final Value durationInSeconds; + final Value id; + final Value checksum; + final Value isFavorite; + final Value orientation; + const LocalAssetEntityCompanion({ + this.name = const Value.absent(), + this.type = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.width = const Value.absent(), + this.height = const Value.absent(), + this.durationInSeconds = const Value.absent(), + this.id = const Value.absent(), + this.checksum = const Value.absent(), + this.isFavorite = const Value.absent(), + this.orientation = const Value.absent(), + }); + LocalAssetEntityCompanion.insert({ + required String name, + required int type, + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.width = const Value.absent(), + this.height = const Value.absent(), + this.durationInSeconds = const Value.absent(), + required String id, + this.checksum = const Value.absent(), + this.isFavorite = const Value.absent(), + this.orientation = const Value.absent(), + }) : name = Value(name), + type = Value(type), + id = Value(id); + static Insertable custom({ + Expression? name, + Expression? type, + Expression? createdAt, + Expression? updatedAt, + Expression? width, + Expression? height, + Expression? durationInSeconds, + Expression? id, + Expression? checksum, + Expression? isFavorite, + Expression? orientation, + }) { + return RawValuesInsertable({ + if (name != null) 'name': name, + if (type != null) 'type': type, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (width != null) 'width': width, + if (height != null) 'height': height, + if (durationInSeconds != null) 'duration_in_seconds': durationInSeconds, + if (id != null) 'id': id, + if (checksum != null) 'checksum': checksum, + if (isFavorite != null) 'is_favorite': isFavorite, + if (orientation != null) 'orientation': orientation, + }); + } + + LocalAssetEntityCompanion copyWith({ + Value? name, + Value? type, + Value? createdAt, + Value? updatedAt, + Value? width, + Value? height, + Value? durationInSeconds, + Value? id, + Value? checksum, + Value? isFavorite, + Value? orientation, + }) { + return LocalAssetEntityCompanion( + name: name ?? this.name, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + width: width ?? this.width, + height: height ?? this.height, + durationInSeconds: durationInSeconds ?? this.durationInSeconds, + id: id ?? this.id, + checksum: checksum ?? this.checksum, + isFavorite: isFavorite ?? this.isFavorite, + orientation: orientation ?? this.orientation, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (name.present) { + map['name'] = Variable(name.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (width.present) { + map['width'] = Variable(width.value); + } + if (height.present) { + map['height'] = Variable(height.value); + } + if (durationInSeconds.present) { + map['duration_in_seconds'] = Variable(durationInSeconds.value); + } + if (id.present) { + map['id'] = Variable(id.value); + } + if (checksum.present) { + map['checksum'] = Variable(checksum.value); + } + if (isFavorite.present) { + map['is_favorite'] = Variable(isFavorite.value); + } + if (orientation.present) { + map['orientation'] = Variable(orientation.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('LocalAssetEntityCompanion(') + ..write('name: $name, ') + ..write('type: $type, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('width: $width, ') + ..write('height: $height, ') + ..write('durationInSeconds: $durationInSeconds, ') + ..write('id: $id, ') + ..write('checksum: $checksum, ') + ..write('isFavorite: $isFavorite, ') + ..write('orientation: $orientation') + ..write(')')) + .toString(); + } +} + +class RemoteAlbumEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RemoteAlbumEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn description = GeneratedColumn( + 'description', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'\''), + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn ownerId = GeneratedColumn( + 'owner_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn thumbnailAssetId = GeneratedColumn( + 'thumbnail_asset_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_asset_entity (id) ON DELETE SET NULL', + ), + ); + late final GeneratedColumn isActivityEnabled = GeneratedColumn( + 'is_activity_enabled', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_activity_enabled" IN (0, 1))', + ), + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn order = GeneratedColumn( + 'order', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + @override + List get $columns => [ + id, + name, + description, + createdAt, + updatedAt, + ownerId, + thumbnailAssetId, + isActivityEnabled, + order, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'remote_album_entity'; + @override + Set get $primaryKey => {id}; + @override + RemoteAlbumEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RemoteAlbumEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + description: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}description'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + ownerId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}owner_id'], + )!, + thumbnailAssetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}thumbnail_asset_id'], + ), + isActivityEnabled: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_activity_enabled'], + )!, + order: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}order'], + )!, + ); + } + + @override + RemoteAlbumEntity createAlias(String alias) { + return RemoteAlbumEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class RemoteAlbumEntityData extends DataClass + implements Insertable { + final String id; + final String name; + final String description; + final DateTime createdAt; + final DateTime updatedAt; + final String ownerId; + final String? thumbnailAssetId; + final bool isActivityEnabled; + final int order; + const RemoteAlbumEntityData({ + required this.id, + required this.name, + required this.description, + required this.createdAt, + required this.updatedAt, + required this.ownerId, + this.thumbnailAssetId, + required this.isActivityEnabled, + required this.order, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + map['description'] = Variable(description); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + map['owner_id'] = Variable(ownerId); + if (!nullToAbsent || thumbnailAssetId != null) { + map['thumbnail_asset_id'] = Variable(thumbnailAssetId); + } + map['is_activity_enabled'] = Variable(isActivityEnabled); + map['order'] = Variable(order); + return map; + } + + factory RemoteAlbumEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RemoteAlbumEntityData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + description: serializer.fromJson(json['description']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + ownerId: serializer.fromJson(json['ownerId']), + thumbnailAssetId: serializer.fromJson(json['thumbnailAssetId']), + isActivityEnabled: serializer.fromJson(json['isActivityEnabled']), + order: serializer.fromJson(json['order']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'description': serializer.toJson(description), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'ownerId': serializer.toJson(ownerId), + 'thumbnailAssetId': serializer.toJson(thumbnailAssetId), + 'isActivityEnabled': serializer.toJson(isActivityEnabled), + 'order': serializer.toJson(order), + }; + } + + RemoteAlbumEntityData copyWith({ + String? id, + String? name, + String? description, + DateTime? createdAt, + DateTime? updatedAt, + String? ownerId, + Value thumbnailAssetId = const Value.absent(), + bool? isActivityEnabled, + int? order, + }) => RemoteAlbumEntityData( + id: id ?? this.id, + name: name ?? this.name, + description: description ?? this.description, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + thumbnailAssetId: thumbnailAssetId.present + ? thumbnailAssetId.value + : this.thumbnailAssetId, + isActivityEnabled: isActivityEnabled ?? this.isActivityEnabled, + order: order ?? this.order, + ); + RemoteAlbumEntityData copyWithCompanion(RemoteAlbumEntityCompanion data) { + return RemoteAlbumEntityData( + id: data.id.present ? data.id.value : this.id, + name: data.name.present ? data.name.value : this.name, + description: data.description.present + ? data.description.value + : this.description, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId, + thumbnailAssetId: data.thumbnailAssetId.present + ? data.thumbnailAssetId.value + : this.thumbnailAssetId, + isActivityEnabled: data.isActivityEnabled.present + ? data.isActivityEnabled.value + : this.isActivityEnabled, + order: data.order.present ? data.order.value : this.order, + ); + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumEntityData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('description: $description, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('thumbnailAssetId: $thumbnailAssetId, ') + ..write('isActivityEnabled: $isActivityEnabled, ') + ..write('order: $order') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + name, + description, + createdAt, + updatedAt, + ownerId, + thumbnailAssetId, + isActivityEnabled, + order, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RemoteAlbumEntityData && + other.id == this.id && + other.name == this.name && + other.description == this.description && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.ownerId == this.ownerId && + other.thumbnailAssetId == this.thumbnailAssetId && + other.isActivityEnabled == this.isActivityEnabled && + other.order == this.order); +} + +class RemoteAlbumEntityCompanion + extends UpdateCompanion { + final Value id; + final Value name; + final Value description; + final Value createdAt; + final Value updatedAt; + final Value ownerId; + final Value thumbnailAssetId; + final Value isActivityEnabled; + final Value order; + const RemoteAlbumEntityCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.description = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.ownerId = const Value.absent(), + this.thumbnailAssetId = const Value.absent(), + this.isActivityEnabled = const Value.absent(), + this.order = const Value.absent(), + }); + RemoteAlbumEntityCompanion.insert({ + required String id, + required String name, + this.description = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + required String ownerId, + this.thumbnailAssetId = const Value.absent(), + this.isActivityEnabled = const Value.absent(), + required int order, + }) : id = Value(id), + name = Value(name), + ownerId = Value(ownerId), + order = Value(order); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? description, + Expression? createdAt, + Expression? updatedAt, + Expression? ownerId, + Expression? thumbnailAssetId, + Expression? isActivityEnabled, + Expression? order, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (description != null) 'description': description, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (ownerId != null) 'owner_id': ownerId, + if (thumbnailAssetId != null) 'thumbnail_asset_id': thumbnailAssetId, + if (isActivityEnabled != null) 'is_activity_enabled': isActivityEnabled, + if (order != null) 'order': order, + }); + } + + RemoteAlbumEntityCompanion copyWith({ + Value? id, + Value? name, + Value? description, + Value? createdAt, + Value? updatedAt, + Value? ownerId, + Value? thumbnailAssetId, + Value? isActivityEnabled, + Value? order, + }) { + return RemoteAlbumEntityCompanion( + id: id ?? this.id, + name: name ?? this.name, + description: description ?? this.description, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + thumbnailAssetId: thumbnailAssetId ?? this.thumbnailAssetId, + isActivityEnabled: isActivityEnabled ?? this.isActivityEnabled, + order: order ?? this.order, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (description.present) { + map['description'] = Variable(description.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (ownerId.present) { + map['owner_id'] = Variable(ownerId.value); + } + if (thumbnailAssetId.present) { + map['thumbnail_asset_id'] = Variable(thumbnailAssetId.value); + } + if (isActivityEnabled.present) { + map['is_activity_enabled'] = Variable(isActivityEnabled.value); + } + if (order.present) { + map['order'] = Variable(order.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumEntityCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('description: $description, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('thumbnailAssetId: $thumbnailAssetId, ') + ..write('isActivityEnabled: $isActivityEnabled, ') + ..write('order: $order') + ..write(')')) + .toString(); + } +} + +class LocalAlbumEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + LocalAlbumEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn backupSelection = GeneratedColumn( + 'backup_selection', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn isIosSharedAlbum = GeneratedColumn( + 'is_ios_shared_album', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_ios_shared_album" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn linkedRemoteAlbumId = + GeneratedColumn( + 'linked_remote_album_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_album_entity (id) ON DELETE SET NULL', + ), + ); + late final GeneratedColumn marker_ = GeneratedColumn( + 'marker', + aliasedName, + true, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("marker" IN (0, 1))', + ), + ); + @override + List get $columns => [ + id, + name, + updatedAt, + backupSelection, + isIosSharedAlbum, + linkedRemoteAlbumId, + marker_, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'local_album_entity'; + @override + Set get $primaryKey => {id}; + @override + LocalAlbumEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return LocalAlbumEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + backupSelection: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}backup_selection'], + )!, + isIosSharedAlbum: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_ios_shared_album'], + )!, + linkedRemoteAlbumId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}linked_remote_album_id'], + ), + marker_: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}marker'], + ), + ); + } + + @override + LocalAlbumEntity createAlias(String alias) { + return LocalAlbumEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class LocalAlbumEntityData extends DataClass + implements Insertable { + final String id; + final String name; + final DateTime updatedAt; + final int backupSelection; + final bool isIosSharedAlbum; + final String? linkedRemoteAlbumId; + final bool? marker_; + const LocalAlbumEntityData({ + required this.id, + required this.name, + required this.updatedAt, + required this.backupSelection, + required this.isIosSharedAlbum, + this.linkedRemoteAlbumId, + this.marker_, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + map['updated_at'] = Variable(updatedAt); + map['backup_selection'] = Variable(backupSelection); + map['is_ios_shared_album'] = Variable(isIosSharedAlbum); + if (!nullToAbsent || linkedRemoteAlbumId != null) { + map['linked_remote_album_id'] = Variable(linkedRemoteAlbumId); + } + if (!nullToAbsent || marker_ != null) { + map['marker'] = Variable(marker_); + } + return map; + } + + factory LocalAlbumEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return LocalAlbumEntityData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + updatedAt: serializer.fromJson(json['updatedAt']), + backupSelection: serializer.fromJson(json['backupSelection']), + isIosSharedAlbum: serializer.fromJson(json['isIosSharedAlbum']), + linkedRemoteAlbumId: serializer.fromJson( + json['linkedRemoteAlbumId'], + ), + marker_: serializer.fromJson(json['marker_']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'updatedAt': serializer.toJson(updatedAt), + 'backupSelection': serializer.toJson(backupSelection), + 'isIosSharedAlbum': serializer.toJson(isIosSharedAlbum), + 'linkedRemoteAlbumId': serializer.toJson(linkedRemoteAlbumId), + 'marker_': serializer.toJson(marker_), + }; + } + + LocalAlbumEntityData copyWith({ + String? id, + String? name, + DateTime? updatedAt, + int? backupSelection, + bool? isIosSharedAlbum, + Value linkedRemoteAlbumId = const Value.absent(), + Value marker_ = const Value.absent(), + }) => LocalAlbumEntityData( + id: id ?? this.id, + name: name ?? this.name, + updatedAt: updatedAt ?? this.updatedAt, + backupSelection: backupSelection ?? this.backupSelection, + isIosSharedAlbum: isIosSharedAlbum ?? this.isIosSharedAlbum, + linkedRemoteAlbumId: linkedRemoteAlbumId.present + ? linkedRemoteAlbumId.value + : this.linkedRemoteAlbumId, + marker_: marker_.present ? marker_.value : this.marker_, + ); + LocalAlbumEntityData copyWithCompanion(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, + backupSelection: data.backupSelection.present + ? data.backupSelection.value + : this.backupSelection, + isIosSharedAlbum: data.isIosSharedAlbum.present + ? data.isIosSharedAlbum.value + : this.isIosSharedAlbum, + linkedRemoteAlbumId: data.linkedRemoteAlbumId.present + ? data.linkedRemoteAlbumId.value + : this.linkedRemoteAlbumId, + marker_: data.marker_.present ? data.marker_.value : this.marker_, + ); + } + + @override + String toString() { + return (StringBuffer('LocalAlbumEntityData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('updatedAt: $updatedAt, ') + ..write('backupSelection: $backupSelection, ') + ..write('isIosSharedAlbum: $isIosSharedAlbum, ') + ..write('linkedRemoteAlbumId: $linkedRemoteAlbumId, ') + ..write('marker_: $marker_') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + name, + updatedAt, + backupSelection, + isIosSharedAlbum, + linkedRemoteAlbumId, + marker_, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is LocalAlbumEntityData && + other.id == this.id && + other.name == this.name && + other.updatedAt == this.updatedAt && + other.backupSelection == this.backupSelection && + other.isIosSharedAlbum == this.isIosSharedAlbum && + other.linkedRemoteAlbumId == this.linkedRemoteAlbumId && + other.marker_ == this.marker_); +} + +class LocalAlbumEntityCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value updatedAt; + final Value backupSelection; + final Value isIosSharedAlbum; + final Value linkedRemoteAlbumId; + final Value marker_; + const LocalAlbumEntityCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.updatedAt = const Value.absent(), + this.backupSelection = const Value.absent(), + this.isIosSharedAlbum = const Value.absent(), + this.linkedRemoteAlbumId = const Value.absent(), + this.marker_ = const Value.absent(), + }); + LocalAlbumEntityCompanion.insert({ + required String id, + required String name, + this.updatedAt = const Value.absent(), + required int backupSelection, + this.isIosSharedAlbum = const Value.absent(), + this.linkedRemoteAlbumId = const Value.absent(), + this.marker_ = const Value.absent(), + }) : id = Value(id), + name = Value(name), + backupSelection = Value(backupSelection); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? updatedAt, + Expression? backupSelection, + Expression? isIosSharedAlbum, + Expression? linkedRemoteAlbumId, + Expression? marker_, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (updatedAt != null) 'updated_at': updatedAt, + if (backupSelection != null) 'backup_selection': backupSelection, + if (isIosSharedAlbum != null) 'is_ios_shared_album': isIosSharedAlbum, + if (linkedRemoteAlbumId != null) + 'linked_remote_album_id': linkedRemoteAlbumId, + if (marker_ != null) 'marker': marker_, + }); + } + + LocalAlbumEntityCompanion copyWith({ + Value? id, + Value? name, + Value? updatedAt, + Value? backupSelection, + Value? isIosSharedAlbum, + Value? linkedRemoteAlbumId, + Value? marker_, + }) { + return LocalAlbumEntityCompanion( + id: id ?? this.id, + name: name ?? this.name, + updatedAt: updatedAt ?? this.updatedAt, + backupSelection: backupSelection ?? this.backupSelection, + isIosSharedAlbum: isIosSharedAlbum ?? this.isIosSharedAlbum, + linkedRemoteAlbumId: linkedRemoteAlbumId ?? this.linkedRemoteAlbumId, + marker_: marker_ ?? this.marker_, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (backupSelection.present) { + map['backup_selection'] = Variable(backupSelection.value); + } + if (isIosSharedAlbum.present) { + map['is_ios_shared_album'] = Variable(isIosSharedAlbum.value); + } + if (linkedRemoteAlbumId.present) { + map['linked_remote_album_id'] = Variable( + linkedRemoteAlbumId.value, + ); + } + if (marker_.present) { + map['marker'] = Variable(marker_.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('LocalAlbumEntityCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('updatedAt: $updatedAt, ') + ..write('backupSelection: $backupSelection, ') + ..write('isIosSharedAlbum: $isIosSharedAlbum, ') + ..write('linkedRemoteAlbumId: $linkedRemoteAlbumId, ') + ..write('marker_: $marker_') + ..write(')')) + .toString(); + } +} + +class LocalAlbumAssetEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + LocalAlbumAssetEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn assetId = GeneratedColumn( + 'asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES local_asset_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn albumId = GeneratedColumn( + 'album_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES local_album_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn marker_ = GeneratedColumn( + 'marker', + aliasedName, + true, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("marker" IN (0, 1))', + ), + ); + @override + List get $columns => [assetId, albumId, marker_]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'local_album_asset_entity'; + @override + Set get $primaryKey => {assetId, albumId}; + @override + LocalAlbumAssetEntityData map( + Map data, { + String? tablePrefix, + }) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return LocalAlbumAssetEntityData( + assetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}asset_id'], + )!, + albumId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}album_id'], + )!, + marker_: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}marker'], + ), + ); + } + + @override + LocalAlbumAssetEntity createAlias(String alias) { + return LocalAlbumAssetEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class LocalAlbumAssetEntityData extends DataClass + implements Insertable { + final String assetId; + final String albumId; + final bool? marker_; + const LocalAlbumAssetEntityData({ + required this.assetId, + required this.albumId, + this.marker_, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['asset_id'] = Variable(assetId); + map['album_id'] = Variable(albumId); + if (!nullToAbsent || marker_ != null) { + map['marker'] = Variable(marker_); + } + return map; + } + + factory LocalAlbumAssetEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return LocalAlbumAssetEntityData( + assetId: serializer.fromJson(json['assetId']), + albumId: serializer.fromJson(json['albumId']), + marker_: serializer.fromJson(json['marker_']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'assetId': serializer.toJson(assetId), + 'albumId': serializer.toJson(albumId), + 'marker_': serializer.toJson(marker_), + }; + } + + LocalAlbumAssetEntityData copyWith({ + String? assetId, + String? albumId, + Value marker_ = const Value.absent(), + }) => LocalAlbumAssetEntityData( + assetId: assetId ?? this.assetId, + albumId: albumId ?? this.albumId, + marker_: marker_.present ? marker_.value : this.marker_, + ); + LocalAlbumAssetEntityData copyWithCompanion( + LocalAlbumAssetEntityCompanion data, + ) { + return LocalAlbumAssetEntityData( + assetId: data.assetId.present ? data.assetId.value : this.assetId, + albumId: data.albumId.present ? data.albumId.value : this.albumId, + marker_: data.marker_.present ? data.marker_.value : this.marker_, + ); + } + + @override + String toString() { + return (StringBuffer('LocalAlbumAssetEntityData(') + ..write('assetId: $assetId, ') + ..write('albumId: $albumId, ') + ..write('marker_: $marker_') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(assetId, albumId, marker_); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is LocalAlbumAssetEntityData && + other.assetId == this.assetId && + other.albumId == this.albumId && + other.marker_ == this.marker_); +} + +class LocalAlbumAssetEntityCompanion + extends UpdateCompanion { + final Value assetId; + final Value albumId; + final Value marker_; + const LocalAlbumAssetEntityCompanion({ + this.assetId = const Value.absent(), + this.albumId = const Value.absent(), + this.marker_ = const Value.absent(), + }); + LocalAlbumAssetEntityCompanion.insert({ + required String assetId, + required String albumId, + this.marker_ = const Value.absent(), + }) : assetId = Value(assetId), + albumId = Value(albumId); + static Insertable custom({ + Expression? assetId, + Expression? albumId, + Expression? marker_, + }) { + return RawValuesInsertable({ + if (assetId != null) 'asset_id': assetId, + if (albumId != null) 'album_id': albumId, + if (marker_ != null) 'marker': marker_, + }); + } + + LocalAlbumAssetEntityCompanion copyWith({ + Value? assetId, + Value? albumId, + Value? marker_, + }) { + return LocalAlbumAssetEntityCompanion( + assetId: assetId ?? this.assetId, + albumId: albumId ?? this.albumId, + marker_: marker_ ?? this.marker_, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (assetId.present) { + map['asset_id'] = Variable(assetId.value); + } + if (albumId.present) { + map['album_id'] = Variable(albumId.value); + } + if (marker_.present) { + map['marker'] = Variable(marker_.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('LocalAlbumAssetEntityCompanion(') + ..write('assetId: $assetId, ') + ..write('albumId: $albumId, ') + ..write('marker_: $marker_') + ..write(')')) + .toString(); + } +} + +class AuthUserEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + AuthUserEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn email = GeneratedColumn( + 'email', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn isAdmin = GeneratedColumn( + 'is_admin', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_admin" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn hasProfileImage = GeneratedColumn( + 'has_profile_image', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("has_profile_image" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn profileChangedAt = + GeneratedColumn( + 'profile_changed_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn avatarColor = GeneratedColumn( + 'avatar_color', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn quotaSizeInBytes = GeneratedColumn( + 'quota_size_in_bytes', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn quotaUsageInBytes = GeneratedColumn( + 'quota_usage_in_bytes', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn pinCode = GeneratedColumn( + 'pin_code', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + @override + List get $columns => [ + id, + name, + email, + isAdmin, + hasProfileImage, + profileChangedAt, + avatarColor, + quotaSizeInBytes, + quotaUsageInBytes, + pinCode, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'auth_user_entity'; + @override + Set get $primaryKey => {id}; + @override + AuthUserEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return AuthUserEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + email: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}email'], + )!, + isAdmin: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_admin'], + )!, + hasProfileImage: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}has_profile_image'], + )!, + profileChangedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}profile_changed_at'], + )!, + avatarColor: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}avatar_color'], + )!, + quotaSizeInBytes: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}quota_size_in_bytes'], + )!, + quotaUsageInBytes: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}quota_usage_in_bytes'], + )!, + pinCode: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}pin_code'], + ), + ); + } + + @override + AuthUserEntity createAlias(String alias) { + return AuthUserEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class AuthUserEntityData extends DataClass + implements Insertable { + final String id; + final String name; + final String email; + final bool isAdmin; + final bool hasProfileImage; + final DateTime profileChangedAt; + final int avatarColor; + final int quotaSizeInBytes; + final int quotaUsageInBytes; + final String? pinCode; + const AuthUserEntityData({ + required this.id, + required this.name, + required this.email, + required this.isAdmin, + required this.hasProfileImage, + required this.profileChangedAt, + required this.avatarColor, + required this.quotaSizeInBytes, + required this.quotaUsageInBytes, + this.pinCode, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + map['email'] = Variable(email); + map['is_admin'] = Variable(isAdmin); + map['has_profile_image'] = Variable(hasProfileImage); + map['profile_changed_at'] = Variable(profileChangedAt); + map['avatar_color'] = Variable(avatarColor); + map['quota_size_in_bytes'] = Variable(quotaSizeInBytes); + map['quota_usage_in_bytes'] = Variable(quotaUsageInBytes); + if (!nullToAbsent || pinCode != null) { + map['pin_code'] = Variable(pinCode); + } + return map; + } + + factory AuthUserEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return AuthUserEntityData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + email: serializer.fromJson(json['email']), + isAdmin: serializer.fromJson(json['isAdmin']), + hasProfileImage: serializer.fromJson(json['hasProfileImage']), + profileChangedAt: serializer.fromJson(json['profileChangedAt']), + avatarColor: serializer.fromJson(json['avatarColor']), + quotaSizeInBytes: serializer.fromJson(json['quotaSizeInBytes']), + quotaUsageInBytes: serializer.fromJson(json['quotaUsageInBytes']), + pinCode: serializer.fromJson(json['pinCode']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'email': serializer.toJson(email), + 'isAdmin': serializer.toJson(isAdmin), + 'hasProfileImage': serializer.toJson(hasProfileImage), + 'profileChangedAt': serializer.toJson(profileChangedAt), + 'avatarColor': serializer.toJson(avatarColor), + 'quotaSizeInBytes': serializer.toJson(quotaSizeInBytes), + 'quotaUsageInBytes': serializer.toJson(quotaUsageInBytes), + 'pinCode': serializer.toJson(pinCode), + }; + } + + AuthUserEntityData copyWith({ + String? id, + String? name, + String? email, + bool? isAdmin, + bool? hasProfileImage, + DateTime? profileChangedAt, + int? avatarColor, + int? quotaSizeInBytes, + int? quotaUsageInBytes, + Value pinCode = const Value.absent(), + }) => AuthUserEntityData( + id: id ?? this.id, + name: name ?? this.name, + email: email ?? this.email, + isAdmin: isAdmin ?? this.isAdmin, + hasProfileImage: hasProfileImage ?? this.hasProfileImage, + profileChangedAt: profileChangedAt ?? this.profileChangedAt, + avatarColor: avatarColor ?? this.avatarColor, + quotaSizeInBytes: quotaSizeInBytes ?? this.quotaSizeInBytes, + quotaUsageInBytes: quotaUsageInBytes ?? this.quotaUsageInBytes, + pinCode: pinCode.present ? pinCode.value : this.pinCode, + ); + AuthUserEntityData copyWithCompanion(AuthUserEntityCompanion data) { + return AuthUserEntityData( + id: data.id.present ? data.id.value : this.id, + name: data.name.present ? data.name.value : this.name, + email: data.email.present ? data.email.value : this.email, + isAdmin: data.isAdmin.present ? data.isAdmin.value : this.isAdmin, + hasProfileImage: data.hasProfileImage.present + ? data.hasProfileImage.value + : this.hasProfileImage, + profileChangedAt: data.profileChangedAt.present + ? data.profileChangedAt.value + : this.profileChangedAt, + avatarColor: data.avatarColor.present + ? data.avatarColor.value + : this.avatarColor, + quotaSizeInBytes: data.quotaSizeInBytes.present + ? data.quotaSizeInBytes.value + : this.quotaSizeInBytes, + quotaUsageInBytes: data.quotaUsageInBytes.present + ? data.quotaUsageInBytes.value + : this.quotaUsageInBytes, + pinCode: data.pinCode.present ? data.pinCode.value : this.pinCode, + ); + } + + @override + String toString() { + return (StringBuffer('AuthUserEntityData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('email: $email, ') + ..write('isAdmin: $isAdmin, ') + ..write('hasProfileImage: $hasProfileImage, ') + ..write('profileChangedAt: $profileChangedAt, ') + ..write('avatarColor: $avatarColor, ') + ..write('quotaSizeInBytes: $quotaSizeInBytes, ') + ..write('quotaUsageInBytes: $quotaUsageInBytes, ') + ..write('pinCode: $pinCode') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + name, + email, + isAdmin, + hasProfileImage, + profileChangedAt, + avatarColor, + quotaSizeInBytes, + quotaUsageInBytes, + pinCode, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is AuthUserEntityData && + other.id == this.id && + other.name == this.name && + other.email == this.email && + other.isAdmin == this.isAdmin && + other.hasProfileImage == this.hasProfileImage && + other.profileChangedAt == this.profileChangedAt && + other.avatarColor == this.avatarColor && + other.quotaSizeInBytes == this.quotaSizeInBytes && + other.quotaUsageInBytes == this.quotaUsageInBytes && + other.pinCode == this.pinCode); +} + +class AuthUserEntityCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value email; + final Value isAdmin; + final Value hasProfileImage; + final Value profileChangedAt; + final Value avatarColor; + final Value quotaSizeInBytes; + final Value quotaUsageInBytes; + final Value pinCode; + const AuthUserEntityCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.email = const Value.absent(), + this.isAdmin = const Value.absent(), + this.hasProfileImage = const Value.absent(), + this.profileChangedAt = const Value.absent(), + this.avatarColor = const Value.absent(), + this.quotaSizeInBytes = const Value.absent(), + this.quotaUsageInBytes = const Value.absent(), + this.pinCode = const Value.absent(), + }); + AuthUserEntityCompanion.insert({ + required String id, + required String name, + required String email, + this.isAdmin = const Value.absent(), + this.hasProfileImage = const Value.absent(), + this.profileChangedAt = const Value.absent(), + required int avatarColor, + this.quotaSizeInBytes = const Value.absent(), + this.quotaUsageInBytes = const Value.absent(), + this.pinCode = const Value.absent(), + }) : id = Value(id), + name = Value(name), + email = Value(email), + avatarColor = Value(avatarColor); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? email, + Expression? isAdmin, + Expression? hasProfileImage, + Expression? profileChangedAt, + Expression? avatarColor, + Expression? quotaSizeInBytes, + Expression? quotaUsageInBytes, + Expression? pinCode, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (email != null) 'email': email, + if (isAdmin != null) 'is_admin': isAdmin, + if (hasProfileImage != null) 'has_profile_image': hasProfileImage, + if (profileChangedAt != null) 'profile_changed_at': profileChangedAt, + if (avatarColor != null) 'avatar_color': avatarColor, + if (quotaSizeInBytes != null) 'quota_size_in_bytes': quotaSizeInBytes, + if (quotaUsageInBytes != null) 'quota_usage_in_bytes': quotaUsageInBytes, + if (pinCode != null) 'pin_code': pinCode, + }); + } + + AuthUserEntityCompanion copyWith({ + Value? id, + Value? name, + Value? email, + Value? isAdmin, + Value? hasProfileImage, + Value? profileChangedAt, + Value? avatarColor, + Value? quotaSizeInBytes, + Value? quotaUsageInBytes, + Value? pinCode, + }) { + return AuthUserEntityCompanion( + id: id ?? this.id, + name: name ?? this.name, + email: email ?? this.email, + isAdmin: isAdmin ?? this.isAdmin, + hasProfileImage: hasProfileImage ?? this.hasProfileImage, + profileChangedAt: profileChangedAt ?? this.profileChangedAt, + avatarColor: avatarColor ?? this.avatarColor, + quotaSizeInBytes: quotaSizeInBytes ?? this.quotaSizeInBytes, + quotaUsageInBytes: quotaUsageInBytes ?? this.quotaUsageInBytes, + pinCode: pinCode ?? this.pinCode, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (email.present) { + map['email'] = Variable(email.value); + } + if (isAdmin.present) { + map['is_admin'] = Variable(isAdmin.value); + } + if (hasProfileImage.present) { + map['has_profile_image'] = Variable(hasProfileImage.value); + } + if (profileChangedAt.present) { + map['profile_changed_at'] = Variable(profileChangedAt.value); + } + if (avatarColor.present) { + map['avatar_color'] = Variable(avatarColor.value); + } + if (quotaSizeInBytes.present) { + map['quota_size_in_bytes'] = Variable(quotaSizeInBytes.value); + } + if (quotaUsageInBytes.present) { + map['quota_usage_in_bytes'] = Variable(quotaUsageInBytes.value); + } + if (pinCode.present) { + map['pin_code'] = Variable(pinCode.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('AuthUserEntityCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('email: $email, ') + ..write('isAdmin: $isAdmin, ') + ..write('hasProfileImage: $hasProfileImage, ') + ..write('profileChangedAt: $profileChangedAt, ') + ..write('avatarColor: $avatarColor, ') + ..write('quotaSizeInBytes: $quotaSizeInBytes, ') + ..write('quotaUsageInBytes: $quotaUsageInBytes, ') + ..write('pinCode: $pinCode') + ..write(')')) + .toString(); + } +} + +class UserMetadataEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + UserMetadataEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn key = GeneratedColumn( + 'key', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn value = GeneratedColumn( + 'value', + aliasedName, + false, + type: DriftSqlType.blob, + requiredDuringInsert: true, + ); + @override + List get $columns => [userId, key, value]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'user_metadata_entity'; + @override + Set get $primaryKey => {userId, key}; + @override + UserMetadataEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return UserMetadataEntityData( + userId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}user_id'], + )!, + key: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}key'], + )!, + value: attachedDatabase.typeMapping.read( + DriftSqlType.blob, + data['${effectivePrefix}value'], + )!, + ); + } + + @override + UserMetadataEntity createAlias(String alias) { + return UserMetadataEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class UserMetadataEntityData extends DataClass + implements Insertable { + final String userId; + final int key; + final Uint8List value; + const UserMetadataEntityData({ + required this.userId, + required this.key, + required this.value, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['user_id'] = Variable(userId); + map['key'] = Variable(key); + map['value'] = Variable(value); + return map; + } + + factory UserMetadataEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return UserMetadataEntityData( + userId: serializer.fromJson(json['userId']), + key: serializer.fromJson(json['key']), + value: serializer.fromJson(json['value']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'userId': serializer.toJson(userId), + 'key': serializer.toJson(key), + 'value': serializer.toJson(value), + }; + } + + UserMetadataEntityData copyWith({ + String? userId, + int? key, + Uint8List? value, + }) => UserMetadataEntityData( + userId: userId ?? this.userId, + key: key ?? this.key, + value: value ?? this.value, + ); + UserMetadataEntityData copyWithCompanion(UserMetadataEntityCompanion data) { + return UserMetadataEntityData( + userId: data.userId.present ? data.userId.value : this.userId, + key: data.key.present ? data.key.value : this.key, + value: data.value.present ? data.value.value : this.value, + ); + } + + @override + String toString() { + return (StringBuffer('UserMetadataEntityData(') + ..write('userId: $userId, ') + ..write('key: $key, ') + ..write('value: $value') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(userId, key, $driftBlobEquality.hash(value)); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is UserMetadataEntityData && + other.userId == this.userId && + other.key == this.key && + $driftBlobEquality.equals(other.value, this.value)); +} + +class UserMetadataEntityCompanion + extends UpdateCompanion { + final Value userId; + final Value key; + final Value value; + const UserMetadataEntityCompanion({ + this.userId = const Value.absent(), + this.key = const Value.absent(), + this.value = const Value.absent(), + }); + UserMetadataEntityCompanion.insert({ + required String userId, + required int key, + required Uint8List value, + }) : userId = Value(userId), + key = Value(key), + value = Value(value); + static Insertable custom({ + Expression? userId, + Expression? key, + Expression? value, + }) { + return RawValuesInsertable({ + if (userId != null) 'user_id': userId, + if (key != null) 'key': key, + if (value != null) 'value': value, + }); + } + + UserMetadataEntityCompanion copyWith({ + Value? userId, + Value? key, + Value? value, + }) { + return UserMetadataEntityCompanion( + userId: userId ?? this.userId, + key: key ?? this.key, + value: value ?? this.value, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (key.present) { + map['key'] = Variable(key.value); + } + if (value.present) { + map['value'] = Variable(value.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('UserMetadataEntityCompanion(') + ..write('userId: $userId, ') + ..write('key: $key, ') + ..write('value: $value') + ..write(')')) + .toString(); + } +} + +class PartnerEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + PartnerEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn sharedById = GeneratedColumn( + 'shared_by_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn sharedWithId = GeneratedColumn( + 'shared_with_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn inTimeline = GeneratedColumn( + 'in_timeline', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("in_timeline" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + @override + List get $columns => [sharedById, sharedWithId, inTimeline]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'partner_entity'; + @override + Set get $primaryKey => {sharedById, sharedWithId}; + @override + PartnerEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return PartnerEntityData( + sharedById: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}shared_by_id'], + )!, + sharedWithId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}shared_with_id'], + )!, + inTimeline: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}in_timeline'], + )!, + ); + } + + @override + PartnerEntity createAlias(String alias) { + return PartnerEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class PartnerEntityData extends DataClass + implements Insertable { + final String sharedById; + final String sharedWithId; + final bool inTimeline; + const PartnerEntityData({ + required this.sharedById, + required this.sharedWithId, + required this.inTimeline, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['shared_by_id'] = Variable(sharedById); + map['shared_with_id'] = Variable(sharedWithId); + map['in_timeline'] = Variable(inTimeline); + return map; + } + + factory PartnerEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return PartnerEntityData( + sharedById: serializer.fromJson(json['sharedById']), + sharedWithId: serializer.fromJson(json['sharedWithId']), + inTimeline: serializer.fromJson(json['inTimeline']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'sharedById': serializer.toJson(sharedById), + 'sharedWithId': serializer.toJson(sharedWithId), + 'inTimeline': serializer.toJson(inTimeline), + }; + } + + PartnerEntityData copyWith({ + String? sharedById, + String? sharedWithId, + bool? inTimeline, + }) => PartnerEntityData( + sharedById: sharedById ?? this.sharedById, + sharedWithId: sharedWithId ?? this.sharedWithId, + inTimeline: inTimeline ?? this.inTimeline, + ); + PartnerEntityData copyWithCompanion(PartnerEntityCompanion data) { + return PartnerEntityData( + sharedById: data.sharedById.present + ? data.sharedById.value + : this.sharedById, + sharedWithId: data.sharedWithId.present + ? data.sharedWithId.value + : this.sharedWithId, + inTimeline: data.inTimeline.present + ? data.inTimeline.value + : this.inTimeline, + ); + } + + @override + String toString() { + return (StringBuffer('PartnerEntityData(') + ..write('sharedById: $sharedById, ') + ..write('sharedWithId: $sharedWithId, ') + ..write('inTimeline: $inTimeline') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(sharedById, sharedWithId, inTimeline); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is PartnerEntityData && + other.sharedById == this.sharedById && + other.sharedWithId == this.sharedWithId && + other.inTimeline == this.inTimeline); +} + +class PartnerEntityCompanion extends UpdateCompanion { + final Value sharedById; + final Value sharedWithId; + final Value inTimeline; + const PartnerEntityCompanion({ + this.sharedById = const Value.absent(), + this.sharedWithId = const Value.absent(), + this.inTimeline = const Value.absent(), + }); + PartnerEntityCompanion.insert({ + required String sharedById, + required String sharedWithId, + this.inTimeline = const Value.absent(), + }) : sharedById = Value(sharedById), + sharedWithId = Value(sharedWithId); + static Insertable custom({ + Expression? sharedById, + Expression? sharedWithId, + Expression? inTimeline, + }) { + return RawValuesInsertable({ + if (sharedById != null) 'shared_by_id': sharedById, + if (sharedWithId != null) 'shared_with_id': sharedWithId, + if (inTimeline != null) 'in_timeline': inTimeline, + }); + } + + PartnerEntityCompanion copyWith({ + Value? sharedById, + Value? sharedWithId, + Value? inTimeline, + }) { + return PartnerEntityCompanion( + sharedById: sharedById ?? this.sharedById, + sharedWithId: sharedWithId ?? this.sharedWithId, + inTimeline: inTimeline ?? this.inTimeline, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (sharedById.present) { + map['shared_by_id'] = Variable(sharedById.value); + } + if (sharedWithId.present) { + map['shared_with_id'] = Variable(sharedWithId.value); + } + if (inTimeline.present) { + map['in_timeline'] = Variable(inTimeline.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('PartnerEntityCompanion(') + ..write('sharedById: $sharedById, ') + ..write('sharedWithId: $sharedWithId, ') + ..write('inTimeline: $inTimeline') + ..write(')')) + .toString(); + } +} + +class RemoteExifEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RemoteExifEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn assetId = GeneratedColumn( + 'asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_asset_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn city = GeneratedColumn( + 'city', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn state = GeneratedColumn( + 'state', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn country = GeneratedColumn( + 'country', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn dateTimeOriginal = + GeneratedColumn( + 'date_time_original', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn description = GeneratedColumn( + 'description', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn height = GeneratedColumn( + 'height', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn width = GeneratedColumn( + 'width', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn exposureTime = GeneratedColumn( + 'exposure_time', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn fNumber = GeneratedColumn( + 'f_number', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + ); + late final GeneratedColumn fileSize = GeneratedColumn( + 'file_size', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn focalLength = GeneratedColumn( + 'focal_length', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + ); + late final GeneratedColumn latitude = GeneratedColumn( + 'latitude', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + ); + late final GeneratedColumn longitude = GeneratedColumn( + 'longitude', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + ); + late final GeneratedColumn iso = GeneratedColumn( + 'iso', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn make = GeneratedColumn( + 'make', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn model = GeneratedColumn( + 'model', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn lens = GeneratedColumn( + 'lens', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn orientation = GeneratedColumn( + 'orientation', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn timeZone = GeneratedColumn( + 'time_zone', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn rating = GeneratedColumn( + 'rating', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn projectionType = GeneratedColumn( + 'projection_type', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + @override + List get $columns => [ + assetId, + city, + state, + country, + dateTimeOriginal, + description, + height, + width, + exposureTime, + fNumber, + fileSize, + focalLength, + latitude, + longitude, + iso, + make, + model, + lens, + orientation, + timeZone, + rating, + projectionType, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'remote_exif_entity'; + @override + Set get $primaryKey => {assetId}; + @override + RemoteExifEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RemoteExifEntityData( + assetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}asset_id'], + )!, + city: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}city'], + ), + state: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}state'], + ), + country: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}country'], + ), + dateTimeOriginal: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}date_time_original'], + ), + description: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}description'], + ), + height: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}height'], + ), + width: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}width'], + ), + exposureTime: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}exposure_time'], + ), + fNumber: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}f_number'], + ), + fileSize: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}file_size'], + ), + focalLength: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}focal_length'], + ), + latitude: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}latitude'], + ), + longitude: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}longitude'], + ), + iso: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}iso'], + ), + make: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}make'], + ), + model: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}model'], + ), + lens: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}lens'], + ), + orientation: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}orientation'], + ), + timeZone: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}time_zone'], + ), + rating: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}rating'], + ), + projectionType: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}projection_type'], + ), + ); + } + + @override + RemoteExifEntity createAlias(String alias) { + return RemoteExifEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class RemoteExifEntityData extends DataClass + implements Insertable { + final String assetId; + final String? city; + final String? state; + final String? country; + final DateTime? dateTimeOriginal; + final String? description; + final int? height; + final int? width; + final String? exposureTime; + final double? fNumber; + final int? fileSize; + final double? focalLength; + final double? latitude; + final double? longitude; + final int? iso; + final String? make; + final String? model; + final String? lens; + final String? orientation; + final String? timeZone; + final int? rating; + final String? projectionType; + const RemoteExifEntityData({ + required this.assetId, + this.city, + this.state, + this.country, + this.dateTimeOriginal, + this.description, + this.height, + this.width, + this.exposureTime, + this.fNumber, + this.fileSize, + this.focalLength, + this.latitude, + this.longitude, + this.iso, + this.make, + this.model, + this.lens, + this.orientation, + this.timeZone, + this.rating, + this.projectionType, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['asset_id'] = Variable(assetId); + if (!nullToAbsent || city != null) { + map['city'] = Variable(city); + } + if (!nullToAbsent || state != null) { + map['state'] = Variable(state); + } + if (!nullToAbsent || country != null) { + map['country'] = Variable(country); + } + if (!nullToAbsent || dateTimeOriginal != null) { + map['date_time_original'] = Variable(dateTimeOriginal); + } + if (!nullToAbsent || description != null) { + map['description'] = Variable(description); + } + if (!nullToAbsent || height != null) { + map['height'] = Variable(height); + } + if (!nullToAbsent || width != null) { + map['width'] = Variable(width); + } + if (!nullToAbsent || exposureTime != null) { + map['exposure_time'] = Variable(exposureTime); + } + if (!nullToAbsent || fNumber != null) { + map['f_number'] = Variable(fNumber); + } + if (!nullToAbsent || fileSize != null) { + map['file_size'] = Variable(fileSize); + } + if (!nullToAbsent || focalLength != null) { + map['focal_length'] = Variable(focalLength); + } + if (!nullToAbsent || latitude != null) { + map['latitude'] = Variable(latitude); + } + if (!nullToAbsent || longitude != null) { + map['longitude'] = Variable(longitude); + } + if (!nullToAbsent || iso != null) { + map['iso'] = Variable(iso); + } + if (!nullToAbsent || make != null) { + map['make'] = Variable(make); + } + if (!nullToAbsent || model != null) { + map['model'] = Variable(model); + } + if (!nullToAbsent || lens != null) { + map['lens'] = Variable(lens); + } + if (!nullToAbsent || orientation != null) { + map['orientation'] = Variable(orientation); + } + if (!nullToAbsent || timeZone != null) { + map['time_zone'] = Variable(timeZone); + } + if (!nullToAbsent || rating != null) { + map['rating'] = Variable(rating); + } + if (!nullToAbsent || projectionType != null) { + map['projection_type'] = Variable(projectionType); + } + return map; + } + + factory RemoteExifEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RemoteExifEntityData( + assetId: serializer.fromJson(json['assetId']), + city: serializer.fromJson(json['city']), + state: serializer.fromJson(json['state']), + country: serializer.fromJson(json['country']), + dateTimeOriginal: serializer.fromJson( + json['dateTimeOriginal'], + ), + description: serializer.fromJson(json['description']), + height: serializer.fromJson(json['height']), + width: serializer.fromJson(json['width']), + exposureTime: serializer.fromJson(json['exposureTime']), + fNumber: serializer.fromJson(json['fNumber']), + fileSize: serializer.fromJson(json['fileSize']), + focalLength: serializer.fromJson(json['focalLength']), + latitude: serializer.fromJson(json['latitude']), + longitude: serializer.fromJson(json['longitude']), + iso: serializer.fromJson(json['iso']), + make: serializer.fromJson(json['make']), + model: serializer.fromJson(json['model']), + lens: serializer.fromJson(json['lens']), + orientation: serializer.fromJson(json['orientation']), + timeZone: serializer.fromJson(json['timeZone']), + rating: serializer.fromJson(json['rating']), + projectionType: serializer.fromJson(json['projectionType']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'assetId': serializer.toJson(assetId), + 'city': serializer.toJson(city), + 'state': serializer.toJson(state), + 'country': serializer.toJson(country), + 'dateTimeOriginal': serializer.toJson(dateTimeOriginal), + 'description': serializer.toJson(description), + 'height': serializer.toJson(height), + 'width': serializer.toJson(width), + 'exposureTime': serializer.toJson(exposureTime), + 'fNumber': serializer.toJson(fNumber), + 'fileSize': serializer.toJson(fileSize), + 'focalLength': serializer.toJson(focalLength), + 'latitude': serializer.toJson(latitude), + 'longitude': serializer.toJson(longitude), + 'iso': serializer.toJson(iso), + 'make': serializer.toJson(make), + 'model': serializer.toJson(model), + 'lens': serializer.toJson(lens), + 'orientation': serializer.toJson(orientation), + 'timeZone': serializer.toJson(timeZone), + 'rating': serializer.toJson(rating), + 'projectionType': serializer.toJson(projectionType), + }; + } + + RemoteExifEntityData copyWith({ + String? assetId, + Value city = const Value.absent(), + Value state = const Value.absent(), + Value country = const Value.absent(), + Value dateTimeOriginal = const Value.absent(), + Value description = const Value.absent(), + Value height = const Value.absent(), + Value width = const Value.absent(), + Value exposureTime = const Value.absent(), + Value fNumber = const Value.absent(), + Value fileSize = const Value.absent(), + Value focalLength = const Value.absent(), + Value latitude = const Value.absent(), + Value longitude = const Value.absent(), + Value iso = const Value.absent(), + Value make = const Value.absent(), + Value model = const Value.absent(), + Value lens = const Value.absent(), + Value orientation = const Value.absent(), + Value timeZone = const Value.absent(), + Value rating = const Value.absent(), + Value projectionType = const Value.absent(), + }) => RemoteExifEntityData( + assetId: assetId ?? this.assetId, + city: city.present ? city.value : this.city, + state: state.present ? state.value : this.state, + country: country.present ? country.value : this.country, + dateTimeOriginal: dateTimeOriginal.present + ? dateTimeOriginal.value + : this.dateTimeOriginal, + description: description.present ? description.value : this.description, + height: height.present ? height.value : this.height, + width: width.present ? width.value : this.width, + exposureTime: exposureTime.present ? exposureTime.value : this.exposureTime, + fNumber: fNumber.present ? fNumber.value : this.fNumber, + fileSize: fileSize.present ? fileSize.value : this.fileSize, + focalLength: focalLength.present ? focalLength.value : this.focalLength, + latitude: latitude.present ? latitude.value : this.latitude, + longitude: longitude.present ? longitude.value : this.longitude, + iso: iso.present ? iso.value : this.iso, + make: make.present ? make.value : this.make, + model: model.present ? model.value : this.model, + lens: lens.present ? lens.value : this.lens, + orientation: orientation.present ? orientation.value : this.orientation, + timeZone: timeZone.present ? timeZone.value : this.timeZone, + rating: rating.present ? rating.value : this.rating, + projectionType: projectionType.present + ? projectionType.value + : this.projectionType, + ); + RemoteExifEntityData copyWithCompanion(RemoteExifEntityCompanion data) { + return RemoteExifEntityData( + assetId: data.assetId.present ? data.assetId.value : this.assetId, + city: data.city.present ? data.city.value : this.city, + state: data.state.present ? data.state.value : this.state, + country: data.country.present ? data.country.value : this.country, + dateTimeOriginal: data.dateTimeOriginal.present + ? data.dateTimeOriginal.value + : this.dateTimeOriginal, + description: data.description.present + ? data.description.value + : this.description, + height: data.height.present ? data.height.value : this.height, + width: data.width.present ? data.width.value : this.width, + exposureTime: data.exposureTime.present + ? data.exposureTime.value + : this.exposureTime, + fNumber: data.fNumber.present ? data.fNumber.value : this.fNumber, + fileSize: data.fileSize.present ? data.fileSize.value : this.fileSize, + focalLength: data.focalLength.present + ? data.focalLength.value + : this.focalLength, + latitude: data.latitude.present ? data.latitude.value : this.latitude, + longitude: data.longitude.present ? data.longitude.value : this.longitude, + iso: data.iso.present ? data.iso.value : this.iso, + make: data.make.present ? data.make.value : this.make, + model: data.model.present ? data.model.value : this.model, + lens: data.lens.present ? data.lens.value : this.lens, + orientation: data.orientation.present + ? data.orientation.value + : this.orientation, + timeZone: data.timeZone.present ? data.timeZone.value : this.timeZone, + rating: data.rating.present ? data.rating.value : this.rating, + projectionType: data.projectionType.present + ? data.projectionType.value + : this.projectionType, + ); + } + + @override + String toString() { + return (StringBuffer('RemoteExifEntityData(') + ..write('assetId: $assetId, ') + ..write('city: $city, ') + ..write('state: $state, ') + ..write('country: $country, ') + ..write('dateTimeOriginal: $dateTimeOriginal, ') + ..write('description: $description, ') + ..write('height: $height, ') + ..write('width: $width, ') + ..write('exposureTime: $exposureTime, ') + ..write('fNumber: $fNumber, ') + ..write('fileSize: $fileSize, ') + ..write('focalLength: $focalLength, ') + ..write('latitude: $latitude, ') + ..write('longitude: $longitude, ') + ..write('iso: $iso, ') + ..write('make: $make, ') + ..write('model: $model, ') + ..write('lens: $lens, ') + ..write('orientation: $orientation, ') + ..write('timeZone: $timeZone, ') + ..write('rating: $rating, ') + ..write('projectionType: $projectionType') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hashAll([ + assetId, + city, + state, + country, + dateTimeOriginal, + description, + height, + width, + exposureTime, + fNumber, + fileSize, + focalLength, + latitude, + longitude, + iso, + make, + model, + lens, + orientation, + timeZone, + rating, + projectionType, + ]); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RemoteExifEntityData && + other.assetId == this.assetId && + other.city == this.city && + other.state == this.state && + other.country == this.country && + other.dateTimeOriginal == this.dateTimeOriginal && + other.description == this.description && + other.height == this.height && + other.width == this.width && + other.exposureTime == this.exposureTime && + other.fNumber == this.fNumber && + other.fileSize == this.fileSize && + other.focalLength == this.focalLength && + other.latitude == this.latitude && + other.longitude == this.longitude && + other.iso == this.iso && + other.make == this.make && + other.model == this.model && + other.lens == this.lens && + other.orientation == this.orientation && + other.timeZone == this.timeZone && + other.rating == this.rating && + other.projectionType == this.projectionType); +} + +class RemoteExifEntityCompanion extends UpdateCompanion { + final Value assetId; + final Value city; + final Value state; + final Value country; + final Value dateTimeOriginal; + final Value description; + final Value height; + final Value width; + final Value exposureTime; + final Value fNumber; + final Value fileSize; + final Value focalLength; + final Value latitude; + final Value longitude; + final Value iso; + final Value make; + final Value model; + final Value lens; + final Value orientation; + final Value timeZone; + final Value rating; + final Value projectionType; + const RemoteExifEntityCompanion({ + this.assetId = const Value.absent(), + this.city = const Value.absent(), + this.state = const Value.absent(), + this.country = const Value.absent(), + this.dateTimeOriginal = const Value.absent(), + this.description = const Value.absent(), + this.height = const Value.absent(), + this.width = const Value.absent(), + this.exposureTime = const Value.absent(), + this.fNumber = const Value.absent(), + this.fileSize = const Value.absent(), + this.focalLength = const Value.absent(), + this.latitude = const Value.absent(), + this.longitude = const Value.absent(), + this.iso = const Value.absent(), + this.make = const Value.absent(), + this.model = const Value.absent(), + this.lens = const Value.absent(), + this.orientation = const Value.absent(), + this.timeZone = const Value.absent(), + this.rating = const Value.absent(), + this.projectionType = const Value.absent(), + }); + RemoteExifEntityCompanion.insert({ + required String assetId, + this.city = const Value.absent(), + this.state = const Value.absent(), + this.country = const Value.absent(), + this.dateTimeOriginal = const Value.absent(), + this.description = const Value.absent(), + this.height = const Value.absent(), + this.width = const Value.absent(), + this.exposureTime = const Value.absent(), + this.fNumber = const Value.absent(), + this.fileSize = const Value.absent(), + this.focalLength = const Value.absent(), + this.latitude = const Value.absent(), + this.longitude = const Value.absent(), + this.iso = const Value.absent(), + this.make = const Value.absent(), + this.model = const Value.absent(), + this.lens = const Value.absent(), + this.orientation = const Value.absent(), + this.timeZone = const Value.absent(), + this.rating = const Value.absent(), + this.projectionType = const Value.absent(), + }) : assetId = Value(assetId); + static Insertable custom({ + Expression? assetId, + Expression? city, + Expression? state, + Expression? country, + Expression? dateTimeOriginal, + Expression? description, + Expression? height, + Expression? width, + Expression? exposureTime, + Expression? fNumber, + Expression? fileSize, + Expression? focalLength, + Expression? latitude, + Expression? longitude, + Expression? iso, + Expression? make, + Expression? model, + Expression? lens, + Expression? orientation, + Expression? timeZone, + Expression? rating, + Expression? projectionType, + }) { + return RawValuesInsertable({ + if (assetId != null) 'asset_id': assetId, + if (city != null) 'city': city, + if (state != null) 'state': state, + if (country != null) 'country': country, + if (dateTimeOriginal != null) 'date_time_original': dateTimeOriginal, + if (description != null) 'description': description, + if (height != null) 'height': height, + if (width != null) 'width': width, + if (exposureTime != null) 'exposure_time': exposureTime, + if (fNumber != null) 'f_number': fNumber, + if (fileSize != null) 'file_size': fileSize, + if (focalLength != null) 'focal_length': focalLength, + if (latitude != null) 'latitude': latitude, + if (longitude != null) 'longitude': longitude, + if (iso != null) 'iso': iso, + if (make != null) 'make': make, + if (model != null) 'model': model, + if (lens != null) 'lens': lens, + if (orientation != null) 'orientation': orientation, + if (timeZone != null) 'time_zone': timeZone, + if (rating != null) 'rating': rating, + if (projectionType != null) 'projection_type': projectionType, + }); + } + + RemoteExifEntityCompanion copyWith({ + Value? assetId, + Value? city, + Value? state, + Value? country, + Value? dateTimeOriginal, + Value? description, + Value? height, + Value? width, + Value? exposureTime, + Value? fNumber, + Value? fileSize, + Value? focalLength, + Value? latitude, + Value? longitude, + Value? iso, + Value? make, + Value? model, + Value? lens, + Value? orientation, + Value? timeZone, + Value? rating, + Value? projectionType, + }) { + return RemoteExifEntityCompanion( + assetId: assetId ?? this.assetId, + city: city ?? this.city, + state: state ?? this.state, + country: country ?? this.country, + dateTimeOriginal: dateTimeOriginal ?? this.dateTimeOriginal, + description: description ?? this.description, + height: height ?? this.height, + width: width ?? this.width, + exposureTime: exposureTime ?? this.exposureTime, + fNumber: fNumber ?? this.fNumber, + fileSize: fileSize ?? this.fileSize, + focalLength: focalLength ?? this.focalLength, + latitude: latitude ?? this.latitude, + longitude: longitude ?? this.longitude, + iso: iso ?? this.iso, + make: make ?? this.make, + model: model ?? this.model, + lens: lens ?? this.lens, + orientation: orientation ?? this.orientation, + timeZone: timeZone ?? this.timeZone, + rating: rating ?? this.rating, + projectionType: projectionType ?? this.projectionType, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (assetId.present) { + map['asset_id'] = Variable(assetId.value); + } + if (city.present) { + map['city'] = Variable(city.value); + } + if (state.present) { + map['state'] = Variable(state.value); + } + if (country.present) { + map['country'] = Variable(country.value); + } + if (dateTimeOriginal.present) { + map['date_time_original'] = Variable(dateTimeOriginal.value); + } + if (description.present) { + map['description'] = Variable(description.value); + } + if (height.present) { + map['height'] = Variable(height.value); + } + if (width.present) { + map['width'] = Variable(width.value); + } + if (exposureTime.present) { + map['exposure_time'] = Variable(exposureTime.value); + } + if (fNumber.present) { + map['f_number'] = Variable(fNumber.value); + } + if (fileSize.present) { + map['file_size'] = Variable(fileSize.value); + } + if (focalLength.present) { + map['focal_length'] = Variable(focalLength.value); + } + if (latitude.present) { + map['latitude'] = Variable(latitude.value); + } + if (longitude.present) { + map['longitude'] = Variable(longitude.value); + } + if (iso.present) { + map['iso'] = Variable(iso.value); + } + if (make.present) { + map['make'] = Variable(make.value); + } + if (model.present) { + map['model'] = Variable(model.value); + } + if (lens.present) { + map['lens'] = Variable(lens.value); + } + if (orientation.present) { + map['orientation'] = Variable(orientation.value); + } + if (timeZone.present) { + map['time_zone'] = Variable(timeZone.value); + } + if (rating.present) { + map['rating'] = Variable(rating.value); + } + if (projectionType.present) { + map['projection_type'] = Variable(projectionType.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RemoteExifEntityCompanion(') + ..write('assetId: $assetId, ') + ..write('city: $city, ') + ..write('state: $state, ') + ..write('country: $country, ') + ..write('dateTimeOriginal: $dateTimeOriginal, ') + ..write('description: $description, ') + ..write('height: $height, ') + ..write('width: $width, ') + ..write('exposureTime: $exposureTime, ') + ..write('fNumber: $fNumber, ') + ..write('fileSize: $fileSize, ') + ..write('focalLength: $focalLength, ') + ..write('latitude: $latitude, ') + ..write('longitude: $longitude, ') + ..write('iso: $iso, ') + ..write('make: $make, ') + ..write('model: $model, ') + ..write('lens: $lens, ') + ..write('orientation: $orientation, ') + ..write('timeZone: $timeZone, ') + ..write('rating: $rating, ') + ..write('projectionType: $projectionType') + ..write(')')) + .toString(); + } +} + +class RemoteAlbumAssetEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RemoteAlbumAssetEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn assetId = GeneratedColumn( + 'asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_asset_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn albumId = GeneratedColumn( + 'album_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_album_entity (id) ON DELETE CASCADE', + ), + ); + @override + List get $columns => [assetId, albumId]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'remote_album_asset_entity'; + @override + Set get $primaryKey => {assetId, albumId}; + @override + RemoteAlbumAssetEntityData map( + Map data, { + String? tablePrefix, + }) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RemoteAlbumAssetEntityData( + assetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}asset_id'], + )!, + albumId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}album_id'], + )!, + ); + } + + @override + RemoteAlbumAssetEntity createAlias(String alias) { + return RemoteAlbumAssetEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class RemoteAlbumAssetEntityData extends DataClass + implements Insertable { + final String assetId; + final String albumId; + const RemoteAlbumAssetEntityData({ + required this.assetId, + required this.albumId, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['asset_id'] = Variable(assetId); + map['album_id'] = Variable(albumId); + return map; + } + + factory RemoteAlbumAssetEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RemoteAlbumAssetEntityData( + assetId: serializer.fromJson(json['assetId']), + albumId: serializer.fromJson(json['albumId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'assetId': serializer.toJson(assetId), + 'albumId': serializer.toJson(albumId), + }; + } + + RemoteAlbumAssetEntityData copyWith({String? assetId, String? albumId}) => + RemoteAlbumAssetEntityData( + assetId: assetId ?? this.assetId, + albumId: albumId ?? this.albumId, + ); + RemoteAlbumAssetEntityData copyWithCompanion( + RemoteAlbumAssetEntityCompanion data, + ) { + return RemoteAlbumAssetEntityData( + assetId: data.assetId.present ? data.assetId.value : this.assetId, + albumId: data.albumId.present ? data.albumId.value : this.albumId, + ); + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumAssetEntityData(') + ..write('assetId: $assetId, ') + ..write('albumId: $albumId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(assetId, albumId); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RemoteAlbumAssetEntityData && + other.assetId == this.assetId && + other.albumId == this.albumId); +} + +class RemoteAlbumAssetEntityCompanion + extends UpdateCompanion { + final Value assetId; + final Value albumId; + const RemoteAlbumAssetEntityCompanion({ + this.assetId = const Value.absent(), + this.albumId = const Value.absent(), + }); + RemoteAlbumAssetEntityCompanion.insert({ + required String assetId, + required String albumId, + }) : assetId = Value(assetId), + albumId = Value(albumId); + static Insertable custom({ + Expression? assetId, + Expression? albumId, + }) { + return RawValuesInsertable({ + if (assetId != null) 'asset_id': assetId, + if (albumId != null) 'album_id': albumId, + }); + } + + RemoteAlbumAssetEntityCompanion copyWith({ + Value? assetId, + Value? albumId, + }) { + return RemoteAlbumAssetEntityCompanion( + assetId: assetId ?? this.assetId, + albumId: albumId ?? this.albumId, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (assetId.present) { + map['asset_id'] = Variable(assetId.value); + } + if (albumId.present) { + map['album_id'] = Variable(albumId.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumAssetEntityCompanion(') + ..write('assetId: $assetId, ') + ..write('albumId: $albumId') + ..write(')')) + .toString(); + } +} + +class RemoteAlbumUserEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RemoteAlbumUserEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn albumId = GeneratedColumn( + 'album_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_album_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn role = GeneratedColumn( + 'role', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + @override + List get $columns => [albumId, userId, role]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'remote_album_user_entity'; + @override + Set get $primaryKey => {albumId, userId}; + @override + RemoteAlbumUserEntityData map( + Map data, { + String? tablePrefix, + }) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RemoteAlbumUserEntityData( + albumId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}album_id'], + )!, + userId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}user_id'], + )!, + role: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}role'], + )!, + ); + } + + @override + RemoteAlbumUserEntity createAlias(String alias) { + return RemoteAlbumUserEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class RemoteAlbumUserEntityData extends DataClass + implements Insertable { + final String albumId; + final String userId; + final int role; + const RemoteAlbumUserEntityData({ + required this.albumId, + required this.userId, + required this.role, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['album_id'] = Variable(albumId); + map['user_id'] = Variable(userId); + map['role'] = Variable(role); + return map; + } + + factory RemoteAlbumUserEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RemoteAlbumUserEntityData( + albumId: serializer.fromJson(json['albumId']), + userId: serializer.fromJson(json['userId']), + role: serializer.fromJson(json['role']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'albumId': serializer.toJson(albumId), + 'userId': serializer.toJson(userId), + 'role': serializer.toJson(role), + }; + } + + RemoteAlbumUserEntityData copyWith({ + String? albumId, + String? userId, + int? role, + }) => RemoteAlbumUserEntityData( + albumId: albumId ?? this.albumId, + userId: userId ?? this.userId, + role: role ?? this.role, + ); + RemoteAlbumUserEntityData copyWithCompanion( + RemoteAlbumUserEntityCompanion data, + ) { + return RemoteAlbumUserEntityData( + albumId: data.albumId.present ? data.albumId.value : this.albumId, + userId: data.userId.present ? data.userId.value : this.userId, + role: data.role.present ? data.role.value : this.role, + ); + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumUserEntityData(') + ..write('albumId: $albumId, ') + ..write('userId: $userId, ') + ..write('role: $role') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(albumId, userId, role); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RemoteAlbumUserEntityData && + other.albumId == this.albumId && + other.userId == this.userId && + other.role == this.role); +} + +class RemoteAlbumUserEntityCompanion + extends UpdateCompanion { + final Value albumId; + final Value userId; + final Value role; + const RemoteAlbumUserEntityCompanion({ + this.albumId = const Value.absent(), + this.userId = const Value.absent(), + this.role = const Value.absent(), + }); + RemoteAlbumUserEntityCompanion.insert({ + required String albumId, + required String userId, + required int role, + }) : albumId = Value(albumId), + userId = Value(userId), + role = Value(role); + static Insertable custom({ + Expression? albumId, + Expression? userId, + Expression? role, + }) { + return RawValuesInsertable({ + if (albumId != null) 'album_id': albumId, + if (userId != null) 'user_id': userId, + if (role != null) 'role': role, + }); + } + + RemoteAlbumUserEntityCompanion copyWith({ + Value? albumId, + Value? userId, + Value? role, + }) { + return RemoteAlbumUserEntityCompanion( + albumId: albumId ?? this.albumId, + userId: userId ?? this.userId, + role: role ?? this.role, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (albumId.present) { + map['album_id'] = Variable(albumId.value); + } + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (role.present) { + map['role'] = Variable(role.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumUserEntityCompanion(') + ..write('albumId: $albumId, ') + ..write('userId: $userId, ') + ..write('role: $role') + ..write(')')) + .toString(); + } +} + +class MemoryEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + MemoryEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn deletedAt = GeneratedColumn( + 'deleted_at', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn ownerId = GeneratedColumn( + 'owner_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn type = GeneratedColumn( + 'type', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn data = GeneratedColumn( + 'data', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn isSaved = GeneratedColumn( + 'is_saved', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_saved" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn memoryAt = GeneratedColumn( + 'memory_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: true, + ); + late final GeneratedColumn seenAt = GeneratedColumn( + 'seen_at', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn showAt = GeneratedColumn( + 'show_at', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn hideAt = GeneratedColumn( + 'hide_at', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + deletedAt, + ownerId, + type, + data, + isSaved, + memoryAt, + seenAt, + showAt, + hideAt, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'memory_entity'; + @override + Set get $primaryKey => {id}; + @override + MemoryEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return MemoryEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + deletedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}deleted_at'], + ), + ownerId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}owner_id'], + )!, + type: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}type'], + )!, + data: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}data'], + )!, + isSaved: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_saved'], + )!, + memoryAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}memory_at'], + )!, + seenAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}seen_at'], + ), + showAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}show_at'], + ), + hideAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}hide_at'], + ), + ); + } + + @override + MemoryEntity createAlias(String alias) { + return MemoryEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class MemoryEntityData extends DataClass + implements Insertable { + final String id; + final DateTime createdAt; + final DateTime updatedAt; + final DateTime? deletedAt; + final String ownerId; + final int type; + final String data; + final bool isSaved; + final DateTime memoryAt; + final DateTime? seenAt; + final DateTime? showAt; + final DateTime? hideAt; + const MemoryEntityData({ + required this.id, + required this.createdAt, + required this.updatedAt, + this.deletedAt, + required this.ownerId, + required this.type, + required this.data, + required this.isSaved, + required this.memoryAt, + this.seenAt, + this.showAt, + this.hideAt, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || deletedAt != null) { + map['deleted_at'] = Variable(deletedAt); + } + map['owner_id'] = Variable(ownerId); + map['type'] = Variable(type); + map['data'] = Variable(data); + map['is_saved'] = Variable(isSaved); + map['memory_at'] = Variable(memoryAt); + if (!nullToAbsent || seenAt != null) { + map['seen_at'] = Variable(seenAt); + } + if (!nullToAbsent || showAt != null) { + map['show_at'] = Variable(showAt); + } + if (!nullToAbsent || hideAt != null) { + map['hide_at'] = Variable(hideAt); + } + return map; + } + + factory MemoryEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return MemoryEntityData( + id: serializer.fromJson(json['id']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + deletedAt: serializer.fromJson(json['deletedAt']), + ownerId: serializer.fromJson(json['ownerId']), + type: serializer.fromJson(json['type']), + data: serializer.fromJson(json['data']), + isSaved: serializer.fromJson(json['isSaved']), + memoryAt: serializer.fromJson(json['memoryAt']), + seenAt: serializer.fromJson(json['seenAt']), + showAt: serializer.fromJson(json['showAt']), + hideAt: serializer.fromJson(json['hideAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'deletedAt': serializer.toJson(deletedAt), + 'ownerId': serializer.toJson(ownerId), + 'type': serializer.toJson(type), + 'data': serializer.toJson(data), + 'isSaved': serializer.toJson(isSaved), + 'memoryAt': serializer.toJson(memoryAt), + 'seenAt': serializer.toJson(seenAt), + 'showAt': serializer.toJson(showAt), + 'hideAt': serializer.toJson(hideAt), + }; + } + + MemoryEntityData copyWith({ + String? id, + DateTime? createdAt, + DateTime? updatedAt, + Value deletedAt = const Value.absent(), + String? ownerId, + int? type, + String? data, + bool? isSaved, + DateTime? memoryAt, + Value seenAt = const Value.absent(), + Value showAt = const Value.absent(), + Value hideAt = const Value.absent(), + }) => MemoryEntityData( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt, + ownerId: ownerId ?? this.ownerId, + type: type ?? this.type, + data: data ?? this.data, + isSaved: isSaved ?? this.isSaved, + memoryAt: memoryAt ?? this.memoryAt, + seenAt: seenAt.present ? seenAt.value : this.seenAt, + showAt: showAt.present ? showAt.value : this.showAt, + hideAt: hideAt.present ? hideAt.value : this.hideAt, + ); + MemoryEntityData copyWithCompanion(MemoryEntityCompanion data) { + return MemoryEntityData( + id: data.id.present ? data.id.value : this.id, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + deletedAt: data.deletedAt.present ? data.deletedAt.value : this.deletedAt, + ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId, + type: data.type.present ? data.type.value : this.type, + data: data.data.present ? data.data.value : this.data, + isSaved: data.isSaved.present ? data.isSaved.value : this.isSaved, + memoryAt: data.memoryAt.present ? data.memoryAt.value : this.memoryAt, + seenAt: data.seenAt.present ? data.seenAt.value : this.seenAt, + showAt: data.showAt.present ? data.showAt.value : this.showAt, + hideAt: data.hideAt.present ? data.hideAt.value : this.hideAt, + ); + } + + @override + String toString() { + return (StringBuffer('MemoryEntityData(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('ownerId: $ownerId, ') + ..write('type: $type, ') + ..write('data: $data, ') + ..write('isSaved: $isSaved, ') + ..write('memoryAt: $memoryAt, ') + ..write('seenAt: $seenAt, ') + ..write('showAt: $showAt, ') + ..write('hideAt: $hideAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + createdAt, + updatedAt, + deletedAt, + ownerId, + type, + data, + isSaved, + memoryAt, + seenAt, + showAt, + hideAt, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is MemoryEntityData && + other.id == this.id && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.deletedAt == this.deletedAt && + other.ownerId == this.ownerId && + other.type == this.type && + other.data == this.data && + other.isSaved == this.isSaved && + other.memoryAt == this.memoryAt && + other.seenAt == this.seenAt && + other.showAt == this.showAt && + other.hideAt == this.hideAt); +} + +class MemoryEntityCompanion extends UpdateCompanion { + final Value id; + final Value createdAt; + final Value updatedAt; + final Value deletedAt; + final Value ownerId; + final Value type; + final Value data; + final Value isSaved; + final Value memoryAt; + final Value seenAt; + final Value showAt; + final Value hideAt; + const MemoryEntityCompanion({ + this.id = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.ownerId = const Value.absent(), + this.type = const Value.absent(), + this.data = const Value.absent(), + this.isSaved = const Value.absent(), + this.memoryAt = const Value.absent(), + this.seenAt = const Value.absent(), + this.showAt = const Value.absent(), + this.hideAt = const Value.absent(), + }); + MemoryEntityCompanion.insert({ + required String id, + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + required String ownerId, + required int type, + required String data, + this.isSaved = const Value.absent(), + required DateTime memoryAt, + this.seenAt = const Value.absent(), + this.showAt = const Value.absent(), + this.hideAt = const Value.absent(), + }) : id = Value(id), + ownerId = Value(ownerId), + type = Value(type), + data = Value(data), + memoryAt = Value(memoryAt); + static Insertable custom({ + Expression? id, + Expression? createdAt, + Expression? updatedAt, + Expression? deletedAt, + Expression? ownerId, + Expression? type, + Expression? data, + Expression? isSaved, + Expression? memoryAt, + Expression? seenAt, + Expression? showAt, + Expression? hideAt, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (deletedAt != null) 'deleted_at': deletedAt, + if (ownerId != null) 'owner_id': ownerId, + if (type != null) 'type': type, + if (data != null) 'data': data, + if (isSaved != null) 'is_saved': isSaved, + if (memoryAt != null) 'memory_at': memoryAt, + if (seenAt != null) 'seen_at': seenAt, + if (showAt != null) 'show_at': showAt, + if (hideAt != null) 'hide_at': hideAt, + }); + } + + MemoryEntityCompanion copyWith({ + Value? id, + Value? createdAt, + Value? updatedAt, + Value? deletedAt, + Value? ownerId, + Value? type, + Value? data, + Value? isSaved, + Value? memoryAt, + Value? seenAt, + Value? showAt, + Value? hideAt, + }) { + return MemoryEntityCompanion( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + ownerId: ownerId ?? this.ownerId, + type: type ?? this.type, + data: data ?? this.data, + isSaved: isSaved ?? this.isSaved, + memoryAt: memoryAt ?? this.memoryAt, + seenAt: seenAt ?? this.seenAt, + showAt: showAt ?? this.showAt, + hideAt: hideAt ?? this.hideAt, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (deletedAt.present) { + map['deleted_at'] = Variable(deletedAt.value); + } + if (ownerId.present) { + map['owner_id'] = Variable(ownerId.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (data.present) { + map['data'] = Variable(data.value); + } + if (isSaved.present) { + map['is_saved'] = Variable(isSaved.value); + } + if (memoryAt.present) { + map['memory_at'] = Variable(memoryAt.value); + } + if (seenAt.present) { + map['seen_at'] = Variable(seenAt.value); + } + if (showAt.present) { + map['show_at'] = Variable(showAt.value); + } + if (hideAt.present) { + map['hide_at'] = Variable(hideAt.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('MemoryEntityCompanion(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('ownerId: $ownerId, ') + ..write('type: $type, ') + ..write('data: $data, ') + ..write('isSaved: $isSaved, ') + ..write('memoryAt: $memoryAt, ') + ..write('seenAt: $seenAt, ') + ..write('showAt: $showAt, ') + ..write('hideAt: $hideAt') + ..write(')')) + .toString(); + } +} + +class MemoryAssetEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + MemoryAssetEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn assetId = GeneratedColumn( + 'asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_asset_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn memoryId = GeneratedColumn( + 'memory_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES memory_entity (id) ON DELETE CASCADE', + ), + ); + @override + List get $columns => [assetId, memoryId]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'memory_asset_entity'; + @override + Set get $primaryKey => {assetId, memoryId}; + @override + MemoryAssetEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return MemoryAssetEntityData( + assetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}asset_id'], + )!, + memoryId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}memory_id'], + )!, + ); + } + + @override + MemoryAssetEntity createAlias(String alias) { + return MemoryAssetEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class MemoryAssetEntityData extends DataClass + implements Insertable { + final String assetId; + final String memoryId; + const MemoryAssetEntityData({required this.assetId, required this.memoryId}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['asset_id'] = Variable(assetId); + map['memory_id'] = Variable(memoryId); + return map; + } + + factory MemoryAssetEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return MemoryAssetEntityData( + assetId: serializer.fromJson(json['assetId']), + memoryId: serializer.fromJson(json['memoryId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'assetId': serializer.toJson(assetId), + 'memoryId': serializer.toJson(memoryId), + }; + } + + MemoryAssetEntityData copyWith({String? assetId, String? memoryId}) => + MemoryAssetEntityData( + assetId: assetId ?? this.assetId, + memoryId: memoryId ?? this.memoryId, + ); + MemoryAssetEntityData copyWithCompanion(MemoryAssetEntityCompanion data) { + return MemoryAssetEntityData( + assetId: data.assetId.present ? data.assetId.value : this.assetId, + memoryId: data.memoryId.present ? data.memoryId.value : this.memoryId, + ); + } + + @override + String toString() { + return (StringBuffer('MemoryAssetEntityData(') + ..write('assetId: $assetId, ') + ..write('memoryId: $memoryId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(assetId, memoryId); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is MemoryAssetEntityData && + other.assetId == this.assetId && + other.memoryId == this.memoryId); +} + +class MemoryAssetEntityCompanion + extends UpdateCompanion { + final Value assetId; + final Value memoryId; + const MemoryAssetEntityCompanion({ + this.assetId = const Value.absent(), + this.memoryId = const Value.absent(), + }); + MemoryAssetEntityCompanion.insert({ + required String assetId, + required String memoryId, + }) : assetId = Value(assetId), + memoryId = Value(memoryId); + static Insertable custom({ + Expression? assetId, + Expression? memoryId, + }) { + return RawValuesInsertable({ + if (assetId != null) 'asset_id': assetId, + if (memoryId != null) 'memory_id': memoryId, + }); + } + + MemoryAssetEntityCompanion copyWith({ + Value? assetId, + Value? memoryId, + }) { + return MemoryAssetEntityCompanion( + assetId: assetId ?? this.assetId, + memoryId: memoryId ?? this.memoryId, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (assetId.present) { + map['asset_id'] = Variable(assetId.value); + } + if (memoryId.present) { + map['memory_id'] = Variable(memoryId.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('MemoryAssetEntityCompanion(') + ..write('assetId: $assetId, ') + ..write('memoryId: $memoryId') + ..write(')')) + .toString(); + } +} + +class PersonEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + PersonEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn ownerId = GeneratedColumn( + 'owner_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn faceAssetId = GeneratedColumn( + 'face_asset_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn isFavorite = GeneratedColumn( + 'is_favorite', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_favorite" IN (0, 1))', + ), + ); + late final GeneratedColumn isHidden = GeneratedColumn( + 'is_hidden', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_hidden" IN (0, 1))', + ), + ); + late final GeneratedColumn color = GeneratedColumn( + 'color', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn birthDate = GeneratedColumn( + 'birth_date', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + ownerId, + name, + faceAssetId, + isFavorite, + isHidden, + color, + birthDate, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'person_entity'; + @override + Set get $primaryKey => {id}; + @override + PersonEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return PersonEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + ownerId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}owner_id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + faceAssetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}face_asset_id'], + ), + isFavorite: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_favorite'], + )!, + isHidden: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_hidden'], + )!, + color: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}color'], + ), + birthDate: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}birth_date'], + ), + ); + } + + @override + PersonEntity createAlias(String alias) { + return PersonEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class PersonEntityData extends DataClass + implements Insertable { + final String id; + final DateTime createdAt; + final DateTime updatedAt; + final String ownerId; + final String name; + final String? faceAssetId; + final bool isFavorite; + final bool isHidden; + final String? color; + final DateTime? birthDate; + const PersonEntityData({ + required this.id, + required this.createdAt, + required this.updatedAt, + required this.ownerId, + required this.name, + this.faceAssetId, + required this.isFavorite, + required this.isHidden, + this.color, + this.birthDate, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + map['owner_id'] = Variable(ownerId); + map['name'] = Variable(name); + if (!nullToAbsent || faceAssetId != null) { + map['face_asset_id'] = Variable(faceAssetId); + } + map['is_favorite'] = Variable(isFavorite); + map['is_hidden'] = Variable(isHidden); + if (!nullToAbsent || color != null) { + map['color'] = Variable(color); + } + if (!nullToAbsent || birthDate != null) { + map['birth_date'] = Variable(birthDate); + } + return map; + } + + factory PersonEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return PersonEntityData( + id: serializer.fromJson(json['id']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + ownerId: serializer.fromJson(json['ownerId']), + name: serializer.fromJson(json['name']), + faceAssetId: serializer.fromJson(json['faceAssetId']), + isFavorite: serializer.fromJson(json['isFavorite']), + isHidden: serializer.fromJson(json['isHidden']), + color: serializer.fromJson(json['color']), + birthDate: serializer.fromJson(json['birthDate']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'ownerId': serializer.toJson(ownerId), + 'name': serializer.toJson(name), + 'faceAssetId': serializer.toJson(faceAssetId), + 'isFavorite': serializer.toJson(isFavorite), + 'isHidden': serializer.toJson(isHidden), + 'color': serializer.toJson(color), + 'birthDate': serializer.toJson(birthDate), + }; + } + + PersonEntityData copyWith({ + String? id, + DateTime? createdAt, + DateTime? updatedAt, + String? ownerId, + String? name, + Value faceAssetId = const Value.absent(), + bool? isFavorite, + bool? isHidden, + Value color = const Value.absent(), + Value birthDate = const Value.absent(), + }) => PersonEntityData( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + name: name ?? this.name, + faceAssetId: faceAssetId.present ? faceAssetId.value : this.faceAssetId, + isFavorite: isFavorite ?? this.isFavorite, + isHidden: isHidden ?? this.isHidden, + color: color.present ? color.value : this.color, + birthDate: birthDate.present ? birthDate.value : this.birthDate, + ); + PersonEntityData copyWithCompanion(PersonEntityCompanion data) { + return PersonEntityData( + id: data.id.present ? data.id.value : this.id, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId, + name: data.name.present ? data.name.value : this.name, + faceAssetId: data.faceAssetId.present + ? data.faceAssetId.value + : this.faceAssetId, + isFavorite: data.isFavorite.present + ? data.isFavorite.value + : this.isFavorite, + isHidden: data.isHidden.present ? data.isHidden.value : this.isHidden, + color: data.color.present ? data.color.value : this.color, + birthDate: data.birthDate.present ? data.birthDate.value : this.birthDate, + ); + } + + @override + String toString() { + return (StringBuffer('PersonEntityData(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('name: $name, ') + ..write('faceAssetId: $faceAssetId, ') + ..write('isFavorite: $isFavorite, ') + ..write('isHidden: $isHidden, ') + ..write('color: $color, ') + ..write('birthDate: $birthDate') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + createdAt, + updatedAt, + ownerId, + name, + faceAssetId, + isFavorite, + isHidden, + color, + birthDate, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is PersonEntityData && + other.id == this.id && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.ownerId == this.ownerId && + other.name == this.name && + other.faceAssetId == this.faceAssetId && + other.isFavorite == this.isFavorite && + other.isHidden == this.isHidden && + other.color == this.color && + other.birthDate == this.birthDate); +} + +class PersonEntityCompanion extends UpdateCompanion { + final Value id; + final Value createdAt; + final Value updatedAt; + final Value ownerId; + final Value name; + final Value faceAssetId; + final Value isFavorite; + final Value isHidden; + final Value color; + final Value birthDate; + const PersonEntityCompanion({ + this.id = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.ownerId = const Value.absent(), + this.name = const Value.absent(), + this.faceAssetId = const Value.absent(), + this.isFavorite = const Value.absent(), + this.isHidden = const Value.absent(), + this.color = const Value.absent(), + this.birthDate = const Value.absent(), + }); + PersonEntityCompanion.insert({ + required String id, + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + required String ownerId, + required String name, + this.faceAssetId = const Value.absent(), + required bool isFavorite, + required bool isHidden, + this.color = const Value.absent(), + this.birthDate = const Value.absent(), + }) : id = Value(id), + ownerId = Value(ownerId), + name = Value(name), + isFavorite = Value(isFavorite), + isHidden = Value(isHidden); + static Insertable custom({ + Expression? id, + Expression? createdAt, + Expression? updatedAt, + Expression? ownerId, + Expression? name, + Expression? faceAssetId, + Expression? isFavorite, + Expression? isHidden, + Expression? color, + Expression? birthDate, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (ownerId != null) 'owner_id': ownerId, + if (name != null) 'name': name, + if (faceAssetId != null) 'face_asset_id': faceAssetId, + if (isFavorite != null) 'is_favorite': isFavorite, + if (isHidden != null) 'is_hidden': isHidden, + if (color != null) 'color': color, + if (birthDate != null) 'birth_date': birthDate, + }); + } + + PersonEntityCompanion copyWith({ + Value? id, + Value? createdAt, + Value? updatedAt, + Value? ownerId, + Value? name, + Value? faceAssetId, + Value? isFavorite, + Value? isHidden, + Value? color, + Value? birthDate, + }) { + return PersonEntityCompanion( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + name: name ?? this.name, + faceAssetId: faceAssetId ?? this.faceAssetId, + isFavorite: isFavorite ?? this.isFavorite, + isHidden: isHidden ?? this.isHidden, + color: color ?? this.color, + birthDate: birthDate ?? this.birthDate, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (ownerId.present) { + map['owner_id'] = Variable(ownerId.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (faceAssetId.present) { + map['face_asset_id'] = Variable(faceAssetId.value); + } + if (isFavorite.present) { + map['is_favorite'] = Variable(isFavorite.value); + } + if (isHidden.present) { + map['is_hidden'] = Variable(isHidden.value); + } + if (color.present) { + map['color'] = Variable(color.value); + } + if (birthDate.present) { + map['birth_date'] = Variable(birthDate.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('PersonEntityCompanion(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('name: $name, ') + ..write('faceAssetId: $faceAssetId, ') + ..write('isFavorite: $isFavorite, ') + ..write('isHidden: $isHidden, ') + ..write('color: $color, ') + ..write('birthDate: $birthDate') + ..write(')')) + .toString(); + } +} + +class AssetFaceEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + AssetFaceEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn assetId = GeneratedColumn( + 'asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_asset_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn personId = GeneratedColumn( + 'person_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES person_entity (id) ON DELETE SET NULL', + ), + ); + late final GeneratedColumn imageWidth = GeneratedColumn( + 'image_width', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn imageHeight = GeneratedColumn( + 'image_height', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn boundingBoxX1 = GeneratedColumn( + 'bounding_box_x1', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn boundingBoxY1 = GeneratedColumn( + 'bounding_box_y1', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn boundingBoxX2 = GeneratedColumn( + 'bounding_box_x2', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn boundingBoxY2 = GeneratedColumn( + 'bounding_box_y2', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn sourceType = GeneratedColumn( + 'source_type', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + @override + List get $columns => [ + id, + assetId, + personId, + imageWidth, + imageHeight, + boundingBoxX1, + boundingBoxY1, + boundingBoxX2, + boundingBoxY2, + sourceType, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'asset_face_entity'; + @override + Set get $primaryKey => {id}; + @override + AssetFaceEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return AssetFaceEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + assetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}asset_id'], + )!, + personId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}person_id'], + ), + imageWidth: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}image_width'], + )!, + imageHeight: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}image_height'], + )!, + boundingBoxX1: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}bounding_box_x1'], + )!, + boundingBoxY1: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}bounding_box_y1'], + )!, + boundingBoxX2: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}bounding_box_x2'], + )!, + boundingBoxY2: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}bounding_box_y2'], + )!, + sourceType: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}source_type'], + )!, + ); + } + + @override + AssetFaceEntity createAlias(String alias) { + return AssetFaceEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class AssetFaceEntityData extends DataClass + implements Insertable { + final String id; + final String assetId; + final String? personId; + final int imageWidth; + final int imageHeight; + final int boundingBoxX1; + final int boundingBoxY1; + final int boundingBoxX2; + final int boundingBoxY2; + final String sourceType; + const AssetFaceEntityData({ + required this.id, + required this.assetId, + this.personId, + required this.imageWidth, + required this.imageHeight, + required this.boundingBoxX1, + required this.boundingBoxY1, + required this.boundingBoxX2, + required this.boundingBoxY2, + required this.sourceType, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['asset_id'] = Variable(assetId); + if (!nullToAbsent || personId != null) { + map['person_id'] = Variable(personId); + } + map['image_width'] = Variable(imageWidth); + map['image_height'] = Variable(imageHeight); + map['bounding_box_x1'] = Variable(boundingBoxX1); + map['bounding_box_y1'] = Variable(boundingBoxY1); + map['bounding_box_x2'] = Variable(boundingBoxX2); + map['bounding_box_y2'] = Variable(boundingBoxY2); + map['source_type'] = Variable(sourceType); + return map; + } + + factory AssetFaceEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return AssetFaceEntityData( + id: serializer.fromJson(json['id']), + assetId: serializer.fromJson(json['assetId']), + personId: serializer.fromJson(json['personId']), + imageWidth: serializer.fromJson(json['imageWidth']), + imageHeight: serializer.fromJson(json['imageHeight']), + boundingBoxX1: serializer.fromJson(json['boundingBoxX1']), + boundingBoxY1: serializer.fromJson(json['boundingBoxY1']), + boundingBoxX2: serializer.fromJson(json['boundingBoxX2']), + boundingBoxY2: serializer.fromJson(json['boundingBoxY2']), + sourceType: serializer.fromJson(json['sourceType']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'assetId': serializer.toJson(assetId), + 'personId': serializer.toJson(personId), + 'imageWidth': serializer.toJson(imageWidth), + 'imageHeight': serializer.toJson(imageHeight), + 'boundingBoxX1': serializer.toJson(boundingBoxX1), + 'boundingBoxY1': serializer.toJson(boundingBoxY1), + 'boundingBoxX2': serializer.toJson(boundingBoxX2), + 'boundingBoxY2': serializer.toJson(boundingBoxY2), + 'sourceType': serializer.toJson(sourceType), + }; + } + + AssetFaceEntityData copyWith({ + String? id, + String? assetId, + Value personId = const Value.absent(), + int? imageWidth, + int? imageHeight, + int? boundingBoxX1, + int? boundingBoxY1, + int? boundingBoxX2, + int? boundingBoxY2, + String? sourceType, + }) => AssetFaceEntityData( + id: id ?? this.id, + assetId: assetId ?? this.assetId, + personId: personId.present ? personId.value : this.personId, + imageWidth: imageWidth ?? this.imageWidth, + imageHeight: imageHeight ?? this.imageHeight, + boundingBoxX1: boundingBoxX1 ?? this.boundingBoxX1, + boundingBoxY1: boundingBoxY1 ?? this.boundingBoxY1, + boundingBoxX2: boundingBoxX2 ?? this.boundingBoxX2, + boundingBoxY2: boundingBoxY2 ?? this.boundingBoxY2, + sourceType: sourceType ?? this.sourceType, + ); + AssetFaceEntityData copyWithCompanion(AssetFaceEntityCompanion data) { + return AssetFaceEntityData( + id: data.id.present ? data.id.value : this.id, + assetId: data.assetId.present ? data.assetId.value : this.assetId, + personId: data.personId.present ? data.personId.value : this.personId, + imageWidth: data.imageWidth.present + ? data.imageWidth.value + : this.imageWidth, + imageHeight: data.imageHeight.present + ? data.imageHeight.value + : this.imageHeight, + boundingBoxX1: data.boundingBoxX1.present + ? data.boundingBoxX1.value + : this.boundingBoxX1, + boundingBoxY1: data.boundingBoxY1.present + ? data.boundingBoxY1.value + : this.boundingBoxY1, + boundingBoxX2: data.boundingBoxX2.present + ? data.boundingBoxX2.value + : this.boundingBoxX2, + boundingBoxY2: data.boundingBoxY2.present + ? data.boundingBoxY2.value + : this.boundingBoxY2, + sourceType: data.sourceType.present + ? data.sourceType.value + : this.sourceType, + ); + } + + @override + String toString() { + return (StringBuffer('AssetFaceEntityData(') + ..write('id: $id, ') + ..write('assetId: $assetId, ') + ..write('personId: $personId, ') + ..write('imageWidth: $imageWidth, ') + ..write('imageHeight: $imageHeight, ') + ..write('boundingBoxX1: $boundingBoxX1, ') + ..write('boundingBoxY1: $boundingBoxY1, ') + ..write('boundingBoxX2: $boundingBoxX2, ') + ..write('boundingBoxY2: $boundingBoxY2, ') + ..write('sourceType: $sourceType') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + assetId, + personId, + imageWidth, + imageHeight, + boundingBoxX1, + boundingBoxY1, + boundingBoxX2, + boundingBoxY2, + sourceType, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is AssetFaceEntityData && + other.id == this.id && + other.assetId == this.assetId && + other.personId == this.personId && + other.imageWidth == this.imageWidth && + other.imageHeight == this.imageHeight && + other.boundingBoxX1 == this.boundingBoxX1 && + other.boundingBoxY1 == this.boundingBoxY1 && + other.boundingBoxX2 == this.boundingBoxX2 && + other.boundingBoxY2 == this.boundingBoxY2 && + other.sourceType == this.sourceType); +} + +class AssetFaceEntityCompanion extends UpdateCompanion { + final Value id; + final Value assetId; + final Value personId; + final Value imageWidth; + final Value imageHeight; + final Value boundingBoxX1; + final Value boundingBoxY1; + final Value boundingBoxX2; + final Value boundingBoxY2; + final Value sourceType; + const AssetFaceEntityCompanion({ + this.id = const Value.absent(), + this.assetId = const Value.absent(), + this.personId = const Value.absent(), + this.imageWidth = const Value.absent(), + this.imageHeight = const Value.absent(), + this.boundingBoxX1 = const Value.absent(), + this.boundingBoxY1 = const Value.absent(), + this.boundingBoxX2 = const Value.absent(), + this.boundingBoxY2 = const Value.absent(), + this.sourceType = const Value.absent(), + }); + AssetFaceEntityCompanion.insert({ + required String id, + required String assetId, + this.personId = const Value.absent(), + required int imageWidth, + required int imageHeight, + required int boundingBoxX1, + required int boundingBoxY1, + required int boundingBoxX2, + required int boundingBoxY2, + required String sourceType, + }) : id = Value(id), + assetId = Value(assetId), + imageWidth = Value(imageWidth), + imageHeight = Value(imageHeight), + boundingBoxX1 = Value(boundingBoxX1), + boundingBoxY1 = Value(boundingBoxY1), + boundingBoxX2 = Value(boundingBoxX2), + boundingBoxY2 = Value(boundingBoxY2), + sourceType = Value(sourceType); + static Insertable custom({ + Expression? id, + Expression? assetId, + Expression? personId, + Expression? imageWidth, + Expression? imageHeight, + Expression? boundingBoxX1, + Expression? boundingBoxY1, + Expression? boundingBoxX2, + Expression? boundingBoxY2, + Expression? sourceType, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (assetId != null) 'asset_id': assetId, + if (personId != null) 'person_id': personId, + if (imageWidth != null) 'image_width': imageWidth, + if (imageHeight != null) 'image_height': imageHeight, + if (boundingBoxX1 != null) 'bounding_box_x1': boundingBoxX1, + if (boundingBoxY1 != null) 'bounding_box_y1': boundingBoxY1, + if (boundingBoxX2 != null) 'bounding_box_x2': boundingBoxX2, + if (boundingBoxY2 != null) 'bounding_box_y2': boundingBoxY2, + if (sourceType != null) 'source_type': sourceType, + }); + } + + AssetFaceEntityCompanion copyWith({ + Value? id, + Value? assetId, + Value? personId, + Value? imageWidth, + Value? imageHeight, + Value? boundingBoxX1, + Value? boundingBoxY1, + Value? boundingBoxX2, + Value? boundingBoxY2, + Value? sourceType, + }) { + return AssetFaceEntityCompanion( + id: id ?? this.id, + assetId: assetId ?? this.assetId, + personId: personId ?? this.personId, + imageWidth: imageWidth ?? this.imageWidth, + imageHeight: imageHeight ?? this.imageHeight, + boundingBoxX1: boundingBoxX1 ?? this.boundingBoxX1, + boundingBoxY1: boundingBoxY1 ?? this.boundingBoxY1, + boundingBoxX2: boundingBoxX2 ?? this.boundingBoxX2, + boundingBoxY2: boundingBoxY2 ?? this.boundingBoxY2, + sourceType: sourceType ?? this.sourceType, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (assetId.present) { + map['asset_id'] = Variable(assetId.value); + } + if (personId.present) { + map['person_id'] = Variable(personId.value); + } + if (imageWidth.present) { + map['image_width'] = Variable(imageWidth.value); + } + if (imageHeight.present) { + map['image_height'] = Variable(imageHeight.value); + } + if (boundingBoxX1.present) { + map['bounding_box_x1'] = Variable(boundingBoxX1.value); + } + if (boundingBoxY1.present) { + map['bounding_box_y1'] = Variable(boundingBoxY1.value); + } + if (boundingBoxX2.present) { + map['bounding_box_x2'] = Variable(boundingBoxX2.value); + } + if (boundingBoxY2.present) { + map['bounding_box_y2'] = Variable(boundingBoxY2.value); + } + if (sourceType.present) { + map['source_type'] = Variable(sourceType.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('AssetFaceEntityCompanion(') + ..write('id: $id, ') + ..write('assetId: $assetId, ') + ..write('personId: $personId, ') + ..write('imageWidth: $imageWidth, ') + ..write('imageHeight: $imageHeight, ') + ..write('boundingBoxX1: $boundingBoxX1, ') + ..write('boundingBoxY1: $boundingBoxY1, ') + ..write('boundingBoxX2: $boundingBoxX2, ') + ..write('boundingBoxY2: $boundingBoxY2, ') + ..write('sourceType: $sourceType') + ..write(')')) + .toString(); + } +} + +class StoreEntity extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + StoreEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn stringValue = GeneratedColumn( + 'string_value', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn intValue = GeneratedColumn( + 'int_value', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + @override + List get $columns => [id, stringValue, intValue]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'store_entity'; + @override + Set get $primaryKey => {id}; + @override + StoreEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return StoreEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}id'], + )!, + stringValue: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}string_value'], + ), + intValue: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}int_value'], + ), + ); + } + + @override + StoreEntity createAlias(String alias) { + return StoreEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class StoreEntityData extends DataClass implements Insertable { + final int id; + final String? stringValue; + final int? intValue; + const StoreEntityData({required this.id, this.stringValue, this.intValue}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + if (!nullToAbsent || stringValue != null) { + map['string_value'] = Variable(stringValue); + } + if (!nullToAbsent || intValue != null) { + map['int_value'] = Variable(intValue); + } + return map; + } + + factory StoreEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return StoreEntityData( + id: serializer.fromJson(json['id']), + stringValue: serializer.fromJson(json['stringValue']), + intValue: serializer.fromJson(json['intValue']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'stringValue': serializer.toJson(stringValue), + 'intValue': serializer.toJson(intValue), + }; + } + + StoreEntityData copyWith({ + int? id, + Value stringValue = const Value.absent(), + Value intValue = const Value.absent(), + }) => StoreEntityData( + id: id ?? this.id, + stringValue: stringValue.present ? stringValue.value : this.stringValue, + intValue: intValue.present ? intValue.value : this.intValue, + ); + StoreEntityData copyWithCompanion(StoreEntityCompanion data) { + return StoreEntityData( + id: data.id.present ? data.id.value : this.id, + stringValue: data.stringValue.present + ? data.stringValue.value + : this.stringValue, + intValue: data.intValue.present ? data.intValue.value : this.intValue, + ); + } + + @override + String toString() { + return (StringBuffer('StoreEntityData(') + ..write('id: $id, ') + ..write('stringValue: $stringValue, ') + ..write('intValue: $intValue') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, stringValue, intValue); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is StoreEntityData && + other.id == this.id && + other.stringValue == this.stringValue && + other.intValue == this.intValue); +} + +class StoreEntityCompanion extends UpdateCompanion { + final Value id; + final Value stringValue; + final Value intValue; + const StoreEntityCompanion({ + this.id = const Value.absent(), + this.stringValue = const Value.absent(), + this.intValue = const Value.absent(), + }); + StoreEntityCompanion.insert({ + required int id, + this.stringValue = const Value.absent(), + this.intValue = const Value.absent(), + }) : id = Value(id); + static Insertable custom({ + Expression? id, + Expression? stringValue, + Expression? intValue, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (stringValue != null) 'string_value': stringValue, + if (intValue != null) 'int_value': intValue, + }); + } + + StoreEntityCompanion copyWith({ + Value? id, + Value? stringValue, + Value? intValue, + }) { + return StoreEntityCompanion( + id: id ?? this.id, + stringValue: stringValue ?? this.stringValue, + intValue: intValue ?? this.intValue, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (stringValue.present) { + map['string_value'] = Variable(stringValue.value); + } + if (intValue.present) { + map['int_value'] = Variable(intValue.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('StoreEntityCompanion(') + ..write('id: $id, ') + ..write('stringValue: $stringValue, ') + ..write('intValue: $intValue') + ..write(')')) + .toString(); + } +} + +class DatabaseAtV11 extends GeneratedDatabase { + DatabaseAtV11(QueryExecutor e) : super(e); + late final UserEntity userEntity = UserEntity(this); + late final RemoteAssetEntity remoteAssetEntity = RemoteAssetEntity(this); + late final StackEntity stackEntity = StackEntity(this); + late final LocalAssetEntity localAssetEntity = LocalAssetEntity(this); + late final RemoteAlbumEntity remoteAlbumEntity = RemoteAlbumEntity(this); + late final LocalAlbumEntity localAlbumEntity = LocalAlbumEntity(this); + late final LocalAlbumAssetEntity localAlbumAssetEntity = + LocalAlbumAssetEntity(this); + late final Index idxLocalAssetChecksum = Index( + 'idx_local_asset_checksum', + 'CREATE INDEX IF NOT EXISTS idx_local_asset_checksum ON local_asset_entity (checksum)', + ); + late final Index idxRemoteAssetOwnerChecksum = Index( + 'idx_remote_asset_owner_checksum', + 'CREATE INDEX IF NOT EXISTS idx_remote_asset_owner_checksum ON remote_asset_entity (owner_id, checksum)', + ); + late final Index uQRemoteAssetsOwnerChecksum = Index( + 'UQ_remote_assets_owner_checksum', + 'CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_checksum ON remote_asset_entity (owner_id, checksum) WHERE(library_id IS NULL)', + ); + late final Index uQRemoteAssetsOwnerLibraryChecksum = Index( + 'UQ_remote_assets_owner_library_checksum', + 'CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_library_checksum ON remote_asset_entity (owner_id, library_id, checksum) WHERE(library_id IS NOT NULL)', + ); + late final Index idxRemoteAssetChecksum = Index( + 'idx_remote_asset_checksum', + 'CREATE INDEX IF NOT EXISTS idx_remote_asset_checksum ON remote_asset_entity (checksum)', + ); + late final AuthUserEntity authUserEntity = AuthUserEntity(this); + late final UserMetadataEntity userMetadataEntity = UserMetadataEntity(this); + late final PartnerEntity partnerEntity = PartnerEntity(this); + late final RemoteExifEntity remoteExifEntity = RemoteExifEntity(this); + late final RemoteAlbumAssetEntity remoteAlbumAssetEntity = + RemoteAlbumAssetEntity(this); + late final RemoteAlbumUserEntity remoteAlbumUserEntity = + RemoteAlbumUserEntity(this); + late final MemoryEntity memoryEntity = MemoryEntity(this); + late final MemoryAssetEntity memoryAssetEntity = MemoryAssetEntity(this); + late final PersonEntity personEntity = PersonEntity(this); + late final AssetFaceEntity assetFaceEntity = AssetFaceEntity(this); + late final StoreEntity storeEntity = StoreEntity(this); + late final Index idxLatLng = Index( + 'idx_lat_lng', + 'CREATE INDEX IF NOT EXISTS idx_lat_lng ON remote_exif_entity (latitude, longitude)', + ); + @override + Iterable> get allTables => + allSchemaEntities.whereType>(); + @override + List get allSchemaEntities => [ + userEntity, + remoteAssetEntity, + stackEntity, + localAssetEntity, + remoteAlbumEntity, + localAlbumEntity, + localAlbumAssetEntity, + idxLocalAssetChecksum, + idxRemoteAssetOwnerChecksum, + uQRemoteAssetsOwnerChecksum, + uQRemoteAssetsOwnerLibraryChecksum, + idxRemoteAssetChecksum, + authUserEntity, + userMetadataEntity, + partnerEntity, + remoteExifEntity, + remoteAlbumAssetEntity, + remoteAlbumUserEntity, + memoryEntity, + memoryAssetEntity, + personEntity, + assetFaceEntity, + storeEntity, + idxLatLng, + ]; + @override + int get schemaVersion => 11; + @override + DriftDatabaseOptions get options => + const DriftDatabaseOptions(storeDateTimeAsText: true); +} diff --git a/mobile/test/drift/main/generated/schema_v12.dart b/mobile/test/drift/main/generated/schema_v12.dart new file mode 100644 index 0000000000..c42df284ec --- /dev/null +++ b/mobile/test/drift/main/generated/schema_v12.dart @@ -0,0 +1,7198 @@ +// dart format width=80 +// GENERATED CODE, DO NOT EDIT BY HAND. +// ignore_for_file: type=lint +import 'package:drift/drift.dart'; + +class UserEntity extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + UserEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn email = GeneratedColumn( + 'email', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn hasProfileImage = GeneratedColumn( + 'has_profile_image', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("has_profile_image" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn profileChangedAt = + GeneratedColumn( + 'profile_changed_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn avatarColor = GeneratedColumn( + 'avatar_color', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0'), + ); + @override + List get $columns => [ + id, + name, + email, + hasProfileImage, + profileChangedAt, + avatarColor, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'user_entity'; + @override + Set get $primaryKey => {id}; + @override + UserEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return UserEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + email: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}email'], + )!, + hasProfileImage: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}has_profile_image'], + )!, + profileChangedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}profile_changed_at'], + )!, + avatarColor: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}avatar_color'], + )!, + ); + } + + @override + UserEntity createAlias(String alias) { + return UserEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class UserEntityData extends DataClass implements Insertable { + final String id; + final String name; + final String email; + final bool hasProfileImage; + final DateTime profileChangedAt; + final int avatarColor; + const UserEntityData({ + required this.id, + required this.name, + required this.email, + required this.hasProfileImage, + required this.profileChangedAt, + required this.avatarColor, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + map['email'] = Variable(email); + map['has_profile_image'] = Variable(hasProfileImage); + map['profile_changed_at'] = Variable(profileChangedAt); + map['avatar_color'] = Variable(avatarColor); + return map; + } + + factory UserEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return UserEntityData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + email: serializer.fromJson(json['email']), + hasProfileImage: serializer.fromJson(json['hasProfileImage']), + profileChangedAt: serializer.fromJson(json['profileChangedAt']), + avatarColor: serializer.fromJson(json['avatarColor']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'email': serializer.toJson(email), + 'hasProfileImage': serializer.toJson(hasProfileImage), + 'profileChangedAt': serializer.toJson(profileChangedAt), + 'avatarColor': serializer.toJson(avatarColor), + }; + } + + UserEntityData copyWith({ + String? id, + String? name, + String? email, + bool? hasProfileImage, + DateTime? profileChangedAt, + int? avatarColor, + }) => UserEntityData( + id: id ?? this.id, + name: name ?? this.name, + email: email ?? this.email, + hasProfileImage: hasProfileImage ?? this.hasProfileImage, + profileChangedAt: profileChangedAt ?? this.profileChangedAt, + avatarColor: avatarColor ?? this.avatarColor, + ); + UserEntityData copyWithCompanion(UserEntityCompanion data) { + return UserEntityData( + id: data.id.present ? data.id.value : this.id, + name: data.name.present ? data.name.value : this.name, + email: data.email.present ? data.email.value : this.email, + hasProfileImage: data.hasProfileImage.present + ? data.hasProfileImage.value + : this.hasProfileImage, + profileChangedAt: data.profileChangedAt.present + ? data.profileChangedAt.value + : this.profileChangedAt, + avatarColor: data.avatarColor.present + ? data.avatarColor.value + : this.avatarColor, + ); + } + + @override + String toString() { + return (StringBuffer('UserEntityData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('email: $email, ') + ..write('hasProfileImage: $hasProfileImage, ') + ..write('profileChangedAt: $profileChangedAt, ') + ..write('avatarColor: $avatarColor') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + name, + email, + hasProfileImage, + profileChangedAt, + avatarColor, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is UserEntityData && + other.id == this.id && + other.name == this.name && + other.email == this.email && + other.hasProfileImage == this.hasProfileImage && + other.profileChangedAt == this.profileChangedAt && + other.avatarColor == this.avatarColor); +} + +class UserEntityCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value email; + final Value hasProfileImage; + final Value profileChangedAt; + final Value avatarColor; + const UserEntityCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.email = const Value.absent(), + this.hasProfileImage = const Value.absent(), + this.profileChangedAt = const Value.absent(), + this.avatarColor = const Value.absent(), + }); + UserEntityCompanion.insert({ + required String id, + required String name, + required String email, + this.hasProfileImage = const Value.absent(), + this.profileChangedAt = const Value.absent(), + this.avatarColor = const Value.absent(), + }) : id = Value(id), + name = Value(name), + email = Value(email); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? email, + Expression? hasProfileImage, + Expression? profileChangedAt, + Expression? avatarColor, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (email != null) 'email': email, + if (hasProfileImage != null) 'has_profile_image': hasProfileImage, + if (profileChangedAt != null) 'profile_changed_at': profileChangedAt, + if (avatarColor != null) 'avatar_color': avatarColor, + }); + } + + UserEntityCompanion copyWith({ + Value? id, + Value? name, + Value? email, + Value? hasProfileImage, + Value? profileChangedAt, + Value? avatarColor, + }) { + return UserEntityCompanion( + id: id ?? this.id, + name: name ?? this.name, + email: email ?? this.email, + hasProfileImage: hasProfileImage ?? this.hasProfileImage, + profileChangedAt: profileChangedAt ?? this.profileChangedAt, + avatarColor: avatarColor ?? this.avatarColor, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (email.present) { + map['email'] = Variable(email.value); + } + if (hasProfileImage.present) { + map['has_profile_image'] = Variable(hasProfileImage.value); + } + if (profileChangedAt.present) { + map['profile_changed_at'] = Variable(profileChangedAt.value); + } + if (avatarColor.present) { + map['avatar_color'] = Variable(avatarColor.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('UserEntityCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('email: $email, ') + ..write('hasProfileImage: $hasProfileImage, ') + ..write('profileChangedAt: $profileChangedAt, ') + ..write('avatarColor: $avatarColor') + ..write(')')) + .toString(); + } +} + +class RemoteAssetEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RemoteAssetEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn type = GeneratedColumn( + 'type', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn width = GeneratedColumn( + 'width', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn height = GeneratedColumn( + 'height', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn durationInSeconds = GeneratedColumn( + 'duration_in_seconds', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn checksum = GeneratedColumn( + 'checksum', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn isFavorite = GeneratedColumn( + 'is_favorite', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_favorite" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn ownerId = GeneratedColumn( + 'owner_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn localDateTime = + GeneratedColumn( + 'local_date_time', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn thumbHash = GeneratedColumn( + 'thumb_hash', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn deletedAt = GeneratedColumn( + 'deleted_at', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn livePhotoVideoId = GeneratedColumn( + 'live_photo_video_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn visibility = GeneratedColumn( + 'visibility', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn stackId = GeneratedColumn( + 'stack_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn libraryId = GeneratedColumn( + 'library_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + @override + List get $columns => [ + name, + type, + createdAt, + updatedAt, + width, + height, + durationInSeconds, + id, + checksum, + isFavorite, + ownerId, + localDateTime, + thumbHash, + deletedAt, + livePhotoVideoId, + visibility, + stackId, + libraryId, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'remote_asset_entity'; + @override + Set get $primaryKey => {id}; + @override + RemoteAssetEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RemoteAssetEntityData( + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + type: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}type'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + width: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}width'], + ), + height: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}height'], + ), + durationInSeconds: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}duration_in_seconds'], + ), + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + checksum: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}checksum'], + )!, + isFavorite: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_favorite'], + )!, + ownerId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}owner_id'], + )!, + localDateTime: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}local_date_time'], + ), + thumbHash: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}thumb_hash'], + ), + deletedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}deleted_at'], + ), + livePhotoVideoId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}live_photo_video_id'], + ), + visibility: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}visibility'], + )!, + stackId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}stack_id'], + ), + libraryId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}library_id'], + ), + ); + } + + @override + RemoteAssetEntity createAlias(String alias) { + return RemoteAssetEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class RemoteAssetEntityData extends DataClass + implements Insertable { + final String name; + final int type; + final DateTime createdAt; + final DateTime updatedAt; + final int? width; + final int? height; + final int? durationInSeconds; + final String id; + final String checksum; + final bool isFavorite; + final String ownerId; + final DateTime? localDateTime; + final String? thumbHash; + final DateTime? deletedAt; + final String? livePhotoVideoId; + final int visibility; + final String? stackId; + final String? libraryId; + const RemoteAssetEntityData({ + required this.name, + required this.type, + required this.createdAt, + required this.updatedAt, + this.width, + this.height, + this.durationInSeconds, + required this.id, + required this.checksum, + required this.isFavorite, + required this.ownerId, + this.localDateTime, + this.thumbHash, + this.deletedAt, + this.livePhotoVideoId, + required this.visibility, + this.stackId, + this.libraryId, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['name'] = Variable(name); + map['type'] = Variable(type); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || width != null) { + map['width'] = Variable(width); + } + if (!nullToAbsent || height != null) { + map['height'] = Variable(height); + } + if (!nullToAbsent || durationInSeconds != null) { + map['duration_in_seconds'] = Variable(durationInSeconds); + } + map['id'] = Variable(id); + map['checksum'] = Variable(checksum); + map['is_favorite'] = Variable(isFavorite); + map['owner_id'] = Variable(ownerId); + if (!nullToAbsent || localDateTime != null) { + map['local_date_time'] = Variable(localDateTime); + } + if (!nullToAbsent || thumbHash != null) { + map['thumb_hash'] = Variable(thumbHash); + } + if (!nullToAbsent || deletedAt != null) { + map['deleted_at'] = Variable(deletedAt); + } + if (!nullToAbsent || livePhotoVideoId != null) { + map['live_photo_video_id'] = Variable(livePhotoVideoId); + } + map['visibility'] = Variable(visibility); + if (!nullToAbsent || stackId != null) { + map['stack_id'] = Variable(stackId); + } + if (!nullToAbsent || libraryId != null) { + map['library_id'] = Variable(libraryId); + } + return map; + } + + factory RemoteAssetEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RemoteAssetEntityData( + name: serializer.fromJson(json['name']), + type: serializer.fromJson(json['type']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + width: serializer.fromJson(json['width']), + height: serializer.fromJson(json['height']), + durationInSeconds: serializer.fromJson(json['durationInSeconds']), + id: serializer.fromJson(json['id']), + checksum: serializer.fromJson(json['checksum']), + isFavorite: serializer.fromJson(json['isFavorite']), + ownerId: serializer.fromJson(json['ownerId']), + localDateTime: serializer.fromJson(json['localDateTime']), + thumbHash: serializer.fromJson(json['thumbHash']), + deletedAt: serializer.fromJson(json['deletedAt']), + livePhotoVideoId: serializer.fromJson(json['livePhotoVideoId']), + visibility: serializer.fromJson(json['visibility']), + stackId: serializer.fromJson(json['stackId']), + libraryId: serializer.fromJson(json['libraryId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'name': serializer.toJson(name), + 'type': serializer.toJson(type), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'width': serializer.toJson(width), + 'height': serializer.toJson(height), + 'durationInSeconds': serializer.toJson(durationInSeconds), + 'id': serializer.toJson(id), + 'checksum': serializer.toJson(checksum), + 'isFavorite': serializer.toJson(isFavorite), + 'ownerId': serializer.toJson(ownerId), + 'localDateTime': serializer.toJson(localDateTime), + 'thumbHash': serializer.toJson(thumbHash), + 'deletedAt': serializer.toJson(deletedAt), + 'livePhotoVideoId': serializer.toJson(livePhotoVideoId), + 'visibility': serializer.toJson(visibility), + 'stackId': serializer.toJson(stackId), + 'libraryId': serializer.toJson(libraryId), + }; + } + + RemoteAssetEntityData copyWith({ + String? name, + int? type, + DateTime? createdAt, + DateTime? updatedAt, + Value width = const Value.absent(), + Value height = const Value.absent(), + Value durationInSeconds = const Value.absent(), + String? id, + String? checksum, + bool? isFavorite, + String? ownerId, + Value localDateTime = const Value.absent(), + Value thumbHash = const Value.absent(), + Value deletedAt = const Value.absent(), + Value livePhotoVideoId = const Value.absent(), + int? visibility, + Value stackId = const Value.absent(), + Value libraryId = const Value.absent(), + }) => RemoteAssetEntityData( + name: name ?? this.name, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + width: width.present ? width.value : this.width, + height: height.present ? height.value : this.height, + durationInSeconds: durationInSeconds.present + ? durationInSeconds.value + : this.durationInSeconds, + id: id ?? this.id, + checksum: checksum ?? this.checksum, + isFavorite: isFavorite ?? this.isFavorite, + ownerId: ownerId ?? this.ownerId, + localDateTime: localDateTime.present + ? localDateTime.value + : this.localDateTime, + thumbHash: thumbHash.present ? thumbHash.value : this.thumbHash, + deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt, + livePhotoVideoId: livePhotoVideoId.present + ? livePhotoVideoId.value + : this.livePhotoVideoId, + visibility: visibility ?? this.visibility, + stackId: stackId.present ? stackId.value : this.stackId, + libraryId: libraryId.present ? libraryId.value : this.libraryId, + ); + RemoteAssetEntityData copyWithCompanion(RemoteAssetEntityCompanion data) { + return RemoteAssetEntityData( + name: data.name.present ? data.name.value : this.name, + type: data.type.present ? data.type.value : this.type, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + width: data.width.present ? data.width.value : this.width, + height: data.height.present ? data.height.value : this.height, + durationInSeconds: data.durationInSeconds.present + ? data.durationInSeconds.value + : this.durationInSeconds, + id: data.id.present ? data.id.value : this.id, + checksum: data.checksum.present ? data.checksum.value : this.checksum, + isFavorite: data.isFavorite.present + ? data.isFavorite.value + : this.isFavorite, + ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId, + localDateTime: data.localDateTime.present + ? data.localDateTime.value + : this.localDateTime, + thumbHash: data.thumbHash.present ? data.thumbHash.value : this.thumbHash, + deletedAt: data.deletedAt.present ? data.deletedAt.value : this.deletedAt, + livePhotoVideoId: data.livePhotoVideoId.present + ? data.livePhotoVideoId.value + : this.livePhotoVideoId, + visibility: data.visibility.present + ? data.visibility.value + : this.visibility, + stackId: data.stackId.present ? data.stackId.value : this.stackId, + libraryId: data.libraryId.present ? data.libraryId.value : this.libraryId, + ); + } + + @override + String toString() { + return (StringBuffer('RemoteAssetEntityData(') + ..write('name: $name, ') + ..write('type: $type, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('width: $width, ') + ..write('height: $height, ') + ..write('durationInSeconds: $durationInSeconds, ') + ..write('id: $id, ') + ..write('checksum: $checksum, ') + ..write('isFavorite: $isFavorite, ') + ..write('ownerId: $ownerId, ') + ..write('localDateTime: $localDateTime, ') + ..write('thumbHash: $thumbHash, ') + ..write('deletedAt: $deletedAt, ') + ..write('livePhotoVideoId: $livePhotoVideoId, ') + ..write('visibility: $visibility, ') + ..write('stackId: $stackId, ') + ..write('libraryId: $libraryId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + name, + type, + createdAt, + updatedAt, + width, + height, + durationInSeconds, + id, + checksum, + isFavorite, + ownerId, + localDateTime, + thumbHash, + deletedAt, + livePhotoVideoId, + visibility, + stackId, + libraryId, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RemoteAssetEntityData && + other.name == this.name && + other.type == this.type && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.width == this.width && + other.height == this.height && + other.durationInSeconds == this.durationInSeconds && + other.id == this.id && + other.checksum == this.checksum && + other.isFavorite == this.isFavorite && + other.ownerId == this.ownerId && + other.localDateTime == this.localDateTime && + other.thumbHash == this.thumbHash && + other.deletedAt == this.deletedAt && + other.livePhotoVideoId == this.livePhotoVideoId && + other.visibility == this.visibility && + other.stackId == this.stackId && + other.libraryId == this.libraryId); +} + +class RemoteAssetEntityCompanion + extends UpdateCompanion { + final Value name; + final Value type; + final Value createdAt; + final Value updatedAt; + final Value width; + final Value height; + final Value durationInSeconds; + final Value id; + final Value checksum; + final Value isFavorite; + final Value ownerId; + final Value localDateTime; + final Value thumbHash; + final Value deletedAt; + final Value livePhotoVideoId; + final Value visibility; + final Value stackId; + final Value libraryId; + const RemoteAssetEntityCompanion({ + this.name = const Value.absent(), + this.type = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.width = const Value.absent(), + this.height = const Value.absent(), + this.durationInSeconds = const Value.absent(), + this.id = const Value.absent(), + this.checksum = const Value.absent(), + this.isFavorite = const Value.absent(), + this.ownerId = const Value.absent(), + this.localDateTime = const Value.absent(), + this.thumbHash = const Value.absent(), + this.deletedAt = const Value.absent(), + this.livePhotoVideoId = const Value.absent(), + this.visibility = const Value.absent(), + this.stackId = const Value.absent(), + this.libraryId = const Value.absent(), + }); + RemoteAssetEntityCompanion.insert({ + required String name, + required int type, + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.width = const Value.absent(), + this.height = const Value.absent(), + this.durationInSeconds = const Value.absent(), + required String id, + required String checksum, + this.isFavorite = const Value.absent(), + required String ownerId, + this.localDateTime = const Value.absent(), + this.thumbHash = const Value.absent(), + this.deletedAt = const Value.absent(), + this.livePhotoVideoId = const Value.absent(), + required int visibility, + this.stackId = const Value.absent(), + this.libraryId = const Value.absent(), + }) : name = Value(name), + type = Value(type), + id = Value(id), + checksum = Value(checksum), + ownerId = Value(ownerId), + visibility = Value(visibility); + static Insertable custom({ + Expression? name, + Expression? type, + Expression? createdAt, + Expression? updatedAt, + Expression? width, + Expression? height, + Expression? durationInSeconds, + Expression? id, + Expression? checksum, + Expression? isFavorite, + Expression? ownerId, + Expression? localDateTime, + Expression? thumbHash, + Expression? deletedAt, + Expression? livePhotoVideoId, + Expression? visibility, + Expression? stackId, + Expression? libraryId, + }) { + return RawValuesInsertable({ + if (name != null) 'name': name, + if (type != null) 'type': type, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (width != null) 'width': width, + if (height != null) 'height': height, + if (durationInSeconds != null) 'duration_in_seconds': durationInSeconds, + if (id != null) 'id': id, + if (checksum != null) 'checksum': checksum, + if (isFavorite != null) 'is_favorite': isFavorite, + if (ownerId != null) 'owner_id': ownerId, + if (localDateTime != null) 'local_date_time': localDateTime, + if (thumbHash != null) 'thumb_hash': thumbHash, + if (deletedAt != null) 'deleted_at': deletedAt, + if (livePhotoVideoId != null) 'live_photo_video_id': livePhotoVideoId, + if (visibility != null) 'visibility': visibility, + if (stackId != null) 'stack_id': stackId, + if (libraryId != null) 'library_id': libraryId, + }); + } + + RemoteAssetEntityCompanion copyWith({ + Value? name, + Value? type, + Value? createdAt, + Value? updatedAt, + Value? width, + Value? height, + Value? durationInSeconds, + Value? id, + Value? checksum, + Value? isFavorite, + Value? ownerId, + Value? localDateTime, + Value? thumbHash, + Value? deletedAt, + Value? livePhotoVideoId, + Value? visibility, + Value? stackId, + Value? libraryId, + }) { + return RemoteAssetEntityCompanion( + name: name ?? this.name, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + width: width ?? this.width, + height: height ?? this.height, + durationInSeconds: durationInSeconds ?? this.durationInSeconds, + id: id ?? this.id, + checksum: checksum ?? this.checksum, + isFavorite: isFavorite ?? this.isFavorite, + ownerId: ownerId ?? this.ownerId, + localDateTime: localDateTime ?? this.localDateTime, + thumbHash: thumbHash ?? this.thumbHash, + deletedAt: deletedAt ?? this.deletedAt, + livePhotoVideoId: livePhotoVideoId ?? this.livePhotoVideoId, + visibility: visibility ?? this.visibility, + stackId: stackId ?? this.stackId, + libraryId: libraryId ?? this.libraryId, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (name.present) { + map['name'] = Variable(name.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (width.present) { + map['width'] = Variable(width.value); + } + if (height.present) { + map['height'] = Variable(height.value); + } + if (durationInSeconds.present) { + map['duration_in_seconds'] = Variable(durationInSeconds.value); + } + if (id.present) { + map['id'] = Variable(id.value); + } + if (checksum.present) { + map['checksum'] = Variable(checksum.value); + } + if (isFavorite.present) { + map['is_favorite'] = Variable(isFavorite.value); + } + if (ownerId.present) { + map['owner_id'] = Variable(ownerId.value); + } + if (localDateTime.present) { + map['local_date_time'] = Variable(localDateTime.value); + } + if (thumbHash.present) { + map['thumb_hash'] = Variable(thumbHash.value); + } + if (deletedAt.present) { + map['deleted_at'] = Variable(deletedAt.value); + } + if (livePhotoVideoId.present) { + map['live_photo_video_id'] = Variable(livePhotoVideoId.value); + } + if (visibility.present) { + map['visibility'] = Variable(visibility.value); + } + if (stackId.present) { + map['stack_id'] = Variable(stackId.value); + } + if (libraryId.present) { + map['library_id'] = Variable(libraryId.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RemoteAssetEntityCompanion(') + ..write('name: $name, ') + ..write('type: $type, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('width: $width, ') + ..write('height: $height, ') + ..write('durationInSeconds: $durationInSeconds, ') + ..write('id: $id, ') + ..write('checksum: $checksum, ') + ..write('isFavorite: $isFavorite, ') + ..write('ownerId: $ownerId, ') + ..write('localDateTime: $localDateTime, ') + ..write('thumbHash: $thumbHash, ') + ..write('deletedAt: $deletedAt, ') + ..write('livePhotoVideoId: $livePhotoVideoId, ') + ..write('visibility: $visibility, ') + ..write('stackId: $stackId, ') + ..write('libraryId: $libraryId') + ..write(')')) + .toString(); + } +} + +class StackEntity extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + StackEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn ownerId = GeneratedColumn( + 'owner_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn primaryAssetId = GeneratedColumn( + 'primary_asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + ownerId, + primaryAssetId, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'stack_entity'; + @override + Set get $primaryKey => {id}; + @override + StackEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return StackEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + ownerId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}owner_id'], + )!, + primaryAssetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}primary_asset_id'], + )!, + ); + } + + @override + StackEntity createAlias(String alias) { + return StackEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class StackEntityData extends DataClass implements Insertable { + final String id; + final DateTime createdAt; + final DateTime updatedAt; + final String ownerId; + final String primaryAssetId; + const StackEntityData({ + required this.id, + required this.createdAt, + required this.updatedAt, + required this.ownerId, + required this.primaryAssetId, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + map['owner_id'] = Variable(ownerId); + map['primary_asset_id'] = Variable(primaryAssetId); + return map; + } + + factory StackEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return StackEntityData( + id: serializer.fromJson(json['id']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + ownerId: serializer.fromJson(json['ownerId']), + primaryAssetId: serializer.fromJson(json['primaryAssetId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'ownerId': serializer.toJson(ownerId), + 'primaryAssetId': serializer.toJson(primaryAssetId), + }; + } + + StackEntityData copyWith({ + String? id, + DateTime? createdAt, + DateTime? updatedAt, + String? ownerId, + String? primaryAssetId, + }) => StackEntityData( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + primaryAssetId: primaryAssetId ?? this.primaryAssetId, + ); + StackEntityData copyWithCompanion(StackEntityCompanion data) { + return StackEntityData( + id: data.id.present ? data.id.value : this.id, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId, + primaryAssetId: data.primaryAssetId.present + ? data.primaryAssetId.value + : this.primaryAssetId, + ); + } + + @override + String toString() { + return (StringBuffer('StackEntityData(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('primaryAssetId: $primaryAssetId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => + Object.hash(id, createdAt, updatedAt, ownerId, primaryAssetId); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is StackEntityData && + other.id == this.id && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.ownerId == this.ownerId && + other.primaryAssetId == this.primaryAssetId); +} + +class StackEntityCompanion extends UpdateCompanion { + final Value id; + final Value createdAt; + final Value updatedAt; + final Value ownerId; + final Value primaryAssetId; + const StackEntityCompanion({ + this.id = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.ownerId = const Value.absent(), + this.primaryAssetId = const Value.absent(), + }); + StackEntityCompanion.insert({ + required String id, + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + required String ownerId, + required String primaryAssetId, + }) : id = Value(id), + ownerId = Value(ownerId), + primaryAssetId = Value(primaryAssetId); + static Insertable custom({ + Expression? id, + Expression? createdAt, + Expression? updatedAt, + Expression? ownerId, + Expression? primaryAssetId, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (ownerId != null) 'owner_id': ownerId, + if (primaryAssetId != null) 'primary_asset_id': primaryAssetId, + }); + } + + StackEntityCompanion copyWith({ + Value? id, + Value? createdAt, + Value? updatedAt, + Value? ownerId, + Value? primaryAssetId, + }) { + return StackEntityCompanion( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + primaryAssetId: primaryAssetId ?? this.primaryAssetId, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (ownerId.present) { + map['owner_id'] = Variable(ownerId.value); + } + if (primaryAssetId.present) { + map['primary_asset_id'] = Variable(primaryAssetId.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('StackEntityCompanion(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('primaryAssetId: $primaryAssetId') + ..write(')')) + .toString(); + } +} + +class LocalAssetEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + LocalAssetEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn type = GeneratedColumn( + 'type', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn width = GeneratedColumn( + 'width', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn height = GeneratedColumn( + 'height', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn durationInSeconds = GeneratedColumn( + 'duration_in_seconds', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn checksum = GeneratedColumn( + 'checksum', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn isFavorite = GeneratedColumn( + 'is_favorite', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_favorite" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn orientation = GeneratedColumn( + 'orientation', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0'), + ); + @override + List get $columns => [ + name, + type, + createdAt, + updatedAt, + width, + height, + durationInSeconds, + id, + checksum, + isFavorite, + orientation, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'local_asset_entity'; + @override + Set get $primaryKey => {id}; + @override + LocalAssetEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return LocalAssetEntityData( + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + type: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}type'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + width: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}width'], + ), + height: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}height'], + ), + durationInSeconds: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}duration_in_seconds'], + ), + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + checksum: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}checksum'], + ), + isFavorite: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_favorite'], + )!, + orientation: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}orientation'], + )!, + ); + } + + @override + LocalAssetEntity createAlias(String alias) { + return LocalAssetEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class LocalAssetEntityData extends DataClass + implements Insertable { + final String name; + final int type; + final DateTime createdAt; + final DateTime updatedAt; + final int? width; + final int? height; + final int? durationInSeconds; + final String id; + final String? checksum; + final bool isFavorite; + final int orientation; + const LocalAssetEntityData({ + required this.name, + required this.type, + required this.createdAt, + required this.updatedAt, + this.width, + this.height, + this.durationInSeconds, + required this.id, + this.checksum, + required this.isFavorite, + required this.orientation, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['name'] = Variable(name); + map['type'] = Variable(type); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || width != null) { + map['width'] = Variable(width); + } + if (!nullToAbsent || height != null) { + map['height'] = Variable(height); + } + if (!nullToAbsent || durationInSeconds != null) { + map['duration_in_seconds'] = Variable(durationInSeconds); + } + map['id'] = Variable(id); + if (!nullToAbsent || checksum != null) { + map['checksum'] = Variable(checksum); + } + map['is_favorite'] = Variable(isFavorite); + map['orientation'] = Variable(orientation); + return map; + } + + factory LocalAssetEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return LocalAssetEntityData( + name: serializer.fromJson(json['name']), + type: serializer.fromJson(json['type']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + width: serializer.fromJson(json['width']), + height: serializer.fromJson(json['height']), + durationInSeconds: serializer.fromJson(json['durationInSeconds']), + id: serializer.fromJson(json['id']), + checksum: serializer.fromJson(json['checksum']), + isFavorite: serializer.fromJson(json['isFavorite']), + orientation: serializer.fromJson(json['orientation']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'name': serializer.toJson(name), + 'type': serializer.toJson(type), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'width': serializer.toJson(width), + 'height': serializer.toJson(height), + 'durationInSeconds': serializer.toJson(durationInSeconds), + 'id': serializer.toJson(id), + 'checksum': serializer.toJson(checksum), + 'isFavorite': serializer.toJson(isFavorite), + 'orientation': serializer.toJson(orientation), + }; + } + + LocalAssetEntityData copyWith({ + String? name, + int? type, + DateTime? createdAt, + DateTime? updatedAt, + Value width = const Value.absent(), + Value height = const Value.absent(), + Value durationInSeconds = const Value.absent(), + String? id, + Value checksum = const Value.absent(), + bool? isFavorite, + int? orientation, + }) => LocalAssetEntityData( + name: name ?? this.name, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + width: width.present ? width.value : this.width, + height: height.present ? height.value : this.height, + durationInSeconds: durationInSeconds.present + ? durationInSeconds.value + : this.durationInSeconds, + id: id ?? this.id, + checksum: checksum.present ? checksum.value : this.checksum, + isFavorite: isFavorite ?? this.isFavorite, + orientation: orientation ?? this.orientation, + ); + LocalAssetEntityData copyWithCompanion(LocalAssetEntityCompanion data) { + return LocalAssetEntityData( + name: data.name.present ? data.name.value : this.name, + type: data.type.present ? data.type.value : this.type, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + width: data.width.present ? data.width.value : this.width, + height: data.height.present ? data.height.value : this.height, + durationInSeconds: data.durationInSeconds.present + ? data.durationInSeconds.value + : this.durationInSeconds, + id: data.id.present ? data.id.value : this.id, + checksum: data.checksum.present ? data.checksum.value : this.checksum, + isFavorite: data.isFavorite.present + ? data.isFavorite.value + : this.isFavorite, + orientation: data.orientation.present + ? data.orientation.value + : this.orientation, + ); + } + + @override + String toString() { + return (StringBuffer('LocalAssetEntityData(') + ..write('name: $name, ') + ..write('type: $type, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('width: $width, ') + ..write('height: $height, ') + ..write('durationInSeconds: $durationInSeconds, ') + ..write('id: $id, ') + ..write('checksum: $checksum, ') + ..write('isFavorite: $isFavorite, ') + ..write('orientation: $orientation') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + name, + type, + createdAt, + updatedAt, + width, + height, + durationInSeconds, + id, + checksum, + isFavorite, + orientation, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is LocalAssetEntityData && + other.name == this.name && + other.type == this.type && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.width == this.width && + other.height == this.height && + other.durationInSeconds == this.durationInSeconds && + other.id == this.id && + other.checksum == this.checksum && + other.isFavorite == this.isFavorite && + other.orientation == this.orientation); +} + +class LocalAssetEntityCompanion extends UpdateCompanion { + final Value name; + final Value type; + final Value createdAt; + final Value updatedAt; + final Value width; + final Value height; + final Value durationInSeconds; + final Value id; + final Value checksum; + final Value isFavorite; + final Value orientation; + const LocalAssetEntityCompanion({ + this.name = const Value.absent(), + this.type = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.width = const Value.absent(), + this.height = const Value.absent(), + this.durationInSeconds = const Value.absent(), + this.id = const Value.absent(), + this.checksum = const Value.absent(), + this.isFavorite = const Value.absent(), + this.orientation = const Value.absent(), + }); + LocalAssetEntityCompanion.insert({ + required String name, + required int type, + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.width = const Value.absent(), + this.height = const Value.absent(), + this.durationInSeconds = const Value.absent(), + required String id, + this.checksum = const Value.absent(), + this.isFavorite = const Value.absent(), + this.orientation = const Value.absent(), + }) : name = Value(name), + type = Value(type), + id = Value(id); + static Insertable custom({ + Expression? name, + Expression? type, + Expression? createdAt, + Expression? updatedAt, + Expression? width, + Expression? height, + Expression? durationInSeconds, + Expression? id, + Expression? checksum, + Expression? isFavorite, + Expression? orientation, + }) { + return RawValuesInsertable({ + if (name != null) 'name': name, + if (type != null) 'type': type, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (width != null) 'width': width, + if (height != null) 'height': height, + if (durationInSeconds != null) 'duration_in_seconds': durationInSeconds, + if (id != null) 'id': id, + if (checksum != null) 'checksum': checksum, + if (isFavorite != null) 'is_favorite': isFavorite, + if (orientation != null) 'orientation': orientation, + }); + } + + LocalAssetEntityCompanion copyWith({ + Value? name, + Value? type, + Value? createdAt, + Value? updatedAt, + Value? width, + Value? height, + Value? durationInSeconds, + Value? id, + Value? checksum, + Value? isFavorite, + Value? orientation, + }) { + return LocalAssetEntityCompanion( + name: name ?? this.name, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + width: width ?? this.width, + height: height ?? this.height, + durationInSeconds: durationInSeconds ?? this.durationInSeconds, + id: id ?? this.id, + checksum: checksum ?? this.checksum, + isFavorite: isFavorite ?? this.isFavorite, + orientation: orientation ?? this.orientation, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (name.present) { + map['name'] = Variable(name.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (width.present) { + map['width'] = Variable(width.value); + } + if (height.present) { + map['height'] = Variable(height.value); + } + if (durationInSeconds.present) { + map['duration_in_seconds'] = Variable(durationInSeconds.value); + } + if (id.present) { + map['id'] = Variable(id.value); + } + if (checksum.present) { + map['checksum'] = Variable(checksum.value); + } + if (isFavorite.present) { + map['is_favorite'] = Variable(isFavorite.value); + } + if (orientation.present) { + map['orientation'] = Variable(orientation.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('LocalAssetEntityCompanion(') + ..write('name: $name, ') + ..write('type: $type, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('width: $width, ') + ..write('height: $height, ') + ..write('durationInSeconds: $durationInSeconds, ') + ..write('id: $id, ') + ..write('checksum: $checksum, ') + ..write('isFavorite: $isFavorite, ') + ..write('orientation: $orientation') + ..write(')')) + .toString(); + } +} + +class RemoteAlbumEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RemoteAlbumEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn description = GeneratedColumn( + 'description', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'\''), + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn ownerId = GeneratedColumn( + 'owner_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn thumbnailAssetId = GeneratedColumn( + 'thumbnail_asset_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_asset_entity (id) ON DELETE SET NULL', + ), + ); + late final GeneratedColumn isActivityEnabled = GeneratedColumn( + 'is_activity_enabled', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_activity_enabled" IN (0, 1))', + ), + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn order = GeneratedColumn( + 'order', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + @override + List get $columns => [ + id, + name, + description, + createdAt, + updatedAt, + ownerId, + thumbnailAssetId, + isActivityEnabled, + order, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'remote_album_entity'; + @override + Set get $primaryKey => {id}; + @override + RemoteAlbumEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RemoteAlbumEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + description: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}description'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + ownerId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}owner_id'], + )!, + thumbnailAssetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}thumbnail_asset_id'], + ), + isActivityEnabled: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_activity_enabled'], + )!, + order: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}order'], + )!, + ); + } + + @override + RemoteAlbumEntity createAlias(String alias) { + return RemoteAlbumEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class RemoteAlbumEntityData extends DataClass + implements Insertable { + final String id; + final String name; + final String description; + final DateTime createdAt; + final DateTime updatedAt; + final String ownerId; + final String? thumbnailAssetId; + final bool isActivityEnabled; + final int order; + const RemoteAlbumEntityData({ + required this.id, + required this.name, + required this.description, + required this.createdAt, + required this.updatedAt, + required this.ownerId, + this.thumbnailAssetId, + required this.isActivityEnabled, + required this.order, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + map['description'] = Variable(description); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + map['owner_id'] = Variable(ownerId); + if (!nullToAbsent || thumbnailAssetId != null) { + map['thumbnail_asset_id'] = Variable(thumbnailAssetId); + } + map['is_activity_enabled'] = Variable(isActivityEnabled); + map['order'] = Variable(order); + return map; + } + + factory RemoteAlbumEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RemoteAlbumEntityData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + description: serializer.fromJson(json['description']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + ownerId: serializer.fromJson(json['ownerId']), + thumbnailAssetId: serializer.fromJson(json['thumbnailAssetId']), + isActivityEnabled: serializer.fromJson(json['isActivityEnabled']), + order: serializer.fromJson(json['order']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'description': serializer.toJson(description), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'ownerId': serializer.toJson(ownerId), + 'thumbnailAssetId': serializer.toJson(thumbnailAssetId), + 'isActivityEnabled': serializer.toJson(isActivityEnabled), + 'order': serializer.toJson(order), + }; + } + + RemoteAlbumEntityData copyWith({ + String? id, + String? name, + String? description, + DateTime? createdAt, + DateTime? updatedAt, + String? ownerId, + Value thumbnailAssetId = const Value.absent(), + bool? isActivityEnabled, + int? order, + }) => RemoteAlbumEntityData( + id: id ?? this.id, + name: name ?? this.name, + description: description ?? this.description, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + thumbnailAssetId: thumbnailAssetId.present + ? thumbnailAssetId.value + : this.thumbnailAssetId, + isActivityEnabled: isActivityEnabled ?? this.isActivityEnabled, + order: order ?? this.order, + ); + RemoteAlbumEntityData copyWithCompanion(RemoteAlbumEntityCompanion data) { + return RemoteAlbumEntityData( + id: data.id.present ? data.id.value : this.id, + name: data.name.present ? data.name.value : this.name, + description: data.description.present + ? data.description.value + : this.description, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId, + thumbnailAssetId: data.thumbnailAssetId.present + ? data.thumbnailAssetId.value + : this.thumbnailAssetId, + isActivityEnabled: data.isActivityEnabled.present + ? data.isActivityEnabled.value + : this.isActivityEnabled, + order: data.order.present ? data.order.value : this.order, + ); + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumEntityData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('description: $description, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('thumbnailAssetId: $thumbnailAssetId, ') + ..write('isActivityEnabled: $isActivityEnabled, ') + ..write('order: $order') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + name, + description, + createdAt, + updatedAt, + ownerId, + thumbnailAssetId, + isActivityEnabled, + order, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RemoteAlbumEntityData && + other.id == this.id && + other.name == this.name && + other.description == this.description && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.ownerId == this.ownerId && + other.thumbnailAssetId == this.thumbnailAssetId && + other.isActivityEnabled == this.isActivityEnabled && + other.order == this.order); +} + +class RemoteAlbumEntityCompanion + extends UpdateCompanion { + final Value id; + final Value name; + final Value description; + final Value createdAt; + final Value updatedAt; + final Value ownerId; + final Value thumbnailAssetId; + final Value isActivityEnabled; + final Value order; + const RemoteAlbumEntityCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.description = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.ownerId = const Value.absent(), + this.thumbnailAssetId = const Value.absent(), + this.isActivityEnabled = const Value.absent(), + this.order = const Value.absent(), + }); + RemoteAlbumEntityCompanion.insert({ + required String id, + required String name, + this.description = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + required String ownerId, + this.thumbnailAssetId = const Value.absent(), + this.isActivityEnabled = const Value.absent(), + required int order, + }) : id = Value(id), + name = Value(name), + ownerId = Value(ownerId), + order = Value(order); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? description, + Expression? createdAt, + Expression? updatedAt, + Expression? ownerId, + Expression? thumbnailAssetId, + Expression? isActivityEnabled, + Expression? order, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (description != null) 'description': description, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (ownerId != null) 'owner_id': ownerId, + if (thumbnailAssetId != null) 'thumbnail_asset_id': thumbnailAssetId, + if (isActivityEnabled != null) 'is_activity_enabled': isActivityEnabled, + if (order != null) 'order': order, + }); + } + + RemoteAlbumEntityCompanion copyWith({ + Value? id, + Value? name, + Value? description, + Value? createdAt, + Value? updatedAt, + Value? ownerId, + Value? thumbnailAssetId, + Value? isActivityEnabled, + Value? order, + }) { + return RemoteAlbumEntityCompanion( + id: id ?? this.id, + name: name ?? this.name, + description: description ?? this.description, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + thumbnailAssetId: thumbnailAssetId ?? this.thumbnailAssetId, + isActivityEnabled: isActivityEnabled ?? this.isActivityEnabled, + order: order ?? this.order, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (description.present) { + map['description'] = Variable(description.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (ownerId.present) { + map['owner_id'] = Variable(ownerId.value); + } + if (thumbnailAssetId.present) { + map['thumbnail_asset_id'] = Variable(thumbnailAssetId.value); + } + if (isActivityEnabled.present) { + map['is_activity_enabled'] = Variable(isActivityEnabled.value); + } + if (order.present) { + map['order'] = Variable(order.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumEntityCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('description: $description, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('thumbnailAssetId: $thumbnailAssetId, ') + ..write('isActivityEnabled: $isActivityEnabled, ') + ..write('order: $order') + ..write(')')) + .toString(); + } +} + +class LocalAlbumEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + LocalAlbumEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn backupSelection = GeneratedColumn( + 'backup_selection', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn isIosSharedAlbum = GeneratedColumn( + 'is_ios_shared_album', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_ios_shared_album" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn linkedRemoteAlbumId = + GeneratedColumn( + 'linked_remote_album_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_album_entity (id) ON DELETE SET NULL', + ), + ); + late final GeneratedColumn marker_ = GeneratedColumn( + 'marker', + aliasedName, + true, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("marker" IN (0, 1))', + ), + ); + @override + List get $columns => [ + id, + name, + updatedAt, + backupSelection, + isIosSharedAlbum, + linkedRemoteAlbumId, + marker_, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'local_album_entity'; + @override + Set get $primaryKey => {id}; + @override + LocalAlbumEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return LocalAlbumEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + backupSelection: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}backup_selection'], + )!, + isIosSharedAlbum: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_ios_shared_album'], + )!, + linkedRemoteAlbumId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}linked_remote_album_id'], + ), + marker_: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}marker'], + ), + ); + } + + @override + LocalAlbumEntity createAlias(String alias) { + return LocalAlbumEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class LocalAlbumEntityData extends DataClass + implements Insertable { + final String id; + final String name; + final DateTime updatedAt; + final int backupSelection; + final bool isIosSharedAlbum; + final String? linkedRemoteAlbumId; + final bool? marker_; + const LocalAlbumEntityData({ + required this.id, + required this.name, + required this.updatedAt, + required this.backupSelection, + required this.isIosSharedAlbum, + this.linkedRemoteAlbumId, + this.marker_, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + map['updated_at'] = Variable(updatedAt); + map['backup_selection'] = Variable(backupSelection); + map['is_ios_shared_album'] = Variable(isIosSharedAlbum); + if (!nullToAbsent || linkedRemoteAlbumId != null) { + map['linked_remote_album_id'] = Variable(linkedRemoteAlbumId); + } + if (!nullToAbsent || marker_ != null) { + map['marker'] = Variable(marker_); + } + return map; + } + + factory LocalAlbumEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return LocalAlbumEntityData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + updatedAt: serializer.fromJson(json['updatedAt']), + backupSelection: serializer.fromJson(json['backupSelection']), + isIosSharedAlbum: serializer.fromJson(json['isIosSharedAlbum']), + linkedRemoteAlbumId: serializer.fromJson( + json['linkedRemoteAlbumId'], + ), + marker_: serializer.fromJson(json['marker_']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'updatedAt': serializer.toJson(updatedAt), + 'backupSelection': serializer.toJson(backupSelection), + 'isIosSharedAlbum': serializer.toJson(isIosSharedAlbum), + 'linkedRemoteAlbumId': serializer.toJson(linkedRemoteAlbumId), + 'marker_': serializer.toJson(marker_), + }; + } + + LocalAlbumEntityData copyWith({ + String? id, + String? name, + DateTime? updatedAt, + int? backupSelection, + bool? isIosSharedAlbum, + Value linkedRemoteAlbumId = const Value.absent(), + Value marker_ = const Value.absent(), + }) => LocalAlbumEntityData( + id: id ?? this.id, + name: name ?? this.name, + updatedAt: updatedAt ?? this.updatedAt, + backupSelection: backupSelection ?? this.backupSelection, + isIosSharedAlbum: isIosSharedAlbum ?? this.isIosSharedAlbum, + linkedRemoteAlbumId: linkedRemoteAlbumId.present + ? linkedRemoteAlbumId.value + : this.linkedRemoteAlbumId, + marker_: marker_.present ? marker_.value : this.marker_, + ); + LocalAlbumEntityData copyWithCompanion(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, + backupSelection: data.backupSelection.present + ? data.backupSelection.value + : this.backupSelection, + isIosSharedAlbum: data.isIosSharedAlbum.present + ? data.isIosSharedAlbum.value + : this.isIosSharedAlbum, + linkedRemoteAlbumId: data.linkedRemoteAlbumId.present + ? data.linkedRemoteAlbumId.value + : this.linkedRemoteAlbumId, + marker_: data.marker_.present ? data.marker_.value : this.marker_, + ); + } + + @override + String toString() { + return (StringBuffer('LocalAlbumEntityData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('updatedAt: $updatedAt, ') + ..write('backupSelection: $backupSelection, ') + ..write('isIosSharedAlbum: $isIosSharedAlbum, ') + ..write('linkedRemoteAlbumId: $linkedRemoteAlbumId, ') + ..write('marker_: $marker_') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + name, + updatedAt, + backupSelection, + isIosSharedAlbum, + linkedRemoteAlbumId, + marker_, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is LocalAlbumEntityData && + other.id == this.id && + other.name == this.name && + other.updatedAt == this.updatedAt && + other.backupSelection == this.backupSelection && + other.isIosSharedAlbum == this.isIosSharedAlbum && + other.linkedRemoteAlbumId == this.linkedRemoteAlbumId && + other.marker_ == this.marker_); +} + +class LocalAlbumEntityCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value updatedAt; + final Value backupSelection; + final Value isIosSharedAlbum; + final Value linkedRemoteAlbumId; + final Value marker_; + const LocalAlbumEntityCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.updatedAt = const Value.absent(), + this.backupSelection = const Value.absent(), + this.isIosSharedAlbum = const Value.absent(), + this.linkedRemoteAlbumId = const Value.absent(), + this.marker_ = const Value.absent(), + }); + LocalAlbumEntityCompanion.insert({ + required String id, + required String name, + this.updatedAt = const Value.absent(), + required int backupSelection, + this.isIosSharedAlbum = const Value.absent(), + this.linkedRemoteAlbumId = const Value.absent(), + this.marker_ = const Value.absent(), + }) : id = Value(id), + name = Value(name), + backupSelection = Value(backupSelection); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? updatedAt, + Expression? backupSelection, + Expression? isIosSharedAlbum, + Expression? linkedRemoteAlbumId, + Expression? marker_, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (updatedAt != null) 'updated_at': updatedAt, + if (backupSelection != null) 'backup_selection': backupSelection, + if (isIosSharedAlbum != null) 'is_ios_shared_album': isIosSharedAlbum, + if (linkedRemoteAlbumId != null) + 'linked_remote_album_id': linkedRemoteAlbumId, + if (marker_ != null) 'marker': marker_, + }); + } + + LocalAlbumEntityCompanion copyWith({ + Value? id, + Value? name, + Value? updatedAt, + Value? backupSelection, + Value? isIosSharedAlbum, + Value? linkedRemoteAlbumId, + Value? marker_, + }) { + return LocalAlbumEntityCompanion( + id: id ?? this.id, + name: name ?? this.name, + updatedAt: updatedAt ?? this.updatedAt, + backupSelection: backupSelection ?? this.backupSelection, + isIosSharedAlbum: isIosSharedAlbum ?? this.isIosSharedAlbum, + linkedRemoteAlbumId: linkedRemoteAlbumId ?? this.linkedRemoteAlbumId, + marker_: marker_ ?? this.marker_, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (backupSelection.present) { + map['backup_selection'] = Variable(backupSelection.value); + } + if (isIosSharedAlbum.present) { + map['is_ios_shared_album'] = Variable(isIosSharedAlbum.value); + } + if (linkedRemoteAlbumId.present) { + map['linked_remote_album_id'] = Variable( + linkedRemoteAlbumId.value, + ); + } + if (marker_.present) { + map['marker'] = Variable(marker_.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('LocalAlbumEntityCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('updatedAt: $updatedAt, ') + ..write('backupSelection: $backupSelection, ') + ..write('isIosSharedAlbum: $isIosSharedAlbum, ') + ..write('linkedRemoteAlbumId: $linkedRemoteAlbumId, ') + ..write('marker_: $marker_') + ..write(')')) + .toString(); + } +} + +class LocalAlbumAssetEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + LocalAlbumAssetEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn assetId = GeneratedColumn( + 'asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES local_asset_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn albumId = GeneratedColumn( + 'album_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES local_album_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn marker_ = GeneratedColumn( + 'marker', + aliasedName, + true, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("marker" IN (0, 1))', + ), + ); + @override + List get $columns => [assetId, albumId, marker_]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'local_album_asset_entity'; + @override + Set get $primaryKey => {assetId, albumId}; + @override + LocalAlbumAssetEntityData map( + Map data, { + String? tablePrefix, + }) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return LocalAlbumAssetEntityData( + assetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}asset_id'], + )!, + albumId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}album_id'], + )!, + marker_: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}marker'], + ), + ); + } + + @override + LocalAlbumAssetEntity createAlias(String alias) { + return LocalAlbumAssetEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class LocalAlbumAssetEntityData extends DataClass + implements Insertable { + final String assetId; + final String albumId; + final bool? marker_; + const LocalAlbumAssetEntityData({ + required this.assetId, + required this.albumId, + this.marker_, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['asset_id'] = Variable(assetId); + map['album_id'] = Variable(albumId); + if (!nullToAbsent || marker_ != null) { + map['marker'] = Variable(marker_); + } + return map; + } + + factory LocalAlbumAssetEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return LocalAlbumAssetEntityData( + assetId: serializer.fromJson(json['assetId']), + albumId: serializer.fromJson(json['albumId']), + marker_: serializer.fromJson(json['marker_']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'assetId': serializer.toJson(assetId), + 'albumId': serializer.toJson(albumId), + 'marker_': serializer.toJson(marker_), + }; + } + + LocalAlbumAssetEntityData copyWith({ + String? assetId, + String? albumId, + Value marker_ = const Value.absent(), + }) => LocalAlbumAssetEntityData( + assetId: assetId ?? this.assetId, + albumId: albumId ?? this.albumId, + marker_: marker_.present ? marker_.value : this.marker_, + ); + LocalAlbumAssetEntityData copyWithCompanion( + LocalAlbumAssetEntityCompanion data, + ) { + return LocalAlbumAssetEntityData( + assetId: data.assetId.present ? data.assetId.value : this.assetId, + albumId: data.albumId.present ? data.albumId.value : this.albumId, + marker_: data.marker_.present ? data.marker_.value : this.marker_, + ); + } + + @override + String toString() { + return (StringBuffer('LocalAlbumAssetEntityData(') + ..write('assetId: $assetId, ') + ..write('albumId: $albumId, ') + ..write('marker_: $marker_') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(assetId, albumId, marker_); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is LocalAlbumAssetEntityData && + other.assetId == this.assetId && + other.albumId == this.albumId && + other.marker_ == this.marker_); +} + +class LocalAlbumAssetEntityCompanion + extends UpdateCompanion { + final Value assetId; + final Value albumId; + final Value marker_; + const LocalAlbumAssetEntityCompanion({ + this.assetId = const Value.absent(), + this.albumId = const Value.absent(), + this.marker_ = const Value.absent(), + }); + LocalAlbumAssetEntityCompanion.insert({ + required String assetId, + required String albumId, + this.marker_ = const Value.absent(), + }) : assetId = Value(assetId), + albumId = Value(albumId); + static Insertable custom({ + Expression? assetId, + Expression? albumId, + Expression? marker_, + }) { + return RawValuesInsertable({ + if (assetId != null) 'asset_id': assetId, + if (albumId != null) 'album_id': albumId, + if (marker_ != null) 'marker': marker_, + }); + } + + LocalAlbumAssetEntityCompanion copyWith({ + Value? assetId, + Value? albumId, + Value? marker_, + }) { + return LocalAlbumAssetEntityCompanion( + assetId: assetId ?? this.assetId, + albumId: albumId ?? this.albumId, + marker_: marker_ ?? this.marker_, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (assetId.present) { + map['asset_id'] = Variable(assetId.value); + } + if (albumId.present) { + map['album_id'] = Variable(albumId.value); + } + if (marker_.present) { + map['marker'] = Variable(marker_.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('LocalAlbumAssetEntityCompanion(') + ..write('assetId: $assetId, ') + ..write('albumId: $albumId, ') + ..write('marker_: $marker_') + ..write(')')) + .toString(); + } +} + +class AuthUserEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + AuthUserEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn email = GeneratedColumn( + 'email', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn isAdmin = GeneratedColumn( + 'is_admin', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_admin" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn hasProfileImage = GeneratedColumn( + 'has_profile_image', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("has_profile_image" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn profileChangedAt = + GeneratedColumn( + 'profile_changed_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn avatarColor = GeneratedColumn( + 'avatar_color', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn quotaSizeInBytes = GeneratedColumn( + 'quota_size_in_bytes', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn quotaUsageInBytes = GeneratedColumn( + 'quota_usage_in_bytes', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn pinCode = GeneratedColumn( + 'pin_code', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + @override + List get $columns => [ + id, + name, + email, + isAdmin, + hasProfileImage, + profileChangedAt, + avatarColor, + quotaSizeInBytes, + quotaUsageInBytes, + pinCode, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'auth_user_entity'; + @override + Set get $primaryKey => {id}; + @override + AuthUserEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return AuthUserEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + email: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}email'], + )!, + isAdmin: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_admin'], + )!, + hasProfileImage: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}has_profile_image'], + )!, + profileChangedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}profile_changed_at'], + )!, + avatarColor: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}avatar_color'], + )!, + quotaSizeInBytes: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}quota_size_in_bytes'], + )!, + quotaUsageInBytes: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}quota_usage_in_bytes'], + )!, + pinCode: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}pin_code'], + ), + ); + } + + @override + AuthUserEntity createAlias(String alias) { + return AuthUserEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class AuthUserEntityData extends DataClass + implements Insertable { + final String id; + final String name; + final String email; + final bool isAdmin; + final bool hasProfileImage; + final DateTime profileChangedAt; + final int avatarColor; + final int quotaSizeInBytes; + final int quotaUsageInBytes; + final String? pinCode; + const AuthUserEntityData({ + required this.id, + required this.name, + required this.email, + required this.isAdmin, + required this.hasProfileImage, + required this.profileChangedAt, + required this.avatarColor, + required this.quotaSizeInBytes, + required this.quotaUsageInBytes, + this.pinCode, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + map['email'] = Variable(email); + map['is_admin'] = Variable(isAdmin); + map['has_profile_image'] = Variable(hasProfileImage); + map['profile_changed_at'] = Variable(profileChangedAt); + map['avatar_color'] = Variable(avatarColor); + map['quota_size_in_bytes'] = Variable(quotaSizeInBytes); + map['quota_usage_in_bytes'] = Variable(quotaUsageInBytes); + if (!nullToAbsent || pinCode != null) { + map['pin_code'] = Variable(pinCode); + } + return map; + } + + factory AuthUserEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return AuthUserEntityData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + email: serializer.fromJson(json['email']), + isAdmin: serializer.fromJson(json['isAdmin']), + hasProfileImage: serializer.fromJson(json['hasProfileImage']), + profileChangedAt: serializer.fromJson(json['profileChangedAt']), + avatarColor: serializer.fromJson(json['avatarColor']), + quotaSizeInBytes: serializer.fromJson(json['quotaSizeInBytes']), + quotaUsageInBytes: serializer.fromJson(json['quotaUsageInBytes']), + pinCode: serializer.fromJson(json['pinCode']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'email': serializer.toJson(email), + 'isAdmin': serializer.toJson(isAdmin), + 'hasProfileImage': serializer.toJson(hasProfileImage), + 'profileChangedAt': serializer.toJson(profileChangedAt), + 'avatarColor': serializer.toJson(avatarColor), + 'quotaSizeInBytes': serializer.toJson(quotaSizeInBytes), + 'quotaUsageInBytes': serializer.toJson(quotaUsageInBytes), + 'pinCode': serializer.toJson(pinCode), + }; + } + + AuthUserEntityData copyWith({ + String? id, + String? name, + String? email, + bool? isAdmin, + bool? hasProfileImage, + DateTime? profileChangedAt, + int? avatarColor, + int? quotaSizeInBytes, + int? quotaUsageInBytes, + Value pinCode = const Value.absent(), + }) => AuthUserEntityData( + id: id ?? this.id, + name: name ?? this.name, + email: email ?? this.email, + isAdmin: isAdmin ?? this.isAdmin, + hasProfileImage: hasProfileImage ?? this.hasProfileImage, + profileChangedAt: profileChangedAt ?? this.profileChangedAt, + avatarColor: avatarColor ?? this.avatarColor, + quotaSizeInBytes: quotaSizeInBytes ?? this.quotaSizeInBytes, + quotaUsageInBytes: quotaUsageInBytes ?? this.quotaUsageInBytes, + pinCode: pinCode.present ? pinCode.value : this.pinCode, + ); + AuthUserEntityData copyWithCompanion(AuthUserEntityCompanion data) { + return AuthUserEntityData( + id: data.id.present ? data.id.value : this.id, + name: data.name.present ? data.name.value : this.name, + email: data.email.present ? data.email.value : this.email, + isAdmin: data.isAdmin.present ? data.isAdmin.value : this.isAdmin, + hasProfileImage: data.hasProfileImage.present + ? data.hasProfileImage.value + : this.hasProfileImage, + profileChangedAt: data.profileChangedAt.present + ? data.profileChangedAt.value + : this.profileChangedAt, + avatarColor: data.avatarColor.present + ? data.avatarColor.value + : this.avatarColor, + quotaSizeInBytes: data.quotaSizeInBytes.present + ? data.quotaSizeInBytes.value + : this.quotaSizeInBytes, + quotaUsageInBytes: data.quotaUsageInBytes.present + ? data.quotaUsageInBytes.value + : this.quotaUsageInBytes, + pinCode: data.pinCode.present ? data.pinCode.value : this.pinCode, + ); + } + + @override + String toString() { + return (StringBuffer('AuthUserEntityData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('email: $email, ') + ..write('isAdmin: $isAdmin, ') + ..write('hasProfileImage: $hasProfileImage, ') + ..write('profileChangedAt: $profileChangedAt, ') + ..write('avatarColor: $avatarColor, ') + ..write('quotaSizeInBytes: $quotaSizeInBytes, ') + ..write('quotaUsageInBytes: $quotaUsageInBytes, ') + ..write('pinCode: $pinCode') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + name, + email, + isAdmin, + hasProfileImage, + profileChangedAt, + avatarColor, + quotaSizeInBytes, + quotaUsageInBytes, + pinCode, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is AuthUserEntityData && + other.id == this.id && + other.name == this.name && + other.email == this.email && + other.isAdmin == this.isAdmin && + other.hasProfileImage == this.hasProfileImage && + other.profileChangedAt == this.profileChangedAt && + other.avatarColor == this.avatarColor && + other.quotaSizeInBytes == this.quotaSizeInBytes && + other.quotaUsageInBytes == this.quotaUsageInBytes && + other.pinCode == this.pinCode); +} + +class AuthUserEntityCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value email; + final Value isAdmin; + final Value hasProfileImage; + final Value profileChangedAt; + final Value avatarColor; + final Value quotaSizeInBytes; + final Value quotaUsageInBytes; + final Value pinCode; + const AuthUserEntityCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.email = const Value.absent(), + this.isAdmin = const Value.absent(), + this.hasProfileImage = const Value.absent(), + this.profileChangedAt = const Value.absent(), + this.avatarColor = const Value.absent(), + this.quotaSizeInBytes = const Value.absent(), + this.quotaUsageInBytes = const Value.absent(), + this.pinCode = const Value.absent(), + }); + AuthUserEntityCompanion.insert({ + required String id, + required String name, + required String email, + this.isAdmin = const Value.absent(), + this.hasProfileImage = const Value.absent(), + this.profileChangedAt = const Value.absent(), + required int avatarColor, + this.quotaSizeInBytes = const Value.absent(), + this.quotaUsageInBytes = const Value.absent(), + this.pinCode = const Value.absent(), + }) : id = Value(id), + name = Value(name), + email = Value(email), + avatarColor = Value(avatarColor); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? email, + Expression? isAdmin, + Expression? hasProfileImage, + Expression? profileChangedAt, + Expression? avatarColor, + Expression? quotaSizeInBytes, + Expression? quotaUsageInBytes, + Expression? pinCode, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (email != null) 'email': email, + if (isAdmin != null) 'is_admin': isAdmin, + if (hasProfileImage != null) 'has_profile_image': hasProfileImage, + if (profileChangedAt != null) 'profile_changed_at': profileChangedAt, + if (avatarColor != null) 'avatar_color': avatarColor, + if (quotaSizeInBytes != null) 'quota_size_in_bytes': quotaSizeInBytes, + if (quotaUsageInBytes != null) 'quota_usage_in_bytes': quotaUsageInBytes, + if (pinCode != null) 'pin_code': pinCode, + }); + } + + AuthUserEntityCompanion copyWith({ + Value? id, + Value? name, + Value? email, + Value? isAdmin, + Value? hasProfileImage, + Value? profileChangedAt, + Value? avatarColor, + Value? quotaSizeInBytes, + Value? quotaUsageInBytes, + Value? pinCode, + }) { + return AuthUserEntityCompanion( + id: id ?? this.id, + name: name ?? this.name, + email: email ?? this.email, + isAdmin: isAdmin ?? this.isAdmin, + hasProfileImage: hasProfileImage ?? this.hasProfileImage, + profileChangedAt: profileChangedAt ?? this.profileChangedAt, + avatarColor: avatarColor ?? this.avatarColor, + quotaSizeInBytes: quotaSizeInBytes ?? this.quotaSizeInBytes, + quotaUsageInBytes: quotaUsageInBytes ?? this.quotaUsageInBytes, + pinCode: pinCode ?? this.pinCode, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (email.present) { + map['email'] = Variable(email.value); + } + if (isAdmin.present) { + map['is_admin'] = Variable(isAdmin.value); + } + if (hasProfileImage.present) { + map['has_profile_image'] = Variable(hasProfileImage.value); + } + if (profileChangedAt.present) { + map['profile_changed_at'] = Variable(profileChangedAt.value); + } + if (avatarColor.present) { + map['avatar_color'] = Variable(avatarColor.value); + } + if (quotaSizeInBytes.present) { + map['quota_size_in_bytes'] = Variable(quotaSizeInBytes.value); + } + if (quotaUsageInBytes.present) { + map['quota_usage_in_bytes'] = Variable(quotaUsageInBytes.value); + } + if (pinCode.present) { + map['pin_code'] = Variable(pinCode.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('AuthUserEntityCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('email: $email, ') + ..write('isAdmin: $isAdmin, ') + ..write('hasProfileImage: $hasProfileImage, ') + ..write('profileChangedAt: $profileChangedAt, ') + ..write('avatarColor: $avatarColor, ') + ..write('quotaSizeInBytes: $quotaSizeInBytes, ') + ..write('quotaUsageInBytes: $quotaUsageInBytes, ') + ..write('pinCode: $pinCode') + ..write(')')) + .toString(); + } +} + +class UserMetadataEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + UserMetadataEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn key = GeneratedColumn( + 'key', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn value = GeneratedColumn( + 'value', + aliasedName, + false, + type: DriftSqlType.blob, + requiredDuringInsert: true, + ); + @override + List get $columns => [userId, key, value]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'user_metadata_entity'; + @override + Set get $primaryKey => {userId, key}; + @override + UserMetadataEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return UserMetadataEntityData( + userId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}user_id'], + )!, + key: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}key'], + )!, + value: attachedDatabase.typeMapping.read( + DriftSqlType.blob, + data['${effectivePrefix}value'], + )!, + ); + } + + @override + UserMetadataEntity createAlias(String alias) { + return UserMetadataEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class UserMetadataEntityData extends DataClass + implements Insertable { + final String userId; + final int key; + final Uint8List value; + const UserMetadataEntityData({ + required this.userId, + required this.key, + required this.value, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['user_id'] = Variable(userId); + map['key'] = Variable(key); + map['value'] = Variable(value); + return map; + } + + factory UserMetadataEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return UserMetadataEntityData( + userId: serializer.fromJson(json['userId']), + key: serializer.fromJson(json['key']), + value: serializer.fromJson(json['value']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'userId': serializer.toJson(userId), + 'key': serializer.toJson(key), + 'value': serializer.toJson(value), + }; + } + + UserMetadataEntityData copyWith({ + String? userId, + int? key, + Uint8List? value, + }) => UserMetadataEntityData( + userId: userId ?? this.userId, + key: key ?? this.key, + value: value ?? this.value, + ); + UserMetadataEntityData copyWithCompanion(UserMetadataEntityCompanion data) { + return UserMetadataEntityData( + userId: data.userId.present ? data.userId.value : this.userId, + key: data.key.present ? data.key.value : this.key, + value: data.value.present ? data.value.value : this.value, + ); + } + + @override + String toString() { + return (StringBuffer('UserMetadataEntityData(') + ..write('userId: $userId, ') + ..write('key: $key, ') + ..write('value: $value') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(userId, key, $driftBlobEquality.hash(value)); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is UserMetadataEntityData && + other.userId == this.userId && + other.key == this.key && + $driftBlobEquality.equals(other.value, this.value)); +} + +class UserMetadataEntityCompanion + extends UpdateCompanion { + final Value userId; + final Value key; + final Value value; + const UserMetadataEntityCompanion({ + this.userId = const Value.absent(), + this.key = const Value.absent(), + this.value = const Value.absent(), + }); + UserMetadataEntityCompanion.insert({ + required String userId, + required int key, + required Uint8List value, + }) : userId = Value(userId), + key = Value(key), + value = Value(value); + static Insertable custom({ + Expression? userId, + Expression? key, + Expression? value, + }) { + return RawValuesInsertable({ + if (userId != null) 'user_id': userId, + if (key != null) 'key': key, + if (value != null) 'value': value, + }); + } + + UserMetadataEntityCompanion copyWith({ + Value? userId, + Value? key, + Value? value, + }) { + return UserMetadataEntityCompanion( + userId: userId ?? this.userId, + key: key ?? this.key, + value: value ?? this.value, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (key.present) { + map['key'] = Variable(key.value); + } + if (value.present) { + map['value'] = Variable(value.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('UserMetadataEntityCompanion(') + ..write('userId: $userId, ') + ..write('key: $key, ') + ..write('value: $value') + ..write(')')) + .toString(); + } +} + +class PartnerEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + PartnerEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn sharedById = GeneratedColumn( + 'shared_by_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn sharedWithId = GeneratedColumn( + 'shared_with_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn inTimeline = GeneratedColumn( + 'in_timeline', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("in_timeline" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + @override + List get $columns => [sharedById, sharedWithId, inTimeline]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'partner_entity'; + @override + Set get $primaryKey => {sharedById, sharedWithId}; + @override + PartnerEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return PartnerEntityData( + sharedById: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}shared_by_id'], + )!, + sharedWithId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}shared_with_id'], + )!, + inTimeline: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}in_timeline'], + )!, + ); + } + + @override + PartnerEntity createAlias(String alias) { + return PartnerEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class PartnerEntityData extends DataClass + implements Insertable { + final String sharedById; + final String sharedWithId; + final bool inTimeline; + const PartnerEntityData({ + required this.sharedById, + required this.sharedWithId, + required this.inTimeline, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['shared_by_id'] = Variable(sharedById); + map['shared_with_id'] = Variable(sharedWithId); + map['in_timeline'] = Variable(inTimeline); + return map; + } + + factory PartnerEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return PartnerEntityData( + sharedById: serializer.fromJson(json['sharedById']), + sharedWithId: serializer.fromJson(json['sharedWithId']), + inTimeline: serializer.fromJson(json['inTimeline']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'sharedById': serializer.toJson(sharedById), + 'sharedWithId': serializer.toJson(sharedWithId), + 'inTimeline': serializer.toJson(inTimeline), + }; + } + + PartnerEntityData copyWith({ + String? sharedById, + String? sharedWithId, + bool? inTimeline, + }) => PartnerEntityData( + sharedById: sharedById ?? this.sharedById, + sharedWithId: sharedWithId ?? this.sharedWithId, + inTimeline: inTimeline ?? this.inTimeline, + ); + PartnerEntityData copyWithCompanion(PartnerEntityCompanion data) { + return PartnerEntityData( + sharedById: data.sharedById.present + ? data.sharedById.value + : this.sharedById, + sharedWithId: data.sharedWithId.present + ? data.sharedWithId.value + : this.sharedWithId, + inTimeline: data.inTimeline.present + ? data.inTimeline.value + : this.inTimeline, + ); + } + + @override + String toString() { + return (StringBuffer('PartnerEntityData(') + ..write('sharedById: $sharedById, ') + ..write('sharedWithId: $sharedWithId, ') + ..write('inTimeline: $inTimeline') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(sharedById, sharedWithId, inTimeline); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is PartnerEntityData && + other.sharedById == this.sharedById && + other.sharedWithId == this.sharedWithId && + other.inTimeline == this.inTimeline); +} + +class PartnerEntityCompanion extends UpdateCompanion { + final Value sharedById; + final Value sharedWithId; + final Value inTimeline; + const PartnerEntityCompanion({ + this.sharedById = const Value.absent(), + this.sharedWithId = const Value.absent(), + this.inTimeline = const Value.absent(), + }); + PartnerEntityCompanion.insert({ + required String sharedById, + required String sharedWithId, + this.inTimeline = const Value.absent(), + }) : sharedById = Value(sharedById), + sharedWithId = Value(sharedWithId); + static Insertable custom({ + Expression? sharedById, + Expression? sharedWithId, + Expression? inTimeline, + }) { + return RawValuesInsertable({ + if (sharedById != null) 'shared_by_id': sharedById, + if (sharedWithId != null) 'shared_with_id': sharedWithId, + if (inTimeline != null) 'in_timeline': inTimeline, + }); + } + + PartnerEntityCompanion copyWith({ + Value? sharedById, + Value? sharedWithId, + Value? inTimeline, + }) { + return PartnerEntityCompanion( + sharedById: sharedById ?? this.sharedById, + sharedWithId: sharedWithId ?? this.sharedWithId, + inTimeline: inTimeline ?? this.inTimeline, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (sharedById.present) { + map['shared_by_id'] = Variable(sharedById.value); + } + if (sharedWithId.present) { + map['shared_with_id'] = Variable(sharedWithId.value); + } + if (inTimeline.present) { + map['in_timeline'] = Variable(inTimeline.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('PartnerEntityCompanion(') + ..write('sharedById: $sharedById, ') + ..write('sharedWithId: $sharedWithId, ') + ..write('inTimeline: $inTimeline') + ..write(')')) + .toString(); + } +} + +class RemoteExifEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RemoteExifEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn assetId = GeneratedColumn( + 'asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_asset_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn city = GeneratedColumn( + 'city', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn state = GeneratedColumn( + 'state', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn country = GeneratedColumn( + 'country', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn dateTimeOriginal = + GeneratedColumn( + 'date_time_original', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn description = GeneratedColumn( + 'description', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn height = GeneratedColumn( + 'height', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn width = GeneratedColumn( + 'width', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn exposureTime = GeneratedColumn( + 'exposure_time', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn fNumber = GeneratedColumn( + 'f_number', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + ); + late final GeneratedColumn fileSize = GeneratedColumn( + 'file_size', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn focalLength = GeneratedColumn( + 'focal_length', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + ); + late final GeneratedColumn latitude = GeneratedColumn( + 'latitude', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + ); + late final GeneratedColumn longitude = GeneratedColumn( + 'longitude', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + ); + late final GeneratedColumn iso = GeneratedColumn( + 'iso', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn make = GeneratedColumn( + 'make', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn model = GeneratedColumn( + 'model', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn lens = GeneratedColumn( + 'lens', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn orientation = GeneratedColumn( + 'orientation', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn timeZone = GeneratedColumn( + 'time_zone', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn rating = GeneratedColumn( + 'rating', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn projectionType = GeneratedColumn( + 'projection_type', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + @override + List get $columns => [ + assetId, + city, + state, + country, + dateTimeOriginal, + description, + height, + width, + exposureTime, + fNumber, + fileSize, + focalLength, + latitude, + longitude, + iso, + make, + model, + lens, + orientation, + timeZone, + rating, + projectionType, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'remote_exif_entity'; + @override + Set get $primaryKey => {assetId}; + @override + RemoteExifEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RemoteExifEntityData( + assetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}asset_id'], + )!, + city: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}city'], + ), + state: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}state'], + ), + country: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}country'], + ), + dateTimeOriginal: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}date_time_original'], + ), + description: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}description'], + ), + height: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}height'], + ), + width: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}width'], + ), + exposureTime: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}exposure_time'], + ), + fNumber: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}f_number'], + ), + fileSize: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}file_size'], + ), + focalLength: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}focal_length'], + ), + latitude: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}latitude'], + ), + longitude: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}longitude'], + ), + iso: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}iso'], + ), + make: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}make'], + ), + model: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}model'], + ), + lens: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}lens'], + ), + orientation: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}orientation'], + ), + timeZone: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}time_zone'], + ), + rating: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}rating'], + ), + projectionType: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}projection_type'], + ), + ); + } + + @override + RemoteExifEntity createAlias(String alias) { + return RemoteExifEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class RemoteExifEntityData extends DataClass + implements Insertable { + final String assetId; + final String? city; + final String? state; + final String? country; + final DateTime? dateTimeOriginal; + final String? description; + final int? height; + final int? width; + final String? exposureTime; + final double? fNumber; + final int? fileSize; + final double? focalLength; + final double? latitude; + final double? longitude; + final int? iso; + final String? make; + final String? model; + final String? lens; + final String? orientation; + final String? timeZone; + final int? rating; + final String? projectionType; + const RemoteExifEntityData({ + required this.assetId, + this.city, + this.state, + this.country, + this.dateTimeOriginal, + this.description, + this.height, + this.width, + this.exposureTime, + this.fNumber, + this.fileSize, + this.focalLength, + this.latitude, + this.longitude, + this.iso, + this.make, + this.model, + this.lens, + this.orientation, + this.timeZone, + this.rating, + this.projectionType, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['asset_id'] = Variable(assetId); + if (!nullToAbsent || city != null) { + map['city'] = Variable(city); + } + if (!nullToAbsent || state != null) { + map['state'] = Variable(state); + } + if (!nullToAbsent || country != null) { + map['country'] = Variable(country); + } + if (!nullToAbsent || dateTimeOriginal != null) { + map['date_time_original'] = Variable(dateTimeOriginal); + } + if (!nullToAbsent || description != null) { + map['description'] = Variable(description); + } + if (!nullToAbsent || height != null) { + map['height'] = Variable(height); + } + if (!nullToAbsent || width != null) { + map['width'] = Variable(width); + } + if (!nullToAbsent || exposureTime != null) { + map['exposure_time'] = Variable(exposureTime); + } + if (!nullToAbsent || fNumber != null) { + map['f_number'] = Variable(fNumber); + } + if (!nullToAbsent || fileSize != null) { + map['file_size'] = Variable(fileSize); + } + if (!nullToAbsent || focalLength != null) { + map['focal_length'] = Variable(focalLength); + } + if (!nullToAbsent || latitude != null) { + map['latitude'] = Variable(latitude); + } + if (!nullToAbsent || longitude != null) { + map['longitude'] = Variable(longitude); + } + if (!nullToAbsent || iso != null) { + map['iso'] = Variable(iso); + } + if (!nullToAbsent || make != null) { + map['make'] = Variable(make); + } + if (!nullToAbsent || model != null) { + map['model'] = Variable(model); + } + if (!nullToAbsent || lens != null) { + map['lens'] = Variable(lens); + } + if (!nullToAbsent || orientation != null) { + map['orientation'] = Variable(orientation); + } + if (!nullToAbsent || timeZone != null) { + map['time_zone'] = Variable(timeZone); + } + if (!nullToAbsent || rating != null) { + map['rating'] = Variable(rating); + } + if (!nullToAbsent || projectionType != null) { + map['projection_type'] = Variable(projectionType); + } + return map; + } + + factory RemoteExifEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RemoteExifEntityData( + assetId: serializer.fromJson(json['assetId']), + city: serializer.fromJson(json['city']), + state: serializer.fromJson(json['state']), + country: serializer.fromJson(json['country']), + dateTimeOriginal: serializer.fromJson( + json['dateTimeOriginal'], + ), + description: serializer.fromJson(json['description']), + height: serializer.fromJson(json['height']), + width: serializer.fromJson(json['width']), + exposureTime: serializer.fromJson(json['exposureTime']), + fNumber: serializer.fromJson(json['fNumber']), + fileSize: serializer.fromJson(json['fileSize']), + focalLength: serializer.fromJson(json['focalLength']), + latitude: serializer.fromJson(json['latitude']), + longitude: serializer.fromJson(json['longitude']), + iso: serializer.fromJson(json['iso']), + make: serializer.fromJson(json['make']), + model: serializer.fromJson(json['model']), + lens: serializer.fromJson(json['lens']), + orientation: serializer.fromJson(json['orientation']), + timeZone: serializer.fromJson(json['timeZone']), + rating: serializer.fromJson(json['rating']), + projectionType: serializer.fromJson(json['projectionType']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'assetId': serializer.toJson(assetId), + 'city': serializer.toJson(city), + 'state': serializer.toJson(state), + 'country': serializer.toJson(country), + 'dateTimeOriginal': serializer.toJson(dateTimeOriginal), + 'description': serializer.toJson(description), + 'height': serializer.toJson(height), + 'width': serializer.toJson(width), + 'exposureTime': serializer.toJson(exposureTime), + 'fNumber': serializer.toJson(fNumber), + 'fileSize': serializer.toJson(fileSize), + 'focalLength': serializer.toJson(focalLength), + 'latitude': serializer.toJson(latitude), + 'longitude': serializer.toJson(longitude), + 'iso': serializer.toJson(iso), + 'make': serializer.toJson(make), + 'model': serializer.toJson(model), + 'lens': serializer.toJson(lens), + 'orientation': serializer.toJson(orientation), + 'timeZone': serializer.toJson(timeZone), + 'rating': serializer.toJson(rating), + 'projectionType': serializer.toJson(projectionType), + }; + } + + RemoteExifEntityData copyWith({ + String? assetId, + Value city = const Value.absent(), + Value state = const Value.absent(), + Value country = const Value.absent(), + Value dateTimeOriginal = const Value.absent(), + Value description = const Value.absent(), + Value height = const Value.absent(), + Value width = const Value.absent(), + Value exposureTime = const Value.absent(), + Value fNumber = const Value.absent(), + Value fileSize = const Value.absent(), + Value focalLength = const Value.absent(), + Value latitude = const Value.absent(), + Value longitude = const Value.absent(), + Value iso = const Value.absent(), + Value make = const Value.absent(), + Value model = const Value.absent(), + Value lens = const Value.absent(), + Value orientation = const Value.absent(), + Value timeZone = const Value.absent(), + Value rating = const Value.absent(), + Value projectionType = const Value.absent(), + }) => RemoteExifEntityData( + assetId: assetId ?? this.assetId, + city: city.present ? city.value : this.city, + state: state.present ? state.value : this.state, + country: country.present ? country.value : this.country, + dateTimeOriginal: dateTimeOriginal.present + ? dateTimeOriginal.value + : this.dateTimeOriginal, + description: description.present ? description.value : this.description, + height: height.present ? height.value : this.height, + width: width.present ? width.value : this.width, + exposureTime: exposureTime.present ? exposureTime.value : this.exposureTime, + fNumber: fNumber.present ? fNumber.value : this.fNumber, + fileSize: fileSize.present ? fileSize.value : this.fileSize, + focalLength: focalLength.present ? focalLength.value : this.focalLength, + latitude: latitude.present ? latitude.value : this.latitude, + longitude: longitude.present ? longitude.value : this.longitude, + iso: iso.present ? iso.value : this.iso, + make: make.present ? make.value : this.make, + model: model.present ? model.value : this.model, + lens: lens.present ? lens.value : this.lens, + orientation: orientation.present ? orientation.value : this.orientation, + timeZone: timeZone.present ? timeZone.value : this.timeZone, + rating: rating.present ? rating.value : this.rating, + projectionType: projectionType.present + ? projectionType.value + : this.projectionType, + ); + RemoteExifEntityData copyWithCompanion(RemoteExifEntityCompanion data) { + return RemoteExifEntityData( + assetId: data.assetId.present ? data.assetId.value : this.assetId, + city: data.city.present ? data.city.value : this.city, + state: data.state.present ? data.state.value : this.state, + country: data.country.present ? data.country.value : this.country, + dateTimeOriginal: data.dateTimeOriginal.present + ? data.dateTimeOriginal.value + : this.dateTimeOriginal, + description: data.description.present + ? data.description.value + : this.description, + height: data.height.present ? data.height.value : this.height, + width: data.width.present ? data.width.value : this.width, + exposureTime: data.exposureTime.present + ? data.exposureTime.value + : this.exposureTime, + fNumber: data.fNumber.present ? data.fNumber.value : this.fNumber, + fileSize: data.fileSize.present ? data.fileSize.value : this.fileSize, + focalLength: data.focalLength.present + ? data.focalLength.value + : this.focalLength, + latitude: data.latitude.present ? data.latitude.value : this.latitude, + longitude: data.longitude.present ? data.longitude.value : this.longitude, + iso: data.iso.present ? data.iso.value : this.iso, + make: data.make.present ? data.make.value : this.make, + model: data.model.present ? data.model.value : this.model, + lens: data.lens.present ? data.lens.value : this.lens, + orientation: data.orientation.present + ? data.orientation.value + : this.orientation, + timeZone: data.timeZone.present ? data.timeZone.value : this.timeZone, + rating: data.rating.present ? data.rating.value : this.rating, + projectionType: data.projectionType.present + ? data.projectionType.value + : this.projectionType, + ); + } + + @override + String toString() { + return (StringBuffer('RemoteExifEntityData(') + ..write('assetId: $assetId, ') + ..write('city: $city, ') + ..write('state: $state, ') + ..write('country: $country, ') + ..write('dateTimeOriginal: $dateTimeOriginal, ') + ..write('description: $description, ') + ..write('height: $height, ') + ..write('width: $width, ') + ..write('exposureTime: $exposureTime, ') + ..write('fNumber: $fNumber, ') + ..write('fileSize: $fileSize, ') + ..write('focalLength: $focalLength, ') + ..write('latitude: $latitude, ') + ..write('longitude: $longitude, ') + ..write('iso: $iso, ') + ..write('make: $make, ') + ..write('model: $model, ') + ..write('lens: $lens, ') + ..write('orientation: $orientation, ') + ..write('timeZone: $timeZone, ') + ..write('rating: $rating, ') + ..write('projectionType: $projectionType') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hashAll([ + assetId, + city, + state, + country, + dateTimeOriginal, + description, + height, + width, + exposureTime, + fNumber, + fileSize, + focalLength, + latitude, + longitude, + iso, + make, + model, + lens, + orientation, + timeZone, + rating, + projectionType, + ]); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RemoteExifEntityData && + other.assetId == this.assetId && + other.city == this.city && + other.state == this.state && + other.country == this.country && + other.dateTimeOriginal == this.dateTimeOriginal && + other.description == this.description && + other.height == this.height && + other.width == this.width && + other.exposureTime == this.exposureTime && + other.fNumber == this.fNumber && + other.fileSize == this.fileSize && + other.focalLength == this.focalLength && + other.latitude == this.latitude && + other.longitude == this.longitude && + other.iso == this.iso && + other.make == this.make && + other.model == this.model && + other.lens == this.lens && + other.orientation == this.orientation && + other.timeZone == this.timeZone && + other.rating == this.rating && + other.projectionType == this.projectionType); +} + +class RemoteExifEntityCompanion extends UpdateCompanion { + final Value assetId; + final Value city; + final Value state; + final Value country; + final Value dateTimeOriginal; + final Value description; + final Value height; + final Value width; + final Value exposureTime; + final Value fNumber; + final Value fileSize; + final Value focalLength; + final Value latitude; + final Value longitude; + final Value iso; + final Value make; + final Value model; + final Value lens; + final Value orientation; + final Value timeZone; + final Value rating; + final Value projectionType; + const RemoteExifEntityCompanion({ + this.assetId = const Value.absent(), + this.city = const Value.absent(), + this.state = const Value.absent(), + this.country = const Value.absent(), + this.dateTimeOriginal = const Value.absent(), + this.description = const Value.absent(), + this.height = const Value.absent(), + this.width = const Value.absent(), + this.exposureTime = const Value.absent(), + this.fNumber = const Value.absent(), + this.fileSize = const Value.absent(), + this.focalLength = const Value.absent(), + this.latitude = const Value.absent(), + this.longitude = const Value.absent(), + this.iso = const Value.absent(), + this.make = const Value.absent(), + this.model = const Value.absent(), + this.lens = const Value.absent(), + this.orientation = const Value.absent(), + this.timeZone = const Value.absent(), + this.rating = const Value.absent(), + this.projectionType = const Value.absent(), + }); + RemoteExifEntityCompanion.insert({ + required String assetId, + this.city = const Value.absent(), + this.state = const Value.absent(), + this.country = const Value.absent(), + this.dateTimeOriginal = const Value.absent(), + this.description = const Value.absent(), + this.height = const Value.absent(), + this.width = const Value.absent(), + this.exposureTime = const Value.absent(), + this.fNumber = const Value.absent(), + this.fileSize = const Value.absent(), + this.focalLength = const Value.absent(), + this.latitude = const Value.absent(), + this.longitude = const Value.absent(), + this.iso = const Value.absent(), + this.make = const Value.absent(), + this.model = const Value.absent(), + this.lens = const Value.absent(), + this.orientation = const Value.absent(), + this.timeZone = const Value.absent(), + this.rating = const Value.absent(), + this.projectionType = const Value.absent(), + }) : assetId = Value(assetId); + static Insertable custom({ + Expression? assetId, + Expression? city, + Expression? state, + Expression? country, + Expression? dateTimeOriginal, + Expression? description, + Expression? height, + Expression? width, + Expression? exposureTime, + Expression? fNumber, + Expression? fileSize, + Expression? focalLength, + Expression? latitude, + Expression? longitude, + Expression? iso, + Expression? make, + Expression? model, + Expression? lens, + Expression? orientation, + Expression? timeZone, + Expression? rating, + Expression? projectionType, + }) { + return RawValuesInsertable({ + if (assetId != null) 'asset_id': assetId, + if (city != null) 'city': city, + if (state != null) 'state': state, + if (country != null) 'country': country, + if (dateTimeOriginal != null) 'date_time_original': dateTimeOriginal, + if (description != null) 'description': description, + if (height != null) 'height': height, + if (width != null) 'width': width, + if (exposureTime != null) 'exposure_time': exposureTime, + if (fNumber != null) 'f_number': fNumber, + if (fileSize != null) 'file_size': fileSize, + if (focalLength != null) 'focal_length': focalLength, + if (latitude != null) 'latitude': latitude, + if (longitude != null) 'longitude': longitude, + if (iso != null) 'iso': iso, + if (make != null) 'make': make, + if (model != null) 'model': model, + if (lens != null) 'lens': lens, + if (orientation != null) 'orientation': orientation, + if (timeZone != null) 'time_zone': timeZone, + if (rating != null) 'rating': rating, + if (projectionType != null) 'projection_type': projectionType, + }); + } + + RemoteExifEntityCompanion copyWith({ + Value? assetId, + Value? city, + Value? state, + Value? country, + Value? dateTimeOriginal, + Value? description, + Value? height, + Value? width, + Value? exposureTime, + Value? fNumber, + Value? fileSize, + Value? focalLength, + Value? latitude, + Value? longitude, + Value? iso, + Value? make, + Value? model, + Value? lens, + Value? orientation, + Value? timeZone, + Value? rating, + Value? projectionType, + }) { + return RemoteExifEntityCompanion( + assetId: assetId ?? this.assetId, + city: city ?? this.city, + state: state ?? this.state, + country: country ?? this.country, + dateTimeOriginal: dateTimeOriginal ?? this.dateTimeOriginal, + description: description ?? this.description, + height: height ?? this.height, + width: width ?? this.width, + exposureTime: exposureTime ?? this.exposureTime, + fNumber: fNumber ?? this.fNumber, + fileSize: fileSize ?? this.fileSize, + focalLength: focalLength ?? this.focalLength, + latitude: latitude ?? this.latitude, + longitude: longitude ?? this.longitude, + iso: iso ?? this.iso, + make: make ?? this.make, + model: model ?? this.model, + lens: lens ?? this.lens, + orientation: orientation ?? this.orientation, + timeZone: timeZone ?? this.timeZone, + rating: rating ?? this.rating, + projectionType: projectionType ?? this.projectionType, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (assetId.present) { + map['asset_id'] = Variable(assetId.value); + } + if (city.present) { + map['city'] = Variable(city.value); + } + if (state.present) { + map['state'] = Variable(state.value); + } + if (country.present) { + map['country'] = Variable(country.value); + } + if (dateTimeOriginal.present) { + map['date_time_original'] = Variable(dateTimeOriginal.value); + } + if (description.present) { + map['description'] = Variable(description.value); + } + if (height.present) { + map['height'] = Variable(height.value); + } + if (width.present) { + map['width'] = Variable(width.value); + } + if (exposureTime.present) { + map['exposure_time'] = Variable(exposureTime.value); + } + if (fNumber.present) { + map['f_number'] = Variable(fNumber.value); + } + if (fileSize.present) { + map['file_size'] = Variable(fileSize.value); + } + if (focalLength.present) { + map['focal_length'] = Variable(focalLength.value); + } + if (latitude.present) { + map['latitude'] = Variable(latitude.value); + } + if (longitude.present) { + map['longitude'] = Variable(longitude.value); + } + if (iso.present) { + map['iso'] = Variable(iso.value); + } + if (make.present) { + map['make'] = Variable(make.value); + } + if (model.present) { + map['model'] = Variable(model.value); + } + if (lens.present) { + map['lens'] = Variable(lens.value); + } + if (orientation.present) { + map['orientation'] = Variable(orientation.value); + } + if (timeZone.present) { + map['time_zone'] = Variable(timeZone.value); + } + if (rating.present) { + map['rating'] = Variable(rating.value); + } + if (projectionType.present) { + map['projection_type'] = Variable(projectionType.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RemoteExifEntityCompanion(') + ..write('assetId: $assetId, ') + ..write('city: $city, ') + ..write('state: $state, ') + ..write('country: $country, ') + ..write('dateTimeOriginal: $dateTimeOriginal, ') + ..write('description: $description, ') + ..write('height: $height, ') + ..write('width: $width, ') + ..write('exposureTime: $exposureTime, ') + ..write('fNumber: $fNumber, ') + ..write('fileSize: $fileSize, ') + ..write('focalLength: $focalLength, ') + ..write('latitude: $latitude, ') + ..write('longitude: $longitude, ') + ..write('iso: $iso, ') + ..write('make: $make, ') + ..write('model: $model, ') + ..write('lens: $lens, ') + ..write('orientation: $orientation, ') + ..write('timeZone: $timeZone, ') + ..write('rating: $rating, ') + ..write('projectionType: $projectionType') + ..write(')')) + .toString(); + } +} + +class RemoteAlbumAssetEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RemoteAlbumAssetEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn assetId = GeneratedColumn( + 'asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_asset_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn albumId = GeneratedColumn( + 'album_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_album_entity (id) ON DELETE CASCADE', + ), + ); + @override + List get $columns => [assetId, albumId]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'remote_album_asset_entity'; + @override + Set get $primaryKey => {assetId, albumId}; + @override + RemoteAlbumAssetEntityData map( + Map data, { + String? tablePrefix, + }) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RemoteAlbumAssetEntityData( + assetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}asset_id'], + )!, + albumId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}album_id'], + )!, + ); + } + + @override + RemoteAlbumAssetEntity createAlias(String alias) { + return RemoteAlbumAssetEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class RemoteAlbumAssetEntityData extends DataClass + implements Insertable { + final String assetId; + final String albumId; + const RemoteAlbumAssetEntityData({ + required this.assetId, + required this.albumId, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['asset_id'] = Variable(assetId); + map['album_id'] = Variable(albumId); + return map; + } + + factory RemoteAlbumAssetEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RemoteAlbumAssetEntityData( + assetId: serializer.fromJson(json['assetId']), + albumId: serializer.fromJson(json['albumId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'assetId': serializer.toJson(assetId), + 'albumId': serializer.toJson(albumId), + }; + } + + RemoteAlbumAssetEntityData copyWith({String? assetId, String? albumId}) => + RemoteAlbumAssetEntityData( + assetId: assetId ?? this.assetId, + albumId: albumId ?? this.albumId, + ); + RemoteAlbumAssetEntityData copyWithCompanion( + RemoteAlbumAssetEntityCompanion data, + ) { + return RemoteAlbumAssetEntityData( + assetId: data.assetId.present ? data.assetId.value : this.assetId, + albumId: data.albumId.present ? data.albumId.value : this.albumId, + ); + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumAssetEntityData(') + ..write('assetId: $assetId, ') + ..write('albumId: $albumId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(assetId, albumId); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RemoteAlbumAssetEntityData && + other.assetId == this.assetId && + other.albumId == this.albumId); +} + +class RemoteAlbumAssetEntityCompanion + extends UpdateCompanion { + final Value assetId; + final Value albumId; + const RemoteAlbumAssetEntityCompanion({ + this.assetId = const Value.absent(), + this.albumId = const Value.absent(), + }); + RemoteAlbumAssetEntityCompanion.insert({ + required String assetId, + required String albumId, + }) : assetId = Value(assetId), + albumId = Value(albumId); + static Insertable custom({ + Expression? assetId, + Expression? albumId, + }) { + return RawValuesInsertable({ + if (assetId != null) 'asset_id': assetId, + if (albumId != null) 'album_id': albumId, + }); + } + + RemoteAlbumAssetEntityCompanion copyWith({ + Value? assetId, + Value? albumId, + }) { + return RemoteAlbumAssetEntityCompanion( + assetId: assetId ?? this.assetId, + albumId: albumId ?? this.albumId, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (assetId.present) { + map['asset_id'] = Variable(assetId.value); + } + if (albumId.present) { + map['album_id'] = Variable(albumId.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumAssetEntityCompanion(') + ..write('assetId: $assetId, ') + ..write('albumId: $albumId') + ..write(')')) + .toString(); + } +} + +class RemoteAlbumUserEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RemoteAlbumUserEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn albumId = GeneratedColumn( + 'album_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_album_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn role = GeneratedColumn( + 'role', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + @override + List get $columns => [albumId, userId, role]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'remote_album_user_entity'; + @override + Set get $primaryKey => {albumId, userId}; + @override + RemoteAlbumUserEntityData map( + Map data, { + String? tablePrefix, + }) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RemoteAlbumUserEntityData( + albumId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}album_id'], + )!, + userId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}user_id'], + )!, + role: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}role'], + )!, + ); + } + + @override + RemoteAlbumUserEntity createAlias(String alias) { + return RemoteAlbumUserEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class RemoteAlbumUserEntityData extends DataClass + implements Insertable { + final String albumId; + final String userId; + final int role; + const RemoteAlbumUserEntityData({ + required this.albumId, + required this.userId, + required this.role, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['album_id'] = Variable(albumId); + map['user_id'] = Variable(userId); + map['role'] = Variable(role); + return map; + } + + factory RemoteAlbumUserEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RemoteAlbumUserEntityData( + albumId: serializer.fromJson(json['albumId']), + userId: serializer.fromJson(json['userId']), + role: serializer.fromJson(json['role']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'albumId': serializer.toJson(albumId), + 'userId': serializer.toJson(userId), + 'role': serializer.toJson(role), + }; + } + + RemoteAlbumUserEntityData copyWith({ + String? albumId, + String? userId, + int? role, + }) => RemoteAlbumUserEntityData( + albumId: albumId ?? this.albumId, + userId: userId ?? this.userId, + role: role ?? this.role, + ); + RemoteAlbumUserEntityData copyWithCompanion( + RemoteAlbumUserEntityCompanion data, + ) { + return RemoteAlbumUserEntityData( + albumId: data.albumId.present ? data.albumId.value : this.albumId, + userId: data.userId.present ? data.userId.value : this.userId, + role: data.role.present ? data.role.value : this.role, + ); + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumUserEntityData(') + ..write('albumId: $albumId, ') + ..write('userId: $userId, ') + ..write('role: $role') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(albumId, userId, role); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RemoteAlbumUserEntityData && + other.albumId == this.albumId && + other.userId == this.userId && + other.role == this.role); +} + +class RemoteAlbumUserEntityCompanion + extends UpdateCompanion { + final Value albumId; + final Value userId; + final Value role; + const RemoteAlbumUserEntityCompanion({ + this.albumId = const Value.absent(), + this.userId = const Value.absent(), + this.role = const Value.absent(), + }); + RemoteAlbumUserEntityCompanion.insert({ + required String albumId, + required String userId, + required int role, + }) : albumId = Value(albumId), + userId = Value(userId), + role = Value(role); + static Insertable custom({ + Expression? albumId, + Expression? userId, + Expression? role, + }) { + return RawValuesInsertable({ + if (albumId != null) 'album_id': albumId, + if (userId != null) 'user_id': userId, + if (role != null) 'role': role, + }); + } + + RemoteAlbumUserEntityCompanion copyWith({ + Value? albumId, + Value? userId, + Value? role, + }) { + return RemoteAlbumUserEntityCompanion( + albumId: albumId ?? this.albumId, + userId: userId ?? this.userId, + role: role ?? this.role, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (albumId.present) { + map['album_id'] = Variable(albumId.value); + } + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (role.present) { + map['role'] = Variable(role.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumUserEntityCompanion(') + ..write('albumId: $albumId, ') + ..write('userId: $userId, ') + ..write('role: $role') + ..write(')')) + .toString(); + } +} + +class MemoryEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + MemoryEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn deletedAt = GeneratedColumn( + 'deleted_at', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn ownerId = GeneratedColumn( + 'owner_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn type = GeneratedColumn( + 'type', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn data = GeneratedColumn( + 'data', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn isSaved = GeneratedColumn( + 'is_saved', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_saved" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn memoryAt = GeneratedColumn( + 'memory_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: true, + ); + late final GeneratedColumn seenAt = GeneratedColumn( + 'seen_at', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn showAt = GeneratedColumn( + 'show_at', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn hideAt = GeneratedColumn( + 'hide_at', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + deletedAt, + ownerId, + type, + data, + isSaved, + memoryAt, + seenAt, + showAt, + hideAt, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'memory_entity'; + @override + Set get $primaryKey => {id}; + @override + MemoryEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return MemoryEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + deletedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}deleted_at'], + ), + ownerId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}owner_id'], + )!, + type: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}type'], + )!, + data: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}data'], + )!, + isSaved: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_saved'], + )!, + memoryAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}memory_at'], + )!, + seenAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}seen_at'], + ), + showAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}show_at'], + ), + hideAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}hide_at'], + ), + ); + } + + @override + MemoryEntity createAlias(String alias) { + return MemoryEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class MemoryEntityData extends DataClass + implements Insertable { + final String id; + final DateTime createdAt; + final DateTime updatedAt; + final DateTime? deletedAt; + final String ownerId; + final int type; + final String data; + final bool isSaved; + final DateTime memoryAt; + final DateTime? seenAt; + final DateTime? showAt; + final DateTime? hideAt; + const MemoryEntityData({ + required this.id, + required this.createdAt, + required this.updatedAt, + this.deletedAt, + required this.ownerId, + required this.type, + required this.data, + required this.isSaved, + required this.memoryAt, + this.seenAt, + this.showAt, + this.hideAt, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || deletedAt != null) { + map['deleted_at'] = Variable(deletedAt); + } + map['owner_id'] = Variable(ownerId); + map['type'] = Variable(type); + map['data'] = Variable(data); + map['is_saved'] = Variable(isSaved); + map['memory_at'] = Variable(memoryAt); + if (!nullToAbsent || seenAt != null) { + map['seen_at'] = Variable(seenAt); + } + if (!nullToAbsent || showAt != null) { + map['show_at'] = Variable(showAt); + } + if (!nullToAbsent || hideAt != null) { + map['hide_at'] = Variable(hideAt); + } + return map; + } + + factory MemoryEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return MemoryEntityData( + id: serializer.fromJson(json['id']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + deletedAt: serializer.fromJson(json['deletedAt']), + ownerId: serializer.fromJson(json['ownerId']), + type: serializer.fromJson(json['type']), + data: serializer.fromJson(json['data']), + isSaved: serializer.fromJson(json['isSaved']), + memoryAt: serializer.fromJson(json['memoryAt']), + seenAt: serializer.fromJson(json['seenAt']), + showAt: serializer.fromJson(json['showAt']), + hideAt: serializer.fromJson(json['hideAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'deletedAt': serializer.toJson(deletedAt), + 'ownerId': serializer.toJson(ownerId), + 'type': serializer.toJson(type), + 'data': serializer.toJson(data), + 'isSaved': serializer.toJson(isSaved), + 'memoryAt': serializer.toJson(memoryAt), + 'seenAt': serializer.toJson(seenAt), + 'showAt': serializer.toJson(showAt), + 'hideAt': serializer.toJson(hideAt), + }; + } + + MemoryEntityData copyWith({ + String? id, + DateTime? createdAt, + DateTime? updatedAt, + Value deletedAt = const Value.absent(), + String? ownerId, + int? type, + String? data, + bool? isSaved, + DateTime? memoryAt, + Value seenAt = const Value.absent(), + Value showAt = const Value.absent(), + Value hideAt = const Value.absent(), + }) => MemoryEntityData( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt, + ownerId: ownerId ?? this.ownerId, + type: type ?? this.type, + data: data ?? this.data, + isSaved: isSaved ?? this.isSaved, + memoryAt: memoryAt ?? this.memoryAt, + seenAt: seenAt.present ? seenAt.value : this.seenAt, + showAt: showAt.present ? showAt.value : this.showAt, + hideAt: hideAt.present ? hideAt.value : this.hideAt, + ); + MemoryEntityData copyWithCompanion(MemoryEntityCompanion data) { + return MemoryEntityData( + id: data.id.present ? data.id.value : this.id, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + deletedAt: data.deletedAt.present ? data.deletedAt.value : this.deletedAt, + ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId, + type: data.type.present ? data.type.value : this.type, + data: data.data.present ? data.data.value : this.data, + isSaved: data.isSaved.present ? data.isSaved.value : this.isSaved, + memoryAt: data.memoryAt.present ? data.memoryAt.value : this.memoryAt, + seenAt: data.seenAt.present ? data.seenAt.value : this.seenAt, + showAt: data.showAt.present ? data.showAt.value : this.showAt, + hideAt: data.hideAt.present ? data.hideAt.value : this.hideAt, + ); + } + + @override + String toString() { + return (StringBuffer('MemoryEntityData(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('ownerId: $ownerId, ') + ..write('type: $type, ') + ..write('data: $data, ') + ..write('isSaved: $isSaved, ') + ..write('memoryAt: $memoryAt, ') + ..write('seenAt: $seenAt, ') + ..write('showAt: $showAt, ') + ..write('hideAt: $hideAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + createdAt, + updatedAt, + deletedAt, + ownerId, + type, + data, + isSaved, + memoryAt, + seenAt, + showAt, + hideAt, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is MemoryEntityData && + other.id == this.id && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.deletedAt == this.deletedAt && + other.ownerId == this.ownerId && + other.type == this.type && + other.data == this.data && + other.isSaved == this.isSaved && + other.memoryAt == this.memoryAt && + other.seenAt == this.seenAt && + other.showAt == this.showAt && + other.hideAt == this.hideAt); +} + +class MemoryEntityCompanion extends UpdateCompanion { + final Value id; + final Value createdAt; + final Value updatedAt; + final Value deletedAt; + final Value ownerId; + final Value type; + final Value data; + final Value isSaved; + final Value memoryAt; + final Value seenAt; + final Value showAt; + final Value hideAt; + const MemoryEntityCompanion({ + this.id = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.ownerId = const Value.absent(), + this.type = const Value.absent(), + this.data = const Value.absent(), + this.isSaved = const Value.absent(), + this.memoryAt = const Value.absent(), + this.seenAt = const Value.absent(), + this.showAt = const Value.absent(), + this.hideAt = const Value.absent(), + }); + MemoryEntityCompanion.insert({ + required String id, + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + required String ownerId, + required int type, + required String data, + this.isSaved = const Value.absent(), + required DateTime memoryAt, + this.seenAt = const Value.absent(), + this.showAt = const Value.absent(), + this.hideAt = const Value.absent(), + }) : id = Value(id), + ownerId = Value(ownerId), + type = Value(type), + data = Value(data), + memoryAt = Value(memoryAt); + static Insertable custom({ + Expression? id, + Expression? createdAt, + Expression? updatedAt, + Expression? deletedAt, + Expression? ownerId, + Expression? type, + Expression? data, + Expression? isSaved, + Expression? memoryAt, + Expression? seenAt, + Expression? showAt, + Expression? hideAt, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (deletedAt != null) 'deleted_at': deletedAt, + if (ownerId != null) 'owner_id': ownerId, + if (type != null) 'type': type, + if (data != null) 'data': data, + if (isSaved != null) 'is_saved': isSaved, + if (memoryAt != null) 'memory_at': memoryAt, + if (seenAt != null) 'seen_at': seenAt, + if (showAt != null) 'show_at': showAt, + if (hideAt != null) 'hide_at': hideAt, + }); + } + + MemoryEntityCompanion copyWith({ + Value? id, + Value? createdAt, + Value? updatedAt, + Value? deletedAt, + Value? ownerId, + Value? type, + Value? data, + Value? isSaved, + Value? memoryAt, + Value? seenAt, + Value? showAt, + Value? hideAt, + }) { + return MemoryEntityCompanion( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + ownerId: ownerId ?? this.ownerId, + type: type ?? this.type, + data: data ?? this.data, + isSaved: isSaved ?? this.isSaved, + memoryAt: memoryAt ?? this.memoryAt, + seenAt: seenAt ?? this.seenAt, + showAt: showAt ?? this.showAt, + hideAt: hideAt ?? this.hideAt, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (deletedAt.present) { + map['deleted_at'] = Variable(deletedAt.value); + } + if (ownerId.present) { + map['owner_id'] = Variable(ownerId.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (data.present) { + map['data'] = Variable(data.value); + } + if (isSaved.present) { + map['is_saved'] = Variable(isSaved.value); + } + if (memoryAt.present) { + map['memory_at'] = Variable(memoryAt.value); + } + if (seenAt.present) { + map['seen_at'] = Variable(seenAt.value); + } + if (showAt.present) { + map['show_at'] = Variable(showAt.value); + } + if (hideAt.present) { + map['hide_at'] = Variable(hideAt.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('MemoryEntityCompanion(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('ownerId: $ownerId, ') + ..write('type: $type, ') + ..write('data: $data, ') + ..write('isSaved: $isSaved, ') + ..write('memoryAt: $memoryAt, ') + ..write('seenAt: $seenAt, ') + ..write('showAt: $showAt, ') + ..write('hideAt: $hideAt') + ..write(')')) + .toString(); + } +} + +class MemoryAssetEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + MemoryAssetEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn assetId = GeneratedColumn( + 'asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_asset_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn memoryId = GeneratedColumn( + 'memory_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES memory_entity (id) ON DELETE CASCADE', + ), + ); + @override + List get $columns => [assetId, memoryId]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'memory_asset_entity'; + @override + Set get $primaryKey => {assetId, memoryId}; + @override + MemoryAssetEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return MemoryAssetEntityData( + assetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}asset_id'], + )!, + memoryId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}memory_id'], + )!, + ); + } + + @override + MemoryAssetEntity createAlias(String alias) { + return MemoryAssetEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class MemoryAssetEntityData extends DataClass + implements Insertable { + final String assetId; + final String memoryId; + const MemoryAssetEntityData({required this.assetId, required this.memoryId}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['asset_id'] = Variable(assetId); + map['memory_id'] = Variable(memoryId); + return map; + } + + factory MemoryAssetEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return MemoryAssetEntityData( + assetId: serializer.fromJson(json['assetId']), + memoryId: serializer.fromJson(json['memoryId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'assetId': serializer.toJson(assetId), + 'memoryId': serializer.toJson(memoryId), + }; + } + + MemoryAssetEntityData copyWith({String? assetId, String? memoryId}) => + MemoryAssetEntityData( + assetId: assetId ?? this.assetId, + memoryId: memoryId ?? this.memoryId, + ); + MemoryAssetEntityData copyWithCompanion(MemoryAssetEntityCompanion data) { + return MemoryAssetEntityData( + assetId: data.assetId.present ? data.assetId.value : this.assetId, + memoryId: data.memoryId.present ? data.memoryId.value : this.memoryId, + ); + } + + @override + String toString() { + return (StringBuffer('MemoryAssetEntityData(') + ..write('assetId: $assetId, ') + ..write('memoryId: $memoryId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(assetId, memoryId); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is MemoryAssetEntityData && + other.assetId == this.assetId && + other.memoryId == this.memoryId); +} + +class MemoryAssetEntityCompanion + extends UpdateCompanion { + final Value assetId; + final Value memoryId; + const MemoryAssetEntityCompanion({ + this.assetId = const Value.absent(), + this.memoryId = const Value.absent(), + }); + MemoryAssetEntityCompanion.insert({ + required String assetId, + required String memoryId, + }) : assetId = Value(assetId), + memoryId = Value(memoryId); + static Insertable custom({ + Expression? assetId, + Expression? memoryId, + }) { + return RawValuesInsertable({ + if (assetId != null) 'asset_id': assetId, + if (memoryId != null) 'memory_id': memoryId, + }); + } + + MemoryAssetEntityCompanion copyWith({ + Value? assetId, + Value? memoryId, + }) { + return MemoryAssetEntityCompanion( + assetId: assetId ?? this.assetId, + memoryId: memoryId ?? this.memoryId, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (assetId.present) { + map['asset_id'] = Variable(assetId.value); + } + if (memoryId.present) { + map['memory_id'] = Variable(memoryId.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('MemoryAssetEntityCompanion(') + ..write('assetId: $assetId, ') + ..write('memoryId: $memoryId') + ..write(')')) + .toString(); + } +} + +class PersonEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + PersonEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn ownerId = GeneratedColumn( + 'owner_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn faceAssetId = GeneratedColumn( + 'face_asset_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn isFavorite = GeneratedColumn( + 'is_favorite', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_favorite" IN (0, 1))', + ), + ); + late final GeneratedColumn isHidden = GeneratedColumn( + 'is_hidden', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_hidden" IN (0, 1))', + ), + ); + late final GeneratedColumn color = GeneratedColumn( + 'color', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn birthDate = GeneratedColumn( + 'birth_date', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + ownerId, + name, + faceAssetId, + isFavorite, + isHidden, + color, + birthDate, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'person_entity'; + @override + Set get $primaryKey => {id}; + @override + PersonEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return PersonEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + ownerId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}owner_id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + faceAssetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}face_asset_id'], + ), + isFavorite: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_favorite'], + )!, + isHidden: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_hidden'], + )!, + color: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}color'], + ), + birthDate: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}birth_date'], + ), + ); + } + + @override + PersonEntity createAlias(String alias) { + return PersonEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class PersonEntityData extends DataClass + implements Insertable { + final String id; + final DateTime createdAt; + final DateTime updatedAt; + final String ownerId; + final String name; + final String? faceAssetId; + final bool isFavorite; + final bool isHidden; + final String? color; + final DateTime? birthDate; + const PersonEntityData({ + required this.id, + required this.createdAt, + required this.updatedAt, + required this.ownerId, + required this.name, + this.faceAssetId, + required this.isFavorite, + required this.isHidden, + this.color, + this.birthDate, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + map['owner_id'] = Variable(ownerId); + map['name'] = Variable(name); + if (!nullToAbsent || faceAssetId != null) { + map['face_asset_id'] = Variable(faceAssetId); + } + map['is_favorite'] = Variable(isFavorite); + map['is_hidden'] = Variable(isHidden); + if (!nullToAbsent || color != null) { + map['color'] = Variable(color); + } + if (!nullToAbsent || birthDate != null) { + map['birth_date'] = Variable(birthDate); + } + return map; + } + + factory PersonEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return PersonEntityData( + id: serializer.fromJson(json['id']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + ownerId: serializer.fromJson(json['ownerId']), + name: serializer.fromJson(json['name']), + faceAssetId: serializer.fromJson(json['faceAssetId']), + isFavorite: serializer.fromJson(json['isFavorite']), + isHidden: serializer.fromJson(json['isHidden']), + color: serializer.fromJson(json['color']), + birthDate: serializer.fromJson(json['birthDate']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'ownerId': serializer.toJson(ownerId), + 'name': serializer.toJson(name), + 'faceAssetId': serializer.toJson(faceAssetId), + 'isFavorite': serializer.toJson(isFavorite), + 'isHidden': serializer.toJson(isHidden), + 'color': serializer.toJson(color), + 'birthDate': serializer.toJson(birthDate), + }; + } + + PersonEntityData copyWith({ + String? id, + DateTime? createdAt, + DateTime? updatedAt, + String? ownerId, + String? name, + Value faceAssetId = const Value.absent(), + bool? isFavorite, + bool? isHidden, + Value color = const Value.absent(), + Value birthDate = const Value.absent(), + }) => PersonEntityData( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + name: name ?? this.name, + faceAssetId: faceAssetId.present ? faceAssetId.value : this.faceAssetId, + isFavorite: isFavorite ?? this.isFavorite, + isHidden: isHidden ?? this.isHidden, + color: color.present ? color.value : this.color, + birthDate: birthDate.present ? birthDate.value : this.birthDate, + ); + PersonEntityData copyWithCompanion(PersonEntityCompanion data) { + return PersonEntityData( + id: data.id.present ? data.id.value : this.id, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId, + name: data.name.present ? data.name.value : this.name, + faceAssetId: data.faceAssetId.present + ? data.faceAssetId.value + : this.faceAssetId, + isFavorite: data.isFavorite.present + ? data.isFavorite.value + : this.isFavorite, + isHidden: data.isHidden.present ? data.isHidden.value : this.isHidden, + color: data.color.present ? data.color.value : this.color, + birthDate: data.birthDate.present ? data.birthDate.value : this.birthDate, + ); + } + + @override + String toString() { + return (StringBuffer('PersonEntityData(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('name: $name, ') + ..write('faceAssetId: $faceAssetId, ') + ..write('isFavorite: $isFavorite, ') + ..write('isHidden: $isHidden, ') + ..write('color: $color, ') + ..write('birthDate: $birthDate') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + createdAt, + updatedAt, + ownerId, + name, + faceAssetId, + isFavorite, + isHidden, + color, + birthDate, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is PersonEntityData && + other.id == this.id && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.ownerId == this.ownerId && + other.name == this.name && + other.faceAssetId == this.faceAssetId && + other.isFavorite == this.isFavorite && + other.isHidden == this.isHidden && + other.color == this.color && + other.birthDate == this.birthDate); +} + +class PersonEntityCompanion extends UpdateCompanion { + final Value id; + final Value createdAt; + final Value updatedAt; + final Value ownerId; + final Value name; + final Value faceAssetId; + final Value isFavorite; + final Value isHidden; + final Value color; + final Value birthDate; + const PersonEntityCompanion({ + this.id = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.ownerId = const Value.absent(), + this.name = const Value.absent(), + this.faceAssetId = const Value.absent(), + this.isFavorite = const Value.absent(), + this.isHidden = const Value.absent(), + this.color = const Value.absent(), + this.birthDate = const Value.absent(), + }); + PersonEntityCompanion.insert({ + required String id, + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + required String ownerId, + required String name, + this.faceAssetId = const Value.absent(), + required bool isFavorite, + required bool isHidden, + this.color = const Value.absent(), + this.birthDate = const Value.absent(), + }) : id = Value(id), + ownerId = Value(ownerId), + name = Value(name), + isFavorite = Value(isFavorite), + isHidden = Value(isHidden); + static Insertable custom({ + Expression? id, + Expression? createdAt, + Expression? updatedAt, + Expression? ownerId, + Expression? name, + Expression? faceAssetId, + Expression? isFavorite, + Expression? isHidden, + Expression? color, + Expression? birthDate, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (ownerId != null) 'owner_id': ownerId, + if (name != null) 'name': name, + if (faceAssetId != null) 'face_asset_id': faceAssetId, + if (isFavorite != null) 'is_favorite': isFavorite, + if (isHidden != null) 'is_hidden': isHidden, + if (color != null) 'color': color, + if (birthDate != null) 'birth_date': birthDate, + }); + } + + PersonEntityCompanion copyWith({ + Value? id, + Value? createdAt, + Value? updatedAt, + Value? ownerId, + Value? name, + Value? faceAssetId, + Value? isFavorite, + Value? isHidden, + Value? color, + Value? birthDate, + }) { + return PersonEntityCompanion( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + name: name ?? this.name, + faceAssetId: faceAssetId ?? this.faceAssetId, + isFavorite: isFavorite ?? this.isFavorite, + isHidden: isHidden ?? this.isHidden, + color: color ?? this.color, + birthDate: birthDate ?? this.birthDate, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (ownerId.present) { + map['owner_id'] = Variable(ownerId.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (faceAssetId.present) { + map['face_asset_id'] = Variable(faceAssetId.value); + } + if (isFavorite.present) { + map['is_favorite'] = Variable(isFavorite.value); + } + if (isHidden.present) { + map['is_hidden'] = Variable(isHidden.value); + } + if (color.present) { + map['color'] = Variable(color.value); + } + if (birthDate.present) { + map['birth_date'] = Variable(birthDate.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('PersonEntityCompanion(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('name: $name, ') + ..write('faceAssetId: $faceAssetId, ') + ..write('isFavorite: $isFavorite, ') + ..write('isHidden: $isHidden, ') + ..write('color: $color, ') + ..write('birthDate: $birthDate') + ..write(')')) + .toString(); + } +} + +class AssetFaceEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + AssetFaceEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn assetId = GeneratedColumn( + 'asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_asset_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn personId = GeneratedColumn( + 'person_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES person_entity (id) ON DELETE SET NULL', + ), + ); + late final GeneratedColumn imageWidth = GeneratedColumn( + 'image_width', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn imageHeight = GeneratedColumn( + 'image_height', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn boundingBoxX1 = GeneratedColumn( + 'bounding_box_x1', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn boundingBoxY1 = GeneratedColumn( + 'bounding_box_y1', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn boundingBoxX2 = GeneratedColumn( + 'bounding_box_x2', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn boundingBoxY2 = GeneratedColumn( + 'bounding_box_y2', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn sourceType = GeneratedColumn( + 'source_type', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + @override + List get $columns => [ + id, + assetId, + personId, + imageWidth, + imageHeight, + boundingBoxX1, + boundingBoxY1, + boundingBoxX2, + boundingBoxY2, + sourceType, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'asset_face_entity'; + @override + Set get $primaryKey => {id}; + @override + AssetFaceEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return AssetFaceEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + assetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}asset_id'], + )!, + personId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}person_id'], + ), + imageWidth: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}image_width'], + )!, + imageHeight: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}image_height'], + )!, + boundingBoxX1: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}bounding_box_x1'], + )!, + boundingBoxY1: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}bounding_box_y1'], + )!, + boundingBoxX2: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}bounding_box_x2'], + )!, + boundingBoxY2: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}bounding_box_y2'], + )!, + sourceType: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}source_type'], + )!, + ); + } + + @override + AssetFaceEntity createAlias(String alias) { + return AssetFaceEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class AssetFaceEntityData extends DataClass + implements Insertable { + final String id; + final String assetId; + final String? personId; + final int imageWidth; + final int imageHeight; + final int boundingBoxX1; + final int boundingBoxY1; + final int boundingBoxX2; + final int boundingBoxY2; + final String sourceType; + const AssetFaceEntityData({ + required this.id, + required this.assetId, + this.personId, + required this.imageWidth, + required this.imageHeight, + required this.boundingBoxX1, + required this.boundingBoxY1, + required this.boundingBoxX2, + required this.boundingBoxY2, + required this.sourceType, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['asset_id'] = Variable(assetId); + if (!nullToAbsent || personId != null) { + map['person_id'] = Variable(personId); + } + map['image_width'] = Variable(imageWidth); + map['image_height'] = Variable(imageHeight); + map['bounding_box_x1'] = Variable(boundingBoxX1); + map['bounding_box_y1'] = Variable(boundingBoxY1); + map['bounding_box_x2'] = Variable(boundingBoxX2); + map['bounding_box_y2'] = Variable(boundingBoxY2); + map['source_type'] = Variable(sourceType); + return map; + } + + factory AssetFaceEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return AssetFaceEntityData( + id: serializer.fromJson(json['id']), + assetId: serializer.fromJson(json['assetId']), + personId: serializer.fromJson(json['personId']), + imageWidth: serializer.fromJson(json['imageWidth']), + imageHeight: serializer.fromJson(json['imageHeight']), + boundingBoxX1: serializer.fromJson(json['boundingBoxX1']), + boundingBoxY1: serializer.fromJson(json['boundingBoxY1']), + boundingBoxX2: serializer.fromJson(json['boundingBoxX2']), + boundingBoxY2: serializer.fromJson(json['boundingBoxY2']), + sourceType: serializer.fromJson(json['sourceType']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'assetId': serializer.toJson(assetId), + 'personId': serializer.toJson(personId), + 'imageWidth': serializer.toJson(imageWidth), + 'imageHeight': serializer.toJson(imageHeight), + 'boundingBoxX1': serializer.toJson(boundingBoxX1), + 'boundingBoxY1': serializer.toJson(boundingBoxY1), + 'boundingBoxX2': serializer.toJson(boundingBoxX2), + 'boundingBoxY2': serializer.toJson(boundingBoxY2), + 'sourceType': serializer.toJson(sourceType), + }; + } + + AssetFaceEntityData copyWith({ + String? id, + String? assetId, + Value personId = const Value.absent(), + int? imageWidth, + int? imageHeight, + int? boundingBoxX1, + int? boundingBoxY1, + int? boundingBoxX2, + int? boundingBoxY2, + String? sourceType, + }) => AssetFaceEntityData( + id: id ?? this.id, + assetId: assetId ?? this.assetId, + personId: personId.present ? personId.value : this.personId, + imageWidth: imageWidth ?? this.imageWidth, + imageHeight: imageHeight ?? this.imageHeight, + boundingBoxX1: boundingBoxX1 ?? this.boundingBoxX1, + boundingBoxY1: boundingBoxY1 ?? this.boundingBoxY1, + boundingBoxX2: boundingBoxX2 ?? this.boundingBoxX2, + boundingBoxY2: boundingBoxY2 ?? this.boundingBoxY2, + sourceType: sourceType ?? this.sourceType, + ); + AssetFaceEntityData copyWithCompanion(AssetFaceEntityCompanion data) { + return AssetFaceEntityData( + id: data.id.present ? data.id.value : this.id, + assetId: data.assetId.present ? data.assetId.value : this.assetId, + personId: data.personId.present ? data.personId.value : this.personId, + imageWidth: data.imageWidth.present + ? data.imageWidth.value + : this.imageWidth, + imageHeight: data.imageHeight.present + ? data.imageHeight.value + : this.imageHeight, + boundingBoxX1: data.boundingBoxX1.present + ? data.boundingBoxX1.value + : this.boundingBoxX1, + boundingBoxY1: data.boundingBoxY1.present + ? data.boundingBoxY1.value + : this.boundingBoxY1, + boundingBoxX2: data.boundingBoxX2.present + ? data.boundingBoxX2.value + : this.boundingBoxX2, + boundingBoxY2: data.boundingBoxY2.present + ? data.boundingBoxY2.value + : this.boundingBoxY2, + sourceType: data.sourceType.present + ? data.sourceType.value + : this.sourceType, + ); + } + + @override + String toString() { + return (StringBuffer('AssetFaceEntityData(') + ..write('id: $id, ') + ..write('assetId: $assetId, ') + ..write('personId: $personId, ') + ..write('imageWidth: $imageWidth, ') + ..write('imageHeight: $imageHeight, ') + ..write('boundingBoxX1: $boundingBoxX1, ') + ..write('boundingBoxY1: $boundingBoxY1, ') + ..write('boundingBoxX2: $boundingBoxX2, ') + ..write('boundingBoxY2: $boundingBoxY2, ') + ..write('sourceType: $sourceType') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + assetId, + personId, + imageWidth, + imageHeight, + boundingBoxX1, + boundingBoxY1, + boundingBoxX2, + boundingBoxY2, + sourceType, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is AssetFaceEntityData && + other.id == this.id && + other.assetId == this.assetId && + other.personId == this.personId && + other.imageWidth == this.imageWidth && + other.imageHeight == this.imageHeight && + other.boundingBoxX1 == this.boundingBoxX1 && + other.boundingBoxY1 == this.boundingBoxY1 && + other.boundingBoxX2 == this.boundingBoxX2 && + other.boundingBoxY2 == this.boundingBoxY2 && + other.sourceType == this.sourceType); +} + +class AssetFaceEntityCompanion extends UpdateCompanion { + final Value id; + final Value assetId; + final Value personId; + final Value imageWidth; + final Value imageHeight; + final Value boundingBoxX1; + final Value boundingBoxY1; + final Value boundingBoxX2; + final Value boundingBoxY2; + final Value sourceType; + const AssetFaceEntityCompanion({ + this.id = const Value.absent(), + this.assetId = const Value.absent(), + this.personId = const Value.absent(), + this.imageWidth = const Value.absent(), + this.imageHeight = const Value.absent(), + this.boundingBoxX1 = const Value.absent(), + this.boundingBoxY1 = const Value.absent(), + this.boundingBoxX2 = const Value.absent(), + this.boundingBoxY2 = const Value.absent(), + this.sourceType = const Value.absent(), + }); + AssetFaceEntityCompanion.insert({ + required String id, + required String assetId, + this.personId = const Value.absent(), + required int imageWidth, + required int imageHeight, + required int boundingBoxX1, + required int boundingBoxY1, + required int boundingBoxX2, + required int boundingBoxY2, + required String sourceType, + }) : id = Value(id), + assetId = Value(assetId), + imageWidth = Value(imageWidth), + imageHeight = Value(imageHeight), + boundingBoxX1 = Value(boundingBoxX1), + boundingBoxY1 = Value(boundingBoxY1), + boundingBoxX2 = Value(boundingBoxX2), + boundingBoxY2 = Value(boundingBoxY2), + sourceType = Value(sourceType); + static Insertable custom({ + Expression? id, + Expression? assetId, + Expression? personId, + Expression? imageWidth, + Expression? imageHeight, + Expression? boundingBoxX1, + Expression? boundingBoxY1, + Expression? boundingBoxX2, + Expression? boundingBoxY2, + Expression? sourceType, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (assetId != null) 'asset_id': assetId, + if (personId != null) 'person_id': personId, + if (imageWidth != null) 'image_width': imageWidth, + if (imageHeight != null) 'image_height': imageHeight, + if (boundingBoxX1 != null) 'bounding_box_x1': boundingBoxX1, + if (boundingBoxY1 != null) 'bounding_box_y1': boundingBoxY1, + if (boundingBoxX2 != null) 'bounding_box_x2': boundingBoxX2, + if (boundingBoxY2 != null) 'bounding_box_y2': boundingBoxY2, + if (sourceType != null) 'source_type': sourceType, + }); + } + + AssetFaceEntityCompanion copyWith({ + Value? id, + Value? assetId, + Value? personId, + Value? imageWidth, + Value? imageHeight, + Value? boundingBoxX1, + Value? boundingBoxY1, + Value? boundingBoxX2, + Value? boundingBoxY2, + Value? sourceType, + }) { + return AssetFaceEntityCompanion( + id: id ?? this.id, + assetId: assetId ?? this.assetId, + personId: personId ?? this.personId, + imageWidth: imageWidth ?? this.imageWidth, + imageHeight: imageHeight ?? this.imageHeight, + boundingBoxX1: boundingBoxX1 ?? this.boundingBoxX1, + boundingBoxY1: boundingBoxY1 ?? this.boundingBoxY1, + boundingBoxX2: boundingBoxX2 ?? this.boundingBoxX2, + boundingBoxY2: boundingBoxY2 ?? this.boundingBoxY2, + sourceType: sourceType ?? this.sourceType, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (assetId.present) { + map['asset_id'] = Variable(assetId.value); + } + if (personId.present) { + map['person_id'] = Variable(personId.value); + } + if (imageWidth.present) { + map['image_width'] = Variable(imageWidth.value); + } + if (imageHeight.present) { + map['image_height'] = Variable(imageHeight.value); + } + if (boundingBoxX1.present) { + map['bounding_box_x1'] = Variable(boundingBoxX1.value); + } + if (boundingBoxY1.present) { + map['bounding_box_y1'] = Variable(boundingBoxY1.value); + } + if (boundingBoxX2.present) { + map['bounding_box_x2'] = Variable(boundingBoxX2.value); + } + if (boundingBoxY2.present) { + map['bounding_box_y2'] = Variable(boundingBoxY2.value); + } + if (sourceType.present) { + map['source_type'] = Variable(sourceType.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('AssetFaceEntityCompanion(') + ..write('id: $id, ') + ..write('assetId: $assetId, ') + ..write('personId: $personId, ') + ..write('imageWidth: $imageWidth, ') + ..write('imageHeight: $imageHeight, ') + ..write('boundingBoxX1: $boundingBoxX1, ') + ..write('boundingBoxY1: $boundingBoxY1, ') + ..write('boundingBoxX2: $boundingBoxX2, ') + ..write('boundingBoxY2: $boundingBoxY2, ') + ..write('sourceType: $sourceType') + ..write(')')) + .toString(); + } +} + +class StoreEntity extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + StoreEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn stringValue = GeneratedColumn( + 'string_value', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn intValue = GeneratedColumn( + 'int_value', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + @override + List get $columns => [id, stringValue, intValue]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'store_entity'; + @override + Set get $primaryKey => {id}; + @override + StoreEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return StoreEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}id'], + )!, + stringValue: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}string_value'], + ), + intValue: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}int_value'], + ), + ); + } + + @override + StoreEntity createAlias(String alias) { + return StoreEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class StoreEntityData extends DataClass implements Insertable { + final int id; + final String? stringValue; + final int? intValue; + const StoreEntityData({required this.id, this.stringValue, this.intValue}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + if (!nullToAbsent || stringValue != null) { + map['string_value'] = Variable(stringValue); + } + if (!nullToAbsent || intValue != null) { + map['int_value'] = Variable(intValue); + } + return map; + } + + factory StoreEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return StoreEntityData( + id: serializer.fromJson(json['id']), + stringValue: serializer.fromJson(json['stringValue']), + intValue: serializer.fromJson(json['intValue']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'stringValue': serializer.toJson(stringValue), + 'intValue': serializer.toJson(intValue), + }; + } + + StoreEntityData copyWith({ + int? id, + Value stringValue = const Value.absent(), + Value intValue = const Value.absent(), + }) => StoreEntityData( + id: id ?? this.id, + stringValue: stringValue.present ? stringValue.value : this.stringValue, + intValue: intValue.present ? intValue.value : this.intValue, + ); + StoreEntityData copyWithCompanion(StoreEntityCompanion data) { + return StoreEntityData( + id: data.id.present ? data.id.value : this.id, + stringValue: data.stringValue.present + ? data.stringValue.value + : this.stringValue, + intValue: data.intValue.present ? data.intValue.value : this.intValue, + ); + } + + @override + String toString() { + return (StringBuffer('StoreEntityData(') + ..write('id: $id, ') + ..write('stringValue: $stringValue, ') + ..write('intValue: $intValue') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, stringValue, intValue); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is StoreEntityData && + other.id == this.id && + other.stringValue == this.stringValue && + other.intValue == this.intValue); +} + +class StoreEntityCompanion extends UpdateCompanion { + final Value id; + final Value stringValue; + final Value intValue; + const StoreEntityCompanion({ + this.id = const Value.absent(), + this.stringValue = const Value.absent(), + this.intValue = const Value.absent(), + }); + StoreEntityCompanion.insert({ + required int id, + this.stringValue = const Value.absent(), + this.intValue = const Value.absent(), + }) : id = Value(id); + static Insertable custom({ + Expression? id, + Expression? stringValue, + Expression? intValue, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (stringValue != null) 'string_value': stringValue, + if (intValue != null) 'int_value': intValue, + }); + } + + StoreEntityCompanion copyWith({ + Value? id, + Value? stringValue, + Value? intValue, + }) { + return StoreEntityCompanion( + id: id ?? this.id, + stringValue: stringValue ?? this.stringValue, + intValue: intValue ?? this.intValue, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (stringValue.present) { + map['string_value'] = Variable(stringValue.value); + } + if (intValue.present) { + map['int_value'] = Variable(intValue.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('StoreEntityCompanion(') + ..write('id: $id, ') + ..write('stringValue: $stringValue, ') + ..write('intValue: $intValue') + ..write(')')) + .toString(); + } +} + +class DatabaseAtV12 extends GeneratedDatabase { + DatabaseAtV12(QueryExecutor e) : super(e); + late final UserEntity userEntity = UserEntity(this); + late final RemoteAssetEntity remoteAssetEntity = RemoteAssetEntity(this); + late final StackEntity stackEntity = StackEntity(this); + late final LocalAssetEntity localAssetEntity = LocalAssetEntity(this); + late final RemoteAlbumEntity remoteAlbumEntity = RemoteAlbumEntity(this); + late final LocalAlbumEntity localAlbumEntity = LocalAlbumEntity(this); + late final LocalAlbumAssetEntity localAlbumAssetEntity = + LocalAlbumAssetEntity(this); + late final Index idxLocalAssetChecksum = Index( + 'idx_local_asset_checksum', + 'CREATE INDEX IF NOT EXISTS idx_local_asset_checksum ON local_asset_entity (checksum)', + ); + late final Index idxRemoteAssetOwnerChecksum = Index( + 'idx_remote_asset_owner_checksum', + 'CREATE INDEX IF NOT EXISTS idx_remote_asset_owner_checksum ON remote_asset_entity (owner_id, checksum)', + ); + late final Index uQRemoteAssetsOwnerChecksum = Index( + 'UQ_remote_assets_owner_checksum', + 'CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_checksum ON remote_asset_entity (owner_id, checksum) WHERE(library_id IS NULL)', + ); + late final Index uQRemoteAssetsOwnerLibraryChecksum = Index( + 'UQ_remote_assets_owner_library_checksum', + 'CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_library_checksum ON remote_asset_entity (owner_id, library_id, checksum) WHERE(library_id IS NOT NULL)', + ); + late final Index idxRemoteAssetChecksum = Index( + 'idx_remote_asset_checksum', + 'CREATE INDEX IF NOT EXISTS idx_remote_asset_checksum ON remote_asset_entity (checksum)', + ); + late final AuthUserEntity authUserEntity = AuthUserEntity(this); + late final UserMetadataEntity userMetadataEntity = UserMetadataEntity(this); + late final PartnerEntity partnerEntity = PartnerEntity(this); + late final RemoteExifEntity remoteExifEntity = RemoteExifEntity(this); + late final RemoteAlbumAssetEntity remoteAlbumAssetEntity = + RemoteAlbumAssetEntity(this); + late final RemoteAlbumUserEntity remoteAlbumUserEntity = + RemoteAlbumUserEntity(this); + late final MemoryEntity memoryEntity = MemoryEntity(this); + late final MemoryAssetEntity memoryAssetEntity = MemoryAssetEntity(this); + late final PersonEntity personEntity = PersonEntity(this); + late final AssetFaceEntity assetFaceEntity = AssetFaceEntity(this); + late final StoreEntity storeEntity = StoreEntity(this); + late final Index idxLatLng = Index( + 'idx_lat_lng', + 'CREATE INDEX IF NOT EXISTS idx_lat_lng ON remote_exif_entity (latitude, longitude)', + ); + @override + Iterable> get allTables => + allSchemaEntities.whereType>(); + @override + List get allSchemaEntities => [ + userEntity, + remoteAssetEntity, + stackEntity, + localAssetEntity, + remoteAlbumEntity, + localAlbumEntity, + localAlbumAssetEntity, + idxLocalAssetChecksum, + idxRemoteAssetOwnerChecksum, + uQRemoteAssetsOwnerChecksum, + uQRemoteAssetsOwnerLibraryChecksum, + idxRemoteAssetChecksum, + authUserEntity, + userMetadataEntity, + partnerEntity, + remoteExifEntity, + remoteAlbumAssetEntity, + remoteAlbumUserEntity, + memoryEntity, + memoryAssetEntity, + personEntity, + assetFaceEntity, + storeEntity, + idxLatLng, + ]; + @override + int get schemaVersion => 12; + @override + DriftDatabaseOptions get options => + const DriftDatabaseOptions(storeDateTimeAsText: true); +} diff --git a/mobile/test/fixtures/user.stub.dart b/mobile/test/fixtures/user.stub.dart index 369e62440d..2ba7177f89 100644 --- a/mobile/test/fixtures/user.stub.dart +++ b/mobile/test/fixtures/user.stub.dart @@ -1,5 +1,4 @@ import 'package:immich_mobile/domain/models/user.model.dart'; -import 'package:immich_mobile/domain/models/user_metadata.model.dart'; abstract final class UserStub { const UserStub._(); diff --git a/mobile/test/infrastructure/repositories/sync_api_repository_test.dart b/mobile/test/infrastructure/repositories/sync_api_repository_test.dart index 7ce6da3c85..467e19bf3f 100644 --- a/mobile/test/infrastructure/repositories/sync_api_repository_test.dart +++ b/mobile/test/infrastructure/repositories/sync_api_repository_test.dart @@ -4,12 +4,15 @@ import 'dart:convert'; import 'package:flutter_test/flutter_test.dart'; import 'package:http/http.dart' as http; import 'package:immich_mobile/domain/models/sync_event.model.dart'; +import 'package:immich_mobile/domain/services/store.service.dart'; +import 'package:immich_mobile/infrastructure/repositories/store.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/sync_api.repository.dart'; import 'package:mocktail/mocktail.dart'; import 'package:openapi/api.dart'; import '../../api.mocks.dart'; import '../../service.mocks.dart'; +import '../../test_utils.dart'; class MockHttpClient extends Mock implements http.Client {} @@ -33,6 +36,10 @@ void main() { late StreamController> responseStreamController; late int testBatchSize = 3; + setUpAll(() async { + await StoreService.init(storeRepository: IsarStoreRepository(await TestUtils.initIsar())); + }); + setUp(() { mockApiService = MockApiService(); mockApiClient = MockApiClient(); diff --git a/mobile/test/modules/utils/migration_test.dart b/mobile/test/modules/utils/migration_test.dart new file mode 100644 index 0000000000..08ab1204a6 --- /dev/null +++ b/mobile/test/modules/utils/migration_test.dart @@ -0,0 +1,131 @@ +import 'package:drift/drift.dart' hide isNull; +import 'package:drift/native.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:immich_mobile/domain/models/store.model.dart'; +import 'package:immich_mobile/domain/services/store.service.dart'; +import 'package:immich_mobile/entities/store.entity.dart'; +import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/store.repository.dart'; +import 'package:immich_mobile/infrastructure/repositories/sync_stream.repository.dart'; +import 'package:immich_mobile/utils/migration.dart'; +import 'package:mocktail/mocktail.dart'; + +import '../../infrastructure/repository.mock.dart'; + +void main() { + late Drift db; + late SyncStreamRepository mockSyncStreamRepository; + + setUpAll(() async { + db = Drift(DatabaseConnection(NativeDatabase.memory(), closeStreamsSynchronously: true)); + await StoreService.init(storeRepository: DriftStoreRepository(db)); + mockSyncStreamRepository = MockSyncStreamRepository(); + when(() => mockSyncStreamRepository.reset()).thenAnswer((_) async => {}); + }); + + tearDown(() async { + await Store.clear(); + }); + + group('handleBetaMigration Tests', () { + group("version < 15", () { + test('already on new timeline', () async { + await Store.put(StoreKey.betaTimeline, true); + + await handleBetaMigration(14, false, mockSyncStreamRepository); + + expect(Store.tryGet(StoreKey.betaTimeline), true); + expect(Store.tryGet(StoreKey.needBetaMigration), false); + }); + + test('already on old timeline', () async { + await Store.put(StoreKey.betaTimeline, false); + + await handleBetaMigration(14, false, mockSyncStreamRepository); + + expect(Store.tryGet(StoreKey.needBetaMigration), true); + }); + + test('fresh install', () async { + await Store.delete(StoreKey.betaTimeline); + await handleBetaMigration(14, true, mockSyncStreamRepository); + + expect(Store.tryGet(StoreKey.betaTimeline), true); + expect(Store.tryGet(StoreKey.needBetaMigration), false); + }); + }); + + group("version == 15", () { + test('already on new timeline', () async { + await Store.put(StoreKey.betaTimeline, true); + + await handleBetaMigration(15, false, mockSyncStreamRepository); + + expect(Store.tryGet(StoreKey.betaTimeline), true); + expect(Store.tryGet(StoreKey.needBetaMigration), false); + }); + + test('already on old timeline', () async { + await Store.put(StoreKey.betaTimeline, false); + + await handleBetaMigration(15, false, mockSyncStreamRepository); + + expect(Store.tryGet(StoreKey.needBetaMigration), true); + }); + + test('fresh install', () async { + await Store.delete(StoreKey.betaTimeline); + await handleBetaMigration(15, true, mockSyncStreamRepository); + + expect(Store.tryGet(StoreKey.betaTimeline), true); + expect(Store.tryGet(StoreKey.needBetaMigration), false); + }); + }); + + group("version > 15", () { + test('already on new timeline', () async { + await Store.put(StoreKey.betaTimeline, true); + + await handleBetaMigration(16, false, mockSyncStreamRepository); + + expect(Store.tryGet(StoreKey.betaTimeline), true); + expect(Store.tryGet(StoreKey.needBetaMigration), false); + }); + + test('already on old timeline', () async { + await Store.put(StoreKey.betaTimeline, false); + + await handleBetaMigration(16, false, mockSyncStreamRepository); + + expect(Store.tryGet(StoreKey.betaTimeline), false); + expect(Store.tryGet(StoreKey.needBetaMigration), false); + }); + + test('fresh install', () async { + await Store.delete(StoreKey.betaTimeline); + await handleBetaMigration(16, true, mockSyncStreamRepository); + + expect(Store.tryGet(StoreKey.betaTimeline), true); + expect(Store.tryGet(StoreKey.needBetaMigration), false); + }); + }); + }); + + group('sync reset tests', () { + test('version < 16', () async { + await Store.put(StoreKey.shouldResetSync, false); + + await handleBetaMigration(15, false, mockSyncStreamRepository); + + expect(Store.tryGet(StoreKey.shouldResetSync), true); + }); + + test('version >= 16', () async { + await Store.put(StoreKey.shouldResetSync, false); + + await handleBetaMigration(16, false, mockSyncStreamRepository); + + expect(Store.tryGet(StoreKey.shouldResetSync), false); + }); + }); +} diff --git a/mobile/test/modules/utils/throttler_test.dart b/mobile/test/modules/utils/throttler_test.dart index ba5d542fe6..1757826daf 100644 --- a/mobile/test/modules/utils/throttler_test.dart +++ b/mobile/test/modules/utils/throttler_test.dart @@ -1,6 +1,6 @@ -import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:immich_mobile/utils/throttle.dart'; +import 'package:immich_mobile/utils/debug_print.dart'; class _Counter { int _count = 0; @@ -8,7 +8,7 @@ class _Counter { int get count => _count; void increment() { - debugPrint("Counter inside increment: $count"); + dPrint(() => "Counter inside increment: $count"); _count = _count + 1; } } diff --git a/mobile/test/utils/action_button_utils_test.dart b/mobile/test/utils/action_button_utils_test.dart index 3cb77c0b33..274176ae88 100644 --- a/mobile/test/utils/action_button_utils_test.dart +++ b/mobile/test/utils/action_button_utils_test.dart @@ -81,6 +81,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -110,6 +112,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -124,6 +128,8 @@ void main() { isTrashEnabled: true, isInLockedView: true, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -141,6 +147,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -156,6 +164,8 @@ void main() { isTrashEnabled: true, isInLockedView: true, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -171,6 +181,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -188,6 +200,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -203,6 +217,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -218,6 +234,8 @@ void main() { isTrashEnabled: true, isInLockedView: true, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -233,6 +251,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -248,6 +268,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -265,6 +287,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -280,6 +304,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -295,6 +321,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -312,6 +340,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -327,6 +357,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -342,6 +374,8 @@ void main() { isTrashEnabled: true, isInLockedView: true, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -359,6 +393,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -374,6 +410,8 @@ void main() { isTrashEnabled: false, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -391,6 +429,8 @@ void main() { isTrashEnabled: false, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -406,6 +446,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -423,6 +465,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -440,6 +484,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -457,6 +503,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -472,11 +520,29 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); expect(ActionButtonType.deleteLocal.shouldShow(context), isFalse); }); + + test('should show when asset is merged', () { + final context = ActionButtonContext( + asset: mergedAsset, + isOwner: true, + isArchived: false, + isTrashEnabled: true, + isInLockedView: false, + currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, + source: ActionSource.timeline, + ); + + expect(ActionButtonType.deleteLocal.shouldShow(context), isTrue); + }); }); group('upload button', () { @@ -489,6 +555,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -506,6 +574,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: album, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -520,6 +590,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -537,6 +609,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: album, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -552,6 +626,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: album, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -567,6 +643,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: album, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -581,12 +659,101 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); expect(ActionButtonType.likeActivity.shouldShow(context), isFalse); }); }); + + group('advancedTroubleshooting button', () { + test('should show when in advanced troubleshooting mode', () { + final context = ActionButtonContext( + asset: mergedAsset, + isOwner: true, + isArchived: false, + isTrashEnabled: true, + isInLockedView: false, + currentAlbum: null, + advancedTroubleshooting: true, + isStacked: false, + source: ActionSource.timeline, + ); + + expect(ActionButtonType.advancedInfo.shouldShow(context), isTrue); + }); + + test('should not show when not in advanced troubleshooting mode', () { + final context = ActionButtonContext( + asset: mergedAsset, + isOwner: true, + isArchived: false, + isTrashEnabled: true, + isInLockedView: false, + currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, + source: ActionSource.timeline, + ); + + expect(ActionButtonType.advancedInfo.shouldShow(context), isFalse); + }); + }); + }); + + group('unstack button', () { + test('should show when owner, not locked, has remote, and is stacked', () { + final remoteAsset = createRemoteAsset(); + final context = ActionButtonContext( + asset: remoteAsset, + isOwner: true, + isArchived: false, + isTrashEnabled: true, + isInLockedView: false, + currentAlbum: null, + advancedTroubleshooting: false, + isStacked: true, + source: ActionSource.timeline, + ); + + expect(ActionButtonType.unstack.shouldShow(context), isTrue); + }); + + test('should not show when not stacked', () { + final remoteAsset = createRemoteAsset(); + final context = ActionButtonContext( + asset: remoteAsset, + isOwner: true, + isArchived: false, + isTrashEnabled: true, + isInLockedView: false, + currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, + source: ActionSource.timeline, + ); + + expect(ActionButtonType.unstack.shouldShow(context), isFalse); + }); + + test('should not show when not owner', () { + final remoteAsset = createRemoteAsset(); + final context = ActionButtonContext( + asset: remoteAsset, + isOwner: false, + isArchived: true, + isTrashEnabled: true, + isInLockedView: false, + currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, + source: ActionSource.timeline, + ); + + expect(ActionButtonType.unstack.shouldShow(context), isFalse); + }); }); group('ActionButtonType.buildButton', () { @@ -602,6 +769,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); }); @@ -617,6 +786,23 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: album, + advancedTroubleshooting: false, + isStacked: false, + source: ActionSource.timeline, + ); + final widget = buttonType.buildButton(contextWithAlbum); + expect(widget, isA()); + } else if (buttonType == ActionButtonType.unstack) { + final album = createRemoteAlbum(); + final contextWithAlbum = ActionButtonContext( + asset: asset, + isOwner: true, + isArchived: false, + isTrashEnabled: true, + isInLockedView: false, + currentAlbum: album, + advancedTroubleshooting: false, + isStacked: true, source: ActionSource.timeline, ); final widget = buttonType.buildButton(contextWithAlbum); @@ -639,6 +825,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -658,6 +846,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: album, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -675,6 +865,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -693,6 +885,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); @@ -705,6 +899,8 @@ void main() { isTrashEnabled: true, isInLockedView: false, currentAlbum: null, + advancedTroubleshooting: false, + isStacked: false, source: ActionSource.timeline, ); diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index 35da672e01..f3cac6288d 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -2504,7 +2504,8 @@ "description": "This endpoint requires the `asset.download` permission." }, "put": { - "description": "Replace the asset with new file, without changing its id. This endpoint requires the `asset.replace` permission.", + "deprecated": true, + "description": "This property was deprecated in v1.142.0. Replace the asset with new file, without changing its id. This endpoint requires the `asset.replace` permission.", "operationId": "replaceAsset", "parameters": [ { @@ -2566,12 +2567,14 @@ "api_key": [] } ], - "summary": "replaceAsset", + "summary": "Replace the asset with new file, without changing its id", "tags": [ - "Assets" + "Assets", + "Deprecated" ], "x-immich-lifecycle": { - "addedAt": "v1.106.0" + "addedAt": "v1.106.0", + "deprecatedAt": "v1.142.0" }, "x-immich-permission": "asset.replace" } @@ -8903,6 +8906,15 @@ "$ref": "#/components/schemas/AssetVisibility" } }, + { + "name": "withCoordinates", + "required": false, + "in": "query", + "description": "Include location data in the response", + "schema": { + "type": "boolean" + } + }, { "name": "withPartners", "required": false, @@ -9048,6 +9060,15 @@ "$ref": "#/components/schemas/AssetVisibility" } }, + { + "name": "withCoordinates", + "required": false, + "in": "query", + "description": "Include location data in the response", + "schema": { + "type": "boolean" + } + }, { "name": "withPartners", "required": false, @@ -9845,7 +9866,7 @@ "info": { "title": "Immich", "description": "Immich API", - "version": "1.141.1", + "version": "2.1.0", "contact": {} }, "tags": [], @@ -10083,6 +10104,12 @@ }, "type": "array" }, + "contributorCounts": { + "items": { + "$ref": "#/components/schemas/ContributorCountResponseDto" + }, + "type": "array" + }, "createdAt": { "format": "date-time", "type": "string" @@ -11458,6 +11485,21 @@ ], "type": "string" }, + "ContributorCountResponseDto": { + "properties": { + "assetCount": { + "type": "integer" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "assetCount", + "userId" + ], + "type": "object" + }, "CreateAlbumDto": { "properties": { "albumName": { @@ -12246,6 +12288,25 @@ ], "type": "object" }, + "MachineLearningAvailabilityChecksDto": { + "properties": { + "enabled": { + "type": "boolean" + }, + "interval": { + "type": "number" + }, + "timeout": { + "type": "number" + } + }, + "required": [ + "enabled", + "interval", + "timeout" + ], + "type": "object" + }, "ManualJobName": { "enum": [ "person-cleanup", @@ -12788,6 +12849,8 @@ "JobFailed", "BackupFailed", "SystemMessage", + "AlbumInvite", + "AlbumUpdate", "Custom" ], "type": "string" @@ -16383,6 +16446,9 @@ }, "SystemConfigMachineLearningDto": { "properties": { + "availabilityChecks": { + "$ref": "#/components/schemas/MachineLearningAvailabilityChecksDto" + }, "clip": { "$ref": "#/components/schemas/CLIPConfig" }, @@ -16395,11 +16461,6 @@ "facialRecognition": { "$ref": "#/components/schemas/FacialRecognitionConfig" }, - "url": { - "deprecated": true, - "description": "This property was deprecated in v1.122.0", - "type": "string" - }, "urls": { "format": "uri", "items": { @@ -16411,6 +16472,7 @@ } }, "required": [ + "availabilityChecks", "clip", "duplicateDetection", "enabled", @@ -17075,6 +17137,14 @@ }, "type": "array" }, + "latitude": { + "description": "Array of latitude coordinates extracted from EXIF GPS data", + "items": { + "nullable": true, + "type": "number" + }, + "type": "array" + }, "livePhotoVideoId": { "description": "Array of live photo video asset IDs (null for non-live photos)", "items": { @@ -17090,6 +17160,14 @@ }, "type": "array" }, + "longitude": { + "description": "Array of longitude coordinates extracted from EXIF GPS data", + "items": { + "nullable": true, + "type": "number" + }, + "type": "array" + }, "ownerId": { "description": "Array of owner IDs for each asset", "items": { diff --git a/open-api/typescript-sdk/.nvmrc b/open-api/typescript-sdk/.nvmrc index e2228113dd..442c7587a9 100644 --- a/open-api/typescript-sdk/.nvmrc +++ b/open-api/typescript-sdk/.nvmrc @@ -1 +1 @@ -22.19.0 +22.20.0 diff --git a/open-api/typescript-sdk/package.json b/open-api/typescript-sdk/package.json index a44cd60d5b..5be13572e2 100644 --- a/open-api/typescript-sdk/package.json +++ b/open-api/typescript-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@immich/sdk", - "version": "1.141.1", + "version": "2.1.0", "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.18.0", + "@types/node": "^22.18.8", "typescript": "^5.3.3" }, "repository": { @@ -28,6 +28,6 @@ "directory": "open-api/typescript-sdk" }, "volta": { - "node": "22.19.0" + "node": "22.20.0" } } diff --git a/open-api/typescript-sdk/src/fetch-client.ts b/open-api/typescript-sdk/src/fetch-client.ts index 8b10bf2995..fd9beba217 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.141.1 + * 2.1.0 * DO NOT MODIFY - This file has been generated using oazapfts. * See https://www.npmjs.com/package/oazapfts */ @@ -356,12 +356,17 @@ export type AssetResponseDto = { updatedAt: string; visibility: AssetVisibility; }; +export type ContributorCountResponseDto = { + assetCount: number; + userId: string; +}; export type AlbumResponseDto = { albumName: string; albumThumbnailAssetId: string | null; albumUsers: AlbumUserResponseDto[]; assetCount: number; assets: AssetResponseDto[]; + contributorCounts?: ContributorCountResponseDto[]; createdAt: string; description: string; endDate?: string; @@ -1383,6 +1388,11 @@ export type SystemConfigLoggingDto = { enabled: boolean; level: LogLevel; }; +export type MachineLearningAvailabilityChecksDto = { + enabled: boolean; + interval: number; + timeout: number; +}; export type ClipConfig = { enabled: boolean; modelName: string; @@ -1399,12 +1409,11 @@ export type FacialRecognitionConfig = { modelName: string; }; export type SystemConfigMachineLearningDto = { + availabilityChecks: MachineLearningAvailabilityChecksDto; clip: ClipConfig; duplicateDetection: DuplicateDetectionConfig; enabled: boolean; facialRecognition: FacialRecognitionConfig; - /** This property was deprecated in v1.122.0 */ - url?: string; urls: string[]; }; export type SystemConfigMapDto = { @@ -1561,10 +1570,14 @@ export type TimeBucketAssetResponseDto = { isImage: boolean[]; /** Array indicating whether each asset is in the trash */ isTrashed: boolean[]; + /** Array of latitude coordinates extracted from EXIF GPS data */ + latitude?: (number | null)[]; /** Array of live photo video asset IDs (null for non-live photos) */ livePhotoVideoId: (string | null)[]; /** Array of UTC offset hours at the time each photo was taken. Positive values are east of UTC, negative values are west of UTC. Values may be fractional (e.g., 5.5 for +05:30, -9.75 for -09:45). Applying this offset to 'fileCreatedAt' will give you the time the photo was taken from the photographer's perspective. */ localOffsetHours: number[]; + /** Array of longitude coordinates extracted from EXIF GPS data */ + longitude?: (number | null)[]; /** Array of owner IDs for each asset */ ownerId: string[]; /** Array of projection types for 360° content (e.g., "EQUIRECTANGULAR", "CUBEFACE", "CYLINDRICAL") */ @@ -2364,7 +2377,7 @@ export function downloadAsset({ id, key, slug }: { })); } /** - * replaceAsset + * Replace the asset with new file, without changing its id */ export function replaceAsset({ id, key, slug, assetMediaReplaceDto }: { id: string; @@ -4295,7 +4308,7 @@ export function tagAssets({ id, bulkIdsDto }: { /** * This endpoint requires the `asset.read` permission. */ -export function getTimeBucket({ albumId, isFavorite, isTrashed, key, order, personId, slug, tagId, timeBucket, userId, visibility, withPartners, withStacked }: { +export function getTimeBucket({ albumId, isFavorite, isTrashed, key, order, personId, slug, tagId, timeBucket, userId, visibility, withCoordinates, withPartners, withStacked }: { albumId?: string; isFavorite?: boolean; isTrashed?: boolean; @@ -4307,6 +4320,7 @@ export function getTimeBucket({ albumId, isFavorite, isTrashed, key, order, pers timeBucket: string; userId?: string; visibility?: AssetVisibility; + withCoordinates?: boolean; withPartners?: boolean; withStacked?: boolean; }, opts?: Oazapfts.RequestOpts) { @@ -4325,6 +4339,7 @@ export function getTimeBucket({ albumId, isFavorite, isTrashed, key, order, pers timeBucket, userId, visibility, + withCoordinates, withPartners, withStacked }))}`, { @@ -4334,7 +4349,7 @@ export function getTimeBucket({ albumId, isFavorite, isTrashed, key, order, pers /** * This endpoint requires the `asset.read` permission. */ -export function getTimeBuckets({ albumId, isFavorite, isTrashed, key, order, personId, slug, tagId, userId, visibility, withPartners, withStacked }: { +export function getTimeBuckets({ albumId, isFavorite, isTrashed, key, order, personId, slug, tagId, userId, visibility, withCoordinates, withPartners, withStacked }: { albumId?: string; isFavorite?: boolean; isTrashed?: boolean; @@ -4345,6 +4360,7 @@ export function getTimeBuckets({ albumId, isFavorite, isTrashed, key, order, per tagId?: string; userId?: string; visibility?: AssetVisibility; + withCoordinates?: boolean; withPartners?: boolean; withStacked?: boolean; }, opts?: Oazapfts.RequestOpts) { @@ -4362,6 +4378,7 @@ export function getTimeBuckets({ albumId, isFavorite, isTrashed, key, order, per tagId, userId, visibility, + withCoordinates, withPartners, withStacked }))}`, { @@ -4640,6 +4657,8 @@ export enum NotificationType { JobFailed = "JobFailed", BackupFailed = "BackupFailed", SystemMessage = "SystemMessage", + AlbumInvite = "AlbumInvite", + AlbumUpdate = "AlbumUpdate", Custom = "Custom" } export enum UserStatus { diff --git a/package.json b/package.json index a718d7ccd0..415c598179 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "description": "Monorepo for Immich", "private": true, - "packageManager": "pnpm@10.14.0+sha512.ad27a79641b49c3e481a16a805baa71817a04bbe06a38d17e60e2eaee83f6a146c6a688125f5792e48dd5ba30e7da52a5cda4c3992b9ccf333f9ce223af84748", + "packageManager": "pnpm@10.18.1+sha512.77a884a165cbba2d8d1c19e3b4880eee6d2fcabd0d879121e282196b80042351d5eb3ca0935fa599da1dc51265cc68816ad2bddd2a2de5ea9fdf92adbec7cd34", "engines": { "pnpm": ">=10.0.0" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b184f398ff..4a38969b4f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,7 +7,7 @@ settings: overrides: canvas: 2.11.2 - sharp: ^0.34.3 + sharp: ^0.34.4 packageExtensionsChecksum: sha256-DAYr0FTkvKYnvBH4muAER9UE1FVGKhqfRU4/QwA2xPQ= @@ -41,12 +41,9 @@ importers: specifier: ^4.0.8 version: 4.0.8 devDependencies: - '@eslint/eslintrc': - specifier: ^3.1.0 - version: 3.3.1 '@eslint/js': specifier: ^9.8.0 - version: 9.33.0 + version: 9.37.0 '@immich/sdk': specifier: file:../open-api/typescript-sdk version: link:../open-api/typescript-sdk @@ -66,11 +63,11 @@ importers: specifier: ^4.13.1 version: 4.13.4 '@types/node': - specifier: ^22.18.0 - version: 22.18.1 + specifier: ^22.18.8 + version: 22.18.10 '@vitest/coverage-v8': specifier: ^3.0.0 - version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.18.1)(happy-dom@18.0.1)(jiti@2.5.1)(jsdom@26.1.0(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) + version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.18.10)(happy-dom@20.0.0)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) byte-size: specifier: ^9.0.0 version: 9.0.1 @@ -82,19 +79,19 @@ importers: version: 12.1.0 eslint: specifier: ^9.14.0 - version: 9.33.0(jiti@2.5.1) + version: 9.37.0(jiti@2.6.1) eslint-config-prettier: specifier: ^10.1.8 - version: 10.1.8(eslint@9.33.0(jiti@2.5.1)) + version: 10.1.8(eslint@9.37.0(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.1.3 - version: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.33.0(jiti@2.5.1)))(eslint@9.33.0(jiti@2.5.1))(prettier@3.6.2) + version: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.37.0(jiti@2.6.1)))(eslint@9.37.0(jiti@2.6.1))(prettier@3.6.2) eslint-plugin-unicorn: specifier: ^60.0.0 - version: 60.0.0(eslint@9.33.0(jiti@2.5.1)) + version: 60.0.0(eslint@9.37.0(jiti@2.6.1)) globals: specifier: ^16.0.0 - version: 16.3.0 + version: 16.4.0 mock-fs: specifier: ^5.2.0 version: 5.5.0 @@ -103,25 +100,25 @@ importers: version: 3.6.2 prettier-plugin-organize-imports: specifier: ^4.0.0 - version: 4.2.0(prettier@3.6.2)(typescript@5.9.2) + version: 4.3.0(prettier@3.6.2)(typescript@5.9.3) typescript: specifier: ^5.3.3 - version: 5.9.2 + version: 5.9.3 typescript-eslint: specifier: ^8.28.0 - version: 8.39.1(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2) + version: 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) vite: specifier: ^7.0.0 - version: 7.1.2(@types/node@22.18.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + version: 7.1.9(@types/node@22.18.10)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) vite-tsconfig-paths: specifier: ^5.0.0 - version: 5.1.4(typescript@5.9.2)(vite@7.1.2(@types/node@22.18.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) + version: 5.1.4(typescript@5.9.3)(vite@7.1.9(@types/node@22.18.10)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) vitest: specifier: ^3.0.0 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.1)(happy-dom@18.0.1)(jiti@2.5.1)(jsdom@26.1.0(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.10)(happy-dom@20.0.0)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) vitest-fetch-mock: specifier: ^0.4.0 - version: 0.4.5(vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.18.1)(happy-dom@18.0.1)(jiti@2.5.1)(jsdom@26.1.0(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) + version: 0.4.5(vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.18.10)(happy-dom@20.0.0)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) yaml: specifier: ^2.3.1 version: 2.8.1 @@ -129,14 +126,14 @@ importers: docs: dependencies: '@docusaurus/core': - specifier: ~3.8.0 - version: 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) + specifier: ~3.9.0 + version: 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) '@docusaurus/preset-classic': - specifier: ~3.8.0 - version: 3.8.1(@algolia/client-search@5.29.0)(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(@types/react@19.1.12)(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.9.2) + specifier: ~3.9.0 + version: 3.9.1(@algolia/client-search@5.40.0)(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(@types/react@19.2.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.9.3) '@docusaurus/theme-common': - specifier: ~3.8.0 - version: 3.8.1(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ~3.9.0 + version: 3.9.1(@docusaurus/plugin-content-docs@3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mdi/js': specifier: ^7.3.67 version: 7.4.47 @@ -145,22 +142,13 @@ importers: version: 1.6.1 '@mdx-js/react': specifier: ^3.0.0 - version: 3.1.0(@types/react@19.1.12)(react@18.3.1) + version: 3.1.1(@types/react@19.2.2)(react@18.3.1) autoprefixer: specifier: ^10.4.17 version: 10.4.21(postcss@8.5.6) - classnames: - specifier: ^2.3.2 - version: 2.5.1 - clsx: - specifier: ^2.0.0 - version: 2.1.1 docusaurus-lunr-search: specifier: ^3.3.2 - version: 3.6.0(@docusaurus/core@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - docusaurus-preset-openapi: - specifier: ^0.7.5 - version: 0.7.6(@algolia/client-search@5.29.0)(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2))(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(@types/react@19.1.12)(acorn@8.15.0)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1)(search-insights@2.17.3)(typescript@5.9.2) + version: 3.6.0(@docusaurus/core@3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) lunr: specifier: ^2.3.9 version: 2.3.9 @@ -172,7 +160,7 @@ importers: version: 2.4.1(react@18.3.1) raw-loader: specifier: ^4.0.2 - version: 4.0.2(webpack@5.100.2) + version: 4.0.2(webpack@5.102.1) react: specifier: ^18.0.0 version: 18.3.1 @@ -181,35 +169,32 @@ importers: version: 18.3.1(react@18.3.1) tailwindcss: specifier: ^3.2.4 - version: 3.4.17 + version: 3.4.18(yaml@2.8.1) url: specifier: ^0.11.0 version: 0.11.4 devDependencies: '@docusaurus/module-type-aliases': - specifier: ~3.8.0 - version: 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ~3.9.0 + version: 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/tsconfig': specifier: ^3.7.0 - version: 3.8.1 + version: 3.9.1 '@docusaurus/types': specifier: ^3.7.0 - version: 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) prettier: specifier: ^3.2.4 version: 3.6.2 typescript: specifier: ^5.1.6 - version: 5.9.2 + version: 5.9.3 e2e: devDependencies: - '@eslint/eslintrc': - specifier: ^3.1.0 - version: 3.3.1 '@eslint/js': specifier: ^9.8.0 - version: 9.33.0 + version: 9.37.0 '@immich/cli': specifier: file:../cli version: link:../cli @@ -218,7 +203,7 @@ importers: version: link:../open-api/typescript-sdk '@playwright/test': specifier: ^1.44.1 - version: 1.54.2 + version: 1.56.0 '@socket.io/component-emitter': specifier: ^3.1.2 version: 3.1.2 @@ -226,11 +211,11 @@ importers: specifier: ^3.4.2 version: 3.7.1 '@types/node': - specifier: ^22.18.0 - version: 22.18.1 + specifier: ^22.18.8 + version: 22.18.10 '@types/oidc-provider': specifier: ^9.0.0 - version: 9.1.2 + version: 9.5.0 '@types/pg': specifier: ^8.15.1 version: 8.15.5 @@ -240,36 +225,33 @@ importers: '@types/supertest': specifier: ^6.0.2 version: 6.0.3 - '@vitest/coverage-v8': - specifier: ^3.0.0 - version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.18.1)(happy-dom@18.0.1)(jiti@2.5.1)(jsdom@26.1.0(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) eslint: specifier: ^9.14.0 - version: 9.33.0(jiti@2.5.1) + version: 9.37.0(jiti@2.6.1) eslint-config-prettier: specifier: ^10.1.8 - version: 10.1.8(eslint@9.33.0(jiti@2.5.1)) + version: 10.1.8(eslint@9.37.0(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.1.3 - version: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.33.0(jiti@2.5.1)))(eslint@9.33.0(jiti@2.5.1))(prettier@3.6.2) + version: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.37.0(jiti@2.6.1)))(eslint@9.37.0(jiti@2.6.1))(prettier@3.6.2) eslint-plugin-unicorn: specifier: ^60.0.0 - version: 60.0.0(eslint@9.33.0(jiti@2.5.1)) + version: 60.0.0(eslint@9.37.0(jiti@2.6.1)) exiftool-vendored: specifier: ^28.3.1 version: 28.8.0 globals: specifier: ^16.0.0 - version: 16.3.0 + version: 16.4.0 jose: specifier: ^5.6.3 version: 5.10.0 luxon: specifier: ^3.4.4 - version: 3.7.1 + version: 3.7.2 oidc-provider: specifier: ^9.0.0 - version: 9.4.1 + version: 9.5.1 pg: specifier: ^8.11.3 version: 8.16.3 @@ -281,10 +263,10 @@ importers: version: 3.6.2 prettier-plugin-organize-imports: specifier: ^4.0.0 - version: 4.2.0(prettier@3.6.2)(typescript@5.9.2) + version: 4.3.0(prettier@3.6.2)(typescript@5.9.3) sharp: - specifier: ^0.34.3 - version: 0.34.3 + specifier: ^0.34.4 + version: 0.34.4 socket.io-client: specifier: ^4.7.4 version: 4.8.1 @@ -293,16 +275,16 @@ importers: version: 7.1.4 typescript: specifier: ^5.3.3 - version: 5.9.2 + version: 5.9.3 typescript-eslint: specifier: ^8.28.0 - version: 8.39.1(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2) + version: 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) utimes: specifier: ^5.2.1 version: 5.2.1(encoding@0.1.13) vitest: specifier: ^3.0.0 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.1)(happy-dom@18.0.1)(jiti@2.5.1)(jsdom@26.1.0(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.10)(happy-dom@20.0.0)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) open-api/typescript-sdk: dependencies: @@ -311,26 +293,23 @@ importers: version: 1.0.4 devDependencies: '@types/node': - specifier: ^22.18.0 - version: 22.18.1 + specifier: ^22.18.8 + version: 22.18.10 typescript: specifier: ^5.3.3 - version: 5.9.2 + version: 5.9.3 server: dependencies: '@nestjs/bullmq': specifier: ^11.0.1 - version: 11.0.3(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6)(bullmq@5.57.0) + version: 11.0.3(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6)(bullmq@5.61.0) '@nestjs/common': specifier: ^11.0.4 version: 11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/core': specifier: ^11.0.4 version: 11.1.6(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.6)(@nestjs/websockets@11.1.6)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/event-emitter': - specifier: ^3.0.0 - version: 3.0.1(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6) '@nestjs/platform-express': specifier: ^11.0.4 version: 11.1.6(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6) @@ -339,7 +318,7 @@ importers: version: 11.1.6(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.6)(rxjs@7.8.2) '@nestjs/schedule': specifier: ^6.0.0 - version: 6.0.0(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6) + version: 6.0.1(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6) '@nestjs/swagger': specifier: ^11.0.2 version: 11.2.0(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6)(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2) @@ -349,45 +328,42 @@ importers: '@opentelemetry/api': specifier: ^1.9.0 version: 1.9.0 - '@opentelemetry/auto-instrumentations-node': - specifier: ^0.62.0 - version: 0.62.1(@opentelemetry/api@1.9.0)(@opentelemetry/core@2.0.1(@opentelemetry/api@1.9.0))(encoding@0.1.13) '@opentelemetry/context-async-hooks': specifier: ^2.0.0 - version: 2.0.1(@opentelemetry/api@1.9.0) + version: 2.1.0(@opentelemetry/api@1.9.0) '@opentelemetry/exporter-prometheus': - specifier: ^0.203.0 - version: 0.203.0(@opentelemetry/api@1.9.0) + specifier: ^0.206.0 + version: 0.206.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation-http': - specifier: ^0.203.0 - version: 0.203.0(@opentelemetry/api@1.9.0) + specifier: ^0.206.0 + version: 0.206.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation-ioredis': - specifier: ^0.51.0 - version: 0.51.0(@opentelemetry/api@1.9.0) + specifier: ^0.54.0 + version: 0.54.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation-nestjs-core': - specifier: ^0.49.0 - version: 0.49.0(@opentelemetry/api@1.9.0) + specifier: ^0.53.0 + version: 0.53.0(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation-pg': - specifier: ^0.56.0 - version: 0.56.0(@opentelemetry/api@1.9.0) + specifier: ^0.59.0 + version: 0.59.0(@opentelemetry/api@1.9.0) '@opentelemetry/resources': specifier: ^2.0.1 - version: 2.0.1(@opentelemetry/api@1.9.0) + version: 2.1.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-metrics': specifier: ^2.0.1 - version: 2.0.1(@opentelemetry/api@1.9.0) + version: 2.1.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-node': - specifier: ^0.203.0 - version: 0.203.0(@opentelemetry/api@1.9.0) + specifier: ^0.206.0 + version: 0.206.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': specifier: ^1.34.0 - version: 1.36.0 + version: 1.37.0 '@react-email/components': specifier: ^0.5.0 - version: 0.5.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + version: 0.5.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-email/render': specifier: ^1.1.2 - version: 1.2.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + version: 1.3.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@socket.io/redis-adapter': specifier: ^8.3.0 version: 8.3.0(socket.io-adapter@2.5.5) @@ -405,7 +381,7 @@ importers: version: 2.2.0 bullmq: specifier: ^5.51.0 - version: 5.57.0 + version: 5.61.0 chokidar: specifier: ^4.0.3 version: 4.0.3 @@ -425,8 +401,8 @@ importers: specifier: ^1.4.7 version: 1.4.7 cron: - specifier: 4.3.0 - version: 4.3.0 + specifier: 4.3.3 + version: 4.3.3 exiftool-vendored: specifier: ^28.8.0 version: 28.8.0 @@ -450,7 +426,7 @@ importers: version: 7.14.0 ioredis: specifier: ^5.3.2 - version: 5.7.0 + version: 5.8.1 js-yaml: specifier: ^4.1.0 version: 4.1.0 @@ -458,14 +434,14 @@ importers: specifier: 0.28.2 version: 0.28.2 kysely-postgres-js: - specifier: ^2.0.0 - version: 2.0.0(kysely@0.28.2)(postgres@3.4.7) + specifier: ^3.0.0 + version: 3.0.0(kysely@0.28.2)(postgres@3.4.7) lodash: specifier: ^4.17.21 version: 4.17.21 luxon: specifier: ^3.4.2 - version: 3.7.1 + version: 3.7.2 mnemonist: specifier: ^0.40.3 version: 0.40.3 @@ -474,22 +450,22 @@ importers: version: 2.0.2 nest-commander: specifier: ^3.16.0 - version: 3.18.0(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6)(@types/inquirer@8.2.11)(typescript@5.9.2) + version: 3.20.1(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6)(@types/inquirer@8.2.11)(@types/node@22.18.10)(typescript@5.9.3) nestjs-cls: specifier: ^5.0.0 version: 5.4.3(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6)(reflect-metadata@0.2.2)(rxjs@7.8.2) nestjs-kysely: - specifier: ^3.0.0 + specifier: 3.0.0 version: 3.0.0(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6)(kysely@0.28.2)(reflect-metadata@0.2.2) nestjs-otel: specifier: ^7.0.0 version: 7.0.1(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6) nodemailer: specifier: ^7.0.0 - version: 7.0.5 + version: 7.0.9 openid-client: specifier: ^6.3.3 - version: 6.6.4 + version: 6.8.1 pg: specifier: ^8.11.3 version: 8.16.3 @@ -504,13 +480,13 @@ importers: version: 3.4.7 react: specifier: ^19.0.0 - version: 19.1.1 + version: 19.2.0 react-dom: specifier: ^19.0.0 - version: 19.1.1(react@19.1.1) + version: 19.2.0(react@19.2.0) react-email: specifier: ^4.0.0 - version: 4.2.8 + version: 4.3.0 reflect-metadata: specifier: ^0.2.0 version: 0.2.2 @@ -525,28 +501,25 @@ importers: version: 2.17.0 semver: specifier: ^7.6.2 - version: 7.7.2 + version: 7.7.3 sharp: - specifier: ^0.34.3 - version: 0.34.3 + specifier: ^0.34.4 + version: 0.34.4 sirv: specifier: ^3.0.0 - version: 3.0.1 + version: 3.0.2 socket.io: specifier: ^4.8.1 version: 4.8.1 tailwindcss-preset-email: specifier: ^1.4.0 - version: 1.4.0(tailwindcss@3.4.17) + version: 1.4.0(tailwindcss@3.4.18(yaml@2.8.1)) thumbhash: specifier: ^0.1.1 version: 0.1.1 - typeorm: - specifier: ^0.3.17 - version: 0.3.25(ioredis@5.7.0)(pg@8.16.3)(reflect-metadata@0.2.2) ua-parser-js: specifier: ^2.0.0 - version: 2.0.4(encoding@0.1.13) + version: 2.0.5 uuid: specifier: ^11.1.0 version: 11.1.0 @@ -554,30 +527,21 @@ importers: specifier: ^13.12.0 version: 13.15.15 devDependencies: - '@eslint/eslintrc': - specifier: ^3.1.0 - version: 3.3.1 '@eslint/js': specifier: ^9.8.0 - version: 9.33.0 + version: 9.37.0 '@nestjs/cli': specifier: ^11.0.2 - version: 11.0.10(@swc/core@1.13.3(@swc/helpers@0.5.17))(@types/node@22.18.1) + version: 11.0.10(@swc/core@1.13.5(@swc/helpers@0.5.17))(@types/node@22.18.10) '@nestjs/schematics': specifier: ^11.0.0 - version: 11.0.7(chokidar@4.0.3)(typescript@5.9.2) + version: 11.0.8(chokidar@4.0.3)(typescript@5.9.3) '@nestjs/testing': specifier: ^11.0.4 version: 11.1.6(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6)(@nestjs/platform-express@11.1.6) '@swc/core': specifier: ^1.4.14 - version: 1.13.3(@swc/helpers@0.5.17) - '@testcontainers/postgresql': - specifier: ^11.0.0 - version: 11.5.1 - '@testcontainers/redis': - specifier: ^11.0.0 - version: 11.5.1 + version: 1.13.5(@swc/helpers@0.5.17) '@types/archiver': specifier: ^6.0.0 version: 6.0.3 @@ -618,11 +582,11 @@ importers: specifier: ^2.0.0 version: 2.0.0 '@types/node': - specifier: ^22.18.0 - version: 22.18.1 + specifier: ^22.18.8 + version: 22.18.10 '@types/nodemailer': - specifier: ^6.4.14 - version: 6.4.17 + specifier: ^7.0.0 + version: 7.0.2 '@types/picomatch': specifier: ^4.0.0 version: 4.0.2 @@ -631,13 +595,13 @@ importers: version: 6.0.5 '@types/react': specifier: ^19.0.0 - version: 19.1.12 + version: 19.2.2 '@types/sanitize-html': specifier: ^2.13.0 version: 2.16.0 '@types/semver': specifier: ^7.5.8 - version: 7.7.0 + version: 7.7.1 '@types/supertest': specifier: ^6.0.0 version: 6.0.3 @@ -646,37 +610,31 @@ importers: version: 0.7.39 '@types/validator': specifier: ^13.15.2 - version: 13.15.2 + version: 13.15.3 '@vitest/coverage-v8': specifier: ^3.0.0 - version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.18.1)(happy-dom@18.0.1)(jiti@2.5.1)(jsdom@26.1.0(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) - canvas: - specifier: 2.11.2 - version: 2.11.2(encoding@0.1.13) + version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.18.10)(happy-dom@20.0.0)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) eslint: specifier: ^9.14.0 - version: 9.33.0(jiti@2.5.1) + version: 9.37.0(jiti@2.6.1) eslint-config-prettier: specifier: ^10.1.8 - version: 10.1.8(eslint@9.33.0(jiti@2.5.1)) + version: 10.1.8(eslint@9.37.0(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.1.3 - version: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.33.0(jiti@2.5.1)))(eslint@9.33.0(jiti@2.5.1))(prettier@3.6.2) + version: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.37.0(jiti@2.6.1)))(eslint@9.37.0(jiti@2.6.1))(prettier@3.6.2) eslint-plugin-unicorn: specifier: ^60.0.0 - version: 60.0.0(eslint@9.33.0(jiti@2.5.1)) + version: 60.0.0(eslint@9.37.0(jiti@2.6.1)) globals: specifier: ^16.0.0 - version: 16.3.0 + version: 16.4.0 mock-fs: specifier: ^5.2.0 version: 5.5.0 - node-addon-api: - specifier: ^8.3.1 - version: 8.5.0 node-gyp: specifier: ^11.2.0 - version: 11.3.0 + version: 11.4.2 pngjs: specifier: ^7.0.0 version: 7.0.0 @@ -685,58 +643,46 @@ importers: version: 3.6.2 prettier-plugin-organize-imports: specifier: ^4.0.0 - version: 4.2.0(prettier@3.6.2)(typescript@5.9.2) - rimraf: - specifier: ^6.0.0 - version: 6.0.1 - source-map-support: - specifier: ^0.5.21 - version: 0.5.21 + version: 4.3.0(prettier@3.6.2)(typescript@5.9.3) sql-formatter: specifier: ^15.0.0 - version: 15.6.6 + version: 15.6.10 supertest: specifier: ^7.1.0 version: 7.1.4 tailwindcss: specifier: ^3.4.0 - version: 3.4.17 + version: 3.4.18(yaml@2.8.1) testcontainers: specifier: ^11.0.0 - version: 11.5.1 - tsconfig-paths: - specifier: ^4.2.0 - version: 4.2.0 + version: 11.7.1 typescript: specifier: ^5.9.2 - version: 5.9.2 + version: 5.9.3 typescript-eslint: specifier: ^8.28.0 - version: 8.39.1(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2) + version: 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) unplugin-swc: specifier: ^1.4.5 - version: 1.5.5(@swc/core@1.13.3(@swc/helpers@0.5.17))(rollup@4.46.3) - utimes: - specifier: ^5.2.1 - version: 5.2.1(encoding@0.1.13) + version: 1.5.7(@swc/core@1.13.5(@swc/helpers@0.5.17))(rollup@4.52.4) vite-tsconfig-paths: specifier: ^5.0.0 - version: 5.1.4(typescript@5.9.2)(vite@7.1.2(@types/node@22.18.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) + version: 5.1.4(typescript@5.9.3)(vite@7.1.9(@types/node@22.18.10)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) vitest: specifier: ^3.0.0 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.1)(happy-dom@18.0.1)(jiti@2.5.1)(jsdom@26.1.0(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.10)(happy-dom@20.0.0)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) web: dependencies: '@formatjs/icu-messageformat-parser': specifier: ^2.9.8 - version: 2.11.2 + version: 2.11.3 '@immich/sdk': specifier: file:../open-api/typescript-sdk version: link:../open-api/typescript-sdk '@immich/ui': - specifier: ^0.24.0 - version: 0.24.1(@internationalized/date@3.8.2)(svelte@5.35.5) + specifier: ^0.34.0 + version: 0.34.2(@internationalized/date@3.8.2)(svelte@5.39.11) '@mapbox/mapbox-gl-rtl-text': specifier: 0.2.3 version: 0.2.3(mapbox-gl@1.13.3) @@ -745,28 +691,28 @@ importers: version: 7.4.47 '@photo-sphere-viewer/core': specifier: ^5.11.5 - version: 5.13.4 + version: 5.14.0 '@photo-sphere-viewer/equirectangular-video-adapter': specifier: ^5.11.5 - version: 5.13.4(@photo-sphere-viewer/core@5.13.4)(@photo-sphere-viewer/video-plugin@5.13.4(@photo-sphere-viewer/core@5.13.4)) + version: 5.14.0(@photo-sphere-viewer/core@5.14.0)(@photo-sphere-viewer/video-plugin@5.14.0(@photo-sphere-viewer/core@5.14.0)) '@photo-sphere-viewer/resolution-plugin': specifier: ^5.11.5 - version: 5.13.4(@photo-sphere-viewer/core@5.13.4)(@photo-sphere-viewer/settings-plugin@5.13.4(@photo-sphere-viewer/core@5.13.4)) + version: 5.14.0(@photo-sphere-viewer/core@5.14.0)(@photo-sphere-viewer/settings-plugin@5.14.0(@photo-sphere-viewer/core@5.14.0)) '@photo-sphere-viewer/settings-plugin': specifier: ^5.11.5 - version: 5.13.4(@photo-sphere-viewer/core@5.13.4) + version: 5.14.0(@photo-sphere-viewer/core@5.14.0) '@photo-sphere-viewer/video-plugin': specifier: ^5.11.5 - version: 5.13.4(@photo-sphere-viewer/core@5.13.4) + version: 5.14.0(@photo-sphere-viewer/core@5.14.0) '@types/geojson': specifier: ^7946.0.16 version: 7946.0.16 '@zoom-image/core': specifier: ^0.41.0 - version: 0.41.0 + version: 0.41.3 '@zoom-image/svelte': specifier: ^0.3.0 - version: 0.3.4(svelte@5.35.5) + version: 0.3.7(svelte@5.39.11) async-mutex: specifier: ^0.5.0 version: 0.5.0 @@ -786,11 +732,11 @@ importers: specifier: ^4.7.8 version: 4.7.8 happy-dom: - specifier: ^18.0.1 - version: 18.0.1 + specifier: ^20.0.0 + version: 20.0.0 intl-messageformat: specifier: ^10.7.11 - version: 10.7.16 + version: 10.7.17 justified-layout: specifier: ^4.1.0 version: 4.1.0 @@ -799,31 +745,34 @@ importers: version: 4.17.21 luxon: specifier: ^3.4.4 - version: 3.7.1 + version: 3.7.2 maplibre-gl: specifier: ^5.6.2 - version: 5.6.2 + version: 5.8.0 pmtiles: specifier: ^4.3.0 version: 4.3.0 qrcode: specifier: ^1.5.4 version: 1.5.4 + simple-icons: + specifier: ^15.15.0 + version: 15.16.1 socket.io-client: specifier: ~4.8.0 version: 4.8.1 svelte-gestures: - specifier: ^5.1.3 - version: 5.1.4 + specifier: ^5.2.2 + version: 5.2.2 svelte-i18n: specifier: ^4.0.1 - version: 4.0.1(svelte@5.35.5) + version: 4.0.1(svelte@5.39.11) svelte-maplibre: specifier: ^1.2.0 - version: 1.2.0(svelte@5.35.5) + version: 1.2.1(svelte@5.39.11) svelte-persisted-store: specifier: ^0.12.0 - version: 0.12.0(svelte@5.35.5) + version: 0.12.0(svelte@5.39.11) tabbable: specifier: ^6.2.0 version: 6.2.0 @@ -831,42 +780,39 @@ importers: specifier: ^0.1.1 version: 0.1.1 devDependencies: - '@eslint/eslintrc': - specifier: ^3.1.0 - version: 3.3.1 '@eslint/js': - specifier: ^9.18.0 - version: 9.33.0 + specifier: ^9.36.0 + version: 9.37.0 '@faker-js/faker': - specifier: ^9.3.0 - version: 9.9.0 + specifier: ^10.0.0 + version: 10.0.0 '@koddsson/eslint-plugin-tscompat': specifier: ^0.2.0 - version: 0.2.0(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2) + version: 0.2.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) '@socket.io/component-emitter': specifier: ^3.1.0 version: 3.1.2 '@sveltejs/adapter-static': specifier: ^3.0.8 - version: 3.0.9(@sveltejs/kit@2.27.1(@sveltejs/vite-plugin-svelte@6.1.2(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)))(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))) + version: 3.0.10(@sveltejs/kit@2.46.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)))(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))) '@sveltejs/enhanced-img': specifier: ^0.8.0 - version: 0.8.1(@sveltejs/vite-plugin-svelte@6.1.2(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)))(rollup@4.46.3)(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) + version: 0.8.4(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)))(rollup@4.52.4)(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) '@sveltejs/kit': specifier: ^2.27.1 - version: 2.27.1(@sveltejs/vite-plugin-svelte@6.1.2(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)))(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) + version: 2.46.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)))(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) '@sveltejs/vite-plugin-svelte': - specifier: 6.1.2 - version: 6.1.2(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) + specifier: 6.2.1 + version: 6.2.1(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) '@tailwindcss/vite': specifier: ^4.1.7 - version: 4.1.12(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) + version: 4.1.14(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) '@testing-library/jest-dom': specifier: ^6.4.2 - version: 6.7.0 + version: 6.9.1 '@testing-library/svelte': specifier: ^5.2.8 - version: 5.2.8(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.3.0)(happy-dom@18.0.1)(jiti@2.5.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) + version: 5.2.8(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.7.1)(happy-dom@20.0.0)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) '@testing-library/user-event': specifier: ^14.5.2 version: 14.6.1(@testing-library/dom@10.4.0) @@ -890,85 +836,80 @@ importers: version: 1.5.5 '@vitest/coverage-v8': specifier: ^3.0.0 - version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.3.0)(happy-dom@18.0.1)(jiti@2.5.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) - autoprefixer: - specifier: ^10.4.17 - version: 10.4.21(postcss@8.5.6) + version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.7.1)(happy-dom@20.0.0)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) dotenv: specifier: ^17.0.0 - version: 17.2.1 + version: 17.2.3 eslint: - specifier: ^9.18.0 - version: 9.33.0(jiti@2.5.1) + specifier: ^9.36.0 + version: 9.37.0(jiti@2.6.1) eslint-config-prettier: specifier: ^10.1.8 - version: 10.1.8(eslint@9.33.0(jiti@2.5.1)) - eslint-p: - specifier: ^0.25.0 - version: 0.25.0(jiti@2.5.1) + version: 10.1.8(eslint@9.37.0(jiti@2.6.1)) eslint-plugin-compat: specifier: ^6.0.2 - version: 6.0.2(eslint@9.33.0(jiti@2.5.1)) + version: 6.0.2(eslint@9.37.0(jiti@2.6.1)) eslint-plugin-svelte: - specifier: ^3.9.0 - version: 3.11.0(eslint@9.33.0(jiti@2.5.1))(svelte@5.35.5) + specifier: ^3.12.4 + version: 3.12.4(eslint@9.37.0(jiti@2.6.1))(svelte@5.39.11) eslint-plugin-unicorn: - specifier: ^60.0.0 - version: 60.0.0(eslint@9.33.0(jiti@2.5.1)) + specifier: ^61.0.2 + version: 61.0.2(eslint@9.37.0(jiti@2.6.1)) factory.ts: specifier: ^1.4.1 version: 1.4.2 globals: specifier: ^16.0.0 - version: 16.3.0 + version: 16.4.0 prettier: specifier: ^3.4.2 version: 3.6.2 prettier-plugin-organize-imports: specifier: ^4.0.0 - version: 4.2.0(prettier@3.6.2)(typescript@5.9.2) + version: 4.3.0(prettier@3.6.2)(typescript@5.9.3) prettier-plugin-sort-json: specifier: ^4.1.1 version: 4.1.1(prettier@3.6.2) prettier-plugin-svelte: specifier: ^3.3.3 - version: 3.4.0(prettier@3.6.2)(svelte@5.35.5) + version: 3.4.0(prettier@3.6.2)(svelte@5.39.11) rollup-plugin-visualizer: specifier: ^6.0.0 - version: 6.0.3(rollup@4.46.3) + version: 6.0.4(rollup@4.52.4) svelte: - specifier: 5.35.5 - version: 5.35.5 + specifier: 5.39.11 + version: 5.39.11 svelte-check: specifier: ^4.1.5 - version: 4.3.1(picomatch@4.0.3)(svelte@5.35.5)(typescript@5.9.2) + version: 4.3.3(picomatch@4.0.3)(svelte@5.39.11)(typescript@5.9.3) svelte-eslint-parser: - specifier: ^1.2.0 - version: 1.3.1(svelte@5.35.5) + specifier: ^1.3.3 + version: 1.3.3(svelte@5.39.11) tailwindcss: specifier: ^4.1.7 - version: 4.1.12 - tslib: - specifier: ^2.6.2 - version: 2.8.1 + version: 4.1.14 typescript: specifier: ^5.8.3 - version: 5.9.2 + version: 5.9.3 typescript-eslint: - specifier: ^8.28.0 - version: 8.39.1(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2) + specifier: ^8.45.0 + version: 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) vite: specifier: ^7.1.2 - version: 7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + version: 7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) vitest: specifier: ^3.0.0 - version: 3.2.4(@types/debug@4.1.12)(@types/node@24.3.0)(happy-dom@18.0.1)(jiti@2.5.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + version: 3.2.4(@types/debug@4.1.12)(@types/node@24.7.1)(happy-dom@20.0.0)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) packages: '@adobe/css-tools@4.4.4': resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==} + '@algolia/abtesting@1.6.0': + resolution: {integrity: sha512-c4M/Z/KWkEG+RHpZsWKDTTlApXu3fe4vlABNcpankWBhdMe4oPZ/r4JxEr2zKUP6K+BT66tnp8UbHmgOd/vvqQ==} + engines: {node: '>= 14.0.0'} + '@algolia/autocomplete-core@1.17.9': resolution: {integrity: sha512-O7BxrpLDPJWWHv/DLA9DRFWs+iY1uOJZkqUwjS5HSZAGcl0hIVCQ97LTLewiZmZ402JYUrun+8NqFP+hCknlbQ==} @@ -989,59 +930,59 @@ packages: '@algolia/client-search': '>= 4.9.1 < 6' algoliasearch: '>= 4.9.1 < 6' - '@algolia/client-abtesting@5.29.0': - resolution: {integrity: sha512-AM/6LYMSTnZvAT5IarLEKjYWOdV+Fb+LVs8JRq88jn8HH6bpVUtjWdOZXqX1hJRXuCAY8SdQfb7F8uEiMNXdYQ==} + '@algolia/client-abtesting@5.40.0': + resolution: {integrity: sha512-qegVlgHtmiS8m9nEsuKUVhlw1FHsIshtt5nhNnA6EYz3g+tm9+xkVZZMzkrMLPP7kpoheHJZAwz2MYnHtwFa9A==} engines: {node: '>= 14.0.0'} - '@algolia/client-analytics@5.29.0': - resolution: {integrity: sha512-La34HJh90l0waw3wl5zETO8TuukeUyjcXhmjYZL3CAPLggmKv74mobiGRIb+mmBENybiFDXf/BeKFLhuDYWMMQ==} + '@algolia/client-analytics@5.40.0': + resolution: {integrity: sha512-Dw2c+6KGkw7mucnnxPyyMsIGEY8+hqv6oB+viYB612OMM3l8aNaWToBZMnNvXsyP+fArwq7XGR+k3boPZyV53A==} engines: {node: '>= 14.0.0'} - '@algolia/client-common@5.29.0': - resolution: {integrity: sha512-T0lzJH/JiCxQYtCcnWy7Jf1w/qjGDXTi2npyF9B9UsTvXB97GRC6icyfXxe21mhYvhQcaB1EQ/J2575FXxi2rA==} + '@algolia/client-common@5.40.0': + resolution: {integrity: sha512-dbE4+MJIDsTghG3hUYWBq7THhaAmqNqvW9g2vzwPf5edU4IRmuYpKtY3MMotes8/wdTasWG07XoaVhplJBlvdg==} engines: {node: '>= 14.0.0'} - '@algolia/client-insights@5.29.0': - resolution: {integrity: sha512-A39F1zmHY9aev0z4Rt3fTLcGN5AG1VsVUkVWy6yQG5BRDScktH+U5m3zXwThwniBTDV1HrPgiGHZeWb67GkR2Q==} + '@algolia/client-insights@5.40.0': + resolution: {integrity: sha512-SH6zlROyGUCDDWg71DlCnbbZ/zEHYPZC8k901EAaBVhvY43Ju8Wa6LAcMPC4tahcDBgkG2poBy8nJZXvwEWAlQ==} engines: {node: '>= 14.0.0'} - '@algolia/client-personalization@5.29.0': - resolution: {integrity: sha512-ibxmh2wKKrzu5du02gp8CLpRMeo+b/75e4ORct98CT7mIxuYFXowULwCd6cMMkz/R0LpKXIbTUl15UL5soaiUQ==} + '@algolia/client-personalization@5.40.0': + resolution: {integrity: sha512-EgHjJEEf7CbUL9gJHI1ULmAtAFeym2cFNSAi1uwHelWgLPcnLjYW2opruPxigOV7NcetkGu+t2pcWOWmZFuvKQ==} engines: {node: '>= 14.0.0'} - '@algolia/client-query-suggestions@5.29.0': - resolution: {integrity: sha512-VZq4/AukOoJC2WSwF6J5sBtt+kImOoBwQc1nH3tgI+cxJBg7B77UsNC+jT6eP2dQCwGKBBRTmtPLUTDDnHpMgA==} + '@algolia/client-query-suggestions@5.40.0': + resolution: {integrity: sha512-HvE1jtCag95DR41tDh7cGwrMk4X0aQXPOBIhZRmsBPolMeqRJz0kvfVw8VCKvA1uuoAkjFfTG0X0IZED+rKXoA==} engines: {node: '>= 14.0.0'} - '@algolia/client-search@5.29.0': - resolution: {integrity: sha512-cZ0Iq3OzFUPpgszzDr1G1aJV5UMIZ4VygJ2Az252q4Rdf5cQMhYEIKArWY/oUjMhQmosM8ygOovNq7gvA9CdCg==} + '@algolia/client-search@5.40.0': + resolution: {integrity: sha512-nlr/MMgoLNUHcfWC5Ns2ENrzKx9x51orPc6wJ8Ignv1DsrUmKm0LUih+Tj3J+kxYofzqQIQRU495d4xn3ozMbg==} engines: {node: '>= 14.0.0'} '@algolia/events@4.0.1': resolution: {integrity: sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==} - '@algolia/ingestion@1.29.0': - resolution: {integrity: sha512-scBXn0wO5tZCxmO6evfa7A3bGryfyOI3aoXqSQBj5SRvNYXaUlFWQ/iKI70gRe/82ICwE0ICXbHT/wIvxOW7vw==} + '@algolia/ingestion@1.40.0': + resolution: {integrity: sha512-OfHnhE+P0f+p3i90Kmshf9Epgesw5oPV1IEUOY4Mq1HV7cQk16gvklVN1EaY/T9sVavl+Vc3g4ojlfpIwZFA4g==} engines: {node: '>= 14.0.0'} - '@algolia/monitoring@1.29.0': - resolution: {integrity: sha512-FGWWG9jLFhsKB7YiDjM2dwQOYnWu//7Oxrb2vT96N7+s+hg1mdHHfHNRyEudWdxd4jkMhBjeqNA21VbTiOIPVg==} + '@algolia/monitoring@1.40.0': + resolution: {integrity: sha512-SWANV32PTKhBYvwKozeWP9HOnVabOixAuPdFFGoqtysTkkwutrtGI/rrh80tvG+BnQAmZX0vUmD/RqFZVfr/Yg==} engines: {node: '>= 14.0.0'} - '@algolia/recommend@5.29.0': - resolution: {integrity: sha512-xte5+mpdfEARAu61KXa4ewpjchoZuJlAlvQb8ptK6hgHlBHDnYooy1bmOFpokaAICrq/H9HpoqNUX71n+3249A==} + '@algolia/recommend@5.40.0': + resolution: {integrity: sha512-1Qxy9I5bSb3mrhPk809DllMa561zl5hLsMR6YhIqNkqQ0OyXXQokvJ2zApSxvd39veRZZnhN+oGe+XNoNwLgkw==} engines: {node: '>= 14.0.0'} - '@algolia/requester-browser-xhr@5.29.0': - resolution: {integrity: sha512-og+7Em75aPHhahEUScq2HQ3J7ULN63Levtd87BYMpn6Im5d5cNhaC4QAUsXu6LWqxRPgh4G+i+wIb6tVhDhg2A==} + '@algolia/requester-browser-xhr@5.40.0': + resolution: {integrity: sha512-MGt94rdHfkrVjfN/KwUfWcnaeohYbWGINrPs96f5J7ZyRYpVLF+VtPQ2FmcddFvK4gnKXSu8BAi81hiIhUpm3w==} engines: {node: '>= 14.0.0'} - '@algolia/requester-fetch@5.29.0': - resolution: {integrity: sha512-JCxapz7neAy8hT/nQpCvOrI5JO8VyQ1kPvBiaXWNC1prVq0UMYHEL52o1BsPvtXfdQ7BVq19OIq6TjOI06mV/w==} + '@algolia/requester-fetch@5.40.0': + resolution: {integrity: sha512-wXQ05JZZ10Dr642QVAkAZ4ZZlU+lh5r6dIBGmm9WElz+1EaQ6BNYtEOTV6pkXuFYsZpeJA89JpDOiwBOP9j24w==} engines: {node: '>= 14.0.0'} - '@algolia/requester-node-http@5.29.0': - resolution: {integrity: sha512-lVBD81RBW5VTdEYgnzCz7Pf9j2H44aymCP+/eHGJu4vhU+1O8aKf3TVBgbQr5UM6xoe8IkR/B112XY6YIG2vtg==} + '@algolia/requester-node-http@5.40.0': + resolution: {integrity: sha512-5qCRoySnzpbQVg2IPLGFCm4LF75pToxI5tdjOYgUMNL/um91aJ4dH3SVdBEuFlVsalxl8mh3bWPgkUmv6NpJiQ==} engines: {node: '>= 14.0.0'} '@alloc/quick-lru@5.2.0': @@ -1061,6 +1002,15 @@ packages: chokidar: optional: true + '@angular-devkit/core@19.2.17': + resolution: {integrity: sha512-Ah008x2RJkd0F+NLKqIpA34/vUGwjlprRCkvddjDopAWRzYn6xCkz1Tqwuhn0nR1Dy47wTLKYD999TYl5ONOAQ==} + 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'} + peerDependencies: + chokidar: ^4.0.0 + peerDependenciesMeta: + chokidar: + optional: true + '@angular-devkit/schematics-cli@19.2.15': resolution: {integrity: sha512-1ESFmFGMpGQmalDB3t2EtmWDGv6gOFYBMxmHO2f1KI/UDl8UmZnCGL4mD3EWo8Hv0YIsZ9wOH9Q7ZHNYjeSpzg==} 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'} @@ -1070,9 +1020,138 @@ packages: resolution: {integrity: sha512-kNOJ+3vekJJCQKWihNmxBkarJzNW09kP5a9E1SRNiQVNOUEeSwcRR0qYotM65nx821gNzjjhJXnAZ8OazWldrg==} 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'} + '@angular-devkit/schematics@19.2.17': + resolution: {integrity: sha512-ADfbaBsrG8mBF6Mfs+crKA/2ykB8AJI50Cv9tKmZfwcUcyAdmTr+vVvhsBCfvUAEokigSsgqgpYxfkJVxhJYeg==} + 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'} + '@asamuzakjp/css-color@3.2.0': resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} + '@aws-crypto/sha256-browser@5.2.0': + resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==} + + '@aws-crypto/sha256-js@5.2.0': + resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/supports-web-crypto@5.2.0': + resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==} + + '@aws-crypto/util@5.2.0': + resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} + + '@aws-sdk/client-sesv2@3.907.0': + resolution: {integrity: sha512-r0NV1gxN3OO5l3gnxdQPS+STQHh+q9CRoEf9EG1273nOb1TwzrOIE34A0LO0Ow88XL5amgx/e9MdfuopJH9j+g==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/client-sso@3.907.0': + resolution: {integrity: sha512-ANuu0duNTcQHv0g5YrEuWImT8o9t6li3A+MtAaKxIbTA3eFQnl6xHDxyrbsrU19FtKPg3CWhvfY04j6DaDvR8g==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/core@3.907.0': + resolution: {integrity: sha512-vuIHL8qUcA5oNi7IWSZauCMaXstWTcSsnK1iHcvg92ddGDo1LMd2kQNo0G9UANa8vOfc908+8xKO40gfL8+M7w==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-env@3.907.0': + resolution: {integrity: sha512-orqT6djon57y09Ci5q0kezisrEvr78Z+7WvZbq0ZC0Ncul4RgJfCmhcgmzNPaWA18NEI0wGytaxYh3YFE7kIBQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-http@3.907.0': + resolution: {integrity: sha512-CKG/0hT4o8K2aQKOe+xwGP3keSNOyryhZNmKuHPuMRVlsJfO6wNxlu37HcUPzihJ+S2pOmTVGUbeVMCxJVUJmw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-ini@3.907.0': + resolution: {integrity: sha512-Clz1YdXrgQ5WIlcRE7odHbgM/INBxy49EA3csDITafHaDPtPRL39zkQtB5+Lwrrt/Gg0xBlyTbvP5Snan+0lqA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-node@3.907.0': + resolution: {integrity: sha512-w6Hhc4rV/CFaBliIh9Ph/T59xdGcTF6WmPGzzpykjl68+jcJyUem82hbTVIGaMCpvhx8VRqEr5AEXCXdbDbojw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-process@3.907.0': + resolution: {integrity: sha512-MBWpZqZtKkpM/LOGD5quXvlHJJN8YIP4GKo2ad8y1fEEVydwI8cggyXuauMPV7GllW8d0u3kQUs+4rxm1VaS4w==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-sso@3.907.0': + resolution: {integrity: sha512-F8I7xwIt0mhdg8NrC70HDmhDRx3ValBvmWH3YkWsjZltWIFozhQCCDISRPhanMkXVhSFmZY0FJ5Lo+B/SZvAAA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-web-identity@3.907.0': + resolution: {integrity: sha512-1CmRE/M8LJ/joXm5vUsKkQS35MoWA4xvUH9J1jyCuL3J9A8M+bnTe6ER8fnNLgmEs6ikdmYEIdfijPpBjBpFig==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-host-header@3.901.0': + resolution: {integrity: sha512-yWX7GvRmqBtbNnUW7qbre3GvZmyYwU0WHefpZzDTYDoNgatuYq6LgUIQ+z5C04/kCRoFkAFrHag8a3BXqFzq5A==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-logger@3.901.0': + resolution: {integrity: sha512-UoHebjE7el/tfRo8/CQTj91oNUm+5Heus5/a4ECdmWaSCHCS/hXTsU3PTTHAY67oAQR8wBLFPfp3mMvXjB+L2A==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-recursion-detection@3.901.0': + resolution: {integrity: sha512-Wd2t8qa/4OL0v/oDpCHHYkgsXJr8/ttCxrvCKAt0H1zZe2LlRhY9gpDVKqdertfHrHDj786fOvEQA28G1L75Dg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-sdk-s3@3.907.0': + resolution: {integrity: sha512-8VVxcZPmJOKI8P08v5ARvoXbLV41abpAIIkt388fp/lwtfzbnXt6sWhhAk/pHgvCR1NnuvkbGuXGVcux59648Q==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-user-agent@3.907.0': + resolution: {integrity: sha512-j/h3lk4X6AAXvusx/h8rr0zlo7G0l0quZM4k4rS/9jzatI53HCsrMaiGu6YXbxuVqtfMqv0MAj0MVhaMsAIs4A==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/nested-clients@3.907.0': + resolution: {integrity: sha512-LycXsdC5sMIc+Az5z1Mo2eYShr2kLo2gUgx7Rja3udG0GdqgdR/NNJ6ArmDCeKk2O5RFS5EgEg89bT55ecl5Uw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/region-config-resolver@3.901.0': + resolution: {integrity: sha512-7F0N888qVLHo4CSQOsnkZ4QAp8uHLKJ4v3u09Ly5k4AEStrSlFpckTPyUx6elwGL+fxGjNE2aakK8vEgzzCV0A==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/signature-v4-multi-region@3.907.0': + resolution: {integrity: sha512-f5XHRu6MTbjB/ud5RwBZzntYMgThRaDur5PJRZ1CaYAL8gZLNuEpJLzUA7o3queeSfE9JboO+cm1gZnOfnYJkg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/token-providers@3.907.0': + resolution: {integrity: sha512-HjPbNft1Ad8X1lHQG21QXy9pitdXA+OKH6NtcXg57A31002tM+SkyUmU6ty1jbsRBEScxziIVe5doI1NmkHheA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/types@3.901.0': + resolution: {integrity: sha512-FfEM25hLEs4LoXsLXQ/q6X6L4JmKkKkbVFpKD4mwfVHtRVQG6QxJiCPcrkcPISquiy6esbwK2eh64TWbiD60cg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-arn-parser@3.893.0': + resolution: {integrity: sha512-u8H4f2Zsi19DGnwj5FSZzDMhytYF/bCh37vAtBsn3cNDL3YG578X5oc+wSX54pM3tOxS+NY7tvOAo52SW7koUA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-endpoints@3.901.0': + resolution: {integrity: sha512-5nZP3hGA8FHEtKvEQf4Aww5QZOkjLW1Z+NixSd+0XKfHvA39Ah5sZboScjLx0C9kti/K3OGW1RCx5K9Zc3bZqg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-locate-window@3.893.0': + resolution: {integrity: sha512-T89pFfgat6c8nMmpI8eKjBcDcgJq36+m9oiXbcUzeU55MP9ZuGgBomGjGnHaEyF36jenW9gmg3NfZDm0AO2XPg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-user-agent-browser@3.907.0': + resolution: {integrity: sha512-Hus/2YCQmtCEfr4Ls88d07Q99Ex59uvtktiPTV963Q7w7LHuIT/JBjrbwNxtSm2KlJR9PHNdqxwN+fSuNsMGMQ==} + + '@aws-sdk/util-user-agent-node@3.907.0': + resolution: {integrity: sha512-r2Bc8VCU6ymkuem+QWT6oDdGvaYnK0YHg77SGUF47k+JsztSt1kZR0Y0q8jRH97bOsXldThyEcYsNbqDERa1Uw==} + engines: {node: '>=18.0.0'} + peerDependencies: + aws-crt: '>=1.0.0' + peerDependenciesMeta: + aws-crt: + optional: true + + '@aws-sdk/xml-builder@3.901.0': + resolution: {integrity: sha512-pxFCkuAP7Q94wMTNPAwi6hEtNrp/BdFf+HOrIEeFQsk4EoOmpKY3I6S+u6A9Wg295J80Kh74LqDWM22ux3z6Aw==} + engines: {node: '>=18.0.0'} + + '@aws/lambda-invoke-store@0.0.1': + resolution: {integrity: sha512-ORHRQ2tmvnBXc8t/X9Z8IcSbBA4xTLKuN873FopzklHMeqBst7YG0d+AX97inkvDX+NChYtSr+qGfcqGFaI8Zw==} + engines: {node: '>=18.0.0'} + '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} @@ -1176,8 +1255,8 @@ packages: resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==} engines: {node: '>=6.9.0'} - '@babel/parser@7.28.3': - resolution: {integrity: sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==} + '@babel/parser@7.28.4': + resolution: {integrity: sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==} engines: {node: '>=6.0.0'} hasBin: true @@ -1621,20 +1700,20 @@ packages: resolution: {integrity: sha512-vDVrlmRAY8z9Ul/HxT+8ceAru95LQgkSKiXkSYZvqtbkPSfhZJgpRp45Cldbh1GJ1kxzQkI70AqyrTI58KpaWQ==} engines: {node: '>=6.9.0'} - '@babel/runtime@7.28.3': - resolution: {integrity: sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==} + '@babel/runtime@7.28.4': + resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} engines: {node: '>=6.9.0'} '@babel/template@7.27.2': resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.28.3': - resolution: {integrity: sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==} + '@babel/traverse@7.28.4': + resolution: {integrity: sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==} engines: {node: '>=6.9.0'} - '@babel/types@7.28.2': - resolution: {integrity: sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==} + '@babel/types@7.28.4': + resolution: {integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==} engines: {node: '>=6.9.0'} '@balena/dockerignore@1.0.2': @@ -1933,120 +2012,120 @@ packages: search-insights: optional: true - '@docusaurus/babel@3.8.1': - resolution: {integrity: sha512-3brkJrml8vUbn9aeoZUlJfsI/GqyFcDgQJwQkmBtclJgWDEQBKKeagZfOgx0WfUQhagL1sQLNW0iBdxnI863Uw==} - engines: {node: '>=18.0'} + '@docusaurus/babel@3.9.1': + resolution: {integrity: sha512-/uoi3oG+wvbVWNBRfPrzrEslOSeLxrQEyWMywK51TLDFTANqIRivzkMusudh5bdDty8fXzCYUT+tg5t697jYqg==} + engines: {node: '>=20.0'} - '@docusaurus/bundler@3.8.1': - resolution: {integrity: sha512-/z4V0FRoQ0GuSLToNjOSGsk6m2lQUG4FRn8goOVoZSRsTrU8YR2aJacX5K3RG18EaX9b+52pN4m1sL3MQZVsQA==} - engines: {node: '>=18.0'} + '@docusaurus/bundler@3.9.1': + resolution: {integrity: sha512-E1c9DgNmAz4NqbNtiJVp4UgjLtr8O01IgtXD/NDQ4PZaK8895cMiTOgb3k7mN0qX8A3lb8vqyrPJ842+yMpuUg==} + engines: {node: '>=20.0'} peerDependencies: '@docusaurus/faster': '*' peerDependenciesMeta: '@docusaurus/faster': optional: true - '@docusaurus/core@3.8.1': - resolution: {integrity: sha512-ENB01IyQSqI2FLtOzqSI3qxG2B/jP4gQPahl2C3XReiLebcVh5B5cB9KYFvdoOqOWPyr5gXK4sjgTKv7peXCrA==} - engines: {node: '>=18.0'} + '@docusaurus/core@3.9.1': + resolution: {integrity: sha512-FWDk1LIGD5UR5Zmm9rCrXRoxZUgbwuP6FBA7rc50DVfzqDOMkeMe3NyJhOsA2dF0zBE3VbHEIMmTjKwTZJwbaA==} + engines: {node: '>=20.0'} hasBin: true peerDependencies: '@mdx-js/react': ^3.0.0 react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/cssnano-preset@3.8.1': - resolution: {integrity: sha512-G7WyR2N6SpyUotqhGznERBK+x84uyhfMQM2MmDLs88bw4Flom6TY46HzkRkSEzaP9j80MbTN8naiL1fR17WQug==} - engines: {node: '>=18.0'} + '@docusaurus/cssnano-preset@3.9.1': + resolution: {integrity: sha512-2y7+s7RWQMqBg+9ejeKwvZs7Bdw/hHIVJIodwMXbs2kr+S48AhcmAfdOh6Cwm0unJb0hJUshN0ROwRoQMwl3xg==} + engines: {node: '>=20.0'} - '@docusaurus/logger@3.8.1': - resolution: {integrity: sha512-2wjeGDhKcExEmjX8k1N/MRDiPKXGF2Pg+df/bDDPnnJWHXnVEZxXj80d6jcxp1Gpnksl0hF8t/ZQw9elqj2+ww==} - engines: {node: '>=18.0'} + '@docusaurus/logger@3.9.1': + resolution: {integrity: sha512-C9iFzXwHzwvGlisE4bZx+XQE0JIqlGAYAd5LzpR7fEDgjctu7yL8bE5U4nTNywXKHURDzMt4RJK8V6+stFHVkA==} + engines: {node: '>=20.0'} - '@docusaurus/mdx-loader@3.8.1': - resolution: {integrity: sha512-DZRhagSFRcEq1cUtBMo4TKxSNo/W6/s44yhr8X+eoXqCLycFQUylebOMPseHi5tc4fkGJqwqpWJLz6JStU9L4w==} - engines: {node: '>=18.0'} + '@docusaurus/mdx-loader@3.9.1': + resolution: {integrity: sha512-/1PY8lqry8jCt0qZddJSpc0U2sH6XC27kVJZfpA7o2TiQ3mdBQyH5AVbj/B2m682B1ounE+XjI0LdpOkAQLPoA==} + engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/module-type-aliases@3.8.1': - resolution: {integrity: sha512-6xhvAJiXzsaq3JdosS7wbRt/PwEPWHr9eM4YNYqVlbgG1hSK3uQDXTVvQktasp3VO6BmfYWPozueLWuj4gB+vg==} + '@docusaurus/module-type-aliases@3.9.1': + resolution: {integrity: sha512-YBce3GbJGGcMbJTyHcnEOMvdXqg41pa5HsrMCGA5Rm4z0h0tHS6YtEldj0mlfQRhCG7Y0VD66t2tb87Aom+11g==} peerDependencies: react: '*' react-dom: '*' - '@docusaurus/plugin-content-blog@3.8.1': - resolution: {integrity: sha512-vNTpMmlvNP9n3hGEcgPaXyvTljanAKIUkuG9URQ1DeuDup0OR7Ltvoc8yrmH+iMZJbcQGhUJF+WjHLwuk8HSdw==} - engines: {node: '>=18.0'} + '@docusaurus/plugin-content-blog@3.9.1': + resolution: {integrity: sha512-vT6kIimpJLWvW9iuWzH4u7VpTdsGlmn4yfyhq0/Kb1h4kf9uVouGsTmrD7WgtYBUG1P+TSmQzUUQa+ALBSRTig==} + engines: {node: '>=20.0'} peerDependencies: '@docusaurus/plugin-content-docs': '*' react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/plugin-content-docs@3.8.1': - resolution: {integrity: sha512-oByRkSZzeGNQByCMaX+kif5Nl2vmtj2IHQI2fWjCfCootsdKZDPFLonhIp5s3IGJO7PLUfe0POyw0Xh/RrGXJA==} - engines: {node: '>=18.0'} + '@docusaurus/plugin-content-docs@3.9.1': + resolution: {integrity: sha512-DyLk9BIA6I9gPIuia8XIL+XIEbNnExam6AHzRsfrEq4zJr7k/DsWW7oi4aJMepDnL7jMRhpVcdsCxdjb0/A9xg==} + engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/plugin-content-pages@3.8.1': - resolution: {integrity: sha512-a+V6MS2cIu37E/m7nDJn3dcxpvXb6TvgdNI22vJX8iUTp8eoMoPa0VArEbWvCxMY/xdC26WzNv4wZ6y0iIni/w==} - engines: {node: '>=18.0'} + '@docusaurus/plugin-content-pages@3.9.1': + resolution: {integrity: sha512-/1wFzRnXYASI+Nv9ck9IVPIMw0O5BGQ8ZVhDzEwhkL+tl44ycvSnY6PIe6rW2HLxsw61Z3WFwAiU8+xMMtMZpg==} + engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/plugin-css-cascade-layers@3.8.1': - resolution: {integrity: sha512-VQ47xRxfNKjHS5ItzaVXpxeTm7/wJLFMOPo1BkmoMG4Cuz4nuI+Hs62+RMk1OqVog68Swz66xVPK8g9XTrBKRw==} - engines: {node: '>=18.0'} + '@docusaurus/plugin-css-cascade-layers@3.9.1': + resolution: {integrity: sha512-/QyW2gRCk/XE3ttCK/ERIgle8KJ024dBNKMu6U5SmpJvuT2il1n5jR/48Pp/9wEwut8WVml4imNm6X8JsL5A0Q==} + engines: {node: '>=20.0'} - '@docusaurus/plugin-debug@3.8.1': - resolution: {integrity: sha512-nT3lN7TV5bi5hKMB7FK8gCffFTBSsBsAfV84/v293qAmnHOyg1nr9okEw8AiwcO3bl9vije5nsUvP0aRl2lpaw==} - engines: {node: '>=18.0'} + '@docusaurus/plugin-debug@3.9.1': + resolution: {integrity: sha512-qPeAuk0LccC251d7jg2MRhNI+o7niyqa924oEM/AxnZJvIpMa596aAxkRImiAqNN6+gtLE1Hkrz/RHUH2HDGsA==} + engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/plugin-google-analytics@3.8.1': - resolution: {integrity: sha512-Hrb/PurOJsmwHAsfMDH6oVpahkEGsx7F8CWMjyP/dw1qjqmdS9rcV1nYCGlM8nOtD3Wk/eaThzUB5TSZsGz+7Q==} - engines: {node: '>=18.0'} + '@docusaurus/plugin-google-analytics@3.9.1': + resolution: {integrity: sha512-k4Qq2HphqOrIU/CevGPdEO1yJnWUI8m0zOJsYt5NfMJwNsIn/gDD6gv/DKD+hxHndQT5pacsfBd4BWHZVNVroQ==} + engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/plugin-google-gtag@3.8.1': - resolution: {integrity: sha512-tKE8j1cEZCh8KZa4aa80zpSTxsC2/ZYqjx6AAfd8uA8VHZVw79+7OTEP2PoWi0uL5/1Is0LF5Vwxd+1fz5HlKg==} - engines: {node: '>=18.0'} + '@docusaurus/plugin-google-gtag@3.9.1': + resolution: {integrity: sha512-n9BURBiQyJKI/Ecz35IUjXYwXcgNCSq7/eA07+ZYcDiSyH2p/EjPf8q/QcZG3CyEJPZ/SzGkDHePfcVPahY4Gg==} + engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/plugin-google-tag-manager@3.8.1': - resolution: {integrity: sha512-iqe3XKITBquZq+6UAXdb1vI0fPY5iIOitVjPQ581R1ZKpHr0qe+V6gVOrrcOHixPDD/BUKdYwkxFjpNiEN+vBw==} - engines: {node: '>=18.0'} + '@docusaurus/plugin-google-tag-manager@3.9.1': + resolution: {integrity: sha512-rZAQZ25ZuXaThBajxzLjXieTDUCMmBzfAA6ThElQ3o7Q+LEpOjCIrwGFau0KLY9HeG6x91+FwwsAM8zeApYDrg==} + engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/plugin-sitemap@3.8.1': - resolution: {integrity: sha512-+9YV/7VLbGTq8qNkjiugIelmfUEVkTyLe6X8bWq7K5qPvGXAjno27QAfFq63mYfFFbJc7z+pudL63acprbqGzw==} - engines: {node: '>=18.0'} + '@docusaurus/plugin-sitemap@3.9.1': + resolution: {integrity: sha512-k/bf5cXDxAJUYTzqatgFJwmZsLUbIgl6S8AdZMKGG2Mv2wcOHt+EQNN9qPyWZ5/9cFj+Q8f8DN+KQheBMYLong==} + engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/plugin-svgr@3.8.1': - resolution: {integrity: sha512-rW0LWMDsdlsgowVwqiMb/7tANDodpy1wWPwCcamvhY7OECReN3feoFwLjd/U4tKjNY3encj0AJSTxJA+Fpe+Gw==} - engines: {node: '>=18.0'} + '@docusaurus/plugin-svgr@3.9.1': + resolution: {integrity: sha512-TeZOXT2PSdTNR1OpDJMkYqFyX7MMhbd4t16hQByXksgZQCXNyw3Dio+KaDJ2Nj+LA4WkOvsk45bWgYG5MAaXSQ==} + engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/preset-classic@3.8.1': - resolution: {integrity: sha512-yJSjYNHXD8POMGc2mKQuj3ApPrN+eG0rO1UPgSx7jySpYU+n4WjBikbrA2ue5ad9A7aouEtMWUoiSRXTH/g7KQ==} - engines: {node: '>=18.0'} + '@docusaurus/preset-classic@3.9.1': + resolution: {integrity: sha512-ZHga2xsxxsyd0dN1BpLj8S889Eu9eMBuj2suqxdw/vaaXu/FjJ8KEGbcaeo6nHPo8VQcBBnPEdkBtSDm2TfMNw==} + engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 @@ -2056,52 +2135,52 @@ packages: peerDependencies: react: '*' - '@docusaurus/theme-classic@3.8.1': - resolution: {integrity: sha512-bqDUCNqXeYypMCsE1VcTXSI1QuO4KXfx8Cvl6rYfY0bhhqN6d2WZlRkyLg/p6pm+DzvanqHOyYlqdPyP0iz+iw==} - engines: {node: '>=18.0'} + '@docusaurus/theme-classic@3.9.1': + resolution: {integrity: sha512-LrAIu/mQ04nG6s1cssC0TMmICD8twFIIn/hJ5Pd9uIPQvtKnyAKEn12RefopAul5KfMo9kixPaqogV5jIJr26w==} + engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/theme-common@3.8.1': - resolution: {integrity: sha512-UswMOyTnPEVRvN5Qzbo+l8k4xrd5fTFu2VPPfD6FcW/6qUtVLmJTQCktbAL3KJ0BVXGm5aJXz/ZrzqFuZERGPw==} - engines: {node: '>=18.0'} + '@docusaurus/theme-common@3.9.1': + resolution: {integrity: sha512-j9adi961F+6Ps9d0jcb5BokMcbjXAAJqKkV43eo8nh4YgmDj7KUNDX4EnOh/MjTQeO06oPY5cxp3yUXdW/8Ggw==} + engines: {node: '>=20.0'} peerDependencies: '@docusaurus/plugin-content-docs': '*' react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/theme-search-algolia@3.8.1': - resolution: {integrity: sha512-NBFH5rZVQRAQM087aYSRKQ9yGEK9eHd+xOxQjqNpxMiV85OhJDD4ZGz6YJIod26Fbooy54UWVdzNU0TFeUUUzQ==} - engines: {node: '>=18.0'} + '@docusaurus/theme-search-algolia@3.9.1': + resolution: {integrity: sha512-WjM28bzlgfT6nHlEJemkwyGVpvGsZWPireV/w+wZ1Uo64xCZ8lNOb4xwQRukDaLSed3oPBN0gSnu06l5VuCXHg==} + engines: {node: '>=20.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/theme-translations@3.8.1': - resolution: {integrity: sha512-OTp6eebuMcf2rJt4bqnvuwmm3NVXfzfYejL+u/Y1qwKhZPrjPoKWfk1CbOP5xH5ZOPkiAsx4dHdQBRJszK3z2g==} - engines: {node: '>=18.0'} + '@docusaurus/theme-translations@3.9.1': + resolution: {integrity: sha512-mUQd49BSGKTiM6vP9+JFgRJL28lMIN3PUvXjF3rzuOHMByUZUBNwCt26Z23GkKiSIOrRkjKoaBNTipR/MHdYSQ==} + engines: {node: '>=20.0'} - '@docusaurus/tsconfig@3.8.1': - resolution: {integrity: sha512-XBWCcqhRHhkhfolnSolNL+N7gj3HVE3CoZVqnVjfsMzCoOsuQw2iCLxVVHtO+rePUUfouVZHURDgmqIySsF66A==} + '@docusaurus/tsconfig@3.9.1': + resolution: {integrity: sha512-stdzM1dNDgRO0OvxeznXlE3N1igUoeHPNJjiKqyffLizgpVgNXJBAWeG6fuoYiCH4udGUBqy2dyM+1+kG2/UPQ==} - '@docusaurus/types@3.8.1': - resolution: {integrity: sha512-ZPdW5AB+pBjiVrcLuw3dOS6BFlrG0XkS2lDGsj8TizcnREQg3J8cjsgfDviszOk4CweNfwo1AEELJkYaMUuOPg==} + '@docusaurus/types@3.9.1': + resolution: {integrity: sha512-ElekJ29sk39s5LTEZMByY1c2oH9FMtw7KbWFU3BtuQ1TytfIK39HhUivDEJvm5KCLyEnnfUZlvSNDXeyk0vzAA==} peerDependencies: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - '@docusaurus/utils-common@3.8.1': - resolution: {integrity: sha512-zTZiDlvpvoJIrQEEd71c154DkcriBecm4z94OzEE9kz7ikS3J+iSlABhFXM45mZ0eN5pVqqr7cs60+ZlYLewtg==} - engines: {node: '>=18.0'} + '@docusaurus/utils-common@3.9.1': + resolution: {integrity: sha512-4M1u5Q8Zn2CYL2TJ864M51FV4YlxyGyfC3x+7CLuR6xsyTVNBNU4QMcPgsTHRS9J2+X6Lq7MyH6hiWXyi/sXUQ==} + engines: {node: '>=20.0'} - '@docusaurus/utils-validation@3.8.1': - resolution: {integrity: sha512-gs5bXIccxzEbyVecvxg6upTwaUbfa0KMmTj7HhHzc016AGyxH2o73k1/aOD0IFrdCsfJNt37MqNI47s2MgRZMA==} - engines: {node: '>=18.0'} + '@docusaurus/utils-validation@3.9.1': + resolution: {integrity: sha512-5bzab5si3E1udrlZuVGR17857Lfwe8iFPoy5AvMP9PXqDfoyIKT7gDQgAmxdRDMurgHaJlyhXEHHdzDKkOxxZQ==} + engines: {node: '>=20.0'} - '@docusaurus/utils@3.8.1': - resolution: {integrity: sha512-P1ml0nvOmEFdmu0smSXOqTS1sxU5tqvnc0dA4MTKV39kye+bhQnjkIKEE18fNOvxjyB86k8esoCIFM3x4RykOQ==} - engines: {node: '>=18.0'} + '@docusaurus/utils@3.9.1': + resolution: {integrity: sha512-YAL4yhhWLl9DXuf5MVig260a6INz4MehrBGFU/CZu8yXmRiYEuQvRFWh9ZsjfAOyaG7za1MNmBVZ4VVAi/CiJA==} + engines: {node: '>=20.0'} '@emnapi/runtime@1.5.0': resolution: {integrity: sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==} @@ -2112,8 +2191,8 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.25.9': - resolution: {integrity: sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==} + '@esbuild/aix-ppc64@0.25.10': + resolution: {integrity: sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] @@ -2124,8 +2203,8 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.25.9': - resolution: {integrity: sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==} + '@esbuild/android-arm64@0.25.10': + resolution: {integrity: sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==} engines: {node: '>=18'} cpu: [arm64] os: [android] @@ -2136,8 +2215,8 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-arm@0.25.9': - resolution: {integrity: sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==} + '@esbuild/android-arm@0.25.10': + resolution: {integrity: sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==} engines: {node: '>=18'} cpu: [arm] os: [android] @@ -2148,8 +2227,8 @@ packages: cpu: [x64] os: [android] - '@esbuild/android-x64@0.25.9': - resolution: {integrity: sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==} + '@esbuild/android-x64@0.25.10': + resolution: {integrity: sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==} engines: {node: '>=18'} cpu: [x64] os: [android] @@ -2160,8 +2239,8 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.25.9': - resolution: {integrity: sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==} + '@esbuild/darwin-arm64@0.25.10': + resolution: {integrity: sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] @@ -2172,8 +2251,8 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.25.9': - resolution: {integrity: sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==} + '@esbuild/darwin-x64@0.25.10': + resolution: {integrity: sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==} engines: {node: '>=18'} cpu: [x64] os: [darwin] @@ -2184,8 +2263,8 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.25.9': - resolution: {integrity: sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==} + '@esbuild/freebsd-arm64@0.25.10': + resolution: {integrity: sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] @@ -2196,8 +2275,8 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.9': - resolution: {integrity: sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==} + '@esbuild/freebsd-x64@0.25.10': + resolution: {integrity: sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] @@ -2208,8 +2287,8 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.25.9': - resolution: {integrity: sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==} + '@esbuild/linux-arm64@0.25.10': + resolution: {integrity: sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==} engines: {node: '>=18'} cpu: [arm64] os: [linux] @@ -2220,8 +2299,8 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.25.9': - resolution: {integrity: sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==} + '@esbuild/linux-arm@0.25.10': + resolution: {integrity: sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==} engines: {node: '>=18'} cpu: [arm] os: [linux] @@ -2232,8 +2311,8 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.25.9': - resolution: {integrity: sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==} + '@esbuild/linux-ia32@0.25.10': + resolution: {integrity: sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==} engines: {node: '>=18'} cpu: [ia32] os: [linux] @@ -2244,8 +2323,8 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.25.9': - resolution: {integrity: sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==} + '@esbuild/linux-loong64@0.25.10': + resolution: {integrity: sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] @@ -2256,8 +2335,8 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.25.9': - resolution: {integrity: sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==} + '@esbuild/linux-mips64el@0.25.10': + resolution: {integrity: sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] @@ -2268,8 +2347,8 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.25.9': - resolution: {integrity: sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==} + '@esbuild/linux-ppc64@0.25.10': + resolution: {integrity: sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] @@ -2280,8 +2359,8 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.25.9': - resolution: {integrity: sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==} + '@esbuild/linux-riscv64@0.25.10': + resolution: {integrity: sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] @@ -2292,8 +2371,8 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.25.9': - resolution: {integrity: sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==} + '@esbuild/linux-s390x@0.25.10': + resolution: {integrity: sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==} engines: {node: '>=18'} cpu: [s390x] os: [linux] @@ -2304,14 +2383,14 @@ packages: cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.25.9': - resolution: {integrity: sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==} + '@esbuild/linux-x64@0.25.10': + resolution: {integrity: sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.9': - resolution: {integrity: sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==} + '@esbuild/netbsd-arm64@0.25.10': + resolution: {integrity: sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] @@ -2322,14 +2401,14 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.9': - resolution: {integrity: sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==} + '@esbuild/netbsd-x64@0.25.10': + resolution: {integrity: sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.9': - resolution: {integrity: sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==} + '@esbuild/openbsd-arm64@0.25.10': + resolution: {integrity: sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] @@ -2340,14 +2419,14 @@ packages: cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.9': - resolution: {integrity: sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==} + '@esbuild/openbsd-x64@0.25.10': + resolution: {integrity: sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.25.9': - resolution: {integrity: sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==} + '@esbuild/openharmony-arm64@0.25.10': + resolution: {integrity: sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] @@ -2358,8 +2437,8 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.25.9': - resolution: {integrity: sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==} + '@esbuild/sunos-x64@0.25.10': + resolution: {integrity: sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==} engines: {node: '>=18'} cpu: [x64] os: [sunos] @@ -2370,8 +2449,8 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.25.9': - resolution: {integrity: sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==} + '@esbuild/win32-arm64@0.25.10': + resolution: {integrity: sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==} engines: {node: '>=18'} cpu: [arm64] os: [win32] @@ -2382,8 +2461,8 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.25.9': - resolution: {integrity: sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==} + '@esbuild/win32-ia32@0.25.10': + resolution: {integrity: sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==} engines: {node: '>=18'} cpu: [ia32] os: [win32] @@ -2394,14 +2473,14 @@ packages: cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.25.9': - resolution: {integrity: sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==} + '@esbuild/win32-x64@0.25.10': + resolution: {integrity: sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==} engines: {node: '>=18'} cpu: [x64] os: [win32] - '@eslint-community/eslint-utils@4.7.0': - resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==} + '@eslint-community/eslint-utils@4.9.0': + resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 @@ -2414,28 +2493,24 @@ packages: resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/config-helpers@0.3.1': - resolution: {integrity: sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/core@0.14.0': - resolution: {integrity: sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==} + '@eslint/config-helpers@0.4.0': + resolution: {integrity: sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/core@0.15.2': resolution: {integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/core@0.16.0': + resolution: {integrity: sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/eslintrc@3.3.1': resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.30.1': - resolution: {integrity: sha512-zXhuECFlyep42KZUhWjfvsmXGX39W8K8LFb8AWXM9gSV9dQB+MrJGLKvW6Zw0Ggnbpw0VHTtrhFXYe3Gym18jg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/js@9.33.0': - resolution: {integrity: sha512-5K1/mKhWaMfreBGJTwval43JJmkip0RmM+3+IuqupeSKNC/Th2Kc7ucaq5ovTSra/OOKB9c58CGSz3QMVbWt0A==} + '@eslint/js@9.37.0': + resolution: {integrity: sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.6': @@ -2446,16 +2521,13 @@ packages: resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@exodus/schemasafe@1.3.0': - resolution: {integrity: sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==} + '@eslint/plugin-kit@0.4.0': + resolution: {integrity: sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@faker-js/faker@5.5.3': - resolution: {integrity: sha512-R11tGE6yIFwqpaIqcfkcg7AICXzFg14+5h5v0TfF/9+RMDL6jhzCy/pxHVOfbALGdtVYdt6JdR21tuxEgl34dw==} - deprecated: Please update to a newer version. - - '@faker-js/faker@9.9.0': - resolution: {integrity: sha512-OEl393iCOoo/z8bMezRlJu+GlRGlsKbUAN7jKB6LhnKoqKve5DXRpalbItIIcwnCjs1k/FOPjFzcA6Qn+H+YbA==} - engines: {node: '>=18.0.0', npm: '>=9.0.0'} + '@faker-js/faker@10.0.0': + resolution: {integrity: sha512-UollFEUkVXutsaP+Vndjxar40Gs5JL2HeLcl8xO1QAjJgOdhc3OmBFWyEylS+RddWaaBiAzH+5/17PLQJwDiLw==} + engines: {node: ^20.19.0 || ^22.13.0 || ^23.5.0 || >=24.0.0, npm: '>=10'} '@fig/complete-commander@3.2.0': resolution: {integrity: sha512-1Holl3XtRiANVKURZwgpjCnPuV4RsHp+XC0MhgvyAX/avQwj7F2HUItYOvGi/bXjJCkEzgBZmVfCr0HBA+q+Bw==} @@ -2465,35 +2537,35 @@ packages: '@floating-ui/core@1.7.3': resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==} - '@floating-ui/dom@1.7.3': - resolution: {integrity: sha512-uZA413QEpNuhtb3/iIKoYMSK07keHPYeXF02Zhd6e213j+d1NamLix/mCLxBUDW/Gx52sPH2m+chlUsyaBs/Ag==} + '@floating-ui/dom@1.7.4': + resolution: {integrity: sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==} '@floating-ui/utils@0.2.10': resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} - '@formatjs/ecma402-abstract@2.3.4': - resolution: {integrity: sha512-qrycXDeaORzIqNhBOx0btnhpD1c+/qFIHAN9znofuMJX6QBwtbrmlpWfD4oiUUD2vJUOIYFA/gYtg2KAMGG7sA==} + '@formatjs/ecma402-abstract@2.3.5': + resolution: {integrity: sha512-1HTESOq1IUa23g1lFZEGIXsfZKZOwWmB9RROwGn+xariiQnd++wwTMvlRAbZ8wtXRHFUamJPxsKcxpSzeCvFWQ==} '@formatjs/fast-memoize@2.2.7': resolution: {integrity: sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ==} - '@formatjs/icu-messageformat-parser@2.11.2': - resolution: {integrity: sha512-AfiMi5NOSo2TQImsYAg8UYddsNJ/vUEv/HaNqiFjnI3ZFfWihUtD5QtuX6kHl8+H+d3qvnE/3HZrfzgdWpsLNA==} + '@formatjs/icu-messageformat-parser@2.11.3': + resolution: {integrity: sha512-H/KfWSosaiDiOaW4nHe1Fn4Cgzm+oFQ8giTmB5RJzTBNSMmd+j2NVrvvZHAmlxJHcuOelzKBLjQ2EDcyH4NSWw==} - '@formatjs/icu-skeleton-parser@1.8.14': - resolution: {integrity: sha512-i4q4V4qslThK4Ig8SxyD76cp3+QJ3sAqr7f6q9VVfeGtxG9OhiAk3y9XF6Q41OymsKzsGQ6OQQoJNY4/lI8TcQ==} + '@formatjs/icu-skeleton-parser@1.8.15': + resolution: {integrity: sha512-qNrKxWJmnWxin5U4A4Evy7C0rgRiNw3IqXu9OGuT31B8lDxBGl+OgT8kcq0ZVKK0gqA4l4SQB9x+SFAvLT5hcQ==} - '@formatjs/intl-localematcher@0.6.1': - resolution: {integrity: sha512-ePEgLgVCqi2BBFnTMWPfIghu6FkbZnnBVhO2sSxvLfrdFw7wCHAHiDoM2h4NRgjbaY7+B7HgOLZGkK187pZTZg==} + '@formatjs/intl-localematcher@0.6.2': + resolution: {integrity: sha512-XOMO2Hupl0wdd172Y06h6kLpBz6Dv+J4okPLl4LPtzbr8f66WbIoy4ev98EBuZ6ZK4h5ydTN6XneT4QVpD7cdA==} - '@golevelup/nestjs-discovery@4.0.3': - resolution: {integrity: sha512-8w3CsXHN7+7Sn2i419Eal1Iw/kOjAd6Kb55M/ZqKBBwACCMn4WiEuzssC71LpBMI1090CiDxuelfPRwwIrQK+A==} + '@golevelup/nestjs-discovery@5.0.0': + resolution: {integrity: sha512-NaIWLCLI+XvneUK05LH2idHLmLNITYT88YnpOuUQmllKtiJNIS3woSt7QXrMZ5k3qUWuZpehEVz1JtlX4I1KyA==} peerDependencies: - '@nestjs/common': ^10.x || ^11.0.0 - '@nestjs/core': ^10.x || ^11.0.0 + '@nestjs/common': ^11.0.20 + '@nestjs/core': ^11.0.20 - '@grpc/grpc-js@1.13.4': - resolution: {integrity: sha512-GsFaMXCkMqkKIvwCQjCrwH+GHbPKBjhwo/8ZuUkWHqbI73Kky9I+pQltrlT0+MWpedCoosda53lgjYfyEPgxBg==} + '@grpc/grpc-js@1.14.0': + resolution: {integrity: sha512-N8Jx6PaYzcTRNzirReJCtADVoq4z7+1KQ4E70jTg/koQiMoUSN1kbNjPOqpPbhMFhfU1/l7ixspPl8dNY+FoUg==} engines: {node: '>=12.10.0'} '@grpc/proto-loader@0.7.15': @@ -2501,6 +2573,11 @@ packages: engines: {node: '>=6'} hasBin: true + '@grpc/proto-loader@0.8.0': + resolution: {integrity: sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==} + engines: {node: '>=6'} + hasBin: true + '@hapi/hoek@9.3.0': resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} @@ -2511,146 +2588,146 @@ packages: resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} - '@humanfs/node@0.16.6': - resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + '@humanfs/node@0.16.7': + resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} engines: {node: '>=18.18.0'} '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - '@humanwhocodes/retry@0.3.1': - resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} - engines: {node: '>=18.18'} - '@humanwhocodes/retry@0.4.3': resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} - '@img/sharp-darwin-arm64@0.34.3': - resolution: {integrity: sha512-ryFMfvxxpQRsgZJqBd4wsttYQbCxsJksrv9Lw/v798JcQ8+w84mBWuXwl+TT0WJ/WrYOLaYpwQXi3sA9nTIaIg==} + '@img/colour@1.0.0': + resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==} + engines: {node: '>=18'} + + '@img/sharp-darwin-arm64@0.34.4': + resolution: {integrity: sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [darwin] - '@img/sharp-darwin-x64@0.34.3': - resolution: {integrity: sha512-yHpJYynROAj12TA6qil58hmPmAwxKKC7reUqtGLzsOHfP7/rniNGTL8tjWX6L3CTV4+5P4ypcS7Pp+7OB+8ihA==} + '@img/sharp-darwin-x64@0.34.4': + resolution: {integrity: sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [darwin] - '@img/sharp-libvips-darwin-arm64@1.2.0': - resolution: {integrity: sha512-sBZmpwmxqwlqG9ueWFXtockhsxefaV6O84BMOrhtg/YqbTaRdqDE7hxraVE3y6gVM4eExmfzW4a8el9ArLeEiQ==} + '@img/sharp-libvips-darwin-arm64@1.2.3': + resolution: {integrity: sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==} cpu: [arm64] os: [darwin] - '@img/sharp-libvips-darwin-x64@1.2.0': - resolution: {integrity: sha512-M64XVuL94OgiNHa5/m2YvEQI5q2cl9d/wk0qFTDVXcYzi43lxuiFTftMR1tOnFQovVXNZJ5TURSDK2pNe9Yzqg==} + '@img/sharp-libvips-darwin-x64@1.2.3': + resolution: {integrity: sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA==} cpu: [x64] os: [darwin] - '@img/sharp-libvips-linux-arm64@1.2.0': - resolution: {integrity: sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA==} + '@img/sharp-libvips-linux-arm64@1.2.3': + resolution: {integrity: sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==} cpu: [arm64] os: [linux] - '@img/sharp-libvips-linux-arm@1.2.0': - resolution: {integrity: sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw==} + '@img/sharp-libvips-linux-arm@1.2.3': + resolution: {integrity: sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==} cpu: [arm] os: [linux] - '@img/sharp-libvips-linux-ppc64@1.2.0': - resolution: {integrity: sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ==} + '@img/sharp-libvips-linux-ppc64@1.2.3': + resolution: {integrity: sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==} cpu: [ppc64] os: [linux] - '@img/sharp-libvips-linux-s390x@1.2.0': - resolution: {integrity: sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw==} + '@img/sharp-libvips-linux-s390x@1.2.3': + resolution: {integrity: sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==} cpu: [s390x] os: [linux] - '@img/sharp-libvips-linux-x64@1.2.0': - resolution: {integrity: sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg==} + '@img/sharp-libvips-linux-x64@1.2.3': + resolution: {integrity: sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==} cpu: [x64] os: [linux] - '@img/sharp-libvips-linuxmusl-arm64@1.2.0': - resolution: {integrity: sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q==} + '@img/sharp-libvips-linuxmusl-arm64@1.2.3': + resolution: {integrity: sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==} cpu: [arm64] os: [linux] - '@img/sharp-libvips-linuxmusl-x64@1.2.0': - resolution: {integrity: sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q==} + '@img/sharp-libvips-linuxmusl-x64@1.2.3': + resolution: {integrity: sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==} cpu: [x64] os: [linux] - '@img/sharp-linux-arm64@0.34.3': - resolution: {integrity: sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA==} + '@img/sharp-linux-arm64@0.34.4': + resolution: {integrity: sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - '@img/sharp-linux-arm@0.34.3': - resolution: {integrity: sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A==} + '@img/sharp-linux-arm@0.34.4': + resolution: {integrity: sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] - '@img/sharp-linux-ppc64@0.34.3': - resolution: {integrity: sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA==} + '@img/sharp-linux-ppc64@0.34.4': + resolution: {integrity: sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ppc64] os: [linux] - '@img/sharp-linux-s390x@0.34.3': - resolution: {integrity: sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ==} + '@img/sharp-linux-s390x@0.34.4': + resolution: {integrity: sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] - '@img/sharp-linux-x64@0.34.3': - resolution: {integrity: sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ==} + '@img/sharp-linux-x64@0.34.4': + resolution: {integrity: sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - '@img/sharp-linuxmusl-arm64@0.34.3': - resolution: {integrity: sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ==} + '@img/sharp-linuxmusl-arm64@0.34.4': + resolution: {integrity: sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - '@img/sharp-linuxmusl-x64@0.34.3': - resolution: {integrity: sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ==} + '@img/sharp-linuxmusl-x64@0.34.4': + resolution: {integrity: sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - '@img/sharp-wasm32@0.34.3': - resolution: {integrity: sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg==} + '@img/sharp-wasm32@0.34.4': + resolution: {integrity: sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [wasm32] - '@img/sharp-win32-arm64@0.34.3': - resolution: {integrity: sha512-MjnHPnbqMXNC2UgeLJtX4XqoVHHlZNd+nPt1kRPmj63wURegwBhZlApELdtxM2OIZDRv/DFtLcNhVbd1z8GYXQ==} + '@img/sharp-win32-arm64@0.34.4': + resolution: {integrity: sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [win32] - '@img/sharp-win32-ia32@0.34.3': - resolution: {integrity: sha512-xuCdhH44WxuXgOM714hn4amodJMZl3OEvf0GVTm0BEyMeA2to+8HEdRPShH0SLYptJY1uBw+SCFP9WVQi1Q/cw==} + '@img/sharp-win32-ia32@0.34.4': + resolution: {integrity: sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ia32] os: [win32] - '@img/sharp-win32-x64@0.34.3': - resolution: {integrity: sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g==} + '@img/sharp-win32-x64@0.34.4': + resolution: {integrity: sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [win32] - '@immich/ui@0.24.1': - resolution: {integrity: sha512-phJ9BHV0+OnKsxXD+5+Te5Amnb1N4ExYpRGSJPYFqutd5WXeN7kZGKZXd3CfcQ1e31SXRy4DsHSGdM1pY7AUgA==} + '@immich/ui@0.34.2': + resolution: {integrity: sha512-tWjEV1prSZ9VLes69Ha9jnnZj6tbv/9+PdQjsK+5zK7sQok/l7kyzAobj5z4XRD11XtGk/cAqi/ZOlqRWvZilA==} peerDependencies: svelte: ^5.0.0 @@ -2699,8 +2776,8 @@ packages: '@types/node': optional: true - '@inquirer/external-editor@1.0.1': - resolution: {integrity: sha512-Oau4yL24d2B5IL4ma4UpbQigkVhzPDXLoqy1ggK4gnHg/stmkffJE4oOXHXF3uz0UEpywG68KcyXsyYpA1Re/Q==} + '@inquirer/external-editor@1.0.2': + resolution: {integrity: sha512-yy9cOoBnx58TlsPrIxauKIFQTiyH+0MK4e97y4sV9ERbI+zDxw7i2hxHLCIEGIE/8PPvDxGhgzIOTSOWcs6/MQ==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -2796,8 +2873,8 @@ packages: '@internationalized/date@3.8.2': resolution: {integrity: sha512-/wENk7CbvLbkUvX1tu0mwq49CVkkWpkXubGel6birjRPyo6uQ4nQpnq5xZu823zRCwwn82zgHrvgF1vZyvmVgA==} - '@ioredis/commands@1.3.0': - resolution: {integrity: sha512-M/T6Zewn7sDaBQEqIZ8Rb+i9y8qfGmq+5SDFSf9sA2lUZTmdDLVdOiQaeDp+Q4wElZ9HG1GAX5KhDaidp6LQsQ==} + '@ioredis/commands@1.4.0': + resolution: {integrity: sha512-aFT2yemJJo+TZCmieA7qnYGQooOS7QfNmYrzGtsYd3g9j5iDP8AimYYAesf79ohjbLG12XxC4nG5DyEnC88AsQ==} '@isaacs/balanced-match@4.0.1': resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} @@ -2843,12 +2920,48 @@ packages: '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - '@jridgewell/trace-mapping@0.3.30': - resolution: {integrity: sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==} + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} '@js-sdsl/ordered-map@4.4.2': resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==} + '@jsonjoy.com/base64@1.1.2': + resolution: {integrity: sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/buffers@1.2.0': + resolution: {integrity: sha512-6RX+W5a+ZUY/c/7J5s5jK9UinLfJo5oWKh84fb4X0yK2q4WXEWUWZWuEMjvCb1YNUQhEAhUfr5scEGOH7jC4YQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/codegen@1.0.0': + resolution: {integrity: sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pack@1.20.0': + resolution: {integrity: sha512-adcXFVorSQULtT4XDL0giRLr2EVGIcyWm6eQKZWTrRA4EEydGOY8QVQtL0PaITQpUyu+lOd/QOicw6vdy1v8QQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pointer@1.0.2': + resolution: {integrity: sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/util@1.9.0': + resolution: {integrity: sha512-pLuQo+VPRnN8hfPqUTLTHk126wuYdXVxE6aDmjSeV4NCAgyxWbiOIeNJVtID3h1Vzpoi9m4jXezf73I6LgabgQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + '@koa/cors@5.0.0': resolution: {integrity: sha512-x/iUDjcS90W69PryLDIMgFyV21YLTnG9zOpPXS7Bkt2b8AsY3zZsIpOLBkYr9fBcF3HbkKaER5hOBZLfpLgYNw==} engines: {node: '>= 14.0.0'} @@ -2920,8 +3033,8 @@ packages: resolution: {integrity: sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==} engines: {node: '>=6.0.0'} - '@maplibre/maplibre-gl-style-spec@23.3.0': - resolution: {integrity: sha512-IGJtuBbaGzOUgODdBRg66p8stnwj9iDXkgbYKoYcNiiQmaez5WVRfXm4b03MCDwmZyX93csbfHFWEJJYHnn5oA==} + '@maplibre/maplibre-gl-style-spec@24.2.0': + resolution: {integrity: sha512-cE80g83fRcBbZbQC70siOUxUK6YJ/5ZkClDZbmm+hzrUbv+J6yntkMmcpdz9DbOrWOM7FHKR5rruc6Q/hWx5cA==} hasBin: true '@maplibre/vt-pbf@4.0.3': @@ -2939,11 +3052,11 @@ packages: '@mdn/browser-compat-data@6.0.27': resolution: {integrity: sha512-s5kTuDih5Ysb7DS2T2MhvneFLvDS0NwnLY5Jv6dL+zBXbcNVcyFcGdjwn3rttiHvcbb/qF02HP9ywufdwHZbIw==} - '@mdx-js/mdx@3.1.0': - resolution: {integrity: sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==} + '@mdx-js/mdx@3.1.1': + resolution: {integrity: sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==} - '@mdx-js/react@3.1.0': - resolution: {integrity: sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==} + '@mdx-js/react@3.1.1': + resolution: {integrity: sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==} peerDependencies: '@types/react': '>=16' react: '>=16' @@ -2951,16 +3064,6 @@ packages: '@microsoft/tsdoc@0.15.1': resolution: {integrity: sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==} - '@monaco-editor/loader@1.5.0': - resolution: {integrity: sha512-hKoGSM+7aAc7eRTRjpqAZucPmoNOC4UUbknb/VNoTkEIkCPhqV8LfbsgM1webRM7S/z21eHEx9Fkwx8Z/C/+Xw==} - - '@monaco-editor/react@4.7.0': - resolution: {integrity: sha512-cyzXQCtO47ydzxpQtCGSQGOC8Gk3ZUeBXFAxD+CWXYFo5OqZyZUonFl0DwUlTyAfRHntBfw2p3w4s9R6oe1eCA==} - peerDependencies: - monaco-editor: '>= 0.25.0 < 1' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': resolution: {integrity: sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==} cpu: [arm64] @@ -3051,12 +3154,6 @@ packages: '@nestjs/websockets': optional: true - '@nestjs/event-emitter@3.0.1': - resolution: {integrity: sha512-0Ln/x+7xkU6AJFOcQI9tIhUMXVF7D5itiaQGOyJbXtlAfAIt8gzDdJm+Im7cFzKoWkiW5nCXCPh6GSvdQd/3Dw==} - peerDependencies: - '@nestjs/common': ^10.0.0 || ^11.0.0 - '@nestjs/core': ^10.0.0 || ^11.0.0 - '@nestjs/mapped-types@2.1.0': resolution: {integrity: sha512-W+n+rM69XsFdwORF11UqJahn4J3xi4g/ZEOlJNL6KoW5ygWSmBB2p0S2BZ4FQeS/NDH72e6xIcu35SfJnE8bXw==} peerDependencies: @@ -3083,14 +3180,14 @@ packages: '@nestjs/websockets': ^11.0.0 rxjs: ^7.1.0 - '@nestjs/schedule@6.0.0': - resolution: {integrity: sha512-aQySMw6tw2nhitELXd3EiRacQRgzUKD9mFcUZVOJ7jPLqIBvXOyvRWLsK9SdurGA+jjziAlMef7iB5ZEFFoQpw==} + '@nestjs/schedule@6.0.1': + resolution: {integrity: sha512-v3yO6cSPAoBSSyH67HWnXHzuhPhSNZhRmLY38JvCt2sqY8sPMOODpcU1D79iUMFf7k16DaMEbL4Mgx61ZhiC8Q==} peerDependencies: '@nestjs/common': ^10.0.0 || ^11.0.0 '@nestjs/core': ^10.0.0 || ^11.0.0 - '@nestjs/schematics@11.0.7': - resolution: {integrity: sha512-t8dNYYMwEeEsrlwc2jbkfwCfXczq4AeNEgx1KVQuJ6wYibXk0ZbXbPdfp8scnEAaQv1grpncNV5gWgzi7ZwbvQ==} + '@nestjs/schematics@11.0.8': + resolution: {integrity: sha512-HKunkzfBYLpNyL/qP5wu0OBKVPrISJLnrB4r6S53fT99pEvopDcJAeIuznSAD1Dx1njUqpbTR/uGyD0xL1y0nw==} peerDependencies: typescript: '>=4.8.2' @@ -3168,95 +3265,88 @@ packages: '@oazapfts/runtime@1.0.4': resolution: {integrity: sha512-7t6C2shug/6tZhQgkCa532oTYBLEnbASV/i1SG1rH2GB4h3aQQujYciYSPT92hvN4IwTe8S2hPkN/6iiOyTlCg==} - '@opentelemetry/api-logs@0.203.0': - resolution: {integrity: sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==} + '@opentelemetry/api-logs@0.206.0': + resolution: {integrity: sha512-yIVDu9jX//nV5wSMLZLdHdb1SKHIMj9k+wQVFtln5Flcgdldz9BkHtavvExQiJqBZg2OpEEJEZmzQazYztdz2A==} engines: {node: '>=8.0.0'} '@opentelemetry/api@1.9.0': resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} engines: {node: '>=8.0.0'} - '@opentelemetry/auto-instrumentations-node@0.62.1': - resolution: {integrity: sha512-FmPlWS7Dg6E3kP0vv19Pyhq3sqSi8tyn8IZh2RV73UsrcEZeQ3gUTf2Ar8iPRgbsxTukQHRoMGcaCVBsFVRVPw==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.4.1 - '@opentelemetry/core': ^2.0.0 - - '@opentelemetry/context-async-hooks@2.0.1': - resolution: {integrity: sha512-XuY23lSI3d4PEqKA+7SLtAgwqIfc6E/E9eAQWLN1vlpC53ybO3o6jW4BsXo1xvz9lYyyWItfQDDLzezER01mCw==} + '@opentelemetry/context-async-hooks@2.1.0': + resolution: {integrity: sha512-zOyetmZppnwTyPrt4S7jMfXiSX9yyfF0hxlA8B5oo2TtKl+/RGCy7fi4DrBfIf3lCPrkKsRBWZZD7RFojK7FDg==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' - '@opentelemetry/core@2.0.1': - resolution: {integrity: sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw==} + '@opentelemetry/core@2.1.0': + resolution: {integrity: sha512-RMEtHsxJs/GiHHxYT58IY57UXAQTuUnZVco6ymDEqTNlJKTimM4qPUPVe8InNFyBjhHBEAx4k3Q8LtNayBsbUQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' - '@opentelemetry/exporter-logs-otlp-grpc@0.203.0': - resolution: {integrity: sha512-g/2Y2noc/l96zmM+g0LdeuyYKINyBwN6FJySoU15LHPLcMN/1a0wNk2SegwKcxrRdE7Xsm7fkIR5n6XFe3QpPw==} + '@opentelemetry/exporter-logs-otlp-grpc@0.206.0': + resolution: {integrity: sha512-kJKxKBaGwqWop95d6tcluz260IWwIgOG0BH8oVm6429tg8LxY2PJb7Om8d5s+5vOFM8DkUYCnIpn9d/13/RcKQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/exporter-logs-otlp-http@0.203.0': - resolution: {integrity: sha512-s0hys1ljqlMTbXx2XiplmMJg9wG570Z5lH7wMvrZX6lcODI56sG4HL03jklF63tBeyNwK2RV1/ntXGo3HgG4Qw==} + '@opentelemetry/exporter-logs-otlp-http@0.206.0': + resolution: {integrity: sha512-VWcHEnS+1kN+sQTAdCgSn2anqHPxY1/e52fhpe2mcSnEaXI1srFf3RU5DAu7hzQO6T9DPQzOKG8kc76vCtyYDw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/exporter-logs-otlp-proto@0.203.0': - resolution: {integrity: sha512-nl/7S91MXn5R1aIzoWtMKGvqxgJgepB/sH9qW0rZvZtabnsjbf8OQ1uSx3yogtvLr0GzwD596nQKz2fV7q2RBw==} + '@opentelemetry/exporter-logs-otlp-proto@0.206.0': + resolution: {integrity: sha512-CsYNXJwkn1qCXJGE+/JvvYucAjL8rpaxa2hnl+tDP6M5E0O3UVa8zG4ZUEebjr5J5Nc32egvslEZx5rgNOp3lQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/exporter-metrics-otlp-grpc@0.203.0': - resolution: {integrity: sha512-FCCj9nVZpumPQSEI57jRAA89hQQgONuoC35Lt+rayWY/mzCAc6BQT7RFyFaZKJ2B7IQ8kYjOCPsF/HGFWjdQkQ==} + '@opentelemetry/exporter-metrics-otlp-grpc@0.206.0': + resolution: {integrity: sha512-/qGIwVa27BSGqzULB34O+UtEVl4isc+gEd2ydMfZVidWpdkJYbMeZZYBWi4z6giD0w0Dep5k/NIJ/lSEZoKEIg==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/exporter-metrics-otlp-http@0.203.0': - resolution: {integrity: sha512-HFSW10y8lY6BTZecGNpV3GpoSy7eaO0Z6GATwZasnT4bEsILp8UJXNG5OmEsz4SdwCSYvyCbTJdNbZP3/8LGCQ==} + '@opentelemetry/exporter-metrics-otlp-http@0.206.0': + resolution: {integrity: sha512-u6ztHNbgNlFw3vCuOErGsiiEcDk9KB0pwd/Jv6aPnvV4oKJd/5K+lfiSjDpCFUh5UUFJdGmHtADxUgbRpYMPyA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/exporter-metrics-otlp-proto@0.203.0': - resolution: {integrity: sha512-OZnhyd9npU7QbyuHXFEPVm3LnjZYifuKpT3kTnF84mXeEQ84pJJZgyLBpU4FSkSwUkt/zbMyNAI7y5+jYTWGIg==} + '@opentelemetry/exporter-metrics-otlp-proto@0.206.0': + resolution: {integrity: sha512-mLlmXmVOSwMw8Cm9RKz5ZuTUWW28lQWWIcy5cpEUhIrJ5cuSuTZ/PKIaa3+CHmcKkkF2pWFdBkzOIar9aApzoQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/exporter-prometheus@0.203.0': - resolution: {integrity: sha512-2jLuNuw5m4sUj/SncDf/mFPabUxMZmmYetx5RKIMIQyPnl6G6ooFzfeE8aXNRf8YD1ZXNlCnRPcISxjveGJHNg==} + '@opentelemetry/exporter-prometheus@0.206.0': + resolution: {integrity: sha512-sCzW+vE2KhlDZhH73f7drr+d0kvlsqG02t9xGtG40c6t4hjgpa5qEwEZTzFo9s4djtUrmDBjwJ5S3NYuCERVKg==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/exporter-trace-otlp-grpc@0.203.0': - resolution: {integrity: sha512-322coOTf81bm6cAA8+ML6A+m4r2xTCdmAZzGNTboPXRzhwPt4JEmovsFAs+grpdarObd68msOJ9FfH3jxM6wqA==} + '@opentelemetry/exporter-trace-otlp-grpc@0.206.0': + resolution: {integrity: sha512-/q8sU9wj20tT9m+529VXN9E9DzpvNui5Cict8onY/gRGeXqTav21xHkvmv0FSpetb/29WS89drVjfI8/Mf2iWQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/exporter-trace-otlp-http@0.203.0': - resolution: {integrity: sha512-ZDiaswNYo0yq/cy1bBLJFe691izEJ6IgNmkjm4C6kE9ub/OMQqDXORx2D2j8fzTBTxONyzusbaZlqtfmyqURPw==} + '@opentelemetry/exporter-trace-otlp-http@0.206.0': + resolution: {integrity: sha512-xiEhJZxE9yDb13FVW4XaF7J56boLv1NALOGEVu3F8jMC24iZmX5TSVRJCNGLWyy1Xb3N27Yu31kdSsmEBCnxyw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/exporter-trace-otlp-proto@0.203.0': - resolution: {integrity: sha512-1xwNTJ86L0aJmWRwENCJlH4LULMG2sOXWIVw+Szta4fkqKVY50Eo4HoVKKq6U9QEytrWCr8+zjw0q/ZOeXpcAQ==} + '@opentelemetry/exporter-trace-otlp-proto@0.206.0': + resolution: {integrity: sha512-A3lGp39qqZGt6PU/9X682/4KdkDMu+jO+slnNCdm8Zki3AKEFulY2yYtz4rL0rah/liN+ENRsFQWI/B3xJiZGw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/exporter-zipkin@2.0.1': - resolution: {integrity: sha512-a9eeyHIipfdxzCfc2XPrE+/TI3wmrZUDFtG2RRXHSbZZULAny7SyybSvaDvS77a7iib5MPiAvluwVvbGTsHxsw==} + '@opentelemetry/exporter-zipkin@2.1.0': + resolution: {integrity: sha512-0mEI0VDZrrX9t5RE1FhAyGz+jAGt96HSuXu73leswtY3L5YZD11gtcpARY2KAx/s6Z2+rj5Mhj566JsI2C7mfA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.0.0 @@ -3267,364 +3357,112 @@ packages: peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-amqplib@0.50.0': - resolution: {integrity: sha512-kwNs/itehHG/qaQBcVrLNcvXVPW0I4FCOVtw3LHMLdYIqD7GJ6Yv2nX+a4YHjzbzIeRYj8iyMp0Bl7tlkidq5w==} + '@opentelemetry/instrumentation-http@0.206.0': + resolution: {integrity: sha512-U355U6PpRSj5NDLqI8uY2SPp4uapuGASSGFLPoQbrqphHQ6pJrHDFBTR72a+S5XvHJo1PlLS84k4IOl+tXYPsA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-aws-lambda@0.54.0': - resolution: {integrity: sha512-uiYI+kcMUJ/H9cxAwB8c9CaG8behLRgcYSOEA8M/tMQ54Y1ZmzAuEE3QKOi21/s30x5Q+by9g7BwiVfDtqzeMA==} + '@opentelemetry/instrumentation-ioredis@0.54.0': + resolution: {integrity: sha512-SkGBzieEHnpfeYB112R9wzshtpqZkQ0DUHm1DhminO4KYIOTyGS7NkaZlIcRUsmMg3/1Tk1HqEVjSdCO2rOXfA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-aws-sdk@0.57.0': - resolution: {integrity: sha512-RfbyjaeZzX3mPhuaRHlSAQyfX3skfeWOl30jrqSXtE9k0DPdnIqpHhdYS0C/DEDuZbwTmruVJ4cUwMBw5Z6FAg==} + '@opentelemetry/instrumentation-nestjs-core@0.53.0': + resolution: {integrity: sha512-8sDcdwPb6fJ2ayD7Q7H2Vxwj21ao8Atuvm+RtPzAdrOvqEWTigpO99LJaEsZRRphJTdRBejg07/oYQzJusPODQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-bunyan@0.49.0': - resolution: {integrity: sha512-ky5Am1y6s3Ex/3RygHxB/ZXNG07zPfg9Z6Ora+vfeKcr/+I6CJbWXWhSBJor3gFgKN3RvC11UWVURnmDpBS6Pg==} + '@opentelemetry/instrumentation-pg@0.59.0': + resolution: {integrity: sha512-26Q6wwsx84K8KNX/CZ2q6ZRv2hIzPawRpL0og+Ro4BHN8Qin+ktkqFDlF2n83KPJn/tFstz3nErue+DAVXAGTw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-cassandra-driver@0.49.0': - resolution: {integrity: sha512-BNIvqldmLkeikfI5w5Rlm9vG5NnQexfPoxOgEMzfDVOEF+vS6351I6DzWLLgWWR9CNF/jQJJi/lr6am2DLp0Rw==} + '@opentelemetry/instrumentation@0.206.0': + resolution: {integrity: sha512-anPU9GAn3vSH/0JFQZ4e626xRw8p8R21kxM7xammFk9BRhfDw1IpgqvFMllbb+1MSHHEX9EiUqYHJyWo/B6KGA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-connect@0.47.0': - resolution: {integrity: sha512-pjenvjR6+PMRb6/4X85L4OtkQCootgb/Jzh/l/Utu3SJHBid1F+gk9sTGU2FWuhhEfV6P7MZ7BmCdHXQjgJ42g==} + '@opentelemetry/otlp-exporter-base@0.206.0': + resolution: {integrity: sha512-Rv54oSNKMHYS5hv+H5EGksfBUtvPQWFTK+Dk6MjJun9tOijCsFJrhRFvAqg5d67TWSMn+ZQYRKIeXh5oLVrpAQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-cucumber@0.18.1': - resolution: {integrity: sha512-gTfT7AuA0UH0TvqWOXnyr2KCv7mvZsOUmqCrtnU/RDcZ9J3nIX4OBfl7VVXE0fJlLqP7KIDggQ8O9g7rmaVLhA==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.0.0 - - '@opentelemetry/instrumentation-dataloader@0.21.1': - resolution: {integrity: sha512-hNAm/bwGawLM8VDjKR0ZUDJ/D/qKR3s6lA5NV+btNaPVm2acqhPcT47l2uCVi+70lng2mywfQncor9v8/ykuyw==} + '@opentelemetry/otlp-grpc-exporter-base@0.206.0': + resolution: {integrity: sha512-IA8EDbrB8OKtidMqErBY8sUc9mh03LOXuNPwp4/rdPrxSt45g1gBuZMovRXdEWfRyKKbF2E7MdipT2m11bs6SQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-dns@0.47.0': - resolution: {integrity: sha512-775fOnewWkTF4iXMGKgwvOGqEmPrU1PZpXjjqvTrEErYBJe7Fz1WlEeUStHepyKOdld7Ghv7TOF/kE3QDctvrg==} + '@opentelemetry/otlp-transformer@0.206.0': + resolution: {integrity: sha512-Li2Cik1WnmNbU2mmTnw7DxvRiXhMcnAuTfAclP8y/zy7h5+GrLDpTZ+Z0XUs+Q3MLkb/h3ry4uFrC/z+2a6X7g==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-express@0.52.0': - resolution: {integrity: sha512-W7pizN0Wh1/cbNhhTf7C62NpyYw7VfCFTYg0DYieSTrtPBT1vmoSZei19wfKLnrMsz3sHayCg0HxCVL2c+cz5w==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-fastify@0.48.0': - resolution: {integrity: sha512-3zQlE/DoVfVH6/ycuTv7vtR/xib6WOa0aLFfslYcvE62z0htRu/ot8PV/zmMZfnzpTQj8S/4ULv36R6UIbpJIg==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-fs@0.23.0': - resolution: {integrity: sha512-Puan+QopWHA/KNYvDfOZN6M/JtF6buXEyD934vrb8WhsX1/FuM7OtoMlQyIqAadnE8FqqDL4KDPiEfCQH6pQcQ==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-generic-pool@0.47.0': - resolution: {integrity: sha512-UfHqf3zYK+CwDwEtTjaD12uUqGGTswZ7ofLBEdQ4sEJp9GHSSJMQ2hT3pgBxyKADzUdoxQAv/7NqvL42ZI+Qbw==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-graphql@0.51.0': - resolution: {integrity: sha512-LchkOu9X5DrXAnPI1+Z06h/EH/zC7D6sA86hhPrk3evLlsJTz0grPrkL/yUJM9Ty0CL/y2HSvmWQCjbJEz/ADg==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-grpc@0.203.0': - resolution: {integrity: sha512-Qmjx2iwccHYRLoE4RFS46CvQE9JG9Pfeae4EPaNZjvIuJxb/pZa2R9VWzRlTehqQWpAvto/dGhtkw8Tv+o0LTg==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-hapi@0.50.0': - resolution: {integrity: sha512-5xGusXOFQXKacrZmDbpHQzqYD1gIkrMWuwvlrEPkYOsjUqGUjl1HbxCsn5Y9bUXOCgP1Lj6A4PcKt1UiJ2MujA==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-http@0.203.0': - resolution: {integrity: sha512-y3uQAcCOAwnO6vEuNVocmpVzG3PER6/YZqbPbbffDdJ9te5NkHEkfSMNzlC3+v7KlE+WinPGc3N7MR30G1HY2g==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-ioredis@0.51.0': - resolution: {integrity: sha512-9IUws0XWCb80NovS+17eONXsw1ZJbHwYYMXiwsfR9TSurkLV5UNbRSKb9URHO+K+pIJILy9wCxvyiOneMr91Ig==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-kafkajs@0.13.0': - resolution: {integrity: sha512-FPQyJsREOaGH64hcxlzTsIEQC4DYANgTwHjiB7z9lldmvua1LRMVn3/FfBlzXoqF179B0VGYviz6rn75E9wsDw==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-knex@0.48.0': - resolution: {integrity: sha512-V5wuaBPv/lwGxuHjC6Na2JFRjtPgstw19jTFl1B1b6zvaX8zVDYUDaR5hL7glnQtUSCMktPttQsgK4dhXpddcA==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-koa@0.51.0': - resolution: {integrity: sha512-XNLWeMTMG1/EkQBbgPYzCeBD0cwOrfnn8ao4hWgLv0fNCFQu1kCsJYygz2cvKuCs340RlnG4i321hX7R8gj3Rg==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-lru-memoizer@0.48.0': - resolution: {integrity: sha512-KUW29wfMlTPX1wFz+NNrmE7IzN7NWZDrmFWHM/VJcmFEuQGnnBuTIdsP55CnBDxKgQ/qqYFp4udQFNtjeFosPw==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-memcached@0.47.0': - resolution: {integrity: sha512-vXDs/l4hlWy1IepPG1S6aYiIZn+tZDI24kAzwKKJmR2QEJRL84PojmALAEJGazIOLl/VdcCPZdMb0U2K0VzojA==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-mongodb@0.56.0': - resolution: {integrity: sha512-YG5IXUUmxX3Md2buVMvxm9NWlKADrnavI36hbJsihqqvBGsWnIfguf0rUP5Srr0pfPqhQjUP+agLMsvu0GmUpA==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-mongoose@0.50.0': - resolution: {integrity: sha512-Am8pk1Ct951r4qCiqkBcGmPIgGhoDiFcRtqPSLbJrUZqEPUsigjtMjoWDRLG1Ki1NHgOF7D0H7d+suWz1AAizw==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-mysql2@0.50.0': - resolution: {integrity: sha512-PoOMpmq73rOIE3nlTNLf3B1SyNYGsp7QXHYKmeTZZnJ2Ou7/fdURuOhWOI0e6QZ5gSem18IR1sJi6GOULBQJ9g==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-mysql@0.49.0': - resolution: {integrity: sha512-QU9IUNqNsrlfE3dJkZnFHqLjlndiU39ll/YAAEvWE40sGOCi9AtOF6rmEGzJ1IswoZ3oyePV7q2MP8SrhJfVAA==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-nestjs-core@0.49.0': - resolution: {integrity: sha512-1R/JFwdmZIk3T/cPOCkVvFQeKYzbbUvDxVH3ShXamUwBlGkdEu5QJitlRMyVNZaHkKZKWgYrBarGQsqcboYgaw==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-net@0.47.0': - resolution: {integrity: sha512-csoJ++Njpf7C09JH+0HNGenuNbDZBqO1rFhMRo6s0rAmJwNh9zY3M/urzptmKlqbKnf4eH0s+CKHy/+M8fbFsQ==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-oracledb@0.29.0': - resolution: {integrity: sha512-2aHLiJdkyiUbooIUm7FaZf+O4jyqEl+RfFpgud1dxT87QeeYM216wi+xaMNzsb5yKtRBqbA3qeHBCyenYrOZwA==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-pg@0.56.0': - resolution: {integrity: sha512-A/J4SlGX8Y0Wwp7Y66fsNCFT/1h9lmBzqwTnfWW/bULtcKFqkQfqhs3G8+4cRxX02UI2z7T1aW5bsyc6QSYc1Q==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-pino@0.50.0': - resolution: {integrity: sha512-Pi0cWGp4f2gresq2xqef4IsuunLdebJ9n9tZxytDz2ci4euIfW36ILpszQmRNhwCVDCZLmUgGDKZGj4PXyPd0w==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-redis@0.51.0': - resolution: {integrity: sha512-uL/GtBA0u72YPPehwOvthAe+Wf8k3T+XQPBssJmTYl6fzuZjNq8zTfxVFhl9nRFjFVEe+CtiYNT0Q3AyqW1Z0A==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-restify@0.49.0': - resolution: {integrity: sha512-tsGZZhS4mVZH7omYxw5jpsrD3LhWizqWc0PYtAnzpFUvL5ZINHE+cm57bssTQ2AK/GtZMxu9LktwCvIIf3dSmw==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-router@0.48.0': - resolution: {integrity: sha512-Wixrc8CchuJojXpaS/dCQjFOMc+3OEil1H21G+WLYQb8PcKt5kzW9zDBT19nyjjQOx/D/uHPfgbrT+Dc7cfJ9w==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-runtime-node@0.17.1': - resolution: {integrity: sha512-c1FlAk+bB2uF9a8YneGmNPTl7c/xVaan4mmWvbkWcOmH/ipKqR1LaKUlz/BMzLrJLjho1EJlG2NrS2w2Arg+nw==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-socket.io@0.50.0': - resolution: {integrity: sha512-6JN6lnKN9ZuZtZdMQIR+no1qHzQvXSZUsNe3sSWMgqmNRyEXuDUWBIyKKeG0oHRHtR4xE4QhJyD4D5kKRPWZFA==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-tedious@0.22.0': - resolution: {integrity: sha512-XrrNSUCyEjH1ax9t+Uo6lv0S2FCCykcF7hSxBMxKf7Xn0bPRxD3KyFUZy25aQXzbbbUHhtdxj3r2h88SfEM3aA==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation-undici@0.14.0': - resolution: {integrity: sha512-2HN+7ztxAReXuxzrtA3WboAKlfP5OsPA57KQn2AdYZbJ3zeRPcLXyW4uO/jpLE6PLm0QRtmeGCmfYpqRlwgSwg==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.7.0 - - '@opentelemetry/instrumentation-winston@0.48.1': - resolution: {integrity: sha512-XyOuVwdziirHHYlsw+BWrvdI/ymjwnexupKA787zQQ+D5upaE/tseZxjfQa7+t4+FdVLxHICaMTmkSD4yZHpzQ==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/instrumentation@0.203.0': - resolution: {integrity: sha512-ke1qyM+3AK2zPuBPb6Hk/GCsc5ewbLvPNkEuELx/JmANeEp6ZjnZ+wypPAJSucTw0wvCGrUaibDSdcrGFoWxKQ==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/otlp-exporter-base@0.203.0': - resolution: {integrity: sha512-Wbxf7k+87KyvxFr5D7uOiSq/vHXWommvdnNE7vECO3tAhsA2GfOlpWINCMWUEPdHZ7tCXxw6Epp3vgx3jU7llQ==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/otlp-grpc-exporter-base@0.203.0': - resolution: {integrity: sha512-te0Ze1ueJF+N/UOFl5jElJW4U0pZXQ8QklgSfJ2linHN0JJsuaHG8IabEUi2iqxY8ZBDlSiz1Trfv5JcjWWWwQ==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/otlp-transformer@0.203.0': - resolution: {integrity: sha512-Y8I6GgoCna0qDQ2W6GCRtaF24SnvqvA8OfeTi7fqigD23u8Jpb4R5KFv/pRvrlGagcCLICMIyh9wiejp4TXu/A==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.3.0 - - '@opentelemetry/propagation-utils@0.31.3': - resolution: {integrity: sha512-ZI6LKjyo+QYYZY5SO8vfoCQ9A69r1/g+pyjvtu5RSK38npINN1evEmwqbqhbg2CdcIK3a4PN6pDAJz/yC5/gAA==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.0.0 - - '@opentelemetry/propagator-b3@2.0.1': - resolution: {integrity: sha512-Hc09CaQ8Tf5AGLmf449H726uRoBNGPBL4bjr7AnnUpzWMvhdn61F78z9qb6IqB737TffBsokGAK1XykFEZ1igw==} + '@opentelemetry/propagator-b3@2.1.0': + resolution: {integrity: sha512-yOdHmFseIChYanddMMz0mJIFQHyjwbNhoxc65fEAA8yanxcBPwoFDoh1+WBUWAO/Z0NRgk+k87d+aFIzAZhcBw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' - '@opentelemetry/propagator-jaeger@2.0.1': - resolution: {integrity: sha512-7PMdPBmGVH2eQNb/AtSJizQNgeNTfh6jQFqys6lfhd6P4r+m/nTh3gKPPpaCXVdRQ+z93vfKk+4UGty390283w==} + '@opentelemetry/propagator-jaeger@2.1.0': + resolution: {integrity: sha512-QYo7vLyMjrBCUTpwQBF/e+rvP7oGskrSELGxhSvLj5gpM0az9oJnu/0O4l2Nm7LEhAff80ntRYKkAcSwVgvSVQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' - '@opentelemetry/redis-common@0.38.0': - resolution: {integrity: sha512-4Wc0AWURII2cfXVVoZ6vDqK+s5n4K5IssdrlVrvGsx6OEOKdghKtJZqXAHWFiZv4nTDLH2/2fldjIHY8clMOjQ==} + '@opentelemetry/redis-common@0.38.2': + resolution: {integrity: sha512-1BCcU93iwSRZvDAgwUxC/DV4T/406SkMfxGqu5ojc3AvNI+I9GhV7v0J1HljsczuuhcnFLYqD5VmwVXfCGHzxA==} engines: {node: ^18.19.0 || >=20.6.0} - '@opentelemetry/resource-detector-alibaba-cloud@0.31.3': - resolution: {integrity: sha512-I556LHcLVsBXEgnbPgQISP/JezDt5OfpgOaJNR1iVJl202r+K145OSSOxnH5YOc/KvrydBD0FOE03F7x0xnVTw==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.0.0 - - '@opentelemetry/resource-detector-aws@2.3.0': - resolution: {integrity: sha512-PkD/lyXG3B3REq1Y6imBLckljkJYXavtqGYSryAeJYvGOf5Ds3doR+BCGjmKeF6ObAtI5MtpBeUStTDtGtBsWA==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.0.0 - - '@opentelemetry/resource-detector-azure@0.10.0': - resolution: {integrity: sha512-5cNAiyPBg53Uxe/CW7hsCq8HiKNAUGH+gi65TtgpzSR9bhJG4AEbuZhbJDFwe97tn2ifAD1JTkbc/OFuaaFWbA==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.0.0 - - '@opentelemetry/resource-detector-container@0.7.3': - resolution: {integrity: sha512-SK+xUFw6DKYbQniaGmIFsFxAZsr8RpRSRWxKi5/ZJAoqqPnjcyGI/SeUx8zzPk4XLO084zyM4pRHgir0hRTaSQ==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.0.0 - - '@opentelemetry/resource-detector-gcp@0.37.0': - resolution: {integrity: sha512-LGpJBECIMsVKhiulb4nxUw++m1oF4EiDDPmFGW2aqYaAF0oUvJNv8Z/55CAzcZ7SxvlTgUwzewXDBsuCup7iqw==} - engines: {node: ^18.19.0 || >=20.6.0} - peerDependencies: - '@opentelemetry/api': ^1.0.0 - - '@opentelemetry/resources@2.0.1': - resolution: {integrity: sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw==} + '@opentelemetry/resources@2.1.0': + resolution: {integrity: sha512-1CJjf3LCvoefUOgegxi8h6r4B/wLSzInyhGP2UmIBYNlo4Qk5CZ73e1eEyWmfXvFtm1ybkmfb2DqWvspsYLrWw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.3.0 <1.10.0' - '@opentelemetry/sdk-logs@0.203.0': - resolution: {integrity: sha512-vM2+rPq0Vi3nYA5akQD2f3QwossDnTDLvKbea6u/A2NZ3XDkPxMfo/PNrDoXhDUD/0pPo2CdH5ce/thn9K0kLw==} + '@opentelemetry/sdk-logs@0.206.0': + resolution: {integrity: sha512-SQ2yTmqe4Mw9RI3a/glVkfjWPsXh6LySvnljXubiZq4zu+UP8NMJt2j82ZsYb+KpD7Eu+/41/7qlJnjdeVjz7Q==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.4.0 <1.10.0' - '@opentelemetry/sdk-metrics@2.0.1': - resolution: {integrity: sha512-wf8OaJoSnujMAHWR3g+/hGvNcsC16rf9s1So4JlMiFaFHiE4HpIA3oUh+uWZQ7CNuK8gVW/pQSkgoa5HkkOl0g==} + '@opentelemetry/sdk-metrics@2.1.0': + resolution: {integrity: sha512-J9QX459mzqHLL9Y6FZ4wQPRZG4TOpMCyPOh6mkr/humxE1W2S3Bvf4i75yiMW9uyed2Kf5rxmLhTm/UK8vNkAw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.9.0 <1.10.0' - '@opentelemetry/sdk-node@0.203.0': - resolution: {integrity: sha512-zRMvrZGhGVMvAbbjiNQW3eKzW/073dlrSiAKPVWmkoQzah9wfynpVPeL55f9fVIm0GaBxTLcPeukWGy0/Wj7KQ==} + '@opentelemetry/sdk-node@0.206.0': + resolution: {integrity: sha512-t/2xYG1+pXK2M4jra48Gw6BS0E/hz4zYwuqC8G8JCTx9UQpCiFlaA3Yxbns79R1h6NbQz7NAe2kJO3/Jf9BoIA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.3.0 <1.10.0' - '@opentelemetry/sdk-trace-base@2.0.1': - resolution: {integrity: sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ==} + '@opentelemetry/sdk-trace-base@2.1.0': + resolution: {integrity: sha512-uTX9FBlVQm4S2gVQO1sb5qyBLq/FPjbp+tmGoxu4tIgtYGmBYB44+KX/725RFDe30yBSaA9Ml9fqphe1hbUyLQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.3.0 <1.10.0' - '@opentelemetry/sdk-trace-node@2.0.1': - resolution: {integrity: sha512-UhdbPF19pMpBtCWYP5lHbTogLWx9N0EBxtdagvkn5YtsAnCBZzL7SjktG+ZmupRgifsHMjwUaCCaVmqGfSADmA==} + '@opentelemetry/sdk-trace-node@2.1.0': + resolution: {integrity: sha512-SvVlBFc/jI96u/mmlKm86n9BbTCbQ35nsPoOohqJX6DXH92K0kTe73zGY5r8xoI1QkjR9PizszVJLzMC966y9Q==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' - '@opentelemetry/semantic-conventions@1.36.0': - resolution: {integrity: sha512-TtxJSRD8Ohxp6bKkhrm27JRHAxPczQA7idtcTOMYI+wQRRrfgqxHv1cFbCApcSnNjtXkmzFozn6jQtFrOmbjPQ==} + '@opentelemetry/semantic-conventions@1.37.0': + resolution: {integrity: sha512-JD6DerIKdJGmRp4jQyX5FlrQjA4tjOw1cvfsPAZXfOOEErMUHjPcPSICS+6WnM0nB0efSFARh0KAZss+bvExOA==} engines: {node: '>=14'} - '@opentelemetry/sql-common@0.41.0': - resolution: {integrity: sha512-pmzXctVbEERbqSfiAgdes9Y63xjoOyXcD7B6IXBkVb+vbM7M9U98mn33nGXxPf4dfYR0M+vhcKRZmbSJ7HfqFA==} + '@opentelemetry/sql-common@0.41.2': + resolution: {integrity: sha512-4mhWm3Z8z+i508zQJ7r6Xi7y4mmoJpdvH0fZPFRkWrdp5fq7hhZ2HhYokEOLkfqSMgPR4Z9EyB3DBkbKGOqZiQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.1.0 @@ -3632,30 +3470,30 @@ packages: '@paralleldrive/cuid2@2.2.2': resolution: {integrity: sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==} - '@photo-sphere-viewer/core@5.13.4': - resolution: {integrity: sha512-leVQL6gG9wTF+uvCFarHUcr8mzafCZ/GLzauksYQJfiqDVRFSAJNXnTOy7RH9otToluEdjN1hsN1f9HQy+rLYg==} + '@photo-sphere-viewer/core@5.14.0': + resolution: {integrity: sha512-V0JeDSB1D2Q60Zqn7+0FPjq8gqbKEwuxMzNdTLydefkQugVztLvdZykO+4k5XTpweZ2QAWPH/QOI1xZbsdvR9A==} - '@photo-sphere-viewer/equirectangular-video-adapter@5.13.4': - resolution: {integrity: sha512-OdTOKxFunP56FNoPR47mQp7V1WHvV4eiow3qtyJjAgLeU8T2q3kivLuH1kMZN2yTAJaXab+VBXzA/YChiHZ6mQ==} + '@photo-sphere-viewer/equirectangular-video-adapter@5.14.0': + resolution: {integrity: sha512-Ez88sZ4sj3fONpZSortnN3gLXlvV/hn5U/88LsWtxI73YwhkZ06ZtXFYLXU4MBaJvqCbMGaR6j39uVXTWFo5rw==} peerDependencies: - '@photo-sphere-viewer/core': 5.13.4 - '@photo-sphere-viewer/video-plugin': 5.13.4 + '@photo-sphere-viewer/core': 5.14.0 + '@photo-sphere-viewer/video-plugin': 5.14.0 - '@photo-sphere-viewer/resolution-plugin@5.13.4': - resolution: {integrity: sha512-HRBC5zYmpNoo/joKZzXbxn7jwoh3tdtTJFXzHxYPV51ELDclRNmzhmqEaZeVkrFHr4bRF5ow3AOjxiMtu1xQxA==} + '@photo-sphere-viewer/resolution-plugin@5.14.0': + resolution: {integrity: sha512-PvDMX1h+8FzWdySxiorQ2bSmyBGTPsZjNNFRBqIfmb5C+01aWCIE7kuXodXGHwpXQNcOojsVX9IiX0Vz4CiW4A==} peerDependencies: - '@photo-sphere-viewer/core': 5.13.4 - '@photo-sphere-viewer/settings-plugin': 5.13.4 + '@photo-sphere-viewer/core': 5.14.0 + '@photo-sphere-viewer/settings-plugin': 5.14.0 - '@photo-sphere-viewer/settings-plugin@5.13.4': - resolution: {integrity: sha512-As1nmlsfnjKBFQOWPVQLH1+dJ+s62MdEb6Jvlm16+3fUVHF4CBWRTJZyBKejLiu4xjbDxrE8v5ZHDLvG6ButiQ==} + '@photo-sphere-viewer/settings-plugin@5.14.0': + resolution: {integrity: sha512-sMLX4hFSE2PjiP2iUmH9qUAz6GV+UN2WX1zu/D58BBWzF3+8mV+FC9l50qxruO8qvWqqLwYysHUElHnmPPtpTg==} peerDependencies: - '@photo-sphere-viewer/core': 5.13.4 + '@photo-sphere-viewer/core': 5.14.0 - '@photo-sphere-viewer/video-plugin@5.13.4': - resolution: {integrity: sha512-QWbHMVAJHukLbFNn0irND/nEPtmzjbXth1ckBkT1bg8aRilFw50+IIB0Zfdl6X919R2GfGo8P0u+I/Mwxf7yfg==} + '@photo-sphere-viewer/video-plugin@5.14.0': + resolution: {integrity: sha512-jWMZBNlfwYq8Lgc8ncs3ptwHR6Yk7Wl8o1BCFYhmhoRkGZFHEjoOQj7gMPXCET+3iYXQ1TsjTh4ZCW8UUOi+pg==} peerDependencies: - '@photo-sphere-viewer/core': 5.13.4 + '@photo-sphere-viewer/core': 5.14.0 '@photostructure/tz-lookup@11.2.0': resolution: {integrity: sha512-DwrvodcXHNSdGdeSF7SBL5o8aBlsaeuCuG7633F04nYsL3hn5Hxe3z/5kCqxv61J1q7ggKZ27GPylR3x0cPNXQ==} @@ -3668,8 +3506,8 @@ packages: resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@playwright/test@1.54.2': - resolution: {integrity: sha512-A+znathYxPf+72riFd1r1ovOLqsIIB0jKIoPjyK2kqEIe30/6jF6BC7QNluHuwUmsD2tv1XZVugN8GqfTMOxsA==} + '@playwright/test@1.56.0': + resolution: {integrity: sha512-Tzh95Twig7hUwwNe381/K3PggZBZblKUe2wv25oIpzWLr6Z0m4KgV1ZVIjnR6GM9ANEqjZD7XsZEa6JL/7YEgg==} engines: {node: '>=18'} hasBin: true @@ -3747,8 +3585,8 @@ packages: peerDependencies: react: ^18.0 || ^19.0 || ^19.0.0-rc - '@react-email/components@0.5.0': - resolution: {integrity: sha512-esRbP+yMmSkNP9hcpiy2RwpDnvSmlxJcJ1HHbzSwlACGlCHTap+ma344QovvzhpVRhMccyWemdClLG822UvVpQ==} + '@react-email/components@0.5.6': + resolution: {integrity: sha512-3o9ellDaF3bBcVMWeos9HI0iUIT1zGygPRcn9WSfI5JREORiN6ViEJIvz5SKWEn1KPNZtw/iaW8ct7PpVyhomg==} engines: {node: '>=18.0.0'} peerDependencies: react: ^18.0 || ^19.0 || ^19.0.0-rc @@ -3812,8 +3650,8 @@ packages: peerDependencies: react: ^18.0 || ^19.0 || ^19.0.0-rc - '@react-email/render@1.2.0': - resolution: {integrity: sha512-5fpbV16VYR9Fmk8t7xiwPNAjxjdI8XzVtlx9J9OkhOsIHdr2s5DwAj8/MXzWa9qRYJyLirQ/l7rBSjjgyRAomw==} + '@react-email/render@1.3.2': + resolution: {integrity: sha512-oq8/BD/I/YspeuBjjdLJG6xaf9tsPYk+VWu8/mX9xWbRN0t0ExKSVm9sEBL6RsCpndQA2jbY2VgPEreIrzUgqw==} engines: {node: '>=18.0.0'} peerDependencies: react: ^18.0 || ^19.0 || ^19.0.0-rc @@ -3843,19 +3681,8 @@ packages: peerDependencies: react: ^18.0 || ^19.0 || ^19.0.0-rc - '@reduxjs/toolkit@1.9.7': - resolution: {integrity: sha512-t7v8ZPxhhKgOKtU+uyJT13lu4vL7az5aFi4IdoDs/eS548edn2M8Ik9h8fxgvMjGoAUVFSt6ZC1P5cWmQ014QQ==} - peerDependencies: - react: ^16.9.0 || ^17.0.0 || ^18 - react-redux: ^7.2.1 || ^8.0.2 - peerDependenciesMeta: - react: - optional: true - react-redux: - optional: true - - '@rollup/pluginutils@5.2.0': - resolution: {integrity: sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==} + '@rollup/pluginutils@5.3.0': + resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} engines: {node: '>=14.0.0'} peerDependencies: rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 @@ -3863,103 +3690,113 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.46.3': - resolution: {integrity: sha512-UmTdvXnLlqQNOCJnyksjPs1G4GqXNGW1LrzCe8+8QoaLhhDeTXYBgJ3k6x61WIhlHX2U+VzEJ55TtIjR/HTySA==} + '@rollup/rollup-android-arm-eabi@4.52.4': + resolution: {integrity: sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.46.3': - resolution: {integrity: sha512-8NoxqLpXm7VyeI0ocidh335D6OKT0UJ6fHdnIxf3+6oOerZZc+O7r+UhvROji6OspyPm+rrIdb1gTXtVIqn+Sg==} + '@rollup/rollup-android-arm64@4.52.4': + resolution: {integrity: sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.46.3': - resolution: {integrity: sha512-csnNavqZVs1+7/hUKtgjMECsNG2cdB8F7XBHP6FfQjqhjF8rzMzb3SLyy/1BG7YSfQ+bG75Ph7DyedbUqwq1rA==} + '@rollup/rollup-darwin-arm64@4.52.4': + resolution: {integrity: sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.46.3': - resolution: {integrity: sha512-r2MXNjbuYabSIX5yQqnT8SGSQ26XQc8fmp6UhlYJd95PZJkQD1u82fWP7HqvGUf33IsOC6qsiV+vcuD4SDP6iw==} + '@rollup/rollup-darwin-x64@4.52.4': + resolution: {integrity: sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.46.3': - resolution: {integrity: sha512-uluObTmgPJDuJh9xqxyr7MV61Imq+0IvVsAlWyvxAaBSNzCcmZlhfYcRhCdMaCsy46ccZa7vtDDripgs9Jkqsw==} + '@rollup/rollup-freebsd-arm64@4.52.4': + resolution: {integrity: sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.46.3': - resolution: {integrity: sha512-AVJXEq9RVHQnejdbFvh1eWEoobohUYN3nqJIPI4mNTMpsyYN01VvcAClxflyk2HIxvLpRcRggpX1m9hkXkpC/A==} + '@rollup/rollup-freebsd-x64@4.52.4': + resolution: {integrity: sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.46.3': - resolution: {integrity: sha512-byyflM+huiwHlKi7VHLAYTKr67X199+V+mt1iRgJenAI594vcmGGddWlu6eHujmcdl6TqSNnvqaXJqZdnEWRGA==} + '@rollup/rollup-linux-arm-gnueabihf@4.52.4': + resolution: {integrity: sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.46.3': - resolution: {integrity: sha512-aLm3NMIjr4Y9LklrH5cu7yybBqoVCdr4Nvnm8WB7PKCn34fMCGypVNpGK0JQWdPAzR/FnoEoFtlRqZbBBLhVoQ==} + '@rollup/rollup-linux-arm-musleabihf@4.52.4': + resolution: {integrity: sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.46.3': - resolution: {integrity: sha512-VtilE6eznJRDIoFOzaagQodUksTEfLIsvXymS+UdJiSXrPW7Ai+WG4uapAc3F7Hgs791TwdGh4xyOzbuzIZrnw==} + '@rollup/rollup-linux-arm64-gnu@4.52.4': + resolution: {integrity: sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.46.3': - resolution: {integrity: sha512-dG3JuS6+cRAL0GQ925Vppafi0qwZnkHdPeuZIxIPXqkCLP02l7ka+OCyBoDEv8S+nKHxfjvjW4OZ7hTdHkx8/w==} + '@rollup/rollup-linux-arm64-musl@4.52.4': + resolution: {integrity: sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loongarch64-gnu@4.46.3': - resolution: {integrity: sha512-iU8DxnxEKJptf8Vcx4XvAUdpkZfaz0KWfRrnIRrOndL0SvzEte+MTM7nDH4A2Now4FvTZ01yFAgj6TX/mZl8hQ==} + '@rollup/rollup-linux-loong64-gnu@4.52.4': + resolution: {integrity: sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-ppc64-gnu@4.46.3': - resolution: {integrity: sha512-VrQZp9tkk0yozJoQvQcqlWiqaPnLM6uY1qPYXvukKePb0fqaiQtOdMJSxNFUZFsGw5oA5vvVokjHrx8a9Qsz2A==} + '@rollup/rollup-linux-ppc64-gnu@4.52.4': + resolution: {integrity: sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.46.3': - resolution: {integrity: sha512-uf2eucWSUb+M7b0poZ/08LsbcRgaDYL8NCGjUeFMwCWFwOuFcZ8D9ayPl25P3pl+D2FH45EbHdfyUesQ2Lt9wA==} + '@rollup/rollup-linux-riscv64-gnu@4.52.4': + resolution: {integrity: sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.46.3': - resolution: {integrity: sha512-7tnUcDvN8DHm/9ra+/nF7lLzYHDeODKKKrh6JmZejbh1FnCNZS8zMkZY5J4sEipy2OW1d1Ncc4gNHUd0DLqkSg==} + '@rollup/rollup-linux-riscv64-musl@4.52.4': + resolution: {integrity: sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.46.3': - resolution: {integrity: sha512-MUpAOallJim8CsJK+4Lc9tQzlfPbHxWDrGXZm2z6biaadNpvh3a5ewcdat478W+tXDoUiHwErX/dOql7ETcLqg==} + '@rollup/rollup-linux-s390x-gnu@4.52.4': + resolution: {integrity: sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.46.3': - resolution: {integrity: sha512-F42IgZI4JicE2vM2PWCe0N5mR5vR0gIdORPqhGQ32/u1S1v3kLtbZ0C/mi9FFk7C5T0PgdeyWEPajPjaUpyoKg==} + '@rollup/rollup-linux-x64-gnu@4.52.4': + resolution: {integrity: sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.46.3': - resolution: {integrity: sha512-oLc+JrwwvbimJUInzx56Q3ujL3Kkhxehg7O1gWAYzm8hImCd5ld1F2Gry5YDjR21MNb5WCKhC9hXgU7rRlyegQ==} + '@rollup/rollup-linux-x64-musl@4.52.4': + resolution: {integrity: sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.46.3': - resolution: {integrity: sha512-lOrQ+BVRstruD1fkWg9yjmumhowR0oLAAzavB7yFSaGltY8klttmZtCLvOXCmGE9mLIn8IBV/IFrQOWz5xbFPg==} + '@rollup/rollup-openharmony-arm64@4.52.4': + resolution: {integrity: sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.52.4': + resolution: {integrity: sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.46.3': - resolution: {integrity: sha512-vvrVKPRS4GduGR7VMH8EylCBqsDcw6U+/0nPDuIjXQRbHJc6xOBj+frx8ksfZAh6+Fptw5wHrN7etlMmQnPQVg==} + '@rollup/rollup-win32-ia32-msvc@4.52.4': + resolution: {integrity: sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.46.3': - resolution: {integrity: sha512-fi3cPxCnu3ZeM3EwKZPgXbWoGzm2XHgB/WShKI81uj8wG0+laobmqy5wbgEwzstlbLu4MyO8C19FyhhWseYKNQ==} + '@rollup/rollup-win32-x64-gnu@4.52.4': + resolution: {integrity: sha512-UF9KfsH9yEam0UjTwAgdK0anlQ7c8/pWPU2yVjyWcF1I1thABt6WXE47cI71pGiZ8wGvxohBoLnxM04L/wj8mQ==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.52.4': + resolution: {integrity: sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w==} cpu: [x64] os: [win32] @@ -3998,6 +3835,178 @@ packages: '@slorber/remark-comment@1.0.0': resolution: {integrity: sha512-RCE24n7jsOj1M0UPvIQCHTe7fI0sFL4S2nwKVWwHyVr/wI/H8GosgsJGyhnsZoGFnD/P2hLf1mSbrrgSLN93NA==} + '@smithy/abort-controller@4.2.0': + resolution: {integrity: sha512-PLUYa+SUKOEZtXFURBu/CNxlsxfaFGxSBPcStL13KpVeVWIfdezWyDqkz7iDLmwnxojXD0s5KzuB5HGHvt4Aeg==} + engines: {node: '>=18.0.0'} + + '@smithy/config-resolver@4.3.0': + resolution: {integrity: sha512-9oH+n8AVNiLPK/iK/agOsoWfrKZ3FGP3502tkksd6SRsKMYiu7AFX0YXo6YBADdsAj7C+G/aLKdsafIJHxuCkQ==} + engines: {node: '>=18.0.0'} + + '@smithy/core@3.15.0': + resolution: {integrity: sha512-VJWncXgt+ExNn0U2+Y7UywuATtRYaodGQKFo9mDyh70q+fJGedfrqi2XuKU1BhiLeXgg6RZrW7VEKfeqFhHAJA==} + engines: {node: '>=18.0.0'} + + '@smithy/credential-provider-imds@4.2.0': + resolution: {integrity: sha512-SOhFVvFH4D5HJZytb0bLKxCrSnwcqPiNlrw+S4ZXjMnsC+o9JcUQzbZOEQcA8yv9wJFNhfsUiIUKiEnYL68Big==} + engines: {node: '>=18.0.0'} + + '@smithy/fetch-http-handler@5.3.1': + resolution: {integrity: sha512-3AvYYbB+Dv5EPLqnJIAgYw/9+WzeBiUYS8B+rU0pHq5NMQMvrZmevUROS4V2GAt0jEOn9viBzPLrZE+riTNd5Q==} + engines: {node: '>=18.0.0'} + + '@smithy/hash-node@4.2.0': + resolution: {integrity: sha512-ugv93gOhZGysTctZh9qdgng8B+xO0cj+zN0qAZ+Sgh7qTQGPOJbMdIuyP89KNfUyfAqFSNh5tMvC+h2uCpmTtA==} + engines: {node: '>=18.0.0'} + + '@smithy/invalid-dependency@4.2.0': + resolution: {integrity: sha512-ZmK5X5fUPAbtvRcUPtk28aqIClVhbfcmfoS4M7UQBTnDdrNxhsrxYVv0ZEl5NaPSyExsPWqL4GsPlRvtlwg+2A==} + engines: {node: '>=18.0.0'} + + '@smithy/is-array-buffer@2.2.0': + resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} + engines: {node: '>=14.0.0'} + + '@smithy/is-array-buffer@4.2.0': + resolution: {integrity: sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-content-length@4.2.0': + resolution: {integrity: sha512-6ZAnwrXFecrA4kIDOcz6aLBhU5ih2is2NdcZtobBDSdSHtE9a+MThB5uqyK4XXesdOCvOcbCm2IGB95birTSOQ==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-endpoint@4.3.1': + resolution: {integrity: sha512-JtM4SjEgImLEJVXdsbvWHYiJ9dtuKE8bqLlvkvGi96LbejDL6qnVpVxEFUximFodoQbg0Gnkyff9EKUhFhVJFw==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-retry@4.4.1': + resolution: {integrity: sha512-wXxS4ex8cJJteL0PPQmWYkNi9QKDWZIpsndr0wZI2EL+pSSvA/qqxXU60gBOJoIc2YgtZSWY/PE86qhKCCKP1w==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-serde@4.2.0': + resolution: {integrity: sha512-rpTQ7D65/EAbC6VydXlxjvbifTf4IH+sADKg6JmAvhkflJO2NvDeyU9qsWUNBelJiQFcXKejUHWRSdmpJmEmiw==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-stack@4.2.0': + resolution: {integrity: sha512-G5CJ//eqRd9OARrQu9MK1H8fNm2sMtqFh6j8/rPozhEL+Dokpvi1Og+aCixTuwDAGZUkJPk6hJT5jchbk/WCyg==} + engines: {node: '>=18.0.0'} + + '@smithy/node-config-provider@4.3.0': + resolution: {integrity: sha512-5QgHNuWdT9j9GwMPPJCKxy2KDxZ3E5l4M3/5TatSZrqYVoEiqQrDfAq8I6KWZw7RZOHtVtCzEPdYz7rHZixwcA==} + engines: {node: '>=18.0.0'} + + '@smithy/node-http-handler@4.3.0': + resolution: {integrity: sha512-RHZ/uWCmSNZ8cneoWEVsVwMZBKy/8123hEpm57vgGXA3Irf/Ja4v9TVshHK2ML5/IqzAZn0WhINHOP9xl+Qy6Q==} + engines: {node: '>=18.0.0'} + + '@smithy/property-provider@4.2.0': + resolution: {integrity: sha512-rV6wFre0BU6n/tx2Ztn5LdvEdNZ2FasQbPQmDOPfV9QQyDmsCkOAB0osQjotRCQg+nSKFmINhyda0D3AnjSBJw==} + engines: {node: '>=18.0.0'} + + '@smithy/protocol-http@5.3.0': + resolution: {integrity: sha512-6POSYlmDnsLKb7r1D3SVm7RaYW6H1vcNcTWGWrF7s9+2noNYvUsm7E4tz5ZQ9HXPmKn6Hb67pBDRIjrT4w/d7Q==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-builder@4.2.0': + resolution: {integrity: sha512-Q4oFD0ZmI8yJkiPPeGUITZj++4HHYCW3pYBYfIobUCkYpI6mbkzmG1MAQQ3lJYYWj3iNqfzOenUZu+jqdPQ16A==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-parser@4.2.0': + resolution: {integrity: sha512-BjATSNNyvVbQxOOlKse0b0pSezTWGMvA87SvoFoFlkRsKXVsN3bEtjCxvsNXJXfnAzlWFPaT9DmhWy1vn0sNEA==} + engines: {node: '>=18.0.0'} + + '@smithy/service-error-classification@4.2.0': + resolution: {integrity: sha512-Ylv1ttUeKatpR0wEOMnHf1hXMktPUMObDClSWl2TpCVT4DwtJhCeighLzSLbgH3jr5pBNM0LDXT5yYxUvZ9WpA==} + engines: {node: '>=18.0.0'} + + '@smithy/shared-ini-file-loader@4.3.0': + resolution: {integrity: sha512-VCUPPtNs+rKWlqqntX0CbVvWyjhmX30JCtzO+s5dlzzxrvSfRh5SY0yxnkirvc1c80vdKQttahL71a9EsdolSQ==} + engines: {node: '>=18.0.0'} + + '@smithy/signature-v4@5.3.0': + resolution: {integrity: sha512-MKNyhXEs99xAZaFhm88h+3/V+tCRDQ+PrDzRqL0xdDpq4gjxcMmf5rBA3YXgqZqMZ/XwemZEurCBQMfxZOWq/g==} + engines: {node: '>=18.0.0'} + + '@smithy/smithy-client@4.7.1': + resolution: {integrity: sha512-WXVbiyNf/WOS/RHUoFMkJ6leEVpln5ojCjNBnzoZeMsnCg3A0BRhLK3WYc4V7PmYcYPZh9IYzzAg9XcNSzYxYQ==} + engines: {node: '>=18.0.0'} + + '@smithy/types@4.6.0': + resolution: {integrity: sha512-4lI9C8NzRPOv66FaY1LL1O/0v0aLVrq/mXP/keUa9mJOApEeae43LsLd2kZRUJw91gxOQfLIrV3OvqPgWz1YsA==} + engines: {node: '>=18.0.0'} + + '@smithy/url-parser@4.2.0': + resolution: {integrity: sha512-AlBmD6Idav2ugmoAL6UtR6ItS7jU5h5RNqLMZC7QrLCoITA9NzIN3nx9GWi8g4z1pfWh2r9r96SX/jHiNwPJ9A==} + engines: {node: '>=18.0.0'} + + '@smithy/util-base64@4.3.0': + resolution: {integrity: sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-body-length-browser@4.2.0': + resolution: {integrity: sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-body-length-node@4.2.1': + resolution: {integrity: sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-buffer-from@2.2.0': + resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} + engines: {node: '>=14.0.0'} + + '@smithy/util-buffer-from@4.2.0': + resolution: {integrity: sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==} + engines: {node: '>=18.0.0'} + + '@smithy/util-config-provider@4.2.0': + resolution: {integrity: sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-browser@4.3.0': + resolution: {integrity: sha512-H4MAj8j8Yp19Mr7vVtGgi7noJjvjJbsKQJkvNnLlrIFduRFT5jq5Eri1k838YW7rN2g5FTnXpz5ktKVr1KVgPQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-node@4.2.1': + resolution: {integrity: sha512-PuDcgx7/qKEMzV1QFHJ7E4/MMeEjaA7+zS5UNcHCLPvvn59AeZQ0DSDGMpqC2xecfa/1cNGm4l8Ec/VxCuY7Ug==} + engines: {node: '>=18.0.0'} + + '@smithy/util-endpoints@3.2.0': + resolution: {integrity: sha512-TXeCn22D56vvWr/5xPqALc9oO+LN+QpFjrSM7peG/ckqEPoI3zaKZFp+bFwfmiHhn5MGWPaLCqDOJPPIixk9Wg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-hex-encoding@4.2.0': + resolution: {integrity: sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-middleware@4.2.0': + resolution: {integrity: sha512-u9OOfDa43MjagtJZ8AapJcmimP+K2Z7szXn8xbty4aza+7P1wjFmy2ewjSbhEiYQoW1unTlOAIV165weYAaowA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-retry@4.2.0': + resolution: {integrity: sha512-BWSiuGbwRnEE2SFfaAZEX0TqaxtvtSYPM/J73PFVm+A29Fg1HTPiYFb8TmX1DXp4hgcdyJcNQmprfd5foeORsg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-stream@4.5.0': + resolution: {integrity: sha512-0TD5M5HCGu5diEvZ/O/WquSjhJPasqv7trjoqHyWjNh/FBeBl7a0ztl9uFMOsauYtRfd8jvpzIAQhDHbx+nvZw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-uri-escape@4.2.0': + resolution: {integrity: sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-utf8@2.3.0': + resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} + engines: {node: '>=14.0.0'} + + '@smithy/util-utf8@4.2.0': + resolution: {integrity: sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==} + engines: {node: '>=18.0.0'} + + '@smithy/uuid@1.1.0': + resolution: {integrity: sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==} + engines: {node: '>=18.0.0'} + '@socket.io/component-emitter@3.1.2': resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} @@ -4007,37 +4016,38 @@ packages: peerDependencies: socket.io-adapter: ^2.5.4 - '@sqltools/formatter@1.2.5': - resolution: {integrity: sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==} - '@standard-schema/spec@1.0.0': resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==} - '@sveltejs/acorn-typescript@1.0.5': - resolution: {integrity: sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==} + '@sveltejs/acorn-typescript@1.0.6': + resolution: {integrity: sha512-4awhxtMh4cx9blePWl10HRHj8Iivtqj+2QdDCSMDzxG+XKa9+VCNupQuCuvzEhYPzZSrX+0gC+0lHA/0fFKKQQ==} peerDependencies: acorn: ^8.9.0 - '@sveltejs/adapter-static@3.0.9': - resolution: {integrity: sha512-aytHXcMi7lb9ljsWUzXYQ0p5X1z9oWud2olu/EpmH7aCu4m84h7QLvb5Wp+CFirKcwoNnYvYWhyP/L8Vh1ztdw==} + '@sveltejs/adapter-static@3.0.10': + resolution: {integrity: sha512-7D9lYFWJmB7zxZyTE/qxjksvMqzMuYrrsyh1f4AlZqeZeACPRySjbC3aFiY55wb1tWUaKOQG9PVbm74JcN2Iew==} peerDependencies: '@sveltejs/kit': ^2.0.0 - '@sveltejs/enhanced-img@0.8.1': - resolution: {integrity: sha512-Ibom8j6F9vdmOeR+ljQ4q7TEJV0FWN1kB5wJZ2S/GuDVgCrKYrsXBw5gpSKcHwGYpKA3o9EoijPhep/GHgRUWQ==} + '@sveltejs/enhanced-img@0.8.4': + resolution: {integrity: sha512-/L12VUQj+ANIhskHT620jtxAs9wUPUIutgo37rwx5NgLnxOpVsP27fMiSpdIMgERldbgr6uRJ1WZGGOkzm7Vcg==} peerDependencies: '@sveltejs/vite-plugin-svelte': ^6.0.0 svelte: ^5.0.0 vite: ^6.3.0 || >=7.0.0 - '@sveltejs/kit@2.27.1': - resolution: {integrity: sha512-u5HbL9T4TgWZwXZM7hwdT0f5sDkGaNxsSrLYQoql+eiz2+9rcbbq4MiOAPoRtXG0dys5P5ixBmyQdqZedwZUlA==} + '@sveltejs/kit@2.46.4': + resolution: {integrity: sha512-J1fd80WokLzIm6EAV7z7C2+/C02qVAX645LZomARARTRJkbbJSY1Jln3wtBZYibUB8c9/5Z6xqLAV39VdbtWCQ==} engines: {node: '>=18.13'} hasBin: true peerDependencies: + '@opentelemetry/api': ^1.0.0 '@sveltejs/vite-plugin-svelte': ^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0 svelte: ^4.0.0 || ^5.0.0-next.0 vite: ^5.0.3 || ^6.0.0 || ^7.0.0-beta.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true '@sveltejs/vite-plugin-svelte-inspector@5.0.0': resolution: {integrity: sha512-iwQ8Z4ET6ZFSt/gC+tVfcsSBHwsqc6RumSaiLUkAurW3BCpJam65cmHw0oOlDMTO0u+PZi9hilBRYN+LZNHTUQ==} @@ -4047,8 +4057,8 @@ packages: svelte: ^5.0.0 vite: ^6.3.0 || ^7.0.0 - '@sveltejs/vite-plugin-svelte@6.1.2': - resolution: {integrity: sha512-7v+7OkUYelC2dhhYDAgX1qO2LcGscZ18Hi5kKzJQq7tQeXpH215dd0+J/HnX2zM5B3QKcIrTVqCGkZXAy5awYw==} + '@sveltejs/vite-plugin-svelte@6.2.1': + resolution: {integrity: sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ==} engines: {node: ^20.19 || ^22.12 || >=24} peerDependencies: svelte: ^5.0.0 @@ -4132,68 +4142,68 @@ packages: resolution: {integrity: sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==} engines: {node: '>=14'} - '@swc/core-darwin-arm64@1.13.3': - resolution: {integrity: sha512-ux0Ws4pSpBTqbDS9GlVP354MekB1DwYlbxXU3VhnDr4GBcCOimpocx62x7cFJkSpEBF8bmX8+/TTCGKh4PbyXw==} + '@swc/core-darwin-arm64@1.13.5': + resolution: {integrity: sha512-lKNv7SujeXvKn16gvQqUQI5DdyY8v7xcoO3k06/FJbHJS90zEwZdQiMNRiqpYw/orU543tPaWgz7cIYWhbopiQ==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] - '@swc/core-darwin-x64@1.13.3': - resolution: {integrity: sha512-p0X6yhxmNUOMZrbeZ3ZNsPige8lSlSe1llllXvpCLkKKxN/k5vZt1sULoq6Nj4eQ7KeHQVm81/+AwKZyf/e0TA==} + '@swc/core-darwin-x64@1.13.5': + resolution: {integrity: sha512-ILd38Fg/w23vHb0yVjlWvQBoE37ZJTdlLHa8LRCFDdX4WKfnVBiblsCU9ar4QTMNdeTBEX9iUF4IrbNWhaF1Ng==} engines: {node: '>=10'} cpu: [x64] os: [darwin] - '@swc/core-linux-arm-gnueabihf@1.13.3': - resolution: {integrity: sha512-OmDoiexL2fVWvQTCtoh0xHMyEkZweQAlh4dRyvl8ugqIPEVARSYtaj55TBMUJIP44mSUOJ5tytjzhn2KFxFcBA==} + '@swc/core-linux-arm-gnueabihf@1.13.5': + resolution: {integrity: sha512-Q6eS3Pt8GLkXxqz9TAw+AUk9HpVJt8Uzm54MvPsqp2yuGmY0/sNaPPNVqctCX9fu/Nu8eaWUen0si6iEiCsazQ==} engines: {node: '>=10'} cpu: [arm] os: [linux] - '@swc/core-linux-arm64-gnu@1.13.3': - resolution: {integrity: sha512-STfKku3QfnuUj6k3g9ld4vwhtgCGYIFQmsGPPgT9MK/dI3Lwnpe5Gs5t1inoUIoGNP8sIOLlBB4HV4MmBjQuhw==} + '@swc/core-linux-arm64-gnu@1.13.5': + resolution: {integrity: sha512-aNDfeN+9af+y+M2MYfxCzCy/VDq7Z5YIbMqRI739o8Ganz6ST+27kjQFd8Y/57JN/hcnUEa9xqdS3XY7WaVtSw==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-arm64-musl@1.13.3': - resolution: {integrity: sha512-bc+CXYlFc1t8pv9yZJGus372ldzOVscBl7encUBlU1m/Sig0+NDJLz6cXXRcFyl6ABNOApWeR4Yl7iUWx6C8og==} + '@swc/core-linux-arm64-musl@1.13.5': + resolution: {integrity: sha512-9+ZxFN5GJag4CnYnq6apKTnnezpfJhCumyz0504/JbHLo+Ue+ZtJnf3RhyA9W9TINtLE0bC4hKpWi8ZKoETyOQ==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-x64-gnu@1.13.3': - resolution: {integrity: sha512-dFXoa0TEhohrKcxn/54YKs1iwNeW6tUkHJgXW33H381SvjKFUV53WR231jh1sWVJETjA3vsAwxKwR23s7UCmUA==} + '@swc/core-linux-x64-gnu@1.13.5': + resolution: {integrity: sha512-WD530qvHrki8Ywt/PloKUjaRKgstQqNGvmZl54g06kA+hqtSE2FTG9gngXr3UJxYu/cNAjJYiBifm7+w4nbHbA==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-linux-x64-musl@1.13.3': - resolution: {integrity: sha512-ieyjisLB+ldexiE/yD8uomaZuZIbTc8tjquYln9Quh5ykOBY7LpJJYBWvWtm1g3pHv6AXlBI8Jay7Fffb6aLfA==} + '@swc/core-linux-x64-musl@1.13.5': + resolution: {integrity: sha512-Luj8y4OFYx4DHNQTWjdIuKTq2f5k6uSXICqx+FSabnXptaOBAbJHNbHT/06JZh6NRUouaf0mYXN0mcsqvkhd7Q==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-win32-arm64-msvc@1.13.3': - resolution: {integrity: sha512-elTQpnaX5vESSbhCEgcwXjpMsnUbqqHfEpB7ewpkAsLzKEXZaK67ihSRYAuAx6ewRQTo7DS5iTT6X5aQD3MzMw==} + '@swc/core-win32-arm64-msvc@1.13.5': + resolution: {integrity: sha512-cZ6UpumhF9SDJvv4DA2fo9WIzlNFuKSkZpZmPG1c+4PFSEMy5DFOjBSllCvnqihCabzXzpn6ykCwBmHpy31vQw==} engines: {node: '>=10'} cpu: [arm64] os: [win32] - '@swc/core-win32-ia32-msvc@1.13.3': - resolution: {integrity: sha512-nvehQVEOdI1BleJpuUgPLrclJ0TzbEMc+MarXDmmiRFwEUGqj+pnfkTSb7RZyS1puU74IXdK/YhTirHurtbI9w==} + '@swc/core-win32-ia32-msvc@1.13.5': + resolution: {integrity: sha512-C5Yi/xIikrFUzZcyGj9L3RpKljFvKiDMtyDzPKzlsDrKIw2EYY+bF88gB6oGY5RGmv4DAX8dbnpRAqgFD0FMEw==} engines: {node: '>=10'} cpu: [ia32] os: [win32] - '@swc/core-win32-x64-msvc@1.13.3': - resolution: {integrity: sha512-A+JSKGkRbPLVV2Kwx8TaDAV0yXIXm/gc8m98hSkVDGlPBBmydgzNdWy3X7HTUBM7IDk7YlWE7w2+RUGjdgpTmg==} + '@swc/core-win32-x64-msvc@1.13.5': + resolution: {integrity: sha512-YrKdMVxbYmlfybCSbRtrilc6UA8GF5aPmGKBdPvjrarvsmf4i7ZHGCEnLtfOMd3Lwbs2WUZq3WdMbozYeLU93Q==} engines: {node: '>=10'} cpu: [x64] os: [win32] - '@swc/core@1.13.3': - resolution: {integrity: sha512-ZaDETVWnm6FE0fc+c2UE8MHYVS3Fe91o5vkmGfgwGXFbxYvAjKSqxM/j4cRc9T7VZNSJjriXq58XkfCp3Y6f+w==} + '@swc/core@1.13.5': + resolution: {integrity: sha512-WezcBo8a0Dg2rnR82zhwoR6aRNxeTGfK5QCD6TQ+kg3xx/zNT02s/0o+81h/3zhvFSB24NtqEr8FTw88O5W/JQ==} engines: {node: '>=10'} peerDependencies: '@swc/helpers': '>=0.5.17' @@ -4207,72 +4217,72 @@ packages: '@swc/helpers@0.5.17': resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==} - '@swc/types@0.1.24': - resolution: {integrity: sha512-tjTMh3V4vAORHtdTprLlfoMptu1WfTZG9Rsca6yOKyNYsRr+MUXutKmliB17orgSZk5DpnDxs8GUdd/qwYxOng==} + '@swc/types@0.1.25': + resolution: {integrity: sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==} '@szmarczak/http-timer@5.0.1': resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} engines: {node: '>=14.16'} - '@tailwindcss/node@4.1.12': - resolution: {integrity: sha512-3hm9brwvQkZFe++SBt+oLjo4OLDtkvlE8q2WalaD/7QWaeM7KEJbAiY/LJZUaCs7Xa8aUu4xy3uoyX4q54UVdQ==} + '@tailwindcss/node@4.1.14': + resolution: {integrity: sha512-hpz+8vFk3Ic2xssIA3e01R6jkmsAhvkQdXlEbRTk6S10xDAtiQiM3FyvZVGsucefq764euO/b8WUW9ysLdThHw==} - '@tailwindcss/oxide-android-arm64@4.1.12': - resolution: {integrity: sha512-oNY5pq+1gc4T6QVTsZKwZaGpBb2N1H1fsc1GD4o7yinFySqIuRZ2E4NvGasWc6PhYJwGK2+5YT1f9Tp80zUQZQ==} + '@tailwindcss/oxide-android-arm64@4.1.14': + resolution: {integrity: sha512-a94ifZrGwMvbdeAxWoSuGcIl6/DOP5cdxagid7xJv6bwFp3oebp7y2ImYsnZBMTwjn5Ev5xESvS3FFYUGgPODQ==} engines: {node: '>= 10'} cpu: [arm64] os: [android] - '@tailwindcss/oxide-darwin-arm64@4.1.12': - resolution: {integrity: sha512-cq1qmq2HEtDV9HvZlTtrj671mCdGB93bVY6J29mwCyaMYCP/JaUBXxrQQQm7Qn33AXXASPUb2HFZlWiiHWFytw==} + '@tailwindcss/oxide-darwin-arm64@4.1.14': + resolution: {integrity: sha512-HkFP/CqfSh09xCnrPJA7jud7hij5ahKyWomrC3oiO2U9i0UjP17o9pJbxUN0IJ471GTQQmzwhp0DEcpbp4MZTA==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@tailwindcss/oxide-darwin-x64@4.1.12': - resolution: {integrity: sha512-6UCsIeFUcBfpangqlXay9Ffty9XhFH1QuUFn0WV83W8lGdX8cD5/+2ONLluALJD5+yJ7k8mVtwy3zMZmzEfbLg==} + '@tailwindcss/oxide-darwin-x64@4.1.14': + resolution: {integrity: sha512-eVNaWmCgdLf5iv6Qd3s7JI5SEFBFRtfm6W0mphJYXgvnDEAZ5sZzqmI06bK6xo0IErDHdTA5/t7d4eTfWbWOFw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@tailwindcss/oxide-freebsd-x64@4.1.12': - resolution: {integrity: sha512-JOH/f7j6+nYXIrHobRYCtoArJdMJh5zy5lr0FV0Qu47MID/vqJAY3r/OElPzx1C/wdT1uS7cPq+xdYYelny1ww==} + '@tailwindcss/oxide-freebsd-x64@4.1.14': + resolution: {integrity: sha512-QWLoRXNikEuqtNb0dhQN6wsSVVjX6dmUFzuuiL09ZeXju25dsei2uIPl71y2Ic6QbNBsB4scwBoFnlBfabHkEw==} engines: {node: '>= 10'} cpu: [x64] os: [freebsd] - '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.12': - resolution: {integrity: sha512-v4Ghvi9AU1SYgGr3/j38PD8PEe6bRfTnNSUE3YCMIRrrNigCFtHZ2TCm8142X8fcSqHBZBceDx+JlFJEfNg5zQ==} + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.14': + resolution: {integrity: sha512-VB4gjQni9+F0VCASU+L8zSIyjrLLsy03sjcR3bM0V2g4SNamo0FakZFKyUQ96ZVwGK4CaJsc9zd/obQy74o0Fw==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@tailwindcss/oxide-linux-arm64-gnu@4.1.12': - resolution: {integrity: sha512-YP5s1LmetL9UsvVAKusHSyPlzSRqYyRB0f+Kl/xcYQSPLEw/BvGfxzbH+ihUciePDjiXwHh+p+qbSP3SlJw+6g==} + '@tailwindcss/oxide-linux-arm64-gnu@4.1.14': + resolution: {integrity: sha512-qaEy0dIZ6d9vyLnmeg24yzA8XuEAD9WjpM5nIM1sUgQ/Zv7cVkharPDQcmm/t/TvXoKo/0knI3me3AGfdx6w1w==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tailwindcss/oxide-linux-arm64-musl@4.1.12': - resolution: {integrity: sha512-V8pAM3s8gsrXcCv6kCHSuwyb/gPsd863iT+v1PGXC4fSL/OJqsKhfK//v8P+w9ThKIoqNbEnsZqNy+WDnwQqCA==} + '@tailwindcss/oxide-linux-arm64-musl@4.1.14': + resolution: {integrity: sha512-ISZjT44s59O8xKsPEIesiIydMG/sCXoMBCqsphDm/WcbnuWLxxb+GcvSIIA5NjUw6F8Tex7s5/LM2yDy8RqYBQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tailwindcss/oxide-linux-x64-gnu@4.1.12': - resolution: {integrity: sha512-xYfqYLjvm2UQ3TZggTGrwxjYaLB62b1Wiysw/YE3Yqbh86sOMoTn0feF98PonP7LtjsWOWcXEbGqDL7zv0uW8Q==} + '@tailwindcss/oxide-linux-x64-gnu@4.1.14': + resolution: {integrity: sha512-02c6JhLPJj10L2caH4U0zF8Hji4dOeahmuMl23stk0MU1wfd1OraE7rOloidSF8W5JTHkFdVo/O7uRUJJnUAJg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tailwindcss/oxide-linux-x64-musl@4.1.12': - resolution: {integrity: sha512-ha0pHPamN+fWZY7GCzz5rKunlv9L5R8kdh+YNvP5awe3LtuXb5nRi/H27GeL2U+TdhDOptU7T6Is7mdwh5Ar3A==} + '@tailwindcss/oxide-linux-x64-musl@4.1.14': + resolution: {integrity: sha512-TNGeLiN1XS66kQhxHG/7wMeQDOoL0S33x9BgmydbrWAb9Qw0KYdd8o1ifx4HOGDWhVmJ+Ul+JQ7lyknQFilO3Q==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tailwindcss/oxide-wasm32-wasi@4.1.12': - resolution: {integrity: sha512-4tSyu3dW+ktzdEpuk6g49KdEangu3eCYoqPhWNsZgUhyegEda3M9rG0/j1GV/JjVVsj+lG7jWAyrTlLzd/WEBg==} + '@tailwindcss/oxide-wasm32-wasi@4.1.14': + resolution: {integrity: sha512-uZYAsaW/jS/IYkd6EWPJKW/NlPNSkWkBlaeVBi/WsFQNP05/bzkebUL8FH1pdsqx4f2fH/bWFcUABOM9nfiJkQ==} engines: {node: '>=14.0.0'} cpu: [wasm32] bundledDependencies: @@ -4283,39 +4293,33 @@ packages: - '@emnapi/wasi-threads' - tslib - '@tailwindcss/oxide-win32-arm64-msvc@4.1.12': - resolution: {integrity: sha512-iGLyD/cVP724+FGtMWslhcFyg4xyYyM+5F4hGvKA7eifPkXHRAUDFaimu53fpNg9X8dfP75pXx/zFt/jlNF+lg==} + '@tailwindcss/oxide-win32-arm64-msvc@4.1.14': + resolution: {integrity: sha512-Az0RnnkcvRqsuoLH2Z4n3JfAef0wElgzHD5Aky/e+0tBUxUhIeIqFBTMNQvmMRSP15fWwmvjBxZ3Q8RhsDnxAA==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@tailwindcss/oxide-win32-x64-msvc@4.1.12': - resolution: {integrity: sha512-NKIh5rzw6CpEodv/++r0hGLlfgT/gFN+5WNdZtvh6wpU2BpGNgdjvj6H2oFc8nCM839QM1YOhjpgbAONUb4IxA==} + '@tailwindcss/oxide-win32-x64-msvc@4.1.14': + resolution: {integrity: sha512-ttblVGHgf68kEE4om1n/n44I0yGPkCPbLsqzjvybhpwa6mKKtgFfAzy6btc3HRmuW7nHe0OOrSeNP9sQmmH9XA==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@tailwindcss/oxide@4.1.12': - resolution: {integrity: sha512-gM5EoKHW/ukmlEtphNwaGx45fGoEmP10v51t9unv55voWh6WrOL19hfuIdo2FjxIaZzw776/BUQg7Pck++cIVw==} + '@tailwindcss/oxide@4.1.14': + resolution: {integrity: sha512-23yx+VUbBwCg2x5XWdB8+1lkPajzLmALEfMb51zZUBYaYVPDQvBSD/WYDqiVyBIo2BZFa3yw1Rpy3G2Jp+K0dw==} engines: {node: '>= 10'} - '@tailwindcss/vite@4.1.12': - resolution: {integrity: sha512-4pt0AMFDx7gzIrAOIYgYP0KCBuKWqyW8ayrdiLEjoJTT4pKTjrzG/e4uzWtTLDziC+66R9wbUqZBccJalSE5vQ==} + '@tailwindcss/vite@4.1.14': + resolution: {integrity: sha512-BoFUoU0XqgCUS1UXWhmDJroKKhNXeDzD7/XwabjkDIAbMnc4ULn5e2FuEuBbhZ6ENZoSYzKlzvZ44Yr6EUDUSA==} peerDependencies: vite: ^5.2.0 || ^6 || ^7 - '@testcontainers/postgresql@11.5.1': - resolution: {integrity: sha512-6P1QYIKRkktSVwTuwU0Pke5WbXTkvpLleyQcgknJPbZwhaIsCrhnbZlVzj2g/e+Nf9Lmdy1F2OAai+vUrBq0AQ==} - - '@testcontainers/redis@11.5.1': - resolution: {integrity: sha512-ThGaUPUCFW4Vwmx6kfPYhhTQjq/3UXJQrU/xxiYLqgvFJNtvtYlWmzXrwORLhPkkqnoFUnfFaX3u9u1GnrlDkw==} - '@testing-library/dom@10.4.0': resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==} engines: {node: '>=18'} - '@testing-library/jest-dom@6.7.0': - resolution: {integrity: sha512-RI2e97YZ7MRa+vxP4UUnMuMFL2buSsf0ollxUbTgrbPLKhMn8KVTx7raS6DYjC7v1NDVrioOvaShxsguLNISCA==} + '@testing-library/jest-dom@6.9.1': + resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==} engines: {node: '>=14', npm: '>=6', yarn: '>=1'} '@testing-library/svelte@5.2.8': @@ -4373,9 +4377,6 @@ packages: '@types/async-lock@1.4.2': resolution: {integrity: sha512-HlZ6Dcr205BmNhwkdXqrg2vkFMN2PluI7Lgr8In3B3wE5PiQHhjRqtW/lGdVU9gw+sM0JcIDx2AN+cW8oSWIcw==} - '@types/aws-lambda@8.10.150': - resolution: {integrity: sha512-AX+AbjH/rH5ezX1fbK8onC/a+HyQHo7QGmvoxAE42n22OsciAxvZoZNEr22tbXs8WfP1nIsBjKDpgPm3HjOZbA==} - '@types/bcrypt@6.0.0': resolution: {integrity: sha512-/oJGukuH3D2+D+3H4JWLaAsJ/ji86dhRidzZ/Od7H/i8g+aCmvkeCc6Ni/f9uxGLSQVCRZkX2/lqEFG2BvWtlQ==} @@ -4388,9 +4389,6 @@ packages: '@types/braces@3.0.5': resolution: {integrity: sha512-SQFof9H+LXeWNz8wDe7oN5zu7ket0qwMu5vZubW4GCJ8Kkeh6nBWUz87+KTz/G3Kqsrp0j/W253XJb3KMEeg3w==} - '@types/bunyan@1.8.11': - resolution: {integrity: sha512-758fRH7umIMk5qt5ELmRMff4mLDlN+xyYzC+dkPTdKwbSkJFvz6xwyScrytPU0QIBbRRwbiE8/BIg8bpajerNQ==} - '@types/byte-size@8.1.2': resolution: {integrity: sha512-jGyVzYu6avI8yuqQCNTZd65tzI8HZrLjKX9sdMqZrGWVlNChu0rf6p368oVEDCYJe5BMx2Ov04tD1wqtgTwGSA==} @@ -4444,8 +4442,8 @@ packages: '@types/docker-modem@3.0.6': resolution: {integrity: sha512-yKpAGEuKRSS8wwx0joknWxsmLha78wNMe9R2S3UNsVOkZded8UqOrV8KoeDXoXsjndxwyF3eIhyClGbO1SEhEg==} - '@types/dockerode@3.3.42': - resolution: {integrity: sha512-U1jqHMShibMEWHdxYhj3rCMNCiLx5f35i4e3CEUuW+JSSszc/tVqc6WCAPdhwBymG5R/vgbcceagK0St7Cq6Eg==} + '@types/dockerode@3.3.44': + resolution: {integrity: sha512-fUpIHlsbYpxAJb285xx3vp7q5wf5mjqSn3cYwl/MhiM+DB99OdO5sOCPlO0PjO+TyOtphPs7tMVLU/RtOo/JjA==} '@types/dom-to-image@2.6.7': resolution: {integrity: sha512-me5VbCv+fcXozblWwG13krNBvuEOm6kA5xoa4RrjDJCNFOZSWR3/QLtOXimBHk1Fisq69Gx3JtOoXtg1N1tijg==} @@ -4504,9 +4502,6 @@ packages: '@types/history@4.7.11': resolution: {integrity: sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==} - '@types/hoist-non-react-statics@3.3.6': - resolution: {integrity: sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==} - '@types/html-minifier-terser@6.1.0': resolution: {integrity: sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==} @@ -4552,8 +4547,8 @@ packages: '@types/koa@3.0.0': resolution: {integrity: sha512-MOcVYdVYmkSutVHZZPh8j3+dAjLyR5Tl59CN0eKgpkE1h/LBSmPAsQQuWs+bKu7WtGNn+hKfJH9Gzml+PulmDg==} - '@types/leaflet@1.9.19': - resolution: {integrity: sha512-pB+n2daHcZPF2FDaWa+6B0a0mSDf4dPU35y5iTXsx7x/PzzshiX5atYiS1jlBn43X7XvM8AP+AB26lnSk0J4GA==} + '@types/leaflet@1.9.20': + resolution: {integrity: sha512-rooalPMlk61LCaLOvBF2VIf9M47HgMQqi5xQ9QRi7c8PkdIe0WrIi5IxXUXQjAdL0c+vcQ01mYWbthzmp9GHWw==} '@types/lodash-es@4.17.12': resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} @@ -4561,9 +4556,6 @@ packages: '@types/lodash@4.17.20': resolution: {integrity: sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==} - '@types/luxon@3.6.2': - resolution: {integrity: sha512-R/BdP7OxEMc44l2Ex5lSXHoIXTB2JLNa3y2QISIbr58U/YcsffyQrYW//hZSdrfxrjRZj3GcUoxMPGdO8gSYuw==} - '@types/luxon@3.7.1': resolution: {integrity: sha512-H3iskjFIAn5SlJU7OuxUmTEpebK6TKB8rxZShDslBMZJ5u9S//KM1sbdAisiSrqwLQncVjnpi2OK2J51h+4lsg==} @@ -4573,9 +4565,6 @@ packages: '@types/mdx@2.0.13': resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} - '@types/memcached@2.2.10': - resolution: {integrity: sha512-AM9smvZN55Gzs2wRrqeMHVP7KE8KWgCJO/XL5yCly2xF6EKa4YlbpK+cLSAH4NG/Ah64HrlegmGqW8kYws7Vxg==} - '@types/methods@1.1.4': resolution: {integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==} @@ -4594,38 +4583,29 @@ packages: '@types/multer@2.0.0': resolution: {integrity: sha512-C3Z9v9Evij2yST3RSBktxP9STm6OdMc5uR1xF1SGr98uv8dUlAL2hqwrZ3GVB3uyMyiegnscEK6PGtYvNrjTjw==} - '@types/mysql@2.15.27': - resolution: {integrity: sha512-YfWiV16IY0OeBfBCk8+hXKmdTKrKlwKN1MNKAPBu5JYxLwBEZl7QzeEpGnlZb3VMGJrrGmB84gXiH+ofs/TezA==} - - '@types/node-fetch@2.6.12': - resolution: {integrity: sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==} - '@types/node-forge@1.3.11': resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} '@types/node@17.0.45': resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} - '@types/node@18.19.123': - resolution: {integrity: sha512-K7DIaHnh0mzVxreCR9qwgNxp3MH9dltPNIEddW9MYUlcKAzm+3grKNSTe2vCJHI1FaLpvpL5JGJrz1UZDKYvDg==} + '@types/node@18.19.130': + resolution: {integrity: sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==} '@types/node@20.19.2': resolution: {integrity: sha512-9pLGGwdzOUBDYi0GNjM97FIA+f92fqSke6joWeBjWXllfNxZBs7qeMF7tvtOIsbY45xkWkxrdwUfUf3MnQa9gA==} - '@types/node@22.18.1': - resolution: {integrity: sha512-rzSDyhn4cYznVG+PCzGe1lwuMYJrcBS1fc3JqSa2PvtABwWo+dZ1ij5OVok3tqfpEBCBoaR4d7upFJk73HRJDw==} + '@types/node@22.18.10': + resolution: {integrity: sha512-anNG/V/Efn/YZY4pRzbACnKxNKoBng2VTFydVu8RRs5hQjikP8CQfaeAV59VFSCzKNp90mXiVXW2QzV56rwMrg==} - '@types/node@24.3.0': - resolution: {integrity: sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==} + '@types/node@24.7.1': + resolution: {integrity: sha512-CmyhGZanP88uuC5GpWU9q+fI61j2SkhO3UGMUdfYRE6Bcy0ccyzn1Rqj9YAB/ZY4kOXmNf0ocah5GtphmLMP6Q==} - '@types/nodemailer@6.4.17': - resolution: {integrity: sha512-I9CCaIp6DTldEg7vyUTZi8+9Vo0hi1/T8gv3C89yk1rSAAzoKQ8H8ki/jBYJSFoH/BisgLP8tkZMlQ91CIquww==} + '@types/nodemailer@7.0.2': + resolution: {integrity: sha512-Zo6uOA9157WRgBk/ZhMpTQ/iCWLMk7OIs/Q9jvHarMvrzUUP/MDdPHL2U1zpf57HrrWGv4nYQn5uIxna0xY3xw==} - '@types/oidc-provider@9.1.2': - resolution: {integrity: sha512-JAreXkbWsZR72Gt3eigG652wq1qBcjhuy421PXU2a8PS0mM00XlG+UdXbM/QPihM3ko0YF8cwvt0H2kacXGcsg==} - - '@types/oracledb@6.5.2': - resolution: {integrity: sha512-kK1eBS/Adeyis+3OlBDMeQQuasIDLUYXsi2T15ccNJ0iyUpQ4xDF7svFu3+bGVrI0CMBUclPciz+lsQR3JX3TQ==} + '@types/oidc-provider@9.5.0': + resolution: {integrity: sha512-eEzCRVTSqIHD9Bo/qRJ4XQWQ5Z/zBcG+Z2cGJluRsSuWx1RJihqRyPxhIEpMXTwPzHYRTQkVp7hwisQOwzzSAg==} '@types/parse5@5.0.3': resolution: {integrity: sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==} @@ -4633,9 +4613,6 @@ packages: '@types/pg-pool@2.0.6': resolution: {integrity: sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==} - '@types/pg@8.15.4': - resolution: {integrity: sha512-I6UNVBAoYbvuWkkU3oosC8yxqH21f4/Jc4DK71JLG3dT2mdlGe1z+ep/LQGXaKaOgcvUrsQoPRqfgtMcvZiJhg==} - '@types/pg@8.15.5': resolution: {integrity: sha512-LF7lF6zWEKxuT3/OR8wAZGzkg4ENGXFNyiV/JeOt9z5B+0ZVwbql9McqX5c/WStFq1GaGso7H1AzP/qSzmlCKQ==} @@ -4657,9 +4634,6 @@ packages: '@types/range-parser@1.2.7': resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} - '@types/react-redux@7.1.34': - resolution: {integrity: sha512-GdFaVjEbYv4Fthm2ZLvj1VSCedV7TqE5y1kNwnjSdBOTXuRSgowux6J8TAct15T3CKBr63UMk+2CO7ilRhyrAQ==} - '@types/react-router-config@5.0.11': resolution: {integrity: sha512-WmSAg7WgqW7m4x8Mt4N6ZyKz0BubSj/2tVUMsAHp+Yd2AMwcSbeFq9WympT19p5heCFmF97R9eD5uUR/t4HEqw==} @@ -4669,14 +4643,14 @@ packages: '@types/react-router@5.1.20': resolution: {integrity: sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==} - '@types/react@19.1.12': - resolution: {integrity: sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w==} + '@types/react@19.2.2': + resolution: {integrity: sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==} '@types/readdir-glob@1.1.5': resolution: {integrity: sha512-raiuEPUYqXu+nvtY2Pe8s8FEmZ3x5yAH4VkLdihcPdalvsHltomrRC9BzuStrJ9yk06470hS0Crw0f1pXqD+Hg==} - '@types/retry@0.12.0': - resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} + '@types/retry@0.12.2': + resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==} '@types/sanitize-html@2.16.0': resolution: {integrity: sha512-l6rX1MUXje5ztPT0cAFtUayXF06DqPhRyfVXareEN5gGCFaP/iwsxIyKODr9XDhfxPpN6vXUFNfo5kZMXCxBtw==} @@ -4684,8 +4658,8 @@ packages: '@types/sax@1.2.7': resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==} - '@types/semver@7.7.0': - resolution: {integrity: sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==} + '@types/semver@7.7.1': + resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} '@types/send@0.17.5': resolution: {integrity: sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==} @@ -4717,9 +4691,6 @@ packages: '@types/supertest@6.0.3': resolution: {integrity: sha512-8WzXq62EXFhJ7QsH3Ocb/iKQ/Ty9ZVWnVzoTKc9tyyFRRF3a74Tk2+TLFgaFFw364Ere+npzHKEJ6ga2LzIL7w==} - '@types/tedious@4.0.14': - resolution: {integrity: sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==} - '@types/through@0.0.33': resolution: {integrity: sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==} @@ -4732,8 +4703,8 @@ packages: '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} - '@types/validator@13.15.2': - resolution: {integrity: sha512-y7pa/oEJJ4iGYBxOpfAKn5b9+xuihvzDVnC/OSvlVnGxVg0pOqmjiMafiJ1KVNQEaPZf9HsEp5icEwGg8uIe5Q==} + '@types/validator@13.15.3': + resolution: {integrity: sha512-7bcUmDyS6PN3EuD9SlGGOxM77F8WLVsrwkxyWxKnxzmXoequ6c7741QBrANq6htVRGOITJ7z72mTP6Z4XyuG+Q==} '@types/whatwg-mimetype@3.0.2': resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==} @@ -4747,63 +4718,63 @@ packages: '@types/yargs@17.0.33': resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} - '@typescript-eslint/eslint-plugin@8.39.1': - resolution: {integrity: sha512-yYegZ5n3Yr6eOcqgj2nJH8cH/ZZgF+l0YIdKILSDjYFRjgYQMgv/lRjV5Z7Up04b9VYUondt8EPMqg7kTWgJ2g==} + '@typescript-eslint/eslint-plugin@8.46.0': + resolution: {integrity: sha512-hA8gxBq4ukonVXPy0OKhiaUh/68D0E88GSmtC1iAEnGaieuDi38LhS7jdCHRLi6ErJBNDGCzvh5EnzdPwUc0DA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.39.1 + '@typescript-eslint/parser': ^8.46.0 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.39.1': - resolution: {integrity: sha512-pUXGCuHnnKw6PyYq93lLRiZm3vjuslIy7tus1lIQTYVK9bL8XBgJnCWm8a0KcTtHC84Yya1Q6rtll+duSMj0dg==} + '@typescript-eslint/parser@8.46.0': + resolution: {integrity: sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.39.1': - resolution: {integrity: sha512-8fZxek3ONTwBu9ptw5nCKqZOSkXshZB7uAxuFF0J/wTMkKydjXCzqqga7MlFMpHi9DoG4BadhmTkITBcg8Aybw==} + '@typescript-eslint/project-service@8.46.0': + resolution: {integrity: sha512-OEhec0mH+U5Je2NZOeK1AbVCdm0ChyapAyTeXVIYTPXDJ3F07+cu87PPXcGoYqZ7M9YJVvFnfpGg1UmCIqM+QQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.39.1': - resolution: {integrity: sha512-RkBKGBrjgskFGWuyUGz/EtD8AF/GW49S21J8dvMzpJitOF1slLEbbHnNEtAHtnDAnx8qDEdRrULRnWVx27wGBw==} + '@typescript-eslint/scope-manager@8.46.0': + resolution: {integrity: sha512-lWETPa9XGcBes4jqAMYD9fW0j4n6hrPtTJwWDmtqgFO/4HF4jmdH/Q6wggTw5qIT5TXjKzbt7GsZUBnWoO3dqw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.39.1': - resolution: {integrity: sha512-ePUPGVtTMR8XMU2Hee8kD0Pu4NDE1CN9Q1sxGSGd/mbOtGZDM7pnhXNJnzW63zk/q+Z54zVzj44HtwXln5CvHA==} + '@typescript-eslint/tsconfig-utils@8.46.0': + resolution: {integrity: sha512-WrYXKGAHY836/N7zoK/kzi6p8tXFhasHh8ocFL9VZSAkvH956gfeRfcnhs3xzRy8qQ/dq3q44v1jvQieMFg2cw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.39.1': - resolution: {integrity: sha512-gu9/ahyatyAdQbKeHnhT4R+y3YLtqqHyvkfDxaBYk97EcbfChSJXyaJnIL3ygUv7OuZatePHmQvuH5ru0lnVeA==} + '@typescript-eslint/type-utils@8.46.0': + resolution: {integrity: sha512-hy+lvYV1lZpVs2jRaEYvgCblZxUoJiPyCemwbQZ+NGulWkQRy0HRPYAoef/CNSzaLt+MLvMptZsHXHlkEilaeg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.39.1': - resolution: {integrity: sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==} + '@typescript-eslint/types@8.46.0': + resolution: {integrity: sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.39.1': - resolution: {integrity: sha512-EKkpcPuIux48dddVDXyQBlKdeTPMmALqBUbEk38McWv0qVEZwOpVJBi7ugK5qVNgeuYjGNQxrrnoM/5+TI/BPw==} + '@typescript-eslint/typescript-estree@8.46.0': + resolution: {integrity: sha512-ekDCUfVpAKWJbRfm8T1YRrCot1KFxZn21oV76v5Fj4tr7ELyk84OS+ouvYdcDAwZL89WpEkEj2DKQ+qg//+ucg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.39.1': - resolution: {integrity: sha512-VF5tZ2XnUSTuiqZFXCZfZs1cgkdd3O/sSYmdo2EpSyDlC86UM/8YytTmKnehOW3TGAlivqTDT6bS87B/GQ/jyg==} + '@typescript-eslint/utils@8.46.0': + resolution: {integrity: sha512-nD6yGWPj1xiOm4Gk0k6hLSZz2XkNXhuYmyIrOWcHoPuAhjT9i5bAG+xbWPgFeNR8HPHHtpNKdYUXJl/D3x7f5g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.39.1': - resolution: {integrity: sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A==} + '@typescript-eslint/visitor-keys@8.46.0': + resolution: {integrity: sha512-FrvMpAK+hTbFy7vH5j1+tMYHMSKLE6RzluFJlkFNKD0p9YsUT75JlBSmr5so3QRzvMwU5/bIEdeNrxm8du8l3Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@ungap/structured-clone@1.3.0': @@ -4898,11 +4869,11 @@ packages: '@xtuc/long@4.2.2': resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} - '@zoom-image/core@0.41.0': - resolution: {integrity: sha512-LAxGru91286gFmyiQB4RjM277YOWxJX+OZcwtIH/N0dyo73y4NfaAE1eGVdnhjxEYv7yVV3xToMyYnm+uQboTw==} + '@zoom-image/core@0.41.3': + resolution: {integrity: sha512-yW2sZRP6FnZZ7vREpYucDpSCsVFgMSWq22Sp1kabsMPz5+6LSs+sBPPDCVs/ahVYSHa9YOX8rlGHM5iiTFPZLA==} - '@zoom-image/svelte@0.3.4': - resolution: {integrity: sha512-8cPkFUjh+t3/eYkoT2krvz8hoFiXoiYZKpcHOnYCHLhEwaHr1yjgXg/ttWehotVH9V3Z51JQgIcGF3uhYWKB/Q==} + '@zoom-image/svelte@0.3.7': + resolution: {integrity: sha512-vCgA2ClH8J2JBTzpJEgzy03yTi5uJE0963cUjBwc5fi7q8g1wxbbj4/W7YHwQfDmdh9uqHxlX0VcmUQqV44d+w==} peerDependencies: svelte: ^3.0.0 || ^4.0.0 || ^5.0.0 @@ -4973,14 +4944,6 @@ packages: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} - ajv-draft-04@1.0.0: - resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} - peerDependencies: - ajv: ^8.5.0 - peerDependenciesMeta: - ajv: - optional: true - ajv-formats@2.1.1: resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} peerDependencies: @@ -5010,9 +4973,6 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - ajv@8.11.0: - resolution: {integrity: sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==} - ajv@8.17.1: resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} @@ -5021,8 +4981,8 @@ packages: peerDependencies: algoliasearch: '>= 3.1 < 6' - algoliasearch@5.29.0: - resolution: {integrity: sha512-E2l6AlTWGznM2e7vEE6T6hzObvEyXukxMOlBmVlMyixZyK1umuO/CiVc6sDBbzVH0oEviCE5IfVY1oZBmccYPQ==} + algoliasearch@5.40.0: + resolution: {integrity: sha512-a9aIL2E3Z7uYUPMCmjMFFd5MWhn+ccTubEvnMy7rOTZCB62dXBJtz0R5BZ/TPuX3R9ocBsgWuAbGWQ+Ph4Fmlg==} engines: {node: '>= 14.0.0'} ansi-align@3.0.1: @@ -5045,8 +5005,8 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.2.0: - resolution: {integrity: sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==} + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} engines: {node: '>=12'} ansi-styles@4.3.0: @@ -5057,14 +5017,10 @@ packages: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} engines: {node: '>=10'} - ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} - ansis@3.17.0: - resolution: {integrity: sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==} - engines: {node: '>=14'} - ansis@4.1.0: resolution: {integrity: sha512-BGcItUBWSMRgOCe+SVZJ+S7yTRG0eGt9cXAHev72yuGcY23hnLA7Bky5L/xLyPINoSN95geovfBkqoTlNZYa7w==} engines: {node: '>=14'} @@ -5076,10 +5032,6 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} - app-root-path@3.1.0: - resolution: {integrity: sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==} - engines: {node: '>= 6.0.0'} - append-field@1.0.0: resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==} @@ -5157,12 +5109,6 @@ packages: async@0.2.10: resolution: {integrity: sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==} - async@3.2.2: - resolution: {integrity: sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==} - - async@3.2.4: - resolution: {integrity: sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==} - async@3.2.6: resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} @@ -5220,11 +5166,11 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - bare-events@2.6.1: - resolution: {integrity: sha512-AuTJkq9XmE6Vk0FJVNq5QxETrSA/vKHarWVBG5l/JbdCL1prJemiyJqUS0jrlXO0MftuPq4m3YVYhoNc5+aE/g==} + bare-events@2.7.0: + resolution: {integrity: sha512-b3N5eTW1g7vXkw+0CXh/HazGTcO5KYuu/RCNaJbDMPI6LHDi+7qe8EmxKUVe1sUbY2KZOVZFyj62x0OEz9qyAA==} - bare-fs@4.2.0: - resolution: {integrity: sha512-oRfrw7gwwBVAWx9S5zPMo2iiOjxyiZE12DmblmMQREgcogbNO0AFaZ+QBxxkEXiPspcpvO/Qtqn8LabUx4uYXg==} + bare-fs@4.4.7: + resolution: {integrity: sha512-huJQxUWc2d1T+6dxnC/FoYpBgEHzJp33mYZqFtQqTTPPyP9xPvmjC16VpR4wTte4ZKd5VxkFAcfDYi51iwWMcg==} engines: {bare: '>=1.16.0'} peerDependencies: bare-buffer: '*' @@ -5232,8 +5178,8 @@ packages: bare-buffer: optional: true - bare-os@3.6.1: - resolution: {integrity: sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g==} + bare-os@3.6.2: + resolution: {integrity: sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A==} engines: {bare: '>=1.14.0'} bare-path@3.0.0: @@ -5250,6 +5196,9 @@ packages: bare-events: optional: true + bare-url@2.2.2: + resolution: {integrity: sha512-g+ueNGKkrjMazDG3elZO1pNs3HY5+mMmOet1jtKyhOaCnkLzitxf26z7hoAEkDNgdNmnc1KIlt/dw6Po6xZMpA==} + base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -5257,6 +5206,10 @@ packages: resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} engines: {node: ^4.5.0 || >= 5.9} + baseline-browser-mapping@2.8.15: + resolution: {integrity: sha512-qsJ8/X+UypqxHXN75M7dF88jNK37dLBRW7LeUzCPz+TNs37G8cfWy9nWzS+LS//g600zrt2le9KuXt0rWfDz5Q==} + hasBin: true + batch-cluster@13.0.0: resolution: {integrity: sha512-EreW0Vi8TwovhYUHBXXRA5tthuU2ynGsZFlboyMJHCCUXYa2AjgwnE3ubBOJs2xJLcuXFJbi6c/8pH5+FVj8Og==} engines: {node: '>=14'} @@ -5277,15 +5230,12 @@ packages: big.js@5.2.2: resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} - bignumber.js@9.3.1: - resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==} - binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} - bits-ui@2.9.4: - resolution: {integrity: sha512-Cqn685P6DDuEyBZT/CWMyS5+8JAnYbctvoEVPcmiut+HUpG3SozVgjoDaUib5VG4ZYUKEi1FPwHxiXo9c6J0PA==} + bits-ui@2.9.8: + resolution: {integrity: sha512-oVAqdhLSuGIgEiT0yu3ShSI7AxncCxX26Gv6Lul94BuKHV2uzHoKfIodtnMQSq+udJ54svuCIRqA58whsv7vaA==} engines: {node: '>=20'} peerDependencies: '@internationalized/date': ^3.8.1 @@ -5308,6 +5258,9 @@ packages: boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + bowser@2.12.1: + resolution: {integrity: sha512-z4rE2Gxh7tvshQ4hluIT7XcFrgLIQaw9X3A+kTTRdovCz5PMukm/0QC/BKSYPj3omF5Qfypn9O/c5kgpmvYUCw==} + boxen@6.2.1: resolution: {integrity: sha512-H4PEsJXfFI/Pt8sjDWbHlQPx4zL/bvSQjcilJmaulGt5mLDorHOHpmdXAJcBcmru7PhYSp/cDMWRko4ZUMFkSw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -5326,8 +5279,8 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.25.3: - resolution: {integrity: sha512-cDGv1kkDI4/0e5yON9yM5G/0A5u8sf5TnmdX5C9qHzI9PPu++sQ9zjm1k9NiOrf3riY4OkK0zSGqfvJyJsgCBQ==} + browserslist@4.26.3: + resolution: {integrity: sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -5352,8 +5305,12 @@ packages: resolution: {integrity: sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg==} engines: {node: '>=18.20'} - bullmq@5.57.0: - resolution: {integrity: sha512-Xlh5mh6VQmHS6x5PIuYNf55Nn3T7GGN5Is+zHysN4ZUomX3RziyRFzQXeWgn3SKbaXxQ3aLWHjYDMaE5MhEXyA==} + bullmq@5.61.0: + resolution: {integrity: sha512-khaTjc1JnzaYFl4FrUtsSsqugAW/urRrcZ9Q0ZE+REAw8W+gkHFqxbGlutOu6q7j7n91wibVaaNlOUMdiEvoSQ==} + + bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} busboy@1.6.0: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} @@ -5408,9 +5365,6 @@ packages: resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} engines: {node: '>= 0.4'} - call-me-maybe@1.0.2: - resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==} - callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -5437,8 +5391,8 @@ packages: caniuse-api@3.0.0: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} - caniuse-lite@1.0.30001735: - resolution: {integrity: sha512-EV/laoX7Wq2J9TQlyIXRxTJqIw4sxfXS4OYgudGxBYRuTv0q7AM6yMEpU/Vo1I94thg9U6EZ2NfZx9GJq83u7w==} + caniuse-lite@1.0.30001749: + resolution: {integrity: sha512-0rw2fJOmLfnzCRbkm8EyHL8SvI2Apu5UbnQuTsJ0ClgrH8hcwFooJ1s5R0EP8o8aVrFu8++ae29Kt9/gZAZp/Q==} canvas@2.11.2: resolution: {integrity: sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==} @@ -5455,8 +5409,8 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} - chalk@5.6.0: - resolution: {integrity: sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ==} + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} change-case@5.4.4: @@ -5478,16 +5432,9 @@ packages: character-reference-invalid@2.0.1: resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} - chardet@0.7.0: - resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} - chardet@2.1.0: resolution: {integrity: sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==} - charset@1.0.1: - resolution: {integrity: sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==} - engines: {node: '>=4.0.0'} - check-error@2.1.1: resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} engines: {node: '>= 16'} @@ -5542,9 +5489,6 @@ packages: class-validator@0.14.2: resolution: {integrity: sha512-3kMVRF2io8N8pY1IFIXlho9r8IPUUIfHe2hYVtiebvAzU2XeQFXTv+XI4WX+TnXmtwXMDcjngcpkiPM0O9PvLw==} - classnames@2.5.1: - resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} - clean-css@5.3.3: resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} engines: {node: '>= 10.0'} @@ -5608,10 +5552,6 @@ packages: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} - clsx@1.2.1: - resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} - engines: {node: '>=6'} - clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} @@ -5630,17 +5570,10 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - color-string@1.9.1: - resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} - color-support@1.1.3: resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} hasBin: true - color@4.2.3: - resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} - engines: {node: '>=12.5.0'} - colord@2.9.3: resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} @@ -5696,8 +5629,8 @@ packages: resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} engines: {node: '>= 12'} - comment-json@4.2.5: - resolution: {integrity: sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw==} + comment-json@4.4.1: + resolution: {integrity: sha512-r1To31BQD5060QdkC+Iheai7gHwoSZobzunqkf2/kQ6xIAfJyrKNAFUwdKvkK7Qgu7pVTKQEa7ok7Ed3ycAJgg==} engines: {node: '>= 6'} common-path-prefix@3.0.0: @@ -5718,12 +5651,6 @@ packages: resolution: {integrity: sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==} engines: {node: '>= 0.8.0'} - compute-gcd@1.2.1: - resolution: {integrity: sha512-TwMbxBNz0l71+8Sc4czv13h4kEqnchV9igQZBi6QUaz09dnz13juGnnaWWJTRsP3brxOoxeB4SA2WELLw1hCtg==} - - compute-lcm@1.1.2: - resolution: {integrity: sha512-OFNPdQAXnQhDSKioX8/XYT6sdUlXwpeMjfd6ApxMJfyZ4GxmLR1xvMERctlYhlHwIiz6CSpBc2+qYKjHGZw4TQ==} - concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -5805,10 +5732,6 @@ packages: resolution: {integrity: sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==} engines: {node: '>= 0.8'} - copy-text-to-clipboard@3.2.0: - resolution: {integrity: sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q==} - engines: {node: '>=12'} - copy-webpack-plugin@11.0.0: resolution: {integrity: sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==} engines: {node: '>= 14.15.0'} @@ -5857,17 +5780,14 @@ packages: resolution: {integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==} engines: {node: '>=12.0.0'} - cron@4.3.0: - resolution: {integrity: sha512-ciiYNLfSlF9MrDqnbMdRWFiA6oizSF7kA1osPP9lRzNu0Uu+AWog1UKy7SkckiDY2irrNjeO6qLyKnXC8oxmrw==} + cron@4.3.3: + resolution: {integrity: sha512-B/CJj5yL3sjtlun6RtYHvoSB26EmQ2NUmhq9ZiJSyKIM4K/fqfh9aelDFlIayD2YMeFZqWLi9hHV+c+pq2Djkw==} engines: {node: '>=18.x'} cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} - crypto-js@4.2.0: - resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} - crypto-random-string@4.0.0: resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==} engines: {node: '>=12'} @@ -6033,9 +5953,6 @@ packages: resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} engines: {node: '>=18'} - dayjs@1.11.13: - resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} - debounce@1.2.1: resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} @@ -6060,8 +5977,8 @@ packages: supports-color: optional: true - debug@4.4.1: - resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -6087,14 +6004,6 @@ packages: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} - dedent@1.6.0: - resolution: {integrity: sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==} - peerDependencies: - babel-plugin-macros: ^3.1.0 - peerDependenciesMeta: - babel-plugin-macros: - optional: true - deep-eql@5.0.2: resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} @@ -6113,9 +6022,13 @@ packages: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} - default-gateway@6.0.3: - resolution: {integrity: sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==} - engines: {node: '>= 10'} + default-browser-id@5.0.0: + resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} + engines: {node: '>=18'} + + default-browser@5.2.1: + resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} + engines: {node: '>=18'} defaults@1.0.4: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} @@ -6132,6 +6045,10 @@ packages: resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} engines: {node: '>=8'} + define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + define-properties@1.2.1: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} @@ -6166,24 +6083,20 @@ packages: detect-europe-js@0.1.2: resolution: {integrity: sha512-lgdERlL3u0aUdHocoouzT10d9I89VVhk0qNRmll7mXdGfJT1/wqZ2ZLA4oJAjeACPY5fT1wsbq2AT+GkuInsow==} - detect-libc@2.0.4: - resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} detect-node@2.1.0: resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} - detect-package-manager@3.0.2: - resolution: {integrity: sha512-8JFjJHutStYrfWwzfretQoyNGoZVW1Fsrp4JO9spa7h/fBfwgTMEIy4/LBzRDGsxwVPHU0q+T9YvwLDJoOApLQ==} - engines: {node: '>=12'} - detect-port@1.6.1: resolution: {integrity: sha512-CmnVc+Hek2egPx1PeTFVta2W78xy2K/9Rkf6cC4T59S50tVnzKj+tnx5mmx5lwvCkujZ4uRrpRSuV+IVs3f90Q==} engines: {node: '>= 4.0.0'} hasBin: true - devalue@5.1.1: - resolution: {integrity: sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==} + devalue@5.3.2: + resolution: {integrity: sha512-UDsjUbpQn9kvm68slnrs+mfxwFkIflOhkanmyabZ8zOYk8SMEIbJ3TK+88g70hSIeytu4y18f0z/hYHMTrXIWw==} devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} @@ -6218,16 +6131,16 @@ packages: resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} engines: {node: '>=6'} - docker-compose@1.2.0: - resolution: {integrity: sha512-wIU1eHk3Op7dFgELRdmOYlPYS4gP8HhH1ZmZa13QZF59y0fblzFDFmKPhyc05phCy2hze9OEvNZAsoljrs+72w==} + docker-compose@1.3.0: + resolution: {integrity: sha512-7Gevk/5eGD50+eMD+XDnFnOrruFkL0kSd7jEG4cjmqweDSUhB7i0g8is/nBdVpl+Bx338SqIB2GLKm32M+Vs6g==} engines: {node: '>= 6.0.0'} docker-modem@5.0.6: resolution: {integrity: sha512-ens7BiayssQz/uAxGzH8zGXCtiV24rRWXdjNha5V4zSOcxmAZsfGVm/PPFbwQdqEkDnhG+SyR9E3zSHUbOKXBQ==} engines: {node: '>= 8.0'} - dockerode@4.0.7: - resolution: {integrity: sha512-R+rgrSRTRdU5mH14PZTCPZtW/zw3HDWNTS/1ZAQpL/5Upe/ye5K9WQkIysu4wBoiMwKynsz0a8qWuGsHgEvSAA==} + dockerode@4.0.9: + resolution: {integrity: sha512-iND4mcOWhPaCNh54WmK/KoSb35AFqPAUWFMffTQcp52uQt36b5uNwEJTSXntJZBbeGad72Crbi/hvDIv6us/6Q==} engines: {node: '>= 8.0'} docusaurus-lunr-search@3.6.0: @@ -6238,31 +6151,6 @@ packages: react: ^16.8.4 || ^17 || ^18 || ^19 react-dom: ^16.8.4 || ^17 || ^18 || ^19 - docusaurus-plugin-openapi@0.7.6: - resolution: {integrity: sha512-LR8DI0gO9WFy8K+r0xrVgqDkKKA9zQtDgOnX9CatP3I3Oz5lKegfTJM2fVUIp5m25elzHL+vVKNHS12Jg7sWVA==} - engines: {node: '>=18'} - peerDependencies: - react: ^18.0.0 - react-dom: ^18.0.0 - - docusaurus-plugin-proxy@0.7.6: - resolution: {integrity: sha512-MgjzMEsQOHMljwQGglXXoGjQvs0v1DklhRgzqNLKFwpHB9xLWJZ0KQ3GgbPerW/2vy8tWGJeVhKHy5cPrmweUw==} - engines: {node: '>=14'} - - docusaurus-preset-openapi@0.7.6: - resolution: {integrity: sha512-QnArH/3X0lePB7667FyNK3EeTS8ZP8V2PQxz5m+3BMO2kIzdXDwfTIQ37boB0BTqsDfUE0yCWTVjB0W/BA1UXA==} - engines: {node: '>=18'} - peerDependencies: - react: ^18.0.0 - react-dom: ^18.0.0 - - docusaurus-theme-openapi@0.7.6: - resolution: {integrity: sha512-euoEh8tYX/ssQcMQxBOxt3wPttz3zvPu0l5lSe6exiIwMrORB4O2b8XRB7fVa/awF7xzdIkKHMH55uc5zVOKYA==} - engines: {node: '>=18'} - peerDependencies: - react: ^18.0.0 - react-dom: ^18.0.0 - dom-accessibility-api@0.5.16: resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} @@ -6310,12 +6198,8 @@ packages: resolution: {integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==} engines: {node: '>=10'} - dotenv@16.6.1: - resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} - engines: {node: '>=12'} - - dotenv@17.2.1: - resolution: {integrity: sha512-kQhDYKZecqnM0fCnzI5eIv5L4cAe/iRI+HqMbO/hbRdTAeXDG+M9FjipUxNfbARuEg4iHIbhnhs78BCHNbSxEQ==} + dotenv@17.2.3: + resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==} engines: {node: '>=12'} dunder-proto@1.0.1: @@ -6337,11 +6221,11 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.207: - resolution: {integrity: sha512-mryFrrL/GXDTmAtIVMVf+eIXM09BBPlO5IQ7lUyKmK8d+A4VpRGG+M3ofoVef6qyF8s60rJei8ymlJxjUA8Faw==} + electron-to-chromium@1.5.233: + resolution: {integrity: sha512-iUdTQSf7EFXsDdQsp8MwJz5SVk4APEFqXU/S47OtQ0YLqacSwPXdZ5vRlMX3neb07Cy2vgioNuRnWUXFwuslkg==} - emoji-regex@10.4.0: - resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} + emoji-regex@10.6.0: + resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -6406,8 +6290,8 @@ packages: err-code@2.0.3: resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} - error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + error-ex@1.3.4: + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} @@ -6435,9 +6319,6 @@ packages: es6-iterator@2.0.3: resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} - es6-promise@3.3.1: - resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} - es6-symbol@3.1.4: resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==} engines: {node: '>=0.12'} @@ -6456,8 +6337,8 @@ packages: engines: {node: '>=12'} hasBin: true - esbuild@0.25.9: - resolution: {integrity: sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==} + esbuild@0.25.10: + resolution: {integrity: sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==} engines: {node: '>=18'} hasBin: true @@ -6495,12 +6376,6 @@ packages: peerDependencies: eslint: '>=7.0.0' - eslint-p@0.25.0: - resolution: {integrity: sha512-e7oYgXN/tgtoaR3tZ0R2dKyPJtf5J41hYKsgpsBtwpi0t2Cxjf3l8G2QwrXCDwQTFVXW1hmD55hAqQZxiId1XA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - deprecated: ESLint has built-in support for multithread linting now. This package is no longer needed. - hasBin: true - eslint-plugin-compat@6.0.2: resolution: {integrity: sha512-1ME+YfJjmOz1blH0nPZpHgjMGK4kjgEeoYqGCqoBPQ/mGu/dJzdoP0f1C8H2jcWZjzhZjAMccbM/VdXhPORIfA==} engines: {node: '>=18.x'} @@ -6521,8 +6396,8 @@ packages: eslint-config-prettier: optional: true - eslint-plugin-svelte@3.11.0: - resolution: {integrity: sha512-KliWlkieHyEa65aQIkRwUFfHzT5Cn4u3BQQsu3KlkJOs7c1u7ryn84EWaOjEzilbKgttT4OfBURA8Uc4JBSQIw==} + eslint-plugin-svelte@3.12.4: + resolution: {integrity: sha512-hD7wPe+vrPgx3U2X2b/wyTMtWobm660PygMGKrWWYTc9lvtY8DpNFDaU2CJQn1szLjGbn/aJ3g8WiXuKakrEkw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.1 || ^9.0.0 @@ -6537,6 +6412,12 @@ packages: peerDependencies: eslint: '>=9.29.0' + eslint-plugin-unicorn@61.0.2: + resolution: {integrity: sha512-zLihukvneYT7f74GNbVJXfWIiNQmkc/a9vYBTE4qPkQZswolWNdu+Wsp9sIXno1JOzdn6OUwLPd19ekXVkahRA==} + engines: {node: ^20.10.0 || >=21.0.0} + peerDependencies: + eslint: '>=9.29.0' + eslint-scope@5.1.1: resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} engines: {node: '>=8.0.0'} @@ -6553,18 +6434,8 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.30.1: - resolution: {integrity: sha512-zmxXPNMOXmwm9E0yQLi5uqXHs7uq2UIiqEKo3Gq+3fwo1XrJ+hijAZImyF7hclW3E6oHz43Yk3RP8at6OTKflQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - hasBin: true - peerDependencies: - jiti: '*' - peerDependenciesMeta: - jiti: - optional: true - - eslint@9.33.0: - resolution: {integrity: sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA==} + eslint@9.37.0: + resolution: {integrity: sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -6662,12 +6533,12 @@ packages: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} - eventemitter2@6.4.9: - resolution: {integrity: sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==} - eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + events-universal@1.0.1: + resolution: {integrity: sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==} + events@3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} @@ -6715,10 +6586,6 @@ packages: extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - external-editor@3.1.0: - resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} - engines: {node: '>=4'} - fabric@6.7.1: resolution: {integrity: sha512-dLxSmIvN4InJf4xOjbl1LFWh8WGOUIYtcuDIGs2IN0Z9lI0zGobfesDauyEhI1+owMLTPCCiEv01rpYXm7g2EQ==} engines: {node: '>=16.20.0'} @@ -6752,8 +6619,12 @@ packages: fast-safe-stringify@2.1.1: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} - fast-uri@3.0.6: - resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} + fast-uri@3.1.0: + resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + + fast-xml-parser@5.2.5: + resolution: {integrity: sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==} + hasBin: true fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} @@ -6802,10 +6673,6 @@ packages: resolution: {integrity: sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg==} engines: {node: '>=20'} - file-type@3.9.0: - resolution: {integrity: sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==} - engines: {node: '>=0.10.0'} - fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -6863,9 +6730,6 @@ packages: debug: optional: true - foreach@2.0.6: - resolution: {integrity: sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg==} - foreground-child@3.3.1: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} @@ -6889,9 +6753,6 @@ packages: resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} engines: {node: '>=0.4.x'} - formidable@2.1.5: - resolution: {integrity: sha512-Oz5Hwvwak/DCaXVVUtPn4oLMLLy1CdclLKO1LFgU7XzDpVMUU5UjlSLpGMocyQNNk8F6IJW9M/YdooSn2MRI+Q==} - formidable@3.5.4: resolution: {integrity: sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==} engines: {node: '>=14.0.0'} @@ -6957,14 +6818,6 @@ packages: engines: {node: '>=10'} deprecated: This package is no longer supported. - gaxios@6.7.1: - resolution: {integrity: sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==} - engines: {node: '>=14'} - - gcp-metadata@6.1.1: - resolution: {integrity: sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==} - engines: {node: '>=14'} - gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -6994,8 +6847,8 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - get-east-asian-width@1.3.0: - resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} + get-east-asian-width@1.4.0: + resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==} engines: {node: '>=18'} get-intrinsic@1.3.0: @@ -7013,10 +6866,6 @@ packages: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} - get-stdin@5.0.1: - resolution: {integrity: sha512-jZV7n6jGE3Gt7fgSTJoz91Ak5MuTLwMwkoYdjxuJ/AmjIsE1UC03y/IWkZCQGEvVNS9qoRNwy5BCqxImv0FVeA==} - engines: {node: '>=0.12.0'} - get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} @@ -7035,6 +6884,12 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + glob-to-regex.js@1.2.0: + resolution: {integrity: sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + glob-to-regexp@0.4.1: resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} @@ -7067,8 +6922,8 @@ packages: resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} engines: {node: '>=18'} - globals@16.3.0: - resolution: {integrity: sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==} + globals@16.4.0: + resolution: {integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==} engines: {node: '>=18'} globalyzer@0.1.0: @@ -7085,10 +6940,6 @@ packages: globrex@0.1.2: resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} - google-logging-utils@0.0.2: - resolution: {integrity: sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==} - engines: {node: '>=14'} - gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -7106,9 +6957,6 @@ packages: graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - graphlib@2.1.8: - resolution: {integrity: sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==} - gray-matter@4.0.3: resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} engines: {node: '>=6.0'} @@ -7128,18 +6976,14 @@ packages: engines: {node: '>=0.4.7'} hasBin: true - happy-dom@18.0.1: - resolution: {integrity: sha512-qn+rKOW7KWpVTtgIUi6RVmTBZJSe2k0Db0vh1f7CWrWclkkc7/Q+FrOfkZIb2eiErLyqu5AXEzE7XthO9JVxRA==} + happy-dom@20.0.0: + resolution: {integrity: sha512-GkWnwIFxVGCf2raNrxImLo397RdGhLapj5cT3R2PT7FwL62Ze1DROhzmYW7+J3p9105DYMVenEejEbnq5wA37w==} engines: {node: '>=20.0.0'} has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - has-own-prop@2.0.0: - resolution: {integrity: sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==} - engines: {node: '>=8'} - has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} @@ -7177,9 +7021,6 @@ packages: hast-util-parse-selector@2.2.5: resolution: {integrity: sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==} - hast-util-parse-selector@3.1.1: - resolution: {integrity: sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==} - hast-util-parse-selector@4.0.0: resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} @@ -7213,9 +7054,6 @@ packages: hastscript@6.0.0: resolution: {integrity: sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==} - hastscript@7.2.0: - resolution: {integrity: sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==} - hastscript@9.0.1: resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==} @@ -7223,6 +7061,10 @@ packages: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true + highlight.js@11.11.1: + resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==} + engines: {node: '>=12.0.0'} + history@4.10.1: resolution: {integrity: sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==} @@ -7244,9 +7086,6 @@ packages: resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} engines: {node: '>=18'} - html-entities@2.6.0: - resolution: {integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==} - html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} @@ -7335,12 +7174,6 @@ packages: resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} engines: {node: '>=8.0.0'} - http-reasons@0.1.0: - resolution: {integrity: sha512-P6kYh0lKZ+y29T2Gqz+RlC9WBLhKe8kDmcJ+A+611jFfxdPsbMRQ5aNmFRM3lENqFkK+HTTL+tlQviAiv0AbLQ==} - - http2-client@1.3.5: - resolution: {integrity: sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==} - http2-wrapper@2.2.1: resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==} engines: {node: '>=10.19.0'} @@ -7357,6 +7190,10 @@ packages: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} + hyperdyperid@1.2.0: + resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==} + engines: {node: '>=10.18'} + i18n-iso-countries@7.14.0: resolution: {integrity: sha512-nXHJZYtNrfsi1UQbyRqm3Gou431elgLjKl//CYlnBGt5aTWdRPH1PiS2T/p/n8Q8LnqYqzQJik3Q7mkwvLokeg==} engines: {node: '>= 12'} @@ -7369,6 +7206,10 @@ packages: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} + iconv-lite@0.7.0: + resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==} + engines: {node: '>=0.10.0'} + icss-utils@5.1.0: resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} engines: {node: ^10 || ^12 || >= 14} @@ -7398,15 +7239,12 @@ packages: immediate@3.3.0: resolution: {integrity: sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==} - immer@9.0.21: - resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==} - import-fresh@3.3.1: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} - import-in-the-middle@1.14.2: - resolution: {integrity: sha512-5tCuY9BV8ujfOpwtAGgsTx9CGUapcFMEEyByLv1B+v2+6DhAcw+Zr0nhQT7uwaZ7DiourxFEscghOR8e1aPLQw==} + import-in-the-middle@1.14.4: + resolution: {integrity: sha512-eWjxh735SJLFJJDs5X82JQ2405OdJeAHDBnaoFCfdr5GVc7AWc9xU7KbrF+3Xd5F2ccP1aQFKtY+65X6EfKZ7A==} import-lazy@4.0.0: resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} @@ -7448,26 +7286,22 @@ packages: inline-style-parser@0.2.4: resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==} - inquirer@8.2.6: - resolution: {integrity: sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==} + inquirer@8.2.7: + resolution: {integrity: sha512-UjOaSel/iddGZJ5xP/Eixh6dY1XghiBw4XK13rCCIJcJfyhhoul/7KhLLUGtebEj6GDYM6Vnx/mVsjx2L/mFIA==} engines: {node: '>=12.0.0'} internmap@2.0.3: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} - interpret@1.4.0: - resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} - engines: {node: '>= 0.10'} - - intl-messageformat@10.7.16: - resolution: {integrity: sha512-UmdmHUmp5CIKKjSoE10la5yfU+AYJAaiYLsodbjL4lji83JNvgOQUjGaGhGrpFCb0Uh7sl7qfP1IyILa8Z40ug==} + intl-messageformat@10.7.17: + resolution: {integrity: sha512-0Ugaf65B2J76rb31drgNF1l6bGEDkbIiYc2Glx6jaZINHnwa5kDRGy8KXYuA+/8P4G0c9prAFhfVhQJJfzUuvQ==} invariant@2.2.4: resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} - ioredis@5.7.0: - resolution: {integrity: sha512-NUcA93i1lukyXU+riqEyPtSEkyFq8tX90uL659J+qpCZ3rEdViB/APC58oAhIh3+bJln2hzdlZbBZsGNrlsR8g==} + ioredis@5.8.1: + resolution: {integrity: sha512-Qho8TgIamqEPdgiMadJwzRMW3TudIg6vpg4YONokGDudy4eqRIJtDbVX72pfLBcWxvbn3qm/40TyGUObdW4tLQ==} engines: {node: '>=12.22.0'} ip-address@10.0.1: @@ -7491,9 +7325,6 @@ packages: is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - is-arrayish@0.3.2: - resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} - is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} @@ -7522,6 +7353,11 @@ packages: engines: {node: '>=8'} hasBin: true + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + is-extendable@0.1.1: resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} engines: {node: '>=0.10.0'} @@ -7541,6 +7377,11 @@ packages: is-hexadecimal@2.0.1: resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + is-installed-globally@0.4.0: resolution: {integrity: sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==} engines: {node: '>=10'} @@ -7553,6 +7394,10 @@ packages: resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} engines: {node: '>=12'} + is-network-error@1.3.0: + resolution: {integrity: sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==} + engines: {node: '>=16'} + is-npm@6.0.0: resolution: {integrity: sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -7635,6 +7480,10 @@ packages: resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} engines: {node: '>=8'} + is-wsl@3.1.0: + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} + is-yarn-global@0.4.1: resolution: {integrity: sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==} engines: {node: '>=12'} @@ -7703,8 +7552,8 @@ packages: resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} hasBin: true - jiti@2.5.1: - resolution: {integrity: sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==} + jiti@2.6.1: + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true joi@17.13.3: @@ -7713,8 +7562,8 @@ packages: jose@5.10.0: resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==} - jose@6.0.12: - resolution: {integrity: sha512-T8xypXs8CpmiIi78k0E+Lk7T2zlK4zDyg+o1CZ4AkOHgDg98ogdP2BeZ61lTFKFyoEwJ9RgAgN+SdM3iPgNonQ==} + jose@6.1.0: + resolution: {integrity: sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA==} js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -7758,34 +7607,12 @@ packages: engines: {node: '>=6'} hasBin: true - json-bigint@1.0.0: - resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} - json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - json-pointer@0.6.2: - resolution: {integrity: sha512-vLWcKbOaXlO+jvRy4qNd+TI1QUPZzfJj1tpJ3vAXDych5XJf93ftpUKe5pKCrzyIIwgBJcOcCVRUfqQP25afBw==} - - json-refs@3.0.15: - resolution: {integrity: sha512-0vOQd9eLNBL18EGl5yYaO44GhixmImes2wiYn9Z3sag3QnehWrYWlB9AFtMxCL2Bj3fyxgDYkxGFEU/chlYssw==} - engines: {node: '>=0.8'} - hasBin: true - - json-schema-compare@0.2.2: - resolution: {integrity: sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ==} - - json-schema-merge-allof@0.8.1: - resolution: {integrity: sha512-CTUKmIlPJbsWfzRRnOXz+0MjIqvnleIXwFTzz+t9T86HnYX/Rozria6ZVGLktAU9e+NygNljveP+yxqtQp/Q4w==} - engines: {node: '>=12.0.0'} - - json-schema-resolve-allof@1.5.0: - resolution: {integrity: sha512-Jgn6BQGSLDp3D7bTYrmCbP/p7SRFz5BfpeEJ9A7sXuVADMc14aaDN1a49zqk9D26wwJlcNvjRpT63cz1VgFZeg==} - hasBin: true - json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} @@ -7850,11 +7677,15 @@ packages: resolution: {integrity: sha512-oDxVkRwPOHhGlxKIDiDB2h+/l05QPtefD7nSqRgDfZt8P+QVYFWjfeK8jANf5O2YXjk8egd7KntvXKYx82wOag==} engines: {node: '>= 18'} - kysely-postgres-js@2.0.0: - resolution: {integrity: sha512-R1tWx6/x3tSatWvsmbHJxpBZYhNNxcnMw52QzZaHKg7ZOWtHib4iZyEaw4gb2hNKVctWQ3jfMxZT/ZaEMK6kBQ==} + kysely-postgres-js@3.0.0: + resolution: {integrity: sha512-o2t/xNSYJQDW6rVGGFPXKmZ0BEz2dGn66c2B+cO/k9ZNcU2qPWPycQPQ+B+P2MBXbKYq0xV9BZmFIvkUrmFWAQ==} + engines: {bun: '>=1.2', node: '>=20'} peerDependencies: kysely: '>= 0.24.0 < 1' - postgres: '>= 3.4.0 < 4' + postgres: ^3.4.0 + peerDependenciesMeta: + postgres: + optional: true kysely@0.28.2: resolution: {integrity: sha512-4YAVLoF0Sf0UTqlhgQMFU9iQECdah7n+13ANkiuVfRvlK+uI0Etbgd7bVP36dKlG+NXWbhGua8vnGt+sdhvT7A==} @@ -7960,10 +7791,6 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - liquid-json@0.3.1: - resolution: {integrity: sha512-wUayTU8MS827Dam6MxgD72Ui+KOSF+u/eIqpatOtjnvgJ0+mnDq33uC2M7J0tPK+upe/DpUAuK4JUU89iBoNKQ==} - engines: {node: '>=4'} - load-esm@1.0.2: resolution: {integrity: sha512-nVAvWk/jeyrWyXEAs84mpQCYccxRqgKY4OznLuJhJCa0XsPSfdOIr2zvBZEj3IHEHbX97jjscKRRV539bW0Gpw==} engines: {node: '>=13.2.0'} @@ -7972,8 +7799,8 @@ packages: resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - loader-runner@4.3.0: - resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} + loader-runner@4.3.1: + resolution: {integrity: sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==} engines: {node: '>=6.11.5'} loader-utils@2.0.4: @@ -8057,8 +7884,8 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - lru-cache@11.1.0: - resolution: {integrity: sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==} + lru-cache@11.2.1: + resolution: {integrity: sha512-r8LA6i4LP4EeWOhqBaZZjDWwehd1xUJPCJd9Sv300H0ZmcUER4+JPh7bqqZeqs1o5pgtgvXm+d9UGrB5zZGDiQ==} engines: {node: 20 || >=22} lru-cache@5.1.1: @@ -8073,12 +7900,8 @@ packages: lunr@2.3.9: resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} - luxon@3.6.1: - resolution: {integrity: sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ==} - engines: {node: '>=12'} - - luxon@3.7.1: - resolution: {integrity: sha512-RkRWjA926cTvz5rAb1BqyWkKbbjzCGchDUIKMCUvNi17j6f6j8uHGDV82Aqcqtzd+icoYpELmG3ksgGiFNNcNg==} + luxon@3.7.2: + resolution: {integrity: sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==} engines: {node: '>=12'} lz-string@1.5.0: @@ -8088,6 +7911,9 @@ packages: magic-string@0.30.17: resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + magic-string@0.30.19: + resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==} + magicast@0.3.5: resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} @@ -8107,8 +7933,8 @@ packages: resolution: {integrity: sha512-p8lJFEiqmEQlyv+DQxFAOG/XPWN0Wp7j/Psq93Zywz7qt9CcUKFYDBOoOEKzqe6gudHVJY8/Bhqw6VDpX2lSBg==} engines: {node: '>=6.4.0'} - maplibre-gl@5.6.2: - resolution: {integrity: sha512-SEqYThhUCFf6Lm0TckpgpKnto5u4JsdPYdFJb6g12VtuaFsm3nYdBO+fOmnUYddc8dXihgoGnuXvPPooUcRv5w==} + maplibre-gl@5.8.0: + resolution: {integrity: sha512-zLblPFK+z5sxeitDF8RL2cnqfRaivNwxbGoQMfwAm9st6d1lRGTxgI7NNNr/U1AEPkp5+X+wjROagiHvJD8aqg==} engines: {node: '>=16.14.0', npm: '>=8.1.0'} mark.js@8.11.1: @@ -8124,11 +7950,6 @@ packages: markdown-table@3.0.4: resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} - marked@11.2.0: - resolution: {integrity: sha512-HR0m3bvu0jAPYiIvLUUQtdg1g6D247//lvcekpHO1WMvbwDlwSkZAX9Lw4F4YHE1T0HaaNve0tuAWuV1UJ6vtw==} - engines: {node: '>= 18'} - hasBin: true - marked@7.0.4: resolution: {integrity: sha512-t8eP0dXRJMtMvBojtkcsA7n48BkauktUKzfkPSCq85ZMTJ0v76Rke4DYz01omYpPTUh4p/f7HePgRo3ebG8+QQ==} engines: {node: '>= 16'} @@ -8215,6 +8036,9 @@ packages: resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} engines: {node: '>= 4.0.0'} + memfs@4.49.0: + resolution: {integrity: sha512-L9uC9vGuc4xFybbdOpRLoOAOq1YEBBsocCs5NVW32DfU+CZWWIn3OVF+lB8Gp4ttBVSMazwrTrjv8ussX/e3VQ==} + memoizee@0.4.17: resolution: {integrity: sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==} engines: {node: '>=0.12'} @@ -8376,9 +8200,6 @@ packages: resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} engines: {node: '>= 0.6'} - mime-format@2.0.1: - resolution: {integrity: sha512-XxU3ngPbEnrYnNbIX+lYSaYg0M01v6p2ntd2YaFksTu0vayaw5OJvbdRyWs07EYRlLED5qadUZ+xo+XhOvFhwg==} - mime-types@2.1.18: resolution: {integrity: sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==} engines: {node: '>= 0.6'} @@ -8488,8 +8309,8 @@ packages: resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} engines: {node: '>= 8'} - minizlib@3.0.2: - resolution: {integrity: sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==} + minizlib@3.1.0: + resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==} engines: {node: '>= 18'} mkdirp-classic@0.5.3: @@ -8508,11 +8329,6 @@ packages: engines: {node: '>=10'} hasBin: true - mkdirp@3.0.1: - resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} - engines: {node: '>=10'} - hasBin: true - mnemonist@0.40.3: resolution: {integrity: sha512-Vjyr90sJ23CKKH/qPAgUKicw/v6pRoamxIEDFOF8uSgFME7DqPRpHgRTejWVjkdGg5dXj0/NyxZHZ9bcjH+2uQ==} @@ -8523,9 +8339,6 @@ packages: module-details-from-path@1.0.4: resolution: {integrity: sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==} - monaco-editor@0.31.1: - resolution: {integrity: sha512-FYPwxGZAeP6mRRyrr5XTGHD9gRXVjy7GUzF4IPChnyt3fS5WrNxIkS8DNujWf6EQy0Zlzpxw8oTVE+mWI2/D1Q==} - moo@0.5.2: resolution: {integrity: sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==} @@ -8584,9 +8397,6 @@ packages: engines: {node: ^18 || >=20} hasBin: true - native-promise-only@0.8.1: - resolution: {integrity: sha512-zkVhZUA3y8mbz652WrL5x0fB0ehrBkulWT3TomAQ9iDtyXZvzKeEA6GPxAItBYeNYl5yngKRX612qHOhvMkDeg==} - natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -8609,12 +8419,8 @@ packages: neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - neotraverse@0.6.15: - resolution: {integrity: sha512-HZpdkco+JeXq0G+WWpMJ4NsX3pqb5O7eR9uGz3FfoFt+LYzU8iRWp49nJtud6hsDoywM8tIrDo3gjgmOqJA8LA==} - engines: {node: '>= 10'} - - nest-commander@3.18.0: - resolution: {integrity: sha512-NWtodOl2aStnApWp9oajCoJW71lqN0CCjf9ygOWxpXnG3o4nQ8ZO5CgrExfVw2+0CVC877hr0rFR7FSu2rypGg==} + nest-commander@3.20.1: + resolution: {integrity: sha512-LRI7z6UlWy2vWyQR0PYnAXsaRyJvpfiuvOCmx2jk2kLXJH9+y/omPDl9NE3fq4WMaE0/AhviuUjA12eC/zDqXw==} peerDependencies: '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 '@nestjs/core': ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 @@ -8667,10 +8473,6 @@ packages: resolution: {integrity: sha512-Z3lTE9pLaJF47NyMhd4ww1yFTAP8YhYI8SleJiHzM46Fgpm5cnNzSl9XfzFNqbaz+VlJrIj3fXQ4DeN1Rjm6cw==} engines: {node: '>=18'} - node-fetch-h2@2.3.0: - resolution: {integrity: sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==} - engines: {node: 4.x || >=6.0.0} - node-fetch@2.7.0: resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} engines: {node: 4.x || >=6.0.0} @@ -8692,19 +8494,16 @@ packages: resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} hasBin: true - node-gyp@11.3.0: - resolution: {integrity: sha512-9J0+C+2nt3WFuui/mC46z2XCZ21/cKlFDuywULmseD/LlmnOrSeEAE4c/1jw6aybXLmpZnQY3/LmOJfgyHIcng==} + node-gyp@11.4.2: + resolution: {integrity: sha512-3gD+6zsrLQH7DyYOUIutaauuXrcyxeTPyQuZQCQoNPZMHMMS5m4y0xclNpvYzoK3VNzuyxT6eF4mkIL4WSZ1eQ==} engines: {node: ^18.17.0 || >=20.5.0} hasBin: true - node-readfiles@0.2.0: - resolution: {integrity: sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA==} + node-releases@2.0.23: + resolution: {integrity: sha512-cCmFDMSm26S6tQSDpBCg/NR8NENrVPhAJSf+XbxBG4rPFaaonlEoE9wHQmun+cls499TQGSb7ZyPBRlzgKfpeg==} - node-releases@2.0.19: - resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} - - nodemailer@7.0.5: - resolution: {integrity: sha512-nsrh2lO3j4GkLLXoeEksAMgAOqxOv6QumNRVQTJwKH4nuiww6iC2y7GyANs9kRAxCexg3+lTWM3PZ91iLlVjfg==} + nodemailer@7.0.9: + resolution: {integrity: sha512-9/Qm0qXIByEP8lEV2qOqcAW7bRpL8CR9jcTwk3NBnHJNmP9fIJ86g2fgmIXqHY+nj55ZEMwWqYAT2QTDpRUYiQ==} engines: {node: '>=6.0.0'} nopt@1.0.10: @@ -8759,36 +8558,16 @@ packages: peerDependencies: webpack: ^4.0.0 || ^5.0.0 - nwsapi@2.2.21: - resolution: {integrity: sha512-o6nIY3qwiSXl7/LuOU0Dmuctd34Yay0yeuZRLFmDPrrdHpXKFndPj3hM+YEPVHYC5fx2otBx4Ilc/gyYSAUaIA==} + nwsapi@2.2.22: + resolution: {integrity: sha512-ujSMe1OWVn55euT1ihwCI1ZcAaAU3nxUiDwfDQldc51ZXaB9m2AyOn6/jh1BLe2t/G8xd6uKG1UBF2aZJeg2SQ==} nypm@0.6.0: resolution: {integrity: sha512-mn8wBFV9G9+UFHIrq+pZ2r2zL4aPau/by3kJb3cM7+5tQHMt6HGQB8FDIeKFYp8o0D2pnH6nVsO88N4AmUxIWg==} engines: {node: ^14.16.0 || >=16.10.0} hasBin: true - oas-kit-common@1.0.8: - resolution: {integrity: sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ==} - - oas-linter@3.2.2: - resolution: {integrity: sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ==} - - oas-resolver-browser@2.5.6: - resolution: {integrity: sha512-Jw5elT/kwUJrnGaVuRWe1D7hmnYWB8rfDDjBnpQ+RYY/dzAewGXeTexXzt4fGEo6PUE4eqKqPWF79MZxxvMppA==} - hasBin: true - - oas-resolver@2.5.6: - resolution: {integrity: sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ==} - hasBin: true - - oas-schema-walker@1.1.5: - resolution: {integrity: sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ==} - - oas-validator@5.0.8: - resolution: {integrity: sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw==} - - oauth4webapi@3.7.0: - resolution: {integrity: sha512-Q52wTPUWPsVLVVmTViXPQFMW2h2xv2jnDGxypjpelCFKaOjLsm7AxYuOk1oQgFm95VNDbuggasu9htXrz6XwKw==} + oauth4webapi@3.8.2: + resolution: {integrity: sha512-FzZZ+bht5X0FKe7Mwz3DAVAmlH1BV5blSak/lHMBKz0/EBMhX6B10GlQYI51+oRp8ObJaX0g6pXrAxZh5s8rjw==} object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} @@ -8816,8 +8595,8 @@ packages: obuf@1.1.2: resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} - oidc-provider@9.4.1: - resolution: {integrity: sha512-luNQK3MBTN6oRliEm+sWVzne8UR+e+Zo0qCWzsY7mhdUNOcjjoe5joFgJrW4i/6mEMYdeWUAPiTGrvggCsyMgQ==} + oidc-provider@9.5.1: + resolution: {integrity: sha512-19Wa4bfz3reoudxrY7sF5SeQKxe5b3dY8hWzQdnBGS87rH0BoYoDDUDRTYciJMN3oI6S02C9xM6vuaHtoZ48eA==} on-finished@2.4.1: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} @@ -8838,21 +8617,20 @@ packages: resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} engines: {node: '>=18'} + open@10.2.0: + resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==} + engines: {node: '>=18'} + open@8.4.2: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} engines: {node: '>=12'} - openapi-to-postmanv2@4.25.0: - resolution: {integrity: sha512-sIymbkQby0gzxt2Yez8YKB6hoISEel05XwGwNrAhr6+vxJWXNxkmssQc/8UEtVkuJ9ZfUXLkip9PYACIpfPDWg==} - engines: {node: '>=8'} - hasBin: true - opener@1.5.2: resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==} hasBin: true - openid-client@6.6.4: - resolution: {integrity: sha512-PLWVhRksRnNH05sqeuCX/PR+1J70NyZcAcPske+FeF732KKONd3v0p5Utx1ro1iLfCglH8B3/+dA1vqIHDoIiA==} + openid-client@6.8.1: + resolution: {integrity: sha512-VoYT6enBo6Vj2j3Q5Ec0AezS+9YGzQo1f5Xc42lreMGlfP4ljiXPKVDvCADh+XHCV/bqPu/wWSiCVXbJKvrODw==} optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} @@ -8866,10 +8644,6 @@ packages: resolution: {integrity: sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==} engines: {node: '>=18'} - os-tmpdir@1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} - p-cancelable@3.0.0: resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} engines: {node: '>=12.20'} @@ -8914,9 +8688,9 @@ packages: resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} engines: {node: '>=8'} - p-retry@4.6.2: - resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} - engines: {node: '>=8'} + p-retry@6.2.1: + resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==} + engines: {node: '>=16.17'} p-timeout@3.2.0: resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} @@ -8972,9 +8746,6 @@ packages: pascal-case@3.1.2: resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} - path-browserify@1.0.1: - resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} - path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -8994,9 +8765,6 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - path-loader@1.0.12: - resolution: {integrity: sha512-n7oDG8B+k/p818uweWrOixY9/Dsr89o2TkCm6tOTex3fpdo2+BFDgR+KpB37mGKBRsBAlR8CIJMFN0OEy/7hIQ==} - path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} @@ -9024,13 +8792,13 @@ packages: resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==} engines: {node: '>=16'} + path-to-regexp@8.3.0: + resolution: {integrity: sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==} + path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - path@0.12.7: - resolution: {integrity: sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==} - pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} @@ -9110,16 +8878,16 @@ packages: resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==} engines: {node: '>=14.16'} - pkg-types@2.2.0: - resolution: {integrity: sha512-2SM/GZGAEkPp3KWORxQZns4M+WSeXbC2HEvmOIJe3Cmiv6ieAJvdVhDldtHqM5J1Y7MrR1XhkBT/rMlhh9FdqQ==} + pkg-types@2.3.0: + resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==} - playwright-core@1.54.2: - resolution: {integrity: sha512-n5r4HFbMmWsB4twG7tJLDN9gmBUeSPcsBZiWSE4DnYz9mJMAFqr2ID7+eGC9kpEnxExJ1epttwR59LEWCk8mtA==} + playwright-core@1.56.0: + resolution: {integrity: sha512-1SXl7pMfemAMSDn5rkPeZljxOCYAmQnYLBTExuh6E8USHXGSX3dx6lYZN/xPpTz1vimXmPA9CDnILvmJaB8aSQ==} engines: {node: '>=18'} hasBin: true - playwright@1.54.2: - resolution: {integrity: sha512-Hu/BMoA1NAdRUuulyvQC0pEqZ4vQbGfn8f7wPXcnqQmM+zct9UliKxsIkLNmz/ku7LElUNqmaiv1TG/aL5ACsw==} + playwright@1.56.0: + resolution: {integrity: sha512-X5Q1b8lOdWIE4KAoHpW3SE8HvUB+ZZsUoN64ZhjnN8dOb1UpujxBtENGiZFE+9F/yhzJwYa+ca3u43FeLbboHA==} engines: {node: '>=18'} hasBin: true @@ -9287,8 +9055,8 @@ packages: peerDependencies: postcss: ^8.0.0 - postcss-js@4.0.1: - resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + postcss-js@4.1.0: + resolution: {integrity: sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==} engines: {node: ^12 || ^14 || >= 16} peerDependencies: postcss: ^8.4.21 @@ -9311,16 +9079,22 @@ packages: ts-node: optional: true - postcss-load-config@4.0.2: - resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} - engines: {node: '>= 14'} + postcss-load-config@6.0.1: + resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} + engines: {node: '>= 18'} peerDependencies: + jiti: '>=1.21.0' postcss: '>=8.0.9' - ts-node: '>=9.0.0' + tsx: ^4.8.1 + yaml: ^2.4.2 peerDependenciesMeta: + jiti: + optional: true postcss: optional: true - ts-node: + tsx: + optional: true + yaml: optional: true postcss-loader@7.3.4: @@ -9609,18 +9383,6 @@ packages: resolution: {integrity: sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==} engines: {node: '>=12'} - postman-code-generators@1.14.2: - resolution: {integrity: sha512-qZAyyowfQAFE4MSCu2KtMGGQE/+oG1JhMZMJNMdZHYCSfQiVVeKxgk3oI4+KJ3d1y5rrm2D6C6x+Z+7iyqm+fA==} - engines: {node: '>=12'} - - postman-collection@4.5.0: - resolution: {integrity: sha512-152JSW9pdbaoJihwjc7Q8lc3nPg/PC9lPTHdMk7SHnHhu/GBJB7b2yb9zG7Qua578+3PxkQ/HYBuXpDSvsf7GQ==} - engines: {node: '>=10'} - - postman-url-encoder@3.0.5: - resolution: {integrity: sha512-jOrdVvzUXBC7C+9gkIkpDJ3HIxOHTIqjpQ4C1EMt1ZGeMvSEpbFCKq23DEfgsj46vMnDgyQf+1ZLp2Wm+bKSsA==} - engines: {node: '>=10'} - potpack@1.0.2: resolution: {integrity: sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==} @@ -9635,8 +9397,8 @@ packages: resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} engines: {node: '>=6.0.0'} - prettier-plugin-organize-imports@4.2.0: - resolution: {integrity: sha512-Zdy27UhlmyvATZi67BTnLcKTo8fm6Oik59Sz6H64PgZJVs6NJpPD1mT240mmJn62c98/QaL+r3kx9Q3gRpDajg==} + prettier-plugin-organize-imports@4.3.0: + resolution: {integrity: sha512-FxFz0qFhyBsGdIsb697f/EkvHzi5SZOhWAjxcx2dLt+Q532bAlhswcXGYB1yzjZ69kW8UoadFBw7TyNwlq96Iw==} peerDependencies: prettier: '>=2.0' typescript: '>=2.9' @@ -9774,8 +9536,8 @@ packages: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} engines: {node: '>=10'} - quick-lru@7.0.1: - resolution: {integrity: sha512-kLjThirJMkWKutUKbZ8ViqFc09tDQhlbQo2MNuVeLWbRauqYP96Sm6nzlQ24F0HFjUNZ4i9+AgldJ9H6DZXi7g==} + quick-lru@7.2.0: + resolution: {integrity: sha512-fG4L8TlD1CacJiGMGPxM1/K8l/GaKL2eFQZ6DWAjxZYxSf07DkumbC/Mhh+u/NHvxkfQVL25By0pxBS8QE9ZrQ==} engines: {node: '>=18'} quickselect@2.0.0: @@ -9806,9 +9568,9 @@ packages: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} - raw-body@3.0.0: - resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==} - engines: {node: '>= 0.8'} + raw-body@3.0.1: + resolution: {integrity: sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==} + engines: {node: '>= 0.10'} raw-loader@4.0.2: resolution: {integrity: sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==} @@ -9825,13 +9587,13 @@ packages: peerDependencies: react: ^18.3.1 - react-dom@19.1.1: - resolution: {integrity: sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==} + react-dom@19.2.0: + resolution: {integrity: sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==} peerDependencies: - react: ^19.1.1 + react: ^19.2.0 - react-email@4.2.8: - resolution: {integrity: sha512-Eqzs/xZnS881oghPO/4CQ1cULyESuUhEjfYboXmYNOokXnJ6QP5GKKJZ6zjkg9SnKXxSrIxSo5PxzCI5jReJMA==} + react-email@4.3.0: + resolution: {integrity: sha512-XFHCSfhdlO7k5q2TYGwC0HsVh5Yn13YaOdahuJEUEOfOJKHEpSP4PKg7R/RiKFoK9cDvzunhY+58pXxz0vE2zA==} engines: {node: '>=18.0.0'} hasBin: true @@ -9857,24 +9619,9 @@ packages: react-loadable: '*' webpack: '>=4.41.1 || 5.x' - react-magic-dropzone@1.0.1: - resolution: {integrity: sha512-0BIROPARmXHpk4AS3eWBOsewxoM5ndk2psYP/JmbCq8tz3uR2LIV1XiroZ9PKrmDRMctpW+TvsBCtWasuS8vFA==} - react-promise-suspense@0.3.4: resolution: {integrity: sha512-I42jl7L3Ze6kZaq+7zXWSunBa3b1on5yfvUW6Eo/3fFOj6dZ5Bqmcd264nJbTK/gn1HjjILAjSwnZbV4RpSaNQ==} - react-redux@7.2.9: - resolution: {integrity: sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==} - peerDependencies: - react: ^16.8.3 || ^17 || ^18 - react-dom: '*' - react-native: '*' - peerDependenciesMeta: - react-dom: - optional: true - react-native: - optional: true - react-router-config@5.1.1: resolution: {integrity: sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==} peerDependencies: @@ -9895,8 +9642,8 @@ packages: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} - react@19.1.1: - resolution: {integrity: sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==} + react@19.2.0: + resolution: {integrity: sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==} engines: {node: '>=0.10.0'} read-cache@1.0.0: @@ -9924,15 +9671,13 @@ packages: resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} engines: {node: '>= 14.18.0'} - rechoir@0.6.2: - resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} - engines: {node: '>= 0.10'} - recma-build-jsx@1.0.0: resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==} - recma-jsx@1.0.0: - resolution: {integrity: sha512-5vwkv65qWwYxg+Atz95acp8DMu1JDSqdGkA2Of1j6rCreyFUE/gp15fC8MnGEuG1W68UKjM6x6+YTWIh7hZM/Q==} + recma-jsx@1.0.1: + resolution: {integrity: sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 recma-parse@1.0.0: resolution: {integrity: sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==} @@ -9952,29 +9697,9 @@ packages: resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} engines: {node: '>=4'} - redux-devtools-extension@2.13.9: - resolution: {integrity: sha512-cNJ8Q/EtjhQaZ71c8I9+BPySIBVEKssbPpskBfsXqb8HJ002A3KRVHfeRzwRo6mGPqsm7XuHTqNSNeS1Khig0A==} - deprecated: Package moved to @redux-devtools/extension. - peerDependencies: - redux: ^3.1.0 || ^4.0.0 - - redux-thunk@2.4.2: - resolution: {integrity: sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==} - peerDependencies: - redux: ^4 - - redux@4.2.1: - resolution: {integrity: sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==} - reflect-metadata@0.2.2: resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} - refractor@4.9.0: - resolution: {integrity: sha512-nEG1SPXFoGGx+dcjftjv8cAjEusIh6ED1xhf5DG3C0x/k+rmZ2duKnc3QLpt6qeHv5fPb8uwN3VWN2BT7fr3Og==} - - reftools@1.1.9: - resolution: {integrity: sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w==} - regenerate-unicode-properties@10.2.0: resolution: {integrity: sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==} engines: {node: '>=4'} @@ -10031,8 +9756,8 @@ packages: remark-gfm@4.0.1: resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==} - remark-mdx@3.1.0: - resolution: {integrity: sha512-Ngl/H3YXyBV9RcRNdlYsZujAmhsxwzxpDzpDEhFBVAGthS4GDgnctpDjgFl/ULx5UEDzqtW1cyBSNKqYYrqLBA==} + remark-mdx@3.1.1: + resolution: {integrity: sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==} remark-parse@11.0.0: resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} @@ -10058,9 +9783,9 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - require-in-the-middle@7.5.2: - resolution: {integrity: sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==} - engines: {node: '>=8.6.0'} + require-in-the-middle@8.0.0: + resolution: {integrity: sha512-9s0pnM5tH8G4dSI3pms2GboYOs25LwOGnRMxN/Hx3TYT1K0rh6OjaWf4dI0DAQnMyaEXWoGVnSTPQasqwzTTAA==} + engines: {node: '>=9.3.0 || >=8.10.0 <9.0.0'} require-like@0.1.2: resolution: {integrity: sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==} @@ -10071,9 +9796,6 @@ packages: requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} - reselect@4.1.8: - resolution: {integrity: sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==} - resolve-alpn@1.2.1: resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} @@ -10129,16 +9851,11 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true - rimraf@6.0.1: - resolution: {integrity: sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==} - engines: {node: 20 || >=22} - hasBin: true - robust-predicates@3.0.2: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} - rollup-plugin-visualizer@6.0.3: - resolution: {integrity: sha512-ZU41GwrkDcCpVoffviuM9Clwjy5fcUxlz0oMoTXTYsK+tcIFzbdacnrr2n8TXcHxbGKKXtOdjxM2HUS4HjkwIw==} + rollup-plugin-visualizer@6.0.4: + resolution: {integrity: sha512-q8Q7J/6YofkmaGW1sH/fPRAz37x/+pd7VBuaUU7lwvOS/YikuiiEU9jeb9PH8XHiq50XFrUsBbOxeAMYQ7KZkg==} engines: {node: '>=18'} hasBin: true peerDependencies: @@ -10150,8 +9867,8 @@ packages: rollup: optional: true - rollup@4.46.3: - resolution: {integrity: sha512-RZn2XTjXb8t5g13f5YclGoilU/kwT696DIkY3sywjdZidNSi3+vseaQov7D7BZXVJCPv3pDWUN69C78GGbXsKw==} + rollup@4.52.4: + resolution: {integrity: sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -10167,6 +9884,10 @@ packages: engines: {node: '>=12.0.0'} hasBin: true + run-applescript@7.1.0: + resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==} + engines: {node: '>=18'} + run-async@2.4.1: resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} engines: {node: '>=0.12.0'} @@ -10217,8 +9938,8 @@ packages: scheduler@0.23.2: resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} - scheduler@0.26.0: - resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} schema-dts@1.1.5: resolution: {integrity: sha512-RJr9EaCmsLzBX2NDiO5Z3ux2BVosNZN5jo0gWgsyKvxKIUL5R3swNvoorulAeL9kLB0iTSX7V6aokhla2m7xbg==} @@ -10227,8 +9948,8 @@ packages: resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} engines: {node: '>= 10.13.0'} - schema-utils@4.3.2: - resolution: {integrity: sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==} + schema-utils@4.3.3: + resolution: {integrity: sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==} engines: {node: '>= 10.13.0'} search-insights@2.17.3: @@ -10256,13 +9977,8 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.6.3: - resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} - engines: {node: '>=10'} - hasBin: true - - semver@7.7.2: - resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} engines: {node: '>=10'} hasBin: true @@ -10308,10 +10024,6 @@ packages: setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - sha.js@2.4.11: - resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} - hasBin: true - shallow-clone@3.0.1: resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} engines: {node: '>=8'} @@ -10323,8 +10035,8 @@ packages: resolution: {integrity: sha512-rLGSWeK2ufzCVx05wYd+xrWnOOdSV7xNUW5/XFgx3Bc02hBkpMlrd2F1dDII7/jhWzv0MSyBFh5uJIy9hLdfuw==} hasBin: true - sharp@0.34.3: - resolution: {integrity: sha512-eX2IQ6nFohW4DbvHIOLRB3MHFpYqaqvXd3Tp5e/T/dSH83fxaNJQRvDMhASmkNTsNTVF2/OOopzRCt7xokgPfg==} + sharp@0.34.4: + resolution: {integrity: sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} shebang-command@2.0.0: @@ -10339,29 +10051,6 @@ packages: resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==} engines: {node: '>= 0.4'} - shelljs@0.8.5: - resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} - engines: {node: '>=4'} - hasBin: true - - should-equal@2.0.0: - resolution: {integrity: sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==} - - should-format@3.0.3: - resolution: {integrity: sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==} - - should-type-adaptors@1.1.0: - resolution: {integrity: sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==} - - should-type@1.4.0: - resolution: {integrity: sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==} - - should-util@1.0.1: - resolution: {integrity: sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==} - - should@13.2.3: - resolution: {integrity: sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==} - side-channel-list@1.0.0: resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} engines: {node: '>= 0.4'} @@ -10394,15 +10083,16 @@ packages: simple-get@3.1.1: resolution: {integrity: sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==} - simple-swizzle@0.2.2: - resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + simple-icons@15.16.1: + resolution: {integrity: sha512-UpT6dslPDUfl+9xAjxHAh4ralefkrAqBe8o4cN+HtBOa2HjYZnEAiQsUkAdkaMfW05rU/rc/MWaKxF/cpUllCg==} + engines: {node: '>=0.12.18'} sirv@2.0.4: resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} engines: {node: '>= 10'} - sirv@3.0.1: - resolution: {integrity: sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==} + sirv@3.0.2: + resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==} engines: {node: '>=18'} sisteransi@1.0.5: @@ -10480,6 +10170,10 @@ packages: resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} engines: {node: '>= 8'} + source-map@0.7.6: + resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} + engines: {node: '>= 12'} + space-separated-tokens@1.1.5: resolution: {integrity: sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==} @@ -10503,14 +10197,10 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - sql-formatter@15.6.6: - resolution: {integrity: sha512-bZydXEXhaNDQBr8xYHC3a8thwcaMuTBp0CkKGjwGYDsIB26tnlWeWPwJtSQ0TEwiJcz9iJJON5mFPkx7XroHcg==} + sql-formatter@15.6.10: + resolution: {integrity: sha512-0bJOPQrRO/JkjQhiThVayq0hOKnI1tHI+2OTkmT7TGtc6kqS+V7kveeMzRW+RNQGxofmTmet9ILvztyuxv0cJQ==} hasBin: true - sql-highlight@6.1.0: - resolution: {integrity: sha512-ed7OK4e9ywpE7pgRMkMQmZDPKSVdm0oX5IEtZiKnFucSF0zu6c80GZBe38UqHuVhTWJ9xsKgSMjCG2bml86KvA==} - engines: {node: '>=14'} - srcset@4.0.0: resolution: {integrity: sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw==} engines: {node: '>=12'} @@ -10518,8 +10208,8 @@ packages: ssh-remote-port-forward@1.0.4: resolution: {integrity: sha512-x0LV1eVDwjf1gmG7TTnfqIzf+3VPRz7vrNIjX6oYLbeCrf/PeVY6hkT68Mg+q02qXxQhrLjB0jfgvhevoCRmLQ==} - ssh2@1.16.0: - resolution: {integrity: sha512-r1X4KsBGedJqo7h8F5c4Ybpcr5RjyP+aWIG007uBPRjmdQWfEiVLzSK71Zji1B9sKxwaCvD8y8cwSkYrlLiRRg==} + ssh2@1.17.0: + resolution: {integrity: sha512-wPldCk3asibAjQ/kziWQQt1Wh3PgDFpC0XpwclzKcdT1vql6KeYxf5LIt4nlFkUeR8WuphYMKqUA56X4rjbfgQ==} engines: {node: '>=10.16.0'} ssri@12.0.0: @@ -10532,9 +10222,6 @@ packages: standard-as-callback@2.1.0: resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} - state-local@1.0.7: - resolution: {integrity: sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==} - statuses@1.5.0: resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} engines: {node: '>= 0.6'} @@ -10561,8 +10248,8 @@ packages: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} engines: {node: '>=10.0.0'} - streamx@2.22.1: - resolution: {integrity: sha512-znKXEBxfatz2GBNK02kRnCXjV+AA4kjZIUxeWSr3UGirZMJfTE9uiwKHobnbgxWyL/JWro8tTq+vOqAK1/qbSA==} + streamx@2.23.0: + resolution: {integrity: sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==} string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} @@ -10593,8 +10280,8 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} - strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + strip-ansi@7.1.2: + resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} engines: {node: '>=12'} strip-bom-string@1.0.0: @@ -10628,8 +10315,8 @@ packages: strip-literal@3.0.0: resolution: {integrity: sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==} - striptags@3.2.0: - resolution: {integrity: sha512-g45ZOGzHDMe2bdYMdIvdAfCQkCTDMGBazSw1ypMowwGIee7ZQ5dU0rBJ8Jqgl+jAKIv4dbeE1jscZq9wid1Tkw==} + strnum@2.1.1: + resolution: {integrity: sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==} strtok3@10.3.4: resolution: {integrity: sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==} @@ -10656,11 +10343,6 @@ packages: resolution: {integrity: sha512-y/hkYGeXAj7wUMjxRbB21g/l6aAEituGXM9Rwl4o20+SX3e8YOSV6BxFXl+dL3Uk0mjSL3kCbNkwURm8/gEDig==} engines: {node: '>=14.18.0'} - superagent@7.1.6: - resolution: {integrity: sha512-gZkVCQR1gy/oUXr+kxJMLDjla434KmSOKbx5iGD30Ql+AkJQ/YlPKECJy2nhqOsHLjGHzoDTXNSjhnvWhzKk7g==} - engines: {node: '>=6.4.0 <13 || >=14'} - deprecated: Please upgrade to superagent v10.2.2+, see release notes at https://github.com/forwardemail/superagent/releases/tag/v10.2.2 - maintenance is supported by Forward Email @ https://forwardemail.net - supercluster@7.1.5: resolution: {integrity: sha512-EulshI3pGUM66o6ZdH3ReiFcvHpM3vAigyK+vcxdjpJyEbIIrtbmBdY23mGgnI24uXiGFvrGq9Gkum/8U7vJWg==} @@ -10683,16 +10365,16 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - svelte-check@4.3.1: - resolution: {integrity: sha512-lkh8gff5gpHLjxIV+IaApMxQhTGnir2pNUAqcNgeKkvK5bT/30Ey/nzBxNLDlkztCH4dP7PixkMt9SWEKFPBWg==} + svelte-check@4.3.3: + resolution: {integrity: sha512-RYP0bEwenDXzfv0P1sKAwjZSlaRyqBn0Fz1TVni58lqyEiqgwztTpmodJrGzP6ZT2aHl4MbTvWP6gbmQ3FOnBg==} engines: {node: '>= 18.0.0'} hasBin: true peerDependencies: svelte: ^4.0.0 || ^5.0.0-next.0 typescript: '>=5.0.0' - svelte-eslint-parser@1.3.1: - resolution: {integrity: sha512-0Iztj5vcOVOVkhy1pbo5uA9r+d3yaVoE5XPc9eABIWDOSJZ2mOsZ4D+t45rphWCOr0uMw3jtSG2fh2e7GvKnPg==} + svelte-eslint-parser@1.3.3: + resolution: {integrity: sha512-oTrDR8Z7Wnguut7QH3YKh7JR19xv1seB/bz4dxU5J/86eJtZOU4eh0/jZq4dy6tAlz/KROxnkRQspv5ZEt7t+Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: svelte: ^3.37.0 || ^4.0.0 || ^5.0.0 @@ -10700,8 +10382,11 @@ packages: svelte: optional: true - svelte-gestures@5.1.4: - resolution: {integrity: sha512-gfSO/GqWLu9nRMCz12jqdyA0+NTsojYcIBcRqZjwWrpQbqMXr0zWPFpZBtzfYbRHtuFxZImMZp9MrVaFCYbhDg==} + svelte-gestures@5.2.2: + resolution: {integrity: sha512-Y+chXPaSx8OsPoFppUwPk8PJzgrZ7xoDJKXeiEc7JBqyKKzXer9hlf8F9O34eFuAWB4/WQEvccACvyBplESL7A==} + + svelte-highlight@7.8.4: + resolution: {integrity: sha512-aVp+Q0hH9kI7PlSDrklmFTF4Uj7wYj7UGuqkREnkXlqpEffxr2g6esZcMMaTgECdg5rb2mJqM88+nwS10ecoTg==} svelte-i18n@4.0.1: resolution: {integrity: sha512-jaykGlGT5PUaaq04JWbJREvivlCnALtT+m87Kbm0fxyYHynkQaxQMnIKHLm2WeIuBRoljzwgyvz0Z6/CMwfdmQ==} @@ -10710,8 +10395,8 @@ packages: peerDependencies: svelte: ^3 || ^4 || ^5 - svelte-maplibre@1.2.0: - resolution: {integrity: sha512-JKYzL0glnqCJ7LwkdDAMb3jdZdFl8ZDHEZyc043BV624kG9ZVaXlIPgjb8sNktqx1D0rQBNrYNt5rR4XszNCiQ==} + svelte-maplibre@1.2.1: + resolution: {integrity: sha512-IVkbc54hQXznyaiFN69RIdjqbLHriNYPVEo1DQMtWSm1kLovrt/aZuhV4eOoZKn6wIvY2Vz34jXPS33f/d/GNw==} peerDependencies: '@deck.gl/core': ^9 '@deck.gl/layers': ^9 @@ -10742,8 +10427,8 @@ packages: peerDependencies: svelte: ^5.30.2 - svelte@5.35.5: - resolution: {integrity: sha512-KuRvI82rhh0RMz1EKsUJD96gZyHJ+h2+8zrwO8iqE/p/CmcNKvIItDUAeUePhuCDgtegDJmF8IKThbHIfmTgTA==} + svelte@5.39.11: + resolution: {integrity: sha512-8MxWVm2+3YwrFbPaxOlT1bbMi6OTenrAgks6soZfiaS8Fptk4EVyRIFhJc3RpO264EeSNwgjWAdki0ufg4zkGw==} engines: {node: '>=18'} svg-parser@2.0.4: @@ -10757,10 +10442,6 @@ packages: swagger-ui-dist@5.21.0: resolution: {integrity: sha512-E0K3AB6HvQd8yQNSMR7eE5bk+323AUxjtCz/4ZNKiahOlPhPJxqn3UPIGs00cyY/dhrTDJ61L7C/a8u6zhGrZg==} - swagger2openapi@7.0.8: - resolution: {integrity: sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g==} - hasBin: true - symbol-observable@4.0.0: resolution: {integrity: sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==} engines: {node: '>=0.10'} @@ -10784,8 +10465,8 @@ packages: tailwind-merge@3.3.1: resolution: {integrity: sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==} - tailwind-variants@2.1.0: - resolution: {integrity: sha512-82m0eRex0z6A3GpvfoTCpHr+wWJmbecfVZfP3mqLoDxeya5tN4mYJQZwa5Aw1hRZTedwpu1D2JizYenoEdyD8w==} + tailwind-variants@3.1.1: + resolution: {integrity: sha512-ftLXe3krnqkMHsuBTEmaVUXYovXtPyTK7ckEfDRXS8PBZx0bAUas+A0jYxuKA5b8qg++wvQ3d2MQ7l/xeZxbZQ==} engines: {node: '>=16.x', pnpm: '>=7.x'} peerDependencies: tailwind-merge: '>=3.0.0' @@ -10811,23 +10492,23 @@ packages: peerDependencies: tailwindcss: '>=3.4.17' - tailwindcss@3.4.17: - resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==} + tailwindcss@3.4.18: + resolution: {integrity: sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ==} engines: {node: '>=14.0.0'} hasBin: true - tailwindcss@4.1.12: - resolution: {integrity: sha512-DzFtxOi+7NsFf7DBtI3BJsynR+0Yp6etH+nRPTbpWnS2pZBaSksv/JGctNwSWzbFjp0vxSqknaUylseZqMDGrA==} + tailwindcss@4.1.14: + resolution: {integrity: sha512-b7pCxjGO98LnxVkKjaZSDeNuljC4ueKUddjENJOADtubtdo8llTaJy7HwBMeLNSSo2N5QIAgklslK1+Ir8r6CA==} - tapable@2.2.2: - resolution: {integrity: sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==} + tapable@2.3.0: + resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} engines: {node: '>=6'} - tar-fs@2.1.3: - resolution: {integrity: sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==} + tar-fs@2.1.4: + resolution: {integrity: sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==} - tar-fs@3.1.0: - resolution: {integrity: sha512-5Mty5y/sOF1YWj1J6GiBodjlDc05CUR8PKXrsnFAiSG0xA+GHeWLovaZPYUDXkH/1iKRf2+M5+OrRgzC7O9b7w==} + tar-fs@3.1.1: + resolution: {integrity: sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==} tar-stream@2.2.0: resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} @@ -10840,8 +10521,8 @@ packages: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} - tar@7.4.3: - resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==} + tar@7.5.1: + resolution: {integrity: sha512-nlGpxf+hv0v7GkWBK2V9spgactGOp0qvfWRxUMjqHyzrt3SgwE48DIv/FhqPHJYLHpgW1opq3nERbz5Anq7n1g==} engines: {node: '>=18'} terser-webpack-plugin@5.3.14: @@ -10869,8 +10550,8 @@ packages: resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} engines: {node: '>=18'} - testcontainers@11.5.1: - resolution: {integrity: sha512-YSSP4lSJB8498zTeu4HYTZYgSky54ozBmIDdC8PFU5inj+vBo5hPpilhcYTgmsqsYjrXOJGV7jl0MWByS7GwuA==} + testcontainers@11.7.1: + resolution: {integrity: sha512-fjut+07G4Avp6Lly/6hQePpUpQFv9ZyQd+7JC5iCDKg+dWa2Sw7fXD3pBrkzslYFfKqGx9M6kyIaLpg9VeMsjw==} text-decoder@1.2.3: resolution: {integrity: sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==} @@ -10886,12 +10567,18 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - three@0.175.0: - resolution: {integrity: sha512-nNE3pnTHxXN/Phw768u0Grr7W4+rumGg/H6PgeseNJojkJtmeHJfZWi41Gp2mpXl1pg1pf1zjwR4McM1jTqkpg==} + thingies@2.5.0: + resolution: {integrity: sha512-s+2Bwztg6PhWUD7XMfeYm5qliDdSiZm7M7n8KjTkIsm3l/2lgVRc2/Gx/v+ZX8lT4FMA+i8aQvhcWylldc+ZNw==} + engines: {node: '>=10.18'} + peerDependencies: + tslib: ^2 three@0.179.1: resolution: {integrity: sha512-5y/elSIQbrvKOISxpwXCR4sQqHtGiOI+MKLc3SsBdDXA2hz3Mdp3X59aUp8DyybMa34aeBwbFTpdoLJaUDEWSw==} + three@0.180.0: + resolution: {integrity: sha512-o+qycAMZrh+TsE01GqWUxUIKR1AL0S8pq7zDkYOQw8GqfX8b8VoCKYUoHbhiX5j+7hr8XsuHDVU6+gkQJQKg9w==} + through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} @@ -10920,8 +10607,8 @@ packages: tinyexec@0.3.2: resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} - tinyglobby@0.2.14: - resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} tinypool@1.1.1: @@ -10949,10 +10636,6 @@ packages: resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} hasBin: true - tmp@0.0.33: - resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} - engines: {node: '>=0.6.0'} - tmp@0.2.5: resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} engines: {node: '>=14.14'} @@ -10995,6 +10678,12 @@ packages: resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} engines: {node: '>=18'} + tree-dump@1.1.0: + resolution: {integrity: sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true @@ -11081,67 +10770,8 @@ packages: typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - typeorm@0.3.25: - resolution: {integrity: sha512-fTKDFzWXKwAaBdEMU4k661seZewbNYET4r1J/z3Jwf+eAvlzMVpTLKAVcAzg75WwQk7GDmtsmkZ5MfkmXCiFWg==} - engines: {node: '>=16.13.0'} - hasBin: true - peerDependencies: - '@google-cloud/spanner': ^5.18.0 || ^6.0.0 || ^7.0.0 - '@sap/hana-client': ^2.12.25 - better-sqlite3: ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 - hdb-pool: ^0.1.6 - ioredis: ^5.0.4 - mongodb: ^5.8.0 || ^6.0.0 - mssql: ^9.1.1 || ^10.0.1 || ^11.0.1 - mysql2: ^2.2.5 || ^3.0.1 - oracledb: ^6.3.0 - pg: ^8.5.1 - pg-native: ^3.0.0 - pg-query-stream: ^4.0.0 - redis: ^3.1.1 || ^4.0.0 - reflect-metadata: ^0.1.14 || ^0.2.0 - sql.js: ^1.4.0 - sqlite3: ^5.0.3 - ts-node: ^10.7.0 - typeorm-aurora-data-api-driver: ^2.0.0 || ^3.0.0 - peerDependenciesMeta: - '@google-cloud/spanner': - optional: true - '@sap/hana-client': - optional: true - better-sqlite3: - optional: true - hdb-pool: - optional: true - ioredis: - optional: true - mongodb: - optional: true - mssql: - optional: true - mysql2: - optional: true - oracledb: - optional: true - pg: - optional: true - pg-native: - optional: true - pg-query-stream: - optional: true - redis: - optional: true - sql.js: - optional: true - sqlite3: - optional: true - ts-node: - optional: true - typeorm-aurora-data-api-driver: - optional: true - - typescript-eslint@8.39.1: - resolution: {integrity: sha512-GDUv6/NDYngUlNvwaHM1RamYftxf782IyEDbdj3SeaIHHv8fNQVRC++fITT7kUJV/5rIA/tkoRSSskt6osEfqg==} + typescript-eslint@8.46.0: + resolution: {integrity: sha512-6+ZrB6y2bT2DX3K+Qd9vn7OFOJR+xSLDj+Aw/N3zBwUt27uTw2sw2TE2+UcY1RiyBZkaGbTkVg9SSdPNUG6aUw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -11152,16 +10782,16 @@ packages: engines: {node: '>=14.17'} hasBin: true - typescript@5.9.2: - resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==} + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} hasBin: true ua-is-frozen@0.1.2: resolution: {integrity: sha512-RwKDW2p3iyWn4UbaxpP2+VxwqXh0jpvdxsYpZ5j/MLLiQOfbsV5shpgQiw93+KMYQPcteeMQ289MaAFzs3G9pw==} - ua-parser-js@2.0.4: - resolution: {integrity: sha512-XiBOnM/UpUq21ZZ91q2AVDOnGROE6UQd37WrO9WBgw4u2eGvUCNOheMmZ3EfEUj7DLHr8tre+Um/436Of/Vwzg==} + ua-parser-js@2.0.5: + resolution: {integrity: sha512-sZErtx3rhpvZQanWW5umau4o/snfoLqRcQwQIZ54377WtRzIecnIKvjpkd5JwPcSUMglGnbIgcsQBGAbdi3S9Q==} hasBin: true uglify-js@3.19.3: @@ -11187,11 +10817,11 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - undici-types@7.10.0: - resolution: {integrity: sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==} + undici-types@7.14.0: + resolution: {integrity: sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==} - undici@7.14.0: - resolution: {integrity: sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==} + undici@7.16.0: + resolution: {integrity: sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==} engines: {node: '>=20.18.1'} unicode-canonical-property-names-ecmascript@2.0.1: @@ -11277,13 +10907,13 @@ packages: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} - unplugin-swc@1.5.5: - resolution: {integrity: sha512-BahYtYvQ/KSgOqHoy5FfQgp/oZNAB7jwERxNeFVeN/PtJhg4fpK/ybj9OwKtqGPseOadS7+TGbq6tH2DmDAYvA==} + unplugin-swc@1.5.7: + resolution: {integrity: sha512-Ng4uuLAodZToA0kQk3+oY8b0C/Q9oV0ohRMixH2nqWMhCF/wNuMYZXZznYpwRLmF7wC36TFIOywBAxCLOReoeg==} peerDependencies: '@swc/core': ^1.2.108 - unplugin@2.3.5: - resolution: {integrity: sha512-RyWSb5AHmGtjjNQ6gIlA67sHOsWpsbWpwDokLwTcejVdOjEkJZh7QKu14J00gDDVSh8kGH4KYC/TNBceXFZhtw==} + unplugin@2.3.10: + resolution: {integrity: sha512-6NCPkv1ClwH+/BGE9QeoTIl09nuiAt0gS28nn1PvYXsGKRwM2TCbFA2QiilmehPDTXIe684k4rZI1yl3A1PCUw==} engines: {node: '>=18.12.0'} update-browserslist-db@1.1.3: @@ -11322,9 +10952,6 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - util@0.10.4: - resolution: {integrity: sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==} - utila@0.4.0: resolution: {integrity: sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==} @@ -11352,25 +10979,6 @@ packages: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true - uuid@9.0.1: - resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} - hasBin: true - - validate.io-array@1.0.6: - resolution: {integrity: sha512-DeOy7CnPEziggrOO5CZhVKJw6S3Yi7e9e65R1Nl/RTN1vTQKnzjfvks0/8kQ40FP/dsjRAOd4hxmJ7uLa6vxkg==} - - validate.io-function@1.0.2: - resolution: {integrity: sha512-LlFybRJEriSuBnUhQyG5bwglhh50EpTL2ul23MPIuR1odjO7XaMLFV8vHGwp7AZciFxtYOeiSCT5st+XSPONiQ==} - - validate.io-integer-array@1.0.0: - resolution: {integrity: sha512-mTrMk/1ytQHtCY0oNO3dztafHYyGU88KL+jRxWuzfOmQb+4qqnWmI+gykvGp8usKZOM0H7keJHEbRaFiYA0VrA==} - - validate.io-integer@1.0.5: - resolution: {integrity: sha512-22izsYSLojN/P6bppBqhgUDjCkr5RY2jd+N2a3DCAUey8ydvrZ/OkGvFPR7qfOpwR2LC5p4Ngzxz36g5Vgr/hQ==} - - validate.io-number@1.0.3: - resolution: {integrity: sha512-kRAyotcbNaSYoDnXvb4MHg/0a1egJdLwS6oJ38TJY7aw9n93Fl/3blIXdyYvPOp55CNxywooG/3BcrwNrBpcSg==} - validator@13.15.15: resolution: {integrity: sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==} engines: {node: '>= 0.10'} @@ -11391,8 +10999,8 @@ packages: vfile-message@2.0.4: resolution: {integrity: sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==} - vfile-message@4.0.2: - resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} + vfile-message@4.0.3: + resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} vfile@4.2.1: resolution: {integrity: sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==} @@ -11417,8 +11025,8 @@ packages: vite: optional: true - vite@7.1.2: - resolution: {integrity: sha512-J0SQBPlQiEXAF7tajiH+rUooJPo0l8KQgyg4/aMunNtrOa7bwuZJsJbDWzeljqQpgftxuq5yNJxQ91O9ts29UQ==} + vite@7.1.9: + resolution: {integrity: sha512-4nVGliEpxmhCL8DslSAUdxlB6+SMrhB0a1v5ijlh1xB1nEPuy1mxaHxysVucLHuWryAxLWg6a5ei+U4TLn/rFg==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -11538,18 +11146,21 @@ packages: engines: {node: '>= 10.13.0'} hasBin: true - webpack-dev-middleware@5.3.4: - resolution: {integrity: sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==} - engines: {node: '>= 12.13.0'} + webpack-dev-middleware@7.4.5: + resolution: {integrity: sha512-uxQ6YqGdE4hgDKNf7hUiPXOdtkXvBJXrfEGYSx7P7LC8hnUYGK70X6xQXUvXeNyBDDcsiQXpG2m3G9vxowaEuA==} + engines: {node: '>= 18.12.0'} peerDependencies: - webpack: ^4.0.0 || ^5.0.0 + webpack: ^5.0.0 + peerDependenciesMeta: + webpack: + optional: true - webpack-dev-server@4.15.2: - resolution: {integrity: sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==} - engines: {node: '>= 12.13.0'} + webpack-dev-server@5.2.2: + resolution: {integrity: sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg==} + engines: {node: '>= 18.12.0'} hasBin: true peerDependencies: - webpack: ^4.37.0 || ^5.0.0 + webpack: ^5.0.0 webpack-cli: '*' peerDependenciesMeta: webpack: @@ -11586,6 +11197,16 @@ packages: webpack-cli: optional: true + webpack@5.102.1: + resolution: {integrity: sha512-7h/weGm9d/ywQ6qzJ+Xy+r9n/3qgp/thalBbpOi5i223dPXKi04IBtqPN9nTd+jBc7QKfvDbaBnFipYp4sJAUQ==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + webpackbar@6.0.1: resolution: {integrity: sha512-TnErZpmuKdwWBdMoexjio3KKX6ZtoKHRVvLIU0A47R0VVBDtx3ZyOJDktgYixhoJokZTYTt1Z37OkO9pnGJa9Q==} engines: {node: '>=14.21.3'} @@ -11720,6 +11341,10 @@ packages: utf-8-validate: optional: true + wsl-utils@0.1.0: + resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==} + engines: {node: '>=18'} + xdg-basedir@5.1.0: resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==} engines: {node: '>=12'} @@ -11801,12 +11426,12 @@ packages: resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==} engines: {node: '>=18'} - yoctocolors@2.1.1: - resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==} + yoctocolors@2.1.2: + resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} engines: {node: '>=18'} - zimmerframe@1.1.2: - resolution: {integrity: sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==} + zimmerframe@1.1.4: + resolution: {integrity: sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==} zip-stream@6.0.1: resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==} @@ -11822,119 +11447,126 @@ snapshots: '@adobe/css-tools@4.4.4': {} - '@algolia/autocomplete-core@1.17.9(@algolia/client-search@5.29.0)(algoliasearch@5.29.0)(search-insights@2.17.3)': + '@algolia/abtesting@1.6.0': dependencies: - '@algolia/autocomplete-plugin-algolia-insights': 1.17.9(@algolia/client-search@5.29.0)(algoliasearch@5.29.0)(search-insights@2.17.3) - '@algolia/autocomplete-shared': 1.17.9(@algolia/client-search@5.29.0)(algoliasearch@5.29.0) + '@algolia/client-common': 5.40.0 + '@algolia/requester-browser-xhr': 5.40.0 + '@algolia/requester-fetch': 5.40.0 + '@algolia/requester-node-http': 5.40.0 + + '@algolia/autocomplete-core@1.17.9(@algolia/client-search@5.40.0)(algoliasearch@5.40.0)(search-insights@2.17.3)': + dependencies: + '@algolia/autocomplete-plugin-algolia-insights': 1.17.9(@algolia/client-search@5.40.0)(algoliasearch@5.40.0)(search-insights@2.17.3) + '@algolia/autocomplete-shared': 1.17.9(@algolia/client-search@5.40.0)(algoliasearch@5.40.0) transitivePeerDependencies: - '@algolia/client-search' - algoliasearch - search-insights - '@algolia/autocomplete-plugin-algolia-insights@1.17.9(@algolia/client-search@5.29.0)(algoliasearch@5.29.0)(search-insights@2.17.3)': + '@algolia/autocomplete-plugin-algolia-insights@1.17.9(@algolia/client-search@5.40.0)(algoliasearch@5.40.0)(search-insights@2.17.3)': dependencies: - '@algolia/autocomplete-shared': 1.17.9(@algolia/client-search@5.29.0)(algoliasearch@5.29.0) + '@algolia/autocomplete-shared': 1.17.9(@algolia/client-search@5.40.0)(algoliasearch@5.40.0) search-insights: 2.17.3 transitivePeerDependencies: - '@algolia/client-search' - algoliasearch - '@algolia/autocomplete-preset-algolia@1.17.9(@algolia/client-search@5.29.0)(algoliasearch@5.29.0)': + '@algolia/autocomplete-preset-algolia@1.17.9(@algolia/client-search@5.40.0)(algoliasearch@5.40.0)': dependencies: - '@algolia/autocomplete-shared': 1.17.9(@algolia/client-search@5.29.0)(algoliasearch@5.29.0) - '@algolia/client-search': 5.29.0 - algoliasearch: 5.29.0 + '@algolia/autocomplete-shared': 1.17.9(@algolia/client-search@5.40.0)(algoliasearch@5.40.0) + '@algolia/client-search': 5.40.0 + algoliasearch: 5.40.0 - '@algolia/autocomplete-shared@1.17.9(@algolia/client-search@5.29.0)(algoliasearch@5.29.0)': + '@algolia/autocomplete-shared@1.17.9(@algolia/client-search@5.40.0)(algoliasearch@5.40.0)': dependencies: - '@algolia/client-search': 5.29.0 - algoliasearch: 5.29.0 + '@algolia/client-search': 5.40.0 + algoliasearch: 5.40.0 - '@algolia/client-abtesting@5.29.0': + '@algolia/client-abtesting@5.40.0': dependencies: - '@algolia/client-common': 5.29.0 - '@algolia/requester-browser-xhr': 5.29.0 - '@algolia/requester-fetch': 5.29.0 - '@algolia/requester-node-http': 5.29.0 + '@algolia/client-common': 5.40.0 + '@algolia/requester-browser-xhr': 5.40.0 + '@algolia/requester-fetch': 5.40.0 + '@algolia/requester-node-http': 5.40.0 - '@algolia/client-analytics@5.29.0': + '@algolia/client-analytics@5.40.0': dependencies: - '@algolia/client-common': 5.29.0 - '@algolia/requester-browser-xhr': 5.29.0 - '@algolia/requester-fetch': 5.29.0 - '@algolia/requester-node-http': 5.29.0 + '@algolia/client-common': 5.40.0 + '@algolia/requester-browser-xhr': 5.40.0 + '@algolia/requester-fetch': 5.40.0 + '@algolia/requester-node-http': 5.40.0 - '@algolia/client-common@5.29.0': {} + '@algolia/client-common@5.40.0': {} - '@algolia/client-insights@5.29.0': + '@algolia/client-insights@5.40.0': dependencies: - '@algolia/client-common': 5.29.0 - '@algolia/requester-browser-xhr': 5.29.0 - '@algolia/requester-fetch': 5.29.0 - '@algolia/requester-node-http': 5.29.0 + '@algolia/client-common': 5.40.0 + '@algolia/requester-browser-xhr': 5.40.0 + '@algolia/requester-fetch': 5.40.0 + '@algolia/requester-node-http': 5.40.0 - '@algolia/client-personalization@5.29.0': + '@algolia/client-personalization@5.40.0': dependencies: - '@algolia/client-common': 5.29.0 - '@algolia/requester-browser-xhr': 5.29.0 - '@algolia/requester-fetch': 5.29.0 - '@algolia/requester-node-http': 5.29.0 + '@algolia/client-common': 5.40.0 + '@algolia/requester-browser-xhr': 5.40.0 + '@algolia/requester-fetch': 5.40.0 + '@algolia/requester-node-http': 5.40.0 - '@algolia/client-query-suggestions@5.29.0': + '@algolia/client-query-suggestions@5.40.0': dependencies: - '@algolia/client-common': 5.29.0 - '@algolia/requester-browser-xhr': 5.29.0 - '@algolia/requester-fetch': 5.29.0 - '@algolia/requester-node-http': 5.29.0 + '@algolia/client-common': 5.40.0 + '@algolia/requester-browser-xhr': 5.40.0 + '@algolia/requester-fetch': 5.40.0 + '@algolia/requester-node-http': 5.40.0 - '@algolia/client-search@5.29.0': + '@algolia/client-search@5.40.0': dependencies: - '@algolia/client-common': 5.29.0 - '@algolia/requester-browser-xhr': 5.29.0 - '@algolia/requester-fetch': 5.29.0 - '@algolia/requester-node-http': 5.29.0 + '@algolia/client-common': 5.40.0 + '@algolia/requester-browser-xhr': 5.40.0 + '@algolia/requester-fetch': 5.40.0 + '@algolia/requester-node-http': 5.40.0 '@algolia/events@4.0.1': {} - '@algolia/ingestion@1.29.0': + '@algolia/ingestion@1.40.0': dependencies: - '@algolia/client-common': 5.29.0 - '@algolia/requester-browser-xhr': 5.29.0 - '@algolia/requester-fetch': 5.29.0 - '@algolia/requester-node-http': 5.29.0 + '@algolia/client-common': 5.40.0 + '@algolia/requester-browser-xhr': 5.40.0 + '@algolia/requester-fetch': 5.40.0 + '@algolia/requester-node-http': 5.40.0 - '@algolia/monitoring@1.29.0': + '@algolia/monitoring@1.40.0': dependencies: - '@algolia/client-common': 5.29.0 - '@algolia/requester-browser-xhr': 5.29.0 - '@algolia/requester-fetch': 5.29.0 - '@algolia/requester-node-http': 5.29.0 + '@algolia/client-common': 5.40.0 + '@algolia/requester-browser-xhr': 5.40.0 + '@algolia/requester-fetch': 5.40.0 + '@algolia/requester-node-http': 5.40.0 - '@algolia/recommend@5.29.0': + '@algolia/recommend@5.40.0': dependencies: - '@algolia/client-common': 5.29.0 - '@algolia/requester-browser-xhr': 5.29.0 - '@algolia/requester-fetch': 5.29.0 - '@algolia/requester-node-http': 5.29.0 + '@algolia/client-common': 5.40.0 + '@algolia/requester-browser-xhr': 5.40.0 + '@algolia/requester-fetch': 5.40.0 + '@algolia/requester-node-http': 5.40.0 - '@algolia/requester-browser-xhr@5.29.0': + '@algolia/requester-browser-xhr@5.40.0': dependencies: - '@algolia/client-common': 5.29.0 + '@algolia/client-common': 5.40.0 - '@algolia/requester-fetch@5.29.0': + '@algolia/requester-fetch@5.40.0': dependencies: - '@algolia/client-common': 5.29.0 + '@algolia/client-common': 5.40.0 - '@algolia/requester-node-http@5.29.0': + '@algolia/requester-node-http@5.40.0': dependencies: - '@algolia/client-common': 5.29.0 + '@algolia/client-common': 5.40.0 '@alloc/quick-lru@5.2.0': {} '@ampproject/remapping@2.3.0': dependencies: '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.30 + '@jridgewell/trace-mapping': 0.3.31 '@angular-devkit/core@19.2.15(chokidar@4.0.3)': dependencies: @@ -11947,11 +11579,22 @@ snapshots: optionalDependencies: chokidar: 4.0.3 - '@angular-devkit/schematics-cli@19.2.15(@types/node@22.18.1)(chokidar@4.0.3)': + '@angular-devkit/core@19.2.17(chokidar@4.0.3)': + dependencies: + ajv: 8.17.1 + ajv-formats: 3.0.1(ajv@8.17.1) + jsonc-parser: 3.3.1 + picomatch: 4.0.2 + rxjs: 7.8.1 + source-map: 0.7.4 + optionalDependencies: + chokidar: 4.0.3 + + '@angular-devkit/schematics-cli@19.2.15(@types/node@22.18.10)(chokidar@4.0.3)': dependencies: '@angular-devkit/core': 19.2.15(chokidar@4.0.3) '@angular-devkit/schematics': 19.2.15(chokidar@4.0.3) - '@inquirer/prompts': 7.3.2(@types/node@22.18.1) + '@inquirer/prompts': 7.3.2(@types/node@22.18.10) ansi-colors: 4.1.3 symbol-observable: 4.0.0 yargs-parser: 21.1.1 @@ -11969,6 +11612,16 @@ snapshots: transitivePeerDependencies: - chokidar + '@angular-devkit/schematics@19.2.17(chokidar@4.0.3)': + dependencies: + '@angular-devkit/core': 19.2.17(chokidar@4.0.3) + jsonc-parser: 3.3.1 + magic-string: 0.30.17 + ora: 5.4.1 + rxjs: 7.8.1 + transitivePeerDependencies: + - chokidar + '@asamuzakjp/css-color@3.2.0': dependencies: '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) @@ -11978,6 +11631,391 @@ snapshots: lru-cache: 10.4.3 optional: true + '@aws-crypto/sha256-browser@5.2.0': + dependencies: + '@aws-crypto/sha256-js': 5.2.0 + '@aws-crypto/supports-web-crypto': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.901.0 + '@aws-sdk/util-locate-window': 3.893.0 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-crypto/sha256-js@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.901.0 + tslib: 2.8.1 + + '@aws-crypto/supports-web-crypto@5.2.0': + dependencies: + tslib: 2.8.1 + + '@aws-crypto/util@5.2.0': + dependencies: + '@aws-sdk/types': 3.901.0 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-sdk/client-sesv2@3.907.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.907.0 + '@aws-sdk/credential-provider-node': 3.907.0 + '@aws-sdk/middleware-host-header': 3.901.0 + '@aws-sdk/middleware-logger': 3.901.0 + '@aws-sdk/middleware-recursion-detection': 3.901.0 + '@aws-sdk/middleware-user-agent': 3.907.0 + '@aws-sdk/region-config-resolver': 3.901.0 + '@aws-sdk/signature-v4-multi-region': 3.907.0 + '@aws-sdk/types': 3.901.0 + '@aws-sdk/util-endpoints': 3.901.0 + '@aws-sdk/util-user-agent-browser': 3.907.0 + '@aws-sdk/util-user-agent-node': 3.907.0 + '@smithy/config-resolver': 4.3.0 + '@smithy/core': 3.15.0 + '@smithy/fetch-http-handler': 5.3.1 + '@smithy/hash-node': 4.2.0 + '@smithy/invalid-dependency': 4.2.0 + '@smithy/middleware-content-length': 4.2.0 + '@smithy/middleware-endpoint': 4.3.1 + '@smithy/middleware-retry': 4.4.1 + '@smithy/middleware-serde': 4.2.0 + '@smithy/middleware-stack': 4.2.0 + '@smithy/node-config-provider': 4.3.0 + '@smithy/node-http-handler': 4.3.0 + '@smithy/protocol-http': 5.3.0 + '@smithy/smithy-client': 4.7.1 + '@smithy/types': 4.6.0 + '@smithy/url-parser': 4.2.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-body-length-node': 4.2.1 + '@smithy/util-defaults-mode-browser': 4.3.0 + '@smithy/util-defaults-mode-node': 4.2.1 + '@smithy/util-endpoints': 3.2.0 + '@smithy/util-middleware': 4.2.0 + '@smithy/util-retry': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/client-sso@3.907.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.907.0 + '@aws-sdk/middleware-host-header': 3.901.0 + '@aws-sdk/middleware-logger': 3.901.0 + '@aws-sdk/middleware-recursion-detection': 3.901.0 + '@aws-sdk/middleware-user-agent': 3.907.0 + '@aws-sdk/region-config-resolver': 3.901.0 + '@aws-sdk/types': 3.901.0 + '@aws-sdk/util-endpoints': 3.901.0 + '@aws-sdk/util-user-agent-browser': 3.907.0 + '@aws-sdk/util-user-agent-node': 3.907.0 + '@smithy/config-resolver': 4.3.0 + '@smithy/core': 3.15.0 + '@smithy/fetch-http-handler': 5.3.1 + '@smithy/hash-node': 4.2.0 + '@smithy/invalid-dependency': 4.2.0 + '@smithy/middleware-content-length': 4.2.0 + '@smithy/middleware-endpoint': 4.3.1 + '@smithy/middleware-retry': 4.4.1 + '@smithy/middleware-serde': 4.2.0 + '@smithy/middleware-stack': 4.2.0 + '@smithy/node-config-provider': 4.3.0 + '@smithy/node-http-handler': 4.3.0 + '@smithy/protocol-http': 5.3.0 + '@smithy/smithy-client': 4.7.1 + '@smithy/types': 4.6.0 + '@smithy/url-parser': 4.2.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-body-length-node': 4.2.1 + '@smithy/util-defaults-mode-browser': 4.3.0 + '@smithy/util-defaults-mode-node': 4.2.1 + '@smithy/util-endpoints': 3.2.0 + '@smithy/util-middleware': 4.2.0 + '@smithy/util-retry': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/core@3.907.0': + dependencies: + '@aws-sdk/types': 3.901.0 + '@aws-sdk/xml-builder': 3.901.0 + '@smithy/core': 3.15.0 + '@smithy/node-config-provider': 4.3.0 + '@smithy/property-provider': 4.2.0 + '@smithy/protocol-http': 5.3.0 + '@smithy/signature-v4': 5.3.0 + '@smithy/smithy-client': 4.7.1 + '@smithy/types': 4.6.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-middleware': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-env@3.907.0': + dependencies: + '@aws-sdk/core': 3.907.0 + '@aws-sdk/types': 3.901.0 + '@smithy/property-provider': 4.2.0 + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-http@3.907.0': + dependencies: + '@aws-sdk/core': 3.907.0 + '@aws-sdk/types': 3.901.0 + '@smithy/fetch-http-handler': 5.3.1 + '@smithy/node-http-handler': 4.3.0 + '@smithy/property-provider': 4.2.0 + '@smithy/protocol-http': 5.3.0 + '@smithy/smithy-client': 4.7.1 + '@smithy/types': 4.6.0 + '@smithy/util-stream': 4.5.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-ini@3.907.0': + dependencies: + '@aws-sdk/core': 3.907.0 + '@aws-sdk/credential-provider-env': 3.907.0 + '@aws-sdk/credential-provider-http': 3.907.0 + '@aws-sdk/credential-provider-process': 3.907.0 + '@aws-sdk/credential-provider-sso': 3.907.0 + '@aws-sdk/credential-provider-web-identity': 3.907.0 + '@aws-sdk/nested-clients': 3.907.0 + '@aws-sdk/types': 3.901.0 + '@smithy/credential-provider-imds': 4.2.0 + '@smithy/property-provider': 4.2.0 + '@smithy/shared-ini-file-loader': 4.3.0 + '@smithy/types': 4.6.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-node@3.907.0': + dependencies: + '@aws-sdk/credential-provider-env': 3.907.0 + '@aws-sdk/credential-provider-http': 3.907.0 + '@aws-sdk/credential-provider-ini': 3.907.0 + '@aws-sdk/credential-provider-process': 3.907.0 + '@aws-sdk/credential-provider-sso': 3.907.0 + '@aws-sdk/credential-provider-web-identity': 3.907.0 + '@aws-sdk/types': 3.901.0 + '@smithy/credential-provider-imds': 4.2.0 + '@smithy/property-provider': 4.2.0 + '@smithy/shared-ini-file-loader': 4.3.0 + '@smithy/types': 4.6.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-process@3.907.0': + dependencies: + '@aws-sdk/core': 3.907.0 + '@aws-sdk/types': 3.901.0 + '@smithy/property-provider': 4.2.0 + '@smithy/shared-ini-file-loader': 4.3.0 + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-sso@3.907.0': + dependencies: + '@aws-sdk/client-sso': 3.907.0 + '@aws-sdk/core': 3.907.0 + '@aws-sdk/token-providers': 3.907.0 + '@aws-sdk/types': 3.901.0 + '@smithy/property-provider': 4.2.0 + '@smithy/shared-ini-file-loader': 4.3.0 + '@smithy/types': 4.6.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-web-identity@3.907.0': + dependencies: + '@aws-sdk/core': 3.907.0 + '@aws-sdk/nested-clients': 3.907.0 + '@aws-sdk/types': 3.901.0 + '@smithy/property-provider': 4.2.0 + '@smithy/shared-ini-file-loader': 4.3.0 + '@smithy/types': 4.6.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/middleware-host-header@3.901.0': + dependencies: + '@aws-sdk/types': 3.901.0 + '@smithy/protocol-http': 5.3.0 + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-logger@3.901.0': + dependencies: + '@aws-sdk/types': 3.901.0 + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-recursion-detection@3.901.0': + dependencies: + '@aws-sdk/types': 3.901.0 + '@aws/lambda-invoke-store': 0.0.1 + '@smithy/protocol-http': 5.3.0 + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-sdk-s3@3.907.0': + dependencies: + '@aws-sdk/core': 3.907.0 + '@aws-sdk/types': 3.901.0 + '@aws-sdk/util-arn-parser': 3.893.0 + '@smithy/core': 3.15.0 + '@smithy/node-config-provider': 4.3.0 + '@smithy/protocol-http': 5.3.0 + '@smithy/signature-v4': 5.3.0 + '@smithy/smithy-client': 4.7.1 + '@smithy/types': 4.6.0 + '@smithy/util-config-provider': 4.2.0 + '@smithy/util-middleware': 4.2.0 + '@smithy/util-stream': 4.5.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-user-agent@3.907.0': + dependencies: + '@aws-sdk/core': 3.907.0 + '@aws-sdk/types': 3.901.0 + '@aws-sdk/util-endpoints': 3.901.0 + '@smithy/core': 3.15.0 + '@smithy/protocol-http': 5.3.0 + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@aws-sdk/nested-clients@3.907.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.907.0 + '@aws-sdk/middleware-host-header': 3.901.0 + '@aws-sdk/middleware-logger': 3.901.0 + '@aws-sdk/middleware-recursion-detection': 3.901.0 + '@aws-sdk/middleware-user-agent': 3.907.0 + '@aws-sdk/region-config-resolver': 3.901.0 + '@aws-sdk/types': 3.901.0 + '@aws-sdk/util-endpoints': 3.901.0 + '@aws-sdk/util-user-agent-browser': 3.907.0 + '@aws-sdk/util-user-agent-node': 3.907.0 + '@smithy/config-resolver': 4.3.0 + '@smithy/core': 3.15.0 + '@smithy/fetch-http-handler': 5.3.1 + '@smithy/hash-node': 4.2.0 + '@smithy/invalid-dependency': 4.2.0 + '@smithy/middleware-content-length': 4.2.0 + '@smithy/middleware-endpoint': 4.3.1 + '@smithy/middleware-retry': 4.4.1 + '@smithy/middleware-serde': 4.2.0 + '@smithy/middleware-stack': 4.2.0 + '@smithy/node-config-provider': 4.3.0 + '@smithy/node-http-handler': 4.3.0 + '@smithy/protocol-http': 5.3.0 + '@smithy/smithy-client': 4.7.1 + '@smithy/types': 4.6.0 + '@smithy/url-parser': 4.2.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-body-length-node': 4.2.1 + '@smithy/util-defaults-mode-browser': 4.3.0 + '@smithy/util-defaults-mode-node': 4.2.1 + '@smithy/util-endpoints': 3.2.0 + '@smithy/util-middleware': 4.2.0 + '@smithy/util-retry': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/region-config-resolver@3.901.0': + dependencies: + '@aws-sdk/types': 3.901.0 + '@smithy/node-config-provider': 4.3.0 + '@smithy/types': 4.6.0 + '@smithy/util-config-provider': 4.2.0 + '@smithy/util-middleware': 4.2.0 + tslib: 2.8.1 + + '@aws-sdk/signature-v4-multi-region@3.907.0': + dependencies: + '@aws-sdk/middleware-sdk-s3': 3.907.0 + '@aws-sdk/types': 3.901.0 + '@smithy/protocol-http': 5.3.0 + '@smithy/signature-v4': 5.3.0 + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@aws-sdk/token-providers@3.907.0': + dependencies: + '@aws-sdk/core': 3.907.0 + '@aws-sdk/nested-clients': 3.907.0 + '@aws-sdk/types': 3.901.0 + '@smithy/property-provider': 4.2.0 + '@smithy/shared-ini-file-loader': 4.3.0 + '@smithy/types': 4.6.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/types@3.901.0': + dependencies: + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@aws-sdk/util-arn-parser@3.893.0': + dependencies: + tslib: 2.8.1 + + '@aws-sdk/util-endpoints@3.901.0': + dependencies: + '@aws-sdk/types': 3.901.0 + '@smithy/types': 4.6.0 + '@smithy/url-parser': 4.2.0 + '@smithy/util-endpoints': 3.2.0 + tslib: 2.8.1 + + '@aws-sdk/util-locate-window@3.893.0': + dependencies: + tslib: 2.8.1 + + '@aws-sdk/util-user-agent-browser@3.907.0': + dependencies: + '@aws-sdk/types': 3.901.0 + '@smithy/types': 4.6.0 + bowser: 2.12.1 + tslib: 2.8.1 + + '@aws-sdk/util-user-agent-node@3.907.0': + dependencies: + '@aws-sdk/middleware-user-agent': 3.907.0 + '@aws-sdk/types': 3.901.0 + '@smithy/node-config-provider': 4.3.0 + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@aws-sdk/xml-builder@3.901.0': + dependencies: + '@smithy/types': 4.6.0 + fast-xml-parser: 5.2.5 + tslib: 2.8.1 + + '@aws/lambda-invoke-store@0.0.1': {} + '@babel/code-frame@7.27.1': dependencies: '@babel/helper-validator-identifier': 7.27.1 @@ -11994,12 +12032,12 @@ snapshots: '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.7) '@babel/helpers': 7.27.6 - '@babel/parser': 7.28.3 + '@babel/parser': 7.28.4 '@babel/template': 7.27.2 - '@babel/traverse': 7.28.3 - '@babel/types': 7.28.2 + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 convert-source-map: 2.0.0 - debug: 4.4.1 + debug: 4.4.3 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -12008,21 +12046,21 @@ snapshots: '@babel/generator@7.28.3': dependencies: - '@babel/parser': 7.28.3 - '@babel/types': 7.28.2 + '@babel/parser': 7.28.4 + '@babel/types': 7.28.4 '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.30 + '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 '@babel/helper-annotate-as-pure@7.27.3': dependencies: - '@babel/types': 7.28.2 + '@babel/types': 7.28.4 '@babel/helper-compilation-targets@7.27.2': dependencies: '@babel/compat-data': 7.27.7 '@babel/helper-validator-option': 7.27.1 - browserslist: 4.25.3 + browserslist: 4.26.3 lru-cache: 5.1.1 semver: 6.3.1 @@ -12034,7 +12072,7 @@ snapshots: '@babel/helper-optimise-call-expression': 7.27.1 '@babel/helper-replace-supers': 7.27.1(@babel/core@7.27.7) '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.4 semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -12051,7 +12089,7 @@ snapshots: '@babel/core': 7.27.7 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 - debug: 4.4.1 + debug: 4.4.3 lodash.debounce: 4.0.8 resolve: 1.22.10 transitivePeerDependencies: @@ -12061,15 +12099,15 @@ snapshots: '@babel/helper-member-expression-to-functions@7.27.1': dependencies: - '@babel/traverse': 7.28.3 - '@babel/types': 7.28.2 + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 transitivePeerDependencies: - supports-color '@babel/helper-module-imports@7.27.1': dependencies: - '@babel/traverse': 7.28.3 - '@babel/types': 7.28.2 + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 transitivePeerDependencies: - supports-color @@ -12078,13 +12116,13 @@ snapshots: '@babel/core': 7.27.7 '@babel/helper-module-imports': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.4 transitivePeerDependencies: - supports-color '@babel/helper-optimise-call-expression@7.27.1': dependencies: - '@babel/types': 7.28.2 + '@babel/types': 7.28.4 '@babel/helper-plugin-utils@7.27.1': {} @@ -12093,7 +12131,7 @@ snapshots: '@babel/core': 7.27.7 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-wrap-function': 7.27.1 - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.4 transitivePeerDependencies: - supports-color @@ -12102,14 +12140,14 @@ snapshots: '@babel/core': 7.27.7 '@babel/helper-member-expression-to-functions': 7.27.1 '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.4 transitivePeerDependencies: - supports-color '@babel/helper-skip-transparent-expression-wrappers@7.27.1': dependencies: - '@babel/traverse': 7.28.3 - '@babel/types': 7.28.2 + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 transitivePeerDependencies: - supports-color @@ -12122,25 +12160,25 @@ snapshots: '@babel/helper-wrap-function@7.27.1': dependencies: '@babel/template': 7.27.2 - '@babel/traverse': 7.28.3 - '@babel/types': 7.28.2 + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 transitivePeerDependencies: - supports-color '@babel/helpers@7.27.6': dependencies: '@babel/template': 7.27.2 - '@babel/types': 7.28.2 + '@babel/types': 7.28.4 - '@babel/parser@7.28.3': + '@babel/parser@7.28.4': dependencies: - '@babel/types': 7.28.2 + '@babel/types': 7.28.4 '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1(@babel/core@7.27.7)': dependencies: '@babel/core': 7.27.7 '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.4 transitivePeerDependencies: - supports-color @@ -12167,7 +12205,7 @@ snapshots: dependencies: '@babel/core': 7.27.7 '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.4 transitivePeerDependencies: - supports-color @@ -12216,7 +12254,7 @@ snapshots: '@babel/core': 7.27.7 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.27.7) - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.4 transitivePeerDependencies: - supports-color @@ -12262,7 +12300,7 @@ snapshots: '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-replace-supers': 7.27.1(@babel/core@7.27.7) - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.4 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -12277,7 +12315,7 @@ snapshots: dependencies: '@babel/core': 7.27.7 '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.4 transitivePeerDependencies: - supports-color @@ -12326,7 +12364,7 @@ snapshots: '@babel/core': 7.27.7 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.4 transitivePeerDependencies: - supports-color @@ -12372,7 +12410,7 @@ snapshots: '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.7) '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.4 transitivePeerDependencies: - supports-color @@ -12412,7 +12450,7 @@ snapshots: '@babel/helper-plugin-utils': 7.27.1 '@babel/plugin-transform-destructuring': 7.27.7(@babel/core@7.27.7) '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.27.7) - '@babel/traverse': 7.28.3 + '@babel/traverse': 7.28.4 transitivePeerDependencies: - supports-color @@ -12488,7 +12526,7 @@ snapshots: '@babel/helper-module-imports': 7.27.1 '@babel/helper-plugin-utils': 7.27.1 '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.27.7) - '@babel/types': 7.28.2 + '@babel/types': 7.28.4 transitivePeerDependencies: - supports-color @@ -12667,7 +12705,7 @@ snapshots: dependencies: '@babel/core': 7.27.7 '@babel/helper-plugin-utils': 7.27.1 - '@babel/types': 7.28.2 + '@babel/types': 7.28.4 esutils: 2.0.3 '@babel/preset-react@7.27.1(@babel/core@7.27.7)': @@ -12697,27 +12735,27 @@ snapshots: dependencies: core-js-pure: 3.43.0 - '@babel/runtime@7.28.3': {} + '@babel/runtime@7.28.4': {} '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 - '@babel/parser': 7.28.3 - '@babel/types': 7.28.2 + '@babel/parser': 7.28.4 + '@babel/types': 7.28.4 - '@babel/traverse@7.28.3': + '@babel/traverse@7.28.4': dependencies: '@babel/code-frame': 7.27.1 '@babel/generator': 7.28.3 '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.28.3 + '@babel/parser': 7.28.4 '@babel/template': 7.27.2 - '@babel/types': 7.28.2 - debug: 4.4.1 + '@babel/types': 7.28.4 + debug: 4.4.3 transitivePeerDependencies: - supports-color - '@babel/types@7.28.2': + '@babel/types@7.28.4': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 @@ -12996,21 +13034,21 @@ snapshots: '@docsearch/css@3.9.0': {} - '@docsearch/react@3.9.0(@algolia/client-search@5.29.0)(@types/react@19.1.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)': + '@docsearch/react@3.9.0(@algolia/client-search@5.40.0)(@types/react@19.2.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)': dependencies: - '@algolia/autocomplete-core': 1.17.9(@algolia/client-search@5.29.0)(algoliasearch@5.29.0)(search-insights@2.17.3) - '@algolia/autocomplete-preset-algolia': 1.17.9(@algolia/client-search@5.29.0)(algoliasearch@5.29.0) + '@algolia/autocomplete-core': 1.17.9(@algolia/client-search@5.40.0)(algoliasearch@5.40.0)(search-insights@2.17.3) + '@algolia/autocomplete-preset-algolia': 1.17.9(@algolia/client-search@5.40.0)(algoliasearch@5.40.0) '@docsearch/css': 3.9.0 - algoliasearch: 5.29.0 + algoliasearch: 5.40.0 optionalDependencies: - '@types/react': 19.1.12 + '@types/react': 19.2.2 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) search-insights: 2.17.3 transitivePeerDependencies: - '@algolia/client-search' - '@docusaurus/babel@3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@docusaurus/babel@3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/core': 7.27.7 '@babel/generator': 7.28.3 @@ -13019,17 +13057,16 @@ snapshots: '@babel/preset-env': 7.27.2(@babel/core@7.27.7) '@babel/preset-react': 7.27.1(@babel/core@7.27.7) '@babel/preset-typescript': 7.27.1(@babel/core@7.27.7) - '@babel/runtime': 7.28.3 + '@babel/runtime': 7.28.4 '@babel/runtime-corejs3': 7.27.6 - '@babel/traverse': 7.28.3 - '@docusaurus/logger': 3.8.1 - '@docusaurus/utils': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@babel/traverse': 7.28.4 + '@docusaurus/logger': 3.9.1 + '@docusaurus/utils': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) babel-plugin-dynamic-import-node: 2.3.3 fs-extra: 11.3.0 tslib: 2.8.1 transitivePeerDependencies: - '@swc/core' - - acorn - esbuild - react - react-dom @@ -13037,38 +13074,37 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/bundler@3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2)': + '@docusaurus/bundler@3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)': dependencies: '@babel/core': 7.27.7 - '@docusaurus/babel': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/cssnano-preset': 3.8.1 - '@docusaurus/logger': 3.8.1 - '@docusaurus/types': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - babel-loader: 9.2.1(@babel/core@7.27.7)(webpack@5.100.2) + '@docusaurus/babel': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/cssnano-preset': 3.9.1 + '@docusaurus/logger': 3.9.1 + '@docusaurus/types': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + babel-loader: 9.2.1(@babel/core@7.27.7)(webpack@5.102.1) clean-css: 5.3.3 - copy-webpack-plugin: 11.0.0(webpack@5.100.2) - css-loader: 6.11.0(webpack@5.100.2) - css-minimizer-webpack-plugin: 5.0.1(clean-css@5.3.3)(webpack@5.100.2) + copy-webpack-plugin: 11.0.0(webpack@5.102.1) + css-loader: 6.11.0(webpack@5.102.1) + css-minimizer-webpack-plugin: 5.0.1(clean-css@5.3.3)(webpack@5.102.1) cssnano: 6.1.2(postcss@8.5.6) - file-loader: 6.2.0(webpack@5.100.2) + file-loader: 6.2.0(webpack@5.102.1) html-minifier-terser: 7.2.0 - mini-css-extract-plugin: 2.9.2(webpack@5.100.2) - null-loader: 4.0.1(webpack@5.100.2) + mini-css-extract-plugin: 2.9.2(webpack@5.102.1) + null-loader: 4.0.1(webpack@5.102.1) postcss: 8.5.6 - postcss-loader: 7.3.4(postcss@8.5.6)(typescript@5.9.2)(webpack@5.100.2) + postcss-loader: 7.3.4(postcss@8.5.6)(typescript@5.9.3)(webpack@5.102.1) postcss-preset-env: 10.2.4(postcss@8.5.6) - terser-webpack-plugin: 5.3.14(webpack@5.100.2) + terser-webpack-plugin: 5.3.14(webpack@5.102.1) tslib: 2.8.1 - url-loader: 4.1.1(file-loader@6.2.0(webpack@5.100.2))(webpack@5.100.2) - webpack: 5.100.2 - webpackbar: 6.0.1(webpack@5.100.2) + url-loader: 4.1.1(file-loader@6.2.0(webpack@5.102.1))(webpack@5.102.1) + webpack: 5.102.1 + webpackbar: 6.0.1(webpack@5.102.1) transitivePeerDependencies: - '@parcel/css' - '@rspack/core' - '@swc/core' - '@swc/css' - - acorn - csso - esbuild - lightningcss @@ -13079,16 +13115,16 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/core@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2)': + '@docusaurus/core@3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)': dependencies: - '@docusaurus/babel': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/bundler': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/logger': 3.8.1 - '@docusaurus/mdx-loader': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-common': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-validation': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@mdx-js/react': 3.1.0(@types/react@19.1.12)(react@18.3.1) + '@docusaurus/babel': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/bundler': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/logger': 3.9.1 + '@docusaurus/mdx-loader': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-common': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-validation': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@mdx-js/react': 3.1.1(@types/react@19.2.2)(react@18.3.1) boxen: 6.2.1 chalk: 4.1.2 chokidar: 3.6.0 @@ -13103,7 +13139,7 @@ snapshots: execa: 5.1.1 fs-extra: 11.3.0 html-tags: 3.3.1 - html-webpack-plugin: 5.6.3(webpack@5.100.2) + html-webpack-plugin: 5.6.3(webpack@5.102.1) leven: 3.1.0 lodash: 4.17.21 open: 8.4.2 @@ -13113,18 +13149,18 @@ snapshots: react-dom: 18.3.1(react@18.3.1) react-helmet-async: '@slorber/react-helmet-async@1.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)' react-loadable: '@docusaurus/react-loadable@6.0.0(react@18.3.1)' - react-loadable-ssr-addon-v5-slorber: 1.0.1(@docusaurus/react-loadable@6.0.0(react@18.3.1))(webpack@5.100.2) + react-loadable-ssr-addon-v5-slorber: 1.0.1(@docusaurus/react-loadable@6.0.0(react@18.3.1))(webpack@5.102.1) react-router: 5.3.4(react@18.3.1) react-router-config: 5.1.1(react-router@5.3.4(react@18.3.1))(react@18.3.1) react-router-dom: 5.3.4(react@18.3.1) - semver: 7.7.2 + semver: 7.7.3 serve-handler: 6.1.6 tinypool: 1.1.1 tslib: 2.8.1 update-notifier: 6.0.2 - webpack: 5.100.2 + webpack: 5.102.1 webpack-bundle-analyzer: 4.10.2 - webpack-dev-server: 4.15.2(webpack@5.100.2) + webpack-dev-server: 5.2.2(webpack@5.102.1) webpack-merge: 6.0.1 transitivePeerDependencies: - '@docusaurus/faster' @@ -13132,7 +13168,6 @@ snapshots: - '@rspack/core' - '@swc/core' - '@swc/css' - - acorn - bufferutil - csso - debug @@ -13144,28 +13179,28 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/cssnano-preset@3.8.1': + '@docusaurus/cssnano-preset@3.9.1': dependencies: cssnano-preset-advanced: 6.1.2(postcss@8.5.6) postcss: 8.5.6 postcss-sort-media-queries: 5.2.0(postcss@8.5.6) tslib: 2.8.1 - '@docusaurus/logger@3.8.1': + '@docusaurus/logger@3.9.1': dependencies: chalk: 4.1.2 tslib: 2.8.1 - '@docusaurus/mdx-loader@3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@docusaurus/mdx-loader@3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@docusaurus/logger': 3.8.1 - '@docusaurus/utils': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-validation': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@mdx-js/mdx': 3.1.0(acorn@8.15.0) + '@docusaurus/logger': 3.9.1 + '@docusaurus/utils': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-validation': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@mdx-js/mdx': 3.1.1 '@slorber/remark-comment': 1.0.0 escape-html: 1.0.3 estree-util-value-to-estree: 3.4.0 - file-loader: 6.2.0(webpack@5.100.2) + file-loader: 6.2.0(webpack@5.102.1) fs-extra: 11.3.0 image-size: 2.0.2 mdast-util-mdx: 3.0.0 @@ -13181,22 +13216,21 @@ snapshots: tslib: 2.8.1 unified: 11.0.5 unist-util-visit: 5.0.0 - url-loader: 4.1.1(file-loader@6.2.0(webpack@5.100.2))(webpack@5.100.2) + url-loader: 4.1.1(file-loader@6.2.0(webpack@5.102.1))(webpack@5.102.1) vfile: 6.0.3 - webpack: 5.100.2 + webpack: 5.102.1 transitivePeerDependencies: - '@swc/core' - - acorn - esbuild - supports-color - uglify-js - webpack-cli - '@docusaurus/module-type-aliases@3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@docusaurus/module-type-aliases@3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@docusaurus/types': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/types': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/history': 4.7.11 - '@types/react': 19.1.12 + '@types/react': 19.2.2 '@types/react-router-config': 5.0.11 '@types/react-router-dom': 5.3.3 react: 18.3.1 @@ -13205,23 +13239,22 @@ snapshots: react-loadable: '@docusaurus/react-loadable@6.0.0(react@18.3.1)' transitivePeerDependencies: - '@swc/core' - - acorn - esbuild - supports-color - uglify-js - webpack-cli - '@docusaurus/plugin-content-blog@3.8.1(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2))(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2)': + '@docusaurus/plugin-content-blog@3.9.1(@docusaurus/plugin-content-docs@3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3))(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)': dependencies: - '@docusaurus/core': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/logger': 3.8.1 - '@docusaurus/mdx-loader': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/plugin-content-docs': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/theme-common': 3.8.1(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/types': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-common': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-validation': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/core': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/logger': 3.9.1 + '@docusaurus/mdx-loader': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/plugin-content-docs': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/theme-common': 3.9.1(@docusaurus/plugin-content-docs@3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/types': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-common': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-validation': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) cheerio: 1.0.0-rc.12 feed: 4.2.2 fs-extra: 11.3.0 @@ -13233,7 +13266,7 @@ snapshots: tslib: 2.8.1 unist-util-visit: 5.0.0 utility-types: 3.11.0 - webpack: 5.100.2 + webpack: 5.102.1 transitivePeerDependencies: - '@docusaurus/faster' - '@mdx-js/react' @@ -13241,7 +13274,6 @@ snapshots: - '@rspack/core' - '@swc/core' - '@swc/css' - - acorn - bufferutil - csso - debug @@ -13253,17 +13285,17 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2)': + '@docusaurus/plugin-content-docs@3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)': dependencies: - '@docusaurus/core': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/logger': 3.8.1 - '@docusaurus/mdx-loader': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/module-type-aliases': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/theme-common': 3.8.1(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/types': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-common': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-validation': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/core': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/logger': 3.9.1 + '@docusaurus/mdx-loader': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/module-type-aliases': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/theme-common': 3.9.1(@docusaurus/plugin-content-docs@3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/types': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-common': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-validation': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/react-router-config': 5.0.11 combine-promises: 1.2.0 fs-extra: 11.3.0 @@ -13274,7 +13306,7 @@ snapshots: schema-dts: 1.1.5 tslib: 2.8.1 utility-types: 3.11.0 - webpack: 5.100.2 + webpack: 5.102.1 transitivePeerDependencies: - '@docusaurus/faster' - '@mdx-js/react' @@ -13282,7 +13314,6 @@ snapshots: - '@rspack/core' - '@swc/core' - '@swc/css' - - acorn - bufferutil - csso - debug @@ -13294,18 +13325,18 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-content-pages@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2)': + '@docusaurus/plugin-content-pages@3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)': dependencies: - '@docusaurus/core': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/mdx-loader': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/types': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-validation': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/core': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/mdx-loader': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/types': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-validation': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) fs-extra: 11.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) tslib: 2.8.1 - webpack: 5.100.2 + webpack: 5.102.1 transitivePeerDependencies: - '@docusaurus/faster' - '@mdx-js/react' @@ -13313,7 +13344,6 @@ snapshots: - '@rspack/core' - '@swc/core' - '@swc/css' - - acorn - bufferutil - csso - debug @@ -13325,12 +13355,12 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-css-cascade-layers@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2)': + '@docusaurus/plugin-css-cascade-layers@3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)': dependencies: - '@docusaurus/core': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/types': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-validation': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/core': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/types': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-validation': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) tslib: 2.8.1 transitivePeerDependencies: - '@docusaurus/faster' @@ -13339,7 +13369,6 @@ snapshots: - '@rspack/core' - '@swc/core' - '@swc/css' - - acorn - bufferutil - csso - debug @@ -13353,11 +13382,11 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-debug@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2)': + '@docusaurus/plugin-debug@3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)': dependencies: - '@docusaurus/core': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/types': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/core': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/types': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) fs-extra: 11.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -13370,7 +13399,6 @@ snapshots: - '@rspack/core' - '@swc/core' - '@swc/css' - - acorn - bufferutil - csso - debug @@ -13382,11 +13410,11 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-google-analytics@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2)': + '@docusaurus/plugin-google-analytics@3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)': dependencies: - '@docusaurus/core': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/types': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-validation': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/core': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/types': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-validation': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) tslib: 2.8.1 @@ -13397,7 +13425,6 @@ snapshots: - '@rspack/core' - '@swc/core' - '@swc/css' - - acorn - bufferutil - csso - debug @@ -13409,11 +13436,11 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-google-gtag@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2)': + '@docusaurus/plugin-google-gtag@3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)': dependencies: - '@docusaurus/core': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/types': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-validation': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/core': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/types': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-validation': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/gtag.js': 0.0.12 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -13425,7 +13452,6 @@ snapshots: - '@rspack/core' - '@swc/core' - '@swc/css' - - acorn - bufferutil - csso - debug @@ -13437,11 +13463,11 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-google-tag-manager@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2)': + '@docusaurus/plugin-google-tag-manager@3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)': dependencies: - '@docusaurus/core': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/types': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-validation': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/core': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/types': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-validation': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) tslib: 2.8.1 @@ -13452,7 +13478,6 @@ snapshots: - '@rspack/core' - '@swc/core' - '@swc/css' - - acorn - bufferutil - csso - debug @@ -13464,14 +13489,14 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-sitemap@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2)': + '@docusaurus/plugin-sitemap@3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)': dependencies: - '@docusaurus/core': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/logger': 3.8.1 - '@docusaurus/types': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-common': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-validation': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/core': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/logger': 3.9.1 + '@docusaurus/types': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-common': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-validation': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) fs-extra: 11.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -13484,7 +13509,6 @@ snapshots: - '@rspack/core' - '@swc/core' - '@swc/css' - - acorn - bufferutil - csso - debug @@ -13496,18 +13520,18 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/plugin-svgr@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2)': + '@docusaurus/plugin-svgr@3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)': dependencies: - '@docusaurus/core': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/types': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-validation': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@svgr/core': 8.1.0(typescript@5.9.2) - '@svgr/webpack': 8.1.0(typescript@5.9.2) + '@docusaurus/core': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/types': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-validation': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@svgr/core': 8.1.0(typescript@5.9.3) + '@svgr/webpack': 8.1.0(typescript@5.9.3) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) tslib: 2.8.1 - webpack: 5.100.2 + webpack: 5.102.1 transitivePeerDependencies: - '@docusaurus/faster' - '@mdx-js/react' @@ -13515,7 +13539,6 @@ snapshots: - '@rspack/core' - '@swc/core' - '@swc/css' - - acorn - bufferutil - csso - debug @@ -13527,23 +13550,23 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/preset-classic@3.8.1(@algolia/client-search@5.29.0)(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(@types/react@19.1.12)(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.9.2)': + '@docusaurus/preset-classic@3.9.1(@algolia/client-search@5.40.0)(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(@types/react@19.2.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.9.3)': dependencies: - '@docusaurus/core': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/plugin-content-blog': 3.8.1(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2))(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/plugin-content-docs': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/plugin-content-pages': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/plugin-css-cascade-layers': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/plugin-debug': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/plugin-google-analytics': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/plugin-google-gtag': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/plugin-google-tag-manager': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/plugin-sitemap': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/plugin-svgr': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/theme-classic': 3.8.1(@types/react@19.1.12)(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/theme-common': 3.8.1(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/theme-search-algolia': 3.8.1(@algolia/client-search@5.29.0)(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(@types/react@19.1.12)(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.9.2) - '@docusaurus/types': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/core': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/plugin-content-blog': 3.9.1(@docusaurus/plugin-content-docs@3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3))(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/plugin-content-docs': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/plugin-content-pages': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/plugin-css-cascade-layers': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/plugin-debug': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/plugin-google-analytics': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/plugin-google-gtag': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/plugin-google-tag-manager': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/plugin-sitemap': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/plugin-svgr': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/theme-classic': 3.9.1(@types/react@19.2.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/theme-common': 3.9.1(@docusaurus/plugin-content-docs@3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/theme-search-algolia': 3.9.1(@algolia/client-search@5.40.0)(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(@types/react@19.2.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.9.3) + '@docusaurus/types': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) transitivePeerDependencies: @@ -13555,7 +13578,6 @@ snapshots: - '@swc/core' - '@swc/css' - '@types/react' - - acorn - bufferutil - csso - debug @@ -13570,27 +13592,26 @@ snapshots: '@docusaurus/react-loadable@6.0.0(react@18.3.1)': dependencies: - '@types/react': 19.1.12 + '@types/react': 19.2.2 react: 18.3.1 - '@docusaurus/theme-classic@3.8.1(@types/react@19.1.12)(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2)': + '@docusaurus/theme-classic@3.9.1(@types/react@19.2.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)': dependencies: - '@docusaurus/core': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/logger': 3.8.1 - '@docusaurus/mdx-loader': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/module-type-aliases': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/plugin-content-blog': 3.8.1(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2))(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/plugin-content-docs': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/plugin-content-pages': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/theme-common': 3.8.1(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/theme-translations': 3.8.1 - '@docusaurus/types': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-common': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-validation': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@mdx-js/react': 3.1.0(@types/react@19.1.12)(react@18.3.1) + '@docusaurus/core': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/logger': 3.9.1 + '@docusaurus/mdx-loader': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/module-type-aliases': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/plugin-content-blog': 3.9.1(@docusaurus/plugin-content-docs@3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3))(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/plugin-content-docs': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/plugin-content-pages': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/theme-common': 3.9.1(@docusaurus/plugin-content-docs@3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/theme-translations': 3.9.1 + '@docusaurus/types': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-common': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-validation': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@mdx-js/react': 3.1.1(@types/react@19.2.2)(react@18.3.1) clsx: 2.1.1 - copy-text-to-clipboard: 3.2.0 infima: 0.2.0-alpha.45 lodash: 4.17.21 nprogress: 0.2.0 @@ -13610,7 +13631,6 @@ snapshots: - '@swc/core' - '@swc/css' - '@types/react' - - acorn - bufferutil - csso - debug @@ -13622,15 +13642,15 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/theme-common@3.8.1(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@docusaurus/theme-common@3.9.1(@docusaurus/plugin-content-docs@3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@docusaurus/mdx-loader': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/module-type-aliases': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/plugin-content-docs': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/utils': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-common': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/mdx-loader': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/module-type-aliases': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/plugin-content-docs': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/utils': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-common': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/history': 4.7.11 - '@types/react': 19.1.12 + '@types/react': 19.2.2 '@types/react-router-config': 5.0.11 clsx: 2.1.1 parse-numeric-range: 1.3.0 @@ -13641,24 +13661,23 @@ snapshots: utility-types: 3.11.0 transitivePeerDependencies: - '@swc/core' - - acorn - esbuild - supports-color - uglify-js - webpack-cli - '@docusaurus/theme-search-algolia@3.8.1(@algolia/client-search@5.29.0)(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(@types/react@19.1.12)(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.9.2)': + '@docusaurus/theme-search-algolia@3.9.1(@algolia/client-search@5.40.0)(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(@types/react@19.2.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.9.3)': dependencies: - '@docsearch/react': 3.9.0(@algolia/client-search@5.29.0)(@types/react@19.1.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3) - '@docusaurus/core': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/logger': 3.8.1 - '@docusaurus/plugin-content-docs': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/theme-common': 3.8.1(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/theme-translations': 3.8.1 - '@docusaurus/utils': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-validation': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - algoliasearch: 5.29.0 - algoliasearch-helper: 3.26.0(algoliasearch@5.29.0) + '@docsearch/react': 3.9.0(@algolia/client-search@5.40.0)(@types/react@19.2.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3) + '@docusaurus/core': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/logger': 3.9.1 + '@docusaurus/plugin-content-docs': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) + '@docusaurus/theme-common': 3.9.1(@docusaurus/plugin-content-docs@3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/theme-translations': 3.9.1 + '@docusaurus/utils': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-validation': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + algoliasearch: 5.40.0 + algoliasearch-helper: 3.26.0(algoliasearch@5.40.0) clsx: 2.1.1 eta: 2.2.0 fs-extra: 11.3.0 @@ -13676,7 +13695,6 @@ snapshots: - '@swc/core' - '@swc/css' - '@types/react' - - acorn - bufferutil - csso - debug @@ -13689,41 +13707,40 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/theme-translations@3.8.1': + '@docusaurus/theme-translations@3.9.1': dependencies: fs-extra: 11.3.0 tslib: 2.8.1 - '@docusaurus/tsconfig@3.8.1': {} + '@docusaurus/tsconfig@3.9.1': {} - '@docusaurus/types@3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@docusaurus/types@3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@mdx-js/mdx': 3.1.0(acorn@8.15.0) + '@mdx-js/mdx': 3.1.1 '@types/history': 4.7.11 - '@types/react': 19.1.12 + '@types/mdast': 4.0.4 + '@types/react': 19.2.2 commander: 5.1.0 joi: 17.13.3 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-helmet-async: '@slorber/react-helmet-async@1.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)' utility-types: 3.11.0 - webpack: 5.100.2 + webpack: 5.102.1 webpack-merge: 5.10.0 transitivePeerDependencies: - '@swc/core' - - acorn - esbuild - supports-color - uglify-js - webpack-cli - '@docusaurus/utils-common@3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@docusaurus/utils-common@3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@docusaurus/types': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/types': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) tslib: 2.8.1 transitivePeerDependencies: - '@swc/core' - - acorn - esbuild - react - react-dom @@ -13731,11 +13748,11 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/utils-validation@3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@docusaurus/utils-validation@3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@docusaurus/logger': 3.8.1 - '@docusaurus/utils': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-common': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/logger': 3.9.1 + '@docusaurus/utils': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-common': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) fs-extra: 11.3.0 joi: 17.13.3 js-yaml: 4.1.0 @@ -13743,7 +13760,6 @@ snapshots: tslib: 2.8.1 transitivePeerDependencies: - '@swc/core' - - acorn - esbuild - react - react-dom @@ -13751,14 +13767,14 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/utils@3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@docusaurus/utils@3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@docusaurus/logger': 3.8.1 - '@docusaurus/types': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-common': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/logger': 3.9.1 + '@docusaurus/types': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/utils-common': 3.9.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) escape-string-regexp: 4.0.0 execa: 5.1.1 - file-loader: 6.2.0(webpack@5.100.2) + file-loader: 6.2.0(webpack@5.102.1) fs-extra: 11.3.0 github-slugger: 1.5.0 globby: 11.1.0 @@ -13771,12 +13787,11 @@ snapshots: prompts: 2.4.2 resolve-pathname: 3.0.0 tslib: 2.8.1 - url-loader: 4.1.1(file-loader@6.2.0(webpack@5.100.2))(webpack@5.100.2) + url-loader: 4.1.1(file-loader@6.2.0(webpack@5.102.1))(webpack@5.102.1) utility-types: 3.11.0 - webpack: 5.100.2 + webpack: 5.102.1 transitivePeerDependencies: - '@swc/core' - - acorn - esbuild - react - react-dom @@ -13792,158 +13807,153 @@ snapshots: '@esbuild/aix-ppc64@0.19.12': optional: true - '@esbuild/aix-ppc64@0.25.9': + '@esbuild/aix-ppc64@0.25.10': optional: true '@esbuild/android-arm64@0.19.12': optional: true - '@esbuild/android-arm64@0.25.9': + '@esbuild/android-arm64@0.25.10': optional: true '@esbuild/android-arm@0.19.12': optional: true - '@esbuild/android-arm@0.25.9': + '@esbuild/android-arm@0.25.10': optional: true '@esbuild/android-x64@0.19.12': optional: true - '@esbuild/android-x64@0.25.9': + '@esbuild/android-x64@0.25.10': optional: true '@esbuild/darwin-arm64@0.19.12': optional: true - '@esbuild/darwin-arm64@0.25.9': + '@esbuild/darwin-arm64@0.25.10': optional: true '@esbuild/darwin-x64@0.19.12': optional: true - '@esbuild/darwin-x64@0.25.9': + '@esbuild/darwin-x64@0.25.10': optional: true '@esbuild/freebsd-arm64@0.19.12': optional: true - '@esbuild/freebsd-arm64@0.25.9': + '@esbuild/freebsd-arm64@0.25.10': optional: true '@esbuild/freebsd-x64@0.19.12': optional: true - '@esbuild/freebsd-x64@0.25.9': + '@esbuild/freebsd-x64@0.25.10': optional: true '@esbuild/linux-arm64@0.19.12': optional: true - '@esbuild/linux-arm64@0.25.9': + '@esbuild/linux-arm64@0.25.10': optional: true '@esbuild/linux-arm@0.19.12': optional: true - '@esbuild/linux-arm@0.25.9': + '@esbuild/linux-arm@0.25.10': optional: true '@esbuild/linux-ia32@0.19.12': optional: true - '@esbuild/linux-ia32@0.25.9': + '@esbuild/linux-ia32@0.25.10': optional: true '@esbuild/linux-loong64@0.19.12': optional: true - '@esbuild/linux-loong64@0.25.9': + '@esbuild/linux-loong64@0.25.10': optional: true '@esbuild/linux-mips64el@0.19.12': optional: true - '@esbuild/linux-mips64el@0.25.9': + '@esbuild/linux-mips64el@0.25.10': optional: true '@esbuild/linux-ppc64@0.19.12': optional: true - '@esbuild/linux-ppc64@0.25.9': + '@esbuild/linux-ppc64@0.25.10': optional: true '@esbuild/linux-riscv64@0.19.12': optional: true - '@esbuild/linux-riscv64@0.25.9': + '@esbuild/linux-riscv64@0.25.10': optional: true '@esbuild/linux-s390x@0.19.12': optional: true - '@esbuild/linux-s390x@0.25.9': + '@esbuild/linux-s390x@0.25.10': optional: true '@esbuild/linux-x64@0.19.12': optional: true - '@esbuild/linux-x64@0.25.9': + '@esbuild/linux-x64@0.25.10': optional: true - '@esbuild/netbsd-arm64@0.25.9': + '@esbuild/netbsd-arm64@0.25.10': optional: true '@esbuild/netbsd-x64@0.19.12': optional: true - '@esbuild/netbsd-x64@0.25.9': + '@esbuild/netbsd-x64@0.25.10': optional: true - '@esbuild/openbsd-arm64@0.25.9': + '@esbuild/openbsd-arm64@0.25.10': optional: true '@esbuild/openbsd-x64@0.19.12': optional: true - '@esbuild/openbsd-x64@0.25.9': + '@esbuild/openbsd-x64@0.25.10': optional: true - '@esbuild/openharmony-arm64@0.25.9': + '@esbuild/openharmony-arm64@0.25.10': optional: true '@esbuild/sunos-x64@0.19.12': optional: true - '@esbuild/sunos-x64@0.25.9': + '@esbuild/sunos-x64@0.25.10': optional: true '@esbuild/win32-arm64@0.19.12': optional: true - '@esbuild/win32-arm64@0.25.9': + '@esbuild/win32-arm64@0.25.10': optional: true '@esbuild/win32-ia32@0.19.12': optional: true - '@esbuild/win32-ia32@0.25.9': + '@esbuild/win32-ia32@0.25.10': optional: true '@esbuild/win32-x64@0.19.12': optional: true - '@esbuild/win32-x64@0.25.9': + '@esbuild/win32-x64@0.25.10': optional: true - '@eslint-community/eslint-utils@4.7.0(eslint@9.30.1(jiti@2.5.1))': + '@eslint-community/eslint-utils@4.9.0(eslint@9.37.0(jiti@2.6.1))': dependencies: - eslint: 9.30.1(jiti@2.5.1) - eslint-visitor-keys: 3.4.3 - - '@eslint-community/eslint-utils@4.7.0(eslint@9.33.0(jiti@2.5.1))': - dependencies: - eslint: 9.33.0(jiti@2.5.1) + eslint: 9.37.0(jiti@2.6.1) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} @@ -13951,25 +13961,27 @@ snapshots: '@eslint/config-array@0.21.0': dependencies: '@eslint/object-schema': 2.1.6 - debug: 4.4.1 + debug: 4.4.3 minimatch: 3.1.2 transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.3.1': {} + '@eslint/config-helpers@0.4.0': + dependencies: + '@eslint/core': 0.16.0 - '@eslint/core@0.14.0': + '@eslint/core@0.15.2': dependencies: '@types/json-schema': 7.0.15 - '@eslint/core@0.15.2': + '@eslint/core@0.16.0': dependencies: '@types/json-schema': 7.0.15 '@eslint/eslintrc@3.3.1': dependencies: ajv: 6.12.6 - debug: 4.4.1 + debug: 4.4.3 espree: 10.4.0 globals: 14.0.0 ignore: 5.3.2 @@ -13980,9 +13992,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.30.1': {} - - '@eslint/js@9.33.0': {} + '@eslint/js@9.37.0': {} '@eslint/object-schema@2.1.6': {} @@ -13991,11 +14001,12 @@ snapshots: '@eslint/core': 0.15.2 levn: 0.4.1 - '@exodus/schemasafe@1.3.0': {} + '@eslint/plugin-kit@0.4.0': + dependencies: + '@eslint/core': 0.16.0 + levn: 0.4.1 - '@faker-js/faker@5.5.3': {} - - '@faker-js/faker@9.9.0': {} + '@faker-js/faker@10.0.0': {} '@fig/complete-commander@3.2.0(commander@11.1.0)': dependencies: @@ -14006,17 +14017,17 @@ snapshots: dependencies: '@floating-ui/utils': 0.2.10 - '@floating-ui/dom@1.7.3': + '@floating-ui/dom@1.7.4': dependencies: '@floating-ui/core': 1.7.3 '@floating-ui/utils': 0.2.10 '@floating-ui/utils@0.2.10': {} - '@formatjs/ecma402-abstract@2.3.4': + '@formatjs/ecma402-abstract@2.3.5': dependencies: '@formatjs/fast-memoize': 2.2.7 - '@formatjs/intl-localematcher': 0.6.1 + '@formatjs/intl-localematcher': 0.6.2 decimal.js: 10.6.0 tslib: 2.8.1 @@ -14024,30 +14035,30 @@ snapshots: dependencies: tslib: 2.8.1 - '@formatjs/icu-messageformat-parser@2.11.2': + '@formatjs/icu-messageformat-parser@2.11.3': dependencies: - '@formatjs/ecma402-abstract': 2.3.4 - '@formatjs/icu-skeleton-parser': 1.8.14 + '@formatjs/ecma402-abstract': 2.3.5 + '@formatjs/icu-skeleton-parser': 1.8.15 tslib: 2.8.1 - '@formatjs/icu-skeleton-parser@1.8.14': + '@formatjs/icu-skeleton-parser@1.8.15': dependencies: - '@formatjs/ecma402-abstract': 2.3.4 + '@formatjs/ecma402-abstract': 2.3.5 tslib: 2.8.1 - '@formatjs/intl-localematcher@0.6.1': + '@formatjs/intl-localematcher@0.6.2': dependencies: tslib: 2.8.1 - '@golevelup/nestjs-discovery@4.0.3(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6)': + '@golevelup/nestjs-discovery@5.0.0(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6)': dependencies: '@nestjs/common': 11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/core': 11.1.6(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.6)(@nestjs/websockets@11.1.6)(reflect-metadata@0.2.2)(rxjs@7.8.2) lodash: 4.17.21 - '@grpc/grpc-js@1.13.4': + '@grpc/grpc-js@1.14.0': dependencies: - '@grpc/proto-loader': 0.7.15 + '@grpc/proto-loader': 0.8.0 '@js-sdsl/ordered-map': 4.4.2 '@grpc/proto-loader@0.7.15': @@ -14057,6 +14068,13 @@ snapshots: protobufjs: 7.5.4 yargs: 17.7.2 + '@grpc/proto-loader@0.8.0': + dependencies: + lodash.camelcase: 4.3.0 + long: 5.3.2 + protobufjs: 7.5.4 + yargs: 17.7.2 + '@hapi/hoek@9.3.0': {} '@hapi/topo@5.1.0': @@ -14065,135 +14083,138 @@ snapshots: '@humanfs/core@0.19.1': {} - '@humanfs/node@0.16.6': + '@humanfs/node@0.16.7': dependencies: '@humanfs/core': 0.19.1 - '@humanwhocodes/retry': 0.3.1 + '@humanwhocodes/retry': 0.4.3 '@humanwhocodes/module-importer@1.0.1': {} - '@humanwhocodes/retry@0.3.1': {} - '@humanwhocodes/retry@0.4.3': {} - '@img/sharp-darwin-arm64@0.34.3': + '@img/colour@1.0.0': {} + + '@img/sharp-darwin-arm64@0.34.4': optionalDependencies: - '@img/sharp-libvips-darwin-arm64': 1.2.0 + '@img/sharp-libvips-darwin-arm64': 1.2.3 optional: true - '@img/sharp-darwin-x64@0.34.3': + '@img/sharp-darwin-x64@0.34.4': optionalDependencies: - '@img/sharp-libvips-darwin-x64': 1.2.0 + '@img/sharp-libvips-darwin-x64': 1.2.3 optional: true - '@img/sharp-libvips-darwin-arm64@1.2.0': + '@img/sharp-libvips-darwin-arm64@1.2.3': optional: true - '@img/sharp-libvips-darwin-x64@1.2.0': + '@img/sharp-libvips-darwin-x64@1.2.3': optional: true - '@img/sharp-libvips-linux-arm64@1.2.0': + '@img/sharp-libvips-linux-arm64@1.2.3': optional: true - '@img/sharp-libvips-linux-arm@1.2.0': + '@img/sharp-libvips-linux-arm@1.2.3': optional: true - '@img/sharp-libvips-linux-ppc64@1.2.0': + '@img/sharp-libvips-linux-ppc64@1.2.3': optional: true - '@img/sharp-libvips-linux-s390x@1.2.0': + '@img/sharp-libvips-linux-s390x@1.2.3': optional: true - '@img/sharp-libvips-linux-x64@1.2.0': + '@img/sharp-libvips-linux-x64@1.2.3': optional: true - '@img/sharp-libvips-linuxmusl-arm64@1.2.0': + '@img/sharp-libvips-linuxmusl-arm64@1.2.3': optional: true - '@img/sharp-libvips-linuxmusl-x64@1.2.0': + '@img/sharp-libvips-linuxmusl-x64@1.2.3': optional: true - '@img/sharp-linux-arm64@0.34.3': + '@img/sharp-linux-arm64@0.34.4': optionalDependencies: - '@img/sharp-libvips-linux-arm64': 1.2.0 + '@img/sharp-libvips-linux-arm64': 1.2.3 optional: true - '@img/sharp-linux-arm@0.34.3': + '@img/sharp-linux-arm@0.34.4': optionalDependencies: - '@img/sharp-libvips-linux-arm': 1.2.0 + '@img/sharp-libvips-linux-arm': 1.2.3 optional: true - '@img/sharp-linux-ppc64@0.34.3': + '@img/sharp-linux-ppc64@0.34.4': optionalDependencies: - '@img/sharp-libvips-linux-ppc64': 1.2.0 + '@img/sharp-libvips-linux-ppc64': 1.2.3 optional: true - '@img/sharp-linux-s390x@0.34.3': + '@img/sharp-linux-s390x@0.34.4': optionalDependencies: - '@img/sharp-libvips-linux-s390x': 1.2.0 + '@img/sharp-libvips-linux-s390x': 1.2.3 optional: true - '@img/sharp-linux-x64@0.34.3': + '@img/sharp-linux-x64@0.34.4': optionalDependencies: - '@img/sharp-libvips-linux-x64': 1.2.0 + '@img/sharp-libvips-linux-x64': 1.2.3 optional: true - '@img/sharp-linuxmusl-arm64@0.34.3': + '@img/sharp-linuxmusl-arm64@0.34.4': optionalDependencies: - '@img/sharp-libvips-linuxmusl-arm64': 1.2.0 + '@img/sharp-libvips-linuxmusl-arm64': 1.2.3 optional: true - '@img/sharp-linuxmusl-x64@0.34.3': + '@img/sharp-linuxmusl-x64@0.34.4': optionalDependencies: - '@img/sharp-libvips-linuxmusl-x64': 1.2.0 + '@img/sharp-libvips-linuxmusl-x64': 1.2.3 optional: true - '@img/sharp-wasm32@0.34.3': + '@img/sharp-wasm32@0.34.4': dependencies: '@emnapi/runtime': 1.5.0 optional: true - '@img/sharp-win32-arm64@0.34.3': + '@img/sharp-win32-arm64@0.34.4': optional: true - '@img/sharp-win32-ia32@0.34.3': + '@img/sharp-win32-ia32@0.34.4': optional: true - '@img/sharp-win32-x64@0.34.3': + '@img/sharp-win32-x64@0.34.4': optional: true - '@immich/ui@0.24.1(@internationalized/date@3.8.2)(svelte@5.35.5)': + '@immich/ui@0.34.2(@internationalized/date@3.8.2)(svelte@5.39.11)': dependencies: '@mdi/js': 7.4.47 - bits-ui: 2.9.4(@internationalized/date@3.8.2)(svelte@5.35.5) - svelte: 5.35.5 + bits-ui: 2.9.8(@internationalized/date@3.8.2)(svelte@5.39.11) + luxon: 3.7.2 + simple-icons: 15.16.1 + svelte: 5.39.11 + svelte-highlight: 7.8.4 tailwind-merge: 3.3.1 - tailwind-variants: 2.1.0(tailwind-merge@3.3.1)(tailwindcss@4.1.12) - tailwindcss: 4.1.12 + tailwind-variants: 3.1.1(tailwind-merge@3.3.1)(tailwindcss@4.1.14) + tailwindcss: 4.1.14 transitivePeerDependencies: - '@internationalized/date' - '@inquirer/checkbox@4.2.1(@types/node@22.18.1)': + '@inquirer/checkbox@4.2.1(@types/node@22.18.10)': dependencies: - '@inquirer/core': 10.1.15(@types/node@22.18.1) + '@inquirer/core': 10.1.15(@types/node@22.18.10) '@inquirer/figures': 1.0.13 - '@inquirer/type': 3.0.8(@types/node@22.18.1) + '@inquirer/type': 3.0.8(@types/node@22.18.10) ansi-escapes: 4.3.2 yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 - '@inquirer/confirm@5.1.15(@types/node@22.18.1)': + '@inquirer/confirm@5.1.15(@types/node@22.18.10)': dependencies: - '@inquirer/core': 10.1.15(@types/node@22.18.1) - '@inquirer/type': 3.0.8(@types/node@22.18.1) + '@inquirer/core': 10.1.15(@types/node@22.18.10) + '@inquirer/type': 3.0.8(@types/node@22.18.10) optionalDependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 - '@inquirer/core@10.1.15(@types/node@22.18.1)': + '@inquirer/core@10.1.15(@types/node@22.18.10)': dependencies: '@inquirer/figures': 1.0.13 - '@inquirer/type': 3.0.8(@types/node@22.18.1) + '@inquirer/type': 3.0.8(@types/node@22.18.10) ansi-escapes: 4.3.2 cli-width: 4.1.0 mute-stream: 2.0.0 @@ -14201,121 +14222,121 @@ snapshots: wrap-ansi: 6.2.0 yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 - '@inquirer/editor@4.2.17(@types/node@22.18.1)': + '@inquirer/editor@4.2.17(@types/node@22.18.10)': dependencies: - '@inquirer/core': 10.1.15(@types/node@22.18.1) - '@inquirer/external-editor': 1.0.1(@types/node@22.18.1) - '@inquirer/type': 3.0.8(@types/node@22.18.1) + '@inquirer/core': 10.1.15(@types/node@22.18.10) + '@inquirer/external-editor': 1.0.2(@types/node@22.18.10) + '@inquirer/type': 3.0.8(@types/node@22.18.10) optionalDependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 - '@inquirer/expand@4.0.17(@types/node@22.18.1)': + '@inquirer/expand@4.0.17(@types/node@22.18.10)': dependencies: - '@inquirer/core': 10.1.15(@types/node@22.18.1) - '@inquirer/type': 3.0.8(@types/node@22.18.1) + '@inquirer/core': 10.1.15(@types/node@22.18.10) + '@inquirer/type': 3.0.8(@types/node@22.18.10) yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 - '@inquirer/external-editor@1.0.1(@types/node@22.18.1)': + '@inquirer/external-editor@1.0.2(@types/node@22.18.10)': dependencies: chardet: 2.1.0 - iconv-lite: 0.6.3 + iconv-lite: 0.7.0 optionalDependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@inquirer/figures@1.0.13': {} - '@inquirer/input@4.2.1(@types/node@22.18.1)': + '@inquirer/input@4.2.1(@types/node@22.18.10)': dependencies: - '@inquirer/core': 10.1.15(@types/node@22.18.1) - '@inquirer/type': 3.0.8(@types/node@22.18.1) + '@inquirer/core': 10.1.15(@types/node@22.18.10) + '@inquirer/type': 3.0.8(@types/node@22.18.10) optionalDependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 - '@inquirer/number@3.0.17(@types/node@22.18.1)': + '@inquirer/number@3.0.17(@types/node@22.18.10)': dependencies: - '@inquirer/core': 10.1.15(@types/node@22.18.1) - '@inquirer/type': 3.0.8(@types/node@22.18.1) + '@inquirer/core': 10.1.15(@types/node@22.18.10) + '@inquirer/type': 3.0.8(@types/node@22.18.10) optionalDependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 - '@inquirer/password@4.0.17(@types/node@22.18.1)': + '@inquirer/password@4.0.17(@types/node@22.18.10)': dependencies: - '@inquirer/core': 10.1.15(@types/node@22.18.1) - '@inquirer/type': 3.0.8(@types/node@22.18.1) + '@inquirer/core': 10.1.15(@types/node@22.18.10) + '@inquirer/type': 3.0.8(@types/node@22.18.10) ansi-escapes: 4.3.2 optionalDependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 - '@inquirer/prompts@7.3.2(@types/node@22.18.1)': + '@inquirer/prompts@7.3.2(@types/node@22.18.10)': dependencies: - '@inquirer/checkbox': 4.2.1(@types/node@22.18.1) - '@inquirer/confirm': 5.1.15(@types/node@22.18.1) - '@inquirer/editor': 4.2.17(@types/node@22.18.1) - '@inquirer/expand': 4.0.17(@types/node@22.18.1) - '@inquirer/input': 4.2.1(@types/node@22.18.1) - '@inquirer/number': 3.0.17(@types/node@22.18.1) - '@inquirer/password': 4.0.17(@types/node@22.18.1) - '@inquirer/rawlist': 4.1.5(@types/node@22.18.1) - '@inquirer/search': 3.1.0(@types/node@22.18.1) - '@inquirer/select': 4.3.1(@types/node@22.18.1) + '@inquirer/checkbox': 4.2.1(@types/node@22.18.10) + '@inquirer/confirm': 5.1.15(@types/node@22.18.10) + '@inquirer/editor': 4.2.17(@types/node@22.18.10) + '@inquirer/expand': 4.0.17(@types/node@22.18.10) + '@inquirer/input': 4.2.1(@types/node@22.18.10) + '@inquirer/number': 3.0.17(@types/node@22.18.10) + '@inquirer/password': 4.0.17(@types/node@22.18.10) + '@inquirer/rawlist': 4.1.5(@types/node@22.18.10) + '@inquirer/search': 3.1.0(@types/node@22.18.10) + '@inquirer/select': 4.3.1(@types/node@22.18.10) optionalDependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 - '@inquirer/prompts@7.8.0(@types/node@22.18.1)': + '@inquirer/prompts@7.8.0(@types/node@22.18.10)': dependencies: - '@inquirer/checkbox': 4.2.1(@types/node@22.18.1) - '@inquirer/confirm': 5.1.15(@types/node@22.18.1) - '@inquirer/editor': 4.2.17(@types/node@22.18.1) - '@inquirer/expand': 4.0.17(@types/node@22.18.1) - '@inquirer/input': 4.2.1(@types/node@22.18.1) - '@inquirer/number': 3.0.17(@types/node@22.18.1) - '@inquirer/password': 4.0.17(@types/node@22.18.1) - '@inquirer/rawlist': 4.1.5(@types/node@22.18.1) - '@inquirer/search': 3.1.0(@types/node@22.18.1) - '@inquirer/select': 4.3.1(@types/node@22.18.1) + '@inquirer/checkbox': 4.2.1(@types/node@22.18.10) + '@inquirer/confirm': 5.1.15(@types/node@22.18.10) + '@inquirer/editor': 4.2.17(@types/node@22.18.10) + '@inquirer/expand': 4.0.17(@types/node@22.18.10) + '@inquirer/input': 4.2.1(@types/node@22.18.10) + '@inquirer/number': 3.0.17(@types/node@22.18.10) + '@inquirer/password': 4.0.17(@types/node@22.18.10) + '@inquirer/rawlist': 4.1.5(@types/node@22.18.10) + '@inquirer/search': 3.1.0(@types/node@22.18.10) + '@inquirer/select': 4.3.1(@types/node@22.18.10) optionalDependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 - '@inquirer/rawlist@4.1.5(@types/node@22.18.1)': + '@inquirer/rawlist@4.1.5(@types/node@22.18.10)': dependencies: - '@inquirer/core': 10.1.15(@types/node@22.18.1) - '@inquirer/type': 3.0.8(@types/node@22.18.1) + '@inquirer/core': 10.1.15(@types/node@22.18.10) + '@inquirer/type': 3.0.8(@types/node@22.18.10) yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 - '@inquirer/search@3.1.0(@types/node@22.18.1)': + '@inquirer/search@3.1.0(@types/node@22.18.10)': dependencies: - '@inquirer/core': 10.1.15(@types/node@22.18.1) + '@inquirer/core': 10.1.15(@types/node@22.18.10) '@inquirer/figures': 1.0.13 - '@inquirer/type': 3.0.8(@types/node@22.18.1) + '@inquirer/type': 3.0.8(@types/node@22.18.10) yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 - '@inquirer/select@4.3.1(@types/node@22.18.1)': + '@inquirer/select@4.3.1(@types/node@22.18.10)': dependencies: - '@inquirer/core': 10.1.15(@types/node@22.18.1) + '@inquirer/core': 10.1.15(@types/node@22.18.10) '@inquirer/figures': 1.0.13 - '@inquirer/type': 3.0.8(@types/node@22.18.1) + '@inquirer/type': 3.0.8(@types/node@22.18.10) ansi-escapes: 4.3.2 yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 - '@inquirer/type@3.0.8(@types/node@22.18.1)': + '@inquirer/type@3.0.8(@types/node@22.18.10)': optionalDependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@internationalized/date@3.8.2': dependencies: '@swc/helpers': 0.5.17 - '@ioredis/commands@1.3.0': {} + '@ioredis/commands@1.4.0': {} '@isaacs/balanced-match@4.0.1': {} @@ -14327,7 +14348,7 @@ snapshots: dependencies: string-width: 5.1.2 string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 strip-ansi-cjs: strip-ansi@6.0.1 wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 @@ -14347,55 +14368,90 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/yargs': 17.0.33 chalk: 4.1.2 '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - '@jridgewell/trace-mapping': 0.3.30 + '@jridgewell/trace-mapping': 0.3.31 '@jridgewell/remapping@2.3.5': dependencies: '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.30 + '@jridgewell/trace-mapping': 0.3.31 '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/source-map@0.3.6': dependencies: '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.30 + '@jridgewell/trace-mapping': 0.3.31 '@jridgewell/sourcemap-codec@1.5.5': {} - '@jridgewell/trace-mapping@0.3.30': + '@jridgewell/trace-mapping@0.3.31': dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 '@js-sdsl/ordered-map@4.4.2': {} + '@jsonjoy.com/base64@1.1.2(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/buffers@1.2.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/codegen@1.0.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/json-pack@1.20.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/base64': 1.1.2(tslib@2.8.1) + '@jsonjoy.com/buffers': 1.2.0(tslib@2.8.1) + '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) + '@jsonjoy.com/json-pointer': 1.0.2(tslib@2.8.1) + '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) + hyperdyperid: 1.2.0 + thingies: 2.5.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/json-pointer@1.0.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) + '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/util@1.9.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/buffers': 1.2.0(tslib@2.8.1) + '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) + tslib: 2.8.1 + '@koa/cors@5.0.0': dependencies: vary: 1.1.2 '@koa/router@14.0.0': dependencies: - debug: 4.4.1 + debug: 4.4.3 http-errors: 2.0.0 koa-compose: 4.1.0 - path-to-regexp: 8.2.0 + path-to-regexp: 8.3.0 transitivePeerDependencies: - supports-color - '@koddsson/eslint-plugin-tscompat@0.2.0(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2)': + '@koddsson/eslint-plugin-tscompat@0.2.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@mdn/browser-compat-data': 6.0.27 - '@typescript-eslint/type-utils': 8.39.1(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2) - '@typescript-eslint/utils': 8.39.1(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2) - browserslist: 4.25.3 + '@typescript-eslint/type-utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) + browserslist: 4.26.3 transitivePeerDependencies: - eslint - supports-color @@ -14424,14 +14480,14 @@ snapshots: '@mapbox/node-pre-gyp@1.0.11': dependencies: - detect-libc: 2.0.4 + detect-libc: 2.1.2 https-proxy-agent: 5.0.1 make-dir: 3.1.0 node-fetch: 2.7.0 nopt: 5.0.0 npmlog: 5.0.1 rimraf: 3.0.2 - semver: 7.7.2 + semver: 7.7.3 tar: 6.2.1 transitivePeerDependencies: - encoding @@ -14440,14 +14496,14 @@ snapshots: '@mapbox/node-pre-gyp@1.0.11(encoding@0.1.13)': dependencies: - detect-libc: 2.0.4 + detect-libc: 2.1.2 https-proxy-agent: 5.0.1 make-dir: 3.1.0 node-fetch: 2.7.0(encoding@0.1.13) nopt: 5.0.0 npmlog: 5.0.1 rimraf: 3.0.2 - semver: 7.7.2 + semver: 7.7.3 tar: 6.2.1 transitivePeerDependencies: - encoding @@ -14477,7 +14533,7 @@ snapshots: '@mapbox/whoots-js@3.1.0': {} - '@maplibre/maplibre-gl-style-spec@23.3.0': + '@maplibre/maplibre-gl-style-spec@24.2.0': dependencies: '@mapbox/jsonlint-lines-primitives': 2.0.2 '@mapbox/unitbezier': 0.0.1 @@ -14507,12 +14563,13 @@ snapshots: '@mdn/browser-compat-data@6.0.27': {} - '@mdx-js/mdx@3.1.0(acorn@8.15.0)': + '@mdx-js/mdx@3.1.1': dependencies: '@types/estree': 1.0.8 '@types/estree-jsx': 1.0.5 '@types/hast': 3.0.4 '@types/mdx': 2.0.13 + acorn: 8.15.0 collapse-white-space: 2.1.0 devlop: 1.1.0 estree-util-is-identifier-name: 3.0.0 @@ -14521,41 +14578,29 @@ snapshots: hast-util-to-jsx-runtime: 2.3.6 markdown-extensions: 2.0.0 recma-build-jsx: 1.0.0 - recma-jsx: 1.0.0(acorn@8.15.0) + recma-jsx: 1.0.1(acorn@8.15.0) recma-stringify: 1.0.0 rehype-recma: 1.0.0 - remark-mdx: 3.1.0 + remark-mdx: 3.1.1 remark-parse: 11.0.0 remark-rehype: 11.1.2 - source-map: 0.7.4 + source-map: 0.7.6 unified: 11.0.5 unist-util-position-from-estree: 2.0.0 unist-util-stringify-position: 4.0.0 unist-util-visit: 5.0.0 vfile: 6.0.3 transitivePeerDependencies: - - acorn - supports-color - '@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1)': + '@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1)': dependencies: '@types/mdx': 2.0.13 - '@types/react': 19.1.12 + '@types/react': 19.2.2 react: 18.3.1 '@microsoft/tsdoc@0.15.1': {} - '@monaco-editor/loader@1.5.0': - dependencies: - state-local: 1.0.7 - - '@monaco-editor/react@4.7.0(monaco-editor@0.31.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@monaco-editor/loader': 1.5.0 - monaco-editor: 0.31.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': optional: true @@ -14582,26 +14627,26 @@ snapshots: '@nestjs/core': 11.1.6(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.6)(@nestjs/websockets@11.1.6)(reflect-metadata@0.2.2)(rxjs@7.8.2) tslib: 2.8.1 - '@nestjs/bullmq@11.0.3(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6)(bullmq@5.57.0)': + '@nestjs/bullmq@11.0.3(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6)(bullmq@5.61.0)': dependencies: '@nestjs/bull-shared': 11.0.3(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6) '@nestjs/common': 11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/core': 11.1.6(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.6)(@nestjs/websockets@11.1.6)(reflect-metadata@0.2.2)(rxjs@7.8.2) - bullmq: 5.57.0 + bullmq: 5.61.0 tslib: 2.8.1 - '@nestjs/cli@11.0.10(@swc/core@1.13.3(@swc/helpers@0.5.17))(@types/node@22.18.1)': + '@nestjs/cli@11.0.10(@swc/core@1.13.5(@swc/helpers@0.5.17))(@types/node@22.18.10)': dependencies: '@angular-devkit/core': 19.2.15(chokidar@4.0.3) '@angular-devkit/schematics': 19.2.15(chokidar@4.0.3) - '@angular-devkit/schematics-cli': 19.2.15(@types/node@22.18.1)(chokidar@4.0.3) - '@inquirer/prompts': 7.8.0(@types/node@22.18.1) - '@nestjs/schematics': 11.0.7(chokidar@4.0.3)(typescript@5.8.3) + '@angular-devkit/schematics-cli': 19.2.15(@types/node@22.18.10)(chokidar@4.0.3) + '@inquirer/prompts': 7.8.0(@types/node@22.18.10) + '@nestjs/schematics': 11.0.8(chokidar@4.0.3)(typescript@5.8.3) ansis: 4.1.0 chokidar: 4.0.3 cli-table3: 0.6.5 commander: 4.1.1 - fork-ts-checker-webpack-plugin: 9.1.0(typescript@5.8.3)(webpack@5.100.2(@swc/core@1.13.3(@swc/helpers@0.5.17))) + fork-ts-checker-webpack-plugin: 9.1.0(typescript@5.8.3)(webpack@5.100.2(@swc/core@1.13.5(@swc/helpers@0.5.17))) glob: 11.0.3 node-emoji: 1.11.0 ora: 5.4.1 @@ -14609,10 +14654,10 @@ snapshots: tsconfig-paths: 4.2.0 tsconfig-paths-webpack-plugin: 4.2.0 typescript: 5.8.3 - webpack: 5.100.2(@swc/core@1.13.3(@swc/helpers@0.5.17)) + webpack: 5.100.2(@swc/core@1.13.5(@swc/helpers@0.5.17)) webpack-node-externals: 3.0.0 optionalDependencies: - '@swc/core': 1.13.3(@swc/helpers@0.5.17) + '@swc/core': 1.13.5(@swc/helpers@0.5.17) transitivePeerDependencies: - '@types/node' - esbuild @@ -14649,12 +14694,6 @@ snapshots: '@nestjs/platform-express': 11.1.6(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6) '@nestjs/websockets': 11.1.6(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6)(@nestjs/platform-socket.io@11.1.6)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/event-emitter@3.0.1(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6)': - dependencies: - '@nestjs/common': 11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/core': 11.1.6(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.6)(@nestjs/websockets@11.1.6)(reflect-metadata@0.2.2)(rxjs@7.8.2) - eventemitter2: 6.4.9 - '@nestjs/mapped-types@2.1.0(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)': dependencies: '@nestjs/common': 11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2) @@ -14687,31 +14726,31 @@ snapshots: - supports-color - utf-8-validate - '@nestjs/schedule@6.0.0(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6)': + '@nestjs/schedule@6.0.1(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6)': dependencies: '@nestjs/common': 11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/core': 11.1.6(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.6)(@nestjs/websockets@11.1.6)(reflect-metadata@0.2.2)(rxjs@7.8.2) - cron: 4.3.0 + cron: 4.3.3 - '@nestjs/schematics@11.0.7(chokidar@4.0.3)(typescript@5.8.3)': + '@nestjs/schematics@11.0.8(chokidar@4.0.3)(typescript@5.8.3)': dependencies: - '@angular-devkit/core': 19.2.15(chokidar@4.0.3) - '@angular-devkit/schematics': 19.2.15(chokidar@4.0.3) - comment-json: 4.2.5 + '@angular-devkit/core': 19.2.17(chokidar@4.0.3) + '@angular-devkit/schematics': 19.2.17(chokidar@4.0.3) + comment-json: 4.4.1 jsonc-parser: 3.3.1 pluralize: 8.0.0 typescript: 5.8.3 transitivePeerDependencies: - chokidar - '@nestjs/schematics@11.0.7(chokidar@4.0.3)(typescript@5.9.2)': + '@nestjs/schematics@11.0.8(chokidar@4.0.3)(typescript@5.9.3)': dependencies: - '@angular-devkit/core': 19.2.15(chokidar@4.0.3) - '@angular-devkit/schematics': 19.2.15(chokidar@4.0.3) - comment-json: 4.2.5 + '@angular-devkit/core': 19.2.17(chokidar@4.0.3) + '@angular-devkit/schematics': 19.2.17(chokidar@4.0.3) + comment-json: 4.4.1 jsonc-parser: 3.3.1 pluralize: 8.0.0 - typescript: 5.9.2 + typescript: 5.9.3 transitivePeerDependencies: - chokidar @@ -14776,7 +14815,7 @@ snapshots: '@npmcli/fs@4.0.0': dependencies: - semver: 7.7.2 + semver: 7.7.3 '@nuxt/opencollective@0.4.1': dependencies: @@ -14784,712 +14823,310 @@ snapshots: '@oazapfts/runtime@1.0.4': {} - '@opentelemetry/api-logs@0.203.0': + '@opentelemetry/api-logs@0.206.0': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/api@1.9.0': {} - '@opentelemetry/auto-instrumentations-node@0.62.1(@opentelemetry/api@1.9.0)(@opentelemetry/core@2.0.1(@opentelemetry/api@1.9.0))(encoding@0.1.13)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-amqplib': 0.50.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-aws-lambda': 0.54.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-aws-sdk': 0.57.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-bunyan': 0.49.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-cassandra-driver': 0.49.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-connect': 0.47.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-cucumber': 0.18.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-dataloader': 0.21.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-dns': 0.47.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-express': 0.52.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-fastify': 0.48.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-fs': 0.23.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-generic-pool': 0.47.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-graphql': 0.51.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-grpc': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-hapi': 0.50.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-http': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-ioredis': 0.51.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-kafkajs': 0.13.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-knex': 0.48.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-koa': 0.51.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-lru-memoizer': 0.48.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-memcached': 0.47.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-mongodb': 0.56.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-mongoose': 0.50.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-mysql': 0.49.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-mysql2': 0.50.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-nestjs-core': 0.49.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-net': 0.47.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-oracledb': 0.29.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-pg': 0.56.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-pino': 0.50.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-redis': 0.51.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-restify': 0.49.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-router': 0.48.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-runtime-node': 0.17.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-socket.io': 0.50.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-tedious': 0.22.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-undici': 0.14.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-winston': 0.48.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resource-detector-alibaba-cloud': 0.31.3(@opentelemetry/api@1.9.0) - '@opentelemetry/resource-detector-aws': 2.3.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resource-detector-azure': 0.10.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resource-detector-container': 0.7.3(@opentelemetry/api@1.9.0) - '@opentelemetry/resource-detector-gcp': 0.37.0(@opentelemetry/api@1.9.0)(encoding@0.1.13) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-node': 0.203.0(@opentelemetry/api@1.9.0) - transitivePeerDependencies: - - encoding - - supports-color - - '@opentelemetry/context-async-hooks@2.0.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/context-async-hooks@2.1.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core@2.0.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/core@2.1.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/semantic-conventions': 1.37.0 - '@opentelemetry/exporter-logs-otlp-grpc@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-logs-otlp-grpc@0.206.0(@opentelemetry/api@1.9.0)': dependencies: - '@grpc/grpc-js': 1.13.4 + '@grpc/grpc-js': 1.14.0 '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-grpc-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-logs': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-grpc-exporter-base': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.206.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-logs-otlp-http@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-logs-otlp-http@0.206.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/api-logs': 0.203.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-logs': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/api-logs': 0.206.0 + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.206.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-logs-otlp-proto@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-logs-otlp-proto@0.206.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/api-logs': 0.203.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-logs': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/api-logs': 0.206.0 + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.1.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-metrics-otlp-grpc@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-metrics-otlp-grpc@0.206.0(@opentelemetry/api@1.9.0)': dependencies: - '@grpc/grpc-js': 1.13.4 + '@grpc/grpc-js': 1.14.0 '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-metrics-otlp-http': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-grpc-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-metrics-otlp-http': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-grpc-exporter-base': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 2.1.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-metrics-otlp-http@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-metrics-otlp-http@0.206.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 2.1.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-metrics-otlp-proto@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-metrics-otlp-proto@0.206.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-metrics-otlp-http': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-metrics-otlp-http': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 2.1.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-prometheus@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-prometheus@0.206.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 2.1.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-trace-otlp-grpc@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-trace-otlp-grpc@0.206.0(@opentelemetry/api@1.9.0)': dependencies: - '@grpc/grpc-js': 1.13.4 + '@grpc/grpc-js': 1.14.0 '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-grpc-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-grpc-exporter-base': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.1.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-trace-otlp-http@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-trace-otlp-http@0.206.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.1.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-trace-otlp-proto@0.203.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-trace-otlp-proto@0.206.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.1.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-zipkin@2.0.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/exporter-zipkin@2.1.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 '@opentelemetry/host-metrics@0.36.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 systeminformation: 5.23.8 - '@opentelemetry/instrumentation-amqplib@0.50.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-http@0.206.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-aws-lambda@0.54.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - '@types/aws-lambda': 8.10.150 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-aws-sdk@0.57.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/propagation-utils': 0.31.3(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-bunyan@0.49.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/api-logs': 0.203.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@types/bunyan': 1.8.11 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-cassandra-driver@0.49.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-connect@0.47.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - '@types/connect': 3.4.38 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-cucumber@0.18.1(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-dataloader@0.21.1(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-dns@0.47.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-express@0.52.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-fastify@0.48.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-fs@0.23.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-generic-pool@0.47.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-graphql@0.51.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-grpc@0.203.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-hapi@0.50.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-http@0.203.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 forwarded-parse: 2.1.2 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-ioredis@0.51.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-ioredis@0.54.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/redis-common': 0.38.0 - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/instrumentation': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/redis-common': 0.38.2 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-kafkajs@0.13.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-nestjs-core@0.53.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/instrumentation': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-knex@0.48.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation-pg@0.59.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-koa@0.51.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-lru-memoizer@0.48.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-memcached@0.47.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - '@types/memcached': 2.2.10 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-mongodb@0.56.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-mongoose@0.50.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-mysql2@0.50.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - '@opentelemetry/sql-common': 0.41.0(@opentelemetry/api@1.9.0) - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-mysql@0.49.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - '@types/mysql': 2.15.27 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-nestjs-core@0.49.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-net@0.47.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-oracledb@0.29.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - '@types/oracledb': 6.5.2 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-pg@0.56.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - '@opentelemetry/sql-common': 0.41.0(@opentelemetry/api@1.9.0) - '@types/pg': 8.15.4 + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 + '@opentelemetry/sql-common': 0.41.2(@opentelemetry/api@1.9.0) + '@types/pg': 8.15.5 '@types/pg-pool': 2.0.6 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-pino@0.50.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/instrumentation@0.206.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/api-logs': 0.203.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) + '@opentelemetry/api-logs': 0.206.0 + import-in-the-middle: 1.14.4 + require-in-the-middle: 8.0.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-redis@0.51.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/otlp-exporter-base@0.206.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/redis-common': 0.38.0 - '@opentelemetry/semantic-conventions': 1.36.0 - transitivePeerDependencies: - - supports-color + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.206.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-restify@0.49.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/otlp-grpc-exporter-base@0.206.0(@opentelemetry/api@1.9.0)': dependencies: + '@grpc/grpc-js': 1.14.0 '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - transitivePeerDependencies: - - supports-color + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.206.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-router@0.48.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/otlp-transformer@0.206.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-runtime-node@0.17.1(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-socket.io@0.50.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-tedious@0.22.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - '@types/tedious': 4.0.14 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-undici@0.14.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation-winston@0.48.1(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/api-logs': 0.203.0 - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - transitivePeerDependencies: - - supports-color - - '@opentelemetry/instrumentation@0.203.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/api-logs': 0.203.0 - import-in-the-middle: 1.14.2 - require-in-the-middle: 7.5.2 - transitivePeerDependencies: - - supports-color - - '@opentelemetry/otlp-exporter-base@0.203.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) - - '@opentelemetry/otlp-grpc-exporter-base@0.203.0(@opentelemetry/api@1.9.0)': - dependencies: - '@grpc/grpc-js': 1.13.4 - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-exporter-base': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/otlp-transformer': 0.203.0(@opentelemetry/api@1.9.0) - - '@opentelemetry/otlp-transformer@0.203.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/api-logs': 0.203.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-logs': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/api-logs': 0.206.0 + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.1.0(@opentelemetry/api@1.9.0) protobufjs: 7.5.4 - '@opentelemetry/propagation-utils@0.31.3(@opentelemetry/api@1.9.0)': + '@opentelemetry/propagator-b3@2.1.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) - '@opentelemetry/propagator-b3@2.0.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/propagator-jaeger@2.1.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) - '@opentelemetry/propagator-jaeger@2.0.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/redis-common@0.38.2': {} + + '@opentelemetry/resources@2.1.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 - '@opentelemetry/redis-common@0.38.0': {} - - '@opentelemetry/resource-detector-alibaba-cloud@0.31.3(@opentelemetry/api@1.9.0)': + '@opentelemetry/sdk-logs@0.206.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/api-logs': 0.206.0 + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.1.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resource-detector-aws@2.3.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/sdk-metrics@2.1.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.1.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resource-detector-azure@0.10.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/sdk-node@0.206.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - - '@opentelemetry/resource-detector-container@0.7.3(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - - '@opentelemetry/resource-detector-gcp@0.37.0(@opentelemetry/api@1.9.0)(encoding@0.1.13)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - gcp-metadata: 6.1.1(encoding@0.1.13) - transitivePeerDependencies: - - encoding - - supports-color - - '@opentelemetry/resources@2.0.1(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 - - '@opentelemetry/sdk-logs@0.203.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/api-logs': 0.203.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - - '@opentelemetry/sdk-metrics@2.0.1(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - - '@opentelemetry/sdk-node@0.203.0(@opentelemetry/api@1.9.0)': - dependencies: - '@opentelemetry/api': 1.9.0 - '@opentelemetry/api-logs': 0.203.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-logs-otlp-grpc': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-logs-otlp-http': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-logs-otlp-proto': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-metrics-otlp-grpc': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-metrics-otlp-http': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-metrics-otlp-proto': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-prometheus': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-trace-otlp-grpc': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-trace-otlp-http': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-trace-otlp-proto': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/exporter-zipkin': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/propagator-b3': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/propagator-jaeger': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-logs': 0.203.0(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-metrics': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-node': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/api-logs': 0.206.0 + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-logs-otlp-grpc': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-logs-otlp-http': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-logs-otlp-proto': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-metrics-otlp-grpc': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-metrics-otlp-http': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-metrics-otlp-proto': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-prometheus': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-trace-otlp-grpc': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-trace-otlp-http': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-trace-otlp-proto': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-zipkin': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/propagator-b3': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/propagator-jaeger': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.206.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-node': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 transitivePeerDependencies: - supports-color - '@opentelemetry/sdk-trace-base@2.0.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/sdk-trace-base@2.1.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.36.0 + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.37.0 - '@opentelemetry/sdk-trace-node@2.0.1(@opentelemetry/api@1.9.0)': + '@opentelemetry/sdk-trace-node@2.1.0(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/context-async-hooks': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/context-async-hooks': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 2.1.0(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions@1.36.0': {} + '@opentelemetry/semantic-conventions@1.37.0': {} - '@opentelemetry/sql-common@0.41.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/sql-common@0.41.2(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/core': 2.0.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) '@paralleldrive/cuid2@2.2.2': dependencies: '@noble/hashes': 1.8.0 - '@photo-sphere-viewer/core@5.13.4': + '@photo-sphere-viewer/core@5.14.0': dependencies: - three: 0.175.0 - - '@photo-sphere-viewer/equirectangular-video-adapter@5.13.4(@photo-sphere-viewer/core@5.13.4)(@photo-sphere-viewer/video-plugin@5.13.4(@photo-sphere-viewer/core@5.13.4))': - dependencies: - '@photo-sphere-viewer/core': 5.13.4 - '@photo-sphere-viewer/video-plugin': 5.13.4(@photo-sphere-viewer/core@5.13.4) three: 0.179.1 - '@photo-sphere-viewer/resolution-plugin@5.13.4(@photo-sphere-viewer/core@5.13.4)(@photo-sphere-viewer/settings-plugin@5.13.4(@photo-sphere-viewer/core@5.13.4))': + '@photo-sphere-viewer/equirectangular-video-adapter@5.14.0(@photo-sphere-viewer/core@5.14.0)(@photo-sphere-viewer/video-plugin@5.14.0(@photo-sphere-viewer/core@5.14.0))': dependencies: - '@photo-sphere-viewer/core': 5.13.4 - '@photo-sphere-viewer/settings-plugin': 5.13.4(@photo-sphere-viewer/core@5.13.4) + '@photo-sphere-viewer/core': 5.14.0 + '@photo-sphere-viewer/video-plugin': 5.14.0(@photo-sphere-viewer/core@5.14.0) + three: 0.180.0 - '@photo-sphere-viewer/settings-plugin@5.13.4(@photo-sphere-viewer/core@5.13.4)': + '@photo-sphere-viewer/resolution-plugin@5.14.0(@photo-sphere-viewer/core@5.14.0)(@photo-sphere-viewer/settings-plugin@5.14.0(@photo-sphere-viewer/core@5.14.0))': dependencies: - '@photo-sphere-viewer/core': 5.13.4 + '@photo-sphere-viewer/core': 5.14.0 + '@photo-sphere-viewer/settings-plugin': 5.14.0(@photo-sphere-viewer/core@5.14.0) - '@photo-sphere-viewer/video-plugin@5.13.4(@photo-sphere-viewer/core@5.13.4)': + '@photo-sphere-viewer/settings-plugin@5.14.0(@photo-sphere-viewer/core@5.14.0)': dependencies: - '@photo-sphere-viewer/core': 5.13.4 - three: 0.179.1 + '@photo-sphere-viewer/core': 5.14.0 + + '@photo-sphere-viewer/video-plugin@5.14.0(@photo-sphere-viewer/core@5.14.0)': + dependencies: + '@photo-sphere-viewer/core': 5.14.0 + three: 0.180.0 '@photostructure/tz-lookup@11.2.0': {} @@ -15498,9 +15135,9 @@ snapshots: '@pkgr/core@0.2.9': {} - '@playwright/test@1.54.2': + '@playwright/test@1.56.0': dependencies: - playwright: 1.54.2 + playwright: 1.56.0 '@pnpm/config.env-replace@1.1.0': {} @@ -15539,194 +15176,190 @@ snapshots: '@protobufjs/utf8@1.1.0': {} - '@react-email/body@0.1.0(react@19.1.1)': + '@react-email/body@0.1.0(react@19.2.0)': dependencies: - react: 19.1.1 + react: 19.2.0 - '@react-email/button@0.2.0(react@19.1.1)': + '@react-email/button@0.2.0(react@19.2.0)': dependencies: - react: 19.1.1 + react: 19.2.0 - '@react-email/code-block@0.1.0(react@19.1.1)': + '@react-email/code-block@0.1.0(react@19.2.0)': dependencies: prismjs: 1.30.0 - react: 19.1.1 + react: 19.2.0 - '@react-email/code-inline@0.0.5(react@19.1.1)': + '@react-email/code-inline@0.0.5(react@19.2.0)': dependencies: - react: 19.1.1 + react: 19.2.0 - '@react-email/column@0.0.13(react@19.1.1)': + '@react-email/column@0.0.13(react@19.2.0)': dependencies: - react: 19.1.1 + react: 19.2.0 - '@react-email/components@0.5.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@react-email/components@0.5.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@react-email/body': 0.1.0(react@19.1.1) - '@react-email/button': 0.2.0(react@19.1.1) - '@react-email/code-block': 0.1.0(react@19.1.1) - '@react-email/code-inline': 0.0.5(react@19.1.1) - '@react-email/column': 0.0.13(react@19.1.1) - '@react-email/container': 0.0.15(react@19.1.1) - '@react-email/font': 0.0.9(react@19.1.1) - '@react-email/head': 0.0.12(react@19.1.1) - '@react-email/heading': 0.0.15(react@19.1.1) - '@react-email/hr': 0.0.11(react@19.1.1) - '@react-email/html': 0.0.11(react@19.1.1) - '@react-email/img': 0.0.11(react@19.1.1) - '@react-email/link': 0.0.12(react@19.1.1) - '@react-email/markdown': 0.0.15(react@19.1.1) - '@react-email/preview': 0.0.13(react@19.1.1) - '@react-email/render': 1.2.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) - '@react-email/row': 0.0.12(react@19.1.1) - '@react-email/section': 0.0.16(react@19.1.1) - '@react-email/tailwind': 1.2.2(react@19.1.1) - '@react-email/text': 0.1.5(react@19.1.1) - react: 19.1.1 + '@react-email/body': 0.1.0(react@19.2.0) + '@react-email/button': 0.2.0(react@19.2.0) + '@react-email/code-block': 0.1.0(react@19.2.0) + '@react-email/code-inline': 0.0.5(react@19.2.0) + '@react-email/column': 0.0.13(react@19.2.0) + '@react-email/container': 0.0.15(react@19.2.0) + '@react-email/font': 0.0.9(react@19.2.0) + '@react-email/head': 0.0.12(react@19.2.0) + '@react-email/heading': 0.0.15(react@19.2.0) + '@react-email/hr': 0.0.11(react@19.2.0) + '@react-email/html': 0.0.11(react@19.2.0) + '@react-email/img': 0.0.11(react@19.2.0) + '@react-email/link': 0.0.12(react@19.2.0) + '@react-email/markdown': 0.0.15(react@19.2.0) + '@react-email/preview': 0.0.13(react@19.2.0) + '@react-email/render': 1.3.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-email/row': 0.0.12(react@19.2.0) + '@react-email/section': 0.0.16(react@19.2.0) + '@react-email/tailwind': 1.2.2(react@19.2.0) + '@react-email/text': 0.1.5(react@19.2.0) + react: 19.2.0 transitivePeerDependencies: - react-dom - '@react-email/container@0.0.15(react@19.1.1)': + '@react-email/container@0.0.15(react@19.2.0)': dependencies: - react: 19.1.1 + react: 19.2.0 - '@react-email/font@0.0.9(react@19.1.1)': + '@react-email/font@0.0.9(react@19.2.0)': dependencies: - react: 19.1.1 + react: 19.2.0 - '@react-email/head@0.0.12(react@19.1.1)': + '@react-email/head@0.0.12(react@19.2.0)': dependencies: - react: 19.1.1 + react: 19.2.0 - '@react-email/heading@0.0.15(react@19.1.1)': + '@react-email/heading@0.0.15(react@19.2.0)': dependencies: - react: 19.1.1 + react: 19.2.0 - '@react-email/hr@0.0.11(react@19.1.1)': + '@react-email/hr@0.0.11(react@19.2.0)': dependencies: - react: 19.1.1 + react: 19.2.0 - '@react-email/html@0.0.11(react@19.1.1)': + '@react-email/html@0.0.11(react@19.2.0)': dependencies: - react: 19.1.1 + react: 19.2.0 - '@react-email/img@0.0.11(react@19.1.1)': + '@react-email/img@0.0.11(react@19.2.0)': dependencies: - react: 19.1.1 + react: 19.2.0 - '@react-email/link@0.0.12(react@19.1.1)': + '@react-email/link@0.0.12(react@19.2.0)': dependencies: - react: 19.1.1 + react: 19.2.0 - '@react-email/markdown@0.0.15(react@19.1.1)': + '@react-email/markdown@0.0.15(react@19.2.0)': dependencies: - md-to-react-email: 5.0.5(react@19.1.1) - react: 19.1.1 + md-to-react-email: 5.0.5(react@19.2.0) + react: 19.2.0 - '@react-email/preview@0.0.13(react@19.1.1)': + '@react-email/preview@0.0.13(react@19.2.0)': dependencies: - react: 19.1.1 + react: 19.2.0 - '@react-email/render@1.2.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@react-email/render@1.3.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: html-to-text: 9.0.5 prettier: 3.6.2 - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) react-promise-suspense: 0.3.4 - '@react-email/row@0.0.12(react@19.1.1)': + '@react-email/row@0.0.12(react@19.2.0)': dependencies: - react: 19.1.1 + react: 19.2.0 - '@react-email/section@0.0.16(react@19.1.1)': + '@react-email/section@0.0.16(react@19.2.0)': dependencies: - react: 19.1.1 + react: 19.2.0 - '@react-email/tailwind@1.2.2(react@19.1.1)': + '@react-email/tailwind@1.2.2(react@19.2.0)': dependencies: - react: 19.1.1 + react: 19.2.0 - '@react-email/text@0.1.5(react@19.1.1)': + '@react-email/text@0.1.5(react@19.2.0)': dependencies: - react: 19.1.1 + react: 19.2.0 - '@reduxjs/toolkit@1.9.7(react-redux@7.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)': - dependencies: - immer: 9.0.21 - redux: 4.2.1 - redux-thunk: 2.4.2(redux@4.2.1) - reselect: 4.1.8 - optionalDependencies: - react: 18.3.1 - react-redux: 7.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - - '@rollup/pluginutils@5.2.0(rollup@4.46.3)': + '@rollup/pluginutils@5.3.0(rollup@4.52.4)': dependencies: '@types/estree': 1.0.8 estree-walker: 2.0.2 picomatch: 4.0.3 optionalDependencies: - rollup: 4.46.3 + rollup: 4.52.4 - '@rollup/rollup-android-arm-eabi@4.46.3': + '@rollup/rollup-android-arm-eabi@4.52.4': optional: true - '@rollup/rollup-android-arm64@4.46.3': + '@rollup/rollup-android-arm64@4.52.4': optional: true - '@rollup/rollup-darwin-arm64@4.46.3': + '@rollup/rollup-darwin-arm64@4.52.4': optional: true - '@rollup/rollup-darwin-x64@4.46.3': + '@rollup/rollup-darwin-x64@4.52.4': optional: true - '@rollup/rollup-freebsd-arm64@4.46.3': + '@rollup/rollup-freebsd-arm64@4.52.4': optional: true - '@rollup/rollup-freebsd-x64@4.46.3': + '@rollup/rollup-freebsd-x64@4.52.4': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.46.3': + '@rollup/rollup-linux-arm-gnueabihf@4.52.4': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.46.3': + '@rollup/rollup-linux-arm-musleabihf@4.52.4': optional: true - '@rollup/rollup-linux-arm64-gnu@4.46.3': + '@rollup/rollup-linux-arm64-gnu@4.52.4': optional: true - '@rollup/rollup-linux-arm64-musl@4.46.3': + '@rollup/rollup-linux-arm64-musl@4.52.4': optional: true - '@rollup/rollup-linux-loongarch64-gnu@4.46.3': + '@rollup/rollup-linux-loong64-gnu@4.52.4': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.46.3': + '@rollup/rollup-linux-ppc64-gnu@4.52.4': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.46.3': + '@rollup/rollup-linux-riscv64-gnu@4.52.4': optional: true - '@rollup/rollup-linux-riscv64-musl@4.46.3': + '@rollup/rollup-linux-riscv64-musl@4.52.4': optional: true - '@rollup/rollup-linux-s390x-gnu@4.46.3': + '@rollup/rollup-linux-s390x-gnu@4.52.4': optional: true - '@rollup/rollup-linux-x64-gnu@4.46.3': + '@rollup/rollup-linux-x64-gnu@4.52.4': optional: true - '@rollup/rollup-linux-x64-musl@4.46.3': + '@rollup/rollup-linux-x64-musl@4.52.4': optional: true - '@rollup/rollup-win32-arm64-msvc@4.46.3': + '@rollup/rollup-openharmony-arm64@4.52.4': optional: true - '@rollup/rollup-win32-ia32-msvc@4.46.3': + '@rollup/rollup-win32-arm64-msvc@4.52.4': optional: true - '@rollup/rollup-win32-x64-msvc@4.46.3': + '@rollup/rollup-win32-ia32-msvc@4.52.4': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.52.4': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.52.4': optional: true '@scarf/scarf@1.4.0': {} @@ -15752,7 +15385,7 @@ snapshots: '@slorber/react-helmet-async@1.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.28.3 + '@babel/runtime': 7.28.4 invariant: 2.2.4 prop-types: 15.8.1 react: 18.3.1 @@ -15766,6 +15399,279 @@ snapshots: micromark-util-character: 1.2.0 micromark-util-symbol: 1.1.0 + '@smithy/abort-controller@4.2.0': + dependencies: + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@smithy/config-resolver@4.3.0': + dependencies: + '@smithy/node-config-provider': 4.3.0 + '@smithy/types': 4.6.0 + '@smithy/util-config-provider': 4.2.0 + '@smithy/util-middleware': 4.2.0 + tslib: 2.8.1 + + '@smithy/core@3.15.0': + dependencies: + '@smithy/middleware-serde': 4.2.0 + '@smithy/protocol-http': 5.3.0 + '@smithy/types': 4.6.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-middleware': 4.2.0 + '@smithy/util-stream': 4.5.0 + '@smithy/util-utf8': 4.2.0 + '@smithy/uuid': 1.1.0 + tslib: 2.8.1 + + '@smithy/credential-provider-imds@4.2.0': + dependencies: + '@smithy/node-config-provider': 4.3.0 + '@smithy/property-provider': 4.2.0 + '@smithy/types': 4.6.0 + '@smithy/url-parser': 4.2.0 + tslib: 2.8.1 + + '@smithy/fetch-http-handler@5.3.1': + dependencies: + '@smithy/protocol-http': 5.3.0 + '@smithy/querystring-builder': 4.2.0 + '@smithy/types': 4.6.0 + '@smithy/util-base64': 4.3.0 + tslib: 2.8.1 + + '@smithy/hash-node@4.2.0': + dependencies: + '@smithy/types': 4.6.0 + '@smithy/util-buffer-from': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/invalid-dependency@4.2.0': + dependencies: + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@smithy/is-array-buffer@2.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/is-array-buffer@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/middleware-content-length@4.2.0': + dependencies: + '@smithy/protocol-http': 5.3.0 + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@smithy/middleware-endpoint@4.3.1': + dependencies: + '@smithy/core': 3.15.0 + '@smithy/middleware-serde': 4.2.0 + '@smithy/node-config-provider': 4.3.0 + '@smithy/shared-ini-file-loader': 4.3.0 + '@smithy/types': 4.6.0 + '@smithy/url-parser': 4.2.0 + '@smithy/util-middleware': 4.2.0 + tslib: 2.8.1 + + '@smithy/middleware-retry@4.4.1': + dependencies: + '@smithy/node-config-provider': 4.3.0 + '@smithy/protocol-http': 5.3.0 + '@smithy/service-error-classification': 4.2.0 + '@smithy/smithy-client': 4.7.1 + '@smithy/types': 4.6.0 + '@smithy/util-middleware': 4.2.0 + '@smithy/util-retry': 4.2.0 + '@smithy/uuid': 1.1.0 + tslib: 2.8.1 + + '@smithy/middleware-serde@4.2.0': + dependencies: + '@smithy/protocol-http': 5.3.0 + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@smithy/middleware-stack@4.2.0': + dependencies: + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@smithy/node-config-provider@4.3.0': + dependencies: + '@smithy/property-provider': 4.2.0 + '@smithy/shared-ini-file-loader': 4.3.0 + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@smithy/node-http-handler@4.3.0': + dependencies: + '@smithy/abort-controller': 4.2.0 + '@smithy/protocol-http': 5.3.0 + '@smithy/querystring-builder': 4.2.0 + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@smithy/property-provider@4.2.0': + dependencies: + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@smithy/protocol-http@5.3.0': + dependencies: + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@smithy/querystring-builder@4.2.0': + dependencies: + '@smithy/types': 4.6.0 + '@smithy/util-uri-escape': 4.2.0 + tslib: 2.8.1 + + '@smithy/querystring-parser@4.2.0': + dependencies: + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@smithy/service-error-classification@4.2.0': + dependencies: + '@smithy/types': 4.6.0 + + '@smithy/shared-ini-file-loader@4.3.0': + dependencies: + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@smithy/signature-v4@5.3.0': + dependencies: + '@smithy/is-array-buffer': 4.2.0 + '@smithy/protocol-http': 5.3.0 + '@smithy/types': 4.6.0 + '@smithy/util-hex-encoding': 4.2.0 + '@smithy/util-middleware': 4.2.0 + '@smithy/util-uri-escape': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/smithy-client@4.7.1': + dependencies: + '@smithy/core': 3.15.0 + '@smithy/middleware-endpoint': 4.3.1 + '@smithy/middleware-stack': 4.2.0 + '@smithy/protocol-http': 5.3.0 + '@smithy/types': 4.6.0 + '@smithy/util-stream': 4.5.0 + tslib: 2.8.1 + + '@smithy/types@4.6.0': + dependencies: + tslib: 2.8.1 + + '@smithy/url-parser@4.2.0': + dependencies: + '@smithy/querystring-parser': 4.2.0 + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@smithy/util-base64@4.3.0': + dependencies: + '@smithy/util-buffer-from': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/util-body-length-browser@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-body-length-node@4.2.1': + dependencies: + tslib: 2.8.1 + + '@smithy/util-buffer-from@2.2.0': + dependencies: + '@smithy/is-array-buffer': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-buffer-from@4.2.0': + dependencies: + '@smithy/is-array-buffer': 4.2.0 + tslib: 2.8.1 + + '@smithy/util-config-provider@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-defaults-mode-browser@4.3.0': + dependencies: + '@smithy/property-provider': 4.2.0 + '@smithy/smithy-client': 4.7.1 + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@smithy/util-defaults-mode-node@4.2.1': + dependencies: + '@smithy/config-resolver': 4.3.0 + '@smithy/credential-provider-imds': 4.2.0 + '@smithy/node-config-provider': 4.3.0 + '@smithy/property-provider': 4.2.0 + '@smithy/smithy-client': 4.7.1 + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@smithy/util-endpoints@3.2.0': + dependencies: + '@smithy/node-config-provider': 4.3.0 + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@smithy/util-hex-encoding@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-middleware@4.2.0': + dependencies: + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@smithy/util-retry@4.2.0': + dependencies: + '@smithy/service-error-classification': 4.2.0 + '@smithy/types': 4.6.0 + tslib: 2.8.1 + + '@smithy/util-stream@4.5.0': + dependencies: + '@smithy/fetch-http-handler': 5.3.1 + '@smithy/node-http-handler': 4.3.0 + '@smithy/types': 4.6.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-buffer-from': 4.2.0 + '@smithy/util-hex-encoding': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/util-uri-escape@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-utf8@2.3.0': + dependencies: + '@smithy/util-buffer-from': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-utf8@4.2.0': + dependencies: + '@smithy/util-buffer-from': 4.2.0 + tslib: 2.8.1 + + '@smithy/uuid@1.1.0': + dependencies: + tslib: 2.8.1 + '@socket.io/component-emitter@3.1.2': {} '@socket.io/redis-adapter@8.3.0(socket.io-adapter@2.5.5)': @@ -15777,70 +15683,69 @@ snapshots: transitivePeerDependencies: - supports-color - '@sqltools/formatter@1.2.5': {} - '@standard-schema/spec@1.0.0': {} - '@sveltejs/acorn-typescript@1.0.5(acorn@8.15.0)': + '@sveltejs/acorn-typescript@1.0.6(acorn@8.15.0)': dependencies: acorn: 8.15.0 - '@sveltejs/adapter-static@3.0.9(@sveltejs/kit@2.27.1(@sveltejs/vite-plugin-svelte@6.1.2(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)))(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)))': + '@sveltejs/adapter-static@3.0.10(@sveltejs/kit@2.46.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)))(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)))': dependencies: - '@sveltejs/kit': 2.27.1(@sveltejs/vite-plugin-svelte@6.1.2(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)))(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) + '@sveltejs/kit': 2.46.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)))(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) - '@sveltejs/enhanced-img@0.8.1(@sveltejs/vite-plugin-svelte@6.1.2(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)))(rollup@4.46.3)(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))': + '@sveltejs/enhanced-img@0.8.4(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)))(rollup@4.52.4)(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 6.1.2(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) - magic-string: 0.30.17 - sharp: 0.34.3 - svelte: 5.35.5 - svelte-parse-markup: 0.1.5(svelte@5.35.5) - vite: 7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) - vite-imagetools: 8.0.0(rollup@4.46.3) - zimmerframe: 1.1.2 + '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) + magic-string: 0.30.19 + sharp: 0.34.4 + svelte: 5.39.11 + svelte-parse-markup: 0.1.5(svelte@5.39.11) + vite: 7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + vite-imagetools: 8.0.0(rollup@4.52.4) + zimmerframe: 1.1.4 transitivePeerDependencies: - rollup - supports-color - '@sveltejs/kit@2.27.1(@sveltejs/vite-plugin-svelte@6.1.2(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)))(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))': + '@sveltejs/kit@2.46.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)))(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))': dependencies: '@standard-schema/spec': 1.0.0 - '@sveltejs/acorn-typescript': 1.0.5(acorn@8.15.0) - '@sveltejs/vite-plugin-svelte': 6.1.2(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) + '@sveltejs/acorn-typescript': 1.0.6(acorn@8.15.0) + '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) '@types/cookie': 0.6.0 acorn: 8.15.0 cookie: 0.6.0 - devalue: 5.1.1 + devalue: 5.3.2 esm-env: 1.2.2 kleur: 4.1.5 - magic-string: 0.30.17 + magic-string: 0.30.19 mrmime: 2.0.1 sade: 1.8.1 set-cookie-parser: 2.7.1 - sirv: 3.0.1 - svelte: 5.35.5 - vite: 7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + sirv: 3.0.2 + svelte: 5.39.11 + vite: 7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + optionalDependencies: + '@opentelemetry/api': 1.9.0 - '@sveltejs/vite-plugin-svelte-inspector@5.0.0(@sveltejs/vite-plugin-svelte@6.1.2(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)))(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))': + '@sveltejs/vite-plugin-svelte-inspector@5.0.0(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)))(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 6.1.2(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) - debug: 4.4.1 - svelte: 5.35.5 - vite: 7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) + debug: 4.4.3 + svelte: 5.39.11 + vite: 7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@6.1.2(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))': + '@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 5.0.0(@sveltejs/vite-plugin-svelte@6.1.2(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)))(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) - debug: 4.4.1 + '@sveltejs/vite-plugin-svelte-inspector': 5.0.0(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)))(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) + debug: 4.4.3 deepmerge: 4.3.1 - kleur: 4.1.5 - magic-string: 0.30.17 - svelte: 5.35.5 - vite: 7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) - vitefu: 1.1.1(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) + magic-string: 0.30.19 + svelte: 5.39.11 + vite: 7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + vitefu: 1.1.1(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) transitivePeerDependencies: - supports-color @@ -15888,12 +15793,12 @@ snapshots: '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.27.7) '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.27.7) - '@svgr/core@8.1.0(typescript@5.9.2)': + '@svgr/core@8.1.0(typescript@5.9.3)': dependencies: '@babel/core': 7.27.7 '@svgr/babel-preset': 8.1.0(@babel/core@7.27.7) camelcase: 6.3.0 - cosmiconfig: 8.3.6(typescript@5.9.2) + cosmiconfig: 8.3.6(typescript@5.9.3) snake-case: 3.0.4 transitivePeerDependencies: - supports-color @@ -15901,87 +15806,87 @@ snapshots: '@svgr/hast-util-to-babel-ast@8.0.0': dependencies: - '@babel/types': 7.28.2 + '@babel/types': 7.28.4 entities: 4.5.0 - '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.9.2))': + '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.9.3))': dependencies: '@babel/core': 7.27.7 '@svgr/babel-preset': 8.1.0(@babel/core@7.27.7) - '@svgr/core': 8.1.0(typescript@5.9.2) + '@svgr/core': 8.1.0(typescript@5.9.3) '@svgr/hast-util-to-babel-ast': 8.0.0 svg-parser: 2.0.4 transitivePeerDependencies: - supports-color - '@svgr/plugin-svgo@8.1.0(@svgr/core@8.1.0(typescript@5.9.2))(typescript@5.9.2)': + '@svgr/plugin-svgo@8.1.0(@svgr/core@8.1.0(typescript@5.9.3))(typescript@5.9.3)': dependencies: - '@svgr/core': 8.1.0(typescript@5.9.2) - cosmiconfig: 8.3.6(typescript@5.9.2) + '@svgr/core': 8.1.0(typescript@5.9.3) + cosmiconfig: 8.3.6(typescript@5.9.3) deepmerge: 4.3.1 svgo: 3.3.2 transitivePeerDependencies: - typescript - '@svgr/webpack@8.1.0(typescript@5.9.2)': + '@svgr/webpack@8.1.0(typescript@5.9.3)': dependencies: '@babel/core': 7.27.7 '@babel/plugin-transform-react-constant-elements': 7.27.1(@babel/core@7.27.7) '@babel/preset-env': 7.27.2(@babel/core@7.27.7) '@babel/preset-react': 7.27.1(@babel/core@7.27.7) '@babel/preset-typescript': 7.27.1(@babel/core@7.27.7) - '@svgr/core': 8.1.0(typescript@5.9.2) - '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.9.2)) - '@svgr/plugin-svgo': 8.1.0(@svgr/core@8.1.0(typescript@5.9.2))(typescript@5.9.2) + '@svgr/core': 8.1.0(typescript@5.9.3) + '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.9.3)) + '@svgr/plugin-svgo': 8.1.0(@svgr/core@8.1.0(typescript@5.9.3))(typescript@5.9.3) transitivePeerDependencies: - supports-color - typescript - '@swc/core-darwin-arm64@1.13.3': + '@swc/core-darwin-arm64@1.13.5': optional: true - '@swc/core-darwin-x64@1.13.3': + '@swc/core-darwin-x64@1.13.5': optional: true - '@swc/core-linux-arm-gnueabihf@1.13.3': + '@swc/core-linux-arm-gnueabihf@1.13.5': optional: true - '@swc/core-linux-arm64-gnu@1.13.3': + '@swc/core-linux-arm64-gnu@1.13.5': optional: true - '@swc/core-linux-arm64-musl@1.13.3': + '@swc/core-linux-arm64-musl@1.13.5': optional: true - '@swc/core-linux-x64-gnu@1.13.3': + '@swc/core-linux-x64-gnu@1.13.5': optional: true - '@swc/core-linux-x64-musl@1.13.3': + '@swc/core-linux-x64-musl@1.13.5': optional: true - '@swc/core-win32-arm64-msvc@1.13.3': + '@swc/core-win32-arm64-msvc@1.13.5': optional: true - '@swc/core-win32-ia32-msvc@1.13.3': + '@swc/core-win32-ia32-msvc@1.13.5': optional: true - '@swc/core-win32-x64-msvc@1.13.3': + '@swc/core-win32-x64-msvc@1.13.5': optional: true - '@swc/core@1.13.3(@swc/helpers@0.5.17)': + '@swc/core@1.13.5(@swc/helpers@0.5.17)': dependencies: '@swc/counter': 0.1.3 - '@swc/types': 0.1.24 + '@swc/types': 0.1.25 optionalDependencies: - '@swc/core-darwin-arm64': 1.13.3 - '@swc/core-darwin-x64': 1.13.3 - '@swc/core-linux-arm-gnueabihf': 1.13.3 - '@swc/core-linux-arm64-gnu': 1.13.3 - '@swc/core-linux-arm64-musl': 1.13.3 - '@swc/core-linux-x64-gnu': 1.13.3 - '@swc/core-linux-x64-musl': 1.13.3 - '@swc/core-win32-arm64-msvc': 1.13.3 - '@swc/core-win32-ia32-msvc': 1.13.3 - '@swc/core-win32-x64-msvc': 1.13.3 + '@swc/core-darwin-arm64': 1.13.5 + '@swc/core-darwin-x64': 1.13.5 + '@swc/core-linux-arm-gnueabihf': 1.13.5 + '@swc/core-linux-arm64-gnu': 1.13.5 + '@swc/core-linux-arm64-musl': 1.13.5 + '@swc/core-linux-x64-gnu': 1.13.5 + '@swc/core-linux-x64-musl': 1.13.5 + '@swc/core-win32-arm64-msvc': 1.13.5 + '@swc/core-win32-ia32-msvc': 1.13.5 + '@swc/core-win32-x64-msvc': 1.13.5 '@swc/helpers': 0.5.17 '@swc/counter@0.1.3': {} @@ -15990,7 +15895,7 @@ snapshots: dependencies: tslib: 2.8.1 - '@swc/types@0.1.24': + '@swc/types@0.1.25': dependencies: '@swc/counter': 0.1.3 @@ -15998,95 +15903,81 @@ snapshots: dependencies: defer-to-connect: 2.0.1 - '@tailwindcss/node@4.1.12': + '@tailwindcss/node@4.1.14': dependencies: '@jridgewell/remapping': 2.3.5 enhanced-resolve: 5.18.3 - jiti: 2.5.1 + jiti: 2.6.1 lightningcss: 1.30.1 - magic-string: 0.30.17 + magic-string: 0.30.19 source-map-js: 1.2.1 - tailwindcss: 4.1.12 + tailwindcss: 4.1.14 - '@tailwindcss/oxide-android-arm64@4.1.12': + '@tailwindcss/oxide-android-arm64@4.1.14': optional: true - '@tailwindcss/oxide-darwin-arm64@4.1.12': + '@tailwindcss/oxide-darwin-arm64@4.1.14': optional: true - '@tailwindcss/oxide-darwin-x64@4.1.12': + '@tailwindcss/oxide-darwin-x64@4.1.14': optional: true - '@tailwindcss/oxide-freebsd-x64@4.1.12': + '@tailwindcss/oxide-freebsd-x64@4.1.14': optional: true - '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.12': + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.14': optional: true - '@tailwindcss/oxide-linux-arm64-gnu@4.1.12': + '@tailwindcss/oxide-linux-arm64-gnu@4.1.14': optional: true - '@tailwindcss/oxide-linux-arm64-musl@4.1.12': + '@tailwindcss/oxide-linux-arm64-musl@4.1.14': optional: true - '@tailwindcss/oxide-linux-x64-gnu@4.1.12': + '@tailwindcss/oxide-linux-x64-gnu@4.1.14': optional: true - '@tailwindcss/oxide-linux-x64-musl@4.1.12': + '@tailwindcss/oxide-linux-x64-musl@4.1.14': optional: true - '@tailwindcss/oxide-wasm32-wasi@4.1.12': + '@tailwindcss/oxide-wasm32-wasi@4.1.14': optional: true - '@tailwindcss/oxide-win32-arm64-msvc@4.1.12': + '@tailwindcss/oxide-win32-arm64-msvc@4.1.14': optional: true - '@tailwindcss/oxide-win32-x64-msvc@4.1.12': + '@tailwindcss/oxide-win32-x64-msvc@4.1.14': optional: true - '@tailwindcss/oxide@4.1.12': + '@tailwindcss/oxide@4.1.14': dependencies: - detect-libc: 2.0.4 - tar: 7.4.3 + detect-libc: 2.1.2 + tar: 7.5.1 optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.1.12 - '@tailwindcss/oxide-darwin-arm64': 4.1.12 - '@tailwindcss/oxide-darwin-x64': 4.1.12 - '@tailwindcss/oxide-freebsd-x64': 4.1.12 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.12 - '@tailwindcss/oxide-linux-arm64-gnu': 4.1.12 - '@tailwindcss/oxide-linux-arm64-musl': 4.1.12 - '@tailwindcss/oxide-linux-x64-gnu': 4.1.12 - '@tailwindcss/oxide-linux-x64-musl': 4.1.12 - '@tailwindcss/oxide-wasm32-wasi': 4.1.12 - '@tailwindcss/oxide-win32-arm64-msvc': 4.1.12 - '@tailwindcss/oxide-win32-x64-msvc': 4.1.12 + '@tailwindcss/oxide-android-arm64': 4.1.14 + '@tailwindcss/oxide-darwin-arm64': 4.1.14 + '@tailwindcss/oxide-darwin-x64': 4.1.14 + '@tailwindcss/oxide-freebsd-x64': 4.1.14 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.14 + '@tailwindcss/oxide-linux-arm64-gnu': 4.1.14 + '@tailwindcss/oxide-linux-arm64-musl': 4.1.14 + '@tailwindcss/oxide-linux-x64-gnu': 4.1.14 + '@tailwindcss/oxide-linux-x64-musl': 4.1.14 + '@tailwindcss/oxide-wasm32-wasi': 4.1.14 + '@tailwindcss/oxide-win32-arm64-msvc': 4.1.14 + '@tailwindcss/oxide-win32-x64-msvc': 4.1.14 - '@tailwindcss/vite@4.1.12(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))': + '@tailwindcss/vite@4.1.14(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))': dependencies: - '@tailwindcss/node': 4.1.12 - '@tailwindcss/oxide': 4.1.12 - tailwindcss: 4.1.12 - vite: 7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) - - '@testcontainers/postgresql@11.5.1': - dependencies: - testcontainers: 11.5.1 - transitivePeerDependencies: - - bare-buffer - - supports-color - - '@testcontainers/redis@11.5.1': - dependencies: - testcontainers: 11.5.1 - transitivePeerDependencies: - - bare-buffer - - supports-color + '@tailwindcss/node': 4.1.14 + '@tailwindcss/oxide': 4.1.14 + tailwindcss: 4.1.14 + vite: 7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) '@testing-library/dom@10.4.0': dependencies: '@babel/code-frame': 7.27.1 - '@babel/runtime': 7.28.3 + '@babel/runtime': 7.28.4 '@types/aria-query': 5.0.4 aria-query: 5.3.0 chalk: 4.1.2 @@ -16094,7 +15985,7 @@ snapshots: lz-string: 1.5.0 pretty-format: 27.5.1 - '@testing-library/jest-dom@6.7.0': + '@testing-library/jest-dom@6.9.1': dependencies: '@adobe/css-tools': 4.4.4 aria-query: 5.3.2 @@ -16103,13 +15994,13 @@ snapshots: picocolors: 1.1.1 redent: 3.0.0 - '@testing-library/svelte@5.2.8(svelte@5.35.5)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.3.0)(happy-dom@18.0.1)(jiti@2.5.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))': + '@testing-library/svelte@5.2.8(svelte@5.39.11)(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.7.1)(happy-dom@20.0.0)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))': dependencies: '@testing-library/dom': 10.4.0 - svelte: 5.35.5 + svelte: 5.39.11 optionalDependencies: - vite: 7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.3.0)(happy-dom@18.0.1)(jiti@2.5.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + vite: 7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.7.1)(happy-dom@20.0.0)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) '@testing-library/user-event@14.6.1(@testing-library/dom@10.4.0)': dependencies: @@ -16117,7 +16008,7 @@ snapshots: '@tokenizer/inflate@0.2.7': dependencies: - debug: 4.4.1 + debug: 4.4.3 fflate: 0.8.2 token-types: 6.1.1 transitivePeerDependencies: @@ -16151,7 +16042,7 @@ snapshots: '@types/accepts@1.3.7': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/archiver@6.0.3': dependencies: @@ -16161,27 +16052,21 @@ snapshots: '@types/async-lock@1.4.2': {} - '@types/aws-lambda@8.10.150': {} - '@types/bcrypt@6.0.0': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/bonjour@3.5.13': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/braces@3.0.5': {} - '@types/bunyan@1.8.11': - dependencies: - '@types/node': 22.18.1 - '@types/byte-size@8.1.2': {} '@types/chai@5.2.2': @@ -16199,21 +16084,21 @@ snapshots: '@types/cli-progress@3.11.6': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/compression@1.8.1': dependencies: '@types/express': 5.0.3 - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/connect-history-api-fallback@1.5.4': dependencies: '@types/express-serve-static-core': 5.0.6 - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/connect@3.4.38': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/content-disposition@0.5.9': {} @@ -16230,11 +16115,11 @@ snapshots: '@types/connect': 3.4.38 '@types/express': 5.0.3 '@types/keygrip': 1.0.6 - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/cors@2.8.19': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/debug@4.1.12': dependencies: @@ -16244,13 +16129,13 @@ snapshots: '@types/docker-modem@3.0.6': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/ssh2': 1.15.5 - '@types/dockerode@3.3.42': + '@types/dockerode@3.3.44': dependencies: '@types/docker-modem': 3.0.6 - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/ssh2': 1.15.5 '@types/dom-to-image@2.6.7': {} @@ -16273,14 +16158,14 @@ snapshots: '@types/express-serve-static-core@4.19.6': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/qs': 6.14.0 '@types/range-parser': 1.2.7 '@types/send': 0.17.5 '@types/express-serve-static-core@5.0.6': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/qs': 6.14.0 '@types/range-parser': 1.2.7 '@types/send': 0.17.5 @@ -16306,7 +16191,7 @@ snapshots: '@types/fluent-ffmpeg@2.1.27': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/geojson-vt@3.2.5': dependencies: @@ -16328,11 +16213,6 @@ snapshots: '@types/history@4.7.11': {} - '@types/hoist-non-react-statics@3.3.6': - dependencies: - '@types/react': 19.1.12 - hoist-non-react-statics: 3.3.2 - '@types/html-minifier-terser@6.1.0': {} '@types/http-assert@1.5.6': {} @@ -16343,7 +16223,7 @@ snapshots: '@types/http-proxy@1.17.16': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/inquirer@8.2.11': dependencies: @@ -16381,9 +16261,9 @@ snapshots: '@types/http-errors': 2.0.5 '@types/keygrip': 1.0.6 '@types/koa-compose': 3.2.8 - '@types/node': 22.18.1 + '@types/node': 22.18.10 - '@types/leaflet@1.9.19': + '@types/leaflet@1.9.20': dependencies: '@types/geojson': 7946.0.16 @@ -16393,8 +16273,6 @@ snapshots: '@types/lodash@4.17.20': {} - '@types/luxon@3.6.2': {} - '@types/luxon@3.7.1': {} '@types/mdast@4.0.4': @@ -16403,10 +16281,6 @@ snapshots: '@types/mdx@2.0.13': {} - '@types/memcached@2.2.10': - dependencies: - '@types/node': 22.18.1 - '@types/methods@1.1.4': {} '@types/micromatch@4.0.9': @@ -16417,7 +16291,7 @@ snapshots: '@types/mock-fs@4.13.4': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/ms@2.1.0': {} @@ -16425,22 +16299,13 @@ snapshots: dependencies: '@types/express': 5.0.3 - '@types/mysql@2.15.27': - dependencies: - '@types/node': 22.18.1 - - '@types/node-fetch@2.6.12': - dependencies: - '@types/node': 22.18.1 - form-data: 4.0.4 - '@types/node-forge@1.3.11': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/node@17.0.45': {} - '@types/node@18.19.123': + '@types/node@18.19.130': dependencies: undici-types: 5.26.5 @@ -16448,28 +16313,27 @@ snapshots: dependencies: undici-types: 6.21.0 - '@types/node@22.18.1': + '@types/node@22.18.10': dependencies: undici-types: 6.21.0 - '@types/node@24.3.0': + '@types/node@24.7.1': dependencies: - undici-types: 7.10.0 + undici-types: 7.14.0 optional: true - '@types/nodemailer@6.4.17': + '@types/nodemailer@7.0.2': dependencies: - '@types/node': 22.18.1 + '@aws-sdk/client-sesv2': 3.907.0 + '@types/node': 22.18.10 + transitivePeerDependencies: + - aws-crt - '@types/oidc-provider@9.1.2': + '@types/oidc-provider@9.5.0': dependencies: '@types/keygrip': 1.0.6 '@types/koa': 3.0.0 - '@types/node': 22.18.1 - - '@types/oracledb@6.5.2': - dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/parse5@5.0.3': {} @@ -16477,15 +16341,9 @@ snapshots: dependencies: '@types/pg': 8.15.5 - '@types/pg@8.15.4': - dependencies: - '@types/node': 22.18.1 - pg-protocol: 1.10.3 - pg-types: 2.2.0 - '@types/pg@8.15.5': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 pg-protocol: 1.10.3 pg-types: 2.2.0 @@ -16493,51 +16351,44 @@ snapshots: '@types/pngjs@6.0.5': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/prismjs@1.26.5': {} '@types/qrcode@1.5.5': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/qs@6.14.0': {} '@types/range-parser@1.2.7': {} - '@types/react-redux@7.1.34': - dependencies: - '@types/hoist-non-react-statics': 3.3.6 - '@types/react': 19.1.12 - hoist-non-react-statics: 3.3.2 - redux: 4.2.1 - '@types/react-router-config@5.0.11': dependencies: '@types/history': 4.7.11 - '@types/react': 19.1.12 + '@types/react': 19.2.2 '@types/react-router': 5.1.20 '@types/react-router-dom@5.3.3': dependencies: '@types/history': 4.7.11 - '@types/react': 19.1.12 + '@types/react': 19.2.2 '@types/react-router': 5.1.20 '@types/react-router@5.1.20': dependencies: '@types/history': 4.7.11 - '@types/react': 19.1.12 + '@types/react': 19.2.2 - '@types/react@19.1.12': + '@types/react@19.2.2': dependencies: csstype: 3.1.3 '@types/readdir-glob@1.1.5': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 - '@types/retry@0.12.0': {} + '@types/retry@0.12.2': {} '@types/sanitize-html@2.16.0': dependencies: @@ -16545,14 +16396,14 @@ snapshots: '@types/sax@1.2.7': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 - '@types/semver@7.7.0': {} + '@types/semver@7.7.1': {} '@types/send@0.17.5': dependencies: '@types/mime': 1.3.5 - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/serve-index@1.9.4': dependencies: @@ -16561,31 +16412,31 @@ snapshots: '@types/serve-static@1.15.8': dependencies: '@types/http-errors': 2.0.5 - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/send': 0.17.5 '@types/sockjs@0.3.36': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/ssh2-streams@0.1.12': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/ssh2@0.5.52': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/ssh2-streams': 0.1.12 '@types/ssh2@1.15.5': dependencies: - '@types/node': 18.19.123 + '@types/node': 18.19.130 '@types/superagent@8.1.9': dependencies: '@types/cookiejar': 2.1.5 '@types/methods': 1.1.4 - '@types/node': 22.18.1 + '@types/node': 22.18.10 form-data: 4.0.4 '@types/supercluster@7.1.3': @@ -16597,13 +16448,9 @@ snapshots: '@types/methods': 1.1.4 '@types/superagent': 8.1.9 - '@types/tedious@4.0.14': - dependencies: - '@types/node': 22.18.1 - '@types/through@0.0.33': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/ua-parser-js@0.7.39': {} @@ -16611,13 +16458,13 @@ snapshots: '@types/unist@3.0.3': {} - '@types/validator@13.15.2': {} + '@types/validator@13.15.3': {} '@types/whatwg-mimetype@3.0.2': {} '@types/ws@8.18.1': dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 '@types/yargs-parser@21.0.3': {} @@ -16625,136 +16472,136 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@8.39.1(@typescript-eslint/parser@8.39.1(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2)': + '@typescript-eslint/eslint-plugin@8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.39.1(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2) - '@typescript-eslint/scope-manager': 8.39.1 - '@typescript-eslint/type-utils': 8.39.1(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2) - '@typescript-eslint/utils': 8.39.1(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2) - '@typescript-eslint/visitor-keys': 8.39.1 - eslint: 9.33.0(jiti@2.5.1) + '@typescript-eslint/parser': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.46.0 + '@typescript-eslint/type-utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.46.0 + eslint: 9.37.0(jiti@2.6.1) graphemer: 1.4.0 ignore: 7.0.5 natural-compare: 1.4.0 - ts-api-utils: 2.1.0(typescript@5.9.2) - typescript: 5.9.2 + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.39.1(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2)': + '@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.39.1 - '@typescript-eslint/types': 8.39.1 - '@typescript-eslint/typescript-estree': 8.39.1(typescript@5.9.2) - '@typescript-eslint/visitor-keys': 8.39.1 - debug: 4.4.1 - eslint: 9.33.0(jiti@2.5.1) - typescript: 5.9.2 + '@typescript-eslint/scope-manager': 8.46.0 + '@typescript-eslint/types': 8.46.0 + '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.46.0 + debug: 4.4.3 + eslint: 9.37.0(jiti@2.6.1) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.39.1(typescript@5.9.2)': + '@typescript-eslint/project-service@8.46.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.39.1(typescript@5.9.2) - '@typescript-eslint/types': 8.39.1 - debug: 4.4.1 - typescript: 5.9.2 + '@typescript-eslint/tsconfig-utils': 8.46.0(typescript@5.9.3) + '@typescript-eslint/types': 8.46.0 + debug: 4.4.3 + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.39.1': + '@typescript-eslint/scope-manager@8.46.0': dependencies: - '@typescript-eslint/types': 8.39.1 - '@typescript-eslint/visitor-keys': 8.39.1 + '@typescript-eslint/types': 8.46.0 + '@typescript-eslint/visitor-keys': 8.46.0 - '@typescript-eslint/tsconfig-utils@8.39.1(typescript@5.9.2)': + '@typescript-eslint/tsconfig-utils@8.46.0(typescript@5.9.3)': dependencies: - typescript: 5.9.2 + typescript: 5.9.3 - '@typescript-eslint/type-utils@8.39.1(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2)': + '@typescript-eslint/type-utils@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.39.1 - '@typescript-eslint/typescript-estree': 8.39.1(typescript@5.9.2) - '@typescript-eslint/utils': 8.39.1(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2) - debug: 4.4.1 - eslint: 9.33.0(jiti@2.5.1) - ts-api-utils: 2.1.0(typescript@5.9.2) - typescript: 5.9.2 + '@typescript-eslint/types': 8.46.0 + '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) + debug: 4.4.3 + eslint: 9.37.0(jiti@2.6.1) + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.39.1': {} + '@typescript-eslint/types@8.46.0': {} - '@typescript-eslint/typescript-estree@8.39.1(typescript@5.9.2)': + '@typescript-eslint/typescript-estree@8.46.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.39.1(typescript@5.9.2) - '@typescript-eslint/tsconfig-utils': 8.39.1(typescript@5.9.2) - '@typescript-eslint/types': 8.39.1 - '@typescript-eslint/visitor-keys': 8.39.1 - debug: 4.4.1 + '@typescript-eslint/project-service': 8.46.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.46.0(typescript@5.9.3) + '@typescript-eslint/types': 8.46.0 + '@typescript-eslint/visitor-keys': 8.46.0 + debug: 4.4.3 fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 - semver: 7.7.2 - ts-api-utils: 2.1.0(typescript@5.9.2) - typescript: 5.9.2 + semver: 7.7.3 + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.39.1(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2)': + '@typescript-eslint/utils@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.33.0(jiti@2.5.1)) - '@typescript-eslint/scope-manager': 8.39.1 - '@typescript-eslint/types': 8.39.1 - '@typescript-eslint/typescript-estree': 8.39.1(typescript@5.9.2) - eslint: 9.33.0(jiti@2.5.1) - typescript: 5.9.2 + '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1)) + '@typescript-eslint/scope-manager': 8.46.0 + '@typescript-eslint/types': 8.46.0 + '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3) + eslint: 9.37.0(jiti@2.6.1) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.39.1': + '@typescript-eslint/visitor-keys@8.46.0': dependencies: - '@typescript-eslint/types': 8.39.1 + '@typescript-eslint/types': 8.46.0 eslint-visitor-keys: 4.2.1 '@ungap/structured-clone@1.3.0': {} - '@vitest/coverage-v8@3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.18.1)(happy-dom@18.0.1)(jiti@2.5.1)(jsdom@26.1.0(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))': + '@vitest/coverage-v8@3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.18.10)(happy-dom@20.0.0)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 ast-v8-to-istanbul: 0.3.3 - debug: 4.4.1 + debug: 4.4.3 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 5.0.6 istanbul-reports: 3.1.7 - magic-string: 0.30.17 + magic-string: 0.30.19 magicast: 0.3.5 std-env: 3.9.0 test-exclude: 7.0.1 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.1)(happy-dom@18.0.1)(jiti@2.5.1)(jsdom@26.1.0(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.10)(happy-dom@20.0.0)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) transitivePeerDependencies: - supports-color - '@vitest/coverage-v8@3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.3.0)(happy-dom@18.0.1)(jiti@2.5.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))': + '@vitest/coverage-v8@3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.7.1)(happy-dom@20.0.0)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 ast-v8-to-istanbul: 0.3.3 - debug: 4.4.1 + debug: 4.4.3 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 5.0.6 istanbul-reports: 3.1.7 - magic-string: 0.30.17 + magic-string: 0.30.19 magicast: 0.3.5 std-env: 3.9.0 test-exclude: 7.0.1 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.3.0)(happy-dom@18.0.1)(jiti@2.5.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.7.1)(happy-dom@20.0.0)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) transitivePeerDependencies: - supports-color @@ -16766,21 +16613,21 @@ snapshots: chai: 5.2.0 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(vite@7.1.2(@types/node@22.18.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))': + '@vitest/mocker@3.2.4(vite@7.1.9(@types/node@22.18.10)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 - magic-string: 0.30.17 + magic-string: 0.30.19 optionalDependencies: - vite: 7.1.2(@types/node@22.18.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + vite: 7.1.9(@types/node@22.18.10)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) - '@vitest/mocker@3.2.4(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))': + '@vitest/mocker@3.2.4(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 - magic-string: 0.30.17 + magic-string: 0.30.19 optionalDependencies: - vite: 7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + vite: 7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) '@vitest/pretty-format@3.2.4': dependencies: @@ -16795,7 +16642,7 @@ snapshots: '@vitest/snapshot@3.2.4': dependencies: '@vitest/pretty-format': 3.2.4 - magic-string: 0.30.17 + magic-string: 0.30.19 pathe: 2.0.3 '@vitest/spy@3.2.4': @@ -16888,14 +16735,14 @@ snapshots: '@xtuc/long@4.2.2': {} - '@zoom-image/core@0.41.0': + '@zoom-image/core@0.41.3': dependencies: '@namnode/store': 0.1.0 - '@zoom-image/svelte@0.3.4(svelte@5.35.5)': + '@zoom-image/svelte@0.3.7(svelte@5.39.11)': dependencies: - '@zoom-image/core': 0.41.0 - svelte: 5.35.5 + '@zoom-image/core': 0.41.3 + svelte: 5.39.11 abab@2.0.6: optional: true @@ -16946,7 +16793,7 @@ snapshots: agent-base@6.0.2: dependencies: - debug: 4.4.1 + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -16957,14 +16804,6 @@ snapshots: clean-stack: 2.2.0 indent-string: 4.0.0 - ajv-draft-04@1.0.0(ajv@8.11.0): - optionalDependencies: - ajv: 8.11.0 - - ajv-formats@2.1.1(ajv@8.11.0): - optionalDependencies: - ajv: 8.11.0 - ajv-formats@2.1.1(ajv@8.17.1): optionalDependencies: ajv: 8.17.1 @@ -16989,40 +16828,34 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ajv@8.11.0: - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - ajv@8.17.1: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.0.6 + fast-uri: 3.1.0 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - algoliasearch-helper@3.26.0(algoliasearch@5.29.0): + algoliasearch-helper@3.26.0(algoliasearch@5.40.0): dependencies: '@algolia/events': 4.0.1 - algoliasearch: 5.29.0 + algoliasearch: 5.40.0 - algoliasearch@5.29.0: + algoliasearch@5.40.0: dependencies: - '@algolia/client-abtesting': 5.29.0 - '@algolia/client-analytics': 5.29.0 - '@algolia/client-common': 5.29.0 - '@algolia/client-insights': 5.29.0 - '@algolia/client-personalization': 5.29.0 - '@algolia/client-query-suggestions': 5.29.0 - '@algolia/client-search': 5.29.0 - '@algolia/ingestion': 1.29.0 - '@algolia/monitoring': 1.29.0 - '@algolia/recommend': 5.29.0 - '@algolia/requester-browser-xhr': 5.29.0 - '@algolia/requester-fetch': 5.29.0 - '@algolia/requester-node-http': 5.29.0 + '@algolia/abtesting': 1.6.0 + '@algolia/client-abtesting': 5.40.0 + '@algolia/client-analytics': 5.40.0 + '@algolia/client-common': 5.40.0 + '@algolia/client-insights': 5.40.0 + '@algolia/client-personalization': 5.40.0 + '@algolia/client-query-suggestions': 5.40.0 + '@algolia/client-search': 5.40.0 + '@algolia/ingestion': 1.40.0 + '@algolia/monitoring': 1.40.0 + '@algolia/recommend': 5.40.0 + '@algolia/requester-browser-xhr': 5.40.0 + '@algolia/requester-fetch': 5.40.0 + '@algolia/requester-node-http': 5.40.0 ansi-align@3.0.1: dependencies: @@ -17038,7 +16871,7 @@ snapshots: ansi-regex@5.0.1: {} - ansi-regex@6.2.0: {} + ansi-regex@6.2.2: {} ansi-styles@4.3.0: dependencies: @@ -17046,9 +16879,7 @@ snapshots: ansi-styles@5.2.0: {} - ansi-styles@6.2.1: {} - - ansis@3.17.0: {} + ansi-styles@6.2.3: {} ansis@4.1.0: {} @@ -17059,8 +16890,6 @@ snapshots: normalize-path: 3.0.0 picomatch: 2.3.1 - app-root-path@3.1.0: {} - append-field@1.0.0: {} aproba@2.0.0: {} @@ -17126,7 +16955,7 @@ snapshots: ast-v8-to-istanbul@0.3.3: dependencies: - '@jridgewell/trace-mapping': 0.3.30 + '@jridgewell/trace-mapping': 0.3.31 estree-walker: 3.0.3 js-tokens: 9.0.1 @@ -17140,10 +16969,6 @@ snapshots: async@0.2.10: {} - async@3.2.2: {} - - async@3.2.4: {} - async@3.2.6: {} asynckit@0.4.0: {} @@ -17154,8 +16979,8 @@ snapshots: autoprefixer@10.4.21(postcss@8.5.6): dependencies: - browserslist: 4.25.3 - caniuse-lite: 1.0.30001735 + browserslist: 4.26.3 + caniuse-lite: 1.0.30001749 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.1.1 @@ -17166,12 +16991,12 @@ snapshots: b4a@1.6.7: {} - babel-loader@9.2.1(@babel/core@7.27.7)(webpack@5.100.2): + babel-loader@9.2.1(@babel/core@7.27.7)(webpack@5.102.1): dependencies: '@babel/core': 7.27.7 find-cache-dir: 4.0.0 - schema-utils: 4.3.2 - webpack: 5.100.2 + schema-utils: 4.3.3 + webpack: 5.102.1 babel-plugin-dynamic-import-node@2.3.3: dependencies: @@ -17207,35 +17032,43 @@ snapshots: balanced-match@1.0.2: {} - bare-events@2.6.1: - optional: true + bare-events@2.7.0: {} - bare-fs@4.2.0: + bare-fs@4.4.7: dependencies: - bare-events: 2.6.1 + bare-events: 2.7.0 bare-path: 3.0.0 - bare-stream: 2.7.0(bare-events@2.6.1) + bare-stream: 2.7.0(bare-events@2.7.0) + bare-url: 2.2.2 + fast-fifo: 1.3.2 optional: true - bare-os@3.6.1: + bare-os@3.6.2: optional: true bare-path@3.0.0: dependencies: - bare-os: 3.6.1 + bare-os: 3.6.2 optional: true - bare-stream@2.7.0(bare-events@2.6.1): + bare-stream@2.7.0(bare-events@2.7.0): dependencies: - streamx: 2.22.1 + streamx: 2.23.0 optionalDependencies: - bare-events: 2.6.1 + bare-events: 2.7.0 + optional: true + + bare-url@2.2.2: + dependencies: + bare-path: 3.0.0 optional: true base64-js@1.5.1: {} base64id@2.0.0: {} + baseline-browser-mapping@2.8.15: {} + batch-cluster@13.0.0: {} batch@0.6.1: {} @@ -17253,19 +17086,17 @@ snapshots: big.js@5.2.2: {} - bignumber.js@9.3.1: {} - binary-extensions@2.3.0: {} - bits-ui@2.9.4(@internationalized/date@3.8.2)(svelte@5.35.5): + bits-ui@2.9.8(@internationalized/date@3.8.2)(svelte@5.39.11): dependencies: '@floating-ui/core': 1.7.3 - '@floating-ui/dom': 1.7.3 + '@floating-ui/dom': 1.7.4 '@internationalized/date': 3.8.2 esm-env: 1.2.2 - runed: 0.29.2(svelte@5.35.5) - svelte: 5.35.5 - svelte-toolbelt: 0.9.3(svelte@5.35.5) + runed: 0.29.2(svelte@5.39.11) + svelte: 5.39.11 + svelte-toolbelt: 0.9.3(svelte@5.39.11) tabbable: 6.2.0 bl@4.1.0: @@ -17295,12 +17126,12 @@ snapshots: dependencies: bytes: 3.1.2 content-type: 1.0.5 - debug: 4.4.1 + debug: 4.4.3 http-errors: 2.0.0 iconv-lite: 0.6.3 on-finished: 2.4.1 qs: 6.14.0 - raw-body: 3.0.0 + raw-body: 3.0.1 type-is: 2.0.1 transitivePeerDependencies: - supports-color @@ -17312,6 +17143,8 @@ snapshots: boolbase@1.0.0: {} + bowser@2.12.1: {} + boxen@6.2.1: dependencies: ansi-align: 3.0.1 @@ -17327,7 +17160,7 @@ snapshots: dependencies: ansi-align: 3.0.1 camelcase: 7.0.1 - chalk: 5.6.0 + chalk: 5.6.2 cli-boxes: 3.0.0 string-width: 5.1.2 type-fest: 2.19.0 @@ -17347,12 +17180,13 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.25.3: + browserslist@4.26.3: dependencies: - caniuse-lite: 1.0.30001735 - electron-to-chromium: 1.5.207 - node-releases: 2.0.19 - update-browserslist-db: 1.1.3(browserslist@4.25.3) + baseline-browser-mapping: 2.8.15 + caniuse-lite: 1.0.30001749 + electron-to-chromium: 1.5.233 + node-releases: 2.0.23 + update-browserslist-db: 1.1.3(browserslist@4.26.3) buffer-crc32@1.0.0: {} @@ -17373,18 +17207,22 @@ snapshots: builtin-modules@5.0.0: {} - bullmq@5.57.0: + bullmq@5.61.0: dependencies: cron-parser: 4.9.0 - ioredis: 5.7.0 + ioredis: 5.8.1 msgpackr: 1.11.5 node-abort-controller: 3.1.1 - semver: 7.7.2 + semver: 7.7.3 tslib: 2.8.1 - uuid: 9.0.1 + uuid: 11.1.0 transitivePeerDependencies: - supports-color + bundle-name@4.1.0: + dependencies: + run-applescript: 7.1.0 + busboy@1.6.0: dependencies: streamsearch: 1.1.0 @@ -17411,7 +17249,7 @@ snapshots: minipass-pipeline: 1.2.4 p-map: 7.0.3 ssri: 12.0.0 - tar: 7.4.3 + tar: 7.5.1 unique-filename: 4.0.0 cacheable-lookup@7.0.0: {} @@ -17443,8 +17281,6 @@ snapshots: call-bind-apply-helpers: 1.0.2 get-intrinsic: 1.3.0 - call-me-maybe@1.0.2: {} - callsites@3.1.0: {} camel-case@4.1.2: @@ -17462,12 +17298,12 @@ snapshots: caniuse-api@3.0.0: dependencies: - browserslist: 4.25.3 - caniuse-lite: 1.0.30001735 + browserslist: 4.26.3 + caniuse-lite: 1.0.30001749 lodash.memoize: 4.1.2 lodash.uniq: 4.5.0 - caniuse-lite@1.0.30001735: {} + caniuse-lite@1.0.30001749: {} canvas@2.11.2: dependencies: @@ -17487,6 +17323,7 @@ snapshots: transitivePeerDependencies: - encoding - supports-color + optional: true ccount@2.0.1: {} @@ -17503,7 +17340,7 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 - chalk@5.6.0: {} + chalk@5.6.2: {} change-case@5.4.4: {} @@ -17517,12 +17354,8 @@ snapshots: character-reference-invalid@2.0.1: {} - chardet@0.7.0: {} - chardet@2.1.0: {} - charset@1.0.1: {} - check-error@2.1.1: {} cheerio-select@2.1.0: @@ -17582,12 +17415,10 @@ snapshots: class-validator@0.14.2: dependencies: - '@types/validator': 13.15.2 + '@types/validator': 13.15.3 libphonenumber-js: 1.12.9 validator: 13.15.15 - classnames@2.5.1: {} - clean-css@5.3.3: dependencies: source-map: 0.6.1 @@ -17652,8 +17483,6 @@ snapshots: clone@1.0.4: {} - clsx@1.2.1: {} - clsx@2.1.1: {} cluster-key-slot@1.1.2: {} @@ -17666,18 +17495,8 @@ snapshots: color-name@1.1.4: {} - color-string@1.9.1: - dependencies: - color-name: 1.1.4 - simple-swizzle: 0.2.2 - color-support@1.1.3: {} - color@4.2.3: - dependencies: - color-convert: 2.0.1 - color-string: 1.9.1 - colord@2.9.3: {} colorette@2.0.20: {} @@ -17710,13 +17529,11 @@ snapshots: commander@8.3.0: {} - comment-json@4.2.5: + comment-json@4.4.1: dependencies: array-timsort: 1.0.3 core-util-is: 1.0.3 esprima: 4.0.1 - has-own-prop: 2.0.0 - repeat-string: 1.6.1 common-path-prefix@3.0.0: {} @@ -17746,19 +17563,6 @@ snapshots: transitivePeerDependencies: - supports-color - compute-gcd@1.2.1: - dependencies: - validate.io-array: 1.0.6 - validate.io-function: 1.0.2 - validate.io-integer-array: 1.0.0 - - compute-lcm@1.1.2: - dependencies: - compute-gcd: 1.2.1 - validate.io-array: 1.0.6 - validate.io-function: 1.0.2 - validate.io-integer-array: 1.0.0 - concat-map@0.0.1: {} concat-stream@2.0.0: @@ -17827,21 +17631,19 @@ snapshots: depd: 2.0.0 keygrip: 1.1.0 - copy-text-to-clipboard@3.2.0: {} - - copy-webpack-plugin@11.0.0(webpack@5.100.2): + copy-webpack-plugin@11.0.0(webpack@5.102.1): dependencies: fast-glob: 3.3.3 glob-parent: 6.0.2 globby: 13.2.2 normalize-path: 3.0.0 - schema-utils: 4.3.2 + schema-utils: 4.3.3 serialize-javascript: 6.0.2 - webpack: 5.100.2 + webpack: 5.102.1 core-js-compat@3.45.0: dependencies: - browserslist: 4.25.3 + browserslist: 4.26.3 core-js-pure@3.43.0: {} @@ -17863,14 +17665,14 @@ snapshots: optionalDependencies: typescript: 5.8.3 - cosmiconfig@8.3.6(typescript@5.9.2): + cosmiconfig@8.3.6(typescript@5.9.3): dependencies: import-fresh: 3.3.1 js-yaml: 4.1.0 parse-json: 5.2.0 path-type: 4.0.0 optionalDependencies: - typescript: 5.9.2 + typescript: 5.9.3 cpu-features@0.0.10: dependencies: @@ -17887,12 +17689,12 @@ snapshots: cron-parser@4.9.0: dependencies: - luxon: 3.7.1 + luxon: 3.7.2 - cron@4.3.0: + cron@4.3.3: dependencies: - '@types/luxon': 3.6.2 - luxon: 3.6.1 + '@types/luxon': 3.7.1 + luxon: 3.7.2 cross-spawn@7.0.6: dependencies: @@ -17900,8 +17702,6 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - crypto-js@4.2.0: {} - crypto-random-string@4.0.0: dependencies: type-fest: 1.4.0 @@ -17922,7 +17722,7 @@ snapshots: postcss-selector-parser: 7.1.0 postcss-value-parser: 4.2.0 - css-loader@6.11.0(webpack@5.100.2): + css-loader@6.11.0(webpack@5.102.1): dependencies: icss-utils: 5.1.0(postcss@8.5.6) postcss: 8.5.6 @@ -17931,19 +17731,19 @@ snapshots: postcss-modules-scope: 3.2.1(postcss@8.5.6) postcss-modules-values: 4.0.0(postcss@8.5.6) postcss-value-parser: 4.2.0 - semver: 7.7.2 + semver: 7.7.3 optionalDependencies: - webpack: 5.100.2 + webpack: 5.102.1 - css-minimizer-webpack-plugin@5.0.1(clean-css@5.3.3)(webpack@5.100.2): + css-minimizer-webpack-plugin@5.0.1(clean-css@5.3.3)(webpack@5.102.1): dependencies: - '@jridgewell/trace-mapping': 0.3.30 + '@jridgewell/trace-mapping': 0.3.31 cssnano: 6.1.2(postcss@8.5.6) jest-worker: 29.7.0 postcss: 8.5.6 - schema-utils: 4.3.2 + schema-utils: 4.3.3 serialize-javascript: 6.0.2 - webpack: 5.100.2 + webpack: 5.102.1 optionalDependencies: clean-css: 5.3.3 @@ -17992,7 +17792,7 @@ snapshots: cssnano-preset-advanced@6.1.2(postcss@8.5.6): dependencies: autoprefixer: 10.4.21(postcss@8.5.6) - browserslist: 4.25.3 + browserslist: 4.26.3 cssnano-preset-default: 6.1.2(postcss@8.5.6) postcss: 8.5.6 postcss-discard-unused: 6.0.5(postcss@8.5.6) @@ -18002,7 +17802,7 @@ snapshots: cssnano-preset-default@6.1.2(postcss@8.5.6): dependencies: - browserslist: 4.25.3 + browserslist: 4.26.3 css-declaration-sorter: 7.2.0(postcss@8.5.6) cssnano-utils: 4.0.2(postcss@8.5.6) postcss: 8.5.6 @@ -18093,8 +17893,6 @@ snapshots: whatwg-url: 14.2.0 optional: true - dayjs@1.11.13: {} - debounce@1.2.1: {} debounce@2.2.0: {} @@ -18107,7 +17905,7 @@ snapshots: dependencies: ms: 2.1.3 - debug@4.4.1: + debug@4.4.3: dependencies: ms: 2.1.3 @@ -18122,13 +17920,12 @@ snapshots: decompress-response@4.2.1: dependencies: mimic-response: 2.1.0 + optional: true decompress-response@6.0.0: dependencies: mimic-response: 3.1.0 - dedent@1.6.0: {} - deep-eql@5.0.2: {} deep-equal@1.0.1: {} @@ -18139,9 +17936,12 @@ snapshots: deepmerge@4.3.1: {} - default-gateway@6.0.3: + default-browser-id@5.0.0: {} + + default-browser@5.2.1: dependencies: - execa: 5.1.1 + bundle-name: 4.1.0 + default-browser-id: 5.0.0 defaults@1.0.4: dependencies: @@ -18157,6 +17957,8 @@ snapshots: define-lazy-prop@2.0.0: {} + define-lazy-prop@3.0.0: {} + define-properties@1.2.1: dependencies: define-data-property: 1.1.4 @@ -18179,22 +17981,18 @@ snapshots: detect-europe-js@0.1.2: {} - detect-libc@2.0.4: {} + detect-libc@2.1.2: {} detect-node@2.1.0: {} - detect-package-manager@3.0.2: - dependencies: - execa: 5.1.1 - detect-port@1.6.1: dependencies: address: 1.2.2 - debug: 4.4.1 + debug: 4.4.3 transitivePeerDependencies: - supports-color - devalue@5.1.1: {} + devalue@5.3.2: {} devlop@1.1.0: dependencies: @@ -18225,34 +18023,34 @@ snapshots: dependencies: '@leichtgewicht/ip-codec': 2.0.5 - docker-compose@1.2.0: + docker-compose@1.3.0: dependencies: yaml: 2.8.1 docker-modem@5.0.6: dependencies: - debug: 4.4.1 + debug: 4.4.3 readable-stream: 3.6.2 split-ca: 1.0.1 - ssh2: 1.16.0 + ssh2: 1.17.0 transitivePeerDependencies: - supports-color - dockerode@4.0.7: + dockerode@4.0.9: dependencies: '@balena/dockerignore': 1.0.2 - '@grpc/grpc-js': 1.13.4 + '@grpc/grpc-js': 1.14.0 '@grpc/proto-loader': 0.7.15 docker-modem: 5.0.6 protobufjs: 7.5.4 - tar-fs: 2.1.3 + tar-fs: 2.1.4 uuid: 10.0.0 transitivePeerDependencies: - supports-color - docusaurus-lunr-search@3.6.0(@docusaurus/core@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + docusaurus-lunr-search@3.6.0(@docusaurus/core@3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@docusaurus/core': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) + '@docusaurus/core': 3.9.1(@mdx-js/react@3.1.1(@types/react@19.2.2)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) autocomplete.js: 0.37.1 clsx: 2.1.1 gauge: 3.0.2 @@ -18270,129 +18068,6 @@ snapshots: unified: 9.2.2 unist-util-is: 4.1.0 - docusaurus-plugin-openapi@0.7.6(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2): - dependencies: - '@docusaurus/mdx-loader': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/plugin-content-docs': 3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - '@docusaurus/utils': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-common': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-validation': 3.8.1(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - chalk: 4.1.2 - clsx: 1.2.1 - js-yaml: 4.1.0 - json-refs: 3.0.15 - json-schema-resolve-allof: 1.5.0 - lodash: 4.17.21 - openapi-to-postmanv2: 4.25.0(encoding@0.1.13) - postman-collection: 4.5.0 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - webpack: 5.100.2 - transitivePeerDependencies: - - '@docusaurus/faster' - - '@mdx-js/react' - - '@parcel/css' - - '@rspack/core' - - '@swc/core' - - '@swc/css' - - acorn - - bufferutil - - csso - - debug - - encoding - - esbuild - - lightningcss - - supports-color - - typescript - - uglify-js - - utf-8-validate - - webpack-cli - - docusaurus-plugin-proxy@0.7.6: {} - - docusaurus-preset-openapi@0.7.6(@algolia/client-search@5.29.0)(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2))(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(@types/react@19.1.12)(acorn@8.15.0)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1)(search-insights@2.17.3)(typescript@5.9.2): - dependencies: - '@docusaurus/preset-classic': 3.8.1(@algolia/client-search@5.29.0)(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(@types/react@19.1.12)(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.9.2) - docusaurus-plugin-openapi: 0.7.6(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - docusaurus-plugin-proxy: 0.7.6 - docusaurus-theme-openapi: 0.7.6(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2))(@types/react@19.1.12)(acorn@8.15.0)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1)(typescript@5.9.2) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - transitivePeerDependencies: - - '@algolia/client-search' - - '@docusaurus/faster' - - '@docusaurus/plugin-content-docs' - - '@mdx-js/react' - - '@parcel/css' - - '@rspack/core' - - '@swc/core' - - '@swc/css' - - '@types/react' - - acorn - - bufferutil - - csso - - debug - - encoding - - esbuild - - lightningcss - - react-native - - redux - - search-insights - - supports-color - - typescript - - uglify-js - - utf-8-validate - - webpack-cli - - docusaurus-theme-openapi@0.7.6(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2))(@types/react@19.1.12)(acorn@8.15.0)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1)(typescript@5.9.2): - dependencies: - '@docusaurus/theme-common': 3.8.1(@docusaurus/plugin-content-docs@3.8.1(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2))(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@mdx-js/react': 3.1.0(@types/react@19.1.12)(react@18.3.1) - '@monaco-editor/react': 4.7.0(monaco-editor@0.31.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@reduxjs/toolkit': 1.9.7(react-redux@7.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) - buffer: 6.0.3 - clsx: 1.2.1 - crypto-js: 4.2.0 - docusaurus-plugin-openapi: 0.7.6(@mdx-js/react@3.1.0(@types/react@19.1.12)(react@18.3.1))(acorn@8.15.0)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2) - immer: 9.0.21 - lodash: 4.17.21 - marked: 11.2.0 - monaco-editor: 0.31.1 - postman-code-generators: 1.14.2 - postman-collection: 4.5.0 - prism-react-renderer: 2.4.1(react@18.3.1) - process: 0.11.10 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-magic-dropzone: 1.0.1 - react-redux: 7.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - redux-devtools-extension: 2.13.9(redux@4.2.1) - refractor: 4.9.0 - striptags: 3.2.0 - webpack: 5.100.2 - transitivePeerDependencies: - - '@docusaurus/faster' - - '@docusaurus/plugin-content-docs' - - '@parcel/css' - - '@rspack/core' - - '@swc/core' - - '@swc/css' - - '@types/react' - - acorn - - bufferutil - - csso - - debug - - encoding - - esbuild - - lightningcss - - react-native - - redux - - supports-color - - typescript - - uglify-js - - utf-8-validate - - webpack-cli - dom-accessibility-api@0.5.16: {} dom-accessibility-api@0.6.3: {} @@ -18451,9 +18126,7 @@ snapshots: dependencies: is-obj: 2.0.0 - dotenv@16.6.1: {} - - dotenv@17.2.1: {} + dotenv@17.2.3: {} dunder-proto@1.0.1: dependencies: @@ -18471,9 +18144,9 @@ snapshots: ee-first@1.1.1: {} - electron-to-chromium@1.5.207: {} + electron-to-chromium@1.5.233: {} - emoji-regex@10.4.0: {} + emoji-regex@10.6.0: {} emoji-regex@8.0.0: {} @@ -18515,7 +18188,7 @@ snapshots: engine.io@6.6.4: dependencies: '@types/cors': 2.8.19 - '@types/node': 22.18.1 + '@types/node': 22.18.10 accepts: 1.3.8 base64id: 2.0.0 cookie: 0.7.2 @@ -18531,7 +18204,7 @@ snapshots: enhanced-resolve@5.18.3: dependencies: graceful-fs: 4.2.11 - tapable: 2.2.2 + tapable: 2.3.0 entities@2.2.0: {} @@ -18543,7 +18216,7 @@ snapshots: err-code@2.0.3: {} - error-ex@1.3.2: + error-ex@1.3.4: dependencies: is-arrayish: 0.2.1 @@ -18577,8 +18250,6 @@ snapshots: es5-ext: 0.10.64 es6-symbol: 3.1.4 - es6-promise@3.3.1: {} - es6-symbol@3.1.4: dependencies: d: 1.0.2 @@ -18603,7 +18274,7 @@ snapshots: '@types/estree-jsx': 1.0.5 acorn: 8.15.0 esast-util-from-estree: 2.0.0 - vfile-message: 4.0.2 + vfile-message: 4.0.3 esbuild@0.19.12: optionalDependencies: @@ -18631,34 +18302,34 @@ snapshots: '@esbuild/win32-ia32': 0.19.12 '@esbuild/win32-x64': 0.19.12 - esbuild@0.25.9: + esbuild@0.25.10: optionalDependencies: - '@esbuild/aix-ppc64': 0.25.9 - '@esbuild/android-arm': 0.25.9 - '@esbuild/android-arm64': 0.25.9 - '@esbuild/android-x64': 0.25.9 - '@esbuild/darwin-arm64': 0.25.9 - '@esbuild/darwin-x64': 0.25.9 - '@esbuild/freebsd-arm64': 0.25.9 - '@esbuild/freebsd-x64': 0.25.9 - '@esbuild/linux-arm': 0.25.9 - '@esbuild/linux-arm64': 0.25.9 - '@esbuild/linux-ia32': 0.25.9 - '@esbuild/linux-loong64': 0.25.9 - '@esbuild/linux-mips64el': 0.25.9 - '@esbuild/linux-ppc64': 0.25.9 - '@esbuild/linux-riscv64': 0.25.9 - '@esbuild/linux-s390x': 0.25.9 - '@esbuild/linux-x64': 0.25.9 - '@esbuild/netbsd-arm64': 0.25.9 - '@esbuild/netbsd-x64': 0.25.9 - '@esbuild/openbsd-arm64': 0.25.9 - '@esbuild/openbsd-x64': 0.25.9 - '@esbuild/openharmony-arm64': 0.25.9 - '@esbuild/sunos-x64': 0.25.9 - '@esbuild/win32-arm64': 0.25.9 - '@esbuild/win32-ia32': 0.25.9 - '@esbuild/win32-x64': 0.25.9 + '@esbuild/aix-ppc64': 0.25.10 + '@esbuild/android-arm': 0.25.10 + '@esbuild/android-arm64': 0.25.10 + '@esbuild/android-x64': 0.25.10 + '@esbuild/darwin-arm64': 0.25.10 + '@esbuild/darwin-x64': 0.25.10 + '@esbuild/freebsd-arm64': 0.25.10 + '@esbuild/freebsd-x64': 0.25.10 + '@esbuild/linux-arm': 0.25.10 + '@esbuild/linux-arm64': 0.25.10 + '@esbuild/linux-ia32': 0.25.10 + '@esbuild/linux-loong64': 0.25.10 + '@esbuild/linux-mips64el': 0.25.10 + '@esbuild/linux-ppc64': 0.25.10 + '@esbuild/linux-riscv64': 0.25.10 + '@esbuild/linux-s390x': 0.25.10 + '@esbuild/linux-x64': 0.25.10 + '@esbuild/netbsd-arm64': 0.25.10 + '@esbuild/netbsd-x64': 0.25.10 + '@esbuild/openbsd-arm64': 0.25.10 + '@esbuild/openbsd-x64': 0.25.10 + '@esbuild/openharmony-arm64': 0.25.10 + '@esbuild/sunos-x64': 0.25.10 + '@esbuild/win32-arm64': 0.25.10 + '@esbuild/win32-ia32': 0.25.10 + '@esbuild/win32-x64': 0.25.10 escalade@3.2.0: {} @@ -18681,77 +18352,92 @@ snapshots: source-map: 0.6.1 optional: true - eslint-config-prettier@10.1.8(eslint@9.33.0(jiti@2.5.1)): + eslint-config-prettier@10.1.8(eslint@9.37.0(jiti@2.6.1)): dependencies: - eslint: 9.33.0(jiti@2.5.1) + eslint: 9.37.0(jiti@2.6.1) - eslint-p@0.25.0(jiti@2.5.1): - dependencies: - eslint: 9.30.1(jiti@2.5.1) - transitivePeerDependencies: - - jiti - - supports-color - - eslint-plugin-compat@6.0.2(eslint@9.33.0(jiti@2.5.1)): + eslint-plugin-compat@6.0.2(eslint@9.37.0(jiti@2.6.1)): dependencies: '@mdn/browser-compat-data': 5.7.6 ast-metadata-inferer: 0.8.1 - browserslist: 4.25.3 - caniuse-lite: 1.0.30001735 - eslint: 9.33.0(jiti@2.5.1) + browserslist: 4.26.3 + caniuse-lite: 1.0.30001749 + eslint: 9.37.0(jiti@2.6.1) find-up: 5.0.0 globals: 15.15.0 lodash.memoize: 4.1.2 - semver: 7.7.2 + semver: 7.7.3 - eslint-plugin-prettier@5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.33.0(jiti@2.5.1)))(eslint@9.33.0(jiti@2.5.1))(prettier@3.6.2): + eslint-plugin-prettier@5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.37.0(jiti@2.6.1)))(eslint@9.37.0(jiti@2.6.1))(prettier@3.6.2): dependencies: - eslint: 9.33.0(jiti@2.5.1) + eslint: 9.37.0(jiti@2.6.1) prettier: 3.6.2 prettier-linter-helpers: 1.0.0 synckit: 0.11.11 optionalDependencies: '@types/eslint': 9.6.1 - eslint-config-prettier: 10.1.8(eslint@9.33.0(jiti@2.5.1)) + eslint-config-prettier: 10.1.8(eslint@9.37.0(jiti@2.6.1)) - eslint-plugin-svelte@3.11.0(eslint@9.33.0(jiti@2.5.1))(svelte@5.35.5): + eslint-plugin-svelte@3.12.4(eslint@9.37.0(jiti@2.6.1))(svelte@5.39.11): dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.33.0(jiti@2.5.1)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1)) '@jridgewell/sourcemap-codec': 1.5.5 - eslint: 9.33.0(jiti@2.5.1) + eslint: 9.37.0(jiti@2.6.1) esutils: 2.0.3 - globals: 16.3.0 + globals: 16.4.0 known-css-properties: 0.37.0 postcss: 8.5.6 postcss-load-config: 3.1.4(postcss@8.5.6) postcss-safe-parser: 7.0.1(postcss@8.5.6) - semver: 7.7.2 - svelte-eslint-parser: 1.3.1(svelte@5.35.5) + semver: 7.7.3 + svelte-eslint-parser: 1.3.3(svelte@5.39.11) optionalDependencies: - svelte: 5.35.5 + svelte: 5.39.11 transitivePeerDependencies: - ts-node - eslint-plugin-unicorn@60.0.0(eslint@9.33.0(jiti@2.5.1)): + eslint-plugin-unicorn@60.0.0(eslint@9.37.0(jiti@2.6.1)): dependencies: '@babel/helper-validator-identifier': 7.27.1 - '@eslint-community/eslint-utils': 4.7.0(eslint@9.33.0(jiti@2.5.1)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1)) '@eslint/plugin-kit': 0.3.5 change-case: 5.4.4 ci-info: 4.3.0 clean-regexp: 1.0.0 core-js-compat: 3.45.0 - eslint: 9.33.0(jiti@2.5.1) + eslint: 9.37.0(jiti@2.6.1) esquery: 1.6.0 find-up-simple: 1.0.1 - globals: 16.3.0 + globals: 16.4.0 indent-string: 5.0.0 is-builtin-module: 5.0.0 jsesc: 3.1.0 pluralize: 8.0.0 regexp-tree: 0.1.27 regjsparser: 0.12.0 - semver: 7.7.2 + semver: 7.7.3 + strip-indent: 4.0.0 + + eslint-plugin-unicorn@61.0.2(eslint@9.37.0(jiti@2.6.1)): + dependencies: + '@babel/helper-validator-identifier': 7.27.1 + '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1)) + '@eslint/plugin-kit': 0.3.5 + change-case: 5.4.4 + ci-info: 4.3.0 + clean-regexp: 1.0.0 + core-js-compat: 3.45.0 + eslint: 9.37.0(jiti@2.6.1) + esquery: 1.6.0 + find-up-simple: 1.0.1 + globals: 16.4.0 + indent-string: 5.0.0 + is-builtin-module: 5.0.0 + jsesc: 3.1.0 + pluralize: 8.0.0 + regexp-tree: 0.1.27 + regjsparser: 0.12.0 + semver: 7.7.3 strip-indent: 4.0.0 eslint-scope@5.1.1: @@ -18768,17 +18454,17 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.30.1(jiti@2.5.1): + eslint@9.37.0(jiti@2.6.1): dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1(jiti@2.5.1)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1)) '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.21.0 - '@eslint/config-helpers': 0.3.1 - '@eslint/core': 0.14.0 + '@eslint/config-helpers': 0.4.0 + '@eslint/core': 0.16.0 '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.30.1 - '@eslint/plugin-kit': 0.3.5 - '@humanfs/node': 0.16.6 + '@eslint/js': 9.37.0 + '@eslint/plugin-kit': 0.4.0 + '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 '@types/estree': 1.0.8 @@ -18786,7 +18472,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.1 + debug: 4.4.3 escape-string-regexp: 4.0.0 eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 @@ -18806,49 +18492,7 @@ snapshots: natural-compare: 1.4.0 optionator: 0.9.4 optionalDependencies: - jiti: 2.5.1 - transitivePeerDependencies: - - supports-color - - eslint@9.33.0(jiti@2.5.1): - dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.33.0(jiti@2.5.1)) - '@eslint-community/regexpp': 4.12.1 - '@eslint/config-array': 0.21.0 - '@eslint/config-helpers': 0.3.1 - '@eslint/core': 0.15.2 - '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.33.0 - '@eslint/plugin-kit': 0.3.5 - '@humanfs/node': 0.16.6 - '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.4.3 - '@types/estree': 1.0.8 - '@types/json-schema': 7.0.15 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.4.1 - escape-string-regexp: 4.0.0 - eslint-scope: 8.4.0 - eslint-visitor-keys: 4.2.1 - espree: 10.4.0 - esquery: 1.6.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 - find-up: 5.0.0 - glob-parent: 6.0.2 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - json-stable-stringify-without-jsonify: 1.0.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - optionalDependencies: - jiti: 2.5.1 + jiti: 2.6.1 transitivePeerDependencies: - supports-color @@ -18907,7 +18551,7 @@ snapshots: dependencies: '@types/estree-jsx': 1.0.5 astring: 1.9.0 - source-map: 0.7.4 + source-map: 0.7.6 estree-util-value-to-estree@3.4.0: dependencies: @@ -18934,7 +18578,7 @@ snapshots: eval@0.1.8: dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 require-like: 0.1.2 event-emitter@0.3.5: @@ -18944,10 +18588,12 @@ snapshots: event-target-shim@5.0.1: {} - eventemitter2@6.4.9: {} - eventemitter3@4.0.7: {} + events-universal@1.0.1: + dependencies: + bare-events: 2.7.0 + events@3.3.0: {} execa@5.1.1: @@ -18974,7 +18620,7 @@ snapshots: batch-cluster: 13.0.0 exiftool-vendored.pl: 13.0.1 he: 1.2.0 - luxon: 3.7.1 + luxon: 3.7.2 optionalDependencies: exiftool-vendored.exe: 13.0.0 @@ -19026,7 +18672,7 @@ snapshots: content-type: 1.0.5 cookie: 0.7.2 cookie-signature: 1.2.2 - debug: 4.4.1 + debug: 4.4.3 encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 @@ -19062,12 +18708,6 @@ snapshots: extend@3.0.2: {} - external-editor@3.1.0: - dependencies: - chardet: 0.7.0 - iconv-lite: 0.4.24 - tmp: 0.0.33 - fabric@6.7.1: optionalDependencies: canvas: 2.11.2 @@ -19105,7 +18745,11 @@ snapshots: fast-safe-stringify@2.1.1: {} - fast-uri@3.0.6: {} + fast-uri@3.1.0: {} + + fast-xml-parser@5.2.5: + dependencies: + strnum: 2.1.1 fastq@1.19.1: dependencies: @@ -19137,11 +18781,11 @@ snapshots: dependencies: flat-cache: 4.0.1 - file-loader@6.2.0(webpack@5.100.2): + file-loader@6.2.0(webpack@5.102.1): dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.100.2 + webpack: 5.102.1 file-source@0.6.1: dependencies: @@ -19156,8 +18800,6 @@ snapshots: transitivePeerDependencies: - supports-color - file-type@3.9.0: {} - fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -19176,7 +18818,7 @@ snapshots: finalhandler@2.1.0: dependencies: - debug: 4.4.1 + debug: 4.4.3 encodeurl: 2.0.0 escape-html: 1.0.3 on-finished: 2.4.1 @@ -19223,14 +18865,12 @@ snapshots: follow-redirects@1.15.9: {} - foreach@2.0.6: {} - foreground-child@3.3.1: dependencies: cross-spawn: 7.0.6 signal-exit: 4.1.0 - fork-ts-checker-webpack-plugin@9.1.0(typescript@5.8.3)(webpack@5.100.2(@swc/core@1.13.3(@swc/helpers@0.5.17))): + fork-ts-checker-webpack-plugin@9.1.0(typescript@5.8.3)(webpack@5.100.2(@swc/core@1.13.5(@swc/helpers@0.5.17))): dependencies: '@babel/code-frame': 7.27.1 chalk: 4.1.2 @@ -19242,10 +18882,10 @@ snapshots: minimatch: 3.1.2 node-abort-controller: 3.1.1 schema-utils: 3.3.0 - semver: 7.7.2 - tapable: 2.2.2 + semver: 7.7.3 + tapable: 2.3.0 typescript: 5.8.3 - webpack: 5.100.2(@swc/core@1.13.3(@swc/helpers@0.5.17)) + webpack: 5.100.2(@swc/core@1.13.5(@swc/helpers@0.5.17)) form-data-encoder@2.1.4: {} @@ -19259,13 +18899,6 @@ snapshots: format@0.2.2: {} - formidable@2.1.5: - dependencies: - '@paralleldrive/cuid2': 2.2.2 - dezalgo: 1.0.4 - once: 1.4.0 - qs: 6.14.0 - formidable@3.5.4: dependencies: '@paralleldrive/cuid2': 2.2.2 @@ -19328,26 +18961,6 @@ snapshots: strip-ansi: 6.0.1 wide-align: 1.1.5 - gaxios@6.7.1(encoding@0.1.13): - dependencies: - extend: 3.0.2 - https-proxy-agent: 7.0.6 - is-stream: 2.0.1 - node-fetch: 2.7.0(encoding@0.1.13) - uuid: 9.0.1 - transitivePeerDependencies: - - encoding - - supports-color - - gcp-metadata@6.1.1(encoding@0.1.13): - dependencies: - gaxios: 6.7.1(encoding@0.1.13) - google-logging-utils: 0.0.2 - json-bigint: 1.0.0 - transitivePeerDependencies: - - encoding - - supports-color - gensync@1.0.0-beta.2: {} geo-coordinates-parser@1.7.4: {} @@ -19373,7 +18986,7 @@ snapshots: get-caller-file@2.0.5: {} - get-east-asian-width@1.3.0: {} + get-east-asian-width@1.4.0: {} get-intrinsic@1.3.0: dependencies: @@ -19397,8 +19010,6 @@ snapshots: dunder-proto: 1.0.1 es-object-atoms: 1.1.1 - get-stdin@5.0.1: {} - get-stream@6.0.1: {} github-slugger@1.5.0: {} @@ -19413,6 +19024,10 @@ snapshots: dependencies: is-glob: 4.0.3 + glob-to-regex.js@1.2.0(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + glob-to-regexp@0.4.1: {} glob@10.4.5: @@ -19452,7 +19067,7 @@ snapshots: globals@15.15.0: {} - globals@16.3.0: {} + globals@16.4.0: {} globalyzer@0.1.0: {} @@ -19475,8 +19090,6 @@ snapshots: globrex@0.1.2: {} - google-logging-utils@0.0.2: {} - gopd@1.2.0: {} got@12.6.1: @@ -19499,10 +19112,6 @@ snapshots: graphemer@1.4.0: {} - graphlib@2.1.8: - dependencies: - lodash: 4.17.21 - gray-matter@4.0.3: dependencies: js-yaml: 3.14.1 @@ -19527,7 +19136,7 @@ snapshots: optionalDependencies: uglify-js: 3.19.3 - happy-dom@18.0.1: + happy-dom@20.0.0: dependencies: '@types/node': 20.19.2 '@types/whatwg-mimetype': 3.0.2 @@ -19535,8 +19144,6 @@ snapshots: has-flag@4.0.0: {} - has-own-prop@2.0.0: {} - has-property-descriptors@1.0.2: dependencies: es-define-property: 1.0.1 @@ -19581,10 +19188,6 @@ snapshots: hast-util-parse-selector@2.2.5: {} - hast-util-parse-selector@3.1.1: - dependencies: - '@types/hast': 2.3.10 - hast-util-parse-selector@4.0.0: dependencies: '@types/hast': 3.0.4 @@ -19659,7 +19262,7 @@ snapshots: space-separated-tokens: 2.0.2 style-to-js: 1.1.17 unist-util-position: 5.0.0 - vfile-message: 4.0.2 + vfile-message: 4.0.3 transitivePeerDependencies: - supports-color @@ -19695,14 +19298,6 @@ snapshots: property-information: 5.6.0 space-separated-tokens: 1.1.5 - hastscript@7.2.0: - dependencies: - '@types/hast': 2.3.10 - comma-separated-tokens: 2.0.3 - hast-util-parse-selector: 3.1.1 - property-information: 6.5.0 - space-separated-tokens: 2.0.2 - hastscript@9.0.1: dependencies: '@types/hast': 3.0.4 @@ -19713,9 +19308,11 @@ snapshots: he@1.2.0: {} + highlight.js@11.11.1: {} + history@4.10.1: dependencies: - '@babel/runtime': 7.28.3 + '@babel/runtime': 7.28.4 loose-envify: 1.4.0 resolve-pathname: 3.0.0 tiny-invariant: 1.3.3 @@ -19748,8 +19345,6 @@ snapshots: whatwg-encoding: 3.1.1 optional: true - html-entities@2.6.0: {} - html-escaper@2.0.2: {} html-minifier-terser@6.1.0: @@ -19784,15 +19379,15 @@ snapshots: html-void-elements@3.0.0: {} - html-webpack-plugin@5.6.3(webpack@5.100.2): + html-webpack-plugin@5.6.3(webpack@5.102.1): dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 lodash: 4.17.21 pretty-error: 4.0.0 - tapable: 2.2.2 + tapable: 2.3.0 optionalDependencies: - webpack: 5.100.2 + webpack: 5.102.1 htmlparser2@6.1.0: dependencies: @@ -19846,7 +19441,7 @@ snapshots: dependencies: '@tootallnate/once': 2.0.0 agent-base: 6.0.2 - debug: 4.4.1 + debug: 4.4.3 transitivePeerDependencies: - supports-color optional: true @@ -19854,7 +19449,7 @@ snapshots: http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.4 - debug: 4.4.1 + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -19878,10 +19473,6 @@ snapshots: transitivePeerDependencies: - debug - http-reasons@0.1.0: {} - - http2-client@1.3.5: {} - http2-wrapper@2.2.1: dependencies: quick-lru: 5.1.1 @@ -19890,19 +19481,21 @@ snapshots: https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.4.1 + debug: 4.4.3 transitivePeerDependencies: - supports-color https-proxy-agent@7.0.6: dependencies: agent-base: 7.1.4 - debug: 4.4.1 + debug: 4.4.3 transitivePeerDependencies: - supports-color human-signals@2.1.0: {} + hyperdyperid@1.2.0: {} + i18n-iso-countries@7.14.0: dependencies: diacritics: 1.3.0 @@ -19915,6 +19508,10 @@ snapshots: dependencies: safer-buffer: 2.1.2 + iconv-lite@0.7.0: + dependencies: + safer-buffer: 2.1.2 + icss-utils@5.1.0(postcss@8.5.6): dependencies: postcss: 8.5.6 @@ -19931,14 +19528,12 @@ snapshots: immediate@3.3.0: {} - immer@9.0.21: {} - import-fresh@3.3.1: dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 - import-in-the-middle@1.14.2: + import-in-the-middle@1.14.4: dependencies: acorn: 8.15.0 acorn-import-attributes: 1.9.5(acorn@8.15.0) @@ -19970,13 +19565,13 @@ snapshots: inline-style-parser@0.2.4: {} - inquirer@8.2.6: + inquirer@8.2.7(@types/node@22.18.10): dependencies: + '@inquirer/external-editor': 1.0.2(@types/node@22.18.10) ansi-escapes: 4.3.2 chalk: 4.1.2 cli-cursor: 3.1.0 cli-width: 3.0.0 - external-editor: 3.1.0 figures: 3.2.0 lodash: 4.17.21 mute-stream: 0.0.8 @@ -19987,27 +19582,27 @@ snapshots: strip-ansi: 6.0.1 through: 2.3.8 wrap-ansi: 6.2.0 + transitivePeerDependencies: + - '@types/node' internmap@2.0.3: {} - interpret@1.4.0: {} - - intl-messageformat@10.7.16: + intl-messageformat@10.7.17: dependencies: - '@formatjs/ecma402-abstract': 2.3.4 + '@formatjs/ecma402-abstract': 2.3.5 '@formatjs/fast-memoize': 2.2.7 - '@formatjs/icu-messageformat-parser': 2.11.2 + '@formatjs/icu-messageformat-parser': 2.11.3 tslib: 2.8.1 invariant@2.2.4: dependencies: loose-envify: 1.4.0 - ioredis@5.7.0: + ioredis@5.8.1: dependencies: - '@ioredis/commands': 1.3.0 + '@ioredis/commands': 1.4.0 cluster-key-slot: 1.1.2 - debug: 4.4.1 + debug: 4.4.3 denque: 2.1.0 lodash.defaults: 4.2.0 lodash.isarguments: 3.1.0 @@ -20032,8 +19627,6 @@ snapshots: is-arrayish@0.2.1: {} - is-arrayish@0.3.2: {} - is-binary-path@2.1.0: dependencies: binary-extensions: 2.3.0 @@ -20056,6 +19649,8 @@ snapshots: is-docker@2.2.1: {} + is-docker@3.0.0: {} + is-extendable@0.1.1: {} is-extglob@2.1.1: {} @@ -20068,6 +19663,10 @@ snapshots: is-hexadecimal@2.0.1: {} + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + is-installed-globally@0.4.0: dependencies: global-dirs: 3.0.1 @@ -20077,6 +19676,8 @@ snapshots: is-interactive@2.0.0: {} + is-network-error@1.3.0: {} + is-npm@6.0.0: {} is-number@7.0.0: {} @@ -20128,6 +19729,10 @@ snapshots: dependencies: is-docker: 2.2.1 + is-wsl@3.1.0: + dependencies: + is-inside-container: 1.0.0 + is-yarn-global@0.4.1: {} isarray@0.0.1: {} @@ -20150,8 +19755,8 @@ snapshots: istanbul-lib-source-maps@5.0.6: dependencies: - '@jridgewell/trace-mapping': 0.3.30 - debug: 4.4.1 + '@jridgewell/trace-mapping': 0.3.31 + debug: 4.4.3 istanbul-lib-coverage: 3.2.2 transitivePeerDependencies: - supports-color @@ -20176,7 +19781,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.18.1 + '@types/node': 22.18.10 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -20184,13 +19789,13 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@29.7.0: dependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -20199,7 +19804,7 @@ snapshots: jiti@2.4.2: {} - jiti@2.5.1: {} + jiti@2.6.1: {} joi@17.13.3: dependencies: @@ -20211,7 +19816,7 @@ snapshots: jose@5.10.0: {} - jose@6.0.12: {} + jose@6.1.0: {} js-tokens@4.0.0: {} @@ -20242,7 +19847,7 @@ snapshots: http-proxy-agent: 5.0.0 https-proxy-agent: 5.0.1 is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.21 + nwsapi: 2.2.22 parse5: 7.3.0 saxes: 6.0.0 symbol-tree: 3.2.4 @@ -20271,7 +19876,7 @@ snapshots: http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.21 + nwsapi: 2.2.22 parse5: 7.3.0 rrweb-cssom: 0.8.0 saxes: 6.0.0 @@ -20301,7 +19906,7 @@ snapshots: http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.21 + nwsapi: 2.2.22 parse5: 7.3.0 rrweb-cssom: 0.8.0 saxes: 6.0.0 @@ -20326,46 +19931,10 @@ snapshots: jsesc@3.1.0: {} - json-bigint@1.0.0: - dependencies: - bignumber.js: 9.3.1 - json-buffer@3.0.1: {} json-parse-even-better-errors@2.3.1: {} - json-pointer@0.6.2: - dependencies: - foreach: 2.0.6 - - json-refs@3.0.15: - dependencies: - commander: 4.1.1 - graphlib: 2.1.8 - js-yaml: 3.14.1 - lodash: 4.17.21 - native-promise-only: 0.8.1 - path-loader: 1.0.12 - slash: 3.0.0 - uri-js: 4.4.1 - transitivePeerDependencies: - - supports-color - - json-schema-compare@0.2.2: - dependencies: - lodash: 4.17.21 - - json-schema-merge-allof@0.8.1: - dependencies: - compute-lcm: 1.1.2 - json-schema-compare: 0.2.2 - lodash: 4.17.21 - - json-schema-resolve-allof@1.5.0: - dependencies: - get-stdin: 5.0.1 - lodash: 4.17.21 - json-schema-traverse@0.4.1: {} json-schema-traverse@1.0.0: {} @@ -20431,9 +20000,10 @@ snapshots: type-is: 2.0.1 vary: 1.1.2 - kysely-postgres-js@2.0.0(kysely@0.28.2)(postgres@3.4.7): + kysely-postgres-js@3.0.0(kysely@0.28.2)(postgres@3.4.7): dependencies: kysely: 0.28.2 + optionalDependencies: postgres: 3.4.7 kysely@0.28.2: {} @@ -20494,7 +20064,7 @@ snapshots: lightningcss@1.30.1: dependencies: - detect-libc: 2.0.4 + detect-libc: 2.1.2 optionalDependencies: lightningcss-darwin-arm64: 1.30.1 lightningcss-darwin-x64: 1.30.1 @@ -20513,13 +20083,11 @@ snapshots: lines-and-columns@1.2.4: {} - liquid-json@0.3.1: {} - load-esm@1.0.2: {} load-tsconfig@0.2.5: {} - loader-runner@4.3.0: {} + loader-runner@4.3.1: {} loader-utils@2.0.4: dependencies: @@ -20566,13 +20134,13 @@ snapshots: log-symbols@6.0.0: dependencies: - chalk: 5.6.0 + chalk: 5.6.2 is-unicode-supported: 1.3.0 log-symbols@7.0.1: dependencies: is-unicode-supported: 2.1.0 - yoctocolors: 2.1.1 + yoctocolors: 2.1.2 long@5.3.2: {} @@ -20592,7 +20160,7 @@ snapshots: lru-cache@10.4.3: {} - lru-cache@11.1.0: {} + lru-cache@11.2.1: {} lru-cache@5.1.1: dependencies: @@ -20606,9 +20174,7 @@ snapshots: lunr@2.3.9: {} - luxon@3.6.1: {} - - luxon@3.7.1: {} + luxon@3.7.2: {} lz-string@1.5.0: {} @@ -20616,10 +20182,14 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + magic-string@0.30.19: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + magicast@0.3.5: dependencies: - '@babel/parser': 7.28.3 - '@babel/types': 7.28.2 + '@babel/parser': 7.28.4 + '@babel/types': 7.28.4 source-map-js: 1.2.1 make-dir@3.1.0: @@ -20628,7 +20198,7 @@ snapshots: make-dir@4.0.0: dependencies: - semver: 7.7.2 + semver: 7.7.3 make-fetch-happen@14.0.3: dependencies: @@ -20671,7 +20241,7 @@ snapshots: tinyqueue: 2.0.3 vt-pbf: 3.1.3 - maplibre-gl@5.6.2: + maplibre-gl@5.8.0: dependencies: '@mapbox/geojson-rewind': 0.5.2 '@mapbox/jsonlint-lines-primitives': 2.0.2 @@ -20680,7 +20250,7 @@ snapshots: '@mapbox/unitbezier': 0.0.1 '@mapbox/vector-tile': 2.0.4 '@mapbox/whoots-js': 3.1.0 - '@maplibre/maplibre-gl-style-spec': 23.3.0 + '@maplibre/maplibre-gl-style-spec': 24.2.0 '@maplibre/vt-pbf': 4.0.3 '@types/geojson': 7946.0.16 '@types/geojson-vt': 3.2.5 @@ -20706,16 +20276,14 @@ snapshots: markdown-table@3.0.4: {} - marked@11.2.0: {} - marked@7.0.4: {} math-intrinsics@1.1.0: {} - md-to-react-email@5.0.5(react@19.1.1): + md-to-react-email@5.0.5(react@19.2.0): dependencies: marked: 7.0.4 - react: 19.1.1 + react: 19.2.0 mdast-util-directive@3.1.0: dependencies: @@ -20847,7 +20415,7 @@ snapshots: parse-entities: 4.0.2 stringify-entities: 4.0.4 unist-util-stringify-position: 4.0.0 - vfile-message: 4.0.2 + vfile-message: 4.0.3 transitivePeerDependencies: - supports-color @@ -20917,6 +20485,15 @@ snapshots: dependencies: fs-monkey: 1.1.0 + memfs@4.49.0: + dependencies: + '@jsonjoy.com/json-pack': 1.20.0(tslib@2.8.1) + '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) + glob-to-regex.js: 1.2.0(tslib@2.8.1) + thingies: 2.5.0(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 + memoizee@0.4.17: dependencies: d: 1.0.2 @@ -21054,7 +20631,7 @@ snapshots: micromark-util-events-to-acorn: 2.0.3 micromark-util-symbol: 2.0.1 micromark-util-types: 2.0.2 - vfile-message: 4.0.2 + vfile-message: 4.0.3 micromark-extension-mdx-md@2.0.0: dependencies: @@ -21070,7 +20647,7 @@ snapshots: micromark-util-symbol: 2.0.1 micromark-util-types: 2.0.2 unist-util-position-from-estree: 2.0.0 - vfile-message: 4.0.2 + vfile-message: 4.0.3 micromark-extension-mdxjs@3.0.0: dependencies: @@ -21106,7 +20683,7 @@ snapshots: micromark-util-symbol: 2.0.1 micromark-util-types: 2.0.2 unist-util-position-from-estree: 2.0.0 - vfile-message: 4.0.2 + vfile-message: 4.0.3 micromark-factory-space@1.1.0: dependencies: @@ -21178,7 +20755,7 @@ snapshots: estree-util-visit: 2.0.0 micromark-util-symbol: 2.0.1 micromark-util-types: 2.0.2 - vfile-message: 4.0.2 + vfile-message: 4.0.3 micromark-util-html-tag-name@2.0.1: {} @@ -21214,7 +20791,7 @@ snapshots: micromark@4.0.2: dependencies: '@types/debug': 4.1.12 - debug: 4.4.1 + debug: 4.4.3 decode-named-character-reference: 1.2.0 devlop: 1.1.0 micromark-core-commonmark: 2.0.3 @@ -21244,10 +20821,6 @@ snapshots: mime-db@1.54.0: {} - mime-format@2.0.1: - dependencies: - charset: 1.0.1 - mime-types@2.1.18: dependencies: mime-db: 1.33.0 @@ -21268,7 +20841,8 @@ snapshots: mimic-function@5.0.1: {} - mimic-response@2.1.0: {} + mimic-response@2.1.0: + optional: true mimic-response@3.1.0: {} @@ -21276,11 +20850,11 @@ snapshots: min-indent@1.0.1: {} - mini-css-extract-plugin@2.9.2(webpack@5.100.2): + mini-css-extract-plugin@2.9.2(webpack@5.102.1): dependencies: - schema-utils: 4.3.2 - tapable: 2.2.2 - webpack: 5.100.2 + schema-utils: 4.3.3 + tapable: 2.3.0 + webpack: 5.102.1 minimalistic-assert@1.0.1: {} @@ -21310,7 +20884,7 @@ snapshots: dependencies: minipass: 7.1.2 minipass-sized: 1.0.3 - minizlib: 3.0.2 + minizlib: 3.1.0 optionalDependencies: encoding: 0.1.13 @@ -21339,7 +20913,7 @@ snapshots: minipass: 3.3.6 yallist: 4.0.0 - minizlib@3.0.2: + minizlib@3.1.0: dependencies: minipass: 7.1.2 @@ -21353,8 +20927,6 @@ snapshots: mkdirp@1.0.4: {} - mkdirp@3.0.1: {} - mnemonist@0.40.3: dependencies: obliterator: 2.0.5 @@ -21363,8 +20935,6 @@ snapshots: module-details-from-path@1.0.4: {} - monaco-editor@0.31.1: {} - moo@0.5.2: {} mri@1.2.0: {} @@ -21418,14 +20988,13 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 - nan@2.23.0: {} + nan@2.23.0: + optional: true nanoid@3.3.11: {} nanoid@5.1.5: {} - native-promise-only@0.8.1: {} - natural-compare@1.4.0: {} nearley@2.20.1: @@ -21443,19 +21012,18 @@ snapshots: neo-async@2.6.2: {} - neotraverse@0.6.15: {} - - nest-commander@3.18.0(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6)(@types/inquirer@8.2.11)(typescript@5.9.2): + nest-commander@3.20.1(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6)(@types/inquirer@8.2.11)(@types/node@22.18.10)(typescript@5.9.3): dependencies: '@fig/complete-commander': 3.2.0(commander@11.1.0) - '@golevelup/nestjs-discovery': 4.0.3(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6) + '@golevelup/nestjs-discovery': 5.0.0(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6) '@nestjs/common': 11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/core': 11.1.6(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.6)(@nestjs/websockets@11.1.6)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@types/inquirer': 8.2.11 commander: 11.1.0 - cosmiconfig: 8.3.6(typescript@5.9.2) - inquirer: 8.2.6 + cosmiconfig: 8.3.6(typescript@5.9.3) + inquirer: 8.2.7(@types/node@22.18.10) transitivePeerDependencies: + - '@types/node' - typescript nestjs-cls@5.4.3(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6)(reflect-metadata@0.2.2)(rxjs@7.8.2): @@ -21506,10 +21074,6 @@ snapshots: emojilib: 2.4.0 skin-tone: 2.0.0 - node-fetch-h2@2.3.0: - dependencies: - http2-client: 1.3.5 - node-fetch@2.7.0: dependencies: whatwg-url: 5.0.0 @@ -21525,12 +21089,12 @@ snapshots: node-gyp-build-optional-packages@5.2.2: dependencies: - detect-libc: 2.0.4 + detect-libc: 2.1.2 optional: true node-gyp-build@4.8.4: {} - node-gyp@11.3.0: + node-gyp@11.4.2: dependencies: env-paths: 2.2.1 exponential-backoff: 3.1.2 @@ -21538,20 +21102,16 @@ snapshots: make-fetch-happen: 14.0.3 nopt: 8.1.0 proc-log: 5.0.0 - semver: 7.7.2 - tar: 7.4.3 - tinyglobby: 0.2.14 + semver: 7.7.3 + tar: 7.5.1 + tinyglobby: 0.2.15 which: 5.0.0 transitivePeerDependencies: - supports-color - node-readfiles@0.2.0: - dependencies: - es6-promise: 3.3.1 + node-releases@2.0.23: {} - node-releases@2.0.19: {} - - nodemailer@7.0.5: {} + nodemailer@7.0.9: {} nopt@1.0.10: dependencies: @@ -21592,13 +21152,13 @@ snapshots: dependencies: boolbase: 1.0.0 - null-loader@4.0.1(webpack@5.100.2): + null-loader@4.0.1(webpack@5.102.1): dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.100.2 + webpack: 5.102.1 - nwsapi@2.2.21: + nwsapi@2.2.22: optional: true nypm@0.6.0: @@ -21606,50 +21166,10 @@ snapshots: citty: 0.1.6 consola: 3.4.2 pathe: 2.0.3 - pkg-types: 2.2.0 + pkg-types: 2.3.0 tinyexec: 0.3.2 - oas-kit-common@1.0.8: - dependencies: - fast-safe-stringify: 2.1.1 - - oas-linter@3.2.2: - dependencies: - '@exodus/schemasafe': 1.3.0 - should: 13.2.3 - yaml: 1.10.2 - - oas-resolver-browser@2.5.6: - dependencies: - node-fetch-h2: 2.3.0 - oas-kit-common: 1.0.8 - path-browserify: 1.0.1 - reftools: 1.1.9 - yaml: 1.10.2 - yargs: 17.7.2 - - oas-resolver@2.5.6: - dependencies: - node-fetch-h2: 2.3.0 - oas-kit-common: 1.0.8 - reftools: 1.1.9 - yaml: 1.10.2 - yargs: 17.7.2 - - oas-schema-walker@1.1.5: {} - - oas-validator@5.0.8: - dependencies: - call-me-maybe: 1.0.2 - oas-kit-common: 1.0.8 - oas-linter: 3.2.2 - oas-resolver: 2.5.6 - oas-schema-walker: 1.1.5 - reftools: 1.1.9 - should: 13.2.3 - yaml: 1.10.2 - - oauth4webapi@3.7.0: {} + oauth4webapi@3.8.2: {} object-assign@4.1.1: {} @@ -21672,18 +21192,18 @@ snapshots: obuf@1.1.2: {} - oidc-provider@9.4.1: + oidc-provider@9.5.1: dependencies: '@koa/cors': 5.0.0 '@koa/router': 14.0.0 - debug: 4.4.1 + debug: 4.4.3 eta: 3.5.0 - jose: 6.0.12 + jose: 6.1.0 jsesc: 3.1.0 koa: 3.0.1 nanoid: 5.1.5 - quick-lru: 7.0.1 - raw-body: 3.0.0 + quick-lru: 7.2.0 + raw-body: 3.0.1 transitivePeerDependencies: - supports-color @@ -21705,40 +21225,25 @@ snapshots: dependencies: mimic-function: 5.0.1 + open@10.2.0: + dependencies: + default-browser: 5.2.1 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + wsl-utils: 0.1.0 + open@8.4.2: dependencies: define-lazy-prop: 2.0.0 is-docker: 2.2.1 is-wsl: 2.2.0 - openapi-to-postmanv2@4.25.0(encoding@0.1.13): - dependencies: - ajv: 8.11.0 - ajv-draft-04: 1.0.0(ajv@8.11.0) - ajv-formats: 2.1.1(ajv@8.11.0) - async: 3.2.4 - commander: 2.20.3 - graphlib: 2.1.8 - js-yaml: 4.1.0 - json-pointer: 0.6.2 - json-schema-merge-allof: 0.8.1 - lodash: 4.17.21 - neotraverse: 0.6.15 - oas-resolver-browser: 2.5.6 - object-hash: 3.0.0 - path-browserify: 1.0.1 - postman-collection: 4.5.0 - swagger2openapi: 7.0.8(encoding@0.1.13) - yaml: 1.10.2 - transitivePeerDependencies: - - encoding - opener@1.5.2: {} - openid-client@6.6.4: + openid-client@6.8.1: dependencies: - jose: 6.0.12 - oauth4webapi: 3.7.0 + jose: 6.1.0 + oauth4webapi: 3.8.2 optionator@0.9.4: dependencies: @@ -21763,7 +21268,7 @@ snapshots: ora@8.2.0: dependencies: - chalk: 5.6.0 + chalk: 5.6.2 cli-cursor: 5.0.0 cli-spinners: 2.9.2 is-interactive: 2.0.0 @@ -21771,9 +21276,7 @@ snapshots: log-symbols: 6.0.0 stdin-discarder: 0.2.2 string-width: 7.2.0 - strip-ansi: 7.1.0 - - os-tmpdir@1.0.2: {} + strip-ansi: 7.1.2 p-cancelable@3.0.0: {} @@ -21814,9 +21317,10 @@ snapshots: eventemitter3: 4.0.7 p-timeout: 3.2.0 - p-retry@4.6.2: + p-retry@6.2.1: dependencies: - '@types/retry': 0.12.0 + '@types/retry': 0.12.2 + is-network-error: 1.3.0 retry: 0.13.1 p-timeout@3.2.0: @@ -21832,7 +21336,7 @@ snapshots: got: 12.6.1 registry-auth-token: 5.1.0 registry-url: 6.0.1 - semver: 7.7.2 + semver: 7.7.3 param-case@3.0.4: dependencies: @@ -21856,7 +21360,7 @@ snapshots: parse-json@5.2.0: dependencies: '@babel/code-frame': 7.27.1 - error-ex: 1.3.2 + error-ex: 1.3.4 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -21887,8 +21391,6 @@ snapshots: no-case: 3.0.4 tslib: 2.8.1 - path-browserify@1.0.1: {} - path-exists@4.0.0: {} path-exists@5.0.0: {} @@ -21899,13 +21401,6 @@ snapshots: path-key@3.1.1: {} - path-loader@1.0.12: - dependencies: - native-promise-only: 0.8.1 - superagent: 7.1.6 - transitivePeerDependencies: - - supports-color - path-parse@1.0.7: {} path-scurry@1.11.1: @@ -21915,7 +21410,7 @@ snapshots: path-scurry@2.0.0: dependencies: - lru-cache: 11.1.0 + lru-cache: 11.2.1 minipass: 7.1.2 path-source@0.1.3: @@ -21933,12 +21428,9 @@ snapshots: path-to-regexp@8.2.0: {} - path-type@4.0.0: {} + path-to-regexp@8.3.0: {} - path@0.12.7: - dependencies: - process: 0.11.10 - util: 0.10.4 + path-type@4.0.0: {} pathe@2.0.3: {} @@ -22006,17 +21498,17 @@ snapshots: dependencies: find-up: 6.3.0 - pkg-types@2.2.0: + pkg-types@2.3.0: dependencies: confbox: 0.2.2 exsolve: 1.0.7 pathe: 2.0.3 - playwright-core@1.54.2: {} + playwright-core@1.56.0: {} - playwright@1.54.2: + playwright@1.56.0: dependencies: - playwright-core: 1.54.2 + playwright-core: 1.56.0 optionalDependencies: fsevents: 2.3.2 @@ -22024,7 +21516,7 @@ snapshots: pmtiles@3.2.1: dependencies: - '@types/leaflet': 1.9.19 + '@types/leaflet': 1.9.20 fflate: 0.8.2 pmtiles@4.3.0: @@ -22078,7 +21570,7 @@ snapshots: postcss-colormin@6.1.0(postcss@8.5.6): dependencies: - browserslist: 4.25.3 + browserslist: 4.26.3 caniuse-api: 3.0.0 colord: 2.9.3 postcss: 8.5.6 @@ -22086,7 +21578,7 @@ snapshots: postcss-convert-values@6.1.0(postcss@8.5.6): dependencies: - browserslist: 4.25.3 + browserslist: 4.26.3 postcss: 8.5.6 postcss-value-parser: 4.2.0 @@ -22179,7 +21671,7 @@ snapshots: read-cache: 1.0.0 resolve: 1.22.10 - postcss-js@4.0.1(postcss@8.5.6): + postcss-js@4.1.0(postcss@8.5.6): dependencies: camelcase-css: 2.0.1 postcss: 8.5.6 @@ -22200,20 +21692,21 @@ snapshots: optionalDependencies: postcss: 8.5.6 - postcss-load-config@4.0.2(postcss@8.5.6): + postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.6)(yaml@2.8.1): dependencies: lilconfig: 3.1.3 - yaml: 2.8.1 optionalDependencies: - postcss: 8.5.6 - - postcss-loader@7.3.4(postcss@8.5.6)(typescript@5.9.2)(webpack@5.100.2): - dependencies: - cosmiconfig: 8.3.6(typescript@5.9.2) jiti: 1.21.7 postcss: 8.5.6 - semver: 7.7.2 - webpack: 5.100.2 + yaml: 2.8.1 + + postcss-loader@7.3.4(postcss@8.5.6)(typescript@5.9.3)(webpack@5.102.1): + dependencies: + cosmiconfig: 8.3.6(typescript@5.9.3) + jiti: 1.21.7 + postcss: 8.5.6 + semver: 7.7.3 + webpack: 5.102.1 transitivePeerDependencies: - typescript @@ -22236,7 +21729,7 @@ snapshots: postcss-merge-rules@6.1.1(postcss@8.5.6): dependencies: - browserslist: 4.25.3 + browserslist: 4.26.3 caniuse-api: 3.0.0 cssnano-utils: 4.0.2(postcss@8.5.6) postcss: 8.5.6 @@ -22256,7 +21749,7 @@ snapshots: postcss-minify-params@6.1.0(postcss@8.5.6): dependencies: - browserslist: 4.25.3 + browserslist: 4.26.3 cssnano-utils: 4.0.2(postcss@8.5.6) postcss: 8.5.6 postcss-value-parser: 4.2.0 @@ -22330,7 +21823,7 @@ snapshots: postcss-normalize-unicode@6.1.0(postcss@8.5.6): dependencies: - browserslist: 4.25.3 + browserslist: 4.26.3 postcss: 8.5.6 postcss-value-parser: 4.2.0 @@ -22404,7 +21897,7 @@ snapshots: '@csstools/postcss-trigonometric-functions': 4.0.9(postcss@8.5.6) '@csstools/postcss-unset-value': 4.0.0(postcss@8.5.6) autoprefixer: 10.4.21(postcss@8.5.6) - browserslist: 4.25.3 + browserslist: 4.26.3 css-blank-pseudo: 7.0.1(postcss@8.5.6) css-has-pseudo: 7.0.2(postcss@8.5.6) css-prefers-color-scheme: 10.0.0(postcss@8.5.6) @@ -22448,7 +21941,7 @@ snapshots: postcss-reduce-initial@6.1.0(postcss@8.5.6): dependencies: - browserslist: 4.25.3 + browserslist: 4.26.3 caniuse-api: 3.0.0 postcss: 8.5.6 @@ -22524,33 +22017,6 @@ snapshots: postgres@3.4.7: {} - postman-code-generators@1.14.2: - dependencies: - async: 3.2.2 - detect-package-manager: 3.0.2 - lodash: 4.17.21 - path: 0.12.7 - postman-collection: 4.5.0 - shelljs: 0.8.5 - - postman-collection@4.5.0: - dependencies: - '@faker-js/faker': 5.5.3 - file-type: 3.9.0 - http-reasons: 0.1.0 - iconv-lite: 0.6.3 - liquid-json: 0.3.1 - lodash: 4.17.21 - mime-format: 2.0.1 - mime-types: 2.1.35 - postman-url-encoder: 3.0.5 - semver: 7.6.3 - uuid: 8.3.2 - - postman-url-encoder@3.0.5: - dependencies: - punycode: 2.3.1 - potpack@1.0.2: {} potpack@2.1.0: {} @@ -22561,19 +22027,19 @@ snapshots: dependencies: fast-diff: 1.3.0 - prettier-plugin-organize-imports@4.2.0(prettier@3.6.2)(typescript@5.9.2): + prettier-plugin-organize-imports@4.3.0(prettier@3.6.2)(typescript@5.9.3): dependencies: prettier: 3.6.2 - typescript: 5.9.2 + typescript: 5.9.3 prettier-plugin-sort-json@4.1.1(prettier@3.6.2): dependencies: prettier: 3.6.2 - prettier-plugin-svelte@3.4.0(prettier@3.6.2)(svelte@5.35.5): + prettier-plugin-svelte@3.4.0(prettier@3.6.2)(svelte@5.39.11): dependencies: prettier: 3.6.2 - svelte: 5.35.5 + svelte: 5.39.11 prettier@3.6.2: {} @@ -22652,7 +22118,7 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 22.18.1 + '@types/node': 22.18.10 long: 5.3.2 protocol-buffers-schema@3.6.0: {} @@ -22701,7 +22167,7 @@ snapshots: quick-lru@5.1.1: {} - quick-lru@7.0.1: {} + quick-lru@7.2.0: {} quickselect@2.0.0: {} @@ -22729,18 +22195,18 @@ snapshots: iconv-lite: 0.4.24 unpipe: 1.0.0 - raw-body@3.0.0: + raw-body@3.0.1: dependencies: bytes: 3.1.2 http-errors: 2.0.0 - iconv-lite: 0.6.3 + iconv-lite: 0.7.0 unpipe: 1.0.0 - raw-loader@4.0.2(webpack@5.100.2): + raw-loader@4.0.2(webpack@5.102.1): dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.100.2 + webpack: 5.102.1 rc@1.2.8: dependencies: @@ -22755,20 +22221,19 @@ snapshots: react: 18.3.1 scheduler: 0.23.2 - react-dom@19.1.1(react@19.1.1): + react-dom@19.2.0(react@19.2.0): dependencies: - react: 19.1.1 - scheduler: 0.26.0 + react: 19.2.0 + scheduler: 0.27.0 - react-email@4.2.8: + react-email@4.3.0: dependencies: - '@babel/parser': 7.28.3 - '@babel/traverse': 7.28.3 - chalk: 5.6.0 + '@babel/parser': 7.28.4 + '@babel/traverse': 7.28.4 chokidar: 4.0.3 commander: 13.1.0 debounce: 2.2.0 - esbuild: 0.25.9 + esbuild: 0.25.10 glob: 11.0.3 jiti: 2.4.2 log-symbols: 7.0.1 @@ -22794,39 +22259,25 @@ snapshots: dependencies: react: 18.3.1 - react-loadable-ssr-addon-v5-slorber@1.0.1(@docusaurus/react-loadable@6.0.0(react@18.3.1))(webpack@5.100.2): + react-loadable-ssr-addon-v5-slorber@1.0.1(@docusaurus/react-loadable@6.0.0(react@18.3.1))(webpack@5.102.1): dependencies: - '@babel/runtime': 7.28.3 + '@babel/runtime': 7.28.4 react-loadable: '@docusaurus/react-loadable@6.0.0(react@18.3.1)' - webpack: 5.100.2 - - react-magic-dropzone@1.0.1: {} + webpack: 5.102.1 react-promise-suspense@0.3.4: dependencies: fast-deep-equal: 2.0.1 - react-redux@7.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.28.3 - '@types/react-redux': 7.1.34 - hoist-non-react-statics: 3.3.2 - loose-envify: 1.4.0 - prop-types: 15.8.1 - react: 18.3.1 - react-is: 17.0.2 - optionalDependencies: - react-dom: 18.3.1(react@18.3.1) - react-router-config@5.1.1(react-router@5.3.4(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.28.3 + '@babel/runtime': 7.28.4 react: 18.3.1 react-router: 5.3.4(react@18.3.1) react-router-dom@5.3.4(react@18.3.1): dependencies: - '@babel/runtime': 7.28.3 + '@babel/runtime': 7.28.4 history: 4.10.1 loose-envify: 1.4.0 prop-types: 15.8.1 @@ -22837,7 +22288,7 @@ snapshots: react-router@5.3.4(react@18.3.1): dependencies: - '@babel/runtime': 7.28.3 + '@babel/runtime': 7.28.4 history: 4.10.1 hoist-non-react-statics: 3.3.2 loose-envify: 1.4.0 @@ -22852,7 +22303,7 @@ snapshots: dependencies: loose-envify: 1.4.0 - react@19.1.1: {} + react@19.2.0: {} read-cache@1.0.0: dependencies: @@ -22892,25 +22343,20 @@ snapshots: readdirp@4.1.2: {} - rechoir@0.6.2: - dependencies: - resolve: 1.22.10 - recma-build-jsx@1.0.0: dependencies: '@types/estree': 1.0.8 estree-util-build-jsx: 3.0.1 vfile: 6.0.3 - recma-jsx@1.0.0(acorn@8.15.0): + recma-jsx@1.0.1(acorn@8.15.0): dependencies: + acorn: 8.15.0 acorn-jsx: 5.3.2(acorn@8.15.0) estree-util-to-js: 2.0.0 recma-parse: 1.0.0 recma-stringify: 1.0.0 unified: 11.0.5 - transitivePeerDependencies: - - acorn recma-parse@1.0.0: dependencies: @@ -22937,29 +22383,8 @@ snapshots: dependencies: redis-errors: 1.2.0 - redux-devtools-extension@2.13.9(redux@4.2.1): - dependencies: - redux: 4.2.1 - - redux-thunk@2.4.2(redux@4.2.1): - dependencies: - redux: 4.2.1 - - redux@4.2.1: - dependencies: - '@babel/runtime': 7.28.3 - reflect-metadata@0.2.2: {} - refractor@4.9.0: - dependencies: - '@types/hast': 2.3.10 - '@types/prismjs': 1.26.5 - hastscript: 7.2.0 - parse-entities: 4.0.2 - - reftools@1.1.9: {} - regenerate-unicode-properties@10.2.0: dependencies: regenerate: 1.4.2 @@ -23049,7 +22474,7 @@ snapshots: transitivePeerDependencies: - supports-color - remark-mdx@3.1.0: + remark-mdx@3.1.1: dependencies: mdast-util-mdx: 3.0.0 micromark-extension-mdxjs: 3.0.0 @@ -23093,11 +22518,10 @@ snapshots: require-from-string@2.0.2: {} - require-in-the-middle@7.5.2: + require-in-the-middle@8.0.0: dependencies: - debug: 4.4.1 + debug: 4.4.3 module-details-from-path: 1.0.4 - resolve: 1.22.10 transitivePeerDependencies: - supports-color @@ -23107,8 +22531,6 @@ snapshots: requires-port@1.0.0: {} - reselect@4.1.8: {} - resolve-alpn@1.2.1: {} resolve-from@4.0.0: {} @@ -23156,55 +22578,52 @@ snapshots: dependencies: glob: 7.2.3 - rimraf@6.0.1: - dependencies: - glob: 11.0.3 - package-json-from-dist: 1.0.1 - robust-predicates@3.0.2: {} - rollup-plugin-visualizer@6.0.3(rollup@4.46.3): + rollup-plugin-visualizer@6.0.4(rollup@4.52.4): dependencies: open: 8.4.2 picomatch: 4.0.3 - source-map: 0.7.4 + source-map: 0.7.6 yargs: 17.7.2 optionalDependencies: - rollup: 4.46.3 + rollup: 4.52.4 - rollup@4.46.3: + rollup@4.52.4: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.46.3 - '@rollup/rollup-android-arm64': 4.46.3 - '@rollup/rollup-darwin-arm64': 4.46.3 - '@rollup/rollup-darwin-x64': 4.46.3 - '@rollup/rollup-freebsd-arm64': 4.46.3 - '@rollup/rollup-freebsd-x64': 4.46.3 - '@rollup/rollup-linux-arm-gnueabihf': 4.46.3 - '@rollup/rollup-linux-arm-musleabihf': 4.46.3 - '@rollup/rollup-linux-arm64-gnu': 4.46.3 - '@rollup/rollup-linux-arm64-musl': 4.46.3 - '@rollup/rollup-linux-loongarch64-gnu': 4.46.3 - '@rollup/rollup-linux-ppc64-gnu': 4.46.3 - '@rollup/rollup-linux-riscv64-gnu': 4.46.3 - '@rollup/rollup-linux-riscv64-musl': 4.46.3 - '@rollup/rollup-linux-s390x-gnu': 4.46.3 - '@rollup/rollup-linux-x64-gnu': 4.46.3 - '@rollup/rollup-linux-x64-musl': 4.46.3 - '@rollup/rollup-win32-arm64-msvc': 4.46.3 - '@rollup/rollup-win32-ia32-msvc': 4.46.3 - '@rollup/rollup-win32-x64-msvc': 4.46.3 + '@rollup/rollup-android-arm-eabi': 4.52.4 + '@rollup/rollup-android-arm64': 4.52.4 + '@rollup/rollup-darwin-arm64': 4.52.4 + '@rollup/rollup-darwin-x64': 4.52.4 + '@rollup/rollup-freebsd-arm64': 4.52.4 + '@rollup/rollup-freebsd-x64': 4.52.4 + '@rollup/rollup-linux-arm-gnueabihf': 4.52.4 + '@rollup/rollup-linux-arm-musleabihf': 4.52.4 + '@rollup/rollup-linux-arm64-gnu': 4.52.4 + '@rollup/rollup-linux-arm64-musl': 4.52.4 + '@rollup/rollup-linux-loong64-gnu': 4.52.4 + '@rollup/rollup-linux-ppc64-gnu': 4.52.4 + '@rollup/rollup-linux-riscv64-gnu': 4.52.4 + '@rollup/rollup-linux-riscv64-musl': 4.52.4 + '@rollup/rollup-linux-s390x-gnu': 4.52.4 + '@rollup/rollup-linux-x64-gnu': 4.52.4 + '@rollup/rollup-linux-x64-musl': 4.52.4 + '@rollup/rollup-openharmony-arm64': 4.52.4 + '@rollup/rollup-win32-arm64-msvc': 4.52.4 + '@rollup/rollup-win32-ia32-msvc': 4.52.4 + '@rollup/rollup-win32-x64-gnu': 4.52.4 + '@rollup/rollup-win32-x64-msvc': 4.52.4 fsevents: 2.3.3 router@2.2.0: dependencies: - debug: 4.4.1 + debug: 4.4.3 depd: 2.0.0 is-promise: 4.0.0 parseurl: 1.3.3 - path-to-regexp: 8.2.0 + path-to-regexp: 8.3.0 transitivePeerDependencies: - supports-color @@ -23218,16 +22637,18 @@ snapshots: postcss: 8.5.6 strip-json-comments: 3.1.1 + run-applescript@7.1.0: {} + run-async@2.4.1: {} run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 - runed@0.29.2(svelte@5.35.5): + runed@0.29.2(svelte@5.39.11): dependencies: esm-env: 1.2.2 - svelte: 5.35.5 + svelte: 5.39.11 rw@1.3.3: {} @@ -23273,7 +22694,7 @@ snapshots: dependencies: loose-envify: 1.4.0 - scheduler@0.26.0: {} + scheduler@0.27.0: {} schema-dts@1.1.5: {} @@ -23283,7 +22704,7 @@ snapshots: ajv: 6.12.6 ajv-keywords: 3.5.2(ajv@6.12.6) - schema-utils@4.3.2: + schema-utils@4.3.3: dependencies: '@types/json-schema': 7.0.15 ajv: 8.17.1 @@ -23310,13 +22731,11 @@ snapshots: semver-diff@4.0.0: dependencies: - semver: 7.7.2 + semver: 7.7.3 semver@6.3.1: {} - semver@7.6.3: {} - - semver@7.7.2: {} + semver@7.7.3: {} send@0.19.0: dependencies: @@ -23338,7 +22757,7 @@ snapshots: send@1.2.0: dependencies: - debug: 4.4.1 + debug: 4.4.3 encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 @@ -23413,11 +22832,6 @@ snapshots: setprototypeof@1.2.0: {} - sha.js@2.4.11: - dependencies: - inherits: 2.0.4 - safe-buffer: 5.2.1 - shallow-clone@3.0.1: dependencies: kind-of: 6.0.3 @@ -23433,36 +22847,36 @@ snapshots: stream-source: 0.3.5 text-encoding: 0.6.4 - sharp@0.34.3: + sharp@0.34.4: dependencies: - color: 4.2.3 - detect-libc: 2.0.4 + '@img/colour': 1.0.0 + detect-libc: 2.1.2 node-addon-api: 8.5.0 - node-gyp: 11.3.0 - semver: 7.7.2 + node-gyp: 11.4.2 + semver: 7.7.3 optionalDependencies: - '@img/sharp-darwin-arm64': 0.34.3 - '@img/sharp-darwin-x64': 0.34.3 - '@img/sharp-libvips-darwin-arm64': 1.2.0 - '@img/sharp-libvips-darwin-x64': 1.2.0 - '@img/sharp-libvips-linux-arm': 1.2.0 - '@img/sharp-libvips-linux-arm64': 1.2.0 - '@img/sharp-libvips-linux-ppc64': 1.2.0 - '@img/sharp-libvips-linux-s390x': 1.2.0 - '@img/sharp-libvips-linux-x64': 1.2.0 - '@img/sharp-libvips-linuxmusl-arm64': 1.2.0 - '@img/sharp-libvips-linuxmusl-x64': 1.2.0 - '@img/sharp-linux-arm': 0.34.3 - '@img/sharp-linux-arm64': 0.34.3 - '@img/sharp-linux-ppc64': 0.34.3 - '@img/sharp-linux-s390x': 0.34.3 - '@img/sharp-linux-x64': 0.34.3 - '@img/sharp-linuxmusl-arm64': 0.34.3 - '@img/sharp-linuxmusl-x64': 0.34.3 - '@img/sharp-wasm32': 0.34.3 - '@img/sharp-win32-arm64': 0.34.3 - '@img/sharp-win32-ia32': 0.34.3 - '@img/sharp-win32-x64': 0.34.3 + '@img/sharp-darwin-arm64': 0.34.4 + '@img/sharp-darwin-x64': 0.34.4 + '@img/sharp-libvips-darwin-arm64': 1.2.3 + '@img/sharp-libvips-darwin-x64': 1.2.3 + '@img/sharp-libvips-linux-arm': 1.2.3 + '@img/sharp-libvips-linux-arm64': 1.2.3 + '@img/sharp-libvips-linux-ppc64': 1.2.3 + '@img/sharp-libvips-linux-s390x': 1.2.3 + '@img/sharp-libvips-linux-x64': 1.2.3 + '@img/sharp-libvips-linuxmusl-arm64': 1.2.3 + '@img/sharp-libvips-linuxmusl-x64': 1.2.3 + '@img/sharp-linux-arm': 0.34.4 + '@img/sharp-linux-arm64': 0.34.4 + '@img/sharp-linux-ppc64': 0.34.4 + '@img/sharp-linux-s390x': 0.34.4 + '@img/sharp-linux-x64': 0.34.4 + '@img/sharp-linuxmusl-arm64': 0.34.4 + '@img/sharp-linuxmusl-x64': 0.34.4 + '@img/sharp-wasm32': 0.34.4 + '@img/sharp-win32-arm64': 0.34.4 + '@img/sharp-win32-ia32': 0.34.4 + '@img/sharp-win32-x64': 0.34.4 transitivePeerDependencies: - supports-color @@ -23474,38 +22888,6 @@ snapshots: shell-quote@1.8.3: {} - shelljs@0.8.5: - dependencies: - glob: 7.2.3 - interpret: 1.4.0 - rechoir: 0.6.2 - - should-equal@2.0.0: - dependencies: - should-type: 1.4.0 - - should-format@3.0.3: - dependencies: - should-type: 1.4.0 - should-type-adaptors: 1.1.0 - - should-type-adaptors@1.1.0: - dependencies: - should-type: 1.4.0 - should-util: 1.0.1 - - should-type@1.4.0: {} - - should-util@1.0.1: {} - - should@13.2.3: - dependencies: - should-equal: 2.0.0 - should-format: 3.0.3 - should-type: 1.4.0 - should-type-adaptors: 1.1.0 - should-util: 1.0.1 - side-channel-list@1.0.0: dependencies: es-errors: 1.3.0 @@ -23540,17 +22922,17 @@ snapshots: signal-exit@4.1.0: {} - simple-concat@1.0.1: {} + simple-concat@1.0.1: + optional: true simple-get@3.1.1: dependencies: decompress-response: 4.2.1 once: 1.4.0 simple-concat: 1.0.1 + optional: true - simple-swizzle@0.2.2: - dependencies: - is-arrayish: 0.3.2 + simple-icons@15.16.1: {} sirv@2.0.4: dependencies: @@ -23558,7 +22940,7 @@ snapshots: mrmime: 2.0.1 totalist: 3.0.1 - sirv@3.0.1: + sirv@3.0.2: dependencies: '@polka/url': 1.0.0-next.29 mrmime: 2.0.1 @@ -23640,7 +23022,7 @@ snapshots: socks-proxy-agent@8.0.5: dependencies: agent-base: 7.1.4 - debug: 4.4.1 + debug: 4.4.3 socks: 2.8.7 transitivePeerDependencies: - supports-color @@ -23663,13 +23045,15 @@ snapshots: source-map@0.7.4: {} + source-map@0.7.6: {} + space-separated-tokens@1.1.5: {} space-separated-tokens@2.0.2: {} spdy-transport@3.0.0: dependencies: - debug: 4.4.1 + debug: 4.4.3 detect-node: 2.1.0 hpack.js: 2.1.6 obuf: 1.1.2 @@ -23680,7 +23064,7 @@ snapshots: spdy@4.0.2: dependencies: - debug: 4.4.1 + debug: 4.4.3 handle-thing: 2.0.1 http-deceiver: 1.2.7 select-hose: 2.0.0 @@ -23694,21 +23078,19 @@ snapshots: sprintf-js@1.0.3: {} - sql-formatter@15.6.6: + sql-formatter@15.6.10: dependencies: argparse: 2.0.1 nearley: 2.20.1 - sql-highlight@6.1.0: {} - srcset@4.0.0: {} ssh-remote-port-forward@1.0.4: dependencies: '@types/ssh2': 0.5.52 - ssh2: 1.16.0 + ssh2: 1.17.0 - ssh2@1.16.0: + ssh2@1.17.0: dependencies: asn1: 0.2.6 bcrypt-pbkdf: 1.0.2 @@ -23724,8 +23106,6 @@ snapshots: standard-as-callback@2.1.0: {} - state-local@1.0.7: {} - statuses@1.5.0: {} statuses@2.0.1: {} @@ -23740,12 +23120,11 @@ snapshots: streamsearch@1.1.0: {} - streamx@2.22.1: + streamx@2.23.0: dependencies: + events-universal: 1.0.1 fast-fifo: 1.3.2 text-decoder: 1.2.3 - optionalDependencies: - bare-events: 2.6.1 string-width@4.2.3: dependencies: @@ -23757,13 +23136,13 @@ snapshots: dependencies: eastasianwidth: 0.2.0 emoji-regex: 9.2.2 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 string-width@7.2.0: dependencies: - emoji-regex: 10.4.0 - get-east-asian-width: 1.3.0 - strip-ansi: 7.1.0 + emoji-regex: 10.6.0 + get-east-asian-width: 1.4.0 + strip-ansi: 7.1.2 string_decoder@1.1.1: dependencies: @@ -23788,9 +23167,9 @@ snapshots: dependencies: ansi-regex: 5.0.1 - strip-ansi@7.1.0: + strip-ansi@7.1.2: dependencies: - ansi-regex: 6.2.0 + ansi-regex: 6.2.2 strip-bom-string@1.0.0: {} @@ -23814,7 +23193,7 @@ snapshots: dependencies: js-tokens: 9.0.1 - striptags@3.2.0: {} + strnum@2.1.1: {} strtok3@10.3.4: dependencies: @@ -23830,7 +23209,7 @@ snapshots: stylehacks@6.1.1(postcss@8.5.6): dependencies: - browserslist: 4.25.3 + browserslist: 4.26.3 postcss: 8.5.6 postcss-selector-parser: 6.1.2 @@ -23848,7 +23227,7 @@ snapshots: dependencies: component-emitter: 1.3.1 cookiejar: 2.1.4 - debug: 4.4.1 + debug: 4.4.3 fast-safe-stringify: 2.1.1 form-data: 4.0.4 formidable: 3.5.4 @@ -23858,22 +23237,6 @@ snapshots: transitivePeerDependencies: - supports-color - superagent@7.1.6: - dependencies: - component-emitter: 1.3.1 - cookiejar: 2.1.4 - debug: 4.4.1 - fast-safe-stringify: 2.1.1 - form-data: 4.0.4 - formidable: 2.1.5 - methods: 1.1.2 - mime: 2.6.0 - qs: 6.14.0 - readable-stream: 3.6.2 - semver: 7.7.2 - transitivePeerDependencies: - - supports-color - supercluster@7.1.5: dependencies: kdbush: 3.0.0 @@ -23899,19 +23262,19 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte-check@4.3.1(picomatch@4.0.3)(svelte@5.35.5)(typescript@5.9.2): + svelte-check@4.3.3(picomatch@4.0.3)(svelte@5.39.11)(typescript@5.9.3): dependencies: - '@jridgewell/trace-mapping': 0.3.30 + '@jridgewell/trace-mapping': 0.3.31 chokidar: 4.0.3 fdir: 6.5.0(picomatch@4.0.3) picocolors: 1.1.1 sade: 1.8.1 - svelte: 5.35.5 - typescript: 5.9.2 + svelte: 5.39.11 + typescript: 5.9.3 transitivePeerDependencies: - picomatch - svelte-eslint-parser@1.3.1(svelte@5.35.5): + svelte-eslint-parser@1.3.3(svelte@5.39.11): dependencies: eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 @@ -23920,50 +23283,54 @@ snapshots: postcss-scss: 4.0.9(postcss@8.5.6) postcss-selector-parser: 7.1.0 optionalDependencies: - svelte: 5.35.5 + svelte: 5.39.11 - svelte-gestures@5.1.4: {} + svelte-gestures@5.2.2: {} - svelte-i18n@4.0.1(svelte@5.35.5): + svelte-highlight@7.8.4: + dependencies: + highlight.js: 11.11.1 + + svelte-i18n@4.0.1(svelte@5.39.11): dependencies: cli-color: 2.0.4 deepmerge: 4.3.1 esbuild: 0.19.12 estree-walker: 2.0.2 - intl-messageformat: 10.7.16 + intl-messageformat: 10.7.17 sade: 1.8.1 - svelte: 5.35.5 + svelte: 5.39.11 tiny-glob: 0.2.9 - svelte-maplibre@1.2.0(svelte@5.35.5): + svelte-maplibre@1.2.1(svelte@5.39.11): dependencies: d3-geo: 3.1.1 dequal: 2.0.3 just-compare: 2.3.0 - maplibre-gl: 5.6.2 + maplibre-gl: 5.8.0 pmtiles: 3.2.1 - svelte: 5.35.5 + svelte: 5.39.11 - svelte-parse-markup@0.1.5(svelte@5.35.5): + svelte-parse-markup@0.1.5(svelte@5.39.11): dependencies: - svelte: 5.35.5 + svelte: 5.39.11 - svelte-persisted-store@0.12.0(svelte@5.35.5): + svelte-persisted-store@0.12.0(svelte@5.39.11): dependencies: - svelte: 5.35.5 + svelte: 5.39.11 - svelte-toolbelt@0.9.3(svelte@5.35.5): + svelte-toolbelt@0.9.3(svelte@5.39.11): dependencies: clsx: 2.1.1 - runed: 0.29.2(svelte@5.35.5) + runed: 0.29.2(svelte@5.39.11) style-to-object: 1.0.9 - svelte: 5.35.5 + svelte: 5.39.11 - svelte@5.35.5: + svelte@5.39.11: dependencies: - '@ampproject/remapping': 2.3.0 + '@jridgewell/remapping': 2.3.5 '@jridgewell/sourcemap-codec': 1.5.5 - '@sveltejs/acorn-typescript': 1.0.5(acorn@8.15.0) + '@sveltejs/acorn-typescript': 1.0.6(acorn@8.15.0) '@types/estree': 1.0.8 acorn: 8.15.0 aria-query: 5.3.2 @@ -23973,8 +23340,8 @@ snapshots: esrap: 2.1.0 is-reference: 3.0.3 locate-character: 3.0.0 - magic-string: 0.30.17 - zimmerframe: 1.1.2 + magic-string: 0.30.19 + zimmerframe: 1.1.4 svg-parser@2.0.4: {} @@ -23992,22 +23359,6 @@ snapshots: dependencies: '@scarf/scarf': 1.4.0 - swagger2openapi@7.0.8(encoding@0.1.13): - dependencies: - call-me-maybe: 1.0.2 - node-fetch: 2.7.0(encoding@0.1.13) - node-fetch-h2: 2.3.0 - node-readfiles: 0.2.0 - oas-kit-common: 1.0.8 - oas-resolver: 2.5.6 - oas-schema-walker: 1.1.5 - oas-validator: 5.0.8 - reftools: 1.1.9 - yaml: 1.10.2 - yargs: 17.7.2 - transitivePeerDependencies: - - encoding - symbol-observable@4.0.0: {} symbol-tree@3.2.4: @@ -24023,27 +23374,27 @@ snapshots: tailwind-merge@3.3.1: {} - tailwind-variants@2.1.0(tailwind-merge@3.3.1)(tailwindcss@4.1.12): + tailwind-variants@3.1.1(tailwind-merge@3.3.1)(tailwindcss@4.1.14): dependencies: - tailwindcss: 4.1.12 + tailwindcss: 4.1.14 optionalDependencies: tailwind-merge: 3.3.1 - tailwindcss-email-variants@3.0.4(tailwindcss@3.4.17): + tailwindcss-email-variants@3.0.4(tailwindcss@3.4.18(yaml@2.8.1)): dependencies: - tailwindcss: 3.4.17 + tailwindcss: 3.4.18(yaml@2.8.1) - tailwindcss-mso@2.0.2(tailwindcss@3.4.17): + tailwindcss-mso@2.0.2(tailwindcss@3.4.18(yaml@2.8.1)): dependencies: - tailwindcss: 3.4.17 + tailwindcss: 3.4.18(yaml@2.8.1) - tailwindcss-preset-email@1.4.0(tailwindcss@3.4.17): + tailwindcss-preset-email@1.4.0(tailwindcss@3.4.18(yaml@2.8.1)): dependencies: - tailwindcss: 3.4.17 - tailwindcss-email-variants: 3.0.4(tailwindcss@3.4.17) - tailwindcss-mso: 2.0.2(tailwindcss@3.4.17) + tailwindcss: 3.4.18(yaml@2.8.1) + tailwindcss-email-variants: 3.0.4(tailwindcss@3.4.18(yaml@2.8.1)) + tailwindcss-mso: 2.0.2(tailwindcss@3.4.18(yaml@2.8.1)) - tailwindcss@3.4.17: + tailwindcss@3.4.18(yaml@2.8.1): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -24061,32 +23412,33 @@ snapshots: picocolors: 1.1.1 postcss: 8.5.6 postcss-import: 15.1.0(postcss@8.5.6) - postcss-js: 4.0.1(postcss@8.5.6) - postcss-load-config: 4.0.2(postcss@8.5.6) + postcss-js: 4.1.0(postcss@8.5.6) + postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.6)(yaml@2.8.1) postcss-nested: 6.2.0(postcss@8.5.6) postcss-selector-parser: 6.1.2 resolve: 1.22.10 sucrase: 3.35.0 transitivePeerDependencies: - - ts-node + - tsx + - yaml - tailwindcss@4.1.12: {} + tailwindcss@4.1.14: {} - tapable@2.2.2: {} + tapable@2.3.0: {} - tar-fs@2.1.3: + tar-fs@2.1.4: dependencies: chownr: 1.1.4 mkdirp-classic: 0.5.3 pump: 3.0.3 tar-stream: 2.2.0 - tar-fs@3.1.0: + tar-fs@3.1.1: dependencies: pump: 3.0.3 tar-stream: 3.1.7 optionalDependencies: - bare-fs: 4.2.0 + bare-fs: 4.4.7 bare-path: 3.0.0 transitivePeerDependencies: - bare-buffer @@ -24103,7 +23455,7 @@ snapshots: dependencies: b4a: 1.6.7 fast-fifo: 1.3.2 - streamx: 2.22.1 + streamx: 2.23.0 tar@6.2.1: dependencies: @@ -24114,34 +23466,33 @@ snapshots: mkdirp: 1.0.4 yallist: 4.0.0 - tar@7.4.3: + tar@7.5.1: dependencies: '@isaacs/fs-minipass': 4.0.1 chownr: 3.0.0 minipass: 7.1.2 - minizlib: 3.0.2 - mkdirp: 3.0.1 + minizlib: 3.1.0 yallist: 5.0.0 - terser-webpack-plugin@5.3.14(@swc/core@1.13.3(@swc/helpers@0.5.17))(webpack@5.100.2(@swc/core@1.13.3(@swc/helpers@0.5.17))): + terser-webpack-plugin@5.3.14(@swc/core@1.13.5(@swc/helpers@0.5.17))(webpack@5.100.2(@swc/core@1.13.5(@swc/helpers@0.5.17))): dependencies: - '@jridgewell/trace-mapping': 0.3.30 + '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 - schema-utils: 4.3.2 + schema-utils: 4.3.3 serialize-javascript: 6.0.2 terser: 5.43.1 - webpack: 5.100.2(@swc/core@1.13.3(@swc/helpers@0.5.17)) + webpack: 5.100.2(@swc/core@1.13.5(@swc/helpers@0.5.17)) optionalDependencies: - '@swc/core': 1.13.3(@swc/helpers@0.5.17) + '@swc/core': 1.13.5(@swc/helpers@0.5.17) - terser-webpack-plugin@5.3.14(webpack@5.100.2): + terser-webpack-plugin@5.3.14(webpack@5.102.1): dependencies: - '@jridgewell/trace-mapping': 0.3.30 + '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 - schema-utils: 4.3.2 + schema-utils: 4.3.3 serialize-javascript: 6.0.2 terser: 5.43.1 - webpack: 5.100.2 + webpack: 5.102.1 terser@5.43.1: dependencies: @@ -24156,23 +23507,23 @@ snapshots: glob: 10.4.5 minimatch: 9.0.5 - testcontainers@11.5.1: + testcontainers@11.7.1: dependencies: '@balena/dockerignore': 1.0.2 - '@types/dockerode': 3.3.42 + '@types/dockerode': 3.3.44 archiver: 7.0.1 async-lock: 1.4.1 byline: 5.0.0 - debug: 4.4.1 - docker-compose: 1.2.0 - dockerode: 4.0.7 + debug: 4.4.3 + docker-compose: 1.3.0 + dockerode: 4.0.9 get-port: 7.1.0 proper-lockfile: 4.1.2 properties-reader: 2.3.0 ssh-remote-port-forward: 1.0.4 - tar-fs: 3.1.0 + tar-fs: 3.1.1 tmp: 0.2.5 - undici: 7.14.0 + undici: 7.16.0 transitivePeerDependencies: - bare-buffer - supports-color @@ -24191,10 +23542,14 @@ snapshots: dependencies: any-promise: 1.3.0 - three@0.175.0: {} + thingies@2.5.0(tslib@2.8.1): + dependencies: + tslib: 2.8.1 three@0.179.1: {} + three@0.180.0: {} + through@2.3.8: {} thumbhash@0.1.1: {} @@ -24219,7 +23574,7 @@ snapshots: tinyexec@0.3.2: {} - tinyglobby@0.2.14: + tinyglobby@0.2.15: dependencies: fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 @@ -24242,10 +23597,6 @@ snapshots: tldts-core: 6.1.86 optional: true - tmp@0.0.33: - dependencies: - os-tmpdir: 1.0.2 - tmp@0.2.5: {} to-regex-range@5.0.1: @@ -24292,6 +23643,10 @@ snapshots: punycode: 2.3.1 optional: true + tree-dump@1.1.0(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + tree-kill@1.2.2: {} trim-lines@3.0.1: {} @@ -24304,21 +23659,21 @@ snapshots: dependencies: utf8-byte-length: 1.0.5 - ts-api-utils@2.1.0(typescript@5.9.2): + ts-api-utils@2.1.0(typescript@5.9.3): dependencies: - typescript: 5.9.2 + typescript: 5.9.3 ts-interface-checker@0.1.13: {} - tsconfck@3.1.6(typescript@5.9.2): + tsconfck@3.1.6(typescript@5.9.3): optionalDependencies: - typescript: 5.9.2 + typescript: 5.9.3 tsconfig-paths-webpack-plugin@4.2.0: dependencies: chalk: 4.1.2 enhanced-resolve: 5.18.3 - tapable: 2.2.2 + tapable: 2.3.0 tsconfig-paths: 4.2.0 tsconfig-paths@4.2.0: @@ -24362,56 +23717,29 @@ snapshots: typedarray@0.0.6: {} - typeorm@0.3.25(ioredis@5.7.0)(pg@8.16.3)(reflect-metadata@0.2.2): + typescript-eslint@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3): dependencies: - '@sqltools/formatter': 1.2.5 - ansis: 3.17.0 - app-root-path: 3.1.0 - buffer: 6.0.3 - dayjs: 1.11.13 - debug: 4.4.1 - dedent: 1.6.0 - dotenv: 16.6.1 - glob: 10.4.5 - reflect-metadata: 0.2.2 - sha.js: 2.4.11 - sql-highlight: 6.1.0 - tslib: 2.8.1 - uuid: 11.1.0 - yargs: 17.7.2 - optionalDependencies: - ioredis: 5.7.0 - pg: 8.16.3 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - typescript-eslint@8.39.1(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2): - dependencies: - '@typescript-eslint/eslint-plugin': 8.39.1(@typescript-eslint/parser@8.39.1(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2) - '@typescript-eslint/parser': 8.39.1(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2) - '@typescript-eslint/typescript-estree': 8.39.1(typescript@5.9.2) - '@typescript-eslint/utils': 8.39.1(eslint@9.33.0(jiti@2.5.1))(typescript@5.9.2) - eslint: 9.33.0(jiti@2.5.1) - typescript: 5.9.2 + '@typescript-eslint/eslint-plugin': 8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.37.0(jiti@2.6.1) + typescript: 5.9.3 transitivePeerDependencies: - supports-color typescript@5.8.3: {} - typescript@5.9.2: {} + typescript@5.9.3: {} ua-is-frozen@0.1.2: {} - ua-parser-js@2.0.4(encoding@0.1.13): + ua-parser-js@2.0.5: dependencies: - '@types/node-fetch': 2.6.12 detect-europe-js: 0.1.2 is-standalone-pwa: 0.1.1 - node-fetch: 2.7.0(encoding@0.1.13) ua-is-frozen: 0.1.2 - transitivePeerDependencies: - - encoding + undici: 7.16.0 uglify-js@3.19.3: optional: true @@ -24428,10 +23756,10 @@ snapshots: undici-types@6.21.0: {} - undici-types@7.10.0: + undici-types@7.14.0: optional: true - undici@7.14.0: {} + undici@7.16.0: {} unicode-canonical-property-names-ecmascript@2.0.1: {} @@ -24533,31 +23861,32 @@ snapshots: unpipe@1.0.0: {} - unplugin-swc@1.5.5(@swc/core@1.13.3(@swc/helpers@0.5.17))(rollup@4.46.3): + unplugin-swc@1.5.7(@swc/core@1.13.5(@swc/helpers@0.5.17))(rollup@4.52.4): dependencies: - '@rollup/pluginutils': 5.2.0(rollup@4.46.3) - '@swc/core': 1.13.3(@swc/helpers@0.5.17) + '@rollup/pluginutils': 5.3.0(rollup@4.52.4) + '@swc/core': 1.13.5(@swc/helpers@0.5.17) load-tsconfig: 0.2.5 - unplugin: 2.3.5 + unplugin: 2.3.10 transitivePeerDependencies: - rollup - unplugin@2.3.5: + unplugin@2.3.10: dependencies: + '@jridgewell/remapping': 2.3.5 acorn: 8.15.0 picomatch: 4.0.3 webpack-virtual-modules: 0.6.2 - update-browserslist-db@1.1.3(browserslist@4.25.3): + update-browserslist-db@1.1.3(browserslist@4.26.3): dependencies: - browserslist: 4.25.3 + browserslist: 4.26.3 escalade: 3.2.0 picocolors: 1.1.1 update-notifier@6.0.2: dependencies: boxen: 7.1.1 - chalk: 5.6.0 + chalk: 5.6.2 configstore: 6.0.0 has-yarn: 3.0.0 import-lazy: 4.0.0 @@ -24567,7 +23896,7 @@ snapshots: is-yarn-global: 0.4.1 latest-version: 7.0.0 pupa: 3.1.0 - semver: 7.7.2 + semver: 7.7.3 semver-diff: 4.0.0 xdg-basedir: 5.1.0 @@ -24575,14 +23904,14 @@ snapshots: dependencies: punycode: 2.3.1 - url-loader@4.1.1(file-loader@6.2.0(webpack@5.100.2))(webpack@5.100.2): + url-loader@4.1.1(file-loader@6.2.0(webpack@5.102.1))(webpack@5.102.1): dependencies: loader-utils: 2.0.4 mime-types: 2.1.35 schema-utils: 3.3.0 - webpack: 5.100.2 + webpack: 5.102.1 optionalDependencies: - file-loader: 6.2.0(webpack@5.100.2) + file-loader: 6.2.0(webpack@5.102.1) url-parse@1.5.10: dependencies: @@ -24599,10 +23928,6 @@ snapshots: util-deprecate@1.0.2: {} - util@0.10.4: - dependencies: - inherits: 2.0.3 - utila@0.4.0: {} utility-types@3.11.0: {} @@ -24623,23 +23948,6 @@ snapshots: uuid@8.3.2: {} - uuid@9.0.1: {} - - validate.io-array@1.0.6: {} - - validate.io-function@1.0.2: {} - - validate.io-integer-array@1.0.0: - dependencies: - validate.io-array: 1.0.6 - validate.io-integer: 1.0.5 - - validate.io-integer@1.0.5: - dependencies: - validate.io-number: 1.0.3 - - validate.io-number@1.0.3: {} - validator@13.15.15: {} value-equal@1.0.1: {} @@ -24658,7 +23966,7 @@ snapshots: '@types/unist': 2.0.11 unist-util-stringify-position: 2.0.3 - vfile-message@4.0.2: + vfile-message@4.0.3: dependencies: '@types/unist': 3.0.3 unist-util-stringify-position: 4.0.0 @@ -24673,24 +23981,24 @@ snapshots: vfile@6.0.3: dependencies: '@types/unist': 3.0.3 - vfile-message: 4.0.2 + vfile-message: 4.0.3 - vite-imagetools@8.0.0(rollup@4.46.3): + vite-imagetools@8.0.0(rollup@4.52.4): dependencies: - '@rollup/pluginutils': 5.2.0(rollup@4.46.3) + '@rollup/pluginutils': 5.3.0(rollup@4.52.4) imagetools-core: 8.0.0 - sharp: 0.34.3 + sharp: 0.34.4 transitivePeerDependencies: - rollup - supports-color - vite-node@3.2.4(@types/node@22.18.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1): + vite-node@3.2.4(@types/node@22.18.10)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1): dependencies: cac: 6.7.14 - debug: 4.4.1 + debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 7.1.2(@types/node@22.18.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + vite: 7.1.9(@types/node@22.18.10)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) transitivePeerDependencies: - '@types/node' - jiti @@ -24705,13 +24013,13 @@ snapshots: - tsx - yaml - vite-node@3.2.4(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1): + vite-node@3.2.4(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1): dependencies: cac: 6.7.14 - debug: 4.4.1 + debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + vite: 7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) transitivePeerDependencies: - '@types/node' - jiti @@ -24726,86 +24034,86 @@ snapshots: - tsx - yaml - vite-tsconfig-paths@5.1.4(typescript@5.9.2)(vite@7.1.2(@types/node@22.18.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)): + vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@7.1.9(@types/node@22.18.10)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)): dependencies: - debug: 4.4.1 + debug: 4.4.3 globrex: 0.1.2 - tsconfck: 3.1.6(typescript@5.9.2) + tsconfck: 3.1.6(typescript@5.9.3) optionalDependencies: - vite: 7.1.2(@types/node@22.18.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + vite: 7.1.9(@types/node@22.18.10)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) transitivePeerDependencies: - supports-color - typescript - vite@7.1.2(@types/node@22.18.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1): + vite@7.1.9(@types/node@22.18.10)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1): dependencies: - esbuild: 0.25.9 + esbuild: 0.25.10 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 - rollup: 4.46.3 - tinyglobby: 0.2.14 + rollup: 4.52.4 + tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 22.18.1 + '@types/node': 22.18.10 fsevents: 2.3.3 - jiti: 2.5.1 + jiti: 2.6.1 lightningcss: 1.30.1 terser: 5.43.1 yaml: 2.8.1 - vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1): + vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1): dependencies: - esbuild: 0.25.9 + esbuild: 0.25.10 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 - rollup: 4.46.3 - tinyglobby: 0.2.14 + rollup: 4.52.4 + tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 24.3.0 + '@types/node': 24.7.1 fsevents: 2.3.3 - jiti: 2.5.1 + jiti: 2.6.1 lightningcss: 1.30.1 terser: 5.43.1 yaml: 2.8.1 - vitefu@1.1.1(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)): + vitefu@1.1.1(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)): optionalDependencies: - vite: 7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + vite: 7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) - vitest-fetch-mock@0.4.5(vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.18.1)(happy-dom@18.0.1)(jiti@2.5.1)(jsdom@26.1.0(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)): + vitest-fetch-mock@0.4.5(vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.18.10)(happy-dom@20.0.0)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)): dependencies: - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.1)(happy-dom@18.0.1)(jiti@2.5.1)(jsdom@26.1.0(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.18.10)(happy-dom@20.0.0)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) - vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.18.1)(happy-dom@18.0.1)(jiti@2.5.1)(jsdom@26.1.0(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.18.10)(happy-dom@20.0.0)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1): dependencies: '@types/chai': 5.2.2 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@7.1.2(@types/node@22.18.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) + '@vitest/mocker': 3.2.4(vite@7.1.9(@types/node@22.18.10)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 '@vitest/spy': 3.2.4 '@vitest/utils': 3.2.4 chai: 5.2.0 - debug: 4.4.1 + debug: 4.4.3 expect-type: 1.2.1 - magic-string: 0.30.17 + magic-string: 0.30.19 pathe: 2.0.3 picomatch: 4.0.3 std-env: 3.9.0 tinybench: 2.9.0 tinyexec: 0.3.2 - tinyglobby: 0.2.14 + tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 7.1.2(@types/node@22.18.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) - vite-node: 3.2.4(@types/node@22.18.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + vite: 7.1.9(@types/node@22.18.10)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + vite-node: 3.2.4(@types/node@22.18.10)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 - '@types/node': 22.18.1 - happy-dom: 18.0.1 + '@types/node': 22.18.10 + happy-dom: 20.0.0 jsdom: 26.1.0(canvas@2.11.2(encoding@0.1.13)) transitivePeerDependencies: - jiti @@ -24821,35 +24129,79 @@ snapshots: - tsx - yaml - vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.3.0)(happy-dom@18.0.1)(jiti@2.5.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.18.10)(happy-dom@20.0.0)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1): dependencies: '@types/chai': 5.2.2 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) + '@vitest/mocker': 3.2.4(vite@7.1.9(@types/node@22.18.10)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 '@vitest/spy': 3.2.4 '@vitest/utils': 3.2.4 chai: 5.2.0 - debug: 4.4.1 + debug: 4.4.3 expect-type: 1.2.1 - magic-string: 0.30.17 + magic-string: 0.30.19 pathe: 2.0.3 picomatch: 4.0.3 std-env: 3.9.0 tinybench: 2.9.0 tinyexec: 0.3.2 - tinyglobby: 0.2.14 + tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 7.1.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) - vite-node: 3.2.4(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + vite: 7.1.9(@types/node@22.18.10)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + vite-node: 3.2.4(@types/node@22.18.10)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 - '@types/node': 24.3.0 - happy-dom: 18.0.1 + '@types/node': 22.18.10 + happy-dom: 20.0.0 + jsdom: 26.1.0(canvas@2.11.2) + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.7.1)(happy-dom@20.0.0)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1): + dependencies: + '@types/chai': 5.2.2 + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(vite@7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1)) + '@vitest/pretty-format': 3.2.4 + '@vitest/runner': 3.2.4 + '@vitest/snapshot': 3.2.4 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 + chai: 5.2.0 + debug: 4.4.3 + expect-type: 1.2.1 + magic-string: 0.30.19 + pathe: 2.0.3 + picomatch: 4.0.3 + std-env: 3.9.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.15 + tinypool: 1.1.1 + tinyrainbow: 2.0.0 + vite: 7.1.9(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + vite-node: 3.2.4(@types/node@24.7.1)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.43.1)(yaml@2.8.1) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/debug': 4.1.12 + '@types/node': 24.7.1 + happy-dom: 20.0.0 jsdom: 26.1.0(canvas@2.11.2) transitivePeerDependencies: - jiti @@ -24921,20 +24273,23 @@ snapshots: - bufferutil - utf-8-validate - webpack-dev-middleware@5.3.4(webpack@5.100.2): + webpack-dev-middleware@7.4.5(webpack@5.102.1): dependencies: colorette: 2.0.20 - memfs: 3.5.3 - mime-types: 2.1.35 + memfs: 4.49.0 + mime-types: 3.0.1 + on-finished: 2.4.1 range-parser: 1.2.1 - schema-utils: 4.3.2 - webpack: 5.100.2 + schema-utils: 4.3.3 + optionalDependencies: + webpack: 5.102.1 - webpack-dev-server@4.15.2(webpack@5.100.2): + webpack-dev-server@5.2.2(webpack@5.102.1): dependencies: '@types/bonjour': 3.5.13 '@types/connect-history-api-fallback': 1.5.4 '@types/express': 4.17.23 + '@types/express-serve-static-core': 4.19.6 '@types/serve-index': 1.9.4 '@types/serve-static': 1.15.8 '@types/sockjs': 0.3.36 @@ -24945,25 +24300,22 @@ snapshots: colorette: 2.0.20 compression: 1.8.1 connect-history-api-fallback: 2.0.0 - default-gateway: 6.0.3 express: 4.21.2 graceful-fs: 4.2.11 - html-entities: 2.6.0 http-proxy-middleware: 2.0.9(@types/express@4.17.23) ipaddr.js: 2.2.0 launch-editor: 2.10.0 - open: 8.4.2 - p-retry: 4.6.2 - rimraf: 3.0.2 - schema-utils: 4.3.2 + open: 10.2.0 + p-retry: 6.2.1 + schema-utils: 4.3.3 selfsigned: 2.4.1 serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack-dev-middleware: 5.3.4(webpack@5.100.2) + webpack-dev-middleware: 7.4.5(webpack@5.102.1) ws: 8.18.3 optionalDependencies: - webpack: 5.100.2 + webpack: 5.102.1 transitivePeerDependencies: - bufferutil - debug @@ -24988,7 +24340,7 @@ snapshots: webpack-virtual-modules@0.6.2: {} - webpack@5.100.2: + webpack@5.100.2(@swc/core@1.13.5(@swc/helpers@0.5.17)): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.8 @@ -24998,7 +24350,7 @@ snapshots: '@webassemblyjs/wasm-parser': 1.14.1 acorn: 8.15.0 acorn-import-phases: 1.0.4(acorn@8.15.0) - browserslist: 4.25.3 + browserslist: 4.26.3 chrome-trace-event: 1.0.4 enhanced-resolve: 5.18.3 es-module-lexer: 1.7.0 @@ -25007,12 +24359,12 @@ snapshots: glob-to-regexp: 0.4.1 graceful-fs: 4.2.11 json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.0 + loader-runner: 4.3.1 mime-types: 2.1.35 neo-async: 2.6.2 - schema-utils: 4.3.2 - tapable: 2.2.2 - terser-webpack-plugin: 5.3.14(webpack@5.100.2) + schema-utils: 4.3.3 + tapable: 2.3.0 + terser-webpack-plugin: 5.3.14(@swc/core@1.13.5(@swc/helpers@0.5.17))(webpack@5.100.2(@swc/core@1.13.5(@swc/helpers@0.5.17))) watchpack: 2.4.4 webpack-sources: 3.3.3 transitivePeerDependencies: @@ -25020,7 +24372,7 @@ snapshots: - esbuild - uglify-js - webpack@5.100.2(@swc/core@1.13.3(@swc/helpers@0.5.17)): + webpack@5.102.1: dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.8 @@ -25030,7 +24382,7 @@ snapshots: '@webassemblyjs/wasm-parser': 1.14.1 acorn: 8.15.0 acorn-import-phases: 1.0.4(acorn@8.15.0) - browserslist: 4.25.3 + browserslist: 4.26.3 chrome-trace-event: 1.0.4 enhanced-resolve: 5.18.3 es-module-lexer: 1.7.0 @@ -25039,12 +24391,12 @@ snapshots: glob-to-regexp: 0.4.1 graceful-fs: 4.2.11 json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.0 + loader-runner: 4.3.1 mime-types: 2.1.35 neo-async: 2.6.2 - schema-utils: 4.3.2 - tapable: 2.2.2 - terser-webpack-plugin: 5.3.14(@swc/core@1.13.3(@swc/helpers@0.5.17))(webpack@5.100.2(@swc/core@1.13.3(@swc/helpers@0.5.17))) + schema-utils: 4.3.3 + tapable: 2.3.0 + terser-webpack-plugin: 5.3.14(webpack@5.102.1) watchpack: 2.4.4 webpack-sources: 3.3.3 transitivePeerDependencies: @@ -25052,7 +24404,7 @@ snapshots: - esbuild - uglify-js - webpackbar@6.0.1(webpack@5.100.2): + webpackbar@6.0.1(webpack@5.102.1): dependencies: ansi-escapes: 4.3.2 chalk: 4.1.2 @@ -25061,7 +24413,7 @@ snapshots: markdown-table: 2.0.0 pretty-time: 1.1.0 std-env: 3.9.0 - webpack: 5.100.2 + webpack: 5.102.1 wrap-ansi: 7.0.0 websocket-driver@0.7.4: @@ -25151,9 +24503,9 @@ snapshots: wrap-ansi@8.1.0: dependencies: - ansi-styles: 6.2.1 + ansi-styles: 6.2.3 string-width: 5.1.2 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 wrappy@1.0.2: {} @@ -25170,6 +24522,10 @@ snapshots: ws@8.18.3: {} + wsl-utils@0.1.0: + dependencies: + is-wsl: 3.1.0 + xdg-basedir@5.1.0: {} xml-js@1.6.11: @@ -25240,9 +24596,9 @@ snapshots: yoctocolors-cjs@2.1.2: {} - yoctocolors@2.1.1: {} + yoctocolors@2.1.2: {} - zimmerframe@1.1.2: {} + zimmerframe@1.1.4: {} zip-stream@6.0.1: dependencies: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 880d115880..5fd79faba3 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -27,7 +27,7 @@ onlyBuiltDependencies: - '@tailwindcss/oxide' overrides: canvas: 2.11.2 - sharp: ^0.34.3 + sharp: ^0.34.4 packageExtensions: nestjs-kysely: dependencies: diff --git a/readme_i18n/README_ar_JO.md b/readme_i18n/README_ar_JO.md index 4e7ba99dd2..e0e13eeaf6 100644 --- a/readme_i18n/README_ar_JO.md +++ b/readme_i18n/README_ar_JO.md @@ -28,7 +28,8 @@ Deutsch Nederlands TÃŧrkçe - 中文 + įŽ€äŊ“中文 + æ­ŖéĢ”ä¸­æ–‡ ĐŖĐēŅ€Đ°Ņ—ĐŊҁҌĐēа Đ ŅƒŅŅĐēиК PortuguÃĒs Brasileiro @@ -46,13 +47,13 @@ ## Ų…Ø­ØĒŲˆŲ‰ -- [Ø§Ų„ŲˆØĢاØĻŲ‚ Ø§Ų„ØąØŗŲ…ŲŠØŠ](https://immich.app/docs) +- [Ø§Ų„ŲˆØĢاØĻŲ‚ Ø§Ų„ØąØŗŲ…ŲŠØŠ](https://docs.immich.app) - [ØŽØąŲŠØˇØŠ Ø§Ų„ØˇØąŲŠŲ‚](https://github.com/orgs/immich-app/projects/1) - [ØĒØŦØąŲŠØ¨ŲŠ](#demo) - [ØŗŲ…Ø§ØĒ](#features) -- [Ų…Ų‚Ø¯Ų…ØŠ](https://immich.app/docs/overview/introduction) -- [ØĒØšŲ„ŲŠŲ…Ø§ØĒ Ø§Ų„ØĒØ­Ų…ŲŠŲ„](https://immich.app/docs/install/requirements) -- [Ų‚ŲˆØ§ØšØ¯ Ø§Ų„Ų…ØŗØ§Ų‡Ų…ØŠ](https://immich.app/docs/overview/support-the-project) +- [Ų…Ų‚Ø¯Ų…ØŠ](https://docs.immich.app/overview/introduction) +- [ØĒØšŲ„ŲŠŲ…Ø§ØĒ Ø§Ų„ØĒØ­Ų…ŲŠŲ„](https://docs.immich.app/install/requirements) +- [Ų‚ŲˆØ§ØšØ¯ Ø§Ų„Ų…ØŗØ§Ų‡Ų…ØŠ](https://docs.immich.app/overview/support-the-project) ## ØĒ؈ØĢŲŠŲ‚ diff --git a/readme_i18n/README_ca_ES.md b/readme_i18n/README_ca_ES.md index 0b8dd5999b..d09362aa0f 100644 --- a/readme_i18n/README_ca_ES.md +++ b/readme_i18n/README_ca_ES.md @@ -27,7 +27,8 @@ Deutsch Nederlands TÃŧrkçe - 中文 + įŽ€äŊ“中文 + æ­ŖéĢ”ä¸­æ–‡ ĐŖĐēŅ€Đ°Ņ—ĐŊҁҌĐēа Đ ŅƒŅŅĐēиК PortuguÃĒs Brasileiro @@ -44,13 +45,13 @@ ## Contingut -- [DocumentaciÃŗ oficial](https://immich.app/docs) +- [DocumentaciÃŗ oficial](https://docs.immich.app) - [Mapa de ruta](https://github.com/orgs/immich-app/projects/1) - [Demo](#demo) - [Funcionalitats](#funcionalitats) -- [IntroducciÃŗ](https://immich.app/docs/overview/introduction) -- [Instal¡laciÃŗ](https://immich.app/docs/install/requirements) -- [Directrius de contribuciÃŗ](https://immich.app/docs/overview/support-the-project) +- [IntroducciÃŗ](https://docs.immich.app/overview/introduction) +- [Instal¡laciÃŗ](https://docs.immich.app/install/requirements) +- [Directrius de contribuciÃŗ](https://docs.immich.app/overview/support-the-project) ## DocumentaciÃŗ diff --git a/readme_i18n/README_de_DE.md b/readme_i18n/README_de_DE.md index d24818b881..a8685e0902 100644 --- a/readme_i18n/README_de_DE.md +++ b/readme_i18n/README_de_DE.md @@ -27,7 +27,8 @@ 한ęĩ­ė–´ Nederlands TÃŧrkçe - 中文 + įŽ€äŊ“中文 + æ­ŖéĢ”ä¸­æ–‡ ĐŖĐēŅ€Đ°Ņ—ĐŊҁҌĐēа Đ ŅƒŅŅĐēиК PortuguÃĒs Brasileiro @@ -50,14 +51,14 @@ ## Inhalt -- [Offizielle Dokumentation](https://immich.app/docs) -- [Über Immich](https://immich.app/docs/overview/introduction) -- [Installation](https://immich.app/docs/install/requirements) +- [Offizielle Dokumentation](https://docs.immich.app) +- [Über Immich](https://docs.immich.app/overview/introduction) +- [Installation](https://docs.immich.app/install/requirements) - [Roadmap](https://github.com/orgs/immich-app/projects/1) - [Demo](#demo) - [Funktionen](#funktionen) -- [Übersetzungen](https://immich.app/docs/developer/translations) -- [Beitragsrichtlinien](https://immich.app/docs/overview/support-the-project) +- [Übersetzungen](https://docs.immich.app/developer/translations) +- [Beitragsrichtlinien](https://docs.immich.app/overview/support-the-project) ## Demo @@ -107,7 +108,7 @@ Die Web-Demo kannst Du unter https://demo.immich.app finden. FÃŧr die Handy-App ## Übersetzungen -Mehr zum Thema Übersetzungen kannst du [hier](https://immich.app/docs/developer/translations) erfahren. +Mehr zum Thema Übersetzungen kannst du [hier](https://docs.immich.app/developer/translations) erfahren. Translation status diff --git a/readme_i18n/README_es_ES.md b/readme_i18n/README_es_ES.md index 00417c9188..032f8c50a8 100644 --- a/readme_i18n/README_es_ES.md +++ b/readme_i18n/README_es_ES.md @@ -27,7 +27,8 @@ Deutsch Nederlands TÃŧrkçe - 中文 + įŽ€äŊ“中文 + æ­ŖéĢ”ä¸­æ–‡ ĐŖĐēŅ€Đ°Ņ—ĐŊҁҌĐēа Đ ŅƒŅŅĐēиК PortuguÃĒs Brasileiro @@ -45,13 +46,13 @@ ## Contenido -- [DocumentaciÃŗn oficial](https://immich.app/docs) +- [DocumentaciÃŗn oficial](https://docs.immich.app) - [Hoja de ruta](https://github.com/orgs/immich-app/projects/1) - [Demo](#demo) - [Funciones](#funciones) -- [IntroducciÃŗn](https://immich.app/docs/overview/introduction) -- [InstalaciÃŗn](https://immich.app/docs/install/requirements) -- [Directrices para contribuir](https://immich.app/docs/overview/support-the-project) +- [IntroducciÃŗn](https://docs.immich.app/overview/introduction) +- [InstalaciÃŗn](https://docs.immich.app/install/requirements) +- [Directrices para contribuir](https://docs.immich.app/overview/support-the-project) ## DocumentaciÃŗn @@ -99,7 +100,7 @@ contraseÃąa: demo ## Traducciones -Lea mas acerca de las traducciones [acÃĄ](https://immich.app/docs/developer/translations). +Lea mas acerca de las traducciones [acÃĄ](https://docs.immich.app/developer/translations). Translation status diff --git a/readme_i18n/README_fr_FR.md b/readme_i18n/README_fr_FR.md index e1d4fb1cbc..349a0c49ce 100644 --- a/readme_i18n/README_fr_FR.md +++ b/readme_i18n/README_fr_FR.md @@ -27,7 +27,8 @@ Deutsch Nederlands TÃŧrkçe - 中文 + įŽ€äŊ“中文 + æ­ŖéĢ”ä¸­æ–‡ ĐŖĐēŅ€Đ°Ņ—ĐŊҁҌĐēа Đ ŅƒŅŅĐēиК PortuguÃĒs Brasileiro @@ -45,13 +46,13 @@ ## Sommaire -- [Documentation officielle](https://immich.app/docs) +- [Documentation officielle](https://docs.immich.app) - [Feuille de route](https://github.com/orgs/immich-app/projects/1) - [DÊmo](#dÊmo) - [FonctionnalitÊs](#fonctionnalitÊs) -- [Introduction](https://immich.app/docs/overview/introduction) -- [Installation](https://immich.app/docs/install/requirements) -- [Contribution](https://immich.app/docs/overview/support-the-project) +- [Introduction](https://docs.immich.app/overview/introduction) +- [Installation](https://docs.immich.app/install/requirements) +- [Contribution](https://docs.immich.app/overview/support-the-project) ## Documentation diff --git a/readme_i18n/README_it_IT.md b/readme_i18n/README_it_IT.md index 5a368fe1f9..711840fd9d 100644 --- a/readme_i18n/README_it_IT.md +++ b/readme_i18n/README_it_IT.md @@ -28,7 +28,8 @@ Deutsch Nederlands TÃŧrkçe - 中文 + įŽ€äŊ“中文 + æ­ŖéĢ”ä¸­æ–‡ ĐŖĐēŅ€Đ°Ņ—ĐŊҁҌĐēа Đ ŅƒŅŅĐēиК PortuguÃĒs Brasileiro @@ -49,14 +50,14 @@ ## Link utili -- [Documentazione](https://immich.app/docs) -- [Informazioni](https://immich.app/docs/overview/introduction) -- [Installazione](https://immich.app/docs/install/requirements) +- [Documentazione](https://docs.immich.app) +- [Informazioni](https://docs.immich.app/overview/introduction) +- [Installazione](https://docs.immich.app/install/requirements) - [Roadmap](https://immich.app/roadmap) - [Demo](#demo) - [Funzionalità](#funzionalità) -- [Traduzioni](https://immich.app/docs/developer/translations) -- [Contribuire](https://immich.app/docs/overview/support-the-project) +- [Traduzioni](https://docs.immich.app/developer/translations) +- [Contribuire](https://docs.immich.app/overview/support-the-project) ## Demo @@ -106,7 +107,7 @@ Per l’app mobile puoi usare `https://demo.immich.app` come `Server Endpoint UR ## Traduzioni -Scopri di piÚ sulle traduzioni [qui](https://immich.app/docs/developer/translations). +Scopri di piÚ sulle traduzioni [qui](https://docs.immich.app/developer/translations). Stato traduzioni diff --git a/readme_i18n/README_ja_JP.md b/readme_i18n/README_ja_JP.md index 60dd0f3ed7..0e74077895 100644 --- a/readme_i18n/README_ja_JP.md +++ b/readme_i18n/README_ja_JP.md @@ -27,7 +27,8 @@ Deutsch Nederlands TÃŧrkçe - 中文 + įŽ€äŊ“中文 + æ­ŖéĢ”ä¸­æ–‡ Đ ŅƒŅŅĐēиК PortuguÃĒs Brasileiro Svenska @@ -44,13 +45,13 @@ ## ã‚ŗãƒŗãƒ†ãƒŗãƒ„ -- [å…Ŧåŧãƒ‰ã‚­ãƒĨãƒĄãƒŗãƒˆ](https://immich.app/docs) +- [å…Ŧåŧãƒ‰ã‚­ãƒĨãƒĄãƒŗãƒˆ](https://docs.immich.app) - [ロãƒŧドマップ](https://github.com/orgs/immich-app/projects/1) - [デãƒĸ](#デãƒĸ) - [抟čƒŊ](#抟čƒŊ) -- [į´šäģ‹](https://immich.app/docs/overview/introduction) -- [ã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢ](https://immich.app/docs/install/requirements) -- [ã‚ŗãƒŗãƒˆãƒĒビãƒĨãƒŧã‚ˇãƒ§ãƒŗã‚Ŧイド](https://immich.app/docs/overview/support-the-project) +- [į´šäģ‹](https://docs.immich.app/overview/introduction) +- [ã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢ](https://docs.immich.app/install/requirements) +- [ã‚ŗãƒŗãƒˆãƒĒビãƒĨãƒŧã‚ˇãƒ§ãƒŗã‚Ŧイド](https://docs.immich.app/overview/support-the-project) ## ドキãƒĨãƒĄãƒŗãƒˆ diff --git a/readme_i18n/README_ko_KR.md b/readme_i18n/README_ko_KR.md index 031e2fd9ca..c2dfd11dd3 100644 --- a/readme_i18n/README_ko_KR.md +++ b/readme_i18n/README_ko_KR.md @@ -28,7 +28,8 @@ Deutsch Nederlands TÃŧrkçe -中文 +įŽ€äŊ“中文 +æ­ŖéĢ”ä¸­æ–‡ ĐŖĐēŅ€Đ°Ņ—ĐŊҁҌĐēа Đ ŅƒŅŅĐēиК PortuguÃĒs Brasileiro @@ -50,14 +51,14 @@ ## 링íŦ -- [ëŦ¸ė„œ](https://immich.app/docs) -- [ė†Œę°œ](https://immich.app/docs/overview/introduction) -- [ė„¤ėš˜](https://immich.app/docs/install/requirements) +- [ëŦ¸ė„œ](https://docs.immich.app) +- [ė†Œę°œ](https://docs.immich.app/overview/introduction) +- [ė„¤ėš˜](https://docs.immich.app/install/requirements) - [로드ë§ĩ](https://immich.app/roadmap) - [데ëǍ](#데ëǍ) - [기ëŠĨ](#기ëŠĨ) -- [ë˛ˆė—­](https://immich.app/docs/developer/tranlations) -- [기ė—Ŧ](https://immich.app/docs/overview/support-the-project) +- [ë˛ˆė—­](https://docs.immich.app/developer/tranlations) +- [기ė—Ŧ](https://docs.immich.app/overview/support-the-project) ## 데ëǍ @@ -104,7 +105,7 @@ ## ë˛ˆė—­ -ë˛ˆė—­ė— 대한 ėžė„¸í•œ ė •ëŗ´ëŠ” [ė´ęŗŗ](https://immich.app/docs/developer/translations)ė—ė„œ í™•ė¸í•˜ė„¸ėš”. +ë˛ˆė—­ė— 대한 ėžė„¸í•œ ė •ëŗ´ëŠ” [ė´ęŗŗ](https://docs.immich.app/developer/translations)ė—ė„œ í™•ė¸í•˜ė„¸ėš”. ë˛ˆė—­ 현황 diff --git a/readme_i18n/README_nl_NL.md b/readme_i18n/README_nl_NL.md index 46692bc612..ac72e9d238 100644 --- a/readme_i18n/README_nl_NL.md +++ b/readme_i18n/README_nl_NL.md @@ -27,7 +27,8 @@ 한ęĩ­ė–´ Deutsch TÃŧrkçe - 中文 + įŽ€äŊ“中文 + æ­ŖéĢ”ä¸­æ–‡ ĐŖĐēŅ€Đ°Ņ—ĐŊҁҌĐēа Đ ŅƒŅŅĐēиК PortuguÃĒs Brasileiro @@ -45,13 +46,13 @@ ## Inhoud -- [OfficiÃĢle documentatie](https://immich.app/docs) +- [OfficiÃĢle documentatie](https://docs.immich.app) - [Toekomstplannen](https://github.com/orgs/immich-app/projects/1) - [Demo](#demo) - [Functies](#functies) -- [Introductie](https://immich.app/docs/overview/introduction) -- [Installatie](https://immich.app/docs/install/requirements) -- [Richtlijnen voor bijdragen](https://immich.app/docs/overview/support-the-project) +- [Introductie](https://docs.immich.app/overview/introduction) +- [Installatie](https://docs.immich.app/install/requirements) +- [Richtlijnen voor bijdragen](https://docs.immich.app/overview/support-the-project) ## Documentatie @@ -102,7 +103,7 @@ Je kunt de demo [hier](https://demo.immich.app/) bekijken. Voor de mobiele app k ## Vertalingen -Je kunt [hier](https://immich.app/docs/developer/translations) meer over vertalingen lezen. +Je kunt [hier](https://docs.immich.app/developer/translations) meer over vertalingen lezen. ## Repository activiteit diff --git a/readme_i18n/README_pt_BR.md b/readme_i18n/README_pt_BR.md index 2320e8fd6f..d6f51cd779 100644 --- a/readme_i18n/README_pt_BR.md +++ b/readme_i18n/README_pt_BR.md @@ -29,7 +29,8 @@ Deutsch Nederlands TÃŧrkçe -中文 +įŽ€äŊ“中文 +æ­ŖéĢ”ä¸­æ–‡ ĐŖĐēŅ€Đ°Ņ—ĐŊҁҌĐēа Đ ŅƒŅŅĐēиК Svenska @@ -55,14 +56,14 @@ ## Links -- [DocumentaÃ§ÃŖo](https://immich.app/docs) -- [Sobre](https://immich.app/docs/overview/introduction) -- [InstalaÃ§ÃŖo](https://immich.app/docs/install/requirements) +- [DocumentaÃ§ÃŖo](https://docs.immich.app) +- [Sobre](https://docs.immich.app/overview/introduction) +- [InstalaÃ§ÃŖo](https://docs.immich.app/install/requirements) - [Roadmap](https://github.com/orgs/immich-app/projects/1) - [DemonstraÃ§ÃŖo](#demonstraÃ§ÃŖo) - [Funcionalidades](#funcionalidades) -- [TraduçÃĩes](https://immich.app/docs/developer/translations) -- [Diretrizes de ContribuiÃ§ÃŖo](https://immich.app/docs/overview/support-the-project) +- [TraduçÃĩes](https://docs.immich.app/developer/translations) +- [Diretrizes de ContribuiÃ§ÃŖo](https://docs.immich.app/overview/support-the-project) ## DemonstraÃ§ÃŖo @@ -115,7 +116,7 @@ Acesse a demonstraÃ§ÃŖo [aqui](https://demo.immich.app). No aplicativo para disp ## TraduçÃĩes Leia mais sobre as traduçÃĩes -[aqui](https://immich.app/docs/developer/translations). +[aqui](https://docs.immich.app/developer/translations). Status da traduÃ§ÃŖo diff --git a/readme_i18n/README_ru_RU.md b/readme_i18n/README_ru_RU.md index be97259acc..e29adde9c1 100644 --- a/readme_i18n/README_ru_RU.md +++ b/readme_i18n/README_ru_RU.md @@ -28,7 +28,8 @@ Deutsch Nederlands TÃŧrkçe - 中文 + įŽ€äŊ“中文 + æ­ŖéĢ”ä¸­æ–‡ ĐŖĐēŅ€Đ°Ņ—ĐŊҁҌĐēа PortuguÃĒs Brasileiro Svenska @@ -51,14 +52,14 @@ ## ХОдĐĩŅ€ĐļаĐŊиĐĩ -- [ĐžŅ„Đ¸Ņ†Đ¸Đ°ĐģҌĐŊĐ°Ņ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸Ņ](https://immich.app/docs) -- [ВвĐĩĐ´ĐĩĐŊиĐĩ](https://immich.app/docs/overview/introduction) -- [ĐŖŅŅ‚Đ°ĐŊОвĐēа](https://immich.app/docs/install/requirements) +- [ĐžŅ„Đ¸Ņ†Đ¸Đ°ĐģҌĐŊĐ°Ņ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸Ņ](https://docs.immich.app) +- [ВвĐĩĐ´ĐĩĐŊиĐĩ](https://docs.immich.app/overview/introduction) +- [ĐŖŅŅ‚Đ°ĐŊОвĐēа](https://docs.immich.app/install/requirements) - [ПĐģаĐŊ Ņ€Đ°ĐˇŅ€Đ°ĐąĐžŅ‚Đēи](https://github.com/orgs/immich-app/projects/1) - [ДĐĩĐŧĐž](#demo) - [ВозĐŧĐžĐļĐŊĐžŅŅ‚Đ¸](#features) -- [ПĐĩŅ€ĐĩвОд](https://immich.app/docs/developer/translations) -- [Гид ĐŋĐž ŅƒŅ‡Đ°ŅŅ‚Đ¸ŅŽ и ĐŋОддĐĩŅ€ĐļĐēĐĩ ĐŋŅ€ĐžĐĩĐēŅ‚Đ°](https://immich.app/docs/overview/support-the-project) +- [ПĐĩŅ€ĐĩвОд](https://docs.immich.app/developer/translations) +- [Гид ĐŋĐž ŅƒŅ‡Đ°ŅŅ‚Đ¸ŅŽ и ĐŋОддĐĩŅ€ĐļĐēĐĩ ĐŋŅ€ĐžĐĩĐēŅ‚Đ°](https://docs.immich.app/overview/support-the-project) ## ДĐĩĐŧĐž @@ -107,7 +108,7 @@ ## ПĐĩŅ€ĐĩвОд -Đ’ŅŅ‘ ĐŋŅ€Đž ĐŋĐĩŅ€ĐĩвОд ĐŋŅ€ĐžĐĩĐēŅ‚Đ° [ЗдĐĩҁҌ](https://immich.app/docs/developer/translations). +Đ’ŅŅ‘ ĐŋŅ€Đž ĐŋĐĩŅ€ĐĩвОд ĐŋŅ€ĐžĐĩĐēŅ‚Đ° [ЗдĐĩҁҌ](https://docs.immich.app/developer/translations). Translation status diff --git a/readme_i18n/README_sv_SE.md b/readme_i18n/README_sv_SE.md index daa68b9874..a421c23c2e 100644 --- a/readme_i18n/README_sv_SE.md +++ b/readme_i18n/README_sv_SE.md @@ -29,7 +29,8 @@ Deutsch Nederlands TÃŧrkçe - 中文 + įŽ€äŊ“中文 + æ­ŖéĢ”ä¸­æ–‡ ĐŖĐēŅ€Đ°Ņ—ĐŊҁҌĐēа Đ ŅƒŅŅĐēиК PortuguÃĒs Brasileiro @@ -46,13 +47,13 @@ ## InnehÃĨll -- [Officiell Dokumentation](https://immich.app/docs) +- [Officiell Dokumentation](https://docs.immich.app) - [Roadmap](https://github.com/orgs/immich-app/projects/1) - [Demo](#demo) - [Funktioner](#features) -- [Introduktion](https://immich.app/docs/overview/introduction) -- [Installation](https://immich.app/docs/install/requirements) -- [Riktlinjer fÃļr Bidrag](https://immich.app/docs/overview/support-the-project) +- [Introduktion](https://docs.immich.app/overview/introduction) +- [Installation](https://docs.immich.app/install/requirements) +- [Riktlinjer fÃļr Bidrag](https://docs.immich.app/overview/support-the-project) ## Dokumentation diff --git a/readme_i18n/README_th_TH.md b/readme_i18n/README_th_TH.md index bdb6db868d..cdc28b14e6 100644 --- a/readme_i18n/README_th_TH.md +++ b/readme_i18n/README_th_TH.md @@ -31,7 +31,8 @@ Deutsch Nederlands TÃŧrkçe - 中文 + įŽ€äŊ“中文 + æ­ŖéĢ”ä¸­æ–‡ ĐŖĐēŅ€Đ°Ņ—ĐŊҁҌĐēа Đ ŅƒŅŅĐēиК PortuguÃĒs Brasileiro @@ -52,14 +53,14 @@ ## ā¸Ĩā¸´ā¸‡ā¸āšŒ -- [ā¸„ā¸šāšˆā¸Ąā¸ˇā¸­](https://immich.app/docs) -- [āš€ā¸ā¸ĩāšˆā¸ĸā¸§ā¸ā¸ąā¸š](https://immich.app/docs/overview/introduction) -- [ā¸ā¸˛ā¸Ŗā¸•ā¸´ā¸”ā¸•ā¸ąāš‰ā¸‡](https://immich.app/docs/install/requirements) +- [ā¸„ā¸šāšˆā¸Ąā¸ˇā¸­](https://docs.immich.app) +- [āš€ā¸ā¸ĩāšˆā¸ĸā¸§ā¸ā¸ąā¸š](https://docs.immich.app/overview/introduction) +- [ā¸ā¸˛ā¸Ŗā¸•ā¸´ā¸”ā¸•ā¸ąāš‰ā¸‡](https://docs.immich.app/install/requirements) - [āš‚ā¸Ŗā¸”āšā¸Ąā¸›](https://immich.app/roadmap) - [ā¸Ēā¸˛ā¸˜ā¸´ā¸•](#ā¸Ēā¸˛ā¸˜ā¸´ā¸•) - [⏄⏏⏓ā¸Ēā¸Ąā¸šā¸ąā¸•ā¸´](#⏄⏏⏓ā¸Ēā¸Ąā¸šā¸ąā¸•ā¸´) -- [ā¸ā¸˛ā¸Ŗāšā¸›ā¸Ĩā¸ ā¸˛ā¸Šā¸˛](https://immich.app/docs/developer/translations) -- [ā¸Ēā¸™ā¸ąā¸šā¸Ēā¸™ā¸¸ā¸™āš‚ā¸žā¸Ŗāš€ā¸ˆā¸ā¸•āšŒ](https://immich.app/docs/overview/support-the-project) +- [ā¸ā¸˛ā¸Ŗāšā¸›ā¸Ĩā¸ ā¸˛ā¸Šā¸˛](https://docs.immich.app/developer/translations) +- [ā¸Ēā¸™ā¸ąā¸šā¸Ēā¸™ā¸¸ā¸™āš‚ā¸žā¸Ŗāš€ā¸ˆā¸ā¸•āšŒ](https://docs.immich.app/overview/support-the-project) ## ā¸Ēā¸˛ā¸˜ā¸´ā¸• @@ -106,7 +107,7 @@ ## ā¸ā¸˛ā¸Ŗāšā¸›ā¸Ĩā¸ ā¸˛ā¸Šā¸˛ -ā¸­āšˆā¸˛ā¸™āš€ā¸žā¸´āšˆā¸Ąāš€ā¸•ā¸´ā¸Ąāš€ā¸ā¸ĩāšˆā¸ĸā¸§ā¸ā¸ąā¸šā¸ā¸˛ā¸Ŗāšā¸›ā¸Ĩ [⏗ā¸ĩāšˆā¸™ā¸ĩāšˆ](https://immich.app/docs/developer/translations) +ā¸­āšˆā¸˛ā¸™āš€ā¸žā¸´āšˆā¸Ąāš€ā¸•ā¸´ā¸Ąāš€ā¸ā¸ĩāšˆā¸ĸā¸§ā¸ā¸ąā¸šā¸ā¸˛ā¸Ŗāšā¸›ā¸Ĩ [⏗ā¸ĩāšˆā¸™ā¸ĩāšˆ](https://docs.immich.app/developer/translations) ā¸Ēā¸–ā¸˛ā¸™ā¸°ā¸ā¸˛ā¸Ŗāšā¸›ā¸Ĩ diff --git a/readme_i18n/README_tr_TR.md b/readme_i18n/README_tr_TR.md index 6285ab55a2..46aef49745 100644 --- a/readme_i18n/README_tr_TR.md +++ b/readme_i18n/README_tr_TR.md @@ -27,7 +27,8 @@ 한ęĩ­ė–´ Deutsch Nederlands - 中文 + įŽ€äŊ“中文 + æ­ŖéĢ”ä¸­æ–‡ ĐŖĐēŅ€Đ°Ņ—ĐŊҁҌĐēа Đ ŅƒŅŅĐēиК PortuguÃĒs Brasileiro @@ -44,13 +45,13 @@ ## Content -- [Resmi Belgeler](https://immich.app/docs) +- [Resmi Belgeler](https://docs.immich.app) - [Yol HaritasÄą](https://github.com/orgs/immich-app/projects/1) - [Demo](#demo) - [Özellikler](#Ãļzellikler) -- [Giriş](https://immich.app/docs/overview/introduction) -- [Kurulum](https://immich.app/docs/install/requirements) -- [KatkÄą Sağlama Rehberi](https://immich.app/docs/overview/support-the-project) +- [Giriş](https://docs.immich.app/overview/introduction) +- [Kurulum](https://docs.immich.app/install/requirements) +- [KatkÄą Sağlama Rehberi](https://docs.immich.app/overview/support-the-project) ## Belgeler diff --git a/readme_i18n/README_uk_UA.md b/readme_i18n/README_uk_UA.md index 5a33fa210d..297054ee42 100644 --- a/readme_i18n/README_uk_UA.md +++ b/readme_i18n/README_uk_UA.md @@ -29,7 +29,8 @@ Deutsch Nederlands TÃŧrkçe - 中文 + įŽ€äŊ“中文 + æ­ŖéĢ”ä¸­æ–‡ Đ ŅƒŅŅĐēиК PortuguÃĒs Brasileiro Svenska @@ -42,26 +43,26 @@ - âš ī¸ ĐĻĐĩĐš ĐŋŅ€ĐžŅ”ĐēŅ‚ ĐŋĐĩŅ€ĐĩĐąŅƒĐ˛Đ°Ņ” **в Đ´ŅƒĐļĐĩ аĐēŅ‚Đ¸Đ˛ĐŊŅ–Đš** Ņ€ĐžĐˇŅ€ĐžĐąŅ†Ņ–. - âš ī¸ ĐžŅ‡Ņ–ĐēŅƒĐšŅ‚Đĩ ĐąĐĩСĐģҖ҇ ĐŋĐžĐŧиĐģĐžĐē Ņ– ĐŗĐģОйаĐģҌĐŊĐ¸Ņ… СĐŧŅ–ĐŊ. -- âš ī¸ **НĐĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ ҆ĐĩĐš Đ´ĐžĐ´Đ°Ņ‚ĐžĐē ŅĐē Ņ”Đ´Đ¸ĐŊĐĩ ŅŅ…ĐžĐ˛Đ¸Ņ‰Đĩ ŅĐ˛ĐžŅ—Ņ… Ņ„ĐžŅ‚Đž Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž.** +- âš ī¸ **НĐĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ ҆ĐĩĐš ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐžĐē ŅĐē Ņ”Đ´Đ¸ĐŊĐĩ ŅŅ…ĐžĐ˛Đ¸Ņ‰Đĩ ŅĐ˛ĐžŅ—Ņ… Ņ„ĐžŅ‚Đž Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž.** - âš ī¸ ЗавĐļди Đ´ĐžŅ‚Ņ€Đ¸ĐŧŅƒĐšŅ‚ĐĩҁҌ [ĐŋĐģаĐŊ҃ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ 3-2-1](https://www.backblaze.com/blog/the-3-2-1-backup-strategy/) Đ´ĐģŅ Đ˛Đ°ŅˆĐ¸Ņ… Đ´ĐžŅ€ĐžĐŗĐžŅ†Ņ–ĐŊĐŊĐ¸Ņ… Ņ„ĐžŅ‚ĐžĐŗŅ€Đ°Ņ„Ņ–Đš Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž! > [!NOTE] -> ĐžŅĐŊОвĐŊ҃ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–ŅŽ, СОĐēŅ€ĐĩĐŧа ĐŋĐžŅŅ–ĐąĐŊиĐēи С Đ˛ŅŅ‚Đ°ĐŊОвĐģĐĩĐŊĐŊŅ, ĐŧĐžĐļĐŊа СĐŊĐ°ĐšŅ‚Đ¸ Са Đ°Đ´Ņ€ĐĩŅĐžŅŽ https://immich.app/. +> ĐžŅĐŊОвĐŊ҃ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–ŅŽ, СОĐēŅ€ĐĩĐŧа ĐŋĐžŅŅ–ĐąĐŊиĐēи ĐˇŅ– Đ˛ŅŅ‚Đ°ĐŊОвĐģĐĩĐŊĐŊŅ, ĐŧĐžĐļĐŊа СĐŊĐ°ĐšŅ‚Đ¸ Са Đ°Đ´Ņ€ĐĩŅĐžŅŽ https://immich.app/. ## ĐŸĐžŅĐ¸ĐģаĐŊĐŊŅ -- [ДоĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ](https://immich.app/docs) -- [ĐŸŅ€Đž ĐŋŅ€ĐžŅ”ĐēŅ‚](https://immich.app/docs/overview/introduction) -- [Đ’ŅŅ‚Đ°ĐŊОвĐģĐĩĐŊĐŊŅ](https://immich.app/docs/install/requirements) +- [ДоĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ](https://docs.immich.app) +- [ĐŸŅ€Đž ĐŋŅ€ĐžŅ”ĐēŅ‚](https://docs.immich.app/overview/introduction) +- [Đ’ŅŅ‚Đ°ĐŊОвĐģĐĩĐŊĐŊŅ](https://docs.immich.app/install/requirements) - [Đ”ĐžŅ€ĐžĐļĐŊŅ ĐēĐ°Ņ€Ņ‚Đ°](https://immich.app/roadmap) - [ДĐĩĐŧĐž](#Đ´ĐĩĐŧĐž) - [Đ¤ŅƒĐŊĐē҆Җҗ](#Ņ„ŅƒĐŊĐē҆Җҗ) -- [ПĐĩŅ€ĐĩĐēĐģади](https://immich.app/docs/developer/translations) -- [Đ“Ņ–Đ´ Đ´ĐģŅ Ņ€ĐžĐˇŅ€ĐžĐąĐēи ĐŋŅ€ĐžŅ”ĐēŅ‚Ņƒ](https://immich.app/docs/overview/support-the-project) +- [ПĐĩŅ€ĐĩĐēĐģади](https://docs.immich.app/developer/translations) +- [Đ“Ņ–Đ´ Đ´ĐģŅ Ņ€ĐžĐˇŅ€ĐžĐąĐēи ĐŋŅ€ĐžŅ”ĐēŅ‚Ņƒ](https://docs.immich.app/overview/support-the-project) ## ДĐĩĐŧĐž -Đ”ĐžŅŅ‚ŅƒĐŋ Đ´Đž Đ´ĐĩĐŧĐž-вĐĩҀҁҖҗ [Ņ‚ŅƒŅ‚](https://demo.immich.app). ДĐģŅ ĐŧĐžĐąŅ–ĐģҌĐŊĐžĐŗĐž Đ´ĐžĐ´Đ°Ņ‚Đē҃ ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `https://demo.immich.app` в ŅĐēĐžŅŅ‚Ņ– `Server Endpoint URL`. +Đ”ĐžŅŅ‚ŅƒĐŋ Đ´Đž Đ´ĐĩĐŧĐž-вĐĩҀҁҖҗ [Ņ‚ŅƒŅ‚](https://demo.immich.app). ДĐģŅ ĐŧĐžĐąŅ–ĐģҌĐŊĐžĐŗĐž ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐē҃ ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `https://demo.immich.app` в ŅĐēĐžŅŅ‚Ņ– `Server Endpoint URL`. ### ОбĐģŅ–ĐēĐžĐ˛Ņ– даĐŊŅ– Đ´ĐģŅ Đ˛Ņ…ĐžĐ´Ņƒ @@ -74,7 +75,7 @@ | Đ¤ŅƒĐŊĐē҆Җҗ | Đ”ĐžĐ´Đ°Ņ‚ĐžĐē | ВĐĩĐą | | :------------------------------------------------------- | ------- | --- | | ЗаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ Ņ‚Đ° ĐŋĐĩŅ€ĐĩĐŗĐģŅĐ´ Đ˛Ņ–Đ´ĐĩĐž Đš Ņ„ĐžŅ‚Đž | ĐĸаĐē | ĐĸаĐē | -| ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐĩ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐĩ ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ ĐŋŅ€Đ¸ Đ˛Ņ–Đ´ĐēŅ€Đ¸Ņ‚Ņ‚Ņ– Đ´ĐžĐ´Đ°Ņ‚Đēа | ĐĸаĐē | Н/Д | +| ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐĩ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐĩ ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ ĐŋŅ€Đ¸ Đ˛Ņ–Đ´ĐēŅ€Đ¸Ņ‚Ņ‚Ņ– ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐē҃ | ĐĸаĐē | Н/Д | | ЗаĐŋĐžĐąŅ–ĐŗĐ°ĐŊĐŊŅ Đ´ŅƒĐąĐģŅŽĐ˛Đ°ĐŊĐŊŅŽ Ņ„Đ°ĐšĐģŅ–Đ˛ | ĐĸаĐē | ĐĸаĐē | | Đ’Đ¸ĐąŅ–Ņ€ аĐģŅŒĐąĐžĐŧŅ–Đ˛ Đ´ĐģŅ Ņ€ĐĩСĐĩŅ€Đ˛ĐŊĐžĐŗĐž ĐēĐžĐŋŅ–ŅŽĐ˛Đ°ĐŊĐŊŅ | ĐĸаĐē | Н/Д | | ЗаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ Ņ„ĐžŅ‚Đž Ņ‚Đ° Đ˛Ņ–Đ´ĐĩĐž ĐŊа ĐģĐžĐēаĐģҌĐŊиК ĐŋŅ€Đ¸ŅŅ‚Ņ€Ņ–Đš | ĐĸаĐē | ĐĸаĐē | @@ -106,13 +107,13 @@ ## ПĐĩŅ€ĐĩĐēĐģади -Đ‘Ņ–ĐģҌ҈Đĩ ĐŋŅ€Đž ĐŋĐĩŅ€ĐĩĐēĐģади [Ņ‚ŅƒŅ‚](https://immich.app/docs/developer/translations). +Đ‘Ņ–ĐģҌ҈Đĩ ĐŋŅ€Đž ĐŋĐĩŅ€ĐĩĐēĐģади [Ņ‚ŅƒŅ‚](https://docs.immich.app/developer/translations). ĐĄŅ‚Đ°Ņ‚ŅƒŅ ĐŋĐĩŅ€ĐĩĐēĐģĐ°Đ´Ņ–Đ˛ -## АĐēŅ‚Đ¸Đ˛ĐŊŅ–ŅŅ‚ŅŒ Ņ€ĐĩĐŋĐžĐˇĐ¸Ņ‚Đ°Ņ€Ņ–ŅŽ +## АĐēŅ‚Đ¸Đ˛ĐŊŅ–ŅŅ‚ŅŒ Ņ€ĐĩĐŋĐžĐˇĐ¸Ņ‚ĐžŅ€Ņ–ŅŽ ![Đ”Ņ–ŅĐģҌĐŊŅ–ŅŅ‚ŅŒ](https://repobeats.axiom.co/api/embed/9e86d9dc3ddd137161f2f6d2e758d7863b1789cb.svg "Đ—ĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ аĐŊаĐģŅ–Ņ‚Đ¸Đēи Repobeats") diff --git a/readme_i18n/README_vi_VN.md b/readme_i18n/README_vi_VN.md index fd04bd9fa1..b6b22ff610 100644 --- a/readme_i18n/README_vi_VN.md +++ b/readme_i18n/README_vi_VN.md @@ -29,7 +29,8 @@ Deutsch Nederlands TÃŧrkçe -中文 +įŽ€äŊ“中文 +æ­ŖéĢ”ä¸­æ–‡ ĐŖĐēŅ€Đ°Ņ—ĐŊҁҌĐēа Đ ŅƒŅŅĐēиК PortuguÃĒs Brasileiro @@ -52,14 +53,14 @@ ## LiÃĒn káēŋt -- [Tài liáģ‡u](https://immich.app/docs) -- [Giáģ›i thiáģ‡u](https://immich.app/docs/overview/introduction) -- [Cài đáēˇt](https://immich.app/docs/install/requirements) +- [Tài liáģ‡u](https://docs.immich.app) +- [Giáģ›i thiáģ‡u](https://docs.immich.app/overview/introduction) +- [Cài đáēˇt](https://docs.immich.app/install/requirements) - [Láģ™ trÃŦnh](https://immich.app/roadmap) - [Demo](#demo) - [Tính năng](#Tính-năng) -- [Dáģ‹ch thuáē­t](https://immich.app/docs/developer/translations) -- [ÄÃŗng gÃŗp](https://immich.app/docs/overview/support-the-project) +- [Dáģ‹ch thuáē­t](https://docs.immich.app/developer/translations) +- [ÄÃŗng gÃŗp](https://docs.immich.app/overview/support-the-project) ## Demo @@ -106,7 +107,7 @@ Truy cáē­p báēŖn demo [taĖŖi đÃĸy](https://demo.immich.app). Đáģ‘i váģ›i áģŠng ## Dáģ‹ch thuáē­t -Đáģc thÃĒm váģ dáģ‹ch thuáē­t [taĖŖi đÃĸy](https://immich.app/docs/developer/translations). +Đáģc thÃĒm váģ dáģ‹ch thuáē­t [taĖŖi đÃĸy](https://docs.immich.app/developer/translations). TÃŦnh tráēĄng dáģ‹ch thuáē­t diff --git a/readme_i18n/README_zh_CN.md b/readme_i18n/README_zh_CN.md index 5151e35379..b48e69f94d 100644 --- a/readme_i18n/README_zh_CN.md +++ b/readme_i18n/README_zh_CN.md @@ -32,6 +32,7 @@ Deutsch Nederlands TÃŧrkçe + æ­ŖéĢ”ä¸­æ–‡ ĐŖĐēŅ€Đ°Ņ—ĐŊҁҌĐēа Đ ŅƒŅŅĐēиК PortuguÃĒs Brasileiro @@ -54,14 +55,14 @@ ## į›ŽåŊ• -- [åŽ˜æ–šæ–‡æĄŖ](https://immich.app/docs) -- [éĄšį›Žæ€ģ览](https://immich.app/docs/overview/introduction) -- [åŽ‰čŖ…æ•™į¨‹](https://immich.app/docs/install/requirements) +- [åŽ˜æ–šæ–‡æĄŖ](https://docs.immich.app) +- [éĄšį›Žæ€ģ览](https://docs.immich.app/overview/introduction) +- [åŽ‰čŖ…æ•™į¨‹](https://docs.immich.app/install/requirements) - [莝įēŋ回](https://immich.app/roadmap) - [在įēŋæŧ”į¤ē](#į¤ē例) - [功čƒŊį‰šæ€§](#功čƒŊį‰šæ€§) -- [å¤šč¯­č¨€](https://immich.app/docs/developer/translations) -- [č´ĄįŒŽč€…](https://immich.app/docs/overview/support-the-project) +- [å¤šč¯­č¨€](https://docs.immich.app/developer/translations) +- [č´ĄįŒŽč€…](https://docs.immich.app/overview/support-the-project) ## į¤ē例 @@ -110,7 +111,7 @@ ## å¤šč¯­č¨€ -å…ŗäēŽįŋģč¯‘įš„æ›´å¤šäŋĄæ¯č¯ˇå‚见[此处](https://immich.app/docs/developer/translations)。 +å…ŗäēŽįŋģč¯‘įš„æ›´å¤šäŋĄæ¯č¯ˇå‚见[此处](https://docs.immich.app/developer/translations)。 įŋģ蝑čŋ›åēĻ diff --git a/readme_i18n/README_zh_TW.md b/readme_i18n/README_zh_TW.md new file mode 100644 index 0000000000..bf14ce2dc0 --- /dev/null +++ b/readme_i18n/README_zh_TW.md @@ -0,0 +1,132 @@ +

+
+
授æŦŠæĸæŦžīŧšAGPLv3 + + Discord + +
+
+

+ +

+ +

+

éĢ˜æ•ˆčƒŊįš„č‡Ēæžļį…§į‰‡å’ŒåŊąį‰‡įŽĄį†č§Ŗæąēæ–šæĄˆ

+
+ + + +
+ +

+ English + Català + EspaÃąol + Français + Italiano + æ—ĨæœŦčĒž + 한ęĩ­ė–´ + Deutsch + Nederlands + TÃŧrkçe + įŽ€äŊ“中文 + æ­ŖéĢ”ä¸­æ–‡ + ĐŖĐēŅ€Đ°Ņ—ĐŊҁҌĐēа + Đ ŅƒŅŅĐēиК + PortuguÃĒs Brasileiro + Svenska + Ø§Ų„ØšØąØ¨ŲŠØŠ + Tiáēŋng Viáģ‡t + ā¸ ā¸˛ā¸Šā¸˛āš„ā¸—ā¸ĸ +

+ +> [!WARNING] +> âš ī¸ č̋務åŋ…éĩåžĒ [3-2-1 備äģŊ原則](https://www.backblaze.com/blog/the-3-2-1-backup-strategy/)īŧŒåŽˆč­ˇįč˛´įš„į…§į‰‡čˆ‡åŊąį‰‡īŧ +> + +> [!NOTE] +> ä¸ģčρčĒĒæ˜Žæ–‡äģļīŧˆåŒ…åĢåŽ‰čŖæŒ‡å—īŧ‰å¯æ–ŧ https://immich.app/ 取垗。 + +## 逪įĩ + +- [čĒĒæ˜Žæ–‡äģļ](https://docs.immich.app/) +- [關æ–ŧ](https://docs.immich.app/overview/introduction) +- [åŽ‰čŖ](https://docs.immich.app/install/requirements) +- [į™ŧåą•č—åœ–](https://immich.app/roadmap) +- [᎚䏊éĢ”éŠ—](#᎚䏊éĢ”éŠ—) +- [功čƒŊ](#功čƒŊ) +- [įŋģč­¯](https://docs.immich.app/developer/translations) +- [č˛ĸįģ指南](https://docs.immich.app/overview/support-the-project) + +## ᎚䏊éĢ”éŠ— + +čĢ‹å‰åž€ [Demoo įļ˛įĢ™](https://demo.immich.app) įĢ‹åŗéĢ”éŠ— Immich。č‹ĨčĻåœ¨æ‰‹æŠŸ App čŠĻᔍīŧŒčĢ‹åœ¨ `äŧ翜å™¨į̝éģž URL` æŦ„äŊčŧ¸å…Ĩ `https://demo.immich.app`。 + +### į™ģå…Ĩčŗ‡č¨Š + +| é›ģ子éƒĩäģļ | 密įĸŧ | +| --------------- | ------ | +| demo@immich.app | demo | + +## 功čƒŊ + +| 功čƒŊ | æ‰‹æŠŸį‰ˆ | įļ˛é į‰ˆ | +| :----------------------------------------- | ------ | ------ | +| ä¸Šå‚ŗčˆ‡æĒĸčĻ–į…§į‰‡čˆ‡åŊąį‰‡ | 是 | 是 | +| 開啟 App 時č‡Ē動備äģŊ | 是 | ä¸éŠį”¨ | +| éŋå…é‡č¤‡åĒ’éĢ” | 是 | 是 | +| 選擇čρ備äģŊįš„į›¸į°ŋ | 是 | ä¸éŠį”¨ | +| 下čŧ‰į…§į‰‡čˆ‡åŊąį‰‡åˆ°æœŦæŠŸčŖįŊŽ | 是 | 是 | +| 多äŊŋį”¨č€…æ”¯æ´ | 是 | 是 | +| ᛏį°ŋčˆ‡å…ąäēĢᛏį°ŋ | 是 | 是 | +| å¯æ‹–æ›ŗįš„æ˛čģ¸ | 是 | 是 | +| 支援 RAW æ ŧåŧ | 是 | 是 | +| 中įšŧčŗ‡æ–™æĒĸčĻ–īŧˆEXIF、地圖īŧ‰ | 是 | 是 | +| 䞝中įšŧčŗ‡æ–™ã€į‰Šäģļã€č‡‰å­”čˆ‡ CLIP 搜尋 | 是 | 是 | +| įŽĄį†åŠŸčƒŊīŧˆäŊŋį”¨č€…įŽĄį†īŧ‰ | åĻ | 是 | +| čƒŒæ™¯å‚™äģŊ | 是 | ä¸éŠį”¨ | +| 虛æ“Ŧæģžå‹• | 是 | 是 | +| 支援 OAuth | 是 | 是 | +| API 金鑰 | ä¸éŠį”¨ | 是 | +| Live Photo/å‹•æ…‹į…§į‰‡å‚™äģŊčˆ‡æ’­æ”ž | 是 | 是 | +| 支援 360 åēĻå…¨æ™¯į…§į‰‡éĄ¯į¤ē | åĻ | 是 | +| äŊŋᔍ者č‡Ēč¨‚å„˛å­˜įĩæ§‹ | 是 | 是 | +| å…Ŧ開分äēĢ | 是 | 是 | +| å°å­˜čˆ‡æ”ļ藏 | 是 | 是 | +| ä¸–į•Œåœ°åœ– | 是 | 是 | +| čĻĒæœ‹åĨŊ友分äēĢ | 是 | 是 | +| č‡‰éƒ¨čž¨č­˜čˆ‡åˆ†įž¤ | 是 | 是 | +| 回æ†ļīŧˆx 嚴前īŧ‰ | 是 | 是 | +| é›ĸįˇšæ”¯æ´ | 是 | åĻ | +| å”¯čŽ€åĒ’éĢ”åēĢ | 是 | 是 | +| į…§į‰‡å †į–Š | 是 | 是 | +| æ¨™įą¤ | åĻ | 是 | +| čŗ‡æ–™å¤žæĒĸčĻ– | 是 | 是 | + +## įŋģč­¯ + +更多įŋģč­¯į›¸é—œčŗ‡č¨ŠčĢ‹čĻ‹ [æ­¤č™•](https://docs.immich.app/developer/translations)。 + + +įŋģč­¯į‹€æ…‹ + + +## å°ˆæĄˆæ´ģčēåēĻ + +![å°ˆæĄˆæ´ģčēåēĻ](https://repobeats.axiom.co/api/embed/9e86d9dc3ddd137161f2f6d2e758d7863b1789cb.svg "Repobeats åˆ†æžåœ–į‰‡") + +## Star æ•¸é‡æ­ˇå˛į´€éŒ„ + + + + + + Star æ­ˇå˛į´€éŒ„åœ–čĄ¨ + + + +## č˛ĸįģ者 + + + + diff --git a/renovate.json b/renovate.json index 5fe45d61f7..3a889f4789 100644 --- a/renovate.json +++ b/renovate.json @@ -21,6 +21,11 @@ "addLabels": [ "📱mobile" ] + }, + { + "matchPackageNames": ["ghcr.io/immich-app/postgres"], + "matchUpdateTypes": ["major"], + "enabled": false } ], "ignorePaths": [ diff --git a/server/.nvmrc b/server/.nvmrc index e2228113dd..442c7587a9 100644 --- a/server/.nvmrc +++ b/server/.nvmrc @@ -1 +1 @@ -22.19.0 +22.20.0 diff --git a/server/Dockerfile b/server/Dockerfile index a554e19406..2ff62f9ab4 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -1,131 +1,64 @@ -# dev build -FROM ghcr.io/immich-app/base-server-dev:202509021104@sha256:47d38c94775332000a93fbbeca1c796687b2d2919e3c75b6e26ab8a65d1864f3 AS dev - +FROM ghcr.io/immich-app/base-server-dev:202510092146@sha256:124ec9659cba4a206924de5e3691f84acde16d75fa2b10b7007542424b696b96 AS builder ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \ CI=1 \ - COREPACK_HOME=/tmp + COREPACK_HOME=/tmp \ + PNPM_HOME=/buildcache/pnpm-store \ + PATH="/buildcache/pnpm-store:$PATH" RUN npm install --global corepack@latest && \ corepack enable pnpm && \ - echo "store-dir=/buildcache/pnpm-store" >> /usr/local/etc/npmrc && \ - echo "devdir=/buildcache/node-gyp" >> /usr/local/etc/npmrc + pnpm config set store-dir "$PNPM_HOME" -COPY ./package* ./pnpm* .pnpmfile.cjs /tmp/create-dep-cache/ -COPY ./web/package* ./web/pnpm* /tmp/create-dep-cache/web/ -COPY ./server/package* ./server/pnpm* /tmp/create-dep-cache/server/ -COPY ./open-api/typescript-sdk/package* ./open-api/typescript-sdk/pnpm* /tmp/create-dep-cache/open-api/typescript-sdk/ -WORKDIR /tmp/create-dep-cache -RUN pnpm fetch && rm -rf /tmp/create-dep-cache && chmod -R o+rw /buildcache -WORKDIR /usr/src/app - -ENV PATH="${PATH}:/usr/src/app/server/bin:/usr/src/app/web/bin" \ - IMMICH_ENV=development \ - NVIDIA_DRIVER_CAPABILITIES=all \ - NVIDIA_VISIBLE_DEVICES=all -ENTRYPOINT ["tini", "--", "/bin/bash", "-c"] - -FROM dev AS dev-container-server - -RUN apt-get update --allow-releaseinfo-change && \ - apt-get install sudo inetutils-ping openjdk-11-jre-headless \ - vim nano \ - -y --no-install-recommends --fix-missing - -RUN usermod -aG sudo node && \ - echo "node ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \ - mkdir -p /workspaces/immich - -RUN chown node:node -R /workspaces -COPY --chown=node:node --chmod=755 ../.devcontainer/server/*.sh /immich-devcontainer/ - -WORKDIR /workspaces/immich - -FROM dev-container-server AS dev-container-mobile -USER root -# Enable multiarch for arm64 if necessary -RUN if [ "$(dpkg --print-architecture)" = "arm64" ]; then \ - dpkg --add-architecture amd64 && \ - apt-get update && \ - apt-get install -y --no-install-recommends \ - qemu-user-static \ - libc6:amd64 \ - libstdc++6:amd64 \ - libgcc1:amd64; \ - fi - -# Flutter SDK -# https://flutter.dev/docs/development/tools/sdk/releases?tab=linux -ENV FLUTTER_CHANNEL="stable" -ENV FLUTTER_VERSION="3.32.8" -ENV FLUTTER_HOME=/flutter -ENV PATH=${PATH}:${FLUTTER_HOME}/bin - -# Flutter SDK -RUN mkdir -p ${FLUTTER_HOME} \ - && curl -C - --output flutter.tar.xz https://storage.googleapis.com/flutter_infra_release/releases/${FLUTTER_CHANNEL}/linux/flutter_linux_${FLUTTER_VERSION}-${FLUTTER_CHANNEL}.tar.xz \ - && tar -xf flutter.tar.xz --strip-components=1 -C ${FLUTTER_HOME} \ - && rm flutter.tar.xz \ - && chown -R node ${FLUTTER_HOME} - - -RUN apt-get update \ - && wget -qO- https://dcm.dev/pgp-key.public | gpg --dearmor -o /usr/share/keyrings/dcm.gpg \ - && echo 'deb [signed-by=/usr/share/keyrings/dcm.gpg arch=amd64] https://dcm.dev/debian stable main' | tee /etc/apt/sources.list.d/dart_stable.list \ - && apt-get update \ - && apt-get install dcm -y - -RUN dart --disable-analytics - -# production-builder-base image -FROM ghcr.io/immich-app/base-server-dev:202509021104@sha256:47d38c94775332000a93fbbeca1c796687b2d2919e3c75b6e26ab8a65d1864f3 AS prod-builder-base -ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \ - CI=1 \ - COREPACK_HOME=/tmp - -RUN npm install --global corepack@latest && \ - corepack enable pnpm - -# server production build -FROM prod-builder-base AS server-prod +FROM builder AS server WORKDIR /usr/src/app -COPY ./package* ./pnpm* .pnpmfile.cjs ./ COPY ./server ./server/ -RUN SHARP_IGNORE_GLOBAL_LIBVIPS=true pnpm --filter immich --frozen-lockfile build && \ +RUN --mount=type=cache,id=pnpm-server,target=/buildcache/pnpm-store \ + --mount=type=bind,source=package.json,target=package.json \ + --mount=type=bind,source=.pnpmfile.cjs,target=.pnpmfile.cjs \ + --mount=type=bind,source=pnpm-lock.yaml,target=pnpm-lock.yaml \ + --mount=type=bind,source=pnpm-workspace.yaml,target=pnpm-workspace.yaml \ + SHARP_IGNORE_GLOBAL_LIBVIPS=true pnpm --filter immich --frozen-lockfile build && \ SHARP_FORCE_GLOBAL_LIBVIPS=true pnpm --filter immich --frozen-lockfile --prod --no-optional deploy /output/server-pruned -# web production build -FROM prod-builder-base AS web-prod +FROM builder AS web WORKDIR /usr/src/app -COPY ./package* ./pnpm* .pnpmfile.cjs ./ COPY ./web ./web/ COPY ./i18n ./i18n/ COPY ./open-api ./open-api/ -RUN SHARP_IGNORE_GLOBAL_LIBVIPS=true pnpm --filter @immich/sdk --filter immich-web --frozen-lockfile --force install && \ +RUN --mount=type=cache,id=pnpm-web,target=/buildcache/pnpm-store \ + --mount=type=bind,source=package.json,target=package.json \ + --mount=type=bind,source=.pnpmfile.cjs,target=.pnpmfile.cjs \ + --mount=type=bind,source=pnpm-lock.yaml,target=pnpm-lock.yaml \ + --mount=type=bind,source=pnpm-workspace.yaml,target=pnpm-workspace.yaml \ + SHARP_IGNORE_GLOBAL_LIBVIPS=true pnpm --filter @immich/sdk --filter immich-web --frozen-lockfile --force install && \ pnpm --filter @immich/sdk --filter immich-web build -FROM prod-builder-base AS cli-prod +FROM builder AS cli -COPY ./package* ./pnpm* .pnpmfile.cjs ./ COPY ./cli ./cli/ COPY ./open-api ./open-api/ -RUN pnpm --filter @immich/sdk --filter @immich/cli --frozen-lockfile install && \ +RUN --mount=type=cache,id=pnpm-cli,target=/buildcache/pnpm-store \ + --mount=type=bind,source=package.json,target=package.json \ + --mount=type=bind,source=.pnpmfile.cjs,target=.pnpmfile.cjs \ + --mount=type=bind,source=pnpm-lock.yaml,target=pnpm-lock.yaml \ + --mount=type=bind,source=pnpm-workspace.yaml,target=pnpm-workspace.yaml \ + pnpm --filter @immich/sdk --filter @immich/cli --frozen-lockfile install && \ pnpm --filter @immich/sdk --filter @immich/cli build && \ pnpm --filter @immich/cli --prod --no-optional deploy /output/cli-pruned -# prod base image -FROM ghcr.io/immich-app/base-server-prod:202509021104@sha256:84f3727cff75c623f79236cdd9a2b72c84f7665057f474851016f702c67157af +FROM ghcr.io/immich-app/base-server-prod:202510092146@sha256:c39b9ad949e7777bce415e6931334aeff7331e04cb7f9df93f9ae44f6ff36b9e WORKDIR /usr/src/app ENV NODE_ENV=production \ NVIDIA_DRIVER_CAPABILITIES=all \ NVIDIA_VISIBLE_DEVICES=all -COPY --from=server-prod /output/server-pruned ./server -COPY --from=web-prod /usr/src/app/web/build /build/www -COPY --from=cli-prod /output/cli-pruned ./cli -RUN ln -s ./cli/bin/immich server/bin/immich +COPY --from=server /output/server-pruned ./server +COPY --from=web /usr/src/app/web/build /build/www +COPY --from=cli /output/cli-pruned ./cli +RUN ln -s ../../cli/bin/immich server/bin/immich COPY LICENSE /licenses/LICENSE.txt COPY LICENSE /LICENSE diff --git a/server/Dockerfile.dev b/server/Dockerfile.dev new file mode 100644 index 0000000000..c37d9d3149 --- /dev/null +++ b/server/Dockerfile.dev @@ -0,0 +1,82 @@ +# dev build +FROM ghcr.io/immich-app/base-server-dev:202510092146@sha256:124ec9659cba4a206924de5e3691f84acde16d75fa2b10b7007542424b696b96 AS dev + +ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \ + CI=1 \ + COREPACK_HOME=/tmp + +RUN npm install --global corepack@latest && \ + corepack enable pnpm && \ + echo "store-dir=/buildcache/pnpm-store" >> /usr/local/etc/npmrc && \ + echo "devdir=/buildcache/node-gyp" >> /usr/local/etc/npmrc + +COPY ./package* ./pnpm* .pnpmfile.cjs /tmp/create-dep-cache/ +COPY ./web/package* ./web/pnpm* /tmp/create-dep-cache/web/ +COPY ./server/package* ./server/pnpm* /tmp/create-dep-cache/server/ +COPY ./open-api/typescript-sdk/package* ./open-api/typescript-sdk/pnpm* /tmp/create-dep-cache/open-api/typescript-sdk/ +WORKDIR /tmp/create-dep-cache +RUN pnpm fetch && rm -rf /tmp/create-dep-cache && chmod -R o+rw /buildcache +WORKDIR /usr/src/app + +ENV PATH="${PATH}:/usr/src/app/server/bin:/usr/src/app/web/bin" \ + IMMICH_ENV=development \ + NVIDIA_DRIVER_CAPABILITIES=all \ + NVIDIA_VISIBLE_DEVICES=all +ENTRYPOINT ["tini", "--", "/bin/bash", "-c"] + +FROM dev AS dev-container-server + +RUN apt-get update --allow-releaseinfo-change && \ + apt-get install sudo inetutils-ping openjdk-21-jre-headless \ + vim nano curl \ + -y --no-install-recommends --fix-missing + +RUN usermod -aG sudo node && \ + echo "node ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \ + mkdir -p /workspaces/immich + +RUN chown node:node -R /workspaces +COPY --chown=node:node --chmod=755 ../.devcontainer/server/*.sh /immich-devcontainer/ + +WORKDIR /workspaces/immich + +FROM dev-container-server AS dev-container-mobile +USER root +# Enable multiarch for arm64 if necessary +RUN if [ "$(dpkg --print-architecture)" = "arm64" ]; then \ + dpkg --add-architecture amd64 && \ + apt-get update && \ + apt-get install -y --no-install-recommends \ + gnupg \ + qemu-user-static \ + libc6:amd64 \ + libstdc++6:amd64 \ + libgcc1:amd64; \ + else \ + apt-get update && \ + apt-get install -y --no-install-recommends \ + gnupg; \ + fi + +# Flutter SDK +# https://flutter.dev/docs/development/tools/sdk/releases?tab=linux +ENV FLUTTER_CHANNEL="stable" +ENV FLUTTER_VERSION="3.35.4" +ENV FLUTTER_HOME=/flutter +ENV PATH=${PATH}:${FLUTTER_HOME}/bin + +# Flutter SDK +RUN mkdir -p ${FLUTTER_HOME} \ + && curl -C - --output flutter.tar.xz https://storage.googleapis.com/flutter_infra_release/releases/${FLUTTER_CHANNEL}/linux/flutter_linux_${FLUTTER_VERSION}-${FLUTTER_CHANNEL}.tar.xz \ + && tar -xf flutter.tar.xz --strip-components=1 -C ${FLUTTER_HOME} \ + && rm flutter.tar.xz \ + && chown -R node ${FLUTTER_HOME} \ + && git config --global --add safe.directory ${FLUTTER_HOME} + + +RUN wget -qO- https://dcm.dev/pgp-key.public | gpg --dearmor -o /usr/share/keyrings/dcm.gpg \ + && echo 'deb [signed-by=/usr/share/keyrings/dcm.gpg arch=amd64] https://dcm.dev/debian stable main' | tee /etc/apt/sources.list.d/dart_stable.list \ + && apt-get update \ + && apt-get install dcm -y + +RUN dart --disable-analytics diff --git a/server/bin/start.sh b/server/bin/start.sh index 10f897dd8e..0afff4c3a8 100755 --- a/server/bin/start.sh +++ b/server/bin/start.sh @@ -1,14 +1,15 @@ #!/usr/bin/env bash echo "Initializing Immich $IMMICH_SOURCE_REF" -lib_path="/usr/lib/$(arch)-linux-gnu/libmimalloc.so.2" -if [ -f "$lib_path" ]; then - export LD_PRELOAD="$lib_path" -else - echo "skipping libmimalloc - path not found $lib_path" -fi +# TODO: Update to mimalloc v3 when verified memory isn't released issue is fixed +# lib_path="/usr/lib/$(arch)-linux-gnu/libmimalloc.so.3" +# if [ -f "$lib_path" ]; then +# export LD_PRELOAD="$lib_path" +# else +# echo "skipping libmimalloc - path not found $lib_path" +# fi export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/lib/jellyfin-ffmpeg/lib" -SERVER_HOME=/usr/src/app/server +SERVER_HOME="$(readlink -f "$(dirname "$0")/..")" read_file_and_export() { fname="${!1}" diff --git a/server/package.json b/server/package.json index 554a65c0f3..080452c615 100644 --- a/server/package.json +++ b/server/package.json @@ -1,6 +1,6 @@ { "name": "immich", - "version": "1.141.1", + "version": "2.1.0", "description": "", "author": "", "private": true, @@ -37,23 +37,21 @@ "@nestjs/bullmq": "^11.0.1", "@nestjs/common": "^11.0.4", "@nestjs/core": "^11.0.4", - "@nestjs/event-emitter": "^3.0.0", "@nestjs/platform-express": "^11.0.4", "@nestjs/platform-socket.io": "^11.0.4", "@nestjs/schedule": "^6.0.0", "@nestjs/swagger": "^11.0.2", "@nestjs/websockets": "^11.0.4", "@opentelemetry/api": "^1.9.0", - "@opentelemetry/auto-instrumentations-node": "^0.62.0", "@opentelemetry/context-async-hooks": "^2.0.0", - "@opentelemetry/exporter-prometheus": "^0.203.0", - "@opentelemetry/instrumentation-http": "^0.203.0", - "@opentelemetry/instrumentation-ioredis": "^0.51.0", - "@opentelemetry/instrumentation-nestjs-core": "^0.49.0", - "@opentelemetry/instrumentation-pg": "^0.56.0", + "@opentelemetry/exporter-prometheus": "^0.206.0", + "@opentelemetry/instrumentation-http": "^0.206.0", + "@opentelemetry/instrumentation-ioredis": "^0.54.0", + "@opentelemetry/instrumentation-nestjs-core": "^0.53.0", + "@opentelemetry/instrumentation-pg": "^0.59.0", "@opentelemetry/resources": "^2.0.1", "@opentelemetry/sdk-metrics": "^2.0.1", - "@opentelemetry/sdk-node": "^0.203.0", + "@opentelemetry/sdk-node": "^0.206.0", "@opentelemetry/semantic-conventions": "^1.34.0", "@react-email/components": "^0.5.0", "@react-email/render": "^1.1.2", @@ -69,7 +67,7 @@ "compression": "^1.8.0", "cookie": "^1.0.2", "cookie-parser": "^1.4.7", - "cron": "4.3.0", + "cron": "4.3.3", "exiftool-vendored": "^28.8.0", "express": "^5.1.0", "fast-glob": "^3.3.2", @@ -80,14 +78,14 @@ "ioredis": "^5.3.2", "js-yaml": "^4.1.0", "kysely": "0.28.2", - "kysely-postgres-js": "^2.0.0", + "kysely-postgres-js": "^3.0.0", "lodash": "^4.17.21", "luxon": "^3.4.2", "mnemonist": "^0.40.3", "multer": "^2.0.2", "nest-commander": "^3.16.0", "nestjs-cls": "^5.0.0", - "nestjs-kysely": "^3.0.0", + "nestjs-kysely": "3.0.0", "nestjs-otel": "^7.0.0", "nodemailer": "^7.0.0", "openid-client": "^6.3.3", @@ -103,25 +101,21 @@ "sanitize-filename": "^1.6.3", "sanitize-html": "^2.14.0", "semver": "^7.6.2", - "sharp": "^0.34.3", + "sharp": "^0.34.4", "sirv": "^3.0.0", "socket.io": "^4.8.1", "tailwindcss-preset-email": "^1.4.0", "thumbhash": "^0.1.1", - "typeorm": "^0.3.17", "ua-parser-js": "^2.0.0", "uuid": "^11.1.0", "validator": "^13.12.0" }, "devDependencies": { - "@eslint/eslintrc": "^3.1.0", "@eslint/js": "^9.8.0", "@nestjs/cli": "^11.0.2", "@nestjs/schematics": "^11.0.0", "@nestjs/testing": "^11.0.4", "@swc/core": "^1.4.14", - "@testcontainers/postgresql": "^11.0.0", - "@testcontainers/redis": "^11.0.0", "@types/archiver": "^6.0.0", "@types/async-lock": "^1.4.2", "@types/bcrypt": "^6.0.0", @@ -135,8 +129,8 @@ "@types/luxon": "^3.6.2", "@types/mock-fs": "^4.13.1", "@types/multer": "^2.0.0", - "@types/node": "^22.18.0", - "@types/nodemailer": "^6.4.14", + "@types/node": "^22.18.8", + "@types/nodemailer": "^7.0.0", "@types/picomatch": "^4.0.0", "@types/pngjs": "^6.0.5", "@types/react": "^19.0.0", @@ -146,36 +140,30 @@ "@types/ua-parser-js": "^0.7.36", "@types/validator": "^13.15.2", "@vitest/coverage-v8": "^3.0.0", - "canvas": "^3.1.0", "eslint": "^9.14.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-unicorn": "^60.0.0", "globals": "^16.0.0", "mock-fs": "^5.2.0", - "node-addon-api": "^8.3.1", "node-gyp": "^11.2.0", "pngjs": "^7.0.0", "prettier": "^3.0.2", "prettier-plugin-organize-imports": "^4.0.0", - "rimraf": "^6.0.0", - "source-map-support": "^0.5.21", "sql-formatter": "^15.0.0", "supertest": "^7.1.0", "tailwindcss": "^3.4.0", "testcontainers": "^11.0.0", - "tsconfig-paths": "^4.2.0", "typescript": "^5.9.2", "typescript-eslint": "^8.28.0", "unplugin-swc": "^1.4.5", - "utimes": "^5.2.1", "vite-tsconfig-paths": "^5.0.0", "vitest": "^3.0.0" }, "volta": { - "node": "22.19.0" + "node": "22.20.0" }, "overrides": { - "sharp": "^0.34.3" + "sharp": "^0.34.4" } } diff --git a/server/src/app.module.ts b/server/src/app.module.ts index 8d261463e7..a1cd1edfdf 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -19,6 +19,7 @@ import { ConfigRepository } from 'src/repositories/config.repository'; import { EventRepository } from 'src/repositories/event.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; import { teardownTelemetry, TelemetryRepository } from 'src/repositories/telemetry.repository'; +import { UserRepository } from 'src/repositories/user.repository'; import { services } from 'src/services'; import { AuthService } from 'src/services/auth.service'; import { CliService } from 'src/services/cli.service'; @@ -55,6 +56,7 @@ class BaseModule implements OnModuleInit, OnModuleDestroy { private jobService: JobService, private telemetryRepository: TelemetryRepository, private authService: AuthService, + private userRepository: UserRepository, ) { logger.setAppName(this.worker); } diff --git a/server/src/bin/sync-sql.ts b/server/src/bin/sync-sql.ts index 6d3cb42fae..b632332069 100644 --- a/server/src/bin/sync-sql.ts +++ b/server/src/bin/sync-sql.ts @@ -15,6 +15,7 @@ import { repositories } from 'src/repositories'; import { AccessRepository } from 'src/repositories/access.repository'; import { ConfigRepository } from 'src/repositories/config.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; +import { MachineLearningRepository } from 'src/repositories/machine-learning.repository'; import { SyncRepository } from 'src/repositories/sync.repository'; import { AuthService } from 'src/services/auth.service'; import { getKyselyConfig } from 'src/utils/database'; @@ -57,7 +58,7 @@ class SqlGenerator { try { await this.setup(); for (const Repository of repositories) { - if (Repository === LoggingRepository) { + if (Repository === LoggingRepository || Repository === MachineLearningRepository) { continue; } await this.process(Repository); diff --git a/server/src/config.ts b/server/src/config.ts index 0d1e293be8..66c03450fa 100644 --- a/server/src/config.ts +++ b/server/src/config.ts @@ -54,6 +54,11 @@ export interface SystemConfig { machineLearning: { enabled: boolean; urls: string[]; + availabilityChecks: { + enabled: boolean; + timeout: number; + interval: number; + }; clip: { enabled: boolean; modelName: string; @@ -176,6 +181,8 @@ export interface SystemConfig { }; } +export type MachineLearningConfig = SystemConfig['machineLearning']; + export const defaults = Object.freeze({ backup: { database: { @@ -227,6 +234,11 @@ export const defaults = Object.freeze({ machineLearning: { enabled: process.env.IMMICH_MACHINE_LEARNING_ENABLED !== 'false', urls: [process.env.IMMICH_MACHINE_LEARNING_URL || 'http://immich-machine-learning:3003'], + availabilityChecks: { + enabled: true, + timeout: Number(process.env.IMMICH_MACHINE_LEARNING_PING_TIMEOUT) || 2000, + interval: 30_000, + }, clip: { enabled: true, modelName: 'ViT-B-32__openai', diff --git a/server/src/constants.ts b/server/src/constants.ts index b47640c4ae..3b75ca9f7e 100644 --- a/server/src/constants.ts +++ b/server/src/constants.ts @@ -5,7 +5,7 @@ import { SemVer } from 'semver'; import { DatabaseExtension, ExifOrientation, VectorIndex } from 'src/enum'; export const POSTGRES_VERSION_RANGE = '>=14.0.0'; -export const VECTORCHORD_VERSION_RANGE = '>=0.3 <0.5'; +export const VECTORCHORD_VERSION_RANGE = '>=0.3 <0.6'; export const VECTORS_VERSION_RANGE = '>=0.2 <0.4'; export const VECTOR_VERSION_RANGE = '>=0.5 <1'; @@ -51,11 +51,6 @@ export const serverVersion = new SemVer(version); export const AUDIT_LOG_MAX_DURATION = Duration.fromObject({ days: 100 }); export const ONE_HOUR = Duration.fromObject({ hours: 1 }); -export const MACHINE_LEARNING_PING_TIMEOUT = Number(process.env.MACHINE_LEARNING_PING_TIMEOUT || 2000); -export const MACHINE_LEARNING_AVAILABILITY_BACKOFF_TIME = Number( - process.env.MACHINE_LEARNING_AVAILABILITY_BACKOFF_TIME || 30_000, -); - export const citiesFile = 'cities500.txt'; export const reverseGeocodeMaxDistance = 25_000; diff --git a/server/src/controllers/asset-media.controller.ts b/server/src/controllers/asset-media.controller.ts index 171cfe7047..688e513b64 100644 --- a/server/src/controllers/asset-media.controller.ts +++ b/server/src/controllers/asset-media.controller.ts @@ -96,8 +96,9 @@ export class AssetMediaController { @Put(':id/original') @UseInterceptors(FileUploadInterceptor) @ApiConsumes('multipart/form-data') - @EndpointLifecycle({ addedAt: 'v1.106.0' }) - @ApiOperation({ + @EndpointLifecycle({ + addedAt: 'v1.106.0', + deprecatedAt: 'v1.142.0', summary: 'replaceAsset', description: 'Replace the asset with new file, without changing its id', }) diff --git a/server/src/controllers/auth.controller.ts b/server/src/controllers/auth.controller.ts index e865d18f59..636e3a3047 100644 --- a/server/src/controllers/auth.controller.ts +++ b/server/src/controllers/auth.controller.ts @@ -49,7 +49,7 @@ export class AuthController { } @Post('validateToken') - @Authenticated() + @Authenticated({ permission: false }) @HttpCode(HttpStatus.OK) validateAccessToken(): ValidateAccessTokenResponseDto { return { authStatus: true }; diff --git a/server/src/cores/storage.core.ts b/server/src/cores/storage.core.ts index 06dde4644c..25573cb08e 100644 --- a/server/src/cores/storage.core.ts +++ b/server/src/cores/storage.core.ts @@ -43,7 +43,9 @@ export class StorageCore { private storageRepository: StorageRepository, private systemMetadataRepository: SystemMetadataRepository, private logger: LoggingRepository, - ) {} + ) { + this.logger.setContext(StorageCore.name); + } static create( assetRepository: AssetRepository, diff --git a/server/src/decorators.ts b/server/src/decorators.ts index b88f2d2d7e..8a8e23d880 100644 --- a/server/src/decorators.ts +++ b/server/src/decorators.ts @@ -1,5 +1,5 @@ import { SetMetadata, applyDecorators } from '@nestjs/common'; -import { ApiExtension, ApiOperation, ApiProperty, ApiTags } from '@nestjs/swagger'; +import { ApiExtension, ApiOperation, ApiOperationOptions, ApiProperty, ApiTags } from '@nestjs/swagger'; import _ from 'lodash'; import { ADDED_IN_PREFIX, DEPRECATED_IN_PREFIX, LIFECYCLE_EXTENSION } from 'src/constants'; import { ImmichWorker, JobName, MetadataKey, QueueName } from 'src/enum'; @@ -87,7 +87,7 @@ export function Chunked( return Promise.all( chunks(argument, chunkSize).map(async (chunk) => { - await Reflect.apply(originalMethod, this, [ + return await Reflect.apply(originalMethod, this, [ ...arguments_.slice(0, parameterIndex), chunk, ...arguments_.slice(parameterIndex + 1), @@ -103,7 +103,7 @@ export function ChunkedArray(options?: { paramIndex?: number }): MethodDecorator } export function ChunkedSet(options?: { paramIndex?: number }): MethodDecorator { - return Chunked({ ...options, mergeFn: setUnion }); + return Chunked({ ...options, mergeFn: (args: Set[]) => setUnion(...args) }); } const UUID = '00000000-0000-4000-a000-000000000000'; @@ -159,12 +159,21 @@ type LifecycleMetadata = { deprecatedAt?: LifecycleRelease; }; -export const EndpointLifecycle = ({ addedAt, deprecatedAt }: LifecycleMetadata) => { +export const EndpointLifecycle = ({ + addedAt, + deprecatedAt, + description, + ...options +}: LifecycleMetadata & ApiOperationOptions) => { const decorators: MethodDecorator[] = [ApiExtension(LIFECYCLE_EXTENSION, { addedAt, deprecatedAt })]; if (deprecatedAt) { decorators.push( ApiTags('Deprecated'), - ApiOperation({ deprecated: true, description: DEPRECATED_IN_PREFIX + deprecatedAt }), + ApiOperation({ + deprecated: true, + description: DEPRECATED_IN_PREFIX + deprecatedAt + (description ? `. ${description}` : ''), + ...options, + }), ); } diff --git a/server/src/dtos/album.dto.ts b/server/src/dtos/album.dto.ts index 00f5759aac..2f3f22099a 100644 --- a/server/src/dtos/album.dto.ts +++ b/server/src/dtos/album.dto.ts @@ -128,6 +128,14 @@ export class AlbumUserResponseDto { role!: AlbumUserRole; } +export class ContributorCountResponseDto { + @ApiProperty() + userId!: string; + + @ApiProperty({ type: 'integer' }) + assetCount!: number; +} + export class AlbumResponseDto { id!: string; ownerId!: string; @@ -149,6 +157,11 @@ export class AlbumResponseDto { isActivityEnabled!: boolean; @ValidateEnum({ enum: AssetOrder, name: 'AssetOrder', optional: true }) order?: AssetOrder; + + // Optional per-user contribution counts for shared albums + @Type(() => ContributorCountResponseDto) + @ApiProperty({ type: [ContributorCountResponseDto], required: false }) + contributorCounts?: ContributorCountResponseDto[]; } export type MapAlbumDto = { diff --git a/server/src/dtos/search.dto.ts b/server/src/dtos/search.dto.ts index 30cdf3602e..2dcf97a574 100644 --- a/server/src/dtos/search.dto.ts +++ b/server/src/dtos/search.dto.ts @@ -6,7 +6,7 @@ import { PropertyLifecycle } from 'src/decorators'; import { AlbumResponseDto } from 'src/dtos/album.dto'; import { AssetResponseDto } from 'src/dtos/asset-response.dto'; import { AssetOrder, AssetType, AssetVisibility } from 'src/enum'; -import { Optional, ValidateBoolean, ValidateDate, ValidateEnum, ValidateUUID } from 'src/validation'; +import { Optional, ValidateBoolean, ValidateDate, ValidateEnum, ValidateString, ValidateUUID } from 'src/validation'; class BaseSearchDto { @ValidateUUID({ optional: true, nullable: true }) @@ -144,9 +144,7 @@ export class MetadataSearchDto extends RandomSearchDto { @Optional() deviceAssetId?: string; - @IsString() - @IsNotEmpty() - @Optional() + @ValidateString({ optional: true, trim: true }) description?: string; @IsString() @@ -154,9 +152,7 @@ export class MetadataSearchDto extends RandomSearchDto { @Optional() checksum?: string; - @IsString() - @IsNotEmpty() - @Optional() + @ValidateString({ optional: true, trim: true }) originalFileName?: string; @IsString() @@ -190,16 +186,12 @@ export class MetadataSearchDto extends RandomSearchDto { } export class StatisticsSearchDto extends BaseSearchDto { - @IsString() - @IsNotEmpty() - @Optional() + @ValidateString({ optional: true, trim: true }) description?: string; } export class SmartSearchDto extends BaseSearchWithResultsDto { - @IsString() - @IsNotEmpty() - @Optional() + @ValidateString({ optional: true, trim: true }) query?: string; @ValidateUUID({ optional: true }) diff --git a/server/src/dtos/system-config.dto.ts b/server/src/dtos/system-config.dto.ts index 8a58995de7..1facc6c331 100644 --- a/server/src/dtos/system-config.dto.ts +++ b/server/src/dtos/system-config.dto.ts @@ -1,5 +1,5 @@ import { ApiProperty } from '@nestjs/swagger'; -import { Exclude, Transform, Type } from 'class-transformer'; +import { Type } from 'class-transformer'; import { ArrayMinSize, IsInt, @@ -15,7 +15,6 @@ import { ValidateNested, } from 'class-validator'; import { SystemConfig } from 'src/config'; -import { PropertyLifecycle } from 'src/decorators'; import { CLIPConfig, DuplicateDetectionConfig, FacialRecognitionConfig } from 'src/dtos/model-config.dto'; import { AudioCodec, @@ -257,21 +256,32 @@ class SystemConfigLoggingDto { level!: LogLevel; } +class MachineLearningAvailabilityChecksDto { + @ValidateBoolean() + enabled!: boolean; + + @IsInt() + timeout!: number; + + @IsInt() + interval!: number; +} + class SystemConfigMachineLearningDto { @ValidateBoolean() enabled!: boolean; - @PropertyLifecycle({ deprecatedAt: 'v1.122.0' }) - @Exclude() - url?: string; - @IsUrl({ require_tld: false, allow_underscores: true }, { each: true }) @ArrayMinSize(1) - @Transform(({ obj, value }) => (obj.url ? [obj.url] : value)) @ValidateIf((dto) => dto.enabled) @ApiProperty({ type: 'array', items: { type: 'string', format: 'uri' }, minItems: 1 }) urls!: string[]; + @Type(() => MachineLearningAvailabilityChecksDto) + @ValidateNested() + @IsObject() + availabilityChecks!: MachineLearningAvailabilityChecksDto; + @Type(() => CLIPConfig) @ValidateNested() @IsObject() diff --git a/server/src/dtos/time-bucket.dto.ts b/server/src/dtos/time-bucket.dto.ts index 449cec3207..58772da00b 100644 --- a/server/src/dtos/time-bucket.dto.ts +++ b/server/src/dtos/time-bucket.dto.ts @@ -53,6 +53,12 @@ export class TimeBucketDto { description: 'Filter by asset visibility status (ARCHIVE, TIMELINE, HIDDEN, LOCKED)', }) visibility?: AssetVisibility; + + @ValidateBoolean({ + optional: true, + description: 'Include location data in the response', + }) + withCoordinates?: boolean; } export class TimeBucketAssetDto extends TimeBucketDto { @@ -185,6 +191,22 @@ export class TimeBucketAssetResponseDto { description: 'Array of country names extracted from EXIF GPS data', }) country!: (string | null)[]; + + @ApiProperty({ + type: 'array', + required: false, + items: { type: 'number', nullable: true }, + description: 'Array of latitude coordinates extracted from EXIF GPS data', + }) + latitude!: number[]; + + @ApiProperty({ + type: 'array', + required: false, + items: { type: 'number', nullable: true }, + description: 'Array of longitude coordinates extracted from EXIF GPS data', + }) + longitude!: number[]; } export class TimeBucketsResponseDto { diff --git a/server/src/emails/album-update.email.tsx b/server/src/emails/album-update.email.tsx index 3bed3a5b36..6fd2abb055 100644 --- a/server/src/emails/album-update.email.tsx +++ b/server/src/emails/album-update.email.tsx @@ -29,8 +29,8 @@ export const AlbumUpdateEmail = ({ - New media has been added to {albumName}, -
check it out! + New media has been added to {albumName}. +
Check it out!
); diff --git a/server/src/emails/components/button.component.tsx b/server/src/emails/components/button.component.tsx index b490e36650..a1fc4636cc 100644 --- a/server/src/emails/components/button.component.tsx +++ b/server/src/emails/components/button.component.tsx @@ -1,12 +1,12 @@ import React from 'react'; -import { Button, ButtonProps } from '@react-email/components'; +import { Button, ButtonProps, Text } from '@react-email/components'; export const ImmichButton = ({ children, ...props }: ButtonProps) => ( ); diff --git a/server/src/enum.ts b/server/src/enum.ts index 646138b060..b8e6e5209f 100644 --- a/server/src/enum.ts +++ b/server/src/enum.ts @@ -722,6 +722,8 @@ export enum NotificationType { JobFailed = 'JobFailed', BackupFailed = 'BackupFailed', SystemMessage = 'SystemMessage', + AlbumInvite = 'AlbumInvite', + AlbumUpdate = 'AlbumUpdate', Custom = 'Custom', } diff --git a/server/src/queries/access.repository.sql b/server/src/queries/access.repository.sql index 9aecaafb52..e98c5c6d98 100644 --- a/server/src/queries/access.repository.sql +++ b/server/src/queries/access.repository.sql @@ -71,6 +71,11 @@ where and "shared_link"."albumId" in ($2) -- AccessRepository.asset.checkAlbumAccess +with + "target" as ( + select + array[$1]::uuid[] as "ids" + ) select "asset"."id", "asset"."livePhotoVideoId" @@ -82,8 +87,12 @@ from left join "album_user" as "albumUsers" on "albumUsers"."albumsId" = "album"."id" left join "user" on "user"."id" = "albumUsers"."usersId" and "user"."deletedAt" is null + cross join "target" where - array["asset"."id", "asset"."livePhotoVideoId"] && array[$1]::uuid[] + ( + "asset"."id" = any (target.ids) + or "asset"."livePhotoVideoId" = any (target.ids) + ) and ( "album"."ownerId" = $2 or "user"."id" = $3 diff --git a/server/src/queries/album.repository.sql b/server/src/queries/album.repository.sql index 36c44414db..0087217738 100644 --- a/server/src/queries/album.repository.sql +++ b/server/src/queries/album.repository.sql @@ -407,3 +407,18 @@ from where "album_asset"."albumsId" = $1 and "album_asset"."assetsId" in ($2) + +-- AlbumRepository.getContributorCounts +select + "asset"."ownerId" as "userId", + count(*) as "assetCount" +from + "album_asset" + inner join "asset" on "asset"."id" = "assetsId" +where + "asset"."deletedAt" is null + and "album_asset"."albumsId" = $1 +group by + "asset"."ownerId" +order by + "assetCount" desc diff --git a/server/src/queries/sync.repository.sql b/server/src/queries/sync.repository.sql index 2a1b9d1631..809b59df10 100644 --- a/server/src/queries/sync.repository.sql +++ b/server/src/queries/sync.repository.sql @@ -591,6 +591,7 @@ from where "user"."updateId" < $1 and "user"."updateId" > $2 + and "id" = $3 order by "user"."updateId" asc diff --git a/server/src/queries/user.repository.sql b/server/src/queries/user.repository.sql index 6a02654781..c5a4f139a7 100644 --- a/server/src/queries/user.repository.sql +++ b/server/src/queries/user.repository.sql @@ -363,6 +363,14 @@ group by order by "user"."createdAt" asc +-- UserRepository.getCount +select + count(*) as "count" +from + "user" +where + "user"."deletedAt" is null + -- UserRepository.updateUsage update "user" set diff --git a/server/src/repositories/access.repository.ts b/server/src/repositories/access.repository.ts index 5cceb6dbe0..ca12ff040b 100644 --- a/server/src/repositories/access.repository.ts +++ b/server/src/repositories/access.repository.ts @@ -136,6 +136,7 @@ class AssetAccess { } return this.db + .with('target', (qb) => qb.selectNoFrom(sql`array[${sql.join([...assetIds])}]::uuid[]`.as('ids'))) .selectFrom('album') .innerJoin('album_asset as albumAssets', 'album.id', 'albumAssets.albumsId') .innerJoin('asset', (join) => @@ -143,11 +144,13 @@ class AssetAccess { ) .leftJoin('album_user as albumUsers', 'albumUsers.albumsId', 'album.id') .leftJoin('user', (join) => join.onRef('user.id', '=', 'albumUsers.usersId').on('user.deletedAt', 'is', null)) + .crossJoin('target') .select(['asset.id', 'asset.livePhotoVideoId']) - .where( - sql`array["asset"."id", "asset"."livePhotoVideoId"]`, - '&&', - sql`array[${sql.join([...assetIds])}]::uuid[] `, + .where((eb) => + eb.or([ + eb('asset.id', '=', sql`any(target.ids)`), + eb('asset.livePhotoVideoId', '=', sql`any(target.ids)`), + ]), ) .where((eb) => eb.or([eb('album.ownerId', '=', userId), eb('user.id', '=', userId)])) .where('album.deletedAt', 'is', null) diff --git a/server/src/repositories/album.repository.ts b/server/src/repositories/album.repository.ts index b023068f16..00c1dfda7f 100644 --- a/server/src/repositories/album.repository.ts +++ b/server/src/repositories/album.repository.ts @@ -379,4 +379,22 @@ export class AlbumRepository { ) .whereRef('album_asset.albumsId', '=', 'album.id'); } + + /** + * Get per-user asset contribution counts for a single album. + * Excludes deleted assets, orders by count desc. + */ + @GenerateSql({ params: [DummyValue.UUID] }) + getContributorCounts(id: string) { + return this.db + .selectFrom('album_asset') + .innerJoin('asset', 'asset.id', 'assetsId') + .where('asset.deletedAt', 'is', sql.lit(null)) + .where('album_asset.albumsId', '=', id) + .select('asset.ownerId as userId') + .select((eb) => eb.fn.countAll().as('assetCount')) + .groupBy('asset.ownerId') + .orderBy('assetCount', 'desc') + .execute(); + } } diff --git a/server/src/repositories/asset.repository.ts b/server/src/repositories/asset.repository.ts index ae595e35ae..5c3bd8996c 100644 --- a/server/src/repositories/asset.repository.ts +++ b/server/src/repositories/asset.repository.ts @@ -60,6 +60,7 @@ interface AssetBuilderOptions { status?: AssetStatus; assetType?: AssetType; visibility?: AssetVisibility; + withCoordinates?: boolean; } export interface TimeBucketOptions extends AssetBuilderOptions { @@ -628,6 +629,7 @@ export class AssetRepository { ) .as('ratio'), ]) + .$if(!!options.withCoordinates, (qb) => qb.select(['asset_exif.latitude', 'asset_exif.longitude'])) .where('asset.deletedAt', options.isTrashed ? 'is not' : 'is', null) .$if(options.visibility == undefined, withDefaultVisibility) .$if(!!options.visibility, (qb) => qb.where('asset.visibility', '=', options.visibility!)) @@ -701,6 +703,12 @@ export class AssetRepository { eb.fn.coalesce(eb.fn('array_agg', ['status']), sql.lit('{}')).as('status'), eb.fn.coalesce(eb.fn('array_agg', ['thumbhash']), sql.lit('{}')).as('thumbhash'), ]) + .$if(!!options.withCoordinates, (qb) => + qb.select((eb) => [ + eb.fn.coalesce(eb.fn('array_agg', ['latitude']), sql.lit('{}')).as('latitude'), + eb.fn.coalesce(eb.fn('array_agg', ['longitude']), sql.lit('{}')).as('longitude'), + ]), + ) .$if(!!options.withStacked, (qb) => qb.select((eb) => eb.fn.coalesce(eb.fn('json_agg', ['stack']), sql.lit('[]')).as('stack')), ), diff --git a/server/src/repositories/event.repository.ts b/server/src/repositories/event.repository.ts index c1b26d5dde..ec4c8a8f52 100644 --- a/server/src/repositories/event.repository.ts +++ b/server/src/repositories/event.repository.ts @@ -81,7 +81,7 @@ type EventMap = { StackDeleteAll: [{ stackIds: string[]; userId: string }]; // user events - UserSignup: [{ notify: boolean; id: string; tempPassword?: string }]; + UserSignup: [{ notify: boolean; id: string; password?: string }]; // websocket events WebsocketConnect: [{ userId: string }]; diff --git a/server/src/repositories/index.ts b/server/src/repositories/index.ts index a01b46f3bd..d2e1aa08c8 100644 --- a/server/src/repositories/index.ts +++ b/server/src/repositories/index.ts @@ -31,6 +31,7 @@ import { ProcessRepository } from 'src/repositories/process.repository'; import { SearchRepository } from 'src/repositories/search.repository'; import { ServerInfoRepository } from 'src/repositories/server-info.repository'; import { SessionRepository } from 'src/repositories/session.repository'; +import { SharedLinkAssetRepository } from 'src/repositories/shared-link-asset.repository'; import { SharedLinkRepository } from 'src/repositories/shared-link.repository'; import { StackRepository } from 'src/repositories/stack.repository'; import { StorageRepository } from 'src/repositories/storage.repository'; @@ -79,6 +80,7 @@ export const repositories = [ SessionRepository, ServerInfoRepository, SharedLinkRepository, + SharedLinkAssetRepository, StackRepository, StorageRepository, SyncRepository, diff --git a/server/src/repositories/logging.repository.ts b/server/src/repositories/logging.repository.ts index 939ecb718f..576ee6c810 100644 --- a/server/src/repositories/logging.repository.ts +++ b/server/src/repositories/logging.repository.ts @@ -142,6 +142,10 @@ export class LoggingRepository { this.handleMessage(LogLevel.Fatal, message, details); } + deprecate(message: string) { + this.warn(`[Deprecated] ${message}`); + } + private handleFunction(level: LogLevel, message: LogFunction, details: LogDetails[]) { if (this.logger.isLevelEnabled(level)) { this.handleMessage(level, message(), details); diff --git a/server/src/repositories/machine-learning.repository.ts b/server/src/repositories/machine-learning.repository.ts index f880ed1298..d148dc782b 100644 --- a/server/src/repositories/machine-learning.repository.ts +++ b/server/src/repositories/machine-learning.repository.ts @@ -1,6 +1,7 @@ import { Injectable } from '@nestjs/common'; +import { Duration } from 'luxon'; import { readFile } from 'node:fs/promises'; -import { MACHINE_LEARNING_AVAILABILITY_BACKOFF_TIME, MACHINE_LEARNING_PING_TIMEOUT } from 'src/constants'; +import { MachineLearningConfig } from 'src/config'; import { CLIPConfig } from 'src/dtos/model-config.dto'; import { LoggingRepository } from 'src/repositories/logging.repository'; @@ -57,82 +58,100 @@ export type TextEncodingOptions = ModelOptions & { language?: string }; @Injectable() export class MachineLearningRepository { - // Note that deleted URL's are not removed from this map (ie: they're leaked) - // Cleaning them up is low priority since there should be very few over a - // typical server uptime cycle - private urlAvailability: { - [url: string]: - | { - active: boolean; - lastChecked: number; - } - | undefined; - }; + private healthyMap: Record = {}; + private interval?: ReturnType; + private _config?: MachineLearningConfig; + + private get config(): MachineLearningConfig { + if (!this._config) { + throw new Error('Machine learning repository not been setup'); + } + + return this._config; + } constructor(private logger: LoggingRepository) { this.logger.setContext(MachineLearningRepository.name); - this.urlAvailability = {}; } - private setUrlAvailability(url: string, active: boolean) { - const current = this.urlAvailability[url]; - if (current?.active !== active) { - this.logger.verbose(`Setting ${url} ML server to ${active ? 'active' : 'inactive'}.`); + setup(config: MachineLearningConfig) { + this._config = config; + this.teardown(); + + // delete old servers + for (const url of Object.keys(this.healthyMap)) { + if (!config.urls.includes(url)) { + delete this.healthyMap[url]; + } } - this.urlAvailability[url] = { - active, - lastChecked: Date.now(), - }; + + if (!config.availabilityChecks.enabled) { + return; + } + + this.tick(); + this.interval = setInterval( + () => this.tick(), + Duration.fromObject({ milliseconds: config.availabilityChecks.interval }).as('milliseconds'), + ); } - private async checkAvailability(url: string) { - let active = false; + teardown() { + if (this.interval) { + clearInterval(this.interval); + } + } + + private tick() { + for (const url of this.config.urls) { + void this.check(url); + } + } + + private async check(url: string) { + let healthy = false; try { const response = await fetch(new URL('/ping', url), { - signal: AbortSignal.timeout(MACHINE_LEARNING_PING_TIMEOUT), + signal: AbortSignal.timeout(this.config.availabilityChecks.timeout), }); - active = response.ok; + if (response.ok) { + healthy = true; + } } catch { // nothing to do here } - this.setUrlAvailability(url, active); - return active; + + this.setHealthy(url, healthy); } - private async shouldSkipUrl(url: string) { - const availability = this.urlAvailability[url]; - if (availability === undefined) { - // If this is a new endpoint, then check inline and skip if it fails - if (!(await this.checkAvailability(url))) { - return true; - } - return false; + private setHealthy(url: string, healthy: boolean) { + if (this.healthyMap[url] !== healthy) { + this.logger.log(`Machine learning server became ${healthy ? 'healthy' : 'unhealthy'} (${url}).`); } - if (!availability.active && Date.now() - availability.lastChecked < MACHINE_LEARNING_AVAILABILITY_BACKOFF_TIME) { - // If this is an old inactive endpoint that hasn't been checked in a - // while then check but don't wait for the result, just skip it - // This avoids delays on every search whilst allowing higher priority - // ML servers to recover over time. - void this.checkAvailability(url); + + this.healthyMap[url] = healthy; + } + + private isHealthy(url: string) { + if (!this.config.availabilityChecks.enabled) { return true; } - return false; + + return this.healthyMap[url]; } - private async predict(urls: string[], payload: ModelPayload, config: MachineLearningRequest): Promise { + private async predict(payload: ModelPayload, config: MachineLearningRequest): Promise { const formData = await this.getFormData(payload, config); - let urlCounter = 0; - for (const url of urls) { - urlCounter++; - const isLast = urlCounter >= urls.length; - if (!isLast && (await this.shouldSkipUrl(url))) { - continue; - } + for (const url of [ + // try healthy servers first + ...this.config.urls.filter((url) => this.isHealthy(url)), + ...this.config.urls.filter((url) => !this.isHealthy(url)), + ]) { try { const response = await fetch(new URL('/predict', url), { method: 'POST', body: formData }); if (response.ok) { - this.setUrlAvailability(url, true); + this.setHealthy(url, true); return response.json(); } @@ -144,20 +163,21 @@ export class MachineLearningRepository { `Machine learning request to "${url}" failed: ${error instanceof Error ? error.message : error}`, ); } - this.setUrlAvailability(url, false); + + this.setHealthy(url, false); } throw new Error(`Machine learning request '${JSON.stringify(config)}' failed for all URLs`); } - async detectFaces(urls: string[], imagePath: string, { modelName, minScore }: FaceDetectionOptions) { + async detectFaces(imagePath: string, { modelName, minScore }: FaceDetectionOptions) { const request = { [ModelTask.FACIAL_RECOGNITION]: { [ModelType.DETECTION]: { modelName, options: { minScore } }, [ModelType.RECOGNITION]: { modelName }, }, }; - const response = await this.predict(urls, { imagePath }, request); + const response = await this.predict({ imagePath }, request); return { imageHeight: response.imageHeight, imageWidth: response.imageWidth, @@ -165,15 +185,15 @@ export class MachineLearningRepository { }; } - async encodeImage(urls: string[], imagePath: string, { modelName }: CLIPConfig) { + async encodeImage(imagePath: string, { modelName }: CLIPConfig) { const request = { [ModelTask.SEARCH]: { [ModelType.VISUAL]: { modelName } } }; - const response = await this.predict(urls, { imagePath }, request); + const response = await this.predict({ imagePath }, request); return response[ModelTask.SEARCH]; } - async encodeText(urls: string[], text: string, { language, modelName }: TextEncodingOptions) { + async encodeText(text: string, { language, modelName }: TextEncodingOptions) { const request = { [ModelTask.SEARCH]: { [ModelType.TEXTUAL]: { modelName, options: { language } } } }; - const response = await this.predict(urls, { text }, request); + const response = await this.predict({ text }, request); return response[ModelTask.SEARCH]; } diff --git a/server/src/repositories/media.repository.ts b/server/src/repositories/media.repository.ts index adbb8c5879..d98e018efb 100644 --- a/server/src/repositories/media.repository.ts +++ b/server/src/repositories/media.repository.ts @@ -57,28 +57,28 @@ export class MediaRepository { 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); + this.logger.debug(`Could not extract JpgFromRaw2 buffer from image, trying JPEG from RAW next: ${error}`); } 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); + this.logger.debug(`Could not extract JPEG buffer from image, trying PreviewJXL next: ${error}`); } 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); + this.logger.debug(`Could not extract PreviewJXL buffer from image, trying PreviewImage next: ${error}`); } 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); + this.logger.debug(`Could not extract preview buffer from image: ${error}`); return null; } } @@ -203,6 +203,9 @@ export class MediaRepository { isHDR: stream.color_transfer === 'smpte2084' || stream.color_transfer === 'arib-std-b67', bitrate: this.parseInt(stream.bit_rate), pixelFormat: stream.pix_fmt || 'yuv420p', + colorPrimaries: stream.color_primaries, + colorSpace: stream.color_space, + colorTransfer: stream.color_transfer, })), audioStreams: results.streams .filter((stream) => stream.codec_type === 'audio') diff --git a/server/src/repositories/metadata.repository.ts b/server/src/repositories/metadata.repository.ts index bf3a96f21f..e2360156e4 100644 --- a/server/src/repositories/metadata.repository.ts +++ b/server/src/repositories/metadata.repository.ts @@ -103,7 +103,7 @@ export class MetadataRepository { readTags(path: string): Promise { return this.exiftool.read(path).catch((error) => { - this.logger.warn(`Error reading exif data (${path}): ${error}`, error?.stack); + this.logger.warn(`Error reading exif data (${path}): ${error}\n${error?.stack}`); return {}; }) as Promise; } diff --git a/server/src/repositories/oauth.repository.ts b/server/src/repositories/oauth.repository.ts index 9a436e4b9a..58b1144647 100644 --- a/server/src/repositories/oauth.repository.ts +++ b/server/src/repositories/oauth.repository.ts @@ -29,6 +29,7 @@ export class OAuthRepository { ); const client = await this.getClient(config); state ??= randomState(); + let codeVerifier: string | null; if (codeChallenge) { codeVerifier = null; @@ -36,13 +37,20 @@ export class OAuthRepository { codeVerifier = randomPKCECodeVerifier(); codeChallenge = await calculatePKCECodeChallenge(codeVerifier); } - const url = buildAuthorizationUrl(client, { + + const params: Record = { redirect_uri: redirectUrl, scope: config.scope, state, - code_challenge: client.serverMetadata().supportsPKCE() ? codeChallenge : '', - code_challenge_method: client.serverMetadata().supportsPKCE() ? 'S256' : '', - }).toString(); + }; + + if (client.serverMetadata().supportsPKCE()) { + params.code_challenge = codeChallenge; + params.code_challenge_method = 'S256'; + } + + const url = buildAuthorizationUrl(client, params).toString(); + return { url, state, codeVerifier }; } diff --git a/server/src/repositories/shared-link-asset.repository.ts b/server/src/repositories/shared-link-asset.repository.ts new file mode 100644 index 0000000000..45085c4a8d --- /dev/null +++ b/server/src/repositories/shared-link-asset.repository.ts @@ -0,0 +1,18 @@ +import { Kysely } from 'kysely'; +import { InjectKysely } from 'nestjs-kysely'; +import { DB } from 'src/schema'; + +export class SharedLinkAssetRepository { + constructor(@InjectKysely() private db: Kysely) {} + + async remove(sharedLinkId: string, assetsId: string[]) { + const deleted = await this.db + .deleteFrom('shared_link_asset') + .where('shared_link_asset.sharedLinksId', '=', sharedLinkId) + .where('shared_link_asset.assetsId', 'in', assetsId) + .returning('assetsId') + .execute(); + + return deleted.map((row) => row.assetsId); + } +} diff --git a/server/src/repositories/sync.repository.ts b/server/src/repositories/sync.repository.ts index 6917921008..d8be720f45 100644 --- a/server/src/repositories/sync.repository.ts +++ b/server/src/repositories/sync.repository.ts @@ -412,6 +412,7 @@ class AuthUserSync extends BaseSync { return this.upsertQuery('user', options) .select(columns.syncUser) .select(['isAdmin', 'pinCode', 'oauthId', 'storageLabel', 'quotaSizeInBytes', 'quotaUsageInBytes']) + .where('id', '=', options.userId) .stream(); } } diff --git a/server/src/repositories/tag.repository.ts b/server/src/repositories/tag.repository.ts index 9bbb62bd8b..d9c44f4ba4 100644 --- a/server/src/repositories/tag.repository.ts +++ b/server/src/repositories/tag.repository.ts @@ -163,22 +163,22 @@ export class TagRepository { } async deleteEmptyTags() { - // TODO rewrite as a single statement - await this.db.transaction().execute(async (tx) => { - const result = await tx - .selectFrom('asset') - .innerJoin('tag_asset', 'tag_asset.assetsId', 'asset.id') - .innerJoin('tag_closure', 'tag_closure.id_descendant', 'tag_asset.tagsId') - .innerJoin('tag', 'tag.id', 'tag_closure.id_descendant') - .select((eb) => ['tag.id', eb.fn.count('asset.id').as('count')]) - .groupBy('tag.id') - .execute(); + const result = await this.db + .deleteFrom('tag') + .where(({ not, exists, selectFrom }) => + not( + exists( + selectFrom('tag_closure') + .whereRef('tag.id', '=', 'tag_closure.id_ancestor') + .innerJoin('tag_asset', 'tag_closure.id_descendant', 'tag_asset.tagsId'), + ), + ), + ) + .executeTakeFirst(); - const ids = result.filter(({ count }) => count === 0).map(({ id }) => id); - if (ids.length > 0) { - await this.db.deleteFrom('tag').where('id', 'in', ids).execute(); - this.logger.log(`Deleted ${ids.length} empty tags`); - } - }); + const deletedRows = Number(result.numDeletedRows); + if (deletedRows > 0) { + this.logger.log(`Deleted ${deletedRows} empty tags`); + } } } diff --git a/server/src/repositories/user.repository.ts b/server/src/repositories/user.repository.ts index 44f4a2bb9c..20b41c80f8 100644 --- a/server/src/repositories/user.repository.ts +++ b/server/src/repositories/user.repository.ts @@ -286,6 +286,16 @@ export class UserRepository { .execute(); } + @GenerateSql() + async getCount(): Promise { + const result = await this.db + .selectFrom('user') + .select((eb) => eb.fn.countAll().as('count')) + .where('user.deletedAt', 'is', null) + .executeTakeFirstOrThrow(); + return Number(result.count); + } + @GenerateSql({ params: [DummyValue.UUID, DummyValue.NUMBER] }) async updateUsage(id: string, delta: number): Promise { await this.db diff --git a/server/src/services/album.service.ts b/server/src/services/album.service.ts index d7b857d666..dd12e31892 100644 --- a/server/src/services/album.service.ts +++ b/server/src/services/album.service.ts @@ -79,12 +79,17 @@ export class AlbumService extends BaseService { const album = await this.findOrFail(id, { withAssets }); const [albumMetadataForIds] = await this.albumRepository.getMetadataForIds([album.id]); + const hasSharedUsers = album.albumUsers && album.albumUsers.length > 0; + const hasSharedLink = album.sharedLinks && album.sharedLinks.length > 0; + const isShared = hasSharedUsers || hasSharedLink; + return { ...mapAlbum(album, withAssets, auth), startDate: albumMetadataForIds?.startDate ?? undefined, endDate: albumMetadataForIds?.endDate ?? undefined, assetCount: albumMetadataForIds?.assetCount ?? 0, lastModifiedAssetTimestamp: albumMetadataForIds?.lastModifiedAssetTimestamp ?? undefined, + contributorCounts: isShared ? await this.albumRepository.getContributorCounts(album.id) : undefined, }; } diff --git a/server/src/services/asset.service.spec.ts b/server/src/services/asset.service.spec.ts index 7b29b8ab96..93861149c3 100755 --- a/server/src/services/asset.service.spec.ts +++ b/server/src/services/asset.service.spec.ts @@ -420,7 +420,7 @@ describe(AssetService.name, () => { ids: ['asset-1'], latitude: 0, longitude: 0, - visibility: undefined, + visibility: AssetVisibility.Archive, isFavorite: false, duplicateId: undefined, rating: undefined, diff --git a/server/src/services/asset.service.ts b/server/src/services/asset.service.ts index 725e3cff15..6cb0219745 100644 --- a/server/src/services/asset.service.ts +++ b/server/src/services/asset.service.ts @@ -115,59 +115,68 @@ export class AssetService extends BaseService { } async updateAll(auth: AuthDto, dto: AssetBulkUpdateDto): Promise { - const { ids, description, dateTimeOriginal, dateTimeRelative, timeZone, latitude, longitude, ...options } = dto; + const { + ids, + isFavorite, + visibility, + dateTimeOriginal, + latitude, + longitude, + rating, + description, + duplicateId, + dateTimeRelative, + timeZone, + } = dto; await this.requireAccess({ auth, permission: Permission.AssetUpdate, ids }); - const staticValuesChanged = - description !== undefined || dateTimeOriginal !== undefined || latitude !== undefined || longitude !== undefined; + const assetDto = { isFavorite, visibility, duplicateId }; + const exifDto = { latitude, longitude, rating, description, dateTimeOriginal }; - if (staticValuesChanged) { - await this.assetRepository.updateAllExif(ids, { description, dateTimeOriginal, latitude, longitude }); + const isExifChanged = Object.values(exifDto).some((v) => v !== undefined); + if (isExifChanged) { + await this.assetRepository.updateAllExif(ids, exifDto); } const assets = (dateTimeRelative !== undefined && dateTimeRelative !== 0) || timeZone !== undefined ? await this.assetRepository.updateDateTimeOriginal(ids, dateTimeRelative, timeZone) - : null; + : undefined; - const dateTimesWithTimezone = - assets?.map((asset) => { - const isoString = asset.dateTimeOriginal?.toISOString(); - let dateTime = isoString ? DateTime.fromISO(isoString) : null; + const dateTimesWithTimezone = assets + ? assets.map((asset) => { + const isoString = asset.dateTimeOriginal?.toISOString(); + let dateTime = isoString ? DateTime.fromISO(isoString) : null; - if (dateTime && asset.timeZone) { - dateTime = dateTime.setZone(asset.timeZone); - } + if (dateTime && asset.timeZone) { + dateTime = dateTime.setZone(asset.timeZone); + } - return { - assetId: asset.assetId, - dateTimeOriginal: dateTime?.toISO() ?? null, - }; - }) ?? null; + return { + assetId: asset.assetId, + dateTimeOriginal: dateTime?.toISO() ?? null, + }; + }) + : ids.map((id) => ({ assetId: id, dateTimeOriginal })); - if (staticValuesChanged || dateTimesWithTimezone) { - const entries: JobItem[] = (dateTimesWithTimezone ?? ids).map((entry: any) => ({ - name: JobName.SidecarWrite, - data: { - id: entry.assetId ?? entry, - description, - dateTimeOriginal: entry.dateTimeOriginal ?? dateTimeOriginal, - latitude, - longitude, - }, - })); - await this.jobRepository.queueAll(entries); + if (dateTimesWithTimezone.length > 0) { + await this.jobRepository.queueAll( + dateTimesWithTimezone.map(({ assetId: id, dateTimeOriginal }) => ({ + name: JobName.SidecarWrite, + data: { + ...exifDto, + id, + dateTimeOriginal: dateTimeOriginal ?? undefined, + }, + })), + ); } - if ( - options.visibility !== undefined || - options.isFavorite !== undefined || - options.duplicateId !== undefined || - options.rating !== undefined - ) { - await this.assetRepository.updateAll(ids, options); + const isAssetChanged = Object.values(assetDto).some((v) => v !== undefined); + if (isAssetChanged) { + await this.assetRepository.updateAll(ids, assetDto); - if (options.visibility === AssetVisibility.Locked) { + if (visibility === AssetVisibility.Locked) { await this.albumRepository.removeAssetsFromAll(ids); } } diff --git a/server/src/services/auth.service.ts b/server/src/services/auth.service.ts index 69d872e8c9..535df779cd 100644 --- a/server/src/services/auth.service.ts +++ b/server/src/services/auth.service.ts @@ -344,7 +344,7 @@ export class AuthService extends BaseService { await this.jobRepository.queue({ name: JobName.FileDelete, data: { files: [oldPath] } }); } } catch (error: Error | any) { - this.logger.warn(`Unable to sync oauth profile picture: ${error}`, error?.stack); + this.logger.warn(`Unable to sync oauth profile picture: ${error}\n${error?.stack}`); } } diff --git a/server/src/services/backup.service.ts b/server/src/services/backup.service.ts index 40dea2044c..3d99b6e522 100644 --- a/server/src/services/backup.service.ts +++ b/server/src/services/backup.service.ts @@ -132,12 +132,12 @@ export class BackupService extends BaseService { gzip.stdout.pipe(fileStream); pgdump.on('error', (err) => { - this.logger.error('Backup failed with error', err); + this.logger.error(`Backup failed with error: ${err}`); reject(err); }); gzip.on('error', (err) => { - this.logger.error('Gzip failed with error', err); + this.logger.error(`Gzip failed with error: ${err}`); reject(err); }); @@ -175,10 +175,10 @@ export class BackupService extends BaseService { }); await this.storageRepository.rename(backupFilePath, backupFilePath.replace('.tmp', '')); } catch (error) { - this.logger.error('Database Backup Failure', error); + this.logger.error(`Database Backup Failure: ${error}`); await this.storageRepository .unlink(backupFilePath) - .catch((error) => this.logger.error('Failed to delete failed backup file', error)); + .catch((error) => this.logger.error(`Failed to delete failed backup file: ${error}`)); throw error; } diff --git a/server/src/services/base.service.ts b/server/src/services/base.service.ts index 2f0e272883..5a2dd42c3c 100644 --- a/server/src/services/base.service.ts +++ b/server/src/services/base.service.ts @@ -38,6 +38,7 @@ import { ProcessRepository } from 'src/repositories/process.repository'; import { SearchRepository } from 'src/repositories/search.repository'; import { ServerInfoRepository } from 'src/repositories/server-info.repository'; import { SessionRepository } from 'src/repositories/session.repository'; +import { SharedLinkAssetRepository } from 'src/repositories/shared-link-asset.repository'; import { SharedLinkRepository } from 'src/repositories/shared-link.repository'; import { StackRepository } from 'src/repositories/stack.repository'; import { StorageRepository } from 'src/repositories/storage.repository'; @@ -89,6 +90,7 @@ export const BASE_SERVICE_DEPENDENCIES = [ ServerInfoRepository, SessionRepository, SharedLinkRepository, + SharedLinkAssetRepository, StackRepository, StorageRepository, SyncRepository, @@ -141,6 +143,7 @@ export class BaseService { protected serverInfoRepository: ServerInfoRepository, protected sessionRepository: SessionRepository, protected sharedLinkRepository: SharedLinkRepository, + protected sharedLinkAssetRepository: SharedLinkAssetRepository, protected stackRepository: StackRepository, protected storageRepository: StorageRepository, protected syncRepository: SyncRepository, @@ -215,6 +218,7 @@ export class BaseService { payload.storageLabel = sanitize(payload.storageLabel.replaceAll('.', '')); } + this.telemetryRepository.api.addToGauge(`immich.users.total`, 1); return this.userRepository.create(payload); } } diff --git a/server/src/services/database.service.ts b/server/src/services/database.service.ts index 758198a197..2ff0e0ca27 100644 --- a/server/src/services/database.service.ts +++ b/server/src/services/database.service.ts @@ -22,7 +22,7 @@ const messages = { The ${name} extension version is ${version}, which means it is a nightly release. Please run 'DROP EXTENSION IF EXISTS ${extension}' and switch to a release version. - See https://immich.app/docs/guides/database-queries for how to query the database.`, + See https://docs.immich.app/guides/database-queries for how to query the database.`, outOfRange: ({ name, version, range }: OutOfRangeArgs) => `The ${name} extension version is ${version}, but Immich only supports ${range}. Please change ${name} to a compatible version in the Postgres instance.`, @@ -32,20 +32,20 @@ const messages = { If the Postgres instance already has ${name} installed, Immich may not have the necessary permissions to activate it. In this case, please run 'CREATE EXTENSION IF NOT EXISTS ${extension} CASCADE' manually as a superuser. - See https://immich.app/docs/guides/database-queries for how to query the database.`, + See https://docs.immich.app/guides/database-queries for how to query the database.`, updateFailed: ({ name, extension, availableVersion }: UpdateFailedArgs) => `The ${name} extension can be updated to ${availableVersion}. Immich attempted to update the extension, but failed to do so. This may be because Immich does not have the necessary permissions to update the extension. Please run 'ALTER EXTENSION ${extension} UPDATE' manually as a superuser. - See https://immich.app/docs/guides/database-queries for how to query the database.`, + See https://docs.immich.app/guides/database-queries for how to query the database.`, dropFailed: ({ name, extension }: DropFailedArgs) => `The ${name} extension is no longer needed, but could not be dropped. This may be because Immich does not have the necessary permissions to drop the extension. Please run 'DROP EXTENSION ${extension};' manually as a superuser. - See https://immich.app/docs/guides/database-queries for how to query the database.`, + See https://docs.immich.app/guides/database-queries for how to query the database.`, restartRequired: ({ name, availableVersion }: RestartRequiredArgs) => `The ${name} extension has been updated to ${availableVersion}. Please restart the Postgres instance to complete the update.`, @@ -55,7 +55,7 @@ const messages = { If ${name} ${installedVersion} is compatible with Immich, please ensure the Postgres instance has this available.`, deprecatedExtension: (name: string) => `DEPRECATION WARNING: The ${name} extension is deprecated and support for it will be removed very soon. - See https://immich.app/docs/install/upgrading#migrating-to-vectorchord in order to switch to the VectorChord extension instead.`, + See https://docs.immich.app/install/upgrading#migrating-to-vectorchord in order to switch to the VectorChord extension instead.`, }; @Injectable() diff --git a/server/src/services/library.service.ts b/server/src/services/library.service.ts index f4a1992d91..5f78fa3629 100644 --- a/server/src/services/library.service.ts +++ b/server/src/services/library.service.ts @@ -245,7 +245,7 @@ export class LibraryService extends BaseService { job.paths.map((path) => this.processEntity(path, library.ownerId, job.libraryId) .then((asset) => assetImports.push(asset)) - .catch((error: any) => this.logger.error(`Error processing ${path} for library ${job.libraryId}`, error)), + .catch((error: any) => this.logger.error(`Error processing ${path} for library ${job.libraryId}: ${error}`)), ), ); diff --git a/server/src/services/media.service.spec.ts b/server/src/services/media.service.spec.ts index e494dd9bcc..ad52b0e8b0 100644 --- a/server/src/services/media.service.spec.ts +++ b/server/src/services/media.service.spec.ts @@ -445,6 +445,7 @@ describe(MediaService.name, () => { }), ); }); + it('should not skip intra frames for MTS file', async () => { mocks.media.probe.mockResolvedValue(probeStub.videoStreamMTS); mocks.assetJob.getForGenerateThumbnailJob.mockResolvedValue(assetStub.video); @@ -462,6 +463,25 @@ describe(MediaService.name, () => { ); }); + it('should override reserved color metadata', async () => { + mocks.media.probe.mockResolvedValue(probeStub.videoStreamReserved); + mocks.assetJob.getForGenerateThumbnailJob.mockResolvedValue(assetStub.video); + await sut.handleGenerateThumbnails({ id: assetStub.video.id }); + + expect(mocks.media.transcode).toHaveBeenCalledWith( + '/original/path.ext', + expect.any(String), + expect.objectContaining({ + inputOptions: expect.arrayContaining([ + '-bsf:v hevc_metadata=colour_primaries=1:matrix_coefficients=1:transfer_characteristics=1', + ]), + outputOptions: expect.any(Array), + progress: expect.any(Object), + twoPass: false, + }), + ); + }); + it('should use scaling divisible by 2 even when using quick sync', async () => { mocks.media.probe.mockResolvedValue(probeStub.videoStream2160p); mocks.systemMetadata.get.mockResolvedValue({ ffmpeg: { accel: TranscodeHardwareAcceleration.Qsv } }); @@ -841,6 +861,37 @@ describe(MediaService.name, () => { ); }); + it('should always generate full-size preview from non-web-friendly panoramas', async () => { + mocks.systemMetadata.get.mockResolvedValue({ image: { fullsize: { enabled: false } } }); + mocks.media.extract.mockResolvedValue({ buffer: extractedBuffer, format: RawExtractedFormat.Jpeg }); + mocks.media.getImageDimensions.mockResolvedValue({ width: 3840, height: 2160 }); + + mocks.assetJob.getForGenerateThumbnailJob.mockResolvedValue(assetStub.panoramaTif); + + await sut.handleGenerateThumbnails({ id: assetStub.image.id }); + + expect(mocks.media.decodeImage).toHaveBeenCalledOnce(); + expect(mocks.media.decodeImage).toHaveBeenCalledWith(assetStub.panoramaTif.originalPath, { + colorspace: Colorspace.Srgb, + orientation: undefined, + processInvalidImages: false, + size: undefined, + }); + + expect(mocks.media.generateThumbnail).toHaveBeenCalledTimes(3); + expect(mocks.media.generateThumbnail).toHaveBeenCalledWith( + rawBuffer, + { + colorspace: Colorspace.Srgb, + format: ImageFormat.Jpeg, + quality: 80, + processInvalidImages: false, + raw: rawInfo, + }, + expect.any(String), + ); + }); + it('should respect encoding options when generating full-size preview', async () => { mocks.systemMetadata.get.mockResolvedValue({ image: { fullsize: { enabled: true, format: ImageFormat.Webp, quality: 90 } }, diff --git a/server/src/services/media.service.ts b/server/src/services/media.service.ts index a2c3c5ed42..6caa682f5e 100644 --- a/server/src/services/media.service.ts +++ b/server/src/services/media.service.ts @@ -271,7 +271,9 @@ export class MediaService extends BaseService { // 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 generateFullsize = + (image.fullsize.enabled || asset.exifInfo.projectionType == 'EQUIRECTANGULAR') && + !mimeTypes.isWebSupportedImage(asset.originalPath); const convertFullsize = generateFullsize && (!extracted || !mimeTypes.isWebSupportedImage(` .${extracted.format}`)); const { info, data, colorspace } = await this.decodeImage( diff --git a/server/src/services/memory.service.ts b/server/src/services/memory.service.ts index 7bf9deab4b..1d39169f3e 100644 --- a/server/src/services/memory.service.ts +++ b/server/src/services/memory.service.ts @@ -40,7 +40,7 @@ export class MemoryService extends BaseService { try { await Promise.all(users.map((owner, i) => this.createOnThisDayMemories(owner.id, usersIds[i], target))); } catch (error) { - this.logger.error(`Failed to create memories for ${target.toISO()}`, error); + this.logger.error(`Failed to create memories for ${target.toISO()}: ${error}`); } // update system metadata even when there is an error to minimize the chance of duplicates await this.systemMetadataRepository.set(SystemMetadataKey.MemoriesState, { diff --git a/server/src/services/metadata.service.spec.ts b/server/src/services/metadata.service.spec.ts index 413b20a954..0adb390f6a 100644 --- a/server/src/services/metadata.service.spec.ts +++ b/server/src/services/metadata.service.spec.ts @@ -1660,5 +1660,16 @@ describe(MetadataService.name, () => { expect(result?.tag).toBe('GPSDateTime'); expect(result?.dateTime?.toDate()?.toISOString()).toBe('2023-10-10T10:00:00.000Z'); }); + + it('should prefer CreationDate over CreateDate', () => { + const tags = { + CreationDate: '2025:05:24 18:26:20+02:00', + CreateDate: '2025:08:27 08:45:40', + }; + + const result = firstDateTime(tags); + expect(result?.tag).toBe('CreationDate'); + expect(result?.dateTime?.toDate()?.toISOString()).toBe('2025-05-24T16:26:20.000Z'); + }); }); }); diff --git a/server/src/services/metadata.service.ts b/server/src/services/metadata.service.ts index 94ccd41ff5..7d3de76550 100644 --- a/server/src/services/metadata.service.ts +++ b/server/src/services/metadata.service.ts @@ -39,9 +39,9 @@ const EXIF_DATE_TAGS: Array = [ 'SubSecCreateDate', 'SubSecMediaCreateDate', 'DateTimeOriginal', + 'CreationDate', 'CreateDate', 'MediaCreateDate', - 'CreationDate', 'DateTimeCreated', 'GPSDateTime', 'DateTimeUTC', diff --git a/server/src/services/notification.service.spec.ts b/server/src/services/notification.service.spec.ts index eef1c4f8b2..a96caf5ac2 100644 --- a/server/src/services/notification.service.spec.ts +++ b/server/src/services/notification.service.spec.ts @@ -7,6 +7,7 @@ import { NotificationService } from 'src/services/notification.service'; import { INotifyAlbumUpdateJob } from 'src/types'; import { albumStub } from 'test/fixtures/album.stub'; import { assetStub } from 'test/fixtures/asset.stub'; +import { notificationStub } from 'test/fixtures/notification.stub'; import { userStub } from 'test/fixtures/user.stub'; import { newTestService, ServiceMocks } from 'test/utils'; @@ -147,7 +148,7 @@ describe(NotificationService.name, () => { await sut.onUserSignup({ id: '', notify: true }); expect(mocks.job.queue).toHaveBeenCalledWith({ name: JobName.NotifyUserSignup, - data: { id: '', tempPassword: undefined }, + data: { id: '', password: undefined }, }); }); }); @@ -282,6 +283,7 @@ describe(NotificationService.name, () => { }, ], }); + mocks.notification.create.mockResolvedValue(notificationStub.albumEvent); await expect(sut.handleAlbumInvite({ id: '', recipientId: '' })).resolves.toBe(JobStatus.Skipped); }); @@ -297,6 +299,7 @@ describe(NotificationService.name, () => { }, ], }); + mocks.notification.create.mockResolvedValue(notificationStub.albumEvent); await expect(sut.handleAlbumInvite({ id: '', recipientId: '' })).resolves.toBe(JobStatus.Skipped); }); @@ -313,6 +316,7 @@ describe(NotificationService.name, () => { ], }); mocks.systemMetadata.get.mockResolvedValue({ server: {} }); + mocks.notification.create.mockResolvedValue(notificationStub.albumEvent); mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' }); await expect(sut.handleAlbumInvite({ id: '', recipientId: '' })).resolves.toBe(JobStatus.Success); @@ -334,6 +338,7 @@ describe(NotificationService.name, () => { ], }); mocks.systemMetadata.get.mockResolvedValue({ server: {} }); + mocks.notification.create.mockResolvedValue(notificationStub.albumEvent); mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' }); mocks.assetJob.getAlbumThumbnailFiles.mockResolvedValue([]); @@ -363,6 +368,7 @@ describe(NotificationService.name, () => { ], }); mocks.systemMetadata.get.mockResolvedValue({ server: {} }); + mocks.notification.create.mockResolvedValue(notificationStub.albumEvent); mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' }); mocks.assetJob.getAlbumThumbnailFiles.mockResolvedValue([ { id: '1', type: AssetFileType.Thumbnail, path: 'path-to-thumb.jpg' }, @@ -394,6 +400,7 @@ describe(NotificationService.name, () => { ], }); mocks.systemMetadata.get.mockResolvedValue({ server: {} }); + mocks.notification.create.mockResolvedValue(notificationStub.albumEvent); mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' }); mocks.assetJob.getAlbumThumbnailFiles.mockResolvedValue([assetStub.image.files[2]]); @@ -431,6 +438,7 @@ describe(NotificationService.name, () => { albumUsers: [{ user: { id: userStub.user1.id } } as AlbumUser], }); mocks.user.get.mockResolvedValueOnce(userStub.user1); + mocks.notification.create.mockResolvedValue(notificationStub.albumEvent); mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' }); mocks.assetJob.getAlbumThumbnailFiles.mockResolvedValue([]); @@ -453,6 +461,7 @@ describe(NotificationService.name, () => { }, ], }); + mocks.notification.create.mockResolvedValue(notificationStub.albumEvent); mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' }); mocks.assetJob.getAlbumThumbnailFiles.mockResolvedValue([]); @@ -475,6 +484,7 @@ describe(NotificationService.name, () => { }, ], }); + mocks.notification.create.mockResolvedValue(notificationStub.albumEvent); mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' }); mocks.assetJob.getAlbumThumbnailFiles.mockResolvedValue([]); @@ -489,6 +499,7 @@ describe(NotificationService.name, () => { albumUsers: [{ user: { id: userStub.user1.id } } as AlbumUser], }); mocks.user.get.mockResolvedValue(userStub.user1); + mocks.notification.create.mockResolvedValue(notificationStub.albumEvent); mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' }); mocks.assetJob.getAlbumThumbnailFiles.mockResolvedValue([]); diff --git a/server/src/services/notification.service.ts b/server/src/services/notification.service.ts index 1a257309b2..5d192523b1 100644 --- a/server/src/services/notification.service.ts +++ b/server/src/services/notification.service.ts @@ -1,5 +1,6 @@ import { BadRequestException, Injectable } from '@nestjs/common'; import { OnEvent, OnJob } from 'src/decorators'; +import { MapAlbumDto } from 'src/dtos/album.dto'; import { mapAsset } from 'src/dtos/asset-response.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { @@ -191,9 +192,9 @@ export class NotificationService extends BaseService { } @OnEvent({ name: 'UserSignup' }) - async onUserSignup({ notify, id, tempPassword }: ArgOf<'UserSignup'>) { + async onUserSignup({ notify, id, password: password }: ArgOf<'UserSignup'>) { if (notify) { - await this.jobRepository.queue({ name: JobName.NotifyUserSignup, data: { id, tempPassword } }); + await this.jobRepository.queue({ name: JobName.NotifyUserSignup, data: { id, password } }); } } @@ -251,70 +252,8 @@ export class NotificationService extends BaseService { 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 }; - } - @OnJob({ name: JobName.NotifyUserSignup, queue: QueueName.Notification }) - async handleUserSignup({ id, tempPassword }: JobOf) { + async handleUserSignup({ id, password }: JobOf) { const user = await this.userRepository.get(id, { withDeleted: false }); if (!user) { return JobStatus.Skipped; @@ -327,7 +266,7 @@ export class NotificationService extends BaseService { baseUrl: getExternalDomain(server), displayName: user.name, username: user.email, - password: tempPassword, + password, }, customTemplate: templates.email.welcomeTemplate, }); @@ -357,6 +296,8 @@ export class NotificationService extends BaseService { return JobStatus.Skipped; } + await this.sendAlbumLocalNotification(album, recipientId, NotificationType.AlbumInvite, album.owner.name); + const { emailNotifications } = getPreferences(recipient.metadata); if (!emailNotifications.enabled || !emailNotifications.albumInvite) { @@ -406,6 +347,8 @@ export class NotificationService extends BaseService { return JobStatus.Skipped; } + await this.sendAlbumLocalNotification(album, recipientId, NotificationType.AlbumUpdate); + const attachment = await this.getAlbumThumbnailAttachment(album); const { server, templates } = await this.getConfig({ withCache: false }); @@ -493,4 +436,25 @@ export class NotificationService extends BaseService { cid: 'album-thumbnail', }; } + + private async sendAlbumLocalNotification( + album: MapAlbumDto, + userId: string, + type: NotificationType.AlbumInvite | NotificationType.AlbumUpdate, + senderName?: string, + ) { + const isInvite = type === NotificationType.AlbumInvite; + const item = await this.notificationRepository.create({ + userId, + type, + level: isInvite ? NotificationLevel.Success : NotificationLevel.Info, + title: isInvite ? 'Shared Album Invitation' : 'Shared Album Update', + description: isInvite + ? `${senderName} shared an album (${album.albumName}) with you` + : `New media has been added to the album (${album.albumName})`, + data: JSON.stringify({ albumId: album.id }), + }); + + this.eventRepository.clientSend('on_notification', userId, mapNotification(item)); + } } diff --git a/server/src/services/person.service.spec.ts b/server/src/services/person.service.spec.ts index 13c3128317..41c44ea476 100644 --- a/server/src/services/person.service.spec.ts +++ b/server/src/services/person.service.spec.ts @@ -729,7 +729,6 @@ describe(PersonService.name, () => { mocks.assetJob.getForDetectFacesJob.mockResolvedValue({ ...assetStub.image, files: [assetStub.image.files[1]] }); await sut.handleDetectFaces({ id: assetStub.image.id }); expect(mocks.machineLearning.detectFaces).toHaveBeenCalledWith( - ['http://immich-machine-learning:3003'], '/uploads/user-id/thumbs/path.jpg', expect.objectContaining({ minScore: 0.7, modelName: 'buffalo_l' }), ); diff --git a/server/src/services/person.service.ts b/server/src/services/person.service.ts index 344b69efde..6fa9b3fdd2 100644 --- a/server/src/services/person.service.ts +++ b/server/src/services/person.service.ts @@ -316,7 +316,6 @@ export class PersonService extends BaseService { } const { imageHeight, imageWidth, faces } = await this.machineLearningRepository.detectFaces( - machineLearning.urls, previewFile.path, machineLearning.facialRecognition, ); diff --git a/server/src/services/search.service.spec.ts b/server/src/services/search.service.spec.ts index ecd9b0f98e..0dec02f18f 100644 --- a/server/src/services/search.service.spec.ts +++ b/server/src/services/search.service.spec.ts @@ -231,7 +231,6 @@ describe(SearchService.name, () => { await sut.searchSmart(authStub.user1, { query: 'test' }); expect(mocks.machineLearning.encodeText).toHaveBeenCalledWith( - [expect.any(String)], 'test', expect.objectContaining({ modelName: expect.any(String) }), ); @@ -245,7 +244,6 @@ describe(SearchService.name, () => { await sut.searchSmart(authStub.user1, { query: 'test', page: 2, size: 50 }); expect(mocks.machineLearning.encodeText).toHaveBeenCalledWith( - [expect.any(String)], 'test', expect.objectContaining({ modelName: expect.any(String) }), ); @@ -263,7 +261,6 @@ describe(SearchService.name, () => { await sut.searchSmart(authStub.user1, { query: 'test' }); expect(mocks.machineLearning.encodeText).toHaveBeenCalledWith( - [expect.any(String)], 'test', expect.objectContaining({ modelName: 'ViT-B-16-SigLIP__webli' }), ); @@ -273,7 +270,6 @@ describe(SearchService.name, () => { await sut.searchSmart(authStub.user1, { query: 'test', language: 'de' }); expect(mocks.machineLearning.encodeText).toHaveBeenCalledWith( - [expect.any(String)], 'test', expect.objectContaining({ language: 'de' }), ); diff --git a/server/src/services/search.service.ts b/server/src/services/search.service.ts index 978f481804..9a6f8321a9 100644 --- a/server/src/services/search.service.ts +++ b/server/src/services/search.service.ts @@ -118,7 +118,7 @@ export class SearchService extends BaseService { const key = machineLearning.clip.modelName + dto.query + dto.language; embedding = this.embeddingCache.get(key); if (!embedding) { - embedding = await this.machineLearningRepository.encodeText(machineLearning.urls, dto.query, { + embedding = await this.machineLearningRepository.encodeText(dto.query, { modelName: machineLearning.clip.modelName, language: dto.language, }); diff --git a/server/src/services/shared-link.service.spec.ts b/server/src/services/shared-link.service.spec.ts index 9483cdddff..062214b975 100644 --- a/server/src/services/shared-link.service.spec.ts +++ b/server/src/services/shared-link.service.spec.ts @@ -300,6 +300,7 @@ describe(SharedLinkService.name, () => { mocks.sharedLink.get.mockResolvedValue(_.cloneDeep(sharedLinkStub.individual)); mocks.sharedLink.create.mockResolvedValue(sharedLinkStub.individual); mocks.sharedLink.update.mockResolvedValue(sharedLinkStub.individual); + mocks.sharedLinkAsset.remove.mockResolvedValue([assetStub.image.id]); await expect( sut.removeAssets(authStub.admin, 'link-1', { assetIds: [assetStub.image.id, 'asset-2'] }), @@ -308,6 +309,7 @@ describe(SharedLinkService.name, () => { { assetId: 'asset-2', success: false, error: AssetIdErrorReason.NOT_FOUND }, ]); + expect(mocks.sharedLinkAsset.remove).toHaveBeenCalledWith('link-1', [assetStub.image.id, 'asset-2']); expect(mocks.sharedLink.update).toHaveBeenCalledWith({ ...sharedLinkStub.individual, assets: [] }); }); }); diff --git a/server/src/services/shared-link.service.ts b/server/src/services/shared-link.service.ts index 096739d056..3c1a6083e9 100644 --- a/server/src/services/shared-link.service.ts +++ b/server/src/services/shared-link.service.ts @@ -175,10 +175,12 @@ export class SharedLinkService extends BaseService { throw new BadRequestException('Invalid shared link type'); } + const removedAssetIds = await this.sharedLinkAssetRepository.remove(id, dto.assetIds); + const results: AssetIdsResponseDto[] = []; for (const assetId of dto.assetIds) { - const hasAsset = sharedLink.assets.find((asset) => asset.id === assetId); - if (!hasAsset) { + const wasRemoved = removedAssetIds.find((id) => id === assetId); + if (!wasRemoved) { results.push({ assetId, success: false, error: AssetIdErrorReason.NOT_FOUND }); continue; } diff --git a/server/src/services/smart-info.service.spec.ts b/server/src/services/smart-info.service.spec.ts index edd9f4663a..b3af5cd15f 100644 --- a/server/src/services/smart-info.service.spec.ts +++ b/server/src/services/smart-info.service.spec.ts @@ -205,7 +205,6 @@ describe(SmartInfoService.name, () => { expect(await sut.handleEncodeClip({ id: assetStub.image.id })).toEqual(JobStatus.Success); expect(mocks.machineLearning.encodeImage).toHaveBeenCalledWith( - ['http://immich-machine-learning:3003'], '/uploads/user-id/thumbs/path.jpg', expect.objectContaining({ modelName: 'ViT-B-32__openai' }), ); @@ -242,7 +241,6 @@ describe(SmartInfoService.name, () => { expect(mocks.database.wait).toHaveBeenCalledWith(512); expect(mocks.machineLearning.encodeImage).toHaveBeenCalledWith( - ['http://immich-machine-learning:3003'], '/uploads/user-id/thumbs/path.jpg', expect.objectContaining({ modelName: 'ViT-B-32__openai' }), ); diff --git a/server/src/services/smart-info.service.ts b/server/src/services/smart-info.service.ts index 3b8e2d1fc3..eff16fea45 100644 --- a/server/src/services/smart-info.service.ts +++ b/server/src/services/smart-info.service.ts @@ -108,11 +108,7 @@ export class SmartInfoService extends BaseService { return JobStatus.Skipped; } - const embedding = await this.machineLearningRepository.encodeImage( - machineLearning.urls, - asset.files[0].path, - machineLearning.clip, - ); + const embedding = await this.machineLearningRepository.encodeImage(asset.files[0].path, machineLearning.clip); if (this.databaseRepository.isBusy(DatabaseLock.CLIPDimSize)) { this.logger.verbose(`Waiting for CLIP dimension size to be updated`); diff --git a/server/src/services/storage-template.service.ts b/server/src/services/storage-template.service.ts index 6086d62809..1d38bf7011 100644 --- a/server/src/services/storage-template.service.ts +++ b/server/src/services/storage-template.service.ts @@ -338,7 +338,7 @@ export class StorageTemplateService extends BaseService { return destination; } catch (error: any) { - this.logger.error(`Unable to get template path for ${filename}`, error); + this.logger.error(`Unable to get template path for ${filename}: ${error}`); return asset.originalPath; } } diff --git a/server/src/services/storage.service.ts b/server/src/services/storage.service.ts index b983c34f62..50dffd5465 100644 --- a/server/src/services/storage.service.ts +++ b/server/src/services/storage.service.ts @@ -15,7 +15,7 @@ import { BaseService } from 'src/services/base.service'; import { JobOf, SystemFlags } from 'src/types'; import { ImmichStartupError } from 'src/utils/misc'; -const docsMessage = `Please see https://immich.app/docs/administration/system-integrity#folder-checks for more information.`; +const docsMessage = `Please see https://docs.immich.app/administration/system-integrity#folder-checks for more information.`; @Injectable() export class StorageService extends BaseService { diff --git a/server/src/services/system-config.service.spec.ts b/server/src/services/system-config.service.spec.ts index 486945546f..5a9c7f4df3 100644 --- a/server/src/services/system-config.service.spec.ts +++ b/server/src/services/system-config.service.spec.ts @@ -82,6 +82,11 @@ const updatedConfig = Object.freeze({ machineLearning: { enabled: true, urls: ['http://immich-machine-learning:3003'], + availabilityChecks: { + enabled: true, + interval: 30_000, + timeout: 2000, + }, clip: { enabled: true, modelName: 'ViT-B-32__openai', diff --git a/server/src/services/system-config.service.ts b/server/src/services/system-config.service.ts index d046b0317a..ea95b4df24 100644 --- a/server/src/services/system-config.service.ts +++ b/server/src/services/system-config.service.ts @@ -16,6 +16,20 @@ export class SystemConfigService extends BaseService { async onBootstrap() { const config = await this.getConfig({ withCache: false }); await this.eventRepository.emit('ConfigInit', { newConfig: config }); + + if ( + process.env.IMMICH_MACHINE_LEARNING_PING_TIMEOUT || + process.env.IMMICH_MACHINE_LEARNING_AVAILABILITY_BACKOFF_TIME + ) { + this.logger.deprecate( + 'IMMICH_MACHINE_LEARNING_PING_TIMEOUT and MACHINE_LEARNING_AVAILABILITY_BACKOFF_TIME have been moved to system config(`machineLearning.availabilityChecks`) and will be removed in a future release.', + ); + } + } + + @OnEvent({ name: 'AppShutdown' }) + onShutdown() { + this.machineLearningRepository.teardown(); } async getSystemConfig(): Promise { @@ -28,12 +42,14 @@ export class SystemConfigService extends BaseService { } @OnEvent({ name: 'ConfigInit', priority: -100 }) - onConfigInit({ newConfig: { logging } }: ArgOf<'ConfigInit'>) { + onConfigInit({ newConfig: { logging, machineLearning } }: ArgOf<'ConfigInit'>) { const { logLevel: envLevel } = this.configRepository.getEnv(); const configLevel = logging.enabled ? logging.level : false; const level = envLevel ?? configLevel; this.logger.setLogLevel(level); this.logger.log(`LogLevel=${level} ${envLevel ? '(set via IMMICH_LOG_LEVEL)' : '(set via system config)'}`); + + this.machineLearningRepository.setup(machineLearning); } @OnEvent({ name: 'ConfigUpdate', server: true }) diff --git a/server/src/services/user-admin.service.ts b/server/src/services/user-admin.service.ts index 3ae9d429eb..a57072e496 100644 --- a/server/src/services/user-admin.service.ts +++ b/server/src/services/user-admin.service.ts @@ -38,7 +38,7 @@ export class UserAdminService extends BaseService { await this.eventRepository.emit('UserSignup', { notify: !!notify, id: user.id, - tempPassword: user.shouldChangePassword ? userDto.password : undefined, + password: userDto.password, }); return mapUserAdmin(user); @@ -102,6 +102,7 @@ export class UserAdminService extends BaseService { const status = force ? UserStatus.Removing : UserStatus.Deleted; const user = await this.userRepository.update(id, { status, deletedAt: new Date() }); + this.telemetryRepository.api.addToGauge(`immich.users.total`, -1); if (force) { await this.jobRepository.queue({ name: JobName.UserDelete, data: { id: user.id, force } }); @@ -114,6 +115,7 @@ export class UserAdminService extends BaseService { await this.findOrFail(id, { withDeleted: true }); await this.albumRepository.restoreAll(id); const user = await this.userRepository.restore(id); + this.telemetryRepository.api.addToGauge('immich.users.total', 1); return mapUserAdmin(user); } diff --git a/server/src/services/user.service.ts b/server/src/services/user.service.ts index 6849b17ac3..fc71777673 100644 --- a/server/src/services/user.service.ts +++ b/server/src/services/user.service.ts @@ -3,14 +3,14 @@ import { Updateable } from 'kysely'; import { DateTime } from 'luxon'; import { SALT_ROUNDS } from 'src/constants'; import { StorageCore } from 'src/cores/storage.core'; -import { OnJob } from 'src/decorators'; +import { OnEvent, OnJob } from 'src/decorators'; import { AuthDto } from 'src/dtos/auth.dto'; import { LicenseKeyDto, LicenseResponseDto } from 'src/dtos/license.dto'; import { OnboardingDto, OnboardingResponseDto } from 'src/dtos/onboarding.dto'; import { UserPreferencesResponseDto, UserPreferencesUpdateDto, mapPreferences } from 'src/dtos/user-preferences.dto'; import { CreateProfileImageResponseDto } from 'src/dtos/user-profile.dto'; import { UserAdminResponseDto, UserResponseDto, UserUpdateMeDto, mapUser, mapUserAdmin } from 'src/dtos/user.dto'; -import { CacheControl, JobName, JobStatus, QueueName, StorageFolder, UserMetadataKey } from 'src/enum'; +import { CacheControl, ImmichWorker, JobName, JobStatus, QueueName, StorageFolder, UserMetadataKey } from 'src/enum'; import { UserFindOptions } from 'src/repositories/user.repository'; import { UserTable } from 'src/schema/tables/user.table'; import { BaseService } from 'src/services/base.service'; @@ -213,6 +213,12 @@ export class UserService extends BaseService { }; } + @OnEvent({ name: 'AppBootstrap', workers: [ImmichWorker.Api] }) + async onBootstrap(): Promise { + const userCount = await this.userRepository.getCount(); + this.telemetryRepository.api.addToGauge('immich.users.total', userCount); + } + @OnJob({ name: JobName.UserSyncUsage, queue: QueueName.BackgroundTask }) async handleUserSyncUsage(): Promise { await this.userRepository.syncUsage(); diff --git a/server/src/services/version.service.ts b/server/src/services/version.service.ts index c4d7e9974d..b817363eac 100644 --- a/server/src/services/version.service.ts +++ b/server/src/services/version.service.ts @@ -95,7 +95,7 @@ export class VersionService extends BaseService { this.eventRepository.clientBroadcast('on_new_release', asNotification(metadata)); } } catch (error: Error | any) { - this.logger.warn(`Unable to run version check: ${error}`, error?.stack); + this.logger.warn(`Unable to run version check: ${error}\n${error?.stack}`); return JobStatus.Failed; } diff --git a/server/src/types.ts b/server/src/types.ts index 9e54de80bb..da3889ef7c 100644 --- a/server/src/types.ts +++ b/server/src/types.ts @@ -88,6 +88,9 @@ export interface VideoStreamInfo { isHDR: boolean; bitrate: number; pixelFormat: string; + colorPrimaries?: string; + colorSpace?: string; + colorTransfer?: string; } export interface AudioStreamInfo { @@ -249,7 +252,7 @@ export interface IEmailJob { } export interface INotifySignupJob extends IEntityJob { - tempPassword?: string; + password?: string; } export interface INotifyAlbumInviteJob extends IEntityJob { diff --git a/server/src/utils/file.ts b/server/src/utils/file.ts index 2331a45a62..29c7f6f772 100644 --- a/server/src/utils/file.ts +++ b/server/src/utils/file.ts @@ -73,7 +73,7 @@ export const sendFile = async ( // log non-http errors if (error instanceof HttpException === false) { - logger.error(`Unable to send file: ${error.name}`, error.stack); + logger.error(`Unable to send file: ${error}`, error.stack); } res.header('Cache-Control', 'none'); diff --git a/server/src/utils/media.ts b/server/src/utils/media.ts index 1ecd005315..f678a32b0f 100644 --- a/server/src/utils/media.ts +++ b/server/src/utils/media.ts @@ -392,9 +392,30 @@ export class ThumbnailConfig extends BaseConfig { getBaseInputOptions(videoStream: VideoStreamInfo, format?: VideoFormat): string[] { // skip_frame nointra skips all frames for some MPEG-TS files. Look at ffmpeg tickets 7950 and 7895 for more details. - return format?.formatName === 'mpegts' - ? ['-sws_flags accurate_rnd+full_chroma_int'] - : ['-skip_frame nointra', '-sws_flags accurate_rnd+full_chroma_int']; + const options = + format?.formatName === 'mpegts' + ? ['-sws_flags accurate_rnd+full_chroma_int'] + : ['-skip_frame nointra', '-sws_flags accurate_rnd+full_chroma_int']; + + const metadataOverrides = []; + if (videoStream.colorPrimaries === 'reserved') { + metadataOverrides.push('colour_primaries=1'); + } + + if (videoStream.colorSpace === 'reserved') { + metadataOverrides.push('matrix_coefficients=1'); + } + + if (videoStream.colorTransfer === 'reserved') { + metadataOverrides.push('transfer_characteristics=1'); + } + + if (metadataOverrides.length > 0) { + // workaround for https://fftrac-bg.ffmpeg.org/ticket/11020 + options.push(`-bsf:v ${videoStream.codecName}_metadata=${metadataOverrides.join(':')}`); + } + + return options; } getBaseOutputOptions() { diff --git a/server/src/validation.ts b/server/src/validation.ts index e583f6a44e..6d4bbfbe36 100644 --- a/server/src/validation.ts +++ b/server/src/validation.ts @@ -211,6 +211,18 @@ export const ValidateDate = (options?: DateOptions & ApiPropertyOptions) => { return applyDecorators(...decorators); }; +type StringOptions = { optional?: boolean; nullable?: boolean; trim?: boolean }; +export const ValidateString = (options?: StringOptions & ApiPropertyOptions) => { + const { optional, nullable, trim, ...apiPropertyOptions } = options || {}; + const decorators = [ApiProperty(apiPropertyOptions), IsString(), optional ? Optional({ nullable }) : IsNotEmpty()]; + + if (trim) { + decorators.push(Transform(({ value }: { value: string }) => value?.trim())); + } + + return applyDecorators(...decorators); +}; + type BooleanOptions = { optional?: boolean; nullable?: boolean }; export const ValidateBoolean = (options?: BooleanOptions & ApiPropertyOptions) => { const { optional, nullable, ...apiPropertyOptions } = options || {}; diff --git a/server/test/fixtures/asset.stub.ts b/server/test/fixtures/asset.stub.ts index dd1f98d6eb..0fd2189268 100644 --- a/server/test/fixtures/asset.stub.ts +++ b/server/test/fixtures/asset.stub.ts @@ -866,4 +866,43 @@ export const assetStub = { stackId: null, visibility: AssetVisibility.Timeline, }), + panoramaTif: Object.freeze({ + id: 'asset-id', + status: AssetStatus.Active, + deviceAssetId: 'device-asset-id', + fileModifiedAt: new Date('2023-02-23T05:06:29.716Z'), + fileCreatedAt: new Date('2023-02-23T05:06:29.716Z'), + owner: userStub.user1, + ownerId: 'user-id', + deviceId: 'device-id', + originalPath: '/original/path.tif', + checksum: Buffer.from('file hash', 'utf8'), + type: AssetType.Image, + files, + thumbhash: Buffer.from('blablabla', 'base64'), + encodedVideoPath: null, + createdAt: new Date('2023-02-23T05:06:29.716Z'), + updatedAt: new Date('2023-02-23T05:06:29.716Z'), + localDateTime: new Date('2023-02-23T05:06:29.716Z'), + isFavorite: true, + duration: null, + isExternal: false, + livePhotoVideo: null, + livePhotoVideoId: null, + sharedLinks: [], + originalFileName: 'asset-id.tif', + faces: [], + deletedAt: null, + sidecarPath: null, + exifInfo: { + fileSizeInByte: 5000, + projectionType: 'EQUIRECTANGULAR', + } as Exif, + duplicateId: null, + isOffline: false, + updateId: '42', + libraryId: null, + stackId: null, + visibility: AssetVisibility.Timeline, + }), }; diff --git a/server/test/fixtures/media.stub.ts b/server/test/fixtures/media.stub.ts index efbf21d317..727f5ae7cf 100644 --- a/server/test/fixtures/media.stub.ts +++ b/server/test/fixtures/media.stub.ts @@ -261,4 +261,15 @@ export const probeStub = { bitrate: 0, }, }), + videoStreamReserved: Object.freeze({ + ...probeStubDefault, + videoStreams: [ + { + ...probeStubDefaultVideoStream[0], + colorPrimaries: 'reserved', + colorSpace: 'reserved', + colorTransfer: 'reserved', + }, + ], + }), }; diff --git a/server/test/fixtures/notification.stub.ts b/server/test/fixtures/notification.stub.ts new file mode 100644 index 0000000000..b5a436a622 --- /dev/null +++ b/server/test/fixtures/notification.stub.ts @@ -0,0 +1,14 @@ +import { NotificationLevel, NotificationType } from 'src/enum'; + +export const notificationStub = { + albumEvent: { + id: 'notification-album-event', + type: NotificationType.AlbumInvite, + description: 'You have been invited to a shared album', + title: 'Album Invitation', + createdAt: new Date('2024-01-01'), + data: { albumId: 'album-id' }, + level: NotificationLevel.Success, + readAt: null, + }, +}; diff --git a/server/test/medium.factory.ts b/server/test/medium.factory.ts index a169d96322..3f021f3eb7 100644 --- a/server/test/medium.factory.ts +++ b/server/test/medium.factory.ts @@ -33,12 +33,15 @@ import { PartnerRepository } from 'src/repositories/partner.repository'; import { PersonRepository } from 'src/repositories/person.repository'; import { SearchRepository } from 'src/repositories/search.repository'; import { SessionRepository } from 'src/repositories/session.repository'; +import { SharedLinkAssetRepository } from 'src/repositories/shared-link-asset.repository'; import { SharedLinkRepository } from 'src/repositories/shared-link.repository'; import { StackRepository } from 'src/repositories/stack.repository'; import { StorageRepository } from 'src/repositories/storage.repository'; import { SyncCheckpointRepository } from 'src/repositories/sync-checkpoint.repository'; import { SyncRepository } from 'src/repositories/sync.repository'; import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository'; +import { TagRepository } from 'src/repositories/tag.repository'; +import { TelemetryRepository } from 'src/repositories/telemetry.repository'; import { UserRepository } from 'src/repositories/user.repository'; import { VersionHistoryRepository } from 'src/repositories/version-history.repository'; import { DB } from 'src/schema'; @@ -51,9 +54,12 @@ import { MemoryTable } from 'src/schema/tables/memory.table'; import { PersonTable } from 'src/schema/tables/person.table'; import { SessionTable } from 'src/schema/tables/session.table'; import { StackTable } from 'src/schema/tables/stack.table'; +import { TagAssetTable } from 'src/schema/tables/tag-asset.table'; +import { TagTable } from 'src/schema/tables/tag.table'; import { UserTable } from 'src/schema/tables/user.table'; import { BASE_SERVICE_DEPENDENCIES, BaseService } from 'src/services/base.service'; import { SyncService } from 'src/services/sync.service'; +import { newTelemetryRepositoryMock } from 'test/repositories/telemetry.repository.mock'; import { factory, newDate, newEmbedding, newUuid } from 'test/small.factory'; import { automock, wait } from 'test/utils'; import { Mocked } from 'vitest'; @@ -238,6 +244,18 @@ export class MediumTestContext { user, }; } + + async newTagAsset(tagBulkAssets: { tagIds: string[]; assetIds: string[] }) { + const tagsAssets: Insertable[] = []; + for (const tagsId of tagBulkAssets.tagIds) { + for (const assetsId of tagBulkAssets.assetIds) { + tagsAssets.push({ tagsId, assetsId }); + } + } + + const result = await this.get(TagRepository).upsertAssetIds(tagsAssets); + return { tagsAssets, result }; + } } export class SyncTestContext extends MediumTestContext { @@ -294,6 +312,7 @@ const newRealRepository = (key: ClassConstructor, db: Kysely): T => { case SearchRepository: case SessionRepository: case SharedLinkRepository: + case SharedLinkAssetRepository: case StackRepository: case SyncRepository: case SyncCheckpointRepository: @@ -316,6 +335,10 @@ const newRealRepository = (key: ClassConstructor, db: Kysely): T => { return new key(LoggingRepository.create()); } + case TagRepository: { + return new key(db, LoggingRepository.create()); + } + case LoggingRepository as unknown as ClassConstructor: { return new key() as unknown as T; } @@ -343,10 +366,15 @@ const newMockRepository = (key: ClassConstructor) => { case SyncCheckpointRepository: case SystemMetadataRepository: case UserRepository: - case VersionHistoryRepository: { + case VersionHistoryRepository: + case TagRepository: { return automock(key); } + case TelemetryRepository: { + return newTelemetryRepositoryMock(); + } + case DatabaseRepository: { return automock(DatabaseRepository, { args: [undefined, { setContext: () => {} }, { getEnv: () => ({ database: { vectorExtension: '' } }) }], @@ -561,6 +589,23 @@ const memoryInsert = (memory: Partial> = {}) => { return { ...defaults, ...memory, id }; }; +const tagInsert = (tag: Partial>) => { + const id = tag.id || newUuid(); + + const defaults: Insertable = { + id, + userId: '', + value: '', + createdAt: newDate(), + updatedAt: newDate(), + color: '', + parentId: null, + updateId: newUuid(), + }; + + return { ...defaults, ...tag, id }; +}; + class CustomWritable extends Writable { private data = ''; @@ -613,4 +658,5 @@ export const mediumFactory = { memoryInsert, loginDetails, loginResponse, + tagInsert, }; diff --git a/server/test/medium/specs/services/auth.service.spec.ts b/server/test/medium/specs/services/auth.service.spec.ts index 14ea1451f2..60d3210f4c 100644 --- a/server/test/medium/specs/services/auth.service.spec.ts +++ b/server/test/medium/specs/services/auth.service.spec.ts @@ -11,6 +11,7 @@ import { LoggingRepository } from 'src/repositories/logging.repository'; import { SessionRepository } from 'src/repositories/session.repository'; import { StorageRepository } from 'src/repositories/storage.repository'; import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository'; +import { TelemetryRepository } from 'src/repositories/telemetry.repository'; import { UserRepository } from 'src/repositories/user.repository'; import { DB } from 'src/schema'; import { AuthService } from 'src/services/auth.service'; @@ -32,7 +33,7 @@ const setup = (db?: Kysely) => { SystemMetadataRepository, UserRepository, ], - mock: [LoggingRepository, StorageRepository, EventRepository], + mock: [LoggingRepository, StorageRepository, EventRepository, TelemetryRepository], }); }; diff --git a/server/test/medium/specs/services/shared-link.service.spec.ts b/server/test/medium/specs/services/shared-link.service.spec.ts index 88e7e86df5..acc51374d1 100644 --- a/server/test/medium/specs/services/shared-link.service.spec.ts +++ b/server/test/medium/specs/services/shared-link.service.spec.ts @@ -4,6 +4,7 @@ import { SharedLinkType } from 'src/enum'; import { AccessRepository } from 'src/repositories/access.repository'; import { DatabaseRepository } from 'src/repositories/database.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; +import { SharedLinkAssetRepository } from 'src/repositories/shared-link-asset.repository'; import { SharedLinkRepository } from 'src/repositories/shared-link.repository'; import { StorageRepository } from 'src/repositories/storage.repository'; import { DB } from 'src/schema'; @@ -17,7 +18,7 @@ let defaultDatabase: Kysely; const setup = (db?: Kysely) => { return newMediumService(SharedLinkService, { database: db || defaultDatabase, - real: [AccessRepository, DatabaseRepository, SharedLinkRepository], + real: [AccessRepository, DatabaseRepository, SharedLinkRepository, SharedLinkAssetRepository], mock: [LoggingRepository, StorageRepository], }); }; @@ -62,4 +63,65 @@ describe(SharedLinkService.name, () => { }); }); }); + + it('should share individually assets', async () => { + const { sut, ctx } = setup(); + + const { user } = await ctx.newUser(); + + const assets = await Promise.all([ + ctx.newAsset({ ownerId: user.id }), + ctx.newAsset({ ownerId: user.id }), + ctx.newAsset({ ownerId: user.id }), + ]); + + for (const { asset } of assets) { + await ctx.newExif({ assetId: asset.id, make: 'Canon' }); + } + + const sharedLinkRepo = ctx.get(SharedLinkRepository); + + const sharedLink = await sharedLinkRepo.create({ + key: randomBytes(16), + id: factory.uuid(), + userId: user.id, + allowUpload: false, + type: SharedLinkType.Individual, + assetIds: assets.map(({ asset }) => asset.id), + }); + + await expect(sut.getMine({ user, sharedLink }, {})).resolves.toMatchObject({ + assets: assets.map(({ asset }) => expect.objectContaining({ id: asset.id })), + }); + }); + + it('should remove individually shared asset', async () => { + const { sut, ctx } = setup(); + + const { user } = await ctx.newUser(); + const auth = factory.auth({ user }); + const { asset } = await ctx.newAsset({ ownerId: user.id }); + await ctx.newExif({ assetId: asset.id, make: 'Canon' }); + + const sharedLinkRepo = ctx.get(SharedLinkRepository); + + const sharedLink = await sharedLinkRepo.create({ + key: randomBytes(16), + id: factory.uuid(), + userId: user.id, + allowUpload: false, + type: SharedLinkType.Individual, + assetIds: [asset.id], + }); + + await expect(sut.getMine({ user, sharedLink }, {})).resolves.toMatchObject({ + assets: [expect.objectContaining({ id: asset.id })], + }); + + await sut.removeAssets(auth, sharedLink.id, { + assetIds: [asset.id], + }); + + await expect(sut.getMine({ user, sharedLink }, {})).resolves.toHaveProperty('assets', []); + }); }); diff --git a/server/test/medium/specs/services/tag.service.spec.ts b/server/test/medium/specs/services/tag.service.spec.ts new file mode 100644 index 0000000000..2ec498e56d --- /dev/null +++ b/server/test/medium/specs/services/tag.service.spec.ts @@ -0,0 +1,116 @@ +import { Kysely } from 'kysely'; +import { JobStatus } from 'src/enum'; +import { AccessRepository } from 'src/repositories/access.repository'; +import { LoggingRepository } from 'src/repositories/logging.repository'; +import { TagRepository } from 'src/repositories/tag.repository'; +import { DB } from 'src/schema'; +import { TagService } from 'src/services/tag.service'; +import { upsertTags } from 'src/utils/tag'; +import { newMediumService } from 'test/medium.factory'; +import { getKyselyDB } from 'test/utils'; + +let defaultDatabase: Kysely; + +const setup = (db?: Kysely) => { + return newMediumService(TagService, { + database: db || defaultDatabase, + real: [TagRepository, AccessRepository], + mock: [LoggingRepository], + }); +}; + +beforeAll(async () => { + defaultDatabase = await getKyselyDB(); +}); + +describe(TagService.name, () => { + describe('deleteEmptyTags', () => { + it('single tag exists, not connected to any assets, and is deleted', async () => { + const { sut, ctx } = setup(); + const { user } = await ctx.newUser(); + const tagRepo = ctx.get(TagRepository); + const [tag] = await upsertTags(tagRepo, { userId: user.id, tags: ['tag-1'] }); + + await expect(tagRepo.getByValue(user.id, 'tag-1')).resolves.toEqual(expect.objectContaining({ id: tag.id })); + await expect(sut.handleTagCleanup()).resolves.toBe(JobStatus.Success); + await expect(tagRepo.getByValue(user.id, 'tag-1')).resolves.toBeUndefined(); + }); + + it('single tag exists, connected to one asset, and is not deleted', async () => { + const { sut, ctx } = setup(); + const { user } = await ctx.newUser(); + const { asset } = await ctx.newAsset({ ownerId: user.id }); + const tagRepo = ctx.get(TagRepository); + const [tag] = await upsertTags(tagRepo, { userId: user.id, tags: ['tag-1'] }); + + await ctx.newTagAsset({ tagIds: [tag.id], assetIds: [asset.id] }); + + await expect(tagRepo.getByValue(user.id, 'tag-1')).resolves.toEqual(expect.objectContaining({ id: tag.id })); + await expect(sut.handleTagCleanup()).resolves.toBe(JobStatus.Success); + await expect(tagRepo.getByValue(user.id, 'tag-1')).resolves.toEqual(expect.objectContaining({ id: tag.id })); + }); + + it('hierarchical tag exists, and the parent is connected to an asset, and the child is deleted', async () => { + const { sut, ctx } = setup(); + const { user } = await ctx.newUser(); + const { asset } = await ctx.newAsset({ ownerId: user.id }); + const tagRepo = ctx.get(TagRepository); + const [parentTag, childTag] = await upsertTags(tagRepo, { userId: user.id, tags: ['parent', 'parent/child'] }); + + await ctx.newTagAsset({ tagIds: [parentTag.id], assetIds: [asset.id] }); + + await expect(tagRepo.getByValue(user.id, 'parent')).resolves.toEqual( + expect.objectContaining({ id: parentTag.id }), + ); + await expect(tagRepo.getByValue(user.id, 'parent/child')).resolves.toEqual( + expect.objectContaining({ id: childTag.id }), + ); + await expect(sut.handleTagCleanup()).resolves.toBe(JobStatus.Success); + await expect(tagRepo.getByValue(user.id, 'parent')).resolves.toEqual( + expect.objectContaining({ id: parentTag.id }), + ); + await expect(tagRepo.getByValue(user.id, 'parent/child')).resolves.toBeUndefined(); + }); + + it('hierarchical tag exists, and only the child is connected to an asset, and nothing is deleted', async () => { + const { sut, ctx } = setup(); + const { user } = await ctx.newUser(); + const { asset } = await ctx.newAsset({ ownerId: user.id }); + const tagRepo = ctx.get(TagRepository); + const [parentTag, childTag] = await upsertTags(tagRepo, { userId: user.id, tags: ['parent', 'parent/child'] }); + + await ctx.newTagAsset({ tagIds: [childTag.id], assetIds: [asset.id] }); + + await expect(tagRepo.getByValue(user.id, 'parent')).resolves.toEqual( + expect.objectContaining({ id: parentTag.id }), + ); + await expect(tagRepo.getByValue(user.id, 'parent/child')).resolves.toEqual( + expect.objectContaining({ id: childTag.id }), + ); + await expect(sut.handleTagCleanup()).resolves.toBe(JobStatus.Success); + await expect(tagRepo.getByValue(user.id, 'parent')).resolves.toEqual( + expect.objectContaining({ id: parentTag.id }), + ); + await expect(tagRepo.getByValue(user.id, 'parent/child')).resolves.toEqual( + expect.objectContaining({ id: childTag.id }), + ); + }); + + it('hierarchical tag exists, and neither parent nor child is connected to an asset, and both are deleted', async () => { + const { sut, ctx } = setup(); + const { user } = await ctx.newUser(); + const tagRepo = ctx.get(TagRepository); + const [parentTag, childTag] = await upsertTags(tagRepo, { userId: user.id, tags: ['parent', 'parent/child'] }); + + await expect(tagRepo.getByValue(user.id, 'parent')).resolves.toEqual( + expect.objectContaining({ id: parentTag.id }), + ); + await expect(tagRepo.getByValue(user.id, 'parent/child')).resolves.toEqual( + expect.objectContaining({ id: childTag.id }), + ); + await expect(sut.handleTagCleanup()).resolves.toBe(JobStatus.Success); + await expect(tagRepo.getByValue(user.id, 'parent/child')).resolves.toBeUndefined(); + await expect(tagRepo.getByValue(user.id, 'parent')).resolves.toBeUndefined(); + }); + }); +}); diff --git a/server/test/medium/specs/services/user.service.spec.ts b/server/test/medium/specs/services/user.service.spec.ts index 7643be292e..0d72d39950 100644 --- a/server/test/medium/specs/services/user.service.spec.ts +++ b/server/test/medium/specs/services/user.service.spec.ts @@ -6,6 +6,7 @@ import { CryptoRepository } from 'src/repositories/crypto.repository'; import { JobRepository } from 'src/repositories/job.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository'; +import { TelemetryRepository } from 'src/repositories/telemetry.repository'; import { UserRepository } from 'src/repositories/user.repository'; import { DB } from 'src/schema'; import { UserService } from 'src/services/user.service'; @@ -21,7 +22,7 @@ const setup = (db?: Kysely) => { return newMediumService(UserService, { database: db || defaultDatabase, real: [CryptoRepository, ConfigRepository, SystemMetadataRepository, UserRepository], - mock: [LoggingRepository, JobRepository], + mock: [LoggingRepository, JobRepository, TelemetryRepository], }); }; diff --git a/server/test/medium/specs/sync/sync-auth-user.spec.ts b/server/test/medium/specs/sync/sync-auth-user.spec.ts index eef18e957d..43411129d3 100644 --- a/server/test/medium/specs/sync/sync-auth-user.spec.ts +++ b/server/test/medium/specs/sync/sync-auth-user.spec.ts @@ -84,4 +84,23 @@ describe(SyncEntityType.AuthUserV1, () => { expect.objectContaining({ type: SyncEntityType.SyncCompleteV1 }), ]); }); + + it('should only sync the auth user', async () => { + const { auth, user, ctx } = await setup(await getKyselyDB()); + + await ctx.newUser(); + + const response = await ctx.syncStream(auth, [SyncRequestType.AuthUsersV1]); + expect(response).toEqual([ + { + ack: expect.any(String), + data: expect.objectContaining({ + id: user.id, + isAdmin: false, + }), + type: 'AuthUserV1', + }, + expect.objectContaining({ type: SyncEntityType.SyncCompleteV1 }), + ]); + }); }); diff --git a/server/test/utils.ts b/server/test/utils.ts index c23341d64c..bae9163b80 100644 --- a/server/test/utils.ts +++ b/server/test/utils.ts @@ -47,6 +47,7 @@ import { ProcessRepository } from 'src/repositories/process.repository'; import { SearchRepository } from 'src/repositories/search.repository'; import { ServerInfoRepository } from 'src/repositories/server-info.repository'; import { SessionRepository } from 'src/repositories/session.repository'; +import { SharedLinkAssetRepository } from 'src/repositories/shared-link-asset.repository'; import { SharedLinkRepository } from 'src/repositories/shared-link.repository'; import { StackRepository } from 'src/repositories/stack.repository'; import { StorageRepository } from 'src/repositories/storage.repository'; @@ -236,6 +237,7 @@ export type ServiceOverrides = { serverInfo: ServerInfoRepository; session: SessionRepository; sharedLink: SharedLinkRepository; + sharedLinkAsset: SharedLinkAssetRepository; stack: StackRepository; storage: StorageRepository; sync: SyncRepository; @@ -307,6 +309,7 @@ export const newTestService = ( serverInfo: automock(ServerInfoRepository, { args: [, loggerMock], strict: false }), session: automock(SessionRepository), sharedLink: automock(SharedLinkRepository), + sharedLinkAsset: automock(SharedLinkAssetRepository), stack: automock(StackRepository), storage: newStorageRepositoryMock(), sync: automock(SyncRepository), @@ -357,6 +360,7 @@ export const newTestService = ( overrides.serverInfo || (mocks.serverInfo as As), overrides.session || (mocks.session as As), overrides.sharedLink || (mocks.sharedLink as As), + overrides.sharedLinkAsset || (mocks.sharedLinkAsset as As), overrides.stack || (mocks.stack as As), overrides.storage || (mocks.storage as As), overrides.sync || (mocks.sync as As), diff --git a/web/.nvmrc b/web/.nvmrc index e2228113dd..442c7587a9 100644 --- a/web/.nvmrc +++ b/web/.nvmrc @@ -1 +1 @@ -22.19.0 +22.20.0 diff --git a/web/bin/immich-web b/web/bin/immich-web index 29e7c46edd..23377eddd6 100755 --- a/web/bin/immich-web +++ b/web/bin/immich-web @@ -1,8 +1,9 @@ #!/usr/bin/env sh -echo "Build dependencies for Immich Web" cd /usr/src/app || exit +pnpm --filter @immich/sdk build + COUNT=0 UPSTREAM="${IMMICH_SERVER_URL:-http://immich-server:2283/}" UPSTREAM="${UPSTREAM%/}" @@ -14,5 +15,4 @@ until wget --spider --quiet "${UPSTREAM}/api/server/config" > /dev/null 2>&1; do sleep 1 done echo "Connected to $UPSTREAM, starting Immich Web..." -pnpm --filter @immich/sdk build pnpm --filter immich-web exec vite dev --host 0.0.0.0 --port 3000 diff --git a/web/eslint.config.js b/web/eslint.config.js index e15f80e8e0..792ff90e0c 100644 --- a/web/eslint.config.js +++ b/web/eslint.config.js @@ -1,5 +1,6 @@ import js from '@eslint/js'; import tslintPluginCompat from '@koddsson/eslint-plugin-tscompat'; +import prettier from 'eslint-config-prettier'; import eslintPluginCompat from 'eslint-plugin-compat'; import eslintPluginSvelte from 'eslint-plugin-svelte'; import eslintPluginUnicorn from 'eslint-plugin-unicorn'; @@ -17,6 +18,7 @@ export default typescriptEslint.config( ...eslintPluginSvelte.configs.recommended, eslintPluginUnicorn.configs.recommended, js.configs.recommended, + prettier, { plugins: { tscompat: tslintPluginCompat, @@ -119,12 +121,14 @@ export default typescriptEslint.config( 'unicorn/filename-case': 'off', 'unicorn/prefer-top-level-await': 'off', 'unicorn/import-style': 'off', + 'unicorn/no-array-sort': 'off', 'svelte/button-has-type': 'error', '@typescript-eslint/await-thenable': 'error', '@typescript-eslint/no-floating-promises': 'error', '@typescript-eslint/no-misused-promises': 'error', '@typescript-eslint/require-await': 'error', 'object-shorthand': ['error', 'always'], + 'svelte/no-navigation-without-resolve': 'off', }, }, { diff --git a/web/package.json b/web/package.json index 58009ec8a1..45cbdcc451 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "immich-web", - "version": "1.141.1", + "version": "2.1.0", "license": "GNU Affero General Public License version 3", "type": "module", "scripts": { @@ -9,13 +9,12 @@ "build:stats": "BUILD_STATS=true vite build", "package": "svelte-kit package", "preview": "vite preview", - "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:svelte": "svelte-check --no-tsconfig --fail-on-warnings", "check:typescript": "tsc --noEmit", "check:watch": "npm run check:svelte -- --watch", "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": "eslint . --max-warnings 0 --concurrency 4", "lint:fix": "npm run lint -- --fix", "format": "prettier --check .", "format:fix": "prettier --write . && npm run format:i18n", @@ -28,7 +27,7 @@ "dependencies": { "@formatjs/icu-messageformat-parser": "^2.9.8", "@immich/sdk": "file:../open-api/typescript-sdk", - "@immich/ui": "^0.24.0", + "@immich/ui": "^0.34.0", "@mapbox/mapbox-gl-rtl-text": "0.2.3", "@mdi/js": "^7.4.47", "@photo-sphere-viewer/core": "^5.11.5", @@ -45,7 +44,7 @@ "geo-coordinates-parser": "^1.7.4", "geojson": "^0.5.0", "handlebars": "^4.7.8", - "happy-dom": "^18.0.1", + "happy-dom": "^20.0.0", "intl-messageformat": "^10.7.11", "justified-layout": "^4.1.0", "lodash-es": "^4.17.21", @@ -53,8 +52,9 @@ "maplibre-gl": "^5.6.2", "pmtiles": "^4.3.0", "qrcode": "^1.5.4", + "simple-icons": "^15.15.0", "socket.io-client": "~4.8.0", - "svelte-gestures": "^5.1.3", + "svelte-gestures": "^5.2.2", "svelte-i18n": "^4.0.1", "svelte-maplibre": "^1.2.0", "svelte-persisted-store": "^0.12.0", @@ -62,15 +62,14 @@ "thumbhash": "^0.1.1" }, "devDependencies": { - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "^9.18.0", - "@faker-js/faker": "^9.3.0", + "@eslint/js": "^9.36.0", + "@faker-js/faker": "^10.0.0", "@koddsson/eslint-plugin-tscompat": "^0.2.0", "@socket.io/component-emitter": "^3.1.0", "@sveltejs/adapter-static": "^3.0.8", "@sveltejs/enhanced-img": "^0.8.0", "@sveltejs/kit": "^2.27.1", - "@sveltejs/vite-plugin-svelte": "6.1.2", + "@sveltejs/vite-plugin-svelte": "6.2.1", "@tailwindcss/vite": "^4.1.7", "@testing-library/jest-dom": "^6.4.2", "@testing-library/svelte": "^5.2.8", @@ -82,33 +81,30 @@ "@types/luxon": "^3.4.2", "@types/qrcode": "^1.5.5", "@vitest/coverage-v8": "^3.0.0", - "autoprefixer": "^10.4.17", "dotenv": "^17.0.0", - "eslint": "^9.18.0", + "eslint": "^9.36.0", "eslint-config-prettier": "^10.1.8", - "eslint-p": "^0.25.0", "eslint-plugin-compat": "^6.0.2", - "eslint-plugin-svelte": "^3.9.0", - "eslint-plugin-unicorn": "^60.0.0", + "eslint-plugin-svelte": "^3.12.4", + "eslint-plugin-unicorn": "^61.0.2", "factory.ts": "^1.4.1", "globals": "^16.0.0", - "happy-dom": "^18.0.1", + "happy-dom": "^20.0.0", "prettier": "^3.4.2", "prettier-plugin-organize-imports": "^4.0.0", "prettier-plugin-sort-json": "^4.1.1", "prettier-plugin-svelte": "^3.3.3", "rollup-plugin-visualizer": "^6.0.0", - "svelte": "5.35.5", + "svelte": "5.39.11", "svelte-check": "^4.1.5", - "svelte-eslint-parser": "^1.2.0", + "svelte-eslint-parser": "^1.3.3", "tailwindcss": "^4.1.7", - "tslib": "^2.6.2", "typescript": "^5.8.3", - "typescript-eslint": "^8.28.0", + "typescript-eslint": "^8.45.0", "vite": "^7.1.2", "vitest": "^3.0.0" }, "volta": { - "node": "22.19.0" + "node": "22.20.0" } } diff --git a/web/src/app.css b/web/src/app.css index db6c43652b..f66743f736 100644 --- a/web/src/app.css +++ b/web/src/app.css @@ -169,3 +169,13 @@ filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.8)); } } + +.maplibregl-popup { + .maplibregl-popup-tip { + @apply border-t-subtle! translate-y-[-1px]; + } + + .maplibregl-popup-content { + @apply bg-subtle rounded-lg; + } +} diff --git a/web/src/app.d.ts b/web/src/app.d.ts index d0d25443c9..e0631e3617 100644 --- a/web/src/app.d.ts +++ b/web/src/app.d.ts @@ -36,7 +36,7 @@ type NestedKeys = K extends keyof T & string : never; declare module 'svelte-i18n' { - import type { InterpolationValues } from '$lib/components/i18n/format-message.svelte'; + import type { InterpolationValues } from '$lib/elements/format-message.svelte'; import type { Readable } from 'svelte/store'; type Translations = NestedKeys; diff --git a/web/src/lib/assets/svg-paths.ts b/web/src/lib/assets/svg-paths.ts index ded3db0fc8..cc8d0a1800 100644 --- a/web/src/lib/assets/svg-paths.ts +++ b/web/src/lib/assets/svg-paths.ts @@ -4,7 +4,3 @@ export const sunPath = export const moonViewBox = '0 0 20 20'; export const sunViewBox = '0 0 20 20'; - -export const discordPath = - 'M81.15,0c-1.2376,2.1973-2.3489,4.4704-3.3591,6.794-9.5975-1.4396-19.3718-1.4396-28.9945,0-.985-2.3236-2.1216-4.5967-3.3591-6.794-9.0166,1.5407-17.8059,4.2431-26.1405,8.0568C2.779,32.5304-1.6914,56.3725.5312,79.8863c9.6732,7.1476,20.5083,12.603,32.0505,16.0884,2.6014-3.4854,4.8998-7.1981,6.8698-11.0623-3.738-1.3891-7.3497-3.1318-10.8098-5.1523.9092-.6567,1.7932-1.3386,2.6519-1.9953,20.281,9.547,43.7696,9.547,64.0758,0,.8587.7072,1.7427,1.3891,2.6519,1.9953-3.4601,2.0457-7.0718,3.7632-10.835,5.1776,1.97,3.8642,4.2683,7.5769,6.8698,11.0623,11.5419-3.4854,22.3769-8.9156,32.0509-16.0631,2.626-27.2771-4.496-50.9172-18.817-71.8548C98.9811,4.2684,90.1918,1.5659,81.1752.0505l-.0252-.0505ZM42.2802,65.4144c-6.2383,0-11.4159-5.6575-11.4159-12.6535s4.9755-12.6788,11.3907-12.6788,11.5169,5.708,11.4159,12.6788c-.101,6.9708-5.026,12.6535-11.3907,12.6535ZM84.3576,65.4144c-6.2637,0-11.3907-5.6575-11.3907-12.6535s4.9755-12.6788,11.3907-12.6788,11.4917,5.708,11.3906,12.6788c-.101,6.9708-5.026,12.6535-11.3906,12.6535Z'; -export const discordViewBox = '0 0 126.644 96'; diff --git a/web/src/lib/components/ServerAboutItem.svelte b/web/src/lib/components/ServerAboutItem.svelte new file mode 100644 index 0000000000..415c047732 --- /dev/null +++ b/web/src/lib/components/ServerAboutItem.svelte @@ -0,0 +1,24 @@ + + +
+ + + {#if versionHref} + {version} + {:else} + {version} + {/if} + +
diff --git a/web/src/lib/components/admin-page/settings/admin-settings.svelte b/web/src/lib/components/admin-settings/AdminSettings.svelte similarity index 100% rename from web/src/lib/components/admin-page/settings/admin-settings.svelte rename to web/src/lib/components/admin-settings/AdminSettings.svelte diff --git a/web/src/lib/components/admin-page/settings/auth/auth-settings.svelte b/web/src/lib/components/admin-settings/AuthSettings.svelte similarity index 92% rename from web/src/lib/components/admin-page/settings/auth/auth-settings.svelte rename to web/src/lib/components/admin-settings/AuthSettings.svelte index ef371910c5..dbc96ac02a 100644 --- a/web/src/lib/components/admin-page/settings/auth/auth-settings.svelte +++ b/web/src/lib/components/admin-settings/AuthSettings.svelte @@ -1,5 +1,4 @@
-

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

+

{$t('date_and_time')}

@@ -27,7 +27,7 @@
-

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

+

{$t('year')}

    {#each options.yearOptions as yearFormat, index (index)}
  • {'{{'}{yearFormat}{'}}'} - {getLuxonExample(yearFormat)}
  • @@ -36,7 +36,7 @@
-

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

+

{$t('month')}

    {#each options.monthOptions as monthFormat, index (index)}
  • {'{{'}{monthFormat}{'}}'} - {getLuxonExample(monthFormat)}
  • @@ -45,7 +45,7 @@
-

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

+

{$t('week')}

    {#each options.weekOptions as weekFormat, index (index)}
  • {'{{'}{weekFormat}{'}}'} - {getLuxonExample(weekFormat)}
  • @@ -54,7 +54,7 @@
-

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

+

{$t('day')}

    {#each options.dayOptions as dayFormat, index (index)}
  • {'{{'}{dayFormat}{'}}'} - {getLuxonExample(dayFormat)}
  • @@ -63,7 +63,7 @@
-

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

+

{$t('hour')}

    {#each options.hourOptions as dayFormat, index (index)}
  • {'{{'}{dayFormat}{'}}'} - {getLuxonExample(dayFormat)}
  • @@ -72,7 +72,7 @@
-

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

+

{$t('minute')}

    {#each options.minuteOptions as dayFormat, index (index)}
  • {'{{'}{dayFormat}{'}}'} - {getLuxonExample(dayFormat)}
  • @@ -81,7 +81,7 @@
-

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

+

{$t('second')}